zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Paxos算法简单陈述
    二段式提交和三段式提交
    Guava包学习--Hash
    JedisPool无法获得资源问题
    有料面试题之--Object里面的方法
    Spring常用jar包的功能
    线上日志分析与其他一些脚本
    Flutter-漸變色按鈕
    Flutter-自定義圖標或者選擇框
    Flutter-自定義圖片圖標
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/9893379.html
Copyright © 2011-2022 走看看