17.Struts2__声明式异常处理

来源:互联网 发布:阿里数据库在哪里 编辑:程序博客网 时间:2024/06/11 07:25

一.概念

(1)异常处理:exception-mapping元素

.exception-mapping元素:配置当前action的声明式异常处理

.exception-mapping元素中有2个属性

-exception:指定需要捕获的异常类型

-result:指定一个响应结果,该结果将在捕获到指定异常时被执行,既可以来自当前action的声明,也可以来自global-results声明。

       如:<exception-mapping result=" exception=""></exception-mapping>  


(2)可以通过global-exception-mapping元素为应用程序提供一个全局性的异常捕获映射,但在global-exception-mappings元素下声明的任何exception-mapping元素只能引用在global-results元素下声明的某个result元素。

例:.每个action是不是都要配置异常处理呢?当然不用,下面来看global-exception-mappings、global-results 。
在struts.xml中配置如下:

        <global-results>            <result name="details">/WEB-INF/page/Input.jsp</result>        </global-results>        <global-exception-mappings>            <exception-mapping result="details" exception="java.lang.ArithmeticException"></exception-mapping>        </global-exception-mappings>


(3)声明式异常处理机制由ExceptionMappingInterceptor拦截器负责处理,当某个exception-mapping元素声明的异常被捕获到时,ExcepionMappingInterceptor拦截器就会向ValueStack中添加两个对象:

-exception:表示被捕获异常的Exception对象

-exceptionStack:包含着被捕获异常的栈

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


二.实例:

在save方法中添加 int i=10/0;

   public String save() {          System.out.println("save " + this);          int i=1/0;        return "details";  


运行显示:

在struts.xml中添加异常处理:exception-mapping元素

        </action>              <action name="product-save" class="actionbao.Product" method="save">        <exception-mapping result="details" exception="java.lang.ArithmeticException"></exception-mapping>                <result name="details">/WEB-INF/pages/details.jsp</result>            </action> 


此时,页面将直接跳转到details.jsp:


在details.jsp加入标签显示exception信息:



运行后的显示效果:



点击 Debug :


可见,对象栈的 栈顶 是异常对象,所以在上面页面没用下标就直接读取属性。ExceptionHolder有两个属性,一个是exceptionStack,一个是exception。


2.我们来看,Struts2是如何做到异常映射处理的。
在struts_default.xml中查看:
我们的package的父类struts-default中引用的默认拦截器

<default-interceptor-ref name="defaultStack"/>


ctrl+shift+t 查看 ExceptionMappingInterceptor 源码

public class ExceptionMappingInterceptor extends AbstractInterceptor {    //省略......    @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;    }    //省略......    /**     * 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);    }}
可见,当catch到异常之后publishException(invocation, new ExceptionHolder(e))把异常压入了栈中。