一个类似于springmvc的nodejs框架,内置了常用的express包,有丰富的可选配置,依赖注入. 项目地址 文档
功能
- 依赖注入
- 服务类
- Result 路由和控制器
- 中间件
- 过滤器
- 模型
- 转化器
- 启动器
快速开始
<br>
- 克隆 loon-boilerplate 项目
$ git clone https://github.com/loon-project/loon-boilerplate
$ cd loon-boilerplate
$ npm install
- 开始编译typescript并启动服务器
$ npm run dev
- 在浏览器中测试 http://localhost:9000
控制器
@RestController('/admin')
class AdminController {
@Get('/users/:id')
public userAction(@PathParam('id') id: number) {
# incoming request is /admin/users/1
# then id inside this action would be 1
}
@Get('/users')
public listUsersAction(@QueryParam('is_active') isActive: boolean) {
# incoming request is /admin/users?is_active=true
# then isActive inside this action would be true
isAction === true # => true
}
@Post('/users')
public createUserAction(@BodyParam('user') user: any) {
# incoming request is POST /admin/users with json body
# {
# user: {name: "Jack"}
# }
# then the user inside this action would be a object
user.name === "Jack" # => true
}
}
过滤器
AuthenticateFilter
前置过滤器检查是否用户已经登陆,
如果用户还没有登陆, 就直接返回 403 状态码。
使用时 AuthenticatedResourceController
加上一个 @BeforeFilter(AuthenticateFilter)
的注解,
这就意味着所有这个 Controller 里面的 路由都会使用前置过滤器 AuthenticateFilter
。
如果这个 Controller 需要几个能让匿名用户访问的路由, 可以在使用注解时加上参数来达到部分使用过滤器的目的。
@Filter()
class AuthenticateFilter implements IMiddleware {
public use(@Res() res: Express.Response, @Next() next: Express.NextFunction) {
if (// use is logged in) {
next();
} else {
res.sendStatus(403);
}
}
}
@RestController()
@BeforeFilter(AuthenticateFilter)
class AuthenticatedResourceController {}
中间件
注解了 @Middleware
并且实现了 IMiddleware
的类自动会识别并加载为 Middleware
。
@Middleware({order: 0})
class ELKMiddleware implements IMiddleware {
public use(@Next() next: Express.NextFunction) {
// start tracking
next()
// end tracking
// send to elk
}
}
错误中间件
@ErrorMiddleware
用法和 @Middleware
基本一样, 有一个不同点是你能通过 @Err
拿到错误 Object。
@ErrorMiddleware()
class ExceptionHandler implements IMiddleware {
public use(@Err() err: any, @Res() res: Express.Response) {
console.log(err.message);
res.sendStatus(400);
}
}
模型
模型通过添加 @Property
注解增加了转化的能力。
class User {
@Property()
firstName: string;
@Property()
lastName: string;
}
@RestController("/users")
class UserController {
@Post("")
public createAction(@BodyParam('user') user: User) {
user instanceof User # => true
}
}
控制器中的参数 user
制定了类是 User
, 当带有 http body 的请求到来时:
{
user: {
firstName: "Jack",
lastName: "Hai"
}
}
user 这个变量会自动的转化成 User
model 的实例。
自定义转化器
属性也支持传一个实现了 IConverter
借口的类作为自定义转化器。
@Service()
export class MomentConverter implements IConverter {
public deserialize(data: any, klassProperty: string, objectProperty: string): any {
const value = data[objectProperty];
if (typeof value === 'undefined') {
return;
}
const m = Moment.utc(value);
if (m.isValid()) {
return m;
}
return;
}
}
class User {
@Property({converter: MomentConverter})
public registerDate: Moment.Moment;
}
这个例子显示了如何写一个转化 string/Date
对象到 moment
utc 对象。
服务
@Service()
class UserService {
// any logic
}
@RestController('/users')
class UserController {
@Inject()
private userService: UserService;
@Get('')
public indexAction() {
this.userService.listUsers();
}
}
在例子中, UserService
注解了 @Service
, 然后被注入在了 UserController
。
文档更多详细的说明
欢迎star,fork还有各种issues 项目地址
挺好的,加油
加油加油
感觉特别赞,有空试用下。加油!
赞一个,话说用 ts 写项目可以不编译嘛,我也想学下 ts,但是总感觉每次写完和前端代码一样要打包的话好麻烦…
@hyj1991 可以的,用ts-node就好了 https://github.com/TypeStrong/ts-node
@xfstart07 原来你也看cnode啊,谢谢🙏
文档的静态文件使用了unpkg cdn加速,理论上打开速度会快很多。
感觉挺新颖的,感觉像是在做java。直接上公司项目有什么建议么?
感谢分享
不考虑进化到koa么
@YAOHAO9 上公司项目 🐂B 都开始用ts写node项目,厉害了
@YAOHAO9 问题不大,可以作为express的ts强化版使用,我们自己组已经小范围在用了。
@richenlin 没有看到koa的优势。
你这装饰器有点使用过度了,会让人难以理解
吹气球,吹个大气球。。
@yangchongduo 这个坑我踩定了,@vincent178 我push了一个分支到loon-boilerplate,不知道你有没有看到,没改什么东西,主要是配置。
@Initialize()
class ServiceInitializer implements IInitializer {
@Inject()
private application: ApplicationLoader;
public init() {
}
}
这个我放在Application前面可以用,有固定的文件夹位置么,在启动Application前去加载。但是我觉得这个跟$beforeInit、 $afterInit这些有点重复。希望可以给我点建议。
可以,建议放在 src/initializers/
文件夹
@vincent178 没有用,这个只是命名上的建议吧,我的意思是怎么像controller一样自动被注册到controllerRegister中。还有我看了源码也没有发现那里有去加载controllers文件夹下的controller。好神奇。。。 所以我的问题是 1:那些controller、service等是什么时候、怎样被注册的?是否Initialize也能自动被注册?我放在src/initializers/ 文件夹发现Initialize的init函数并没有被调用。 2:还有一个问题是component是什么东西,后端也有组件化开发了?文档好像中没有提到。
666
@YAOHAO9
在ApplicationSettings里面配置了rootDir之后,这个rootDir的export出来的都会被自动加载。
源代码在loon/src/server/ApplicationLoader.ts
这个文件里面。
加载后会根据不同的类型分别挂载到express里面。
Component和Service这两个互为别名,是一个可以被依赖注入的基本组件。
@vincent178 发现一个小bug。 应该loadComponents在init前面。不然Initializer永远没办法使用
@YAOHAO9 1.4.5版本修复了
@YAOHAO9 cnode没有邮件通知,你发github issue我会回的更及时一点。
mark
Mark
赞
Mark
是挺不错的。但是我已经用nest框架了。更全面些。
不错,spring IOC和AOP很强大,现在写nodejs和java一样,赞👍
Mark 学习下
@qinyang1980 同样,也是用nest.js 了