首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring MVC 全局異常處理實戰:SimpleMappingExceptionResolver 進階應用

     編輯:Java 綜合教學

為什麼需要自定義異常解析器?

Spring MVC 默認的 SimpleMappingExceptionResolver 僅支持將異常映射到視圖頁面。實際項目中往往需要區分「普通請求」與「AJAX 請求」:前者跳轉錯誤頁,後者返回 JSON。繼承並重寫 doResolveException 即可實現這一目標。

核心代碼實現

public class GlobalExceptionResolver extends SimpleMappingExceptionResolver {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionResolver.class);

    @Override
    protected ModelAndView doResolveException(HttpServletRequest request,
                                              HttpServletResponse response,
                                              Object handler, Exception ex) {
        String viewName = determineViewName(ex, request);
        if (viewName == null) return null;

        // 允許控制器通過 request.setAttribute("errorPage", "customError") 指定錯誤頁
        String customErrorPage = (String) request.getAttribute("errorPage");
        if (StringUtils.isNotBlank(customErrorPage)) viewName = customErrorPage;

        // 判斷是否為 AJAX 請求
        boolean isAjax = "XMLHttpRequest".equals(request.getHeader("X-Requested-With"))
                || request.getHeader("accept") != null && request.getHeader("accept").contains("application/json");

        if (!isAjax) {
            // 普通請求:返回錯誤視圖
            Integer statusCode = determineStatusCode(request, viewName);
            if (statusCode != null) applyStatusCodeIfPossible(request, response, statusCode);
            return getModelAndView(viewName, ex, request);
        } else {
            // AJAX 請求:返回 JSON
            try {
                Map<String, Object> result = new HashMap<>();
                result.put("success", false);
                result.put("message", ex.getMessage());
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write(JSON.toJSONString(result));
            } catch (IOException e) {
                logger.error("寫入 AJAX 錯誤響應失敗", e);
            }
            return null; // 避免 Spring 再次渲染視圖
        }
    }
}

Spring XML 配置

<bean class="com.example.exception.GlobalExceptionResolver">
    <!-- 默認錯誤頁 -->
    <property name="defaultErrorView" value="error" />
    <!-- 異常對象在視圖中的屬性名 -->
    <property name="exceptionAttribute" value="ex" />
    <!-- 特定異常映射到特定頁面 -->
    <property name="exceptionMappings">
        <props>
            <prop key="java.io.IOException">error/ioError</prop>
            <prop key="java.sql.SQLException">error/sqlError</prop>
        </props>
    </property>
</bean>

控制器中動態指定錯誤頁

@Controller
public class OrderController {
    @PostMapping("/submit")
    public String submit(Order order, HttpServletRequest request) {
        try {
            orderService.process(order);
        } catch (BusinessException e) {
            request.setAttribute("errorPage", "order/fail"); // 覆蓋默認錯誤頁
            throw e; // 拋出讓解析器捕獲
        }
        return "order/success";
    }
}

關鍵點總結

  1. 繼承 SimpleMappingExceptionResolver 而非實現 HandlerExceptionResolver,復用現有映射邏輯。
  2. 通過 X-Requested-With 和 Accept 頭精準識別 AJAX 請求。
  3. 返回 null 表示已自行處理響應,阻止後續視圖渲染。
  4. 保留 exceptionMappings 配置,實現「約定優於配置」與「特例特辦」並存。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved