sails(v0.12) 目录结构
1 | ├── Gruntfile.js |
controller
由一系列被称为
action的方法构成,action和routes绑定在一起,所以当请求某一个路由时,触发对应的对应的路由方法,并返回一个响应(这里的响应主要指路由的分发)
controller的定义
在
sails中controller定义在controller文件夹下,按照约定,全部采用pascal-case写法(及每个单词的首字母都是大写),并且必须必须以Controller.js结尾。
- NOTE: 可以将
controller分文件夹定义,那么此时子文件夹也会成为路由标示的一部分。
代码演示
SayController.js1
2
3
4
5
6
7
8
9
10
11// 一个controller就是一个纯对象,对象的属性为action的名字,值为对应的action的处理函数
module.exports = {
// req, res跟express中的一样,不过没有第三个参数next
// 如果有next的需求,那么应该见该逻辑写到policies中
hi: function (req, res) {
return res.send('Hi there!');
},
bye: function (req, res) {
return res.redirect('http://www.sayonara.com');
}
}
隐式路由(sails自动绑定)
1 | /:controllerIdentity/:nameOfAction |
拿上面的
SayController.js来说,那么当程序启动时,就会自动绑定到这样的路由/say/hi,/say/bye。
如果上面的controller在一个子文件夹中/we中,那么就会绑定到这样的路由/we/say/hi,/we/say/bye
显式路由(自定义路由)
手动绑定路由,可以在
config/routes.js中按照如下规则进行路由的配置:
http请求方法(POST,GET等)+ 路由地址 :controller的名字+.+action的名字
1 | 'POST /make/a/sandwith': 'SandwichController.makeIt' |
显式路由常见定义方式
1 | module.exports.routes = { |
自定义响应和responses文件夹
一般情况下,
controller中的响应都会定义在responses文件夹中.
任何定义在/api/responses.js中方法都是通过res.[responsesName]这种形式在controller中调用的。
在responses函数中,可以使用this.req,this.res来获取Request和Response对象。
数据库适配器Adapters
可以连接不同的数据库,主要用来和数据库之间的通信。
在adapter中,我们主要关注的是CRUD操作。
在sails中,主要指这个几个方法create(),find(),update(),destroy()
可选的Adapter
- 官方支持的数据库器
| 数据库名称 | 简介 |
|---|---|
| sails-disk | sails默认捆绑的,不需要做任何的配置。直接将数据写入磁盘,不适合用在生成环境,一般用在开发环境或者一些小的项目中 |
| sails-memory | 将数据写入内存中,不会正在的持久化,所以一般适合用在开发环境或者磁盘空间不足的时候 |
| sails-mysql | 链接mysql(关系型数据库) |
| sails-postgres | 链接postgres(关系型数据库) |
| sails-mongo | 链接mongo(非关系型数据库) |
| sails-redis | 链接redis |
- 社区支持的数据库
全局变量
全局变量可以在
sails加载完毕之后全局访问,这些全局变量都可以在config/globals.js中禁用。
- models(文件名作为全局变量名)
- services(文件名作为全局变量名)
- sails
- _(Lodash实例,默认提供,无需安装)
- async(Async实例,默认提供,无需安装)
NOTE: 必须等到sails加载完成之后,才可以访问这些全局变量。也就是说,不能再导出的函数外部使用(此时sails尚未加载完毕),必须导出的函数内部使用
1 | // 禁用所有 |
日志(Logging)
sails内建一个日志输出,可以在/config/logs.js中配置日志输出等级。
详情参看sails内建日志
原则(Policies)
该文件夹中定义的脚本主要用来处理一些
权限认证,第三方单点登录等具有一些通用逻辑,有点类似于spring中的AOP。policies只应该在controller的actions中使用,不应该在views中使用。如果是在config/routes.js中直接定义的视图,那么就无法使用policies了。如果想要继续使用使用policies,因该使用controller+.+action的方式。
如下:
1 | // routes.js |
Policies的定义
定义在
api/policies目录下,每个policy应该对应一个文件,只处理一件事情,导出为单一的函数。
事实上,每个policies都是作为Connect/Express中间件的函数,在controller之前执行。
1 | // 只处理一件事情,导出为单一函数 |
api/policies和config/policies.js的关系
在
config/policies.js中配置controller和policies之间的映射关系。就是说哪些controller使用哪些policies来做权限控制。
1 | module.exports.policies = { |
1 | module.exports.policies = { |
Services
一个导出各种函数的纯对象,对象中的每个方法被称为
helper。
因为是全局的,所以可以在各个地方使用:controller的actions, 其他的services, 自定义的model方法中,甚至在命令行脚本中。
Service的创建
在
api/services文件夹中创建,文件名必须以Service.js结尾。
Service函数参数说明
1 | var Mailgun = require('machinepack-mailgun'); |
sendWelcomeEmail方法中option,done参数说明:
- option: 一个自定义属性的对象。
- done: 一个函数。这个一个可选的参数,当
helper为一个异步方法时,那么当helper被调用时,必须传入done回调函数作为第二个参数。 - 按照nodejs的约定,
done中第一个参数为一个error对象,第二个参数为需要的数据结果。
Session
在sails中,session主要由一下3部分要素组成:
session store: 保存信息- 管理
session的中间件 - 每次请求都会携带
cookie,并且session id(默认的sails.sid)都会被存储到cookie中session store既可以是内存(sails中默认使用内存存储),也可以是数据库。sails在Connect中间件的最顶层管理session,包括将session id保存到cookie中。
Views
views的使用,一般有2种方法:
- res.view(), 由于可以在各个都可以使用
res对象,所以可以用这种方式方式将view编译成功html返回给客户端 - 在
/config/routes.js中对路由进行配置
locals
在模板引擎中使用的变量称为
locals,sails默认传入一些变量作为locals,比如lodash。如果某些数据是通过硬编码的方式填充到模板中,那么可以在config/routes.js中配置:
1 | module.exports.routes = { |
在模板中使用动态数据
大多数时候,数据都是动态获取到的(通过action从model中获取),所以大多时候是按照如下方式进行渲染数据的:
1 | // in api/controllers/UserController.js... |
Partials(模板包含)
支持模板包含,及在一些模板中,将另外一些模板包含进来,达到模板的复用。在
sails中使用模板包含,需要注意的就是路径都是相对于view文件夹的。如
1 | // views/partials/widget.ejs |
关于EJS模板
在
ejs中,模板的标签就以下3种:
<%= %>: 转义输出<%- %>: 不转义输出<% %>: 里面直接写js代码
models文件夹
全局访问
services文件夹
全局访问
responses文件夹
里面的方法都会挂载到
controller的req对象上