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

📄 formaction.java

📁 spring的WEB开发插件,支持多状态WEB开发
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
		return binder.getErrors().hasErrors() ? error() : success();
	}
	
	/**
	 * Resets the form by clearing out the form object in the specified scope and
	 * reloading it by calling loadFormObject.
	 * @param context the request context
	 * @return "success" if the reset action completed successfully, "error" otherwise
	 * @throws Exception if an exception occured
	 */
	public Event resetForm(RequestContext context) throws Exception {
		try {
			Object formObject = loadFormObject(context);
			setFormObject(context, formObject);
			setFormErrors(context, createFormErrors(context, formObject));
			return success();
		}
		catch (FormObjectRetrievalFailureException e) {
			// handle retrieval exceptions only, other exceptions propagate
			return error(e);
		}
	}

	// internal helpers
	
	/**
	 * Create a new binder instance for the given form object and request
	 * context. Can be overridden to plug in custom DataBinder subclasses.
	 * <p>
	 * Default implementation creates a standard WebDataBinder, and invokes
	 * initBinder. Note that initBinder will not be invoked if you override this
	 * method!
	 * @param context the action execution context, for accessing and setting
	 *        data in "flow scope" or "request scope"
	 * @param formObject the form object to bind onto
	 * @return the new binder instance
	 * @see #initBinder(RequestContext, DataBinder)
	 */
	protected DataBinder createBinder(RequestContext context, Object formObject) {
		DataBinder binder = new WebDataBinder(formObject, getFormObjectName());
		if (this.messageCodesResolver != null) {
			binder.setMessageCodesResolver(this.messageCodesResolver);
		}
		initBinder(context, binder);
		return binder;
	}

	/**
	 * Bind parameters of the last event in given context to the form object
	 * using given binder.
	 * @param context the action execution context, for accessing and setting
	 *        data in "flow scope" or "request scope"
	 * @param binder the data binder to use
	 */
	protected void doBind(RequestContext context, DataBinder binder) throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug(
					"Binding allowed parameters in event: " + context.getLastEvent()
					+ " to form object with name: '" + binder.getObjectName()
					+ "', prebind-toString: " + binder.getTarget());
			if (binder.getAllowedFields() != null && binder.getAllowedFields().length > 0) {
				logger.debug("(Allowed event parameters are: " + binder.getAllowedFields() + ")");
			}
			else {
				logger.debug("(Any event parameter is allowed)");
			}
		}
		binder.bind(new MutablePropertyValues(context.getLastEvent().getParameters()));
		if (logger.isDebugEnabled()) {
			logger.debug("Binding completed for form object with name: '" + binder.getObjectName() + "', postbind-toString: " + binder.getTarget());
			logger.debug("There are [" + binder.getErrors().getErrorCount() + "] errors, details: " + binder.getErrors().getAllErrors());
		}
	}
	
	/**
	 * Validate given form object using a registered validator. If a "validatorMethod"
	 * action property is specified for the currently executing action,
	 * the identified validator method will be invoked. When no such property is found,
	 * the defualt <code>validate()</code> method is invoked.
	 * @param context the action execution context, for accessing and setting
	 *        data in "flow scope" or "request scope"
	 * @param binder the data binder to use
	 */
	protected void doValidate(RequestContext context, DataBinder binder) throws Exception {
		String validatorMethod = (String)context.getProperties().getAttribute(VALIDATOR_METHOD_PROPERTY);
		if (StringUtils.hasText(validatorMethod)) {
			invokeValidatorMethod(validatorMethod, binder.getTarget(), binder.getErrors());
		}
		else {
			Assert.notNull(validator, "The validator must not be null but it is: programmer error");
			if (logger.isDebugEnabled()) {
				logger.debug("Invoking validator: " + validator);
			}
			getValidator().validate(binder.getTarget(), binder.getErrors());
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Validation completed for form object with name: '" + binder.getObjectName() + "'");
			logger.debug("There are [" + binder.getErrors().getErrorCount() + "] errors, details: " + binder.getErrors().getAllErrors());
		}
	}

	/**
	 * Invoke specified validator method on the validator registered with this
	 * action.
	 * @param validatorMethod the name of the validator method to invoke
	 * @param formObject the form object
	 * @param errors possible binding errors
	 */
	private void invokeValidatorMethod(String validatorMethod, Object formObject, Errors errors) throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("Invoking piecemeal validator method: '" + validatorMethod + "' on form object: " + formObject);
		}
		getValidateMethodDispatcher().dispatch(validatorMethod, new Object[] { formObject, errors });
	}
	
	/**
	 * Convenience method that returns the form object for this form action.
	 * If not found in the configured scope, a new form object will be created
	 * or loaded by a call to {@link #loadFormObject(RequestContext)}.
	 * @param context the flow request context
	 * @return the form object
	 */
	protected Object getFormObject(RequestContext context) throws Exception {
		Object formObject = getFormObjectAccessor(context).getFormObject(getFormObjectName(), getFormObjectClass(), getFormObjectScope());
		if (formObject == null) {
			formObject = loadFormObject(context);
		}
		return formObject;
	}

	/**
	 * Put given form object in the configured scope of given context.
	 */
	private void setFormObject(RequestContext context, Object formObject) {
		getFormObjectAccessor(context).setFormObject(formObject, getFormObjectName(), getFormObjectScope());
	}
	
	/**
	 * Convenience method that returns the form object errors for this form action.
	 * If not found in the configured scope, a new form object errors will be created.
	 * @param context the flow request context
	 * @return the form errors
	 */
	protected Errors getFormErrors(RequestContext context) throws Exception {
		return ensureFormErrorsExposed(context, getFormObject(context));
	}

	/**
	 * Expose an empty errors collection in the model of the currently executing flow if neccessary.
	 * @param context the flow execution request context
	 * @param errors the errors
	 */
	private Errors ensureFormErrorsExposed(RequestContext context, Object formObject) {
		Errors errors = getFormObjectAccessor(context).getFormErrors(getFormObjectName(), getFormErrorsScope());
		if (errors instanceof BindException) {
			// make sure the existing form errors are consistent with the form object
			BindException be = (BindException)errors;
			if (be.getTarget() != formObject) {
				if (logger.isInfoEnabled()) {
					logger.info(
							"Inconsistency detected: the Errors instance in '" + getFormErrorsScope() + "' does NOT wrap the current form object: " 
							+ formObject + " of class: " + formObject.getClass() + "; instead this Errors instance unexpectedly wraps the target object: " 
							+ be.getTarget() + " of class: " + be.getTarget().getClass() + 
							". [Taking corrective action: overwriting the existing Errors instance with an empty one for the current form object]");
				}
				// fall through below				
				errors = null;
			}
		}
		if (errors == null) {
			errors = createFormErrors(context, formObject);
			setFormErrors(context, errors);
		}
		return errors;
	}

	/**
	 * Return an empty errors collection with property editors registered.
	 * @param context the flow execution request context
	 * @param formObject the object
	 * @return the new errors instance
	 */
	private Errors createFormErrors(RequestContext context, Object formObject) {
		return createBinder(context, formObject).getErrors();
	}

	/**
	 * Put given errors instance in the configured scope of given context.
	 */
	private void setFormErrors(RequestContext context, Errors errors) {
		getFormObjectAccessor(context).setFormErrors(errors, getFormErrorsScope());
	}

	// subclassing hook methods
	
	/**
	 * Returns a dispatcher to invoke validation methods. Subclasses could
	 * override this to return a custom dispatcher.
	 */
	protected DispatchMethodInvoker getValidateMethodDispatcher() {
		return validateMethodDispatcher;
	}
	
	/**
	 * Factory method that returns a new form object accessor for accessing form objects 
	 * in the provided request context.
	 * @param context the flow request context
	 * @return the accessor
	 */
	protected FormObjectAccessor getFormObjectAccessor(RequestContext context) {
		return new FormObjectAccessor(context);
	}

	/**
	 * Load the backing form object that should be updated from incoming event
	 * parameters and validated. By default, will attempt to instantiate a new
	 * form object instance transiently in memory if not already present in the
	 * configured scope by calling {@link #createFormObject(RequestContext)}.
	 * <p>
	 * Subclasses should override if they need to load the form object from a
	 * specific location or resource such as a database or filesystem.
	 * @param context the action execution context, for accessing and setting
	 *        data in "flow scope" or "request scope"
	 * @return the form object
	 * @throws FormObjectRetrievalFailureException the form object could not be
	 *         loaded
	 */
	protected Object loadFormObject(RequestContext context) throws FormObjectRetrievalFailureException, Exception {
		return createFormObject(context);
	}

	/**
	 * Create a new form object by instantiating the configured form object class.
	 * @param context the action execution context, for accessing and setting
	 *        data in "flow scope" or "request scope"
	 * @return the form object
	 * @throws Exception the form object could not be created
	 */
	protected Object createFormObject(RequestContext context) throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating new form object '" + getFormObjectName() + "'");
		}
		if (this.formObjectClass == null) {
			throw new IllegalStateException("Cannot create form object without formObjectClass being set -- "
					+ "either set formObjectClass or override this method");
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Creating new form object of class [" + this.formObjectClass.getName() + "]");
		}
		return this.formObjectClass.newInstance();
	}
	
	/**
	 * Initialize the given binder instance, for example with custom editors.
	 * Called by createBinder().
	 * <p>
	 * This method allows you to register custom editors for certain fields of
	 * your form object. For instance, you will be able to transform Date
	 * objects into a String pattern and back, in order to allow your JavaBeans
	 * to have Date properties and still be able to set and display them in an
	 * HTML interface.
	 * <p>
	 * Default implementation will simply call registerCustomEditors on any
	 * propertyEditorRegistrar object that has been set for the action.
	 * <p>
	 * The request context may be used to feed reference data to any property
	 * editors, although it may be better (in the interest of not bloating the
	 * session, to have the editors get this from somewhere else).
	 * @param context the action execution context, for accessing and setting
	 *        data in "flow scope" or "request scope"
	 * @param binder new binder instance
	 * @see #createBinder(RequestContext, Object)
	 */
	protected void initBinder(RequestContext context, DataBinder binder) {
		if (propertyEditorRegistrar != null) {
			propertyEditorRegistrar.registerCustomEditors(binder);
		}
		else {
			if (logger.isDebugEnabled()) {
				logger.debug("No property editor registrar set, no custom editors to register");
			}
		}
	}
	
	/**
	 * Returns true if event parameters should be bound to the form object during
	 * the {@link #setupForm(RequestContext)} action. The default implementation just
	 * calls {@link #isBindOnSetupForm()}.
	 */
	protected boolean setupBindingEnabled(RequestContext context) {
		return isBindOnSetupForm();
	}

	/**
	 * Return whether validation should be performed given the state of the flow request
	 * context.
	 * <p>
	 * Default implementation always returns true. Can be overridden
	 * in subclasses to test validation, for example, if a special
	 * event parameter is set.
	 * @param context the request context, for accessing and setting
	 *        data in "flow scope" or "request scope"
	 * @return whether or not validation is enabled
	 */
	protected boolean validationEnabled(RequestContext context) {
		return true;
	}
}

⌨️ 快捷键说明

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