Spring Boot Controller中Long类型id参数的空值校验问题
问题根源
Spring在调用Controller方法前会先执行参数绑定与类型转换,当路径变量为空字符串时,Spring尝试将其转为Long类型会直接抛出类型转换异常,此时@NotNull这类校验注解还未触发,所以你看不到校验效果。
可行的解决方案
方案1:先接收String类型再手动校验转换
将参数类型改为String,先校验非空,再转换为Long并处理格式错误:
@GetMapping("/{id}") public ResponseEntity<EmployeeResponse> getById(@PathVariable String id) { // 校验id非空 if (id == null || id.trim().isEmpty()) { throw new IllegalArgumentException("id不能为空"); } // 转换为Long并处理格式异常 Long longId; try { longId = Long.parseLong(id); } catch (NumberFormatException e) { throw new IllegalArgumentException("id必须是有效的数字"); } final EmployeeResponse response = employeeService.getById(longId); return ResponseEntity.ok(response); }
方案2:用正则约束路径变量格式
在路径上添加正则表达式,限制id必须是数字格式,非数字/空字符串的请求会直接不匹配该接口:
@GetMapping("/{id:\\d+}") public ResponseEntity<EmployeeResponse> getById(@PathVariable @NotNull Long id) { final EmployeeResponse response = employeeService.getById(id); return ResponseEntity.ok(response); }
注:这种方式下不符合格式的请求会返回404,若需要返回参数错误提示而非404,需配合全局异常处理器捕获NoHandlerFoundException自定义响应。
方案3:全局异常处理器捕获类型转换异常
保留原参数类型,通过全局异常处理器统一处理类型转换异常,返回友好提示:
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(TypeMismatchException.class) public ResponseEntity<String> handleTypeMismatch(TypeMismatchException e) { if (e.getRequiredType().equals(Long.class)) { return ResponseEntity.badRequest().body("id必须是有效的数字,且不能为空"); } return ResponseEntity.badRequest().body("参数格式错误"); } }
方案4:结合@Validated与全局异常处理
先在Controller或启动类上添加@Validated注解启用方法参数校验,再配合全局异常处理器同时处理校验异常和类型转换异常:
@RestController @Validated // 启用方法参数校验 public class EmployeeController { @GetMapping("/{id}") public ResponseEntity<EmployeeResponse> getById(@PathVariable @NotNull @Min(1) Long id) { final EmployeeResponse response = employeeService.getById(id); return ResponseEntity.ok(response); } }
对应的全局异常处理器:
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(TypeMismatchException.class) public ResponseEntity<String> handleTypeMismatch(TypeMismatchException e) { if (e.getRequiredType().equals(Long.class)) { return ResponseEntity.badRequest().body("id必须是有效的数字,且不能为空"); } return ResponseEntity.badRequest().body("参数格式错误"); } @ExceptionHandler(ConstraintViolationException.class) public ResponseEntity<String> handleConstraintViolation(ConstraintViolationException e) { String message = e.getConstraintViolations().stream() .map(ConstraintViolation::getMessage) .findFirst() .orElse("参数校验失败"); return ResponseEntity.badRequest().body(message); } }
内容的提问来源于stack exchange,提问作者user21263160
相关产品推荐
相关产品推荐

