赞
踩
到现在为止,我们学习了,express框架,编写接口,mysql数据库读写数据,knex,prisma ORM框架,现在是时候把这些组合到一起,并且实现一个类似于Nestjs
或者java的SpringBoot
的架构真正的去开发我们的nodejs项目
MVC(Model-View-Controller)是一种常用的软件架构模式,用于设计和组织应用程序的代码。它将应用程序分为三个主要组件:模型(Model)、视图(View)和控制器(Controller),各自负责不同的职责。
MVC 的主要目标是将应用程序的逻辑、数据和界面分离,以提高代码的可维护性、可扩展性和可重用性。通过将不同的职责分配给不同的组件,MVC 提供了一种清晰的结构,使开发人员能够更好地管理和修改应用程序的各个部分。
控制反转(Inversion of Control,IoC)和依赖注入(Dependency Injection,DI)是软件开发中常用的设计模式和技术,用于解耦和管理组件之间的依赖关系。虽然它们经常一起使用,但它们是不同的概念。
控制反转(IoC)是一种设计原则,它将组件的控制权从组件自身转移到外部容器。传统上,组件负责自己的创建和管理,而控制反转则将这个责任转给了一个外部的容器或框架。容器负责创建组件实例并管理它们的生命周期,组件只需声明自己所需的依赖关系,并通过容器获取这些依赖。这种反转的控制权使得组件更加松耦合、可测试和可维护。
依赖注入(DI)是实现控制反转的一种具体技术。它通过将组件的依赖关系从组件内部移动到外部容器来实现松耦合。组件不再负责创建或管理它所依赖的其他组件,而是通过构造函数、属性或方法参数等方式将依赖关系注入到组件中。依赖注入可以通过构造函数注入(Constructor Injection)、属性注入(Property Injection)或方法注入(Method Injection)等方式实现。
inversify
+ reflect-metadata
实现依赖注入 官网
接口编写express
官网
连接工具 inversify-express-utils
文档
dto class-validator
+ class-transformer
文档
新建一个app文件夹
通过 prisma init --datasource-provider mysql
构建prisma项目 上一章讲过了
https://juejin.cn/post/7337188759056384015
目录结构
main.ts
import 'reflect-metadata' import { InversifyExpressServer } from 'inversify-express-utils' import { Container } from 'inversify' import { UserController } from './src/user/controller' import { UserService } from './src/user/service' import express from 'express' import { PrismaClient } from '@prisma/client' import { PrismaDB } from './src/db' const container = new Container() //Ioc搞个容器 /** * prisma依赖注入 */ //注入工厂封装db container.bind<PrismaClient>('PrismaClient').toFactory(()=>{ return () => { return new PrismaClient() } }) container.bind(PrismaDB).toSelf() /** * user模块 */ container.bind(UserService).to(UserService) //添加到容器 container.bind(UserController).to(UserController) //添加到容器 /** * post模块 */ const server = new InversifyExpressServer(container) //返回server //中间件编写在这儿 server.setConfig(app => { app.use(express.json()) //接受json }) const app = server.build() //app就是express app.listen(3000, () => { console.log('http://localhost:3000') })
src/user/controller.ts
import { controller, httpGet as GetMapping, httpPost as PostMapping } from 'inversify-express-utils' import { inject } from 'inversify' import { UserService } from './service' import type { Request, Response } from 'express' @controller('/user') //路由 export class UserController { constructor( @inject(UserService) private readonly userService: UserService, //依赖注入 ) { } @GetMapping('/index') //get请求 public async getIndex(req: Request, res: Response) { console.log(req?.user.id) const info = await this.userService.getUserInfo() res.send(info) } @PostMapping('/create') //post请求 public async createUser(req: Request, res: Response) { const user = await this.userService.createUser(req.body) res.send(user) } }
src/user/service.ts
import { injectable, inject } from 'inversify' import { UserDto } from './user.dto' import { plainToClass } from 'class-transformer' //dto验证 import { validate } from 'class-validator' //dto验证 import { PrismaDB } from '../db' @injectable() export class UserService { constructor( @inject(PrismaDB) private readonly PrismaDB: PrismaDB //依赖注入 ) { } public async getUserInfo() { return await this.PrismaDB.prisma.user.findMany() } public async createUser(data: UserDto) { const user = plainToClass(UserDto, data) const errors = await validate(user) const dto = [] if (errors.length) { errors.forEach(error => { Object.keys(error.constraints).forEach(key => { dto.push({ [error.property]: error.constraints[key] }) }) }) return dto } else { const userInfo = await this.PrismaDB.prisma.user.create({ data: user }) return userInfo } } }
src/user/user.dto.ts
import { IsNotEmpty, IsEmail } from 'class-validator'
import { Transform } from 'class-transformer'
export class UserDto {
@IsNotEmpty({ message: '用户名必填' })
@Transform(user => user.value.trim())
name: string
@IsNotEmpty({ message: '邮箱必填' })
@IsEmail({},{message: '邮箱格式不正确'})
@Transform(user => user.value.trim())
email: string
}
src/db/index.ts
import { injectable, inject } from 'inversify'
import { PrismaClient } from '@prisma/client'
@injectable()
export class PrismaDB {
prisma: PrismaClient
constructor(@inject('PrismaClient') PrismaClient: () => PrismaClient) {
this.prisma = PrismaClient()
}
}
tsconig.json
支持装饰器和反射 打开一下 严格模式关闭
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"strict": false,
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。