How to handle exceptions with @ RestControllerAdvice
This article is about how to handle exceptions using @ RestControllerAdvice. The editor thinks it is very practical, so I share it with you. I hope you can learn something after reading this article. Let's take a look at it with the editor.
From the DispatcherServlet entrance, as follows:
Protected void doService (HttpServletRequest request, HttpServletResponse response) throws Exception {if (logger.isDebugEnabled ()) {String resumed = WebAsyncUtils.getAsyncManager (request) .hasConcurrentResult ()? " Resumed ":"; logger.debug ("DispatcherServlet with name'" + getServletName () + "'" + resumed + "processing" + request.getMethod () + "request for [" + getRequestUri (request) + "]");} / / Keep a snapshot of the request attributes in case of an include, / / to be able to restore the original attributes after the include. Map attributesSnapshot = null; if (WebUtils.isIncludeRequest (request)) {attributesSnapshot = new HashMap (); Enumeration attrNames = request.getAttributeNames (); while (attrNames.hasMoreElements ()) {String attrName = (String) attrNames.nextElement (); if (this.cleanupAfterInclude | | attrName.startsWith (DEFAULT_STRATEGIES_PREFIX)) {attributesSnapshot.put (attrName, request.getAttribute (attrName)) } / / Make framework objects available to handlers and view objects. Request.setAttribute (WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext ()); request.setAttribute (LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); request.setAttribute (THEME_RESOLVER_ATTRIBUTE, this.themeResolver); request.setAttribute (THEME_SOURCE_ATTRIBUTE, getThemeSource ()); FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate (request, response); if (inputFlashMap! = null) {request.setAttribute (INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap (inputFlashMap)) } request.setAttribute (OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap ()); request.setAttribute (FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); try {/ / look directly at this method doDispatch (request, response);} finally {if (! WebAsyncUtils.getAsyncManager (request). IsConcurrentHandlingStarted ()) {/ / Restore the original attribute snapshot, in case of an include. If (attributesSnapshot! = null) {restoreAttributesAfterInclude (request, attributesSnapshot);} protected void doDispatch (HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager (request); try {ModelAndView mv = null; Exception dispatchException = null; try {processedRequest = checkMultipart (request) MultipartRequestParsed = (processedRequest! = request) / / Determine handler for the current request. MappedHandler = getHandler (processedRequest); if (mappedHandler = = null | | mappedHandler.getHandler () = = null) {noHandlerFound (processedRequest, response); return;} / / Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter (mappedHandler.getHandler ()); / / Process last-modified header, if supported by the handler. String method = request.getMethod (); boolean isGet = "GET" .equals (method); if (isGet | | "HEAD" .equals (method)) {long lastModified = ha.getLastModified (request, mappedHandler.getHandler ()); if (logger.isDebugEnabled ()) {logger.debug ("Last-Modified value for [" + getRequestUri (request) + "] is:" + lastModified) } if (new ServletWebRequest (request, response) .checkNotModified (lastModified) & & isGet) {return;}} if (! mappedHandler.applyPreHandle (processedRequest, response)) {return;} / / Actually invoke the handler. Mv = ha.handle (processedRequest, response, mappedHandler.getHandler ()); if (asyncManager.isConcurrentHandlingStarted ()) {return;} applyDefaultViewName (processedRequest, mv); mappedHandler.applyPostHandle (processedRequest, response, mv);} catch (Exception ex) {dispatchException = ex } catch (Throwable err) {/ / As of 4.3, we're processing Errors thrown from handler methods as well, / / making them available for @ ExceptionHandler methods and other scenarios. DispatchException = new NestedServletException ("Handler dispatch failed", err);} / / handling result (including exception handling) processDispatchResult (processedRequest, response, mappedHandler, mv, dispatchException);} catch (Exception ex) {triggerAfterCompletion (processedRequest, response, mappedHandler, ex);} catch (Throwable err) {triggerAfterCompletion (processedRequest, response, mappedHandler, new NestedServletException ("Handler processing failed", err)) } finally {if (asyncManager.isConcurrentHandlingStarted ()) {/ / Instead of postHandle and afterCompletion if (mappedHandler! = null) {mappedHandler.applyAfterConcurrentHandlingStarted (processedRequest, response);}} else {/ / Clean up any resources used by a multipart request. If (multipartRequestParsed) {cleanupMultipart (processedRequest);}
Enter the place of exception handling
When you go to the resolveException method, there are three default parsers. The specific instantiation of ExceptionHandlerExceptionResolver,ResponseStatusExceptionResolver,DefaultHandlerExceptionResolver; is in the WebMvcConfigurationSupport#addDefaultHandlerExceptionResolvers method.
Protected final void addDefaultHandlerExceptionResolvers (List exceptionResolvers) {ExceptionHandlerExceptionResolver exceptionHandlerResolver = createExceptionHandlerExceptionResolver (); exceptionHandlerResolver.setContentNegotiationManager (mvcContentNegotiationManager ()); exceptionHandlerResolver.setMessageConverters (getMessageConverters ()); exceptionHandlerResolver.setCustomArgumentResolvers (getArgumentResolvers ()); exceptionHandlerResolver.setCustomReturnValueHandlers (getReturnValueHandlers ()); if (jackson2Present) {exceptionHandlerResolver.setResponseBodyAdvice (Collections. HandlerType) {for (Method method: MethodIntrospector.selectMethods (handlerType, EXCEPTION_HANDLER_METHODS)) {for (Class messageConverter: this.messageConverters) {if (messageConverter instanceof GenericHttpMessageConverter) {if (GenericHttpMessageConverter) messageConverter). CanWrite (declaredType, valueType, selectedMediaType)) {outputValue = (T) getAdvice (). BeforeBodyWrite (outputValue, returnType, selectedMediaType) (Class >) messageConverter.getClass (), inputMessage, outputMessage) If (outputValue! = null) {addContentDispositionHeader (inputMessage, outputMessage); ((GenericHttpMessageConverter) messageConverter) .write (outputValue, declaredType, selectedMediaType, outputMessage) If (logger.isDebugEnabled ()) {logger.debug ("Written [" + outputValue + "] as\"+ selectedMediaType +"\ "using [" + messageConverter + "]");} return } else if (messageConverter.canWrite (valueType, selectedMediaType)) {outputValue = (T) getAdvice (). BeforeBodyWrite (outputValue, returnType, selectedMediaType, (Class >) messageConverter.getClass (), inputMessage, outputMessage) If (outputValue! = null) {addContentDispositionHeader (inputMessage, outputMessage); ((HttpMessageConverter) messageConverter) .write (outputValue, selectedMediaType, outputMessage) If (logger.isDebugEnabled ()) {logger.debug ("Written [" + outputValue + "] as\"+ selectedMediaType +"\ "using [" + messageConverter + "]");} return }} if (outputValue! = null) {throw new HttpMediaTypeNotAcceptableException (this.allSupportedMediaTypes);}}
Before body writer, ResponseBodyAdvice match is called to do a layer of processing, that is to say,
@ RestControllerAdvicepublic class GlobalExceptionHandler extends ResponseEntityExceptionHandler implements ResponseBodyAdvice {} the above is how to handle exceptions using @ RestControllerAdvice. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.