Struts2自定義攔截器處理全局異常


  今天在整理之前的項目的時候想着有的action層沒有做異常處理,於是想着自定義攔截器處理一下未攔截的異常。

 

代碼:

package cn.xm.exam.action.safeHat;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionSupport;

@Controller
@Scope("prototype")
public class SafeHatAction extends ActionSupport {
    private static final Logger log = LoggerFactory.getLogger(SafeHatAction.class);
    private Map<String, Object> response;

    public SafeHatAction() {
        log.info("SafeHatAction init.........");
    }

    public String test1() {
        response = new HashMap();
        response.put("ttt", "tttttt");
        return SUCCESS;
    }
    
    public String test2() {
        response = new HashMap();
        response.put("ttt", "tttttt");
        int i = 1/0;
        return SUCCESS;
    }

    public Map<String, Object> getResponse() {
        return response;
    }

    public void setResponse(Map<String, Object> response) {
        this.response = response;
    }

}

 

 

1.異常在Action層未做處理的情況:

 

由於在web.xml中定義了500錯誤的頁面,因此跳轉到500頁面,如下:

    <!-- 500頁面 -->
    <error-page>
        <error-code>500</error-code>
        <location>/500.jsp</location>
    </error-page>

 

  可是上面終究不夠友好。

 

2.自定義攔截器處理全局異常

(1)自定義攔截器

package cn.xm.exam.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class ExceptionInterception implements Interceptor {
    private static final Logger log = LoggerFactory.getLogger(ExceptionInterception.class);
    /**
     * 
     */
    private static final long serialVersionUID = 2268867259828199826L;

    @Override
    public void destroy() {

    }

    @Override
    public void init() {

    }

    @Override
    public String intercept(ActionInvocation arg0) throws Exception {
        log.info("enter ExceptionInterception intercept ... ");
        String result = "";
        try {
            result = arg0.invoke();
            log.info("result -> {}", result);
        } catch (Throwable e) {
            log.error("未處理的異常在攔截器被攔截,class:{}", arg0.getAction().getClass(), e);
            throw new Exception(e);
        }
        log.debug("exit ExceptionInterception intercept ... ");
        return result;
    }

}

  arg0.invoke();是調用我們的action的方法,其返回值就是action的返回值,相當於放行;捕捉到異常之后進行一個簡單的異常記錄之后再次拋出異常,再次拋出異常是為了跳到500頁面;如果有需要可以自己再寫一個頁面提示錯誤已經被記錄等信息,捕捉到異常之后返回到此頁面。 

 

 

(2)struts.xml中定義攔截器

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
    <constant name="struts.i18n.encoding" value="utf-8"></constant>
    <constant name="devMode" value="true"></constant>
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />
    <!-- 配置攔截的后綴 -->
    <constant name="struts.action.extension" value="action,do" />
    <!-- 與spring整合 -->
    <constant name="struts.objectFactory" value="spring"></constant>

    <package name="interceptPackage" extends="json-default">

        <!-- 攔截器 -->
        <interceptors>
            <!-- 定義剛才的攔截器 -->
            <interceptor name="exceptionInterceptor"
                class="cn.xm.exam.interceptor.ExceptionInterception"></interceptor>
            <!-- 定義攔截器棧 -->
            <interceptor-stack name="myStack">
                <!-- 攔截器棧里面可以引用另外一個攔截器,也可以引用另外一個攔截器棧 -->
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="exceptionInterceptor"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!-- 這句是設置所有Action自動調用的攔截器堆棧 -->
        <default-interceptor-ref name="myStack" />
    </package>

    <!-- 2018-11-11引入的二開action -->
    <include file="struts/safeHat.xml"></include>

</struts>

 

 

自定義的package繼承上面的package(package具有多重繼承的特性,safeHalt會繼承其所有父類),例如:safeHat.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
    <package name="safeHalt" namespace="/" extends="interceptPackage">
        <!-- 全局結果集,將response轉換為json傳到前台 -->
        <global-results>
            <result name="success" type="json">
                <param name="root">response</param>
            </result>
        </global-results>

        <action name="safeHat_*" class="safeHatAction" method="{1}"></action>
    </package>
</struts>

 

 

 (3)繼續訪問上面的錯誤action進行測試:

查看記錄的錯誤日志:

2018-11-01 23:09:30 [cn.xm.exam.interceptor.ExceptionInterception]-[ERROR] 未處理的異常在攔截器被攔截,class:class cn.xm.exam.action.safeHat.SafeHatAction
java.lang.ArithmeticException: / by zero
    at cn.xm.exam.action.safeHat.SafeHatAction.test2(SafeHatAction.java:32)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:871)
    at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1294)
    at ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
    at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethodWithDebugInfo(XWorkMethodAccessor.java:117)
    at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethod(XWorkMethodAccessor.java:108)
    at ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1370)
    at ognl.ASTMethod.getValueBody(ASTMethod.java:91)
  ........

 

 

至此實現了簡單的全局異常處理。 

 

3.補充:根據ajax請求與普通請求回傳不同數據 (捕捉到異常之后進行提示)

3.1首先明白ajax請求與普通請求的不同:

AJAX請求頭會多一個x-requested-with參數,值為XMLHttpRequest

String requestType = request.getHeader("X-Requested-With");

 

 

3.2修改上面的攔截器

package cn.xm.exam.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class ExceptionInterception implements Interceptor {
    private static final Logger log = LoggerFactory.getLogger(ExceptionInterception.class);
    /**
     * 
     */
    private static final long serialVersionUID = 2268867259828199826L;

    @Override
    public void destroy() {

    }

    @Override
    public void init() {

    }

    @Override
    public String intercept(ActionInvocation arg0) throws Exception {
        log.info("enter ExceptionInterception intercept ... ");
        String result = "";
        try {
            result = arg0.invoke();
            log.info("result -> {}", result);
        } catch (Throwable e) {
            log.error("未處理的異常在攔截器被攔截,class:{}", arg0.getAction().getClass(), e);
            return "interceptorError";
        }
        log.debug("exit ExceptionInterception intercept ... ");
        return result;
    }

}

 

 

struts全局結果集:

    <package name="interceptPackage" extends="json-default">
        <!-- 攔截器 -->
        <interceptors>
            <!-- 定義剛才的攔截器 -->
            <interceptor name="exceptionInterceptor"
                class="cn.xm.exam.interceptor.ExceptionInterception"></interceptor>
            <!-- 定義攔截器棧 -->
            <interceptor-stack name="myStack">
                <!-- 攔截器棧里面可以引用另外一個攔截器,也可以引用另外一個攔截器棧 -->
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="exceptionInterceptor"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!-- 這句是設置所有Action自動調用的攔截器堆棧 -->
        <default-interceptor-ref name="myStack" />

        <!-- 攔截器攔截的全局異常 -->
        <global-results>
            <result name="interceptorError">/interceptorError.jsp</result>
        </global-results>
    </package>

 

 

錯誤JSP:interceptorError.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
    if (request.getHeader("X-Requested-With") != null
            && "XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
        response.setContentType("application/javascript;charset=utf-8");
        out.write("錯誤提醒:系統發生錯誤,系統已經記錄錯誤日志");
    } else {
        response.setContentType("text/html;charset=\"utf-8\"");
        out.write(
                "<html><head><meta charset=\"utf-8\" /><title>錯誤提醒</title></head><body><br /><span style=\"font-weight: bold;font-size: 20px;margin: 20px;\">系統發生錯誤!日志已經記錄!</span>    <br /></body></html>");
    }
%>

 

 

測試:

(1)普通頁面訪問:

 

(2)ajax請求測試:

js代碼:

<script>
+function(){
    $.post("/Exam/safeHat_test2.do",function(response){
        alert(response);
    },"text");
}();
</script>

 

結果:

 

 

 

 

 

 

 

 攔截器的使用參考我另一篇博客:https://www.cnblogs.com/qlqwjy/p/7190784.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM