是的,覆写formBackingObject方法就是利用Session Form。使用Session Form还必须将Form设置为Session Form。如下代码末端用红色序号标注的地方表示了通过formBackingObject在“GET"修改页面时将Command Object加入到Session的过程。用绿色序号标注的代码表示了如何在”POST“请求后从Session中取出Command对象。
此段代码拷贝自Spring的AbstractFormController类。
如此看来覆写formBackingObject方法才是使用Session Form的正道。不过就是好像必须在form初始化时手动设置为Session Form。
现在还没有看出来Session中的Command对象是什么时候被修改的,这还是个问题。
此段代码拷贝自Spring的AbstractFormController类。
java 代码
- protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
- throws Exception {
- // Form submission or new form to show?
- if (isFormSubmission(request)) {
- // Fetch form object from HTTP session, bind, validate, process submission.
- try {
- Object command = getCommand(request); 1
- ...
- }
- catch (HttpSessionRequiredException ex) {
- ...
- }
- }
- else {
- // New form to show: render form view.
- return showNewForm(request, response); 1
- }
- }
- protected final ModelAndView showNewForm(HttpServletRequest request, HttpServletResponse response)
- throws Exception {
- logger.debug("Displaying new form");
- return showForm(request, response, getErrorsForNewForm(request)); 2
- }
- protected final BindException getErrorsForNewForm(HttpServletRequest request) throws Exception {
- // Create form-backing object for new form.
- Object command = formBackingObject(request); 3
- if (command == null) {
- throw new ServletException("Form object returned by formBackingObject() must not be null");
- }
- if (!checkCommand(command)) {
- throw new ServletException("Form object returned by formBackingObject() must match commandClass");
- }
- // Bind without validation, to allow for prepopulating a form, and for
- // convenient error evaluation in views (on both first attempt and resubmit).
- ServletRequestDataBinder binder = createBinder(request, command);
- BindException errors = new BindException(binder.getBindingResult());
- if (isBindOnNewForm()) {
- logger.debug("Binding to new form");
- binder.bind(request);
- onBindOnNewForm(request, command, errors);
- }
- // Return BindException object that resulted from binding.
- return errors;
- }
- protected final Object getCommand(HttpServletRequest request) throws Exception {
- // If not in session-form mode, create a new form-backing object.
- if (!isSessionForm()) { 2
- return formBackingObject(request);
- }
- // Session-form mode: retrieve form object from HTTP session attribute.
- HttpSession session = request.getSession(false);
- if (session == null) {
- throw new HttpSessionRequiredException("Must have session when trying to bind (in session-form mode)");
- }
- String formAttrName = getFormSessionAttributeName(request);
- Object sessionFormObject = session.getAttribute(formAttrName); 3
- if (sessionFormObject == null) {
- throw new HttpSessionRequiredException("Form object not found in session (in session-form mode)");
- }
- // Remove form object from HTTP session: we might finish the form workflow
- // in this request. If it turns out that we need to show the form view again,
- // we'll re-bind the form object to the HTTP session.
- if (logger.isDebugEnabled()) {
- logger.debug("Removing form session attribute [" + formAttrName + "]");
- }
- session.removeAttribute(formAttrName);
- return currentFormObject(request, sessionFormObject);
- }
- protected final ModelAndView showForm(
- HttpServletRequest request, BindException errors, String viewName, Map controlModel)
- throws Exception {
- // In session form mode, re-expose form object as HTTP session attribute.
- // Re-binding is necessary for proper state handling in a cluster,
- // to notify other nodes of changes in the form object.
- if (isSessionForm()) { 5
- String formAttrName = getFormSessionAttributeName(request);
- if (logger.isDebugEnabled()) {
- logger.debug("Setting form session attribute [" + formAttrName + "] to: " + errors.getTarget());
- }
- request.getSession().setAttribute(formAttrName, errors.getTarget()); 6
- }
- ...
- }
- protected Object formBackingObject(HttpServletRequest request) throws Exception {
- return createCommand(); 4
- }
如此看来覆写formBackingObject方法才是使用Session Form的正道。不过就是好像必须在form初始化时手动设置为Session Form。
现在还没有看出来Session中的Command对象是什么时候被修改的,这还是个问题。