You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 21:44:57