1. 程式人生 > >javaweb異常提示資訊統一處理(使用springmvc,附原始碼)

javaweb異常提示資訊統一處理(使用springmvc,附原始碼)

一、前言

後臺出現異常如何友好而又高效地回顯到前端呢?直接將一堆的錯誤資訊拋給使用者介面,顯然不合適。

先不考慮程式碼實現,我們希望是這樣的:

(1)如果是頁面跳轉的請求,出現異常了,我們希望跳轉到一個異常顯示頁面,如下:

這裡寫圖片描述

當然,這裡的介面不夠美觀,但是理論是這樣的。

(2)如果是ajax請求,那麼我們,希望後臺將合理的錯誤顯示返回到ajax的回撥函式裡面,如下:

$.ajax({ 
    type: "post", 
    url: "<%=request.getContextPath()%>" + "/businessException.json", 
    data: {}, 
    dataType: "json"
, contentType : "application/json", success: function(data) { if(data.success == false){ alert(data.errorMsg); }else{ alert("請求成功無異常"); } }, error: function(data) { alert("呼叫失敗...."); } });

將回調函式的data.errorMsg打印出來:

這裡寫圖片描述

下面,我們根據上面的思路我們來看看程式碼的實現。因此本文例項包含了異常自定義分裝,為了無障礙閱讀下文,請猿友移步先看完博主的另外一篇文章:

Java異常封裝(自己定義錯誤碼和描述,附原始碼)

二、例項詳解

本例項使用的環境 eclipse+maven,其中maven只是為了方便引入jar包。
使用的技術:springmvc

在Spring MVC中,所有用於處理在請求對映和請求處理過程中丟擲的異常的類,都要實現HandlerExceptionResolver介面。HandlerExceptionResolver介面有一個方法resolveException,當controller層出現異常之後就會進入到這個方法resolveException。

下面我們直接實現HandlerExceptionResolver介面,程式碼如下:

package com.luo.exceptionresolver;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.druid.support.json.JSONUtils;
import com.luo.exception.BusinessException;
import org.springframework.web.servlet.HandlerExceptionResolver;

public class MySimpleMappingExceptionResolver implements
        HandlerExceptionResolver {

    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object object, Exception exception) {
        // 判斷是否ajax請求
        if (!(request.getHeader("accept").indexOf("application/json") > -1 || (request
                .getHeader("X-Requested-With") != null && request.getHeader(
                "X-Requested-With").indexOf("XMLHttpRequest") > -1))) {
            // 如果不是ajax,JSP格式返回
            // 為安全起見,只有業務異常我們對前端可見,否則否則統一歸為系統異常
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("success", false);
            if (exception instanceof BusinessException) {
                map.put("errorMsg", exception.getMessage());
            } else {
                map.put("errorMsg", "系統異常!");
            }
            //這裡需要手動將異常打印出來,由於沒有配置log,實際生產環境應該列印到log裡面
            exception.printStackTrace();
            //對於非ajax請求,我們都統一跳轉到error.jsp頁面
            return new ModelAndView("/error", map);
        } else {
            // 如果是ajax請求,JSON格式返回
            try {
                response.setContentType("application/json;charset=UTF-8");
                PrintWriter writer = response.getWriter();
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("success", false);
                // 為安全起見,只有業務異常我們對前端可見,否則統一歸為系統異常
                if (exception instanceof BusinessException) {
                    map.put("errorMsg", exception.getMessage());
                } else {
                    map.put("errorMsg", "系統異常!");
                }
                writer.write(JSONUtils.toJSONString(map));
                writer.flush();
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

上面的程式碼,歸結為以下幾點:
(1)判斷如果不是ajax請求,那麼統一跳轉到error.jsp頁面,否則返回json資料。
(2)如果是業務異常,我們直接列印異常資訊,否則,我們統一歸為系統異常,如果不明白這裡的業務異常為何物,請閱讀博主部落格:Java異常封裝(自己定義錯誤碼和描述,附原始碼)

另外,需要在springmvc配置檔案新增如下配置:

<!-- 框架異常處理Handler -->
<bean id="exceptionResolver" class="com.luo.exceptionresolver.MySimpleMappingExceptionResolver"></bean>

下面我們直接看controller程式碼:

package com.luo.controller;

import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.luo.errorcode.LuoErrorCode;
import com.luo.exception.BusinessException;

@Controller
public class UserController {

    @RequestMapping("/index.jhtml")
    public ModelAndView getIndex(HttpServletRequest request) throws Exception {
        ModelAndView mav = new ModelAndView("index");
        return mav;
    }

    @RequestMapping("/exceptionForPageJumps.jhtml")
    public ModelAndView exceptionForPageJumps(HttpServletRequest request) throws Exception {
        throw new BusinessException(LuoErrorCode.NULL_OBJ);
    }

    @RequestMapping(value="/businessException.json", method=RequestMethod.POST)
    @ResponseBody  
    public String businessException(HttpServletRequest request) {
        throw new BusinessException(LuoErrorCode.NULL_OBJ);
    }

    @RequestMapping(value="/otherException.json", method=RequestMethod.POST)
    @ResponseBody  
    public String otherException(HttpServletRequest request) throws Exception {
        throw new Exception();
    }

}

關於controller程式碼沒什麼好解釋的,下面我們直接看結果吧:

這裡寫圖片描述

這裡寫圖片描述

點選其他異常按鈕結果:

這裡寫圖片描述

(3)HandlerExceptionResolver介面並不能處理404錯誤,這種錯誤我們再web.xml裡面新增如下配置:

<!-- 錯誤跳轉頁面 -->
<error-page>
    <!-- 路徑不正確 -->
    <error-code>404</error-code>
    <location>/WEB-INF/view/404.jsp</location>
</error-page>

然後404.jsp程式碼如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<taglib uri="http://java.sun.com /jsp/jstl/core" prefix="c" />
<html>
<head>
<title>錯誤頁面</title>
</head>
<body>
頁面被黑洞吸走了......
</body>
</html>

這裡寫圖片描述

三、本工程原始碼下載