This article will take you to understand the AOP architecture of the back-end framework Nest.js and introduce the benefits of the Nest.js AOP architecture. I hope it will be helpful to everyone!
Nest.js is a
Nodejsback-end framework. It encapsulates http platforms such as express to solve architectural problems. It provides MVC, IOC, AOP and other architectural features that express does not have, making the code easier to maintain and expand. What do MVC, IOC, and AOP here mean? Let’s take a look at them respectively:
MVC, IOC
Nest.js provides the @Controller decorator to declare the Controller:
And the Service will be decorated with @Injectable Decorator to declare:
Classes declared through @Controller and @Injectable decorators will be scanned by Nest.js, corresponding objects will be created and added to a container. All of these The object will be automatically injected according to the dependency declared in the constructor, which is DI (dependency inject). This idea is called IOC (Inverse Of Control).
The advantage of the IOC architecture is that there is no need to manually create objects and pass them into the constructors of different objects based on dependencies. Everything is automatically scanned, created, and injected.In addition, Nest.js also provides the ability of AOP (Aspect Oriented Programming), which is the ability of aspect-oriented programming:
AOP
A request may go through the logic of Controller, Service, and Repository (database access):
If you want to How to add some general logic to this call link? Such as logging, permission control, exception handling, etc.
The easy thing to think of is to directly transform the Controller layer code and add this logic. This works, but it's not elegant because these common logics invade the business logic. Can we transparently add logs, permissions, etc. to these business logics?
Is it possible to add a stage to execute common logic before and after calling the Controller?
For example:
Such a horizontal expansion point is called an aspect, and this transparent programming method that adds some aspect logic is called AOP (aspect-oriented) programming).
The advantage of AOP is that it can separate some common logic into aspects and keep the business logic pure. In this way, the aspect logic can be reused and dynamically added and deletedIn fact, the onion model of Express's middleware is also an AOP implementation, because you can transparently wrap a layer on the outside and add some logic, and the inner layer will not be aware of it.
And Nest.js has more ways to implement AOP, there are five in total, including Middleware, Guard, Pipe, Inteceptor, ExceptionFilter:,
MiddlewareMiddleware
Global middleware is the middleware of Express. Before requesting and After adding some processing logic, each request will go here:
Routing middleware is for a certain route, with a smaller scope:
This is a concept that directly inherits Express and is easier to understand.
Let’s look at some concepts of Nest.js extension, such as Guard:
Guard
The way to create Guard is as follows:
Guard needs to implement the CanActivate interface and the canActive method. It can get the requested information from the context, and then perform some permission verification and other processing before returning true or false.
Add it to the IOC container through the @Injectable decorator, and then enable it in a Controller:
##The Controller itself does not need to be modified. But the logic of permission judgment is transparently added. This is the benefit of the AOP architecture. And, just like Middleware supports global level and routing level, Guard can also be enabled globally: Guard can abstract the access control logic of routing, However, the request and response cannot be modified. This kind of logic can use Interceptor: InterceptorInterceptor means interceptor. You can add some logic before and after the target Controller method: The way to create an Inteceptor is as follows: Interceptor To implement the NestInterceptor interface, implement the intercept method and call next.handle() The target Controller will be called, and some processing logic can be added before and after. The processing logic before and after the Controller may be asynchronous. Nest.js organizes them through rxjs, so you can use various operators of rxjs. Interceptor supports each route being enabled individually, which only affects a certain controller. It also supports global enablement, which affects all controllers:In addition to routing permission control and processing before and after the target Controller, which are all common logic, the processing of parameters is also a common logic, so Nest.js also extracted the corresponding aspects, that is, Pipe: PipePipe means pipeline, used to do some verification and conversion of parameters: The way to create Pipe is like this : Pipe To implement the PipeTransform interface, implement the transform method, which can perform parameter verification on the incoming parameter value value, such as whether the format and type are correct. If it is not correct, then throw an exception. You can also perform conversion and return the converted value. There are 8 built-in Pipes, and their meanings can be seen from their names:
Whether it is Pipe, Guard, Interceptor or the Controller that is finally called, it can be used during the process Throw some exceptions, how to respond to certain exceptions?
This mapping of exceptions to responses is also a common logic. Nest.js provides ExceptionFilter to support:
ExceptionFilter
The form of creating ExceptionFilter is as follows:
First, implement the ExceptionFilter interface, By implementing the catch method, you can intercept exceptions, but what exceptions you want to intercept need to be declared with the @Catch decorator. After intercepting the exception, you can respond with the exception corresponding to give the user a more friendly prompt.
Of course, not all exceptions will be handled. Only exceptions that inherit HttpException will be handled by ExceptionFilter. Nest.js has many built-in subclasses of HttpException:
BadRequestException
UnauthorizedException
NotFoundException
ForbiddenException
NotAcceptableException
RequestTimeoutException
ConflictException
GoneException
PayloadTooLargeException
UnsupportedMediaTypeException
UnprocessableException
InternalServerErrorException
NotImplementedException
BadGatewayException
Nest.js is implemented in this way With the corresponding relationship between exceptions and responses, as long as different HttpExceptions are thrown in the code, the corresponding responses will be returned, which is very convenient.
Similarly, ExceptionFilter can also choose to take effect globally or take effect on a certain route: A certain route: Globally: We understand the AOP mechanism provided by Nest.js, but what is their sequential relationship? The order of several AOP mechanismsMiddleware, Guard, Pipe, Interceptor, and ExceptionFilter can all transparently add certain processing logic to a certain route or all routes. This is the benefit of AOP. But what is the sequential relationship between them? The calling relationship depends on the source code. The corresponding source code is like this: #Obviously, when entering this route, Guard will be called first to determine whether there is permission, etc., if not Permissions, an exception is thrown here: The HttpException thrown will be handled by ExceptionFilter. If you have permission, the interceptor will be called. The interceptor organizes a chain, calls one by one, and finally calls the controller method: Before calling the controller method, pipe will be used to process the parameters: Each parameter will be converted:The calling timing of ExceptionFilter is easy to think of, which is to handle the exception before responding. And Middleware is a concept in express. Nest.js just inherits it, and it is called at the outermost layer. This is the calling sequence of these AOP mechanisms. Once you have these things sorted out, you will have a good grasp of Nest.js. SummaryNest.js is a layer of encapsulation based on the express http platform, and applies MVC, IOC, AOP and other architectural ideas. MVC is the division of Model and View Controller. The request first passes through the Controller, then calls the Service and Repository of the Model layer to complete the business logic, and finally returns the corresponding View. IOC means that Nest.js will automatically scan classes with @Controller and @Injectable decorators, create their objects, and automatically inject the objects it depends on based on dependencies, eliminating manual creation and assembly. Object trouble. AOP extracts general logic and adds it to a certain place through aspects. It can reuse and dynamically add and delete aspect logic. Middleware, Guard, Interceptor, Pipe, and ExceptionFileter of Nest.js are all implementations of AOP ideas. They are just aspects at different locations. They can all be flexibly applied to a certain route or all routes. This is Advantages of AOP. We looked at their calling sequence through the source code. Middleware is the concept of Express. In the outermost layer, after reaching a certain route, Guard will be called first. Guard is used to determine whether the route has permission to access, and then The Interceptor will be called to extend some logic before and after the Controller. Before reaching the target Controller, the Pipe will be called to verify and convert the parameters. All HttpException exceptions will be handled by ExceptionFilter and return different responses. Nest.js uses this AOP architecture to achieve a loosely coupled, easy to maintain and expand architecture. Have you felt the benefits of AOP architecture? For more node-related knowledge, please visit:
nodejs tutorial!
The above is the detailed content of Understand the AOP architecture of Node.js Nest.js and talk about its benefits. For more information, please follow other related articles on the PHP Chinese website!