2010-10-28 42 views
1

例如,我有以下幾點:的Struts 2 S:動作標籤不使動作錯誤,如果存在的話

的struts.xml:

<action name="personForm"> 
    <result>/jsp/personForm.jsp</result> 
</action> 
<action name="savePerson"> 
    <result>/jsp/successSave.jsp</result> 
    <result name="input">/jsp/personForm.jsp</result> 
</action> 
<action name="countries"> 
    <result>/jsp/countries.jsp</result> 
</action> 

personForm.jsp:

<%@ taglib prefix="s" uri="/struts-tags" %> 
<s:form action="savePerson"> 
     <s:textfield name="firstName" label="First Name" /> 
     <s:textfield name="lastName" label="Last Name" /> 
     <s:action name="countries" executeResult="true" /> 
     <s:submit /> 
</s:form> 

CountriesAction.java:

public class CountriesAction extends ActionSupport { 
    public String execute() { 
     countries = getCountries(); 
     return SUCCESS; 
    } 

    private Map<String, String> getCountries() { 
      ... 
    } 

    private Map<String, String> countries; 
} 

countries.jsp:

<%@ taglib prefix="s" uri="/struts-tags" %> 
    <s:select name="countryId" label="Countries" list="countries" 
     headerKey="-1" headerValue="Please select the country ..."/> 

SavePerson.action

public class SavePerson extends ActionSupport { 

    public void validate() { 
     if (firstName == "") { 
      addFieldError(firstName, "First Name is required."); 
     } 

     if (lastName == "") { 
      addFieldError(lastName, "Last Name is required."); 
     } 

     if (countryId == "-1") { 
      addFieldError(countryId, "Country is required."); 
     } 

    } 

    public String execute() { 
     //get the properties and save the person... 
     return SUCCESS; 
    } 

    private String firstName; 
    private String lastName; 
    private String countryId; 

    //corresponding setters and getters.. 
} 

當我提交表單和驗證錯誤發生時,例如,讓我們說我們沒有任何填充數據,以便輸入字段「的firstName '和'lastName'將在他們旁邊有相應的消息。但是,國家選擇列表並不是這種情況,即使存在那些不會顯示的操作錯誤。

我相信會發生這種情況,因爲SavePerson的父操作是添加錯誤(addFieldErrors)的人,但是當其他操作的國家(填充列表的那個)被調用時,那些錯誤在該上下文中不可用因爲如果我在該Action中調用hasErrors(),它將是「false」,所以當輸入被渲染時,檢查是否有任何錯誤以便呈現消息將調用hasErrors並返回false,以便不會顯示錯誤消息。

調用另一個動作只是爲了使另一個輸入控件的這種做法的是Struts 2個的常見問題的方法之一告訴做到這一點: http://struts.apache.org/2.2.1/docs/how-do-we-repopulate-controls-when-validation-fails.html

所以,我怎樣才能使這些控件在這些行動使採取行動的錯誤從其父母的行爲。

有什麼想法?

預先感謝您

回答

2

我從呼叫者行動調用的動作設定錯誤的參考解決這一點。這被實現爲一個攔截器:

public class CopyErrorsInterceptor extends AbstractInterceptor { 


    public String intercept(ActionInvocation invocation) throws Exception { 
     ValueStack stack = invocation.getStack(); 
     CompoundRoot root = stack.getRoot(); 
     Action currentAction = (Action) invocation.getAction(); 
     if (root.size() > 1 && isValidationAware(currentAction)) { 
      Action callerAction = getFirstActionBelow(root, currentAction); 
      if (callerAction != null && isValidationAware(callerAction)) { 
       ValidationAware currentActionVal = (ValidationAware) currentAction; 
       ValidationAware callerActionVal = (ValidationAware) callerAction; 

       //Copy the errors to the chained action. 
       currentActionVal.setActionErrors(callerActionVal.getActionErrors()); 
       currentActionVal.setFieldErrors(callerActionVal.getFieldErrors()); 
      } 
     } 

     return invocation.invoke(); 
    } 

    /** 
    * Gets the first action below the passed action. 
    * @param root the stack to find the action 
    * @param current is the current action. 
    * @return 
    */ 
    private Action getFirstActionBelow(CompoundRoot root, Action current) { 
     boolean foundCurrentAction = false; 
     for(Object obj : root) { 
      if (obj == current) { 
       foundCurrentAction = true; 
      } else { 
       if (obj instanceof Action && foundCurrentAction) { 
        return (Action) obj; 
       } 
      } 
     } 
     return null; 
    } 

    private boolean isValidationAware(Action action) { 
     return action instanceof ValidationAware; 
    } 

} 

不得不宣佈我自己的堆棧延伸支柱默認:

<interceptors> 
      <interceptor name="copyErrors" class="com.afirme.casa.interceptor.CopyErrorsInterceptor"/> 

      <interceptor-stack name="defaultPlusErrors"> 
       <interceptor-ref name="copyErrors"/> 
       <interceptor-ref name="defaultStack"> 
        <param name="workflow.excludeMethods"> 
         input,back,cancel,execute 
        </param> 
       </interceptor-ref> 
      </interceptor-stack> 
     </interceptors> 

而對於那些打算通過其他行動來inovked(在這種情況下采取的行動通過動作標籤)必須引用這個新的攔截器棧。例如:

<action name="example" class="ExampleAction"> 
      <interceptor-ref name="defaultPlusErrors"/> 
      <result>/jsp/example.jsp</result> 
     </action> 

希望這有助於

阿爾弗雷多·Ø