目实战 NodeJS (IoC,DI)框架 项目实战
用NodeJS实现Nestjs或者java的SpringBoot的架构真正的去开发我们的nodejs项目
NodeJs
框架 ===> Express,Koa
数据库模型框架 ===> knex,prisma ORM,typeOrm
IoC控制反转和DI依赖注入
1- 控制反转(IoC)是一种设计原则,它将组件的控制权从组件自身转移到外部容器。传统上,组件负责自己的创建和管理,而控制反转则将这个责任转给了一个外部的容器或框架。容器负责创建组件实例并管理它们的生命周期,组件只需声明自己所需的依赖关系,并通过容器获取这些依赖。这种反转的控制权使得组件更加松耦合、可测试和可维护。
2- 依赖注入(DI)是实现控制反转的一种具体技术。它通过将组件的依赖关系从组件内部移动到外部容器来实现松耦合。组件不再负责创建或管理它所依赖的其他组件,而是通过构造函数、属性或方法参数等方式将依赖关系注入到组件中。依赖注入可以通过构造函数注入(Constructor Injection)、属性注入(Property Injection)或方法注入(Method Injection)等方式实现。
inversify + reflect-metadata 实现依赖注入中文文档
inversify GitHub
express 官网文档
inversify-express-utils 连接工具 官网
prisma orm 官网
Entity 数据校验和控制 class-validator + class-transformer
安装依赖
pnpm install inversify reflect-metadata inversify-express-utils
pnpm install express prisma class-validator class-transformer
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搞个容器
//注入工厂封装db
container.bind<PrismaClient>('PrismaClient').toFactory(()=>{
return () => {
return new PrismaClient()
}
})
container.bind(PrismaDB).toSelf()
//UserService
container.bind(UserService).to(UserService) //添加到容器
//UserController
container.bind(UserController).to(UserController) //添加到容器
const server = new InversifyExpressServer(container) //返回server
//middleware
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
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
2021-02-25 推荐 7 个 GitHub 上很火的 TypeScript 的宝库