NestJS中NestMiddleware依赖注入问题:express-session集成TypeORM报错
解决NestJS中SessionMiddleware依赖注入失败的问题
我之前也碰到过一模一样的依赖注入报错,结合你用express-session+TypeORM存储的场景,这个错误大概率是因为你的SessionMiddleware类在构造函数里声明了依赖,但Nest找不到对应的提供者。下面一步步给你理清楚怎么修:
1. 先检查你的SessionMiddleware构造函数
先看看你的中间件是不是类似这种写法(带依赖注入的类式中间件):
import { Injectable, NestMiddleware } from '@nestjs/common'; import { Request, Response, NextFunction } from 'express'; import * as session from 'express-session'; import { TypeormStore } from 'connect-typeorm'; import { InjectRepository } from '@nestjs/typeorm'; import { SessionEntity } from './session.entity'; import { Repository } from 'typeorm'; @Injectable() export class SessionMiddleware implements NestMiddleware { constructor( @InjectRepository(SessionEntity) private sessionRepository: Repository<SessionEntity>, ) {} use(req: Request, res: Response, next: NextFunction) { return session({ store: new TypeormStore().connect(this.sessionRepository), secret: 'your-secure-secret-key', resave: false, saveUninitialized: false, cookie: { secure: process.env.NODE_ENV === 'production' }, })(req, res, next); } }
如果是这样,问题就出在模块注册中间件的方式上。
2. 正确注册带依赖的类式中间件
在Nest里,类式中间件如果有依赖注入,不能直接用apply()传类就完事,得确保模块能识别到这个中间件的依赖提供者:
错误的注册方式(会导致依赖找不到)
// app.module.ts import { Module, MiddlewareConsumer } from '@nestjs/common'; import { SessionMiddleware } from './session.middleware'; import { TypeOrmModule } from '@nestjs/typeorm'; import { SessionEntity } from './session.entity'; @Module({ imports: [TypeOrmModule.forFeature([SessionEntity])], }) export class AppModule { configure(consumer: MiddlewareConsumer) { consumer.apply(SessionMiddleware).forRoutes('*'); // 直接传类会导致Nest找不到依赖 } }
正确的注册方式
把中间件加入模块的providers数组,让Nest的DI容器能解析它的依赖:
// app.module.ts import { Module, MiddlewareConsumer } from '@nestjs/common'; import { SessionMiddleware } from './session.middleware'; import { TypeOrmModule } from '@nestjs/typeorm'; import { SessionEntity } from './session.entity'; @Module({ imports: [TypeOrmModule.forFeature([SessionEntity])], providers: [SessionMiddleware], // 把中间件加入提供者列表 }) export class AppModule { configure(consumer: MiddlewareConsumer) { consumer.apply(SessionMiddleware).forRoutes('*'); } }
3. 确保TypeORM配置和实体正确
另外要确认两个关键点:
- 根模块已经导入了
TypeOrmModule.forRoot(),完成数据库连接配置 SessionEntity的字段完全符合connect-typeorm的要求,比如:
// session.entity.ts import { Entity, Column, PrimaryColumn } from 'typeorm'; @Entity() export class SessionEntity { @PrimaryColumn() id: string; @Column() expiresAt: number; @Column('text') data: string; }
4. 备选方案:用函数式中间件绕开DI问题
如果类式中间件的DI实在折腾不清楚,也可以换成函数式中间件,手动获取Repository:
// session.middleware.ts import { Request, Response, NextFunction } from 'express'; import * as session from 'express-session'; import { TypeormStore } from 'connect-typeorm'; import { getRepository } from 'typeorm'; import { SessionEntity } from './session.entity'; export function sessionMiddleware(req: Request, res: Response, next: NextFunction) { const sessionRepository = getRepository(SessionEntity); return session({ store: new TypeormStore().connect(sessionRepository), secret: 'your-secure-secret-key', resave: false, saveUninitialized: false, cookie: { secure: process.env.NODE_ENV === 'production' }, })(req, res, next); }
然后在模块里注册:
// app.module.ts configure(consumer: MiddlewareConsumer) { consumer.apply(sessionMiddleware).forRoutes('*'); }
这种方式不需要依赖注入,适合快速解决问题,但类式中间件的可测试性会更好一些。
最后检查启动顺序
如果还是不行,可能是TypeORM连接还没建立就初始化了session中间件。可以给中间件加上OnModuleInit钩子,确保数据库连接完成后再初始化session:
@Injectable() export class SessionMiddleware implements NestMiddleware, OnModuleInit { private sessionMiddleware: any; constructor( @InjectRepository(SessionEntity) private sessionRepository: Repository<SessionEntity>, ) {} async onModuleInit() { await this.sessionRepository.manager.connection.connect(); this.sessionMiddleware = session({ store: new TypeormStore().connect(this.sessionRepository), // 其他session配置 }); } use(req: Request, res: Response, next: NextFunction) { this.sessionMiddleware(req, res, next); } }
按上面的步骤调整后,应该就能解决依赖注入失败的问题,让Express正常启动了。
内容的提问来源于stack exchange,提问作者cvhberger
相关产品推荐
相关产品推荐

