Como começar rapidamente com o VUE3.0: Entre e aprenda
Nest.js é uma estrutura de back-end do Nodejs. Ele encapsula express e outras plataformas http para resolver problemas de arquitetura. Ele fornece MVC, IOC, AOP e outros recursos de arquitetura que o Express não possui, tornando o código mais fácil de manter e expandir.
O que significam MVC, IOC e AOP aqui? Vamos analisá-los separadamente:
MVC é a abreviatura de Model View Controller. Na arquitetura MVC, a solicitação será enviada primeiro ao Controlador, que despachará o Serviço da camada Modelo para completar a lógica de negócio e, em seguida, retornará a Visualização correspondente.
Nest.js fornece o decorador @Controller para declarar o Controller:
O Serviço será declarado com o decorador @Injectable:
As classes declaradas através dos decoradores @Controller e @Injectable serão varridas pelo Nest.js, os objetos correspondentes serão criados e adicionados a um container. Todos esses objetos serão injetados automaticamente de acordo com as dependências declaradas no construtor, ou seja, DI (dependência). injetar) ), essa ideia é chamada de IOC (Inverse Of Control).
A vantagem da arquitetura IOC é que não há necessidade de criar objetos manualmente e passá-los para os construtores de diferentes objetos com base em dependências. Tudo é verificado, criado e injetado automaticamente.
Além disso, Nest.js também fornece a capacidade de AOP (Aspect Oriented Programming), que é a capacidade de programação orientada a aspectos:
O que significa AOP? O que é programação orientada a aspectos?
Uma solicitação pode passar pela lógica de Controlador, Serviço e Repositório (acesso ao banco de dados):
Se você quiser adicionar alguma lógica geral a este link de chamada, como deverá adicioná-la? Como registro, controle de permissão, tratamento de exceções, etc.
O que é fácil de pensar é transformar diretamente o código da camada Controlador e adicionar essa lógica. Isso funciona, mas não é elegante porque essas lógicas comuns invadem a lógica de negócios. Podemos adicionar logs, permissões, etc. de forma transparente a essas lógicas de negócios?
É possível adicionar um estágio para executar lógica comum antes e depois de chamar o Controlador?
Por exemplo:
Esses pontos de expansão horizontal são chamados de aspectos, e esse método de programação que adiciona de forma transparente alguma lógica de aspecto é chamado de AOP (programação orientada a aspectos).
A vantagem do AOP é que ele pode separar alguma lógica geral em aspectos e manter a lógica de negócios pura. Dessa forma, a lógica de aspecto pode ser reutilizada e adicionada e excluída dinamicamente.
Na verdade, o modelo cebola do middleware do Express também é uma implementação. do AOP, porque você pode envolver uma camada externa de forma transparente e adicionar alguma lógica, e a camada interna não será perceptível.
Nest.js tem mais maneiras de implementar AOP, há cinco no total, incluindo Middleware, Guard, Pipe, Inteceptor, ExceptionFilter:,
Nest.js é baseado em Express e pode usar middleware naturalmente, mas foi subdividido ainda mais. , dividido em middleware global e middleware de roteamento:
middleware global é o middleware do Express. Alguma lógica de processamento é adicionada antes e depois da solicitação.
O middleware de roteamento é para uma determinada rota, com um escopo menor:
Este conceito herda diretamente o Express e é mais fácil de entender.
Vamos dar uma olhada em alguns conceitos estendidos do Nest.js, como Guard:
Guard significa roteamento guard. Ele pode ser usado para determinar permissões antes de chamar um Controller e retornar verdadeiro ou falso para decidir se deve liberar:
A forma de criar um Guarda é a seguinte:
O Guard precisa implementar a interface CanActivate e o método canActive. Ele pode obter as informações solicitadas do contexto e, em seguida, realizar algumas verificações de permissão e outros processamentos antes de retornar verdadeiro ou falso.
Adicione-o ao contêiner IOC através do decorador @Injectable e habilite-o em um Controller:
O controlador em si não precisa ser modificado, mas a lógica de julgamento de permissão é adicionada de forma transparente. Este é o benefício da arquitetura AOP.
E, assim como o Middleware suporta níveis globais e de rota, o Guard também pode ser habilitado globalmente:
O Guard pode abstrair a lógica de controle de acesso do roteamento, mas não pode modificar solicitações e respostas. Esta lógica pode usar o Interceptor:
Interceptor significa interceptor. Você pode adicionar alguma lógica antes e depois do método do controlador de destino.
A maneira de criar um Inteceptor é a seguinte:
O Interceptor precisa implementar a interface NestInterceptor e o método de interceptação. Chamar next.handle() chamará o controlador de destino.
A lógica de processamento antes e depois do Controlador pode ser assíncrona. Nest.js os organiza por meio de rxjs, para que você possa usar vários operadores de rxjs.
O Interceptor suporta que cada rota seja habilitada individualmente, o que afeta apenas um determinado controlador, e também suporta habilitação global, que afeta todos os controladores:
Além do controle de permissão das rotas e do processamento antes e depois do Controlador de destino, que são todos lógicos comuns, o processamento dos parâmetros também é uma lógica comum, então Nest.js também extrai os aspectos correspondentes, ou seja, Pipe:
Pipe significa pipe, usado para fazer alguma verificação e conversão de parâmetros:
A maneira de criar um Pipe é a seguinte:
O Pipe precisa implementar a interface PipeTransform e o método transform, que pode realizar a verificação do parâmetro no valor do parâmetro recebido, como se o formato e o tipo estão corretos. Se não estiver correto, uma exceção será lançada. Você também pode realizar a conversão e retornar o valor convertido.
Existem 8 Pipes integrados, e seus significados podem ser vistos nos nomes:
ValidationPipe
ParseIntPipe
ParseBoolPipe
ParseArrayPipe
ParseUUIDPipe
DefaultValuePipe
ParseEnumPipe
ParseFloatPipe
Da mesma forma, o Pipe só pode ter efeito em uma determinada rota ou em todas as rotas:
Quer seja o Pipe, o Guard, o Interceptor ou o Controller que é finalmente chamado, algumas exceções podem ser lançadas durante o processo. Como responder a certas exceções?
Este mapeamento de exceções para respostas também é uma lógica comum Nest.js fornece ExceptionFilter para suporte:
ExceptionFilter pode lidar com exceções lançadas e retornar respostas correspondentes:
A forma de criação do ExceptionFilter é a seguinte:
Primeiro, você precisa implementar a interface ExceptionFilter e o método catch para interceptar exceções. No entanto, quais exceções você deseja interceptar precisam ser declaradas com o decorador @Catch. Depois de interceptar a exceção, você pode responder com a exceção correspondente para fornecer. usuário um prompt mais amigável.
É claro que nem todas as exceções serão tratadas. Somente as exceções que herdam HttpException serão tratadas por ExceptionFilter Nest.js tem muitas subclasses integradas de HttpException:
BadRequestException
UnauthorizedException
NotFoundException
ForbiddenException
NotAcceptableException
RequestTimeoutException
ConflictException
GoneException
PayloadTooLargeException
UnsupportedMediaTypeException
UnprocessableException
InternalServerErrorException
NotImplementedException
BadGatewayException
ServiceUnavailableException
GatewayTimeoutException
Claro, você também pode estendê-lo:
Nest.js realiza a correspondência entre exceções e respostas desta forma, desde que diferentes HttpExceptions sejam lançadas no código, as respostas correspondentes serão retornadas, o que é muito conveniente.
Da mesma forma, ExceptionFilter também pode optar por ter efeito global ou em uma determinada rota:
uma determinada rota:
Global:
Compreendemos o mecanismo AOP fornecido pelo Nest.js, mas qual é a relação de pedido deles?
Middleware, Guard, Pipe, Interceptor e ExceptionFilter, pode adicionar de forma transparente certa lógica de processamento a uma determinada rota ou a todas as rotas.
Mas qual é a relação sequencial entre eles?
O relacionamento de chamada depende do código-fonte.
O código-fonte correspondente é o seguinte:
Obviamente, ao entrar nesta rota, o Guard será chamado primeiro para determinar se há permissão, etc. Se não houver permissão, uma exceção será lançada aqui:
A HttpException lançada será tratada por ExceptionFilter.
Se você tiver permissão, o interceptor será chamado. O interceptor organiza uma cadeia, chama um por um e finalmente chama o método do controlador:
Antes de chamar o método do controlador, o pipe será usado para processar os parâmetros:
Cada parâmetro será convertido:
É fácil pensar no tempo de chamada do ExceptionFilter, que trata da exceção antes de responder.
Middleware é um conceito expresso, Nest.js apenas o herda e é chamado na camada mais externa.
Esta é a sequência de chamada desses mecanismos AOP. Depois de resolver essas coisas, você terá uma boa noção do Nest.js.
Nest.js é encapsulado com base na plataforma http expressa e aplica ideias de arquitetura como MVC, IOC e AOP.
MVC é a divisão do Model and View Controller. A solicitação passa primeiro pelo Controller, depois chama o Serviço e o Repositório da camada Model para completar a lógica de negócios e, finalmente, retorna a View correspondente.
IOC significa que o Nest.js verificará automaticamente as classes com os decoradores @Controller e @Injectable, criará seus objetos e injetará automaticamente os objetos dos quais depende com base nas dependências, eliminando o problema de criar e montar objetos manualmente.
AOP extrai lógica geral e a adiciona a um determinado local por meio de aspectos. Ele pode reutilizar e adicionar e excluir dinamicamente a lógica de aspecto.
Middleware, Guard, Interceptor, Pipe e ExceptionFileter do Nest.js são todos implementações de ideias de AOP. Eles são apenas aspectos em locais diferentes. Todos podem ser aplicados de maneira flexível a uma determinada rota ou a todas as rotas.
Analisamos sua sequência de chamada por meio do código-fonte. Middleware é o conceito de Express. Na camada mais externa, após atingir uma determinada rota, o Guard será chamado primeiro para determinar se a rota tem permissão de acesso. O Interceptor será chamado. Expanda alguma lógica para frente e para trás e chame o Pipe para verificar e converter os parâmetros antes de chegar ao Controlador de destino. Todas as exceções HttpException serão tratadas por ExceptionFilter e retornarão respostas diferentes.
Nest.js usa essa arquitetura AOP para obter uma arquitetura pouco acoplada, fácil de manter e expandir.
Você sentiu os benefícios da arquitetura AOP?