⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractformcontroller.java

📁 spring api 源代码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright 2002-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.servlet.mvc;

import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
import org.springframework.web.HttpSessionRequiredException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;

/**
 * <p>Form controller that auto-populates a form bean from the request.
 * This, either using a new bean instance per request, or using the same bean
 * when the <code>sessionForm</code> property has been set to <code>true</code>.</p>
 *
 * <p>This class is the base class for both framework subclasses such as
 * {@link SimpleFormController} and {@link AbstractWizardFormController}
 * and custom form controllers that you may provide yourself.</p>
 *
 * <p>A form-input view and an after-submission view have to be provided
 * programmatically. To provide those views using configuration properties,
 * use the {@link SimpleFormController}.</p>
 *
 * <p>Subclasses need to override <code>showForm</code> to prepare the form view,
 * and <code>processFormSubmission</code> to handle submit requests. For the latter,
 * binding errors like type mismatches will be reported via the given "errors" holder.
 * For additional custom form validation, a validator (property inherited from
 * BaseCommandController) can be used, reporting via the same "errors" instance.</p>
 *
 * <p>Comparing this Controller to the Struts notion of the <code>Action</code>
 * shows us that with Spring, you can use any ordinary JavaBeans or database-
 * backed JavaBeans without having to implement a framework-specific class
 * (like Struts' <code>ActionForm</code>). More complex properties of JavaBeans
 * (Dates, Locales, but also your own application-specific or compound types)
 * can be represented and submitted to the controller, by using the notion of
 * a <code>java.beans.PropertyEditor</code>. For more information on that
 * subject, see the workflow of this controller and the explanation of the
 * {@link BaseCommandController}.</p>
 *
 * <p><b><a name="workflow">Workflow
 * (<a href="BaseCommandController.html#workflow">and that defined by superclass</a>):</b><br>
 * <ol>
 *  <li><b>The controller receives a request for a new form (typically a GET).</b></li>
 *  <li>Call to {@link #formBackingObject formBackingObject()} which by default,
 *      returns an instance of the commandClass that has been configured
 *      (see the properties the superclass exposes), but can also be overridden
 *      to e.g. retrieve an object from the database (that needs to be modified
 * using the form).</li>
 *  <li>Call to {@link #initBinder initBinder()} which allows you to register
 *      custom editors for certain fields (often properties of non-primitive
 *      or non-String types) of the command class. This will render appropriate
 *      Strings for those property values, e.g. locale-specific date strings.</li>
 *  <li><em>Only if <code>bindOnNewForm</code> is set to <code>true</code></em>, then
 *      {@link org.springframework.web.bind.ServletRequestDataBinder ServletRequestDataBinder}
 *      gets applied to populate the new form object with initial request parameters and the
 *      {@link #onBindOnNewForm(HttpServletRequest, Object, BindException)} callback method is
 *      called. <em>Note:</em> any defined Validators are not applied at this point, to allow
 *      partial binding. However be aware that any Binder customizations applied via 
 *      initBinder() (such as
 *      {@link org.springframework.validation.DataBinder#setRequiredFields(String[])} will
 *      still apply. As such, if using bindOnNewForm=true and initBinder() customizations are
 *      used to validate fields instead of using Validators, in the case that only some fields
 *      will be populated for the new form, there will potentially be some bind errors for
 *      missing fields in the errors object. Any view (JSP, etc.) that displays binder errors
 *      needs to be intelligent and for this case take into account whether it is displaying the
 *      initial form view or subsequent post results, skipping error display for the former.</li>
 *  <li>Call to {@link #showForm(HttpServletRequest, HttpServletResponse, BindException) showForm()}
 *      to return a View that should be rendered (typically the view that renders
 *      the form). This method has to be implemented in subclasses.</li>
 *  <li>The showForm() implementation will call {@link #referenceData referenceData()},
 *      which you can implement to provide any relevant reference data you might need
 *      when editing a form (e.g. a List of Locale objects you're going to let the
 *      user select one from).</li>
 *  <li>Model gets exposed and view gets rendered, to let the user fill in the form.</li>
 *  <li><b>The controller receives a form submission (typically a POST).</b>
 *      To use a different way of detecting a form submission, override the
 *      {@link #isFormSubmission isFormSubmission} method.
 *      </li>
 *  <li>If <code>sessionForm</code> is not set, {@link #formBackingObject formBackingObject()}
 *      is called to retrieve a form object. Otherwise, the controller tries to
 *      find the command object which is already bound in the session. If it cannot
 *      find the object, it does a call to {@link #handleInvalidSubmit handleInvalidSubmit}
 *      which - by default - tries to create a new form object and resubmit the form.</li>
 *  <li>The {@link org.springframework.web.bind.ServletRequestDataBinder ServletRequestDataBinder}
 *      gets applied to populate the form object with current request parameters.
 *  <li>Call to {@link #onBind onBind(HttpServletRequest, Object, Errors)} which allows
 *      you to do custom processing after binding but before validation (e.g. to manually
 *      bind request parameters to bean properties, to be seen by the Validator).</li>
 *  <li>If <code>validateOnBinding</code> is set, a registered Validator will be invoked.
 *      The Validator will check the form object properties, and register corresponding
 *      errors via the given {@link org.springframework.validation.Errors Errors}</li> object.
 *  <li>Call to {@link #onBindAndValidate onBindAndValidate()} which allows you
 *      to do custom processing after binding and validation (e.g. to manually
 *      bind request parameters, and to validate them outside a Validator).</li>
 *  <li>Call {@link #processFormSubmission(HttpServletRequest, HttpServletResponse,
 *      Object, BindException) processFormSubmission()} to process the submission, with
 *      or without binding errors. This method has to be implemented in subclasses.</li>
 * </ol>
 * </p>
 *
 * <p>In session form mode, a submission without an existing form object in the
 * session is considered invalid, like in case of a resubmit/reload by the browser.
 * The {@link #handleInvalidSubmit handleInvalidSubmit} method is invoked then,
 * by default trying to resubmit. It can be overridden in subclasses to show
 * corresponding messages or to redirect to a new form, in order to avoid duplicate
 * submissions. The form object in the session can be considered a transaction
 * token in that case.</p>
 *
 * <p>Note that views should never retrieve form beans from the session but always
 * from the request, as prepared by the form controller. Remember that some view
 * technologies like Velocity cannot even access a HTTP session.</p>
 *
 * <p><b><a name="config">Exposed configuration properties</a>
 * (<a href="BaseCommandController.html#config">and those defined by superclass</a>):</b><br>
 * <table border="1">
 *  <tr>
 *      <td><b>name</b></td>
 *      <td><b>default</b></td>
 *      <td><b>description</b></td>
 *  </tr>
 *  <tr>
 *      <td>bindOnNewForm</td>
 *      <td>false</td>
 *      <td>Indicates whether to bind servlet request parameters when
 *          creating a new form. Otherwise, the parameters will only be
 *          bound on form submission attempts.</td>
 *  </tr>
 *  <tr>
 *      <td>sessionForm</td>
 *      <td>false</td>
 *      <td>Indicates whether the form object should be kept in the session
 *          when a user asks for a new form. This allows you e.g. to retrieve
 *          an object from the database, let the user edit it, and then persist
 *          it again. Otherwise, a new command object will be created for each
 *          request (even when showing the form again after validation errors).</td>
 *  </tr>
 * </table>
 * </p>
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Alef Arendsen
 * @author Rob Harrop
 * @author Colin Sampaleanu
 * @see #showForm(HttpServletRequest, HttpServletResponse, BindException)
 * @see #processFormSubmission
 * @see SimpleFormController
 * @see AbstractWizardFormController
 */
public abstract class AbstractFormController extends BaseCommandController {

	private boolean bindOnNewForm = false;

	private boolean sessionForm = false;


	/**
	 * Create a new AbstractFormController.
	 * <p>Subclasses should set the following properties, either in the constructor
	 * or via a BeanFactory: commandName, commandClass, bindOnNewForm, sessionForm.
	 * Note that "commandClass" doesn't need to be set when overriding
	 * {@link #formBackingObject}, since the latter determines the class anyway.
	 * <p>"cacheSeconds" is by default set to 0 (-> no caching for all form controllers).
	 * @see #setCommandName
	 * @see #setCommandClass
	 * @see #setBindOnNewForm
	 * @see #setSessionForm
	 * @see #formBackingObject
	 */
	public AbstractFormController() {
		setCacheSeconds(0);
	}

	/**
	 * Set whether request parameters should be bound to the form object
	 * in case of a non-submitting request, that is, a new form.
	 */
	public final void setBindOnNewForm(boolean bindOnNewForm) {
		this.bindOnNewForm = bindOnNewForm;
	}

	/**
	 * Return <code>true</code> if request parameters should be bound in case of a new form.
	 */
	public final boolean isBindOnNewForm() {
		return this.bindOnNewForm;
	}

	/**
	 * Activate/deactivate session form mode. In session form mode,
	 * the form is stored in the session to keep the form object instance
	 * between requests, instead of creating a new one on each request.
	 * <p>This is necessary for either wizard-style controllers that populate a
	 * single form object from multiple pages, or forms that populate a persistent
	 * object that needs to be identical to allow for tracking changes.
	 * <p>Please note that the {@link AbstractFormController} class (and all
	 * subclasses of it unless stated to the contrary) do <i>not</i> support
	 * the notion of a conversation. This is important in the context of this
	 * property, because it means that there is only <i>one</i> form per session:
	 * this means that if session form mode is activated and a user opens up
	 * say two tabs in their browser and attempts to edit two distinct objects
	 * using the same form, then the <i>shared</i> session state can potentially
	 * (and most probably will) be overwritten by the last tab to be opened,
	 * which can lead to errors when either of the forms in each is finally

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -