databinder.java
来自「有关此类编程有心德的高手 希望能够多多给予指教」· Java 代码 · 共 559 行 · 第 1/2 页
JAVA
559 行
* by malicious users when binding HTTP request parameters.
* <p>Supports "xxx*", "*xxx" and "*xxx*" patterns. More sophisticated matching
* can be implemented by overriding the <code>isAllowed</code> method.
* <p>Alternatively, specify a list of <i>disallowed</i> fields.
* @param allowedFields array of field names
* @see #setDisallowedFields
* @see #isAllowed(String)
* @see org.springframework.web.bind.ServletRequestDataBinder
*/
public void setAllowedFields(String[] allowedFields) {
this.allowedFields = PropertyAccessorUtils.canonicalPropertyNames(allowedFields);
}
/**
* Return the fields that should be allowed for binding.
* @return array of field names
*/
public String[] getAllowedFields() {
return this.allowedFields;
}
/**
* Register fields that should <i>not</i> be allowed for binding. Default is none.
* Mark fields as disallowed for example to avoid unwanted modifications
* by malicious users when binding HTTP request parameters.
* <p>Supports "xxx*", "*xxx" and "*xxx*" patterns. More sophisticated matching
* can be implemented by overriding the <code>isAllowed</code> method.
* <p>Alternatively, specify a list of <i>allowed</i> fields.
* @param disallowedFields array of field names
* @see #setAllowedFields
* @see #isAllowed(String)
* @see org.springframework.web.bind.ServletRequestDataBinder
*/
public void setDisallowedFields(String[] disallowedFields) {
this.disallowedFields = PropertyAccessorUtils.canonicalPropertyNames(disallowedFields);
}
/**
* Return the fields that should <i>not</i> be allowed for binding.
* @return array of field names
*/
public String[] getDisallowedFields() {
return this.disallowedFields;
}
/**
* Register fields that are required for each binding process.
* <p>If one of the specified fields is not contained in the list of
* incoming property values, a corresponding "missing field" error
* will be created, with error code "required" (by the default
* binding error processor).
* @param requiredFields array of field names
* @see #setBindingErrorProcessor
* @see DefaultBindingErrorProcessor#MISSING_FIELD_ERROR_CODE
*/
public void setRequiredFields(String[] requiredFields) {
this.requiredFields = PropertyAccessorUtils.canonicalPropertyNames(requiredFields);
if (logger.isDebugEnabled()) {
logger.debug("DataBinder requires binding of required fields [" +
StringUtils.arrayToCommaDelimitedString(requiredFields) + "]");
}
}
/**
* Return the fields that are required for each binding process.
* @return array of field names
*/
public String[] getRequiredFields() {
return this.requiredFields;
}
/**
* Set whether to extract the old field value when applying a
* property editor to a new value for a field.
* <p>Default is "true", exposing previous field values to custom editors.
* Turn this to "false" to avoid side effects caused by getters.
*/
public void setExtractOldValueForEditor(boolean extractOldValueForEditor) {
getPropertyAccessor().setExtractOldValueForEditor(extractOldValueForEditor);
}
public void registerCustomEditor(Class requiredType, PropertyEditor propertyEditor) {
getPropertyAccessor().registerCustomEditor(requiredType, propertyEditor);
}
public void registerCustomEditor(Class requiredType, String field, PropertyEditor propertyEditor) {
getPropertyAccessor().registerCustomEditor(requiredType, field, propertyEditor);
}
public PropertyEditor findCustomEditor(Class requiredType, String propertyPath) {
return getPropertyAccessor().findCustomEditor(requiredType, propertyPath);
}
/**
* Set the strategy to use for resolving errors into message codes.
* Applies the given strategy to the underlying errors holder.
* <p>Default is a DefaultMessageCodesResolver.
* @see BeanPropertyBindingResult#setMessageCodesResolver
* @see DefaultMessageCodesResolver
*/
public void setMessageCodesResolver(MessageCodesResolver messageCodesResolver) {
getInternalBindingResult().setMessageCodesResolver(messageCodesResolver);
}
/**
* Set the strategy to use for processing binding errors, that is,
* required field errors and <code>PropertyAccessException</code>s.
* <p>Default is a DefaultBindingErrorProcessor.
* @see DefaultBindingErrorProcessor
*/
public void setBindingErrorProcessor(BindingErrorProcessor bindingErrorProcessor) {
this.bindingErrorProcessor = bindingErrorProcessor;
}
/**
* Return the strategy for processing binding errors.
*/
public BindingErrorProcessor getBindingErrorProcessor() {
return bindingErrorProcessor;
}
/**
* Bind the given property values to this binder's target.
* <p>This call can create field errors, representing basic binding
* errors like a required field (code "required"), or type mismatch
* between value and bean property (code "typeMismatch").
* <p>Note that the given PropertyValues should be a throwaway instance:
* For efficiency, it will be modified to just contain allowed fields if it
* implements the MutablePropertyValues interface; else, an internal mutable
* copy will be created for this purpose. Pass in a copy of the PropertyValues
* if you want your original instance to stay unmodified in any case.
* @param pvs property values to bind
* @see #doBind(org.springframework.beans.MutablePropertyValues)
*/
public void bind(PropertyValues pvs) {
MutablePropertyValues mpvs = (pvs instanceof MutablePropertyValues) ?
(MutablePropertyValues) pvs : new MutablePropertyValues(pvs);
doBind(mpvs);
}
/**
* Actual implementation of the binding process, working with the
* passed-in MutablePropertyValues instance.
* @param mpvs the property values to bind,
* as MutablePropertyValues instance
* @see #checkAllowedFields
* @see #checkRequiredFields
* @see #applyPropertyValues
*/
protected void doBind(MutablePropertyValues mpvs) {
checkAllowedFields(mpvs);
checkRequiredFields(mpvs);
applyPropertyValues(mpvs);
}
/**
* Check the given property values against the allowed fields,
* removing values for fields that are not allowed.
* @param mpvs the property values to be bound (can be modified)
* @see #getAllowedFields
* @see #isAllowed(String)
*/
protected void checkAllowedFields(MutablePropertyValues mpvs) {
PropertyValue[] pvs = mpvs.getPropertyValues();
for (int i = 0; i < pvs.length; i++) {
PropertyValue pv = pvs[i];
String field = PropertyAccessorUtils.canonicalPropertyName(pv.getName());
if (!isAllowed(field)) {
mpvs.removePropertyValue(pv);
getBindingResult().recordSuppressedField(field);
if (logger.isDebugEnabled()) {
logger.debug("Field [" + field + "] has been removed from PropertyValues " +
"and will not be bound, because it has not been found in the list of allowed fields");
}
}
}
}
/**
* Return if the given field is allowed for binding.
* Invoked for each passed-in property value.
* <p>The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches,
* as well as direct equality, in the specified lists of allowed fields and
* disallowed fields. A field matching a disallowed pattern will not be accepted
* even if it also happens to match a pattern in the allowed list.
* <p>Can be overridden in subclasses.
* @param field the field to check
* @return if the field is allowed
* @see #setAllowedFields
* @see #setDisallowedFields
* @see org.springframework.util.PatternMatchUtils#simpleMatch(String, String)
*/
protected boolean isAllowed(String field) {
String[] allowed = getAllowedFields();
String[] disallowed = getDisallowedFields();
return ((ObjectUtils.isEmpty(allowed) || PatternMatchUtils.simpleMatch(allowed, field)) &&
(ObjectUtils.isEmpty(disallowed) || !PatternMatchUtils.simpleMatch(disallowed, field)));
}
/**
* Check the given property values against the required fields,
* generating missing field errors where appropriate.
* @param mpvs the property values to be bound (can be modified)
* @see #getRequiredFields
* @see #getBindingErrorProcessor
* @see BindingErrorProcessor#processMissingFieldError
*/
protected void checkRequiredFields(MutablePropertyValues mpvs) {
String[] requiredFields = getRequiredFields();
if (!ObjectUtils.isEmpty(requiredFields)) {
Map propertyValues = new HashMap();
PropertyValue[] pvs = mpvs.getPropertyValues();
for (int i = 0; i < pvs.length; i++) {
PropertyValue pv = pvs[i];
String canonicalName = PropertyAccessorUtils.canonicalPropertyName(pv.getName());
propertyValues.put(canonicalName, pv);
}
for (int i = 0; i < requiredFields.length; i++) {
String field = requiredFields[i];
PropertyValue pv = (PropertyValue) propertyValues.get(field);
if (pv == null || pv.getValue() == null ||
(pv.getValue() instanceof String && !StringUtils.hasText((String) pv.getValue()))) {
// Use bind error processor to create FieldError.
getBindingErrorProcessor().processMissingFieldError(field, getInternalBindingResult());
// Remove property from property values to bind:
// It has already caused a field error with a rejected value.
if (pv != null) {
mpvs.removePropertyValue(pv);
propertyValues.remove(field);
}
}
}
}
}
/**
* Apply given property values to the target object.
* <p>Default implementation applies all of the supplied property
* values as bean property values. By default, unknown fields will
* be ignored.
* @param mpvs the property values to be bound (can be modified)
* @see #getTarget
* @see #getPropertyAccessor
* @see #isIgnoreUnknownFields
* @see #getBindingErrorProcessor
* @see BindingErrorProcessor#processPropertyAccessException
*/
protected void applyPropertyValues(MutablePropertyValues mpvs) {
try {
// Bind request parameters onto target object.
getPropertyAccessor().setPropertyValues(mpvs, isIgnoreUnknownFields(), isIgnoreInvalidFields());
}
catch (PropertyBatchUpdateException ex) {
// Use bind error processor to create FieldErrors.
PropertyAccessException[] exs = ex.getPropertyAccessExceptions();
for (int i = 0; i < exs.length; i++) {
getBindingErrorProcessor().processPropertyAccessException(exs[i], getInternalBindingResult());
}
}
}
/**
* Close this DataBinder, which may result in throwing
* a BindException if it encountered any errors.
* @return the model Map, containing target object and Errors instance
* @throws BindException if there were any errors in the bind operation
* @see BindingResult#getModel()
*/
public Map close() throws BindException {
if (getBindingResult().hasErrors()) {
throw new BindException(getBindingResult());
}
return getBindingResult().getModel();
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?