Sails基础之Controller层
通过前面的使用,我们可以看出Sails中MVC的结构更倾向于MVP的概念,Presenter在Sails中被称之为Actions:
They often act as a middleman between your models and views.
Controller层这个结构上的变化是Sails v1.0中新提出的方案,Action可以使用classic和actions2两种格式,另外,仍然兼容支持Sails v0.12上的Controller实现方式。相对于肿胀的Controller,将Controller拆分成多个Action可以更清晰的表达业务逻辑,其中actions2格式的Action更是一种半文档半校验器的形式,可以从接口描述、接口参数、参数校验、逻辑、退出方式等方面构建整个业务逻辑。
Actions
Action2 Action
Action2格式的action与Helper基本相似,需要做调整的主要是各种与Controller层职责相关的exit方式。我们来创建一个signup action:
sails generate action user/login
我们可以编写一个用于登录验证的action,从而实现登录业务逻辑:
- Model层
Model层我们使用前面案例中的User Model:
const crypto = require('crypto');
const uuid = require('node-uuid');module.exports = {primaryKey: 'uuid',attributes: {uuid: {type: 'string',required: true,},username: {type: 'string',required: true,allowNull: false,unique: true,},password: {type: 'string',required: true,allowNull: false,},},customToJSON: function() {return _.omit(this, ['password']);},beforeCreate: function (valuesToSet, proceed) {let md5 = crypto.createHash('md5');valuesToSet.uuid = uuid.v4();valuesToSet.password = md5.update(valuesToSet.password).digest('hex');return proceed();}};
身份验证主要通过对username和password的查询完成。
2. View层
首先在config/routes创建一个view路由:
'/login': {view: 'pages/login',locals: {layout: 'layouts/users',errno: 0,},
},
该路由指定了模板为views/pages/login,layout为views/layouts/users(只有默认的ejs模板引擎支持此项配置),接下来我们分别创建layouts/users和pages/login:
layouts/users.ejs:
<!DOCTYPE html>
<html><head><title>Sails App</title><!-- Viewport mobile tag for sensible mobile support --><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"><!--STYLES--><!--STYLES END--></head><body><%- body %></body>
</html>
pages/login.ejs:
<div class="container"><% if(errno == 1){ %><div class="alert alert-danger" role="alert">Username or password is error!</div><% } %><form method="POST" action="/user/login"><div class="form-group"><label for="username">Username</label><input type="text" class="form-control" id="username" name="username" placeholder="Enter username"></div><div class="form-group"><label for="password">Password</label><input type="password" class="form-control" id="password" name="password" placeholder="Password"></div><button type="submit" class="btn btn-primary">Submit</button></form>
</div>
assets资源:
将bootstrap.min.css拷贝到assets/styles下,启动时grunt任务会将其自动注入到users.ejs的样式文件引用中。
- Controller层
api/controllers/user/login:
const crypto = require('crypto'); module.exports = {friendlyName: 'Login',description: 'Login user.',inputs: {username: {description: 'The username',type: 'string',required: true,},password: {description: 'The password',type: 'string',required: true,}},exits: {success: {responseType: 'view',viewTemplatePath: 'pages/welcome'},fail: {responseType: 'view',viewTemplatePath: 'pages/login'},err: {description: 'Occur error',responseType: 'notFound'}},fn: async function (inputs, exits) {let md5 = crypto.createHash('md5');let {username, password} = inputs;try{let user = await User.findOne({username, username});if(!user || user.password != md5.update(password).digest('hex')){return exits.fail({errno: 1});}return exits.success({errno: 0,msg: {username: username}});} catch(e) {sails.log(e.message);throw 'err';}}
};
可以看到与Helper的结构是一致的,唯一需要调整的是exit的方式,而exit方式主要是由responseType决定的:
responseType is one of the following:
- “” (the standard response: Determine an appropriate response based on context: this might send plain text, download a file, transmit data as JSON, or send no response body at all.)
- “view” (render and respond with a view; exit output will be provided as view locals)
- “redirect” (redirect to the URL returned as the exit output)
为action创建路由:
'post /user/login': 'user.login',
从代码可以看到,登录成功后,渲染模板pages/welcome,因此,我们创建对应的模板:
<h1>Welcome <%= msg.username %> !</h1>
接下来,我们启动测试以下:
创建一个测试user:
http://127.0.0.1:1337/user/create?username=admin&password=123456&uuid=auto登录错误:
http://127.0.0.1:1337/login
输入错误的username或password:
登录成功:
输入正确的username和password:
Classic Action
Classic action与v0.12版本中传统的Controller实现方式基本一致,将传统写在一个Controller中的业务逻辑拆分为单个的一个个action,更有利于业务的实现与维护。
sails generate action user/login--no-actions2
Controller
另外,你仍然可以使用传统的Controller方式实现所有业务逻辑:
module.exports = {login: function (req, res) { ... },logout: function (req, res) { ... },signup: function (req, res) { ... },
};
machine-as-action
你也可以将Controller的编写方式转换到action2的编写风格上来,请参考以下链接:
https://github.com/sailshq/machine-as-action
Sails基础之Controller层相关推荐
- springmvc+mybatis,在mybatis逆向工程的基础上使用模板自动生成controller层代码
在使用mybatis和srpingmvc的过程中,有一点关注了很久,就是controller层 的代码无法自动生成,于是自己研究写了个小程序,可以通过数据库表.自己定制的controller文件的模板 ...
- Java中dao层、service层、controller层、entity层和view层的概述
目录 DAO层:(持久层)主要与数据库进行交互 Service层:(业务层 )控制业务 Controler层:(控制层 )控制业务逻辑 Entity层: (实体层 )数据库在项目中的类 View层: ...
- mvc 怎么把后台拼接好的div写到前台_五、controller层配置和前台数据crud操作的实现...
这个系列专栏的完结可能比我想象要快一些.不过可能将来要完善这个项目的时候还会加以改进.我今天争取把最后一层:控制层的代码给写完.明天最后一篇博文将讲讲Session.cookie对用户登录的控制,并最 ...
- Spring框架中entity层、dao层、service层、mapper层、controller层详解
1. entity层 entity就是属性类,通常定义在model层里面,其相当于MVC的M层,属于数据模型层: 一般的实体类对应一个数据表,其中的属性定义数据表中的字段,实体类的字段数量 >= ...
- 三层架构编程、DAO层、Entity层、Service层、Controller层
什么是三层架构编程: 本质上所有的项目(应用程序)都是需要和用户交互,然后产生数据,对数据进行处理,最后将数据存储到硬盘这么个过程 在编程中,可以将这个过程分一下层次,最初只分两层,用户层和数据层,但 ...
- Dao层service层controller层mannager层和biz层详解
本篇文章内容 1.阿里开发手册关于应用分层的部分 2.对于阿里应用分层的理解 1.阿里开发手册关于应用分层的介绍 1.开放接口层: 可直接封装 Service 方法暴露成 RPC 接口:通过 Web ...
- 如何优雅的写 Controller 层代码?
本篇主要要介绍的就是controller层的处理,一个完整的后端请求由4部分组成:1. 接口地址(也就是URL地址).2. 请求方式(一般就是get.set,当然还有put.delete).3. 请求 ...
- Controller层和Service层具体区分
controller层,主要用于给前端返回数据的以及接收前端的数据的, service层,总之就是处理数据用的. 处理controller层传过来的数据然后传给给dao层链接数据库进行增删改查, 从d ...
- java的dao层_Java中DAO层、Service层和Controller层的区别
DAO层: DAO层叫数据访问层,全称为data access object,属于一种比较底层,比较基础的操作,具体到对于某个表的增删改查,也就是说某个DAO一定是和数据库的某一张表一一对应的,其中封 ...
- Web项目实战 | 购物系统v2.0 | 开发记录(九)Controller层返回数据的封装 | 商品批量操作 | 五表联立实现商品搜索
--若发现文章内容有误,敬请指正,望不吝赐教,感谢! 文章目录 以往记录 运行环境 一.设计Bean用于Controller层返回数据 二.商品批量操作 2.1 批量操作的前端设计 2.2 批量操作的 ...
最新文章
- 边界框的回归策略搞不懂?算法太多分不清?看这篇就够了
- 观点|重磅出炉!29页《业内观点:机器人行业的未来》
- SQL查询从多个表返回数据
- Centos 中 TCPWrappers访问控制
- www/index.html would like to use your current location
- Linux 磁盘管理 二(Raid、LVM、Quota)
- linux fedora14 u盘运行,怎么把fedora 14 装进U盘里
- 荒岛余生为什么没有打开包裹_您会带到荒岛什么办公桌设置?
- .Net线程同步技术解读
- VS里的新建模板(自动添加版本注释)
- [Winform]只允许运行一个exe,如果已运行则将窗口置前
- AvtiveMQ与SpringBoot结合
- plsql 往视图传参数_我们可以将参数传递给SQL中的视图吗?
- ios 对日期的处理(包括计算昨天时间、明天时间)
- NYOJ 个人刷题题解
- Java设计模式(四)行为型 设计模式
- 一键开启macOS HiDPI
- 小白手动安装Win10系统
- (附源码)spring boot校园购物网站 毕业设计041037
- leetcode_Permutations II
热门文章
- C++初学必练基础题【第三期】
- 关于微信小程序获取小程序码并接受buffer流保存为图片
- python随机漫步_【Python】随机漫步
- LeetCode114--词典中最长的单词、最短补全词、宝石与石头
- 解决webView无法播放视频的问题
- 教你在“狼人杀”中实现变声效果
- R语言进行数据分组聚合统计变换(Aggregating transforms)、计算dataframe数据的分组四分位距(IQR)
- 王垠:完全用Linux工作 (转载)
- 【学习笔记】欧拉筛法(线性筛素数)
- Reverse Polish notation(逆波兰式)