Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the principle of Spring MVC exception parser

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.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report