zoukankan      html  css  js  c++  java
  • Struts(十二):异常处理:exception-mapping元素

    • 配置当前action的声明异常处理

    1、exception-mapping元素中有2个属性
      exception:指定需要捕获的异常类型
      result:指定一个响应结果,该结果将在捕获到异常时被执行。即可以来自当前action的声明,也可以来自global-results声明。

    2、可以在视图上通过<s:property>标签显示异常消息。

     基于上几个章节的例子开始往下写,修改save函数:

        public String save(){     
            System.out.println("save");        
            
            int val=10/0;
            
            return "success";
        }

    此时访问http://localhost:8080/Struts_01/,输入信息点击“提交”按钮跳转到details.jsp,当访问save函数时,就跑出了异常信息:

    此时,我们发现异常信息并没有被合理的处理掉,比如出错了,我们让页面跳转到error.jsp该多好,其实struts2中通过配置struts.xml是可以实现的。

    修改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.action.extension" value="action" /> 
        <constant name="struts.enable.DynamicMethodInvocation" value="true" />
        -->
        <constant name="struts.ognl.allowStaticMethodAccess" value="true" />
        <constant name="struts.devMode" value="false" />
    
        <package name="default" namespace="/" extends="struts-default">
            <action name="product-save" class="com.dx.struts2.valuestack.Product" method="save">
                <exception-mapping result="error" exception="java.lang.ArithmeticException"></exception-mapping>
                <result name="error">/error.jsp</result>    
                <result>/details.jsp</result>
            </action>
        </package>
        <!-- Add packages here -->
    </struts>
     

    添加在WebContent下添加error.jsp:

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>Insert title here</title>
    </head>
    <body>
      error
    </body>
    </html>

    重启服务,重新访问页面,并提交参数,发现页面自动跳转到了error.jsp:

    如果光跳转过来不太完美,如果可以显示错误信息不是更好,实际上通过EL或者s:property标签是可以实现的,修改error.jsp:

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib prefix="s" uri="/struts-tags"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        error<br/>    
        <s:debug/>
        <s:property value="exception" /><br/>
        ${exception}<br/>
        ${exception.message}<br/>
        <s:property value="exception.message"/><br/>
        <s:property value="exceptionStack"/><br/>
        ${exceptionStack}
        
    </body>
    </html>

    显示信息:
    s:debug第一个元素类型为:com.opensymphony.xwork2.interceptor.ExceptionHolder

    元素包含两个属性:exception和exceptionStack

    • 可以通过global-exception-mappings元素为应用程序提供一个全局性的异常捕获映射。

      1、但在global-exception-mappings元素下声明任何exception-mapping元素只能引用在global-results元素下声明的某个result元素。

     只需要修改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.action.extension" value="action" /> 
        <constant name="struts.enable.DynamicMethodInvocation" value="true" />
        -->
        <constant name="struts.ognl.allowStaticMethodAccess" value="true" />
        <constant name="struts.devMode" value="false" />
    
        <package name="default" namespace="/" extends="struts-default">
            <global-results>
                <result name="error">/error.jsp</result>
            </global-results>
            <global-exception-mappings>
                <exception-mapping result="error" exception="java.lang.ArithmeticException"></exception-mapping>
            </global-exception-mappings>
            <action name="product-save" class="com.dx.struts2.valuestack.Product" method="save">
                <!-- 
                <exception-mapping result="error" exception="java.lang.ArithmeticException"></exception-mapping>
                <result name="error">/error.jsp</result>    
                -->
                <result>/details.jsp</result>
            </action>
        </package>
        <!-- Add packages here -->
    </struts>

    重新访问即可,其他内容不影响显示。

    • 声明式异常处理机制由ExceptionMappingInterceptor拦截器负责处理。

      1、当某个exception-mapping元素声明的异常被捕获到是,ExceptionMappingInterceptor拦截器就会向ValueStack中添加两个对象:

        exception:表示被捕获异常的Exception对象
        exceptionStack:包含着被捕获异常的栈

      2、什么地方注册这个拦截器?

    struts-core.jar 下的struts-default.xml中<default-interceptor-ref name="defaultStack"/>

    <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>

     com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor怎么向ValueStack中写入异常信息?

    package com.opensymphony.xwork2.interceptor;
    
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig;
    import com.opensymphony.xwork2.util.logging.Logger;
    import com.opensymphony.xwork2.util.logging.LoggerFactory;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * @author Matthew E. Porter (matthew dot porter at metissian dot com) 
     * @author Claus Ibsen
     */
    public class ExceptionMappingInterceptor extends AbstractInterceptor {
        
        protected static final Logger LOG = LoggerFactory.getLogger(ExceptionMappingInterceptor.class);
    
        protected Logger categoryLogger;
        protected boolean logEnabled = false;
        protected String logCategory;
        protected String logLevel;
        
    
        public boolean isLogEnabled() {
            return logEnabled;
        }
    
        public void setLogEnabled(boolean logEnabled) {
            this.logEnabled = logEnabled;
        }
    
        public String getLogCategory() {
            return logCategory;
        }
    
        public void setLogCategory(String logCatgory) {
            this.logCategory = logCatgory;
        }
    
        public String getLogLevel() {
            return logLevel;
        }
    
        public void setLogLevel(String logLevel) {
            this.logLevel = logLevel;
        }
    
        @Override
        public String intercept(ActionInvocation invocation) throws Exception {
            String result;
    
            try {
                result = invocation.invoke();
            } catch (Exception e) {
                if (isLogEnabled()) {
                    handleLogging(e);
                }
                List<ExceptionMappingConfig> exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings();
                ExceptionMappingConfig mappingConfig = this.findMappingFromExceptions(exceptionMappings, e);
                if (mappingConfig != null && mappingConfig.getResult()!=null) {
                    Map parameterMap = mappingConfig.getParams();
                    // create a mutable HashMap since some interceptors will remove parameters, and parameterMap is immutable
                    invocation.getInvocationContext().setParameters(new HashMap<String, Object>(parameterMap));
                    result = mappingConfig.getResult();
                    publishException(invocation, new ExceptionHolder(e));
                } else {
                    throw e;
                }
            }
    
            return result;
        }
    
        /**
         * Handles the logging of the exception.
         * 
         * @param e  the exception to log.
         */
        protected void handleLogging(Exception e) {
            if (logCategory != null) {
                if (categoryLogger == null) {
                    // init category logger
                    categoryLogger = LoggerFactory.getLogger(logCategory);
                }
                doLog(categoryLogger, e);
            } else {
                doLog(LOG, e);
            }
        }
        
        /**
         * Performs the actual logging.
         * 
         * @param logger  the provided logger to use.
         * @param e  the exception to log.
         */
        protected void doLog(Logger logger, Exception e) {
            if (logLevel == null) {
                logger.debug(e.getMessage(), e);
                return;
            }
            
            if ("trace".equalsIgnoreCase(logLevel)) {
                logger.trace(e.getMessage(), e);
            } else if ("debug".equalsIgnoreCase(logLevel)) {
                logger.debug(e.getMessage(), e);
            } else if ("info".equalsIgnoreCase(logLevel)) {
                logger.info(e.getMessage(), e);
            } else if ("warn".equalsIgnoreCase(logLevel)) {
                logger.warn(e.getMessage(), e);
            } else if ("error".equalsIgnoreCase(logLevel)) {
                logger.error(e.getMessage(), e);
            } else if ("fatal".equalsIgnoreCase(logLevel)) {
                logger.fatal(e.getMessage(), e);
            } else {
                throw new IllegalArgumentException("LogLevel [" + logLevel + "] is not supported");
            }
        }
    
        /**
         * @deprecated since 2.3.15 please use #findMappingFromExceptions directly instead
         */
        protected String findResultFromExceptions(List<ExceptionMappingConfig> exceptionMappings, Throwable t) {
            ExceptionMappingConfig result = findMappingFromExceptions(exceptionMappings, t);
            return result==null?null:result.getResult();
        }
    
        /**
         * Try to find appropriate {@link ExceptionMappingConfig} based on provided Throwable
         *
         * @param exceptionMappings list of defined exception mappings
         * @param t caught exception
         * @return appropriate mapping or null
         */
        protected ExceptionMappingConfig findMappingFromExceptions(List<ExceptionMappingConfig> exceptionMappings, Throwable t) {
            ExceptionMappingConfig config = null;
            // Check for specific exception mappings.
            if (exceptionMappings != null) {
                int deepest = Integer.MAX_VALUE;
                for (Object exceptionMapping : exceptionMappings) {
                    ExceptionMappingConfig exceptionMappingConfig = (ExceptionMappingConfig) exceptionMapping;
                    int depth = getDepth(exceptionMappingConfig.getExceptionClassName(), t);
                    if (depth >= 0 && depth < deepest) {
                        deepest = depth;
                        config = exceptionMappingConfig;
                    }
                }
            }
            return config;
        }
    
        /**
         * Return the depth to the superclass matching. 0 means ex matches exactly. Returns -1 if there's no match.
         * Otherwise, returns depth. Lowest depth wins.
         *
         * @param exceptionMapping  the mapping classname
         * @param t  the cause
         * @return the depth, if not found -1 is returned.
         */
        public int getDepth(String exceptionMapping, Throwable t) {
            return getDepth(exceptionMapping, t.getClass(), 0);
        }
    
        private int getDepth(String exceptionMapping, Class exceptionClass, int depth) {
            if (exceptionClass.getName().contains(exceptionMapping)) {
                // Found it!
                return depth;
            }
            // If we've gone as far as we can go and haven't found it...
            if (exceptionClass.equals(Throwable.class)) {
                return -1;
            }
            return getDepth(exceptionMapping, exceptionClass.getSuperclass(), depth + 1);
        }
    
        /**
         * Default implementation to handle ExceptionHolder publishing. Pushes given ExceptionHolder on the stack.
         * Subclasses may override this to customize publishing.
         *
         * @param invocation The invocation to publish Exception for.
         * @param exceptionHolder The exceptionHolder wrapping the Exception to publish.
         */
        protected void publishException(ActionInvocation invocation, ExceptionHolder exceptionHolder) {
            invocation.getStack().push(exceptionHolder);
        }
    
    }
  • 相关阅读:
    JAVA课程设计——飞机大战(团队)
    面向对象设计大作业
    OO之接口-DAO模式代码阅读及应用
    有理数类设计
    图总结
    树、二叉树、查找算法总结
    二叉排序树
    数据结构小结
    C语言文件
    小程序云开发:联表查询去重及排序的不严谨笨办法
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/6539708.html
Copyright © 2011-2022 走看看