跳到主要内容

@InitBinder

DeepSeek V3 中英对照 @InitBinder @InitBinder

@Controller@ControllerAdvice 类可以包含 @InitBinder 方法,用于初始化 WebDataBinder 实例,这些实例可以:

  • 将请求参数绑定到模型对象。

  • 将请求值从字符串转换为对象属性类型。

  • 在渲染 HTML 表单时,将模型对象属性格式化为字符串。

@Controller 中,DataBinder 的自定义设置仅适用于该控制器内部,甚至可以通过注解按名称引用特定的模型属性。而在 @ControllerAdvice 中,自定义设置可以应用于所有控制器或其中的一部分。

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

@InitBinder 方法可以拥有与 @RequestMapping 方法相同的许多参数,但显著的例外是 @ModelAttribute。通常,这些方法会有一个 WebDataBinder 参数(用于注册)和一个 void 返回值,例如:

@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));
}

// ...
}
java
  • 定义一个 @InitBinder 方法。

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

@Controller
public class FormController {

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

// ...
}
java
  • 在自定义格式化器上定义一个 @InitBinder 方法。

模型设计

数据绑定 用于 Web 请求时,涉及将请求参数绑定到模型对象。默认情况下,请求参数可以绑定到模型对象的任何公共属性,这意味着恶意客户端可以为模型对象图中存在但不期望设置的属性提供额外的值。这就是为什么模型对象的设计需要仔细考虑。

提示

模型对象及其嵌套的对象图有时也被称为 命令对象表单支持对象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;
}

}
java

另一个好的实践是应用构造函数绑定,它仅使用构造函数参数所需的请求参数,而忽略其他任何输入。这与属性绑定形成对比,后者默认情况下会绑定每个具有匹配属性的请求参数。

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

@Controller
public class ChangeEmailController {

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

// @RequestMapping methods, etc.

}
java

你也可以注册 disallowedFields 模式(不区分大小写)。然而,更推荐使用“允许”配置,因为它更为明确且不易出错。

默认情况下,构造函数绑定和属性绑定都会被使用。如果你只想使用构造函数绑定,可以通过在控制器内部的 @InitBinder 方法或在全局范围内通过 @ControllerAdvice 设置 WebDataBinderdeclarativeBinding 标志。启用此标志后,确保仅使用构造函数绑定,并且除非配置了 allowedFields 模式,否则不会使用属性绑定。例如:

@Controller
public class MyController {

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

// @RequestMapping methods, etc.

}
java