说明

封装 lenneth 旨在快速方便的搭建出一个 node web 应用,不过度封装也不随波逐流,koa 的 node 是简单的,lenneth 也是。

基于 ES6+typescript 的一些特性,做了一些类似 spring 的注解,对开发本身不增加复杂度,并且不失 koa 的灵活性。

lenneth 内部已经集成了 koa, koa-bodyparser, koa-router 这 3 个基础库,已经满足了大部分的开发,如果需要引入其他的中间件,可以在入口文件中引入。

lenneth 抽象了 3 个模块,分别是 controller,middleware,service,内部不接入任何 db 和 cache。

安装

yarn add lenneth

# or

npm install lenneth瞄一眼

import { LennethApplication, ServerSettings, ILenneth } from "lenneth";

@ServerSettings({

port: 8081

})

class App extends LennethApplication implements ILenneth {

$onMountingMiddlewares() {

this.use(async (ctx, next) => {

ctx.body = "hello world";

});

}

}

new App().start();

open in browser

http://localhost:8081lenneth封装koa核心

koa 最精髓的就是它的洋葱模型,而洋葱模型的元素就是一个一个的中间件,lenneth 的封装就是将普通的类方法转化成 koa 的中间件

/**

* koa中间件,有两个参数

* @params ctx 上下文

* @params next 洋葱模型执行下一个中间件

*/

async (ctx, next) => {

}

/**

* 这个类方法并不是koa的中间件

* 按照设计思路,类方法的两个参数一个是获取path参数,一个是获取返回对象,和koa的中间件参数不同

*/

@Get("/detail/:id")

@UseBefore(UserRuleAuth)

async getUserDetail(

@PathVariable("id") id: string,

@Response() response: TResponse

) {

response.body = this.userService.getUserById(id);

}

转换函数

这个方法就是将上述的类方法转成 koa 的中间件。在类方法的上层封装了一个 koa 的中间件方法,在这个方法内部自动执行类方法,并将这个方法的 this 指向原来的类。

// lenneth封装koa2的核心

const toAsyncMiddleware = (

target: Object | any,

middleware: TApiMiddleware,

key?: string,

cb?: (key: string, ctx: IContext, next: TNext) => any[]

) => {

return async (ctx: IContext, next: TNext) => {

if (key) {

// 此处一定要用call来重新设置this指向

return middleware.call(target, ...cb(key, ctx, next), ctx, next);

}

return middleware.call(target, ctx, next);

};

};各个模块

application

入口文件处,使用 ServerSettings 修饰,里面的参数都是一些全局方法,如 interceptor,response 等,这些都是一个 middleware,lenneth 只是依照 koa 的洋葱模型调整了他们的执行顺利

@ServerSettings({

port: 8081,

// controller

imports: {

"/apis": UserController

},

// 拦截器

interceptor: Interceptor,

// 返回值封装

response: AppResponse,

// error事件捕获

globalError: GlobalError

})

class App extends LennethApplication implements ILenneth {

$onMountingMiddlewares() {

this.use(logger());

}

}interceptor

其实也是一个中间件,只不过在最前执行

import { IMiddleware, Middleware, HeaderParams, Next, TNext } from "lenneth";

@Middleware()

export class Interceptor implements IMiddleware {

async use(@HeaderParams() header: any, @Next() next: TNext) {

console.log("Interceptor", header);

await next();

}

}response

中间件,在最后执行,默认开启,可以覆盖

import { IMiddleware, IContext, TResponse, TNext } from "@interfaces";

import { Middleware, Response, Next } from "@decorators";

import { HttpStatus, ResponseStatus } from "@common";

import { LennethError } from "./Lenneth-error";

@Middleware()

export class LennethResponse implements IMiddleware {

async use(

@Response() response: TResponse,

@Next() next: TNext,

ctx: IContext

) {

try {

// 执行前面所有的中间件

await next();

// 统一处理返回

if (response.body) {

return (response.body = {

code: 0,

message: ResponseStatus.SUCCESS,

data: response.body

});

}

return (response.body = { code: 0, message: ResponseStatus.SUCCESS });

} catch (err) {

ctx.status = err.code;

response.status = HttpStatus.OK;

if (err instanceof LennethError) {

response.body = {

code: err.code,

message: err.message || ResponseStatus.ERROR

};

} else {

response.body = {

code: err.code || HttpStatus.INTERNAL_SERVER_ERROR,

message: err.message || ResponseStatus.ERROR

};

// 未识别错误 抛至最外层error全局处理

throw err;

}

}

}

}controller

controller 主要是设置 router 和注入 services

router 的修饰器有 Post,Get 等,params 参数的获取同 spring,注入 service 使用修饰器 Autowired,这个也和 spring 一致

import {

Controller,

Autowired,

Post,

Get,

RequestBody,

PathVariable,

Response,

TResponse,

UseBefore,

Description

} from "lenneth";

import { UserService } from "../services";

import { IUserInfo } from "../interface";

import { UserAuth, RuleAuth } from "../middleware";

@Controller("/user")

export class UserController {

@Autowired() userService: UserService;

@Post("/add")

@Description("添加会员")

@UseBefore(UserAuth, RuleAuth)

async addUser(

@RequestBody() user: IUserInfo,

@Response() response: TResponse

) {

response.body = this.userService.addUser(user);

}

@Get("/detail/:userId")

@UseBefore(UserAuth)

@Description("查询会员")

async getUser(

@PathVariable("userId") userId: string,

@Response() response: TResponse

) {

response.body = this.userService.getUserInfo(userId);

}

}middleware

middleware 本质上其实就是 koa 的中间件,只不过我在此基础上又抽象出一层方法来引入获取 params 的方法,用来方便开发

在 controller 每个 api 上,使用 UseBefore 修饰器即可使用这些 middleware,在运行期,middleware 先于 controller 定义的接口,如果 middleware 没有调用 next 函数,则不会调用下一个中间件(kao 洋葱模型)

import { IMiddleware, Middleware, Next, TNext, HeaderParams } from "lenneth";

@Middleware()

export class UserAuth implements IMiddleware {

async use(@HeaderParams() headers: any, @Next() next: TNext) {

await next();

}

}

@Middleware()

export class RuleAuth implements IMiddleware {

async use(@HeaderParams() headers: any, @Next() next: TNext) {

await next();

}

}service

这个模块只是做一个类输出方法

export class UserService {

addUser(userInfo: IUserInfo) {

return userInfo;

}

getUserInfo(id: string) {

return {

name: "zhangsan",

age: 30

};

}

}单元测试

yarn test案例

项目地址

说在最后

当初做项目的时候,在 github 上搜过一个项目,是基于 express 的–ts-express-decorators,里面有很多不错的设计,lenneth 里的服务启动生命周期就是照搬其中的。不过我不喜欢把 node 弄得那么大,那么全,而且,koa 本身就是一个极简的应用,所以,lenneth 仅仅只是做了一层封装,繁简自然。

koa2+html模板,lenneth -- 基于koa2 的web极简框架相关推荐

  1. python3web库_基于 Python3 写的极简版 webserver

    基于 Python3 写的极简版 webserver.用于学习 HTTP协议,及 WEB服务器 工作原理.笔者对 WEB服务器 的工作原理理解的比较粗浅,仅是基于个人的理解来写的,存在很多不足和漏洞, ...

  2. Serverless 实战 —— 基于 Serverless 的 VuePress 极简静态网站

    基于 Serverless 的 VuePress 极简静态网站 作者: Aceyclee 之前用过 Docsify + Serverless Framework 快速创建个人博客系统,虽然 docsi ...

  3. 大学生个人网页模板 简单网页制作作业成品 极简风格个人介绍HTML(个人博客 4页)

    ⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材,DIV+CSS 布局制作,HTML+CSS网页设计期末课程大作业 | 个人博客网站 | 个人主页介绍 | 个人简介 | 个人博客设计 ...

  4. Java:2022年最流行的Web开发Java框架

    在2022年,你可以看到Java仍然是世界上最流行的编程语言之一.Java不仅是最流行的计算机编程语言之一,它还是一个平台.平台是帮助创建和运行用任何编程语言编写的程序的环境.此外,已经设计了各种框架 ...

  5. php slim框架 教程,Slim —— PHP web开发微框架

    Slim是一款基于PHP的web开发微框架,帮助 PHP 开发者快速编写简单强大的web应用和API.Slim的接口简单而符合直觉,文档也很详细. 直接看一段代码吧: $app->get('/' ...

  6. iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 处理静态资源

    视频地址:www.cctalk.com/v/151149238- 处理静态资源 无非花开花落,静静. 指定静态资源目录 这里我们使用第三方中间件: koa-static 安装并使用 安装 koa-st ...

  7. iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 路由koa-router

    路由koa-router--MVC 中重要的环节:Url 处理器 ?? iKcamp 制作团队 原创作者:大哼.阿干.三三.小虎.胖子.小哈.DDU.可木.晃晃 文案校对:李益.大力萌.Au.DDU. ...

  8. iKcamp团队制作|基于Koa2搭建Node.js实战(含视频)☞ 中间件用法

    中间件用法--讲解 Koa2 中间件的用法及如何开发中间件 ?? iKcamp 制作团队 原创作者:大哼.阿干.三三.小虎.胖子.小哈.DDU.可木.晃晃 文案校对:李益.大力萌.Au.DDU.小溪里 ...

  9. iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 记录日志

    为什么80%的码农都做不了架构师?>>>    沪江CCtalk视频地址:https://www.cctalk.com/v/15114923883523 log 日志中间件 最困难的 ...

最新文章

  1. URL和URI的区别 【转】
  2. css selector list
  3. java序列化与反序列化(转)
  4. HDU 4282 A very hard mathematic problem 二分题目
  5. 找不到类型{0} 它在 ServiceHost 指令中提供为 Service 特性值
  6. Struts2学习笔记04 之 拦截器
  7. 从部署 httpd 入手,理清 k8s 配置中的 containerPort、port、nodePort、targetPort
  8. P5934-[清华集训2012]最小生成树【最小割】
  9. hive选择mariadb还是mysql_Hive MariaDb的安装
  10. android布局添加布局,Android中添加布局和初始化布局总结
  11. 从入门到入土(八)RocketMQ的Consumer是如何做的负载均衡的
  12. 使用方法 ros_大白菜的ROS笔记(8)(创建TF广播和监听,内容很多,细节满满)...
  13. angular.js 验证码注册登录
  14. 单个圆孔菲涅耳衍射的matlab模拟,矩孔和圆孔菲涅耳衍射的计算机模拟
  15. three.js将fbx文件转为glb文件,并且压缩处理
  16. 快速实现微信公众号支付功能
  17. pandas模块DataFrame数据结构行数据的获取
  18. 苹果电池显示维修_苹果财大气粗:维修换电池?直接给你换个机
  19. C语言_函数可变参数列表
  20. 关于C++中Eigen库效率提升的思考

热门文章

  1. linux 解压缩一个文件夹下所有的压缩文件
  2. 视讯稳定对接出现的问题
  3. fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires MFC sha
  4. Java中String连接性能的分析
  5. 学习GNU Make (2): 规则
  6. C++中内存泄漏的检测方法介绍
  7. 退出页面 数据保留_IOS保留数据换appid教程(副号暂时无法解锁登录看这里)
  8. python中get属性_python3中__get__,__getattr__,__getattribute__的区别
  9. python中说_name_没有被定义_python – 为什么我得到这个NameError:名称’url_for’没有定义?...
  10. python多用户登录_python多用户