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。