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。