1. 程式人生 > >springMVC 統一異常處理的一種方式

springMVC 統一異常處理的一種方式

後端發生異常的時候,如果不處理,返回前段的會是printStackTrace()打出來的結果,會洩露我們伺服器程式碼資訊,可能會被利用攻擊,所以需要一個統一的異常處理機制。

解決方案 @ExceptionHandler 和@ControllerAdvice 註解,在一個檔案中處理所有異常型別,並介面返回固定格式。

@ControllerAdvice
 public class WebExceptionHandle {
@ExceptionHandler(DataAccessException.class)
@ResponseBody
ResultDTO handleSqlException(Exception e){
// 處理sql異常
    return  ResultDTO.faileResult(null,"sql failed");
}

@ExceptionHandler()
@ResponseBody
ResultDTO handleException(Exception e){
//預設異常處理
    return  ResultDTO.faileResult(null,"sql failed");
}

}

博文:https://blog.csdn.net/liujia120103/article/details/75126124 給出了這2個註解的解釋,但沒有說明具體如何能捕獲異常並處理的,通過除錯觀察呼叫堆疊,發現是通過springMVC 的handlerExceptionResolvers.resolveException後呼叫的。這個處理過程應該是如下:

  • spring在啟動過程通過註解@ExceptionHandler將 方法封裝成bean並注入到handlerExceptionResolvers的集合中
  • 當controller執行完成後,執行processDispatchResult對結果進行處理
  • 呼叫processHandlerException 方法,遍歷handlerExceptionResolvers,執行handlerExceptionResolver.resolveException方法。

springMVC過程

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

    try {
        try {
            ModelAndView mv = null;
            Object dispatchException = null;
            try {
                processedRequest = this.checkMultipart(request);
                multipartRequestParsed = processedRequest != request;
                mappedHandler = this.getHandler(processedRequest);
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    this.noHandlerFound(processedRequest, response);
                    return;
                }
                HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                 ......
                  
             //  web的前置處理器
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }
            // 執行controller的對應方法
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }

                this.applyDefaultViewName(processedRequest, mv);
                // web的後置處理器
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            } catch (Exception var20) {
                dispatchException = var20;
            } catch (Throwable var21) {
                dispatchException = new NestedServletException("Handler dispatch failed", var21);
            }
          //處理controller的執行結果
            this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
        } catch (Exception var22) {
            this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
        } catch (Throwable var23) {
            this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
        }

    } finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            }
        } else if (multipartRequestParsed) {
            this.cleanupMultipart(processedRequest);
        }

    }
}

processDispatchResult 中執行processHandlerException方法

protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    ModelAndView exMv = null;
    Iterator var6 = this.handlerExceptionResolvers.iterator();
    while(var6.hasNext()) {
        HandlerExceptionResolver handlerExceptionResolver = (HandlerExceptionResolver)var6.next();
        exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
        if (exMv != null) {
            break;
        }
    }   
 if (exMv != null) {
        if (exMv.isEmpty()) {
            request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
            return null;
        } else {
            if (!exMv.hasView()) {
                exMv.setViewName(this.getDefaultViewName(request));
            }

            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex);
            }

            WebUtils.exposeErrorRequestAttributes(request, ex, this.getServletName());
            return exMv;
        }
    } else {
        throw ex;
    }
}