1. 程式人生 > >Spring MVC之異常處理

Spring MVC之異常處理

一、概況

正常情況下,請求到達服務端,服務端處理完成後返回資料結果(RESTful前後端分離)或返回頁面(傳統jsp web工程),這樣一次完整的流程就走完了。

異常情況下,如404/405/400/500/302/都是由容器或自定義頁面返回給使用者。在現在開發中(RESTful 介面),我們需要一個穩定的報文格式返回,包括異常請求情況,這就需要程式感知並處理所有的異常情況。SpringMVC就提供這個機制,統一處理Controller異常;這樣對介面的使用者就非常友好,且提示資訊明確,減少溝通成本(HEATOS)

異常處理之前返回的結果:


異常處理之後:


二、實現方式

註解@ExceptionHandler,用於異常處理,因所有的請求都需要進行異常處理,所以我們寫一個抽象類讓所有Controller繼承;

public abstract class BaseController {
    protected final Logger logger = LoggerFactory.getLogger(BaseController.class);

    /** 異常處理 */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ModelMap> exceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {
        ModelMap modelMap = new ModelMap();
        ResponseEntity<ModelMap> result = null;
        if (ex instanceof HttpRequestMethodNotSupportedException) {
            result = setModelMap(modelMap, HttpStatus.METHOD_NOT_ALLOWED);
        } else if (ex instanceof MissingServletRequestParameterException) {
            result = setModelMap(modelMap, HttpStatus.BAD_REQUEST);
        } else if (ex instanceof IllegalArgumentException) {
            result = setModelMap(modelMap, HttpStatus.BAD_REQUEST);
        } else {
            result = setModelMap(modelMap, HttpStatus.INTERNAL_SERVER_ERROR);
            logger.error("INTERNAL_SERVER_ERROR ", ex);
        }
        String message = ex.getMessage();
        if (!StringUtils.isBlank(message)) {
            modelMap.put("msg", message);
        }
        if (logger.isDebugEnabled()) {
            logger.debug(ex.getMessage(), ex);
        }
        return result;
    }
}
在ExceptionHandler上加上 @ResponseBody 註解,這樣異常程式碼提示就可以直接返回到使用者端了

上面的程式碼有一個問題:就是405的異常(HtttpRequestMethodNotSupportException)攔截不到,沒有進入ExeptionHandler的處理邏輯中;原因:因為GET 沒有相應的RequestMapping請求對映找不到相應的controller,就無法觸發異常攔截;

解決:@ControllerAdvice註解,把使用@ExceptionHandler、@InitBinder、@ModelAttribute註解的方法應用到所有的 @RequestMapping註解的方法;