在Spring Boot应用中,数据绑定是一个至关重要的环节,它负责将HTTP请求中的参数映射到控制器方法的入参对象上。在这个过程中如果遇到任何问题,如参数缺失、类型不匹配或验证失败等,Spring MVC将会抛出一个org.springframework.validation.BindException
异常。本文将深入解析BindException
异常的原因和处理方式。
BindException
通常与数据绑定和参数校验紧密相关。当用户通过HTTP请求向服务器发送数据时,Spring MVC框架会尝试自动将这些请求参数绑定到控制器方法的入参对象上。如果在这个过程中发生以下情况,就可能引发BindException
异常:
本段所说的 请求参数,均指的是控制器方法的入参对象的属性。
@NotBlank
但未接收到对应的请求参数,则会触发BindException
异常。@Valid
注解配合自定义验证器进行参数校验时,如果验证失败,同样会抛出BindException
异常。在Spring Boot应用中,我们可以利用@ExceptionHandler
注解来捕获并处理BindException
异常,如下所示的代码片段提供了一种通用的异常处理策略:
/**
* 参数校验异常:对象参数校验。
*/
@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Result<Void> handleException(BindException e, HandlerMethod handlerMethod) {
logInfo(e, handlerMethod);
List<FieldError> fieldErrors = e.getFieldErrors();
String userMessage = UserTipGenerator.getUserMessage(fieldErrors);
String errorMessageCore = ErrorMessageGenerator.getErrorMessage(fieldErrors);
String errorMessage = String.format("【参数校验异常】(错误数量:%s):%s", e.getErrorCount(), errorMessageCore);
return Result.fail(userMessage, String.valueOf(HttpStatus.BAD_REQUEST.value()), errorMessage);
}
上述代码中,当出现BindException
异常时,系统将返回一个状态码为400(Bad Request)的结果,并附带详细的错误信息,包括哪个字段校验失败以及失败原因。
详细代码,请参考后面的参考文章《SpringBoot 全局异常统一处理(AOP):@RestControllerAdvice + @ExceptionHandler + @ResponseStatus》
假设我们有一个新增用户的接口,其中入参要求不能为空:
@PostMapping("users")
@Operation(summary = "新增用户")
public void addUser(@Valid @RequestBody UserAddParam param) {
log.info("测试:新增用户,Post请求。param={}", param);
}
package com.example.web.response.model.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
@Schema(name = "新增用户Param")
public class UserAddParam {
@NotBlank(message = "姓名,不能为空")
@Schema(description = "姓名", example = "张三")
private String name;
// ...
}
一下两种情况,会导致出现数据格式异常:
NumberFormatException
。 @GetMapping(path = "users")
@Operation(summary = "查询用户列表", description = "测试:BindException。参数校验异常:Get请求,Query参数,以对象的形式接收。")
public List<UserVO> listUsers(@Valid UserQuery userQuery, PageQuery pageQuery,
HttpServletRequest request, HttpServletResponse response, HttpSession session) {
log.info("查询用户列表。userQuery={},pageQuery={}", userQuery, pageQuery);
// 业务代码...
}
package com.example.core.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springdoc.api.annotations.ParameterObject;
@Data
@ParameterObject
@Schema(name = "分页参数Query")
public class PageQuery {
@Schema(description = "当前页码", type = "Integer", defaultValue = "1", example = "1", minimum = "1")
private Integer pageNumber = 1;
@Schema(description = "每 1 页的数据量", type = "Integer", defaultValue = "10", example = "10", minimum = "1", maximum = "100")
private Integer pageSize = 10;
}
参考相关专栏:《SpringBoot - 接口参数校验》
在没有处理BindException
的情况下,如果客户端提交了缺少必要参数的请求,服务端将返回包含错误信息的标准HTTP响应,并在控制台打印详细的错误日志。而经过上述异常处理器处理后,客户端接收到的响应将以更友好的格式呈现错误详情,便于快速定位和修复问题。
通过适当地处理BindException
异常,不仅可以提升应用的健壮性,还能优化用户体验,使得API接口的错误反馈更加清晰明确。
SpringBoot 全局异常统一处理(AOP):@RestControllerAdvice + @ExceptionHandler + @ResponseStatus