控制器(Controller)

发布时间:

这里只列出 CmsWing 特有的,更详细的内容请阅读 Egg.js 文档 控制器(Controller)

什么是 Controller

简单的说 Controller 负责解析用户的输入,处理后返回相应的结果,例如

在 RESTful 接口中,Controller 接受用户的参数,从数据库中查找内容返回给用户或者将用户的请求更新到数据库中。
在 HTML 页面请求中,Controller 根据用户访问不同的 URL,渲染不同的模板得到 HTML 返回给用户。
在代理服务器中,Controller 将用户的请求转发到其他服务器上,并将其他服务器的处理结果返回给用户。
框架推荐 Controller 层主要对用户的请求参数进行处理(校验、转换),然后调用对应的 service 方法处理业务,得到业务结果后封装并返回:

获取用户通过 HTTP 传递过来的请求参数。
校验、组装参数。
调用 Service 进行业务处理,必要时处理转换 Service 的返回结果,让它适应用户的需求。
通过 HTTP 将结果响应给用户。

如何编写 Controller

所有的 Controller 文件都必须放在 app/controller 目录下,可以支持多级目录,访问的时候可以通过目录名级联访问。Controller 支持多种形式进行编写,可以根据不同的项目场景和开发习惯来选择。

Controller 类

我们可以通过定义 Controller 类的方式来编写代码,编写时所有的 Controller 必须继承 app/core/base_controller.js

// app/controller/post.js
const Controller = require('../core/base_controller');
class PostController extends Controller {
  async create() {
    const { ctx, service } = this;
    const createRule = {
      title: { type: 'string' },
      content: { type: 'string' },
    };
    // 校验参数
    ctx.validate(createRule);
    // 组装参数
    const author = ctx.userInfo.uuid;
    const req = Object.assign(ctx.request.body, { author });
    // 调用 Service 进行业务处理
    const res = await service.post.create(req);
    // 设置响应内容和响应状态码
    ctx.body = { id: res.id };
    ctx.status = 201;
  }
}
module.exports = PostController;

我们通过上面的代码定义了一个 PostController 的类,类里面的每一个方法都可以作为一个 Controller 在 Router 中引用到,我们可以在后台【路由管理】中选择。

Controller 支持多级目录,例如如果我们将上面的 Controller 代码放到 app/controller/sub/post.js 中,我们希望Cotroller文件按照模块分目录放置。

定义的 Controller 类,会在每一个请求访问到 server 时实例化一个全新的对象,而项目中的 Controller 类继承于 egg.Controller,会有下面几个属性挂在 this 上。

  • this.ctx: 当前请求的上下文 Context 对象的实例,通过它我们可以拿到框架封装好的处理当前请求的各种便捷属性和方法。
  • this.app: 当前应用 Application 对象的实例,通过它我们可以拿到框架提供的全局对象和方法。
  • this.service:应用定义的 Service,通过它我们可以访问到抽象出的业务层,等价于 this.ctx.service 。
  • this.config:应用运行时的配置项。
  • this.logger:logger 对象,上面有四个方法(debuginfowarnerror),分别代表打印四个不同级别的日志,使用方法和效果与 context logger 中介绍的一样,但是通过这个 logger 对象记录的日志,在日志前面会加上打印该日志的文件路径,以便快速定位日志打印位置。

ctx.userInfo

  • 如果模块或者路由中间是 sys.authAdminToken ,那么 this.ctx.userInfo 是系统后台的用户登录信息。
  • 如果模块或者路由中间是 mc.authMcToken ,那么 this.ctx.userInfo 是用户中心(MC)的用户登录信息。

//调用系统后台,用户本人发布的信息
const Controller = require('../../core/base_controller');
const { Op } = require('sequelize');
class DocController extends Controller {
  async selfDoc(){
  //获取用户信息
  const user = this.ctx.userInfo;
  const list = await this.model.CmsDoc.findAll({where:{uid:{[Op.eq]:user.uuid}}});
  this.ctx.body = list;
}
}
module.exports = DocController;

 

success(data,msg)

  • data:返回的数据
  • msg:提示

格式化输出一个正常的数据,一般是操作成功后输出

this.success(list)
this.success(null,'操作成功')
//返回格式
{
status: 0,
msg:'',
data:[],
}

 

fail(msg,status,data)

  • msg:错误信息
  • status:错误代码 默认 1000
  • data:额外的错误数据

格式化输出一个异常的数据,一般是操作失败后输出

this.fail('操作失败')
this.fail('操作失败',800)
//返回
{
      status:1000,
      msg:'',
      data:[],
    }

 

上传

POST /upload

  • type  对象储存类型qiniu|七牛 oss|阿里云OSS cos|腾讯云COS obs|华为云OBS ,如果不传该参数 使用系统默认类型
  • resBody 自定义返回格式
  • token 用户登录成功后会携带在返回信息里
  • type,resBody 根据实际需求可以不传,token必须携带。 这三个参数可以通过body,或者header 携带

如果不是前后端分离使用服务器渲染在同域内可以 使用 /upload/<sessionKey> 的形式来验证权限,<sessionKey> 系统后台是 adminToken,用户中心(MC)是 mcToken。

{
"type": "input-image",
"name": "icon",
"label": "分类图标",
"maxLength": 1,
"receiver": "/upload/adminToken"
}

前后端分离调用例子

// 微信小程序
wx.chooseImage({
  success (res) {
    const tempFilePaths = res.tempFilePaths
    wx.uploadFile({
      url: 'https://你的域名/upload', //仅为示例,非真实的接口地址
      filePath: tempFilePaths[0],
      name: 'file',
      formData: {
        'token': 'gfdgdfgfdsafdsgdfgfdsglkjl'
      },
      success (res){
        const data = res.data
        //do something
      }
    })
  }
})

自定义返回格式

自定义返回格式 比如:{'{"id":{{id}},"path":"{{url}}"}'},具体支持参数

//说明: number 类型的 定义格式时直接输入{{}}, string 类型的定义格式时要加“”,比如'{"id":{{id}},"size":{{size}},"url":"{{url}}"}'
{{id}}<number> //文件id
{{name}}<string> // 原始文件名
{{mime}}<string> // 文件mime类型
{{size}}<number> // 文件大小kb
{{type}}<string> // 文件保存位置
{{savename}}<string> // 保存名称
{{url}}<string> // 文件地址
//如果请求时不携带 resBody ,默认返回 
{
"id":{{id}},
"name":"{{name}}",
"mime":"{{mime}}",
"size":{{size}},
"type":"{{type}}",
"savename":"{{savename}}",
"url":"{{url}}"
}

 

最后更新时间: 2022-12-06 15:00:00

评论