struts2 18拦截器详解(十七) --- StrutsConversionErrorInterceptor

StrutsConversionErrorInterceptor

   StrutsConversionErrorInterceptor拦截器处于defaultStack第十六的位置,是用于处理转类型转换错误的,该拦截器继承自ConversionErrorInterceptor类其大部分功能逻辑都在ConversionErrorInterceptor中,StrutsConversionErrorInterceptor只是对其中的两个方法进行了覆盖,分别是getOverrideExpr与shouldAddError方法,因为ConversionErrorInterceptor类是xwrok提供的,而struts2认为这两个方法不是那么合理所以进行了覆盖。所以真正执行到StrutsConversionErrorInterceptor调用的是父类ConversionErrorInterceptor的intercept方法,下面是该方法源码:

@Override
public String intercept(ActionInvocation invocation) throws Exception {
	//获取ActionContext对象
    ActionContext invocationContext = invocation.getInvocationContext();
    //获取ActionContext对象中的conversionErrors Map,所以类型转换错误信息都放在该Map中
    Map<String, Object> conversionErrors = invocationContext.getConversionErrors();
    ValueStack stack = invocationContext.getValueStack();//获取值栈

    HashMap<Object, Object> fakie = null;
	//迭代类型转换错误
    for (Map.Entry<String, Object> entry : conversionErrors.entrySet()) {
        String propertyName = entry.getKey();//转换错误的请求参数名
        Object value = entry.getValue();//转换错误的请求参数值

        if (shouldAddError(propertyName, value)) {//判断是否要添加错误信息
            String message = XWorkConverter.getConversionErrorMessage(propertyName, stack);//获取错误提示信息
			//获取当前Action
            Object action = invocation.getAction();
            if (action instanceof ValidationAware) {//只有Action实现了ValidationAware接口
                ValidationAware va = (ValidationAware) action;
                //才会将错误信息添加到FieldError集合中,因为没有实现ValidationAware接口根本就没有addFieldError方法
                va.addFieldError(propertyName, message);
            }

            if (fakie == null) {
                fakie = new HashMap<Object, Object>();
            }
			//将错误值添加到fakieMap中(fakie意思是:假货,骗子)
            fakie.put(propertyName, getOverrideExpr(invocation, value));
        }
    }
	//如果fakie有值
    if (fakie != null) {
        // 将fakie Map放到ActionContext中
        stack.getContext().put(ORIGINAL_PROPERTY_OVERRIDE, fakie);
        //注册一个PreResultListener监听器
        invocation.addPreResultListener(new PreResultListener() {
            public void beforeResult(ActionInvocation invocation, String resultCode) {
                Map<Object, Object> fakie = (Map<Object, Object>) invocation.getInvocationContext().get(ORIGINAL_PROPERTY_OVERRIDE);

                if (fakie != null) {
                    invocation.getStack().setExprOverrides(fakie);
                }
            }
        });
    }
    return invocation.invoke();//调用下一个拦截器
}

    这里只有Action实现了ValidationAware接口才能将类型转换错误信息添加到FieldError中,提供给最后一个拦载器:DefaultWorkflowInterceptor使用,而且有类型转换错误还会注册一个PreResultListener监听器,该监听器会在Action与拦截器执行完毕之后,Result执行之前执行,这个监听器就是把存储在ActionContext中的fakie Map取出来调用ValueStack的setExprOverrides方法设置进行值栈中,当你再页面中通过OGNL表达获取该类型转换出错的参数时返回的是参数原来的值。例如有一请求参数path?age=xxx,而在Action中是用int类型去接收的,这样就会报转换错误,当你在页面中用OGNL获取age值(<s:property value="age"/>)时返回的是xxx而不是0。

   到此该拦截器就讲完了,最后invocation.invoke();调用下一个拦截器......


你可能感兴趣的:(struts2,Interceptor)