🔍 一、BindingResult 是什么?

BindingResult 是 Spring MVC 中用于 接收参数绑定(Data Binding)与校验(Validation)结果 的对象。

当你使用:

  • @Valid
  • @Validated
  • @ModelAttribute
  • 表单对象 Form / DTO

时,Spring 会自动进行 类型转换参数校验。而校验错误、类型转换异常等都会被放入 BindingResult 中。

它属于:

org.springframework.validation.BindingResult

🔧 二、BindingResult 解决了什么问题?

通常,如果参数校验失败,Spring 会直接抛出异常(如 MethodArgumentNotValidException),导致请求终止。

但:

👉 只要在校验对象后面紧跟一个 BindingResult 参数,Spring 就不会抛异常,而是把错误放到 BindingResult 中,让你自己处理。

即:

public String doSomething(@Valid UserForm form, BindingResult result)

📌 规则:BindingResult 必须紧跟在 @Valid/@Validated 参数后面,否则无效。


🧩 三、BindingResult 内部都存什么?

主要包含三类信息:

内容类型 示例 含义
FieldError username 字段不能为空 字段级错误
ObjectError 整个对象不合法 对象级错误
类型转换异常 age=abc 表单值类型转换失败

常用方法:

result.hasErrors();             // 是否有校验错误
result.getAllErrors();          // 获取全部错误 (包含 FieldError 和 ObjectError)
result.getFieldErrors();        // 字段级错误
result.getFieldError("name");   // 某个字段的错误
result.rejectValue(...);        // 手动添加错误

🧪 四、使用示例

✔️ 1. 表单对象(DTO)

@Data
public class UserForm {
    @NotBlank(message = "用户名不能为空")
    private String username;

    @Min(value = 1, message = "年龄必须大于 0")
    private Integer age;
}

✔️ 2. Controller 使用 BindingResult

@PostMapping("/user/add")
public String addUser(@Valid UserForm form, BindingResult bindingResult) {

    if (bindingResult.hasErrors()) {
        // 返回所有错误
        return bindingResult.getAllErrors().toString();
    }

    return "Success";
}

⚙️ 五、没有 BindingResult 会怎样?

@PostMapping("/user/add")
public String addUser(@Valid UserForm form) {
    return "OK";
}

此时校验失败会:

❌ 直接抛异常
❌ Controller 不会执行
❌ 你无法自定义错误返回

但使用 BindingResult:

✔️ 不抛异常
✔️ 你控制错误返回逻辑


🧠 六、常见错误与注意点

⚠️ 1. BindingResult 必须紧跟校验对象后面

❌ 错误示例:

public void test(String a, @Valid UserForm form, String b, BindingResult r)

✔️ 正确:

public void test(String a, @Valid UserForm form, BindingResult r, String b)

⚠️ 2. @RequestBody + BindingResult 也可使用

如果是 JSON 请求:

@PostMapping("/json")
public Object testJson(@Valid @RequestBody UserForm form, BindingResult r) {
    if (r.hasErrors()) {
        return r.getAllErrors();
    }
    return "ok";
}

但需注意某些版本中,@RequestBody 类型转换错误不会进入 BindingResult。


⚠️ 3. 手动添加错误

bindingResult.rejectValue("username", "error", "用户名已存在");

🧱 七、BindingResult 与 Errors 的关系

BindingResult 实际上是 Errors 的子接口。

Errors → BindingResult

BindingResult 更具体,用于绑定表单/对象的验证结果。


📌 八、总结

功能 描述
作用 保存参数绑定和校验的错误信息
避免异常 有它就不会抛出校验异常
获取错误 getAllErrors / getFieldErrors
使用条件 必须紧跟校验的参数后面

一句话:

BindingResult 是 Spring MVC 校验体系的核心,用来接收所有参数绑定和校验错误,让你可以自定义错误处理。


如果你需要,我还可以给你:

✅ BindingResult + 前端表单校验示例
✅ BindingResult + 全局异常处理(@ControllerAdvice)对比
✅ BindingResult 常见坑分析
✅ 实战代码模板