先贴代码:
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>
@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" onsubmit="return checkLogin();"> <s:textfield id="username" name="username" /> <s:password id="password" name="password" /> <s:fielderror/> <input type="submit" value="登陆" id="submitLogin"> </s:form>
其实原因很简单,那就是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>
LoginAction.java:
@Override public void validate() { super.validate(); clearFieldErrors(); }