midwayjs 入门

本文介绍了MidwayJS框架的安装和基本配置,包括Koa、validate插件的使用,以及自定义中间件的添加。文章还详细讲解了控制器和路由的创建,如使用@Controller和@Get等装饰器创建HTTP请求方法,并展示了如何从Query、Body、Header和Cookie中获取请求参数。此外,还讨论了Session的管理和文件上传功能。
摘要由CSDN通过智能技术生成
安装midwayjs
npm init midway
src/configuration.ts 插件包注入使用配置

import { Configuration, App } from '@midwayjs/decorator';
import * as koa from '@midwayjs/koa';
import * as validate from '@midwayjs/validate';
import * as info from '@midwayjs/info';
import { join } from 'path';
// import { DefaultErrorFilter } from './filter/default.filter';
// import { NotFoundFilter } from './filter/notfound.filter';
import { ReportMiddleware } from './middleware/report.middleware';

@Configuration({
  imports: [
    koa,
    validate, // 使用validata 插件库
    {
      component: info,
      enabledEnvironment: ['local'],
    },
  ],
  importConfigs: [join(__dirname, './config')],
})
export class ContainerLifeCycle {
  @App()
  app: koa.Application;

  async onReady() {
    // add middleware
    this.app.useMiddleware([ReportMiddleware]); // 使用自定义中间件
    // add filter
    // this.app.useFiter([NotFoundFilter, DefaultErrorFilter]);
  }
}


控制器&路由

控制器文件一般来说在 src/controller 目录中,我们可以在其中创建控制器文件。Midway 使用 @Controller() 装饰器标注控制器,其中装饰器有一个可选参数,用于进行路由前缀(分组),这样这个控制器下面的所有路由都会带上这个前缀。

import { Inject, Controller, Get, Query } from '@midwayjs/decorator';
import { Context } from '@midwayjs/koa';
import { UserService } from '../service/user.service';

@Controller('/api') // 访问控制器前缀加入 /api/get_user
export class APIController {
  @Inject()
  ctx: Context;

  @Inject()
  userService: UserService;

  @Get('/get_user') // // 访问控制器前缀加入 /api/get_user
  async getUser(@Query('uid') uid) {
    const user = await this.userService.getUser({ uid });
    return { success: true, message: 'OK', data: user };
  }
}

路由

Midway 提供了更多的路由方法装饰器

// src/controller/home.ts

import { Controller, Get } from '@midwayjs/decorator';

@Controller('/')
export class HomeController {

  @Get('/')
  async home() {
    return 'Hello Midwayjs!';
  }

  @Post('/update')
  async updateData() {
    return 'This is a post method'
  }
}

@Get@Post@Put()@Del()@Patch()@Options()@Head()@All() ,表示各自的 HTTP 请求方法。
@All 装饰器比较特殊,表示能接受以上所有类型的 HTTP Method。

你可以将多个路由绑定到同一个方法上

@Get('/')
@Get('/main')
async home() {
  return 'Hello Midwayjs!';
}

获取请求参数
装饰器参数约定

Midway 添加了常见的动态取值的装饰器,我们以 @Query 装饰器举例, @Query 装饰器会获取到 URL 中的 Query 参数部分,并将它赋值给函数入参。下面的示例,id 会从路由的 Query 参数上拿,如果 URL 为 /?id=1 ,则 id 的值为 1,同时,这个路由将会返回 User 类型的对象。

@Query

// src/controller/user.ts

import { Controller, Get, Query } from "@midwayjs/decorator";

@Controller('/api/user')
export class UserController {
  @Get('/')
  async getUser(@Query('id') id: string): Promise<User> {
    // xxxx
  }
}

@Query 装饰器的有参数,可以传入一个指定的字符串 key,获取对应的值,赋值给入参,如果不传入,则默认返回整个 Query 对象。

// URL = /?id=1
async getUser(@Query('id') id: string) // id = 1
async getUser(@Query() queryData) // {"id": "1"}

@Body() & @Body('key')

// src/controller/user.ts
// POST /user/ HTTP/1.1
// Host: localhost:3000
// Content-Type: application/json; charset=UTF-8
//
// {"uid": "1", "name": "harry"}
import { Controller, Post, Body } from "@midwayjs/decorator";

@Controller('/user')
export class UserController {
  @Post('/')
  async updateUser(@Body('uid') uid: string): Promise<User> {
    // id 等价于 ctx.request.body.uid
  }
}

@Body()

// src/controller/user.ts
// POST /user/ HTTP/1.1
// Host: localhost:3000
// Content-Type: application/json; charset=UTF-8
//
// {"uid": "1", "name": "harry"}
import { Controller, Post, Body } from "@midwayjs/decorator";

@Controller('/user')
export class UserController {
  @Post('/')
  async updateUser(@Body() user: User): Promise<User> {
    // user 等价于 ctx.request.body 整个 body 对象
    // => output user
    // {
    //   uid: '1',
    //   name: 'harry',
    // }
  }
}

@Body()@Query() 组合使用

@Post('/')
async updateUser(@Body() user: User, @Query('pageIdx') pageIdx: number): Promise<User> {
  // user 从 body 获取
  // pageIdx 从 query 获取
}
Router Params

如果路由上使用 :xxx 的格式来声明路由,那么参数可以通过 ctx.params 获取到。


// src/controller/user.ts
// GET /user/1
import { Controller, Get, Inject } from "@midwayjs/decorator";
import { Context } from '@midwayjs/koa';

@Controller('/user')
export class UserController {
  
  @Inject()
  ctx: Context;
  
  @Get('/:uid')
  async getUser(): Promise<User> {
    const params = this.ctx.params;
    // {
    //   uid: '1',
    // }
  }
}

Header

除了从 URL 和请求 body 上获取参数之外,还有许多参数是通过请求 header 传递的。框架提供了一些辅助属性和方法来获取。

ctx.headers,ctx.header,ctx.request.headers,ctx.request.header:这几个方法是等价的,都是获取整个 header 对象。
ctx.get(name),ctx.request.get(name):获取请求 header 中的一个字段的值,如果这个字段不存在,会返回空字符串。
我们建议用 ctx.get(name) 而不是 ctx.headers[‘name’],因为前者会自动处理大小写。


// src/controller/user.ts
// GET /user/1
import { Controller, Get, Headers } from "@midwayjs/decorator";

@Controller('/user')
export class UserController {
  @Get('/:uid')
  async getUser(@Headers('cache-control') cacheSetting: string): Promise<User> {
    // no-cache
    // ...
  }
}

// src/controller/user.ts
// GET /user/1
import { Controller, Get, Inject } from "@midwayjs/decorator";
import { Context } from '@midwayjs/koa';

@Controller('/user')
export class UserController {
  
  @Inject()
  ctx: Context;
  
  @Get('/:uid')
  async getUser(): Promise<User> {
    const cacheSetting = this.ctx.get('cache-control');
    // no-cache
  }
}

Cookie

通过 ctx.cookies,我们可以在 Controller 中便捷、安全的设置和读取 Cookie

import { Inject, Controller, Get, Provide } from '@midwayjs/decorator';
import { Context } from '@midwayjs/koa';

@Controller('/')
export class HomeController {
  @Inject()
  ctx: Context;

  @Get('/')
  async home() {
    // set cookie
    this.ctx.cookies.set('foo', 'bar', { encrypt: true });
    // get cookie
    this.ctx.cookies.get('foo', { encrypt: true });
  }
}
Session

通过 Cookie,我们可以给每一个用户设置一个 Session,用来存储用户身份相关的信息,这份信息会加密后存储在 Cookie 中,实现跨请求的用户身份保持。

框架内置了 Session 插件,给我们提供了 ctx.session 来访问或者修改当前用户 Session 。


import { Inject, Controller, Get, Provide } from '@midwayjs/decorator';
import { Context } from '@midwayjs/koa';

@Controller('/')
export class HomeController {
  @Inject()
  ctx: Context;

  @Get('/')
  async home() {
    // 获取 Session 上的内容
    const userId =  this.ctx.session.userId;
    const posts = await  this.ctx.service.post.fetch(userId);
    // 修改 Session 的值
    this.ctx.session.visited = ctx.session.visited ? (ctx.session.visited + 1) : 1;
    // ...
  }
}

Session 的使用方法非常直观,直接读取它或者修改它就可以了,如果要删除它,直接将它赋值为 null ctx.session = null;

上传的文件 @Files

上传的文件一般使用 multipart/form-data 协议头,由 @Files 装饰器获取,由于上传功能由 upload 组件提供,具体可以参考 upload 组件。

安装依赖 npm i @midwayjs/upload@3 --save

在 configuration 文件中引入组件


import * as upload from '@midwayjs/upload';

@Configuration({
  imports: [
    // ...other components
    upload
  ],
  // ...
})
export class AutoConfiguration {}

在代码中获取上传的文件


@Controller('/')
export class HomeController {

  @Inject()
  ctx;

  @Post('/upload')
  async upload(@Files() files, @Fields() fields) {
    /*
    files = [
      {
        filename: 'test.pdf',        // 文件原名
        data: '/var/tmp/xxx.pdf',    // mode 为 file 时为服务器临时文件地址
        fieldname: 'test1',          // 表单 field 名
        mimeType: 'application/pdf', // mime
      },
      {
        filename: 'test.pdf',        // 文件原名
        data: ReadStream,    // mode 为 stream 时为服务器临时文件地址
        fieldname: 'test2',          // 表单 field 名
        mimeType: 'application/pdf', // mime
      },
      // ...file 下支持同时上传多个文件
    ]

    */
    return {
      files,
      fields
    }
  }
}


配置upload
// src/config/config.default.ts
import { uploadWhiteList } from '@midwayjs/upload';

export default {
  // ...
  upload: {
    // mode: UploadMode, 默认为file,即上传到服务器临时目录,可以配置为 stream
    mode: 'file',
    // fileSize: string, 最大上传文件大小,默认为 10mb
    fileSize: '10mb',
    // whitelist: string[],文件扩展名白名单
    whitelist: uploadWhiteList.filter(ext => ext !== '.pdf'), // 可通过 whitelist: () => true 允许所有后缀文件上传
    // tmpdir: string,上传的文件临时存储路径
    tmpdir: join(tmpdir(), 'midway-upload-files'), // 如果你使用了 file 模式来获取上传的文件,那么上传的文件会存放在您于 config 文件中设置的 upload 组件配置中的 tmpdir 选项指向的文件夹内。
    // cleanTimeout: number,上传的文件在临时目录中多久之后自动删除,默认为 5 分钟 你可以通过在配置中使用 cleanTimeout 来控制自动的临时文件清理时间,默认值为 5 * 60 * 1000,即上传的文件于 5 分钟 后自动清理,设置为 0 则视为不开启自动清理功能。
    cleanTimeout: 5 * 60 * 1000,
  },
}


获取 body & path & ip

@RequestPath() // 获取路径path

@RequestIP() // 获取ip

@Body(‘id’) // 获取body

@Post('/')
async updateUser(
  @Body('id') id: string,
  @RequestPath() p: string,
  @RequestIP() ip: string): Promise<User> {

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值