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

📄 abstractformcontroller.java

📁 Spring API核心源代码 Spring API核心源代码 Spring API核心源代码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
	 * @throws Exception in case of invalid state or arguments
	 * @see #onBindOnNewForm(RenderRequest, Object)
	 * @see #setBindOnNewForm
	 */
	protected void onBindOnNewForm(RenderRequest request, Object command, BindException errors)
			throws Exception {

		onBindOnNewForm(request, command);
	}

	/**
	 * Callback for custom post-processing in terms of binding for a new form.
	 * Called by the default implementation of the <code>onBindOnNewForm</code> version
	 * with all parameters, after standard binding when displaying the form view.
	 * Only called if <code>bindOnNewForm</code> is set to <code>true</code>.
	 * <p>Default implementation is empty.
	 * @param request current render request
	 * @param command the command object to perform further binding on
	 * @throws Exception in case of invalid state or arguments
	 * @see #onBindOnNewForm(RenderRequest, Object, BindException)
	 * @see #setBindOnNewForm(boolean)
	 */
	protected void onBindOnNewForm(RenderRequest request, Object command) throws Exception {
	}


	/**
	 * Return the form object for the given request.
	 * <p>Calls <code>formBackingObject</code> if the object is not in the session
	 * @param request current request
	 * @return object form to bind onto
	 * @see #formBackingObject
	 */
	protected final Object getCommand(PortletRequest request) throws Exception {
		// If not in session-form mode, create a new form-backing object.
		if (!isSessionForm()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Not a session-form -- using new formBackingObject");
			}
			return formBackingObject(request);
		}
		
		// Session-form mode: retrieve form object from portlet session attribute.
		PortletSession session = request.getPortletSession(false);
		if (session == null) {
			throw new PortletSessionRequiredException("Must have session when trying to bind (in session-form mode)");
		}
		String formAttrName = getFormSessionAttributeName(request);
		Object sessionFormObject = session.getAttribute(formAttrName);
		if (sessionFormObject == null) {
			throw new PortletSessionRequiredException("Form object not found in session (in session-form mode)");
		}

		// Remove form object from porlet 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 portlet session.
		if (logger.isDebugEnabled()) {
			logger.debug("Removing form session attribute [" + formAttrName + "]");
		}
		session.removeAttribute(formAttrName);

		// Check the command object to make sure its valid
		if (!checkCommand(sessionFormObject)) {
			throw new PortletSessionRequiredException("Object found in session does not match commandClass");
		}

		return sessionFormObject;
	}

	/**
	 * Retrieve a backing object for the current form from the given request.
	 * <p>The properties of the form object will correspond to the form field values
	 * in your form view. This object will be exposed in the model under the specified
	 * command name, to be accessed under that name in the view: for example, with
	 * a "spring:bind" tag. The default command name is "command".
	 * <p>Note that you need to activate session form mode to reuse the form-backing
	 * object across the entire form workflow. Else, a new instance of the command
	 * class will be created for each submission attempt, just using this backing
	 * object as template for the initial form.
	 * <p>Default implementation calls <code>BaseCommandController.createCommand</code>,
	 * creating a new empty instance of the command class.
	 * Subclasses can override this to provide a preinitialized backing object.
	 * @param request current portlet request
	 * @return the backing object
	 * @throws Exception in case of invalid state or arguments
	 * @see #setCommandName
	 * @see #setCommandClass
	 * @see #createCommand
	 */
	protected Object formBackingObject(PortletRequest request) throws Exception {
		return createCommand();
	}


	/**
	 * Prepare the form model and view, including reference and error data.
	 * Can show a configured form page, or generate a form view programmatically.
	 * <p>A typical implementation will call
	 * <code>showForm(request, errors, "myView")</code>
	 * to prepare the form view for a specific view name, returning the
	 * ModelAndView provided there.
	 * <p>For building a custom ModelAndView, call <code>errors.getModel()</code>
	 * to populate the ModelAndView model with the command and the Errors instance,
	 * under the specified command name, as expected by the "spring:bind" tag.
	 * You also need to include the model returned by <code>referenceData</code>.
	 * <p>Note: If you decide to have a "formView" property specifying the
	 * view name, consider using SimpleFormController.
	 * @param request current render request
	 * @param response current render response
	 * @param errors validation errors holder
	 * @return the prepared form view, or null if handled directly
	 * @throws Exception in case of invalid state or arguments
	 * @see #showForm(RenderRequest, BindException, String)
	 * @see org.springframework.validation.Errors
	 * @see org.springframework.validation.BindException#getModel
	 * @see #referenceData(PortletRequest, Object, Errors)
	 * @see SimpleFormController#setFormView
	 */
	protected abstract ModelAndView showForm(RenderRequest request, RenderResponse response, BindException errors) throws Exception;

	/**
	 * Prepare model and view for the given form, including reference and errors.
	 * <p>In session form mode: Re-puts the form object in the session when
	 * returning to the form, as it has been removed by getCommand.
	 * <p>Can be used in subclasses to redirect back to a specific form page.
	 * @param request current render request
	 * @param errors validation errors holder
	 * @param viewName name of the form view
	 * @return the prepared form view
	 * @throws Exception in case of invalid state or arguments
	 * @see #showForm(RenderRequest, BindException, String, Map)
	 * @see #showForm(RenderRequest, RenderResponse, BindException)
	 */
	protected final ModelAndView showForm(RenderRequest request, BindException errors, String viewName)
			throws Exception {

		return showForm(request, errors, viewName, null);
	}

	/**
	 * Prepare model and view for the given form, including reference and errors,
	 * adding a controller-specific control model.
	 * <p>In session form mode: Re-puts the form object in the session when returning
	 * to the form, as it has been removed by getCommand.
	 * <p>Can be used in subclasses to redirect back to a specific form page.
	 * @param request current render request
	 * @param errors validation errors holder
	 * @param viewName name of the form view
	 * @param controlModel model map containing controller-specific control data
	 * (e.g. current page in wizard-style controllers or special error message)
	 * @return the prepared form view
	 * @throws Exception in case of invalid state or arguments
	 * @see #showForm(RenderRequest, BindException, String)
	 * @see #showForm(RenderRequest, RenderResponse, BindException)
	 */
	protected final ModelAndView showForm(RenderRequest request, BindException errors, String viewName, Map controlModel)
			throws Exception {

		// In session form mode, re-expose form object as portlet 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()) {
			String formAttrName = getFormSessionAttributeName(request);
			if (logger.isDebugEnabled()) {
				logger.debug("Setting form session attribute [" + formAttrName + "] to: " + errors.getTarget());
			}
			request.getPortletSession().setAttribute(formAttrName, errors.getTarget());
		}

		// Fetch errors model as starting point, containing form object under
		// "commandName", and corresponding Errors instance under internal key.
		Map model = errors.getModel();
		
		// Merge reference data into model, if any.
		Map referenceData = referenceData(request, errors.getTarget(), errors);
		if (referenceData != null) {
			model.putAll(referenceData);
		}

		// Merge control attributes into model, if any.
		if (controlModel != null) {
			model.putAll(controlModel);
		}

		// Trigger rendering of the specified view, using the final model.
		return new ModelAndView(viewName, model);
	}

	/**
	 * Create a reference data map for the given request, consisting of
	 * bean name/bean instance pairs as expected by ModelAndView.
	 * <p>Default implementation returns null.
	 * Subclasses can override this to set reference data used in the view.
	 * @param request current render request
	 * @param command form object with request parameters bound onto it
	 * @param errors validation errors holder
	 * @return a Map with reference data entries, or null if none
	 * @throws Exception in case of invalid state or arguments
	 * @see ModelAndView
	 */
	protected Map referenceData(PortletRequest request, Object command, Errors errors) throws Exception {
		return null;
	}


	/**
	 * Process render phase of form submission request. Called by <code>handleRequestInternal</code>
	 * in case of a form submission, with or without binding errors. Implementations
	 * need to proceed properly, typically showing a form view in case of binding
	 * errors or rendering the result of a submit action else.
	 * <p>For a success view, call <code>errors.getModel()</code> to populate the
	 * ModelAndView model with the command and the Errors instance, under the
	 * specified command name, as expected by the "spring:bind" tag. For a form view,
	 * simply return the ModelAndView object privded by <code>showForm</code>.
	 * @param request current render request
	 * @param response current render response
	 * @param command form object with request parameters bound onto it
	 * @param errors errors holder
	 * @return the prepared model and view, or null
	 * @throws Exception in case of errors
	 * @see #handleRenderRequestInternal
	 * @see #processFormSubmission
	 * @see #isFormSubmission
	 * @see #showForm(RenderRequest, RenderResponse, BindException)
	 * @see org.springframework.validation.Errors
	 * @see org.springframework.validation.BindException#getModel
	 */
	protected abstract ModelAndView renderFormSubmission(RenderRequest request, RenderResponse response, Object command, BindException errors)
			throws Exception;

	/**
	 * Process action phase of form submission request. Called by <code>handleRequestInternal</code>
	 * in case of a form submission, with or without binding errors. Implementations
	 * need to proceed properly, typically performing a submit action if there are no binding errors.
	 * <p>Subclasses can implement this to provide custom submission handling
	 * like triggering a custom action. They can also provide custom validation
	 * or proceed with the submission accordingly.
	 * @param request current action request
	 * @param response current action response
	 * @param command form object with request parameters bound onto it
	 * @param errors errors holder (subclass can add errors if it wants to)
	 * @throws Exception in case of errors
	 * @see #handleActionRequestInternal
	 * @see #renderFormSubmission
	 * @see #isFormSubmission
	 * @see org.springframework.validation.Errors
	 */
	protected abstract void processFormSubmission(ActionRequest request, ActionResponse response, Object command, BindException errors)
			throws Exception;

	/**
	 * Handle an invalid submit request, e.g. when in session form mode but no form object
	 * was found in the session (like in case of an invalid resubmit by the browser).
	 * <p>Default implementation simply tries to resubmit the form with a new form object.
	 * This should also work if the user hit the back button, changed some form data,
	 * and resubmitted the form.
	 * <p>Note: To avoid duplicate submissions, you need to override this method.
	 * Either show some "invalid submit" message, or call <code>showNewForm</code> for
	 * resetting the form (prepopulating it with the current values if "bindOnNewForm"
	 * is true). In this case, the form object in the session serves as transaction token.
	 * <pre>
	 * protected ModelAndView handleInvalidSubmit(RenderRequest request, RenderResponse response) throws Exception {
	 *   return showNewForm(request, response);
	 * }</pre>
	 * You can also show a new form but with special errors registered on it:
	 * <pre>
	 * protected ModelAndView handleInvalidSubmit(RenderRequest request, RenderResponse response) throws Exception {
	 *   BindException errors = getErrorsForNewForm(request);
	 *   errors.reject("duplicateFormSubmission", "Duplicate form submission");
	 *   return showForm(request, response, errors);
	 * }</pre>
	 * <p><b>WARNING:</b> If you override this method, be sure to also override the action
	 * phase version of this method so that it will not attempt to perform the resubmit
	 * action by default.
	 * @param request current render request
	 * @param response current render response
	 * @return a prepared view, or null if handled directly
	 * @throws Exception in case of errors
	 * @see #handleInvalidSubmit
	 */
	protected ModelAndView renderInvalidSubmit(RenderRequest request, RenderResponse response)
			throws Exception {

		return renderFormSubmission(request, response, getRenderCommand(request), getRenderErrors(request));
	}

	/**
	 * Handle an invalid submit request, e.g. when in session form mode but no form object
	 * was found in the session (like in case of an invalid resubmit by the browser).
	 * <p>Default implementation simply tries to resubmit the form with a new form object.
	 * This should also work if the user hit the back button, changed some form data,
	 * and resubmitted the form.
	 * <p>Note: To avoid duplicate submissions, you need to override this method.
	 * Most likely you will simply want it to do nothing here in the action phase
	 * and diplay an appropriate error and a new form in the render phase.
	 * <pre>
	 * protected void handleInvalidSubmit(ActionRequest request, ActionResponse response) throws Exception {
	 * }</pre>
	 * <p>If you override this method but you do need a command object and bind errors
	 * in the render phase, be sure to call {@link #setRenderCommandAndErrors setRenderCommandAndErrors}
	 * from here.
	 * @param request current action request
	 * @param response current action response
	 * @throws Exception in case of errors
	 * @see #renderInvalidSubmit
	 * @see #setRenderCommandAndErrors
	 */
	protected void handleInvalidSubmit(ActionRequest request, ActionResponse response) throws Exception {
		passRenderParameters(request, response);
		Object command = formBackingObject(request);
		if (command == null) {
			throw new PortletException("Form object returned by formBackingObject() must not be null");
		}
		if (!checkCommand(command)) {
			throw new PortletException("Form object returned by formBackingObject() must match commandClass");
		}
		PortletRequestDataBinder binder = bindAndValidate(request, command);
		BindException errors = new BindException(binder.getBindingResult());
		processFormSubmission(request, response, command, errors);
		setRenderCommandAndErrors(request, command, errors);
	}

}

⌨️ 快捷键说明

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