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();调用下一个拦截器......