跳到主要内容
版本:7.0.3

DataBinder

Hunyuan 7b 中英对照 DataBinder DataBinder

@Controller@ControllerAdvice 类可以拥有 @InitBinder 方法来初始化 WebDataBinder 实例,这些实例进而可以:

  • 将请求参数绑定到模型对象上。
  • 将请求值从字符串转换为对象属性类型。
  • 在渲染HTML表单时,将模型对象属性格式化为字符串。

@Controller中,DataBinder的定制仅在控制器内部生效,或者仅适用于通过注解按名称引用的特定模型属性。而在@ControllerAdvice中,这些定制可以应用于所有控制器或其中的一部分控制器。

你可以在DataBinder中注册PropertyEditorConverterFormatter组件以进行类型转换。或者,你可以使用WebFlux配置在全局共享的FormattingConversionService中注册ConverterFormatter组件。

@Controller
public class FormController {

@InitBinder 1
public void initBinder(WebDataBinder binder) {
_simpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}

// ...
}
  • 使用 @InitBinder 注解。

或者,当通过共享的 FormattingConversionService 使用基于 Formatter 的设置时,您可以重用相同的方法,并注册特定于控制器的 Formatter 实例,如下例所示:

@Controller
public class FormController {

@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd")); 1
}

// ...
}
  • 添加自定义格式化器(本例中为 DateFormatter)。

模型设计

数据绑定 在Web请求中涉及将请求参数绑定到模型对象上。默认情况下,请求参数可以绑定到模型对象的任何公共属性上,这意味着恶意客户端可以为模型对象图中存在的但预期不会被设置的属性提供额外的值。因此,模型对象的设计需要慎重考虑。

提示

模型对象及其嵌套的对象图有时也被称为命令对象(command object)、表单支持对象(form-backing object),或POJO(Plain Old Java Object,普通老式Java对象)。

一个好的做法是使用专门的模型对象,而不是直接暴露你的领域模型(如JPA或Hibernate实体)来进行Web数据绑定。例如,在一个用于更改电子邮件地址的表单上,创建一个ChangeEmailForm模型对象,该对象仅声明输入所需的属性:

public class ChangeEmailForm {

private String oldEmailAddress;
private String newEmailAddress;

public void setOldEmailAddress(String oldEmailAddress) {
this.oldEmailAddress = oldEmailAddress;
}

public String getOldEmailAddress() {
return this.oldEmailAddress;
}

public void setNewEmailAddress(String newEmailAddress) {
this.newEmailAddress = newEmailAddress;
}

public String getNewEmailAddress() {
return this.newEmailAddress;
}

}

另一个良好的实践是采用构造函数绑定,该方法仅使用构造函数参数所需的请求参数,而忽略其他所有输入。这与属性绑定不同,后者默认会绑定每一个存在匹配属性的请求参数。

如果仅使用专用模型对象或构造函数绑定都不足以解决问题,而你必须使用属性绑定时,我们强烈建议在WebDataBinder上注册allowedFields模式(区分大小写),以防止设置意外的属性。例如:

@Controller
public class ChangeEmailController {

@InitBinder
void initBinder(WebDataBinder binder) {
binder.setAllowedFields("oldEmailAddress", "newEmailAddress");
}

// @RequestMapping methods, etc.

}

您还可以注册 disallowedFields 模式(不区分大小写)。然而,与 “disallowed” 配置相比,“allowed” 配置更明确,出错的概率也更低,因此更受青睐。

默认情况下,会同时使用构造函数绑定(constructor binding)和属性绑定(property binding)。如果你只想使用构造函数绑定,可以通过 @InitBinder 方法在控制器内部局部设置 declarativeBinding 标志,或者通过 @ControllerAdvice 在全局范围内进行设置。启用此标志可以确保只使用构造函数绑定,除非配置了 allowedFields 模式,否则不会使用属性绑定。例如:

@Controller
public class MyController {

@InitBinder
void initBinder(WebDataBinder binder) {
binder.setDeclarativeBinding(true);
}

// @RequestMapping methods, etc.

}