In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article focuses on "what is the principle of Spring MVC exception parser", interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "what is the principle of Spring MVC exception parser"?
Introduction to use
There are two ways to customize the exception handling strategy
Use @ ExceptionHandler annotations
Implement the HandlerExceptionResolver interface
Because the @ ExceptionHandler annotation is powerful enough, we rarely customize exception handling strategies by implementing HandlerExceptionResolver.
Briefly introduce the use of @ ExceptionHandler, and then analyze the source code with these examples
@ RestController @ RequestMapping ("location") public class LocationController {@ RequestMapping ("getLocationInfo") public String index () {int sum = 10 / 0; return "locationInfo";} @ ExceptionHandler (RuntimeException.class) public String processRuntimeException () {return "LocationController-> RuntimeException";} @ ExceptionHandler (Exception.class) public String processException () {return "LocationController-> occur Exception";}}
Visit the link below and return the result as
Http://localhost:8080/location/getLocationInfo LocationController-> RuntimeException occurs
After commenting out the processRuntimeException method, visit the link above again, and the result is
LocationController-> Exception occurs
If it's troublesome to write exception parsers in every Controller, can you handle exceptions in one place? Of course, you have to use @ RestControllerAdvice or @ ControllerAdvice at this time.
Write the following global exception parser
@ RestControllerAdvice public class MyExceptionHandler {@ ExceptionHandler (RuntimeException.class) public String processRuntimeException () {return "MyExceptionHandler-> RuntimeException";} @ ExceptionHandler (Exception.class) public String processException () {return "MyExceptionHandler-> RuntimeException";}}
Visit the link above and return the result as
LocationController-> Exception occurs
We also comment out the processException method of the LocationController class, so that there are no methods marked by the @ ExceptionHandler annotation in the LocationController class.
Visit the link above and return the result as
MyExceptionHandler-> RuntimeException occurs
Comment out the processRuntimeException method in MyExceptionHandler and visit the link above, and the result is
MyExceptionHandler-> Exception occurs
From the above examples, we can draw the following conclusions
The parser in the @ RestControllerAdvice or @ ControllerAdvice class has a lower priority than the parser in the @ RequestMapping class
If an exception can be handled by multiple parsers, select the parser with the closest inheritance relationship
Suppose BizException inherits from NullPointException A method parsing BizException B parsing NullPointException C parsing Exception
BizException will be parsed by A method NullPointException will be parsed by B method if there is no A method, then BizException will be parsed by B method, if there is no B method, it will be parsed by C method, it is not difficult to understand
What's the difference between @ RestControllerAdvice and @ ControllerAdvice?
You can guess from the name that @ RestControllerAdvice just adds the @ ResponseBody annotation to @ ControllerAdvice, and it's true to see a wave of source code. So the @ RestControllerAdvice class ends up returning JSON,@ControllerAdvice and ultimately returning the view. If you don't understand why the @ ResponseBody annotation finally returns JSON, it is recommended to take a look at the return value processor.
Source code analysis
The exception parser interface is defined as follows
Public interface HandlerExceptionResolver {/ / encapsulates the exception as ModelAndView and returns @ Nullable ModelAndView resolveException (HttpServletRequest request, HttpServletResponse response, @ Nullable Object handler, Exception ex);}
The default exception parser for Spring MVC is stored in the following properties
@ Nullable private List handlerExceptionResolvers
The order is as follows
ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
The UML figure is as follows
The Order interface is used to sort, ha. The default parser of Spring MVC does not control the order through the Order interface, because the default parser inherits from AbstractHandlerExceptionResolver and does not override the getOrder method.
Partners who are familiar with Spring MVC should know that the default implementation of the DispatcherServlet attribute is defined in the DispatcherServlet.properties file of the source package, and the order of List is in this way. Put part of the content
Org.springframework.web.servlet.HandlerAdapter= org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter org.springframework.web.servlet.HandlerExceptionResolver= org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\ org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionReso
Next, analyze the three default HandlerExceptionResolver
ExceptionHandlerExceptionResolver
ExceptionHandlerExceptionResolver is used to support @ ExceptionHandler, and @ ExceptionHandler should be our most common. It is easier for us to customize the exception handling policy than by implementing the HandlerExceptionResolver interface.
As you can see from AbstractHandlerMethodExceptionResolver#shouldApplyTo,
@ Override protected boolean shouldApplyTo (HttpServletRequest request, @ Nullable Object handler) {if (handler = = null) {/ / handler is empty, leave it to the parent class to judge / / default that the logic returns true return super.shouldApplyTo (request, null);} else if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler; handler = handlerMethod.getBean (); / / to the parent class to judge return super.shouldApplyTo (request, handler) } else {/ / does not support return false;}}
The following exception resolution logic is executed only if handler is empty or the type of handler is HandlerMethod (the type returned by @ RequestMapping is HandlerMethod). So this annotation doesn't work by implementing the Controller interface or the Handler defined by the HttpRequestHandler interface.
The processing of @ ExceptionHandler is mainly related to the following two classes, ExceptionHandlerExceptionResolver,ExceptionHandlerMethodResolver
If you talk about the process with a few member variables, you won't post too much code.
ExceptionHandlerExceptionResolver
/ / omitted inheritance and implementation relationships public class ExceptionHandlerExceptionResolver {@ Nullable private HandlerMethodArgumentResolverComposite argumentResolvers; @ Nullable private HandlerMethodReturnValueHandlerComposite returnValueHandlers; private List, ExceptionHandlerMethodResolver > exceptionHandlerCache = new ConcurrentHashMap (64); / / classes marked with @ ControllerAdvice annotations-> ExceptionHandlerMethodResolver private final Map exceptionHandlerAdviceCache = new LinkedHashMap ();}
You can see that the ExceptionHandlerExceptionResolver class defines its own parameter handler, return value handler, and message converter. So you can reverse know the parameter types supported by the @ ExceptionHandler method through these components.
For example, you can know from the following method that the supported parameter type is @ SessionAttribute,@RequestAttribute, etc. If you write a @ RequestParam, you will definitely not inject it.
Protected List getDefaultArgumentResolvers () {List resolvers = new ArrayList (); / / Annotation-based argument resolution resolvers.add (new SessionAttributeMethodArgumentResolver ()); resolvers.add (new RequestAttributeMethodArgumentResolver ()); / / Type-based argument resolution resolvers.add (new ServletRequestMethodArgumentResolver ()); resolvers.add (new ServletResponseMethodArgumentResolver ()); resolvers.add (new RedirectAttributesMethodArgumentResolver ()); resolvers.add (new ModelMethodProcessor ()); / / Custom arguments if (getCustomArgumentResolvers ()! = null) {resolvers.addAll (getCustomArgumentResolvers ());} return resolvers }
Here comes the four most important map. The main working process of ExceptionHandlerExceptionResolver is to operate these four map.
/ / classes marked with @ RequestMapping {/ / inheritance and implementation relationship public class ExceptionHandlerExceptionResolver {/ / are omitted-> ExceptionHandlerMethodResolver private final Map
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.