数据绑定器
@Controller
或@ControllerAdvice
类可以拥有@InitBinder
方法来初始化WebDataBinder
实例,这些实例可以:
-
将请求参数绑定到模型对象。
-
将请求值从字符串转换为对象属性类型。
-
在呈现HTML表单时将模型对象属性格式化为字符串。
在@Controller
中,DataBinder
的自定义应用范围仅限于控制器内部,甚至可以应用于通过注解引用的特定模型属性的名称。在@ControllerAdvice
中,自定义可以应用于所有或部分控制器。
您可以在DataBinder
中注册PropertyEditor
、Converter
和Formatter
组件进行类型转换。或者,您可以使用WebFlux配置在全局共享的FormattingConversionService
中注册Converter
和Formatter
组件。
-
Java
-
Kotlin
@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));
}
// ...
}
1 | 使用@InitBinder 注解。 |
@Controller
class FormController {
@InitBinder (1)
fun initBinder(binder: WebDataBinder) {
val dateFormat = SimpleDateFormat("yyyy-MM-dd")
dateFormat.isLenient = false
binder.registerCustomEditor(Date::class.java, CustomDateEditor(dateFormat, false))
}
// ...
}
1 | 使用@InitBinder 注解。 |
或者,当通过共享的FormattingConversionService
使用基于Formatter
的设置时,您可以重用相同的方法并注册特定于控制器的Formatter
实例,如下例所示:
-
Java
-
Kotlin
@Controller
public class FormController {
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd")); (1)
}
// ...
}
1 | 添加自定义格式化程序(在本例中为DateFormatter )。 |
@Controller
class FormController {
@InitBinder
fun initBinder(binder: WebDataBinder) {
binder.addCustomFormatter(DateFormatter("yyyy-MM-dd")) (1)
}
// ...
}
1 | 添加自定义格式化程序(在本例中为DateFormatter )。 |
模型设计
Web请求的数据绑定涉及将请求参数绑定到模型对象。默认情况下,请求参数可以绑定到模型对象的任何公共属性,这意味着恶意客户端可以为模型对象图中存在但不希望设置的属性提供额外值。这就是为什么模型对象设计需要仔细考虑。
模型对象及其嵌套对象图有时也被称为命令对象、表单后备对象或POJO(普通的旧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
模式(不区分大小写)。但是,“允许”配置优于“不允许”,因为它更明确,更不容易出错。
@InitBinder
方法在控制器内部或通过
@ControllerAdvice
全局设置
WebDataBinder
上的
declarativeBinding
标志。打开此标志可以确保仅使用构造函数绑定,并且除非配置了
allowedFields
模式,否则不使用属性绑定。例如:
@Controller
public class MyController {
@InitBinder
void initBinder(WebDataBinder binder) {
binder.setDeclarativeBinding(true);
}
// @RequestMapping methods, etc.
}