?? abstractwizardformcontroller.java
字號(hào):
/*
* 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.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.WebUtils;
/**
* Form controller for typical wizard-style workflows.
*
* <p>In contrast to classic forms, wizards have more than one form view page.
* Therefore, there are various actions instead of one single submit action:
* <ul>
* <li>finish: trying to leave the wizard successfully, that is, perform its
* final action, and thus requiring a valid state;
* <li>cancel: leaving the wizard without performing its final action, and
* thus without regard to the validity of its current state;
* <li>page change: showing another wizard page, e.g. the next or previous
* one, with regard to "dirty back" and "dirty forward".
* </ul>
*
* <p>Finish and cancel actions can be triggered by request parameters, named
* PARAM_FINISH ("_finish") and PARAM_CANCEL ("_cancel"), ignoring parameter
* values to allow for HTML buttons. The target page for page changes can be
* specified by PARAM_TARGET, appending the page number to the parameter name
* (e.g. "_target1"). The action parameters are recognized when triggered by
* image buttons too (via "_finish.x", "_abort.x", or "_target1.x").
*
* <p>The current page number will be stored in the session. It can also be
* specified as request parameter PARAM_PAGE ("_page") in order to properly handle
* usage of the back button in a browser: In this case, a submission will always
* contain the correct page number, even if the user submitted from an old view.
*
* <p>The page can only be changed if it validates correctly, except if a
* "dirty back" or "dirty forward" is allowed. At finish, all pages get
* validated again to guarantee a consistent state.
*
* <p>Note that a validator's default validate method is not executed when using
* this class! Rather, the {@link #validatePage} implementation should call
* special <code>validateXXX</code> methods that the validator needs to provide,
* validating certain pieces of the object. These can be combined to validate
* the elements of individual pages.
*
* <p>Note: Page numbering starts with 0, to be able to pass an array
* consisting of the corresponding view names to the "pages" bean property.
*
* @author Juergen Hoeller
* @since 25.04.2003
* @see #setPages
* @see #validatePage
* @see #processFinish
* @see #processCancel
*/
public abstract class AbstractWizardFormController extends AbstractFormController {
/**
* Parameter triggering the finish action.
* Can be called from any wizard page!
*/
public static final String PARAM_FINISH = "_finish";
/**
* Parameter triggering the cancel action.
* Can be called from any wizard page!
*/
public static final String PARAM_CANCEL = "_cancel";
/**
* Parameter specifying the target page,
* appending the page number to the name.
*/
public static final String PARAM_TARGET = "_target";
/**
* Parameter specifying the current page as value. Not necessary on
* form pages, but allows to properly handle usage of the back button.
* @see #setPageAttribute
*/
public static final String PARAM_PAGE = "_page";
private String[] pages;
private String pageAttribute;
private boolean allowDirtyBack = true;
private boolean allowDirtyForward = false;
/**
* Create a new AbstractWizardFormController.
* <p>"sessionForm" is automatically turned on, "validateOnBinding"
* turned off, and "cacheSeconds" set to 0 by the base class
* (-> no caching for all form controllers).
*/
public AbstractWizardFormController() {
// AbstractFormController sets default cache seconds to 0.
super();
// Always needs session to keep data from all pages.
setSessionForm(true);
// Never validate everything on binding ->
// wizards validate individual pages.
setValidateOnBinding(false);
}
/**
* Set the wizard pages, i.e. the view names for the pages.
* The array index is interpreted as page number.
* @param pages view names for the pages
*/
public final void setPages(String[] pages) {
if (pages == null || pages.length == 0) {
throw new IllegalArgumentException("No wizard pages defined");
}
this.pages = pages;
}
/**
* Return the wizard pages, i.e. the view names for the pages.
* The array index corresponds to the page number.
* <p>Note that a concrete wizard form controller might override
* {@link #getViewName(HttpServletRequest, Object, int)} to
* determine the view name for each page dynamically.
* @see #getViewName(javax.servlet.http.HttpServletRequest, Object, int)
*/
public final String[] getPages() {
return this.pages;
}
/**
* Return the number of wizard pages.
* Useful to check whether the last page has been reached.
* <p>Note that a concrete wizard form controller might override
* {@link #getPageCount(HttpServletRequest, Object)} to determine
* the page count dynamically. The default implementation of that extended
* <code>getPageCount</code> variant returns the static page count as
* determined by this <code>getPageCount()</code> method.
* @see #getPageCount(javax.servlet.http.HttpServletRequest, Object)
*/
protected final int getPageCount() {
return this.pages.length;
}
/**
* Set the name of the page attribute in the model, containing
* an Integer with the current page number.
* <p>This will be necessary for single views rendering multiple view pages.
* It also allows for specifying the optional "_page" parameter.
* @param pageAttribute name of the page attribute
* @see #PARAM_PAGE
*/
public final void setPageAttribute(String pageAttribute) {
this.pageAttribute = pageAttribute;
}
/**
* Return the name of the page attribute in the model.
*/
public final String getPageAttribute() {
return this.pageAttribute;
}
/**
* Set if "dirty back" is allowed, that is, if moving to a former wizard
* page is allowed in case of validation errors for the current page.
* @param allowDirtyBack if "dirty back" is allowed
*/
public final void setAllowDirtyBack(boolean allowDirtyBack) {
this.allowDirtyBack = allowDirtyBack;
}
/**
* Return whether "dirty back" is allowed.
*/
public final boolean isAllowDirtyBack() {
return this.allowDirtyBack;
}
/**
* Set if "dirty forward" is allowed, that is, if moving to a later wizard
* page is allowed in case of validation errors for the current page.
* @param allowDirtyForward if "dirty forward" is allowed
*/
public final void setAllowDirtyForward(boolean allowDirtyForward) {
this.allowDirtyForward = allowDirtyForward;
}
/**
* Return whether "dirty forward" is allowed.
*/
public final boolean isAllowDirtyForward() {
return this.allowDirtyForward;
}
/**
* Calls page-specific onBindAndValidate method.
*/
protected final void onBindAndValidate(HttpServletRequest request, Object command, BindException errors)
throws Exception {
onBindAndValidate(request, command, errors, getCurrentPage(request));
}
/**
* Callback for custom post-processing in terms of binding and validation.
* Called on each submit, after standard binding but before page-specific
* validation of this wizard form controller.
* <p>Note: AbstractWizardFormController does not perform standand
* validation on binding but rather applies page-specific validation
* on processing the form submission.
* @param request current HTTP request
* @param command bound command
* @param errors Errors instance for additional custom validation
* @param page current wizard page
* @throws Exception in case of invalid state or arguments
* @see #bindAndValidate
* @see #processFormSubmission
* @see org.springframework.validation.Errors
*/
protected void onBindAndValidate(HttpServletRequest request, Object command, BindException errors, int page)
throws Exception {
}
/**
* Consider an explicit finish or cancel request as a form submission too.
* @see #isFinishRequest(javax.servlet.http.HttpServletRequest)
* @see #isCancelRequest(javax.servlet.http.HttpServletRequest)
*/
protected boolean isFormSubmission(HttpServletRequest request) {
return super.isFormSubmission(request) || isFinishRequest(request) || isCancelRequest(request);
}
/**
* Calls page-specific referenceData method.
*/
protected final Map referenceData(HttpServletRequest request, Object command, Errors errors)
throws Exception {
return referenceData(request, command, errors, getCurrentPage(request));
}
/**
* Create a reference data map for the given request, consisting of
* bean name/bean instance pairs as expected by ModelAndView.
* <p>The default implementation delegates to referenceData(HttpServletRequest, int).
* Subclasses can override this to set reference data used in the view.
* @param request current HTTP request
* @param command form object with request parameters bound onto it
* @param errors validation errors holder
* @param page current wizard page
* @return a Map with reference data entries, or <code>null</code> if none
* @throws Exception in case of invalid state or arguments
* @see #referenceData(HttpServletRequest, int)
* @see ModelAndView
*/
protected Map referenceData(HttpServletRequest request, Object command, Errors errors, int page)
throws Exception {
return referenceData(request, page);
}
/**
* Create a reference data map for the given request, consisting of
* bean name/bean instance pairs as expected by ModelAndView.
* <p>The default implementation returns <code>null</code>.
* Subclasses can override this to set reference data used in the view.
* @param request current HTTP request
* @param page current wizard page
* @return a Map with reference data entries, or <code>null</code> if none
* @throws Exception in case of invalid state or arguments
* @see ModelAndView
*/
protected Map referenceData(HttpServletRequest request, int page) throws Exception {
return null;
}
/**
* Show the first page as form view.
* <p>This can be overridden in subclasses, e.g. to prepare wizard-specific
* error views in case of an Exception.
*/
protected ModelAndView showForm(
HttpServletRequest request, HttpServletResponse response, BindException errors)
throws Exception {
return showPage(request, errors, getInitialPage(request, errors.getTarget()));
}
/**
* Prepare the form model and view, including reference and error data,
* for the given page. Can be used in {@link #processFinish} implementations,
* to show the corresponding page in case of validation errors.
* @param request current HTTP request
* @param errors validation errors holder
* @param page number of page to show
* @return the prepared form view
* @throws Exception in case of invalid state or arguments
*/
protected final ModelAndView showPage(HttpServletRequest request, BindException errors, int page)
throws Exception {
if (page >= 0 && page < getPageCount(request, errors.getTarget())) {
if (logger.isDebugEnabled()) {
logger.debug("Showing wizard page " + page + " for form bean '" + getCommandName() + "'");
}
// Set page session attribute, expose overriding request attribute.
Integer pageInteger = new Integer(page);
String pageAttrName = getPageSessionAttributeName(request);
if (isSessionForm()) {
if (logger.isDebugEnabled()) {
logger.debug("Setting page session attribute [" + pageAttrName + "] to: " + pageInteger);
}
request.getSession().setAttribute(pageAttrName, pageInteger);
}
request.setAttribute(pageAttrName, pageInteger);
// Set page request attribute for evaluation by views.
Map controlModel = new HashMap();
if (this.pageAttribute != null) {
controlModel.put(this.pageAttribute, new Integer(page));
}
String viewName = getViewName(request, errors.getTarget(), page);
return showForm(request, errors, viewName, controlModel);
}
else {
throw new ServletException("Invalid wizard page number: " + page);
}
}
/**
* Return the page count for this wizard form controller.
* The default implementation delegates to {@link #getPageCount()}.
* <p>Can be overridden to dynamically adapt the page count.
* @param request current HTTP request
* @param command the command object as returned by formBackingObject
* @return the current page count
* @see #getPageCount
*/
protected int getPageCount(HttpServletRequest request, Object command) {
return getPageCount();
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -