news 2026/5/14 21:41:28

Java高级工程师面试题详解(续):Spring Boot 中如何优雅地处理接口参数校验?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java高级工程师面试题详解(续):Spring Boot 中如何优雅地处理接口参数校验?

视频看了几百小时还迷糊?关注我,几分钟让你秒懂!

在上一篇中,我们讲了全局异常处理,解决了“出错后怎么统一返回”的问题。
但你有没有想过:在请求刚进来时,就拦截非法参数,不让脏数据进入业务层

这就是今天要讲的核心内容——Spring Boot 中的参数校验(Bean Validation + 全局异常处理)


一、需求场景

你正在开发一个用户注册接口:

POST /api/user/register Content-Type: application/json { "username": "zhangsan", "email": "invalid-email", "age": -5 }

业务规则要求

  • username:必填,长度 2~20;
  • email:必须是合法邮箱格式;
  • age:必须 ≥ 18。

如果前端传了非法数据,不能等业务逻辑执行到一半才发现错误,而应该在入口处直接拒绝!


二、解决方案:使用 JSR-303 / Bean Validation + @Valid

✅ 正确做法(推荐)

1. 引入依赖(Spring Boot 默认已包含)
<!-- Spring Boot Web 已默认引入 spring-boot-starter-validation --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>

如果你用的是 Spring Boot 2.3+,需要显式添加该依赖,因为从 2.3 开始 validation 不再默认包含。

2. 定义 DTO 并添加校验注解
// UserRegisterDTO.java import javax.validation.constraints.*; public class UserRegisterDTO { @NotBlank(message = "用户名不能为空") @Size(min = 2, max = 20, message = "用户名长度必须在2~20之间") private String username; @Email(message = "邮箱格式不正确") private String email; @Min(value = 18, message = "年龄必须大于等于18岁") private Integer age; // Getter / Setter }
3. Controller 中使用 @Valid
@PostMapping("/register") public CommonResult<String> register(@Valid @RequestBody UserRegisterDTO dto) { // 如果走到这里,说明参数合法! userService.register(dto); return CommonResult.success("注册成功"); }

⚠️ 注意:必须加上@Valid@Validated,否则校验不会生效!

4. 全局捕获校验异常(配合上一篇的异常处理器)
// 在 GlobalExceptionHandler.java 中新增: @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<CommonResult<Void>> handleValidationException(MethodArgumentNotValidException ex) { // 获取第一个错误信息(也可拼接所有) String errorMsg = ex.getBindingResult() .getFieldError() .getDefaultMessage(); return ResponseEntity.status(HttpStatus.BAD_REQUEST) .body(CommonResult.error(400, errorMsg)); }

💡 进阶:如果想返回所有错误字段,可以遍历getFieldErrors()拼成 Map。


三、反例(千万别这么写!)

❌ 反例1:手动 if 判断每个字段

@PostMapping("/register") public ResponseEntity<?> registerBad(@RequestBody UserRegisterDTO dto) { if (dto.getUsername() == null || dto.getUsername().trim().isEmpty()) { return ResponseEntity.badRequest().body("用户名不能为空"); } if (dto.getUsername().length() < 2 || dto.getUsername().length() > 20) { return ResponseEntity.badRequest().body("用户名长度不对"); } if (!dto.getEmail().contains("@")) { return ResponseEntity.badRequest().body("邮箱格式错误"); } // ...更多 if }

问题

  • 代码臃肿,可读性差;
  • 无法复用,换个接口又要重写;
  • 容易漏判,维护成本高。

❌ 反例2:加了 @Valid 但没处理异常

@PostMapping("/register") public String register(@Valid @RequestBody UserRegisterDTO dto) { return "ok"; }

后果
当参数非法时,Spring 会抛出MethodArgumentNotValidException,但如果没有全局处理,默认返回 400 + HTML 错误页(在 REST API 中完全不可接受!)。


四、注意事项(面试高频考点!)

  1. @Valid 和 @Validated 的区别?

    • @Valid:JSR-303 原生注解,支持嵌套校验;
    • @Validated:Spring 扩展,支持分组校验(如:注册 vs 修改密码用不同规则)。
  2. 分组校验示例(加分项!)

public interface RegisterGroup {} public interface UpdateGroup {} public class UserDTO { @NotBlank(groups = RegisterGroup.class) private String username; @Email(groups = {RegisterGroup.class, UpdateGroup.class}) private String email; } // Controller public void update(@Validated(UpdateGroup.class) @RequestBody UserDTO dto) { ... }
  1. 自定义校验注解(体现深度)

比如校验手机号:

@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = PhoneValidator.class) public @interface Phone { String message() default "手机号格式不正确"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } public class PhoneValidator implements ConstraintValidator<Phone, String> { @Override public boolean isValid(String value, ConstraintValidatorContext context) { if (value == null) return true; // 非空由 @NotBlank 控制 return value.matches("^1[3-9]\\d{9}$"); } }
  1. 路径变量/请求参数校验?用 @Validated!
@RestController @Validated // 必须加在类上 public class UserController { @GetMapping("/user/{id}") public User getUser(@Min(1) @PathVariable Long id) { return userService.getById(id); } }

注意:对@PathVariable@RequestParam校验,必须用@Validated注解在类级别


五、总结

能力价值
✅ 自动拦截非法请求提升系统健壮性
✅ 减少 if 判断代码更简洁
✅ 校验规则集中管理易于维护和测试
✅ 与 Swagger 集成自动生成文档约束

掌握参数校验,是你从“能跑就行”迈向“专业工程”的关键一步!


视频看了几百小时还迷糊?关注我,几分钟让你秒懂!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/3 11:53:42

AI侦探P.I.项目:计算机视觉与生成式AI协同质检

AI侦探P.I.项目&#xff1a;计算机视觉与生成式AI协同质检 一项结合了生成式人工智能和计算机视觉成像隧道的技术正在帮助某中心主动改善客户体验。 尽管某中心的配送中心存储着数亿件商品&#xff0c;但客户报告已发货商品受损的情况非常罕见。然而&#xff0c;对客户体验的极…

作者头像 李华
网站建设 2026/5/9 17:32:02

Dify平台任务型对话系统搭建教程

Dify平台任务型对话系统搭建教程 在客户服务日益智能化的今天&#xff0c;企业不再满足于“能回答问题”的聊天机器人&#xff0c;而是期望一个真正“能办事”的数字助手。想象一下&#xff1a;用户一句“帮我把上周买的连衣裙退了”&#xff0c;系统就能自动识别订单、判断是否…

作者头像 李华
网站建设 2026/5/2 20:00:53

23.5 技术调研方法:快速掌握前沿技术动态

23.5 技术调研方法:快速掌握前沿技术动态 课程概述 在上一节课中,我们学习了数据获取策略,了解了如何构建AIGC应用所需的数据资产。本节课我们将探讨技术调研方法,帮助产品经理快速掌握前沿技术动态,为AIGC产品的设计和实施提供技术支撑。 通过本节课的学习,你将能够:…

作者头像 李华
网站建设 2026/5/8 12:39:27

Dify平台竞品分析报告编写效率提升方案

Dify平台竞品分析报告编写效率提升方案 在技术文档撰写日益频繁的今天&#xff0c;如何快速、准确地完成一份结构严谨、内容翔实的《Dify平台竞品分析报告》&#xff0c;是许多产品经理和AI工程师面临的现实挑战。传统方式依赖人工阅读、摘录、对比与重组信息&#xff0c;不仅耗…

作者头像 李华
网站建设 2026/5/12 16:46:29

Dify平台支持的PDF文档解析能力实测

Dify平台支持的PDF文档解析能力实测 在企业纷纷拥抱大模型的今天&#xff0c;一个现实问题摆在面前&#xff1a;我们手握大量PDF格式的产品手册、技术白皮书、内部制度文件&#xff0c;这些“知识沉睡”在服务器角落&#xff0c;却难以被AI真正理解与调用。如何让静态文档变成可…

作者头像 李华