通过前面的使用,我们可以看出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,从而实现登录业务逻辑:

  1. 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的样式文件引用中。

  1. 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>

接下来,我们启动测试以下:

  1. 创建一个测试user:
    http://127.0.0.1:1337/user/create?username=admin&password=123456&uuid=auto

  2. 登录错误:
    http://127.0.0.1:1337/login

    输入错误的username或password:

  3. 登录成功:
    输入正确的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层相关推荐

  1. springmvc+mybatis,在mybatis逆向工程的基础上使用模板自动生成controller层代码

    在使用mybatis和srpingmvc的过程中,有一点关注了很久,就是controller层 的代码无法自动生成,于是自己研究写了个小程序,可以通过数据库表.自己定制的controller文件的模板 ...

  2. Java中dao层、service层、controller层、entity层和view层的概述

    目录 DAO层:(持久层)主要与数据库进行交互 Service层:(业务层 )控制业务 Controler层:(控制层 )控制业务逻辑 Entity层: (实体层 )数据库在项目中的类 View层: ...

  3. mvc 怎么把后台拼接好的div写到前台_五、controller层配置和前台数据crud操作的实现...

    这个系列专栏的完结可能比我想象要快一些.不过可能将来要完善这个项目的时候还会加以改进.我今天争取把最后一层:控制层的代码给写完.明天最后一篇博文将讲讲Session.cookie对用户登录的控制,并最 ...

  4. Spring框架中entity层、dao层、service层、mapper层、controller层详解

    1. entity层 entity就是属性类,通常定义在model层里面,其相当于MVC的M层,属于数据模型层: 一般的实体类对应一个数据表,其中的属性定义数据表中的字段,实体类的字段数量 >= ...

  5. 三层架构编程、DAO层、Entity层、Service层、Controller层

    什么是三层架构编程: 本质上所有的项目(应用程序)都是需要和用户交互,然后产生数据,对数据进行处理,最后将数据存储到硬盘这么个过程 在编程中,可以将这个过程分一下层次,最初只分两层,用户层和数据层,但 ...

  6. Dao层service层controller层mannager层和biz层详解

    本篇文章内容 1.阿里开发手册关于应用分层的部分 2.对于阿里应用分层的理解 1.阿里开发手册关于应用分层的介绍 1.开放接口层: 可直接封装 Service 方法暴露成 RPC 接口:通过 Web ...

  7. 如何优雅的写 Controller 层代码?

    本篇主要要介绍的就是controller层的处理,一个完整的后端请求由4部分组成:1. 接口地址(也就是URL地址).2. 请求方式(一般就是get.set,当然还有put.delete).3. 请求 ...

  8. Controller层和Service层具体区分

    controller层,主要用于给前端返回数据的以及接收前端的数据的, service层,总之就是处理数据用的. 处理controller层传过来的数据然后传给给dao层链接数据库进行增删改查, 从d ...

  9. java的dao层_Java中DAO层、Service层和Controller层的区别

    DAO层: DAO层叫数据访问层,全称为data access object,属于一种比较底层,比较基础的操作,具体到对于某个表的增删改查,也就是说某个DAO一定是和数据库的某一张表一一对应的,其中封 ...

  10. Web项目实战 | 购物系统v2.0 | 开发记录(九)Controller层返回数据的封装 | 商品批量操作 | 五表联立实现商品搜索

    --若发现文章内容有误,敬请指正,望不吝赐教,感谢! 文章目录 以往记录 运行环境 一.设计Bean用于Controller层返回数据 二.商品批量操作 2.1 批量操作的前端设计 2.2 批量操作的 ...

最新文章

  1. 边界框的回归策略搞不懂?算法太多分不清?看这篇就够了
  2. 观点|重磅出炉!29页《业内观点:机器人行业的未来》
  3. SQL查询从多个表返回数据
  4. Centos 中 TCPWrappers访问控制
  5. www/index.html would like to use your current location
  6. Linux 磁盘管理 二(Raid、LVM、Quota)
  7. linux fedora14 u盘运行,怎么把fedora 14 装进U盘里
  8. 荒岛余生为什么没有打开包裹_您会带到荒岛什么办公桌设置?
  9. .Net线程同步技术解读
  10. VS里的新建模板(自动添加版本注释)
  11. [Winform]只允许运行一个exe,如果已运行则将窗口置前
  12. AvtiveMQ与SpringBoot结合
  13. plsql 往视图传参数_我们可以将参数传递给SQL中的视图吗?
  14. ios 对日期的处理(包括计算昨天时间、明天时间)
  15. NYOJ 个人刷题题解
  16. Java设计模式(四)行为型 设计模式
  17. 一键开启macOS HiDPI
  18. 小白手动安装Win10系统
  19. (附源码)spring boot校园购物网站 毕业设计041037
  20. leetcode_Permutations II

热门文章

  1. C++初学必练基础题【第三期】
  2. 关于微信小程序获取小程序码并接受buffer流保存为图片
  3. python随机漫步_【Python】随机漫步
  4. LeetCode114--词典中最长的单词、最短补全词、宝石与石头
  5. 解决webView无法播放视频的问题
  6. 教你在“狼人杀”中实现变声效果
  7. R语言进行数据分组聚合统计变换(Aggregating transforms)、计算dataframe数据的分组四分位距(IQR)
  8. 王垠:完全用Linux工作 (转载)
  9. 【学习笔记】欧拉筛法(线性筛素数)
  10. Reverse Polish notation(逆波兰式)