对于最新的稳定版本,请使用 Spring Framework 6.2.0! |
DataBinder
@Controller
或@ControllerAdvice
类可以具有@InitBinder
方法
初始化 的实例WebDataBinder
,而这些 API 又可以:
-
将请求参数(即表单或查询数据)绑定到模型对象。
-
转换基于 String 的请求值(例如请求参数、路径变量、 headers、cookie 等)传递给 controller 方法参数的目标类型。
-
将模型对象值格式化为
String
值。
@InitBinder
方法可以注册特定于控制器的java.beans.PropertyEditor
或
SpringConverter
和Formatter
组件。此外,您还可以使用 MVC 配置来注册Converter
和Formatter
全局共享FormattingConversionService
.
@InitBinder
方法支持许多相同的参数@RequestMapping
方法
do 的@ModelAttribute
(command 对象) 参数。通常,它们被声明
替换为WebDataBinder
参数(用于注册)和void
返回值。
下面的清单显示了一个示例:
-
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 方法。 |
或者,当您使用Formatter
的设置,通过共享的FormattingConversionService
,您可以重复使用相同的方法并注册
控制器特定Formatter
implementations,如下例所示:
-
Java
-
Kotlin
@Controller
public class FormController {
@InitBinder (1)
protected void initBinder(WebDataBinder binder) {
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
// ...
}
1 | 定义@InitBinder 方法。 |
@Controller
class FormController {
@InitBinder (1)
protected fun initBinder(binder: WebDataBinder) {
binder.addCustomFormatter(DateFormatter("yyyy-MM-dd"))
}
// ...
}
1 | 定义@InitBinder 方法。 |
模型设计
在 Web 应用程序的上下文中,数据绑定涉及 HTTP 请求的绑定 parameters ((即表单数据或查询参数) ) 添加到模型对象中的属性,以及 其嵌套对象。
只public
遵循 JavaBeans 命名约定的属性将公开用于数据绑定,例如public String getFirstName()
和public void setFirstName(String)
方法firstName
财产。
模型对象及其嵌套对象图有时也称为命令对象、表单支持对象或 POJO (Plain Old Java Object)。 |
默认情况下, Spring 允许绑定到模型对象图中的所有公共属性。 这意味着您需要仔细考虑模型具有哪些公共属性,因为 客户端可以面向任何公共属性路径,甚至是一些不需要的公共属性路径 针对给定的使用案例。
例如,给定一个 HTTP 表单数据端点,恶意客户端可能会提供 存在于模型对象图中但不属于 HTML 表单的属性 在浏览器中显示。这可能会导致在模型对象上设置数据,并且任何 的嵌套对象中。
推荐的方法是使用仅公开
与表单提交相关的属性。例如,在用于更改
用户的电子邮件地址,则 Model 对象应声明一组最小属性,例如
如下所示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;
}
}
如果您不能或不想为每个数据使用专用模型对象
binding 用例中,您必须限制允许进行数据绑定的属性。
理想情况下,您可以通过setAllowedFields()
method 开启WebDataBinder
.
例如,要在应用程序中注册允许的字段模式,您可以实现@InitBinder
方法中的@Controller
或@ControllerAdvice
组件,如下所示:
@Controller
public class ChangeEmailController {
@InitBinder
void initBinder(WebDataBinder binder) {
binder.setAllowedFields("oldEmailAddress", "newEmailAddress");
}
// @RequestMapping methods, etc.
}
除了注册允许的模式外,还可以注册不允许的
字段模式通过setDisallowedFields()
method 中DataBinder
及其子类。
但请注意,“允许列表”比“拒绝列表”更安全。因此setAllowedFields()
应该被青睐setDisallowedFields()
.
请注意,与允许的字段模式匹配区分大小写;鉴于匹配 Against Disallowed 字段模式不区分大小写。此外,匹配 不允许的模式将不被接受,即使它也恰好与 允许列表。
正确配置允许和不允许的字段模式非常重要 直接公开域模型以进行数据绑定时。否则,它是一个 安全风险大。 此外,强烈建议您不要使用域中的类型 模型(如 JPA 或 Hibernate 实体)作为数据绑定场景中的模型对象。 |