在struts(version 1.1)中,存在下面描述的一种情况:
有2个Action,UserLoginAction和LoginDetailAction 和一个MyLogin.jsp页面。
程序的流程是这样的:
请求一个MyLogin.jsp,在name输入框中输入:gordian。点击按钮提交,流程跳转到了UserLoginAction,在UserLoginAction中,
把form的name属性的值改为了'gct',并跳转到了LoginDetailAction,这时,我们发现,form中name属性的值,仍然是gordian,而不是在UserLoginAction
中修改的'gct’,就是说,在UserLoginAction中对form的操作失效了。
注:UserLoginAction和LoginDetailAction都指向同一个form
经过对Struts的源码进行跟踪发现,Struts的RequestProcessor类中的方法processPopulate()对form进行了一系列关键的操作.
对于每一次请求,struts引擎复负责生成form实例,并根据配置文件设置的scope,在request或是在session(等)保存form的实例。
当一个请求到来的时候,引擎首先根据Action,查找form的名字,再根据名字在request或者session中查找form的实例。如果,存在则直接返回。
如果不存在,则生成新的实例。
获取实例之后,引擎调用了RequestProcessor类中的方法processPopulate()。该方法,重置了form属性的值: form.reset(mapping, request);
并调用了 RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(),request);方法,从request中重新获取值对,
重新设置form的值。因此,form的值,又与request中的一致了。所以,在UserLoginAction对form的任何操作都是无效的。
照此推论,即使UserLoginAction和LoginDetailAction指向不同的form,但两个form有相同的属性,在UserLoginAction对相同的属性的值进行了修改,
那么,在LoginDetailAction中获取到的该属性的值还是不变的。
代码清单1:
public class UserLoginAction extends ComtopAction{
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
logger.debug("UserLoginAction");
UserForm userForm=(UserForm) form;
logger.debug(userForm);
logger.debug("在UserLoginAction userForm.hashCode "+userForm.hashCode());
userForm.setActionType("detail");
logger.debug("在UserLoginAction 设置actionType 的值");
userForm.setName("gct");
return mapping.findForward("LoginDetailAction");
}
}
代码清单2:
public class LoginDetailAction extends ComtopAction{
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
UserForm userForm=(UserForm) form;
logger.debug("LoginDetailAction");
logger.debug(userForm);
System.out.println(userForm);
logger.debug("在LoginDetailAction userForm.hashCode "+userForm.hashCode());
return mapping.findForward("LoginDetail");
}
}
代码清单3:
/**
* Populate the properties of the specified ActionForm instance from
* the request parameters included with this request. In addition,
* request attribute Globals.CANCEL_KEY
will be set if
* the request was submitted with a button created by
* CancelTag
.
*
* @param request The servlet request we are processing
* @param response The servlet response we are creating
* @param form The ActionForm instance we are populating
* @param mapping The ActionMapping we are using
*
* @exception ServletException if thrown by RequestUtils.populate()
*/
protected void processPopulate(HttpServletRequest request,
HttpServletResponse response,
ActionForm form,
ActionMapping mapping)
throws ServletException {
if (form == null) {
return;
}
// Populate the bean properties of this ActionForm instance
if (log.isDebugEnabled()) {
log.debug(" Populating bean properties from this request");
}
form.setServlet(this.servlet);
form.reset(mapping, request);
if (mapping.getMultipartClass() != null) {
request.setAttribute(Globals.MULTIPART_KEY,
mapping.getMultipartClass());
}
RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(),
request);
// Set the cancellation request attribute if appropriate
if ((request.getParameter(Constants.CANCEL_PROPERTY) != null) ||
(request.getParameter(Constants.CANCEL_PROPERTY_X) != null)) {
request.setAttribute(Globals.CANCEL_KEY, Boolean.TRUE);
}
}