databinder.java
来自「有关此类编程有心德的高手 希望能够多多给予指教」· Java 代码 · 共 559 行 · 第 1/2 页
JAVA
559 行
/*
* 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.validation;
import java.beans.PropertyEditor;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.ConfigurablePropertyAccessor;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessException;
import org.springframework.beans.PropertyAccessorUtils;
import org.springframework.beans.PropertyBatchUpdateException;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.PatternMatchUtils;
import org.springframework.util.StringUtils;
/**
* Binder that allows for setting property values onto a target object,
* including support for validation and binding result analysis.
* The binding process can be customized through specifying allowed fields,
* required fields, custom editors, etc.
*
* <p>Note that there are potential security implications in failing to set an array
* of allowed fields. In the case of HTTP form POST data for example, malicious clients
* can attempt to subvert an application by supplying values for fields or properties
* that do not exist on the form. In some cases this could lead to illegal data being
* set on command objects <i>or their nested objects</i>. For this reason, it is
* <b>highly recommended to specify the {@link #setAllowedFields allowedFields} property</b>
* on the DataBinder.
*
* <p>The binding results can be examined via the {@link BindingResult} interface,
* extending the {@link Errors} interface: see the {@link #getBindingResult()} method.
* Missing fields and property access exceptions will be converted to {@link FieldError FieldErrors},
* collected in the Errors instance, using the following error codes:
*
* <ul>
* <li>Missing field error: "required"
* <li>Type mismatch error: "typeMismatch"
* <li>Method invocation error: "methodInvocation"
* </ul>
*
* <p>By default, binding errors get resolved through the {@link BindingErrorProcessor}
* strategy, processing for missing fields and property access exceptions: see the
* {@link #setBindingErrorProcessor} method. You can override the default strategy
* if needed, for example to generate different error codes.
*
* <p>Custom validation errors can be added afterwards. You will typically want to resolve
* such error codes into proper user-visible error messages; this can be achieved through
* resolving each error via a {@link org.springframework.context.MessageSource}, which is
* able to resolve an {@link ObjectError}/{@link FieldError} through its
* {@link org.springframework.context.MessageSource#getMessage(org.springframework.context.MessageSourceResolvable, java.util.Locale)}
* method. The list of message codes can be customized through the {@link MessageCodesResolver}
* strategy: see the {@link #setMessageCodesResolver} method. {@link DefaultMessageCodesResolver}'s
* javadoc states details on the default resolution rules.
*
* <p>This generic data binder can be used in any kind of environment.
* It is typically used by Spring web MVC controllers, via the web-specific
* subclasses {@link org.springframework.web.bind.ServletRequestDataBinder}
* and {@link org.springframework.web.portlet.bind.PortletRequestDataBinder}.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Rob Harrop
* @see #setAllowedFields
* @see #setRequiredFields
* @see #registerCustomEditor
* @see #setMessageCodesResolver
* @see #setBindingErrorProcessor
* @see #bind
* @see #getBindingResult
* @see DefaultMessageCodesResolver
* @see DefaultBindingErrorProcessor
* @see org.springframework.context.MessageSource
* @see org.springframework.web.bind.ServletRequestDataBinder
*/
public class DataBinder implements PropertyEditorRegistry {
/** Default object name used for binding: "target" */
public static final String DEFAULT_OBJECT_NAME = "target";
/**
* We'll create a lot of DataBinder instances: Let's use a static logger.
*/
protected static final Log logger = LogFactory.getLog(DataBinder.class);
private final Object target;
private final String objectName;
private AbstractPropertyBindingResult bindingResult;
private BindException bindException;
private boolean ignoreUnknownFields = true;
private boolean ignoreInvalidFields = false;
private String[] allowedFields;
private String[] disallowedFields;
private String[] requiredFields;
private BindingErrorProcessor bindingErrorProcessor = new DefaultBindingErrorProcessor();
/**
* Create a new DataBinder instance, with default object name.
* @param target target object to bind onto
* @see #DEFAULT_OBJECT_NAME
*/
public DataBinder(Object target) {
this(target, DEFAULT_OBJECT_NAME);
}
/**
* Create a new DataBinder instance.
* @param target target object to bind onto
* @param objectName name of the target object
*/
public DataBinder(Object target, String objectName) {
Assert.notNull(target, "Target must not be null");
this.target = target;
this.objectName = objectName;
}
/**
* Return the wrapped target object.
*/
public Object getTarget() {
return this.target;
}
/**
* Return the name of the bound object.
*/
public String getObjectName() {
return this.objectName;
}
/**
* Initialize standard JavaBean property access for this DataBinder.
* <p>This is the default; an explicit call just leads to eager initialization.
* @see #initDirectFieldAccess()
*/
public void initBeanPropertyAccess() {
Assert.isNull(this.bindingResult,
"DataBinder is already initialized - call initBeanPropertyAccess before any other configuration methods");
this.bindingResult = new BeanPropertyBindingResult(getTarget(), getObjectName());
}
/**
* Initialize direct field access for this DataBinder,
* as alternative to the default bean property access.
* @see #initBeanPropertyAccess()
*/
public void initDirectFieldAccess() {
Assert.isNull(this.bindingResult,
"DataBinder is already initialized - call initDirectFieldAccess before any other configuration methods");
this.bindingResult = new DirectFieldBindingResult(getTarget(), getObjectName());
}
/**
* Return the internal BindingResult held by this DataBinder,
* as AbstractPropertyBindingResult.
*/
protected AbstractPropertyBindingResult getInternalBindingResult() {
if (this.bindingResult == null) {
initBeanPropertyAccess();
}
return this.bindingResult;
}
/**
* Return the underlying PropertyAccessor of this binder's BindingResult.
* To be used by binder subclasses that need property checks.
*/
protected ConfigurablePropertyAccessor getPropertyAccessor() {
return getInternalBindingResult().getPropertyAccessor();
}
/**
* Return the BindingResult instance created by this DataBinder.
* This allows for convenient access to the binding results after
* a bind operation.
* @return the BindingResult instance, to be treated as BindingResult
* or as Errors instance (Errors is a super-interface of BindingResult)
* @see Errors
* @see #bind
*/
public BindingResult getBindingResult() {
return getInternalBindingResult();
}
/**
* Return the Errors instance for this data binder.
* @return the Errors instance, to be treated as Errors or as BindException
* @deprecated in favor of {@link #getBindingResult()}.
* Use the {@link BindException#BindException(BindingResult)} constructor
* to create a BindException instance if still needed.
* @see #getBindingResult()
*/
public BindException getErrors() {
if (this.bindException == null) {
this.bindException = new BindException(getBindingResult());
}
return this.bindException;
}
/**
* Set whether to ignore unknown fields, that is, whether to ignore bind
* parameters that do not have corresponding fields in the target object.
* <p>Default is "true". Turn this off to enforce that all bind parameters
* must have a matching field in the target object.
* <p>Note that this setting only applies to <i>binding</i> operations
* on this DataBinder, not to <i>retrieving</i> values via its
* {@link #getBindingResult() BindingResult}.
* @see #bind
*/
public void setIgnoreUnknownFields(boolean ignoreUnknownFields) {
this.ignoreUnknownFields = ignoreUnknownFields;
}
/**
* Return whether to ignore unknown fields when binding.
*/
public boolean isIgnoreUnknownFields() {
return this.ignoreUnknownFields;
}
/**
* Set whether to ignore invalid fields, that is, whether to ignore bind
* parameters that have corresponding fields in the target object which are
* not accessible (for example because of null values in the nested path).
* <p>Default is "false". Turn this on to ignore bind parameters for
* nested objects in non-existing parts of the target object graph.
* <p>Note that this setting only applies to <i>binding</i> operations
* on this DataBinder, not to <i>retrieving</i> values via its
* {@link #getBindingResult() BindingResult}.
* @see #bind
*/
public void setIgnoreInvalidFields(boolean ignoreInvalidFields) {
this.ignoreInvalidFields = ignoreInvalidFields;
}
/**
* Return whether to ignore invalid fields when binding.
*/
public boolean isIgnoreInvalidFields() {
return this.ignoreInvalidFields;
}
/**
* Register fields that should be allowed for binding. Default is all
* fields. Restrict this for example to avoid unwanted modifications
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?