推荐答案
Nest.js 的架构主要基于模块化设计,采用了分层架构模式,主要包括以下几个核心部分:
模块(Module):Nest.js 应用由多个模块组成,每个模块封装了特定的功能。模块通过
@Module装饰器定义,并可以导入其他模块。控制器(Controller):控制器负责处理传入的 HTTP 请求,并返回响应。控制器通过
@Controller装饰器定义,通常与路由相关联。服务(Service):服务负责处理业务逻辑,通常被注入到控制器中。服务通过
@Injectable装饰器定义,并通过依赖注入(DI)机制进行管理。提供者(Provider):提供者是 Nest.js 中用于注入依赖的通用概念,服务是提供者的一种。提供者可以是任何类、值或工厂函数。
中间件(Middleware):中间件在请求到达控制器之前或之后执行,用于处理请求和响应。中间件可以是函数或类。
异常过滤器(Exception Filter):异常过滤器用于捕获和处理应用程序中的异常,可以自定义异常处理逻辑。
管道(Pipe):管道用于验证和转换输入数据,通常用于请求参数的验证和转换。
守卫(Guard):守卫用于实现路由级别的权限控制,通常用于身份验证和授权。
拦截器(Interceptor):拦截器用于在请求处理前后执行额外的逻辑,例如日志记录、性能监控等。
依赖注入(Dependency Injection, DI):Nest.js 使用依赖注入机制来管理类之间的依赖关系,使得代码更加模块化和可测试。
本题详细解读
模块(Module)
模块是 Nest.js 应用的基本构建块,每个模块都封装了一组相关的功能。模块通过 @Module 装饰器定义,并可以导入其他模块。模块的主要作用是将应用程序划分为多个功能区域,便于管理和维护。
@Module({
imports: [OtherModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}控制器(Controller)
控制器负责处理传入的 HTTP 请求,并返回响应。控制器通过 @Controller 装饰器定义,通常与路由相关联。控制器中的每个方法都可以处理特定的 HTTP 请求方法(如 GET、POST 等)。
@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
return 'This action returns all cats';
}
}服务(Service)
服务负责处理业务逻辑,通常被注入到控制器中。服务通过 @Injectable 装饰器定义,并通过依赖注入(DI)机制进行管理。服务的主要作用是将业务逻辑从控制器中分离出来,使得代码更加清晰和可维护。
@Injectable()
export class CatsService {
private readonly cats: string[] = ['Milo', 'Oscar', 'Max'];
findAll(): string[] {
return this.cats;
}
}提供者(Provider)
提供者是 Nest.js 中用于注入依赖的通用概念,服务是提供者的一种。提供者可以是任何类、值或工厂函数。提供者的主要作用是通过依赖注入机制将依赖关系注入到需要的地方。
const connectionProvider = {
provide: 'CONNECTION',
useValue: new Connection(),
};中间件(Middleware)
中间件在请求到达控制器之前或之后执行,用于处理请求和响应。中间件可以是函数或类。中间件的主要作用是处理跨切面的关注点,例如日志记录、请求验证等。
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log('Request...');
next();
}
}异常过滤器(Exception Filter)
异常过滤器用于捕获和处理应用程序中的异常,可以自定义异常处理逻辑。异常过滤器的主要作用是统一处理应用程序中的异常,使得异常处理更加集中和一致。
// www.javascriptcn.com code example
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const status = exception.getStatus();
response.status(status).json({
statusCode: status,
message: exception.message,
});
}
}管道(Pipe)
管道用于验证和转换输入数据,通常用于请求参数的验证和转换。管道的主要作用是确保输入数据的有效性和一致性。
@Injectable()
export class ValidationPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
// 验证和转换逻辑
return value;
}
}守卫(Guard)
守卫用于实现路由级别的权限控制,通常用于身份验证和授权。守卫的主要作用是保护路由,确保只有经过验证的用户才能访问特定的路由。
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
return validateRequest(request);
}
}拦截器(Interceptor)
拦截器用于在请求处理前后执行额外的逻辑,例如日志记录、性能监控等。拦截器的主要作用是在请求处理过程中插入额外的逻辑,而不需要修改控制器或服务的代码。
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
console.log('Before...');
return next.handle().pipe(tap(() => console.log('After...')));
}
}依赖注入(Dependency Injection, DI)
Nest.js 使用依赖注入机制来管理类之间的依赖关系,使得代码更加模块化和可测试。依赖注入的主要作用是将类的依赖关系从类内部解耦出来,使得类更加灵活和可测试。
@Injectable()
export class CatsService {
constructor(private readonly httpService: HttpService) {}
findAll(): Observable<Cat[]> {
return this.httpService.get('/cats').pipe(map(response => response.data));
}
}