記一次SpringMVC全局異常處理未捕獲到異常BUG定位

前因

博主在寫項目的時候,自定義了一個異常類,繼承自運行時異常類:

/**
 * 禁止訪問異常類
 * @author alageek
 */
public class AccessForbiddenException extends RuntimeException {

    private static final long serialVersionUID = 7526324512252691698L;

    public AccessForbiddenException(){
        super();
    }

    public AccessForbiddenException(String message, Throwable cause, Boolean enableSuppression, Boolean writableStackTrace){
        super(message, cause, enableSuppression, writableStackTrace);
    }

    public AccessForbiddenException(String message, Throwable cause){
        super(message, cause);
    }

    public AccessForbiddenException(Throwable cause){
        super(cause);
    }

    public AccessForbiddenException(String message){
        super(message);
    }

}

而後在攔截器中,將其拋出:

/**
 * 登錄攔截
 * @author alageek
 */
public class LoginInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        Admin admin = (Admin) session.getAttribute(CrowdConstant.ATTR_NAME_LOGIN_ADMIN);
        if(admin == null){
            throw new AccessForbiddenException(CrowdConstant.MESSAGE_ACCESS_FORBIDDEN);
        }
        return true;
    }
}

同時又在SpringMVC中設置了全局異常處理:

/**
 * 異常處理機制
 * @author alageek
 * 註解ControllerAdvice表示當前類是基於註解的異常處理器類
 */
@ControllerAdvice
public class CrowdExceptionResolver {

    /**
     * 禁止訪問異常處理
     * 註解ExceptionHandler將異常類與方法關聯
     * @param exception 異常對象
     * @param request   請求對象
     * @param response  響應對象
     * @return 若請求爲Ajax請求,則返回json類型的錯誤信息,否則返回錯誤頁面
     * @throws IOException ResultEntity對象轉json異常
     */
    @ExceptionHandler(value = AccessForbiddenException.class)
    public ModelAndView resolveAccessForbiddenException(
            AccessForbiddenException exception,
            HttpServletRequest request,
            HttpServletResponse response) throws IOException {
        String viewName = "admin-login";
        return commonResolve(exception, request, response, viewName);
    }

    private ModelAndView commonResolve(
            Exception exception,
            HttpServletRequest request,
            HttpServletResponse response,
            String viewName) throws IOException {
        if(CrowdUtil.judgeRequestType(request)){
            // Ajax請求
            response.getWriter().write(new Gson().toJson(ResultEntity.failed(exception.getMessage())));
            return null;
        }
        // 普通請求
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION, exception);
        modelAndView.setViewName(viewName);
        return modelAndView;
    }

}

最終的啓動項目後,發現在攔截器拋出AccessForbiddenException異常時,全局異常處理並未捕獲到異常。

BUG定位

經過百度SpringMVC全局異常處理的三種方式後,恍然大悟,按上面博主所寫的這種方式捕獲全局異常,只能捕獲到Controller裏拋出的異常,想要捕獲攔截器裏這個異常,需要在SpringMVC的配置文件中進行配置。

BUG修復

在SpringMVC配置文件中配置異常機制,如下:

<!-- 配置基於XML的異常機制 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" id="simpleMappingExceptionResolver">
        <!-- 配置異常類型和具體視圖頁面的對應關係 -->
        <property name="exceptionMappings">
            <props>
                <prop key="com.alageek.crowd.exception.AccessForbiddenException">admin-login</prop>
            </props>
        </property>
    </bean>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章