先貼代碼:
applicationContext.xml:
<bean id="loginAction" class="jk.action.LoginAction">
<property name="userService" ref="userService"/>
</bean>
struts.xml:
<action name="login" class="loginAction" >
<result name="success">/index.jsp</result>
<result name="login">/login.jsp</result>
</action>
LoginAction.java:
@Override
public String execute() throws Exception {
User user = userService.userLogin(username, password);
if (user == null) {
addFieldError("login_error", getText("用戶名或密碼錯誤。。。"));
return LOGIN;
} else {
return SUCCESS;
}
}
<s:form action="login" method="post" οnsubmit="return checkLogin();">
<s:textfield id="username" name="username" />
<s:password id="password" name="password" />
<s:fielderror/>
<input type="submit" value="登陸" id="submitLogin">
</s:form>
這是一段簡單的登陸驗證的代碼,但是這樣寫代碼會出現一個問題,那就是當你第一次登陸驗證失敗後,以後無論你在怎麼輸賬號驗證,它都會跳轉到input視圖,而不是login視圖。
其實原因很簡單,那就是action執行的時候會先執行validate方法對參數進行一些列的驗證,如果他發現當前對象包含fieldError信息,就會直接給你跳轉到input視圖,由於我們在execute()方法中使用了addFieidError方法給對象添加了fieldErrod信息,所以當第一次驗證失敗再進行第二次驗證的時候,action發現自己有fieldEorr信息,就直接跳轉到input視圖了。
如果我們上面所說的成立,那麼就證明我們兩次訪問的是同一個action對象,但是爲什麼會是同一個action對象呢,我們知道struts2是線程安全的,每次請求都會創建一個新的action對象,但是爲什麼這裏不新建了呢?這主要是因爲spring的Ioc容器,我們在srping中配置struts2的時候,在bean裏面有一個選項scope,這個選項是用來配置bean的作用域的。其默認值是singleton,當bean的作用域是singleton時,Ioc容器只會爲該bean創建一個實例對象,以後所有對該bean的請求都是訪問的這一個對象。因此我們可以將bean的作用域配置爲prototype,當bean的作用域爲prototype時,每次訪問該bean都會創建一個新的對象。更改後的代碼:
applicationContext.xml:
<bean id="loginAction" class="jk.action.LoginAction" scope="prototype">
<property name="userService" ref="userService"/>
</bean>
除此之外還有一種方法,就是在action驗證的時候把fieldError信息清理了
LoginAction.java:
@Override
public void validate() {
super.validate();
clearFieldErrors();
}