SpringBoot注解参数校验,给代码穿上“防弹衣”

大家好,我是小悟。

一、参数校验:程序员的“防杠精神器”

假如你的API像个热情的饭店服务员,用户说“随便来点吃的”,你就真给他上了盘空气——这可不妙!参数校验就像是那个会耐心问“要辣的还是不辣的?要牛肉还是鸡肉?”的细心服务员,确保不闹出“我要咖啡你却给我上了杯洗脚水”的尴尬。

SpringBoot的注解校验就像给你的方法参数请了个私人保镖,专门拦截那些不靠谱的输入。没有它?用户传个null过来,你的程序可能就会表演“当场崩溃”的绝活。

二、详细步骤:给代码戴上“紧箍咒”

第1步:先来点“开胃菜”——添加依赖

<!-- pom.xml里加入这个,就像泡面加卤蛋,标配! --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>

第2步:创建个“相亲简历”DTO类

import javax.validation.constraints.*; import java.util.Date; import java.util.List; /** * 用户注册DTO - 比相亲网站的个人资料要求还严格 */ public class UserRegisterDTO { @NotBlank(message = "用户名不能为空,难道您是无名氏?") @Size(min = 2, max = 20, message = "用户名长度在2-20之间,太短没存在感,太长记不住") private String username; @Email(message = "邮箱格式不对,这可不是在写情书,随便写写就行") private String email; @Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$", message = "密码至少8位,包含字母和数字,别再用123456了!") private String password; @Min(value = 18, message = "未满18岁?小朋友先去写作业") @Max(value = 120, message = "超过120岁?您是老神仙吧") private Integer age; @NotNull(message = "手机号必须填,不然外卖到了找谁?") private String phone; @AssertTrue(message = "必须接受协议,虽然可能没人看") private Boolean acceptedAgreement; @Future(message = "预约时间必须是未来,时光机还没发明呢") private Date appointmentTime; @Size(min = 1, max = 3, message = "最多选3个爱好,您是想成为全能超人吗?") private List<String> hobbies; // 此处省略getter和setter,但它们确实存在,我发誓! // 用Lombok的@Data也行,但今天咱们保持纯洁的Java关系 // 自定义校验注解示例 @ValidGender private String gender; }

第3步:自定义校验注解——打造专属“安检仪”

import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.*; /** * 性别校验注解 - 咱们思想很开放,但数据要规范 */ @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = GenderValidator.class) public @interface ValidGender { String message() default "性别必须是男、女或保密,您这是来自火星吗?"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } /** * 性别校验器 - 严肃的判官 */ public class GenderValidator implements ConstraintValidator<ValidGender, String> { private static final Set<String> VALID_GENDERS = new HashSet<>(Arrays.asList("男", "女", "保密")); @Override public boolean isValid(String value, ConstraintValidatorContext context) { if (value == null) { return true; // 用@NotNull管非空,咱们只管格式 } return VALID_GENDERS.contains(value); } }

第4步:控制器里使用——给API装上“安检门”

import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import javax.validation.constraints.NotBlank; @RestController @RequestMapping("/api/users") @Validated // 这个注解让方法参数校验生效,就像给方法吃了“严格丸” public class UserController { /** * 注册用户 - 参数校验比丈母娘挑女婿还严格 */ @PostMapping("/register") public Result register(@RequestBody @Valid UserRegisterDTO userDTO) { // 如果参数校验失败,根本走不到这里 // 就像考试不及格,进不了下一轮面试 return Result.success("注册成功,恭喜通过严格审查!"); } /** * 方法参数校验 - 连路径变量都不放过 */ @GetMapping("/{id}") public Result getUser( @PathVariable @Min(value = 1, message = "ID必须大于0,您这是要找空气用户吗?") Long id, @RequestParam @NotBlank(message = "令牌不能为空,您这是想蒙混过关?") String token) { return Result.success("找到了用户ID: " + id); } /** * 分组校验 - 根据不同场景使用不同规则 * 就像上班穿正装,在家穿睡衣,场合要分清 */ @PostMapping("/update") public Result updateUser(@RequestBody @Validated(UserUpdateGroup.class) UserUpdateDTO dto) { return Result.success("更新成功"); } } // 分组接口定义 interface UserUpdateGroup {} interface UserCreateGroup {}

第5步:全局异常处理——优雅的“救火队员”

import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.validation.FieldError; /** * 全局异常处理器 - 专业收拾校验失败的烂摊子 */ @RestControllerAdvice public class GlobalExceptionHandler { /** * 处理参数校验异常 - 把技术语言翻译成人话 */ @ExceptionHandler(MethodArgumentNotValidException.class) public Result handleValidationException(MethodArgumentNotValidException ex) { // 收集所有错误信息,就像收集考试错题 Map<String, String> errors = new HashMap<>(); ex.getBindingResult().getAllErrors().forEach(error -> { String fieldName = ((FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); errors.put(fieldName, errorMessage); }); return Result.error(400, "参数校验失败", errors) .setMessage("您提交的数据有点小问题,请检查后再试哦~"); } /** * 处理ConstraintViolationException - 方法参数校验失败 */ @ExceptionHandler(ConstraintViolationException.class) public Result handleConstraintViolationException(ConstraintViolationException ex) { List<String> errors = ex.getConstraintViolations().stream() .map(violation -> violation.getMessage()) .collect(Collectors.toList()); return Result.error(400, "参数不合法", errors); } } /** * 统一返回结果 - 给前端一个标准的“成绩单” */ @Data @AllArgsConstructor @NoArgsConstructor public class Result<T> { private Integer code; private String message; private T data; private Long timestamp = System.currentTimeMillis(); public static <T> Result<T> success(T data) { return new Result<>(200, "成功", data); } public static <T> Result<T> error(Integer code, String message, T data) { return new Result<>(code, message, data); } public Result<T> setMessage(String message) { this.message = message; return this; } }

第6步:进阶玩法——嵌套校验和集合校验

/** * 订单DTO - 俄罗斯套娃式的校验 */ public class OrderDTO { @NotNull(message = "订单信息不能为空") @Valid // 这个注解让嵌套校验生效,就像班主任检查每个学生的作业 private UserDTO user; @Valid // 集合也要逐个校验,一个都别想逃 private List<@Valid OrderItemDTO> items; @Valid private AddressDTO address; } /** * 地址DTO - 精确到门牌号 */ public class AddressDTO { @NotBlank(message = "省份不能空,您这是要寄到外太空?") private String province; @NotBlank(message = "城市不能空") private String city; @Size(min = 5, max = 100, message = "详细地址5-100字,说清楚点,快递员会感谢您") private String detail; }

三、测试一下:看看“保镖”工作认不认真

// 测试Controller - 专门捣乱看系统反应 @SpringBootTest @AutoConfigureMockMvc class UserControllerTest { @Autowired private MockMvc mockMvc; @Test void testRegisterWithInvalidData() throws Exception { String invalidUserJson = """ { "username": "A", // 太短了! "email": "not-an-email", // 这不是邮箱 "password": "123", // 太弱了 "age": 10, // 未成年! "phone": null, // 空值 "acceptedAgreement": false, // 不同意协议 "appointmentTime": "2020-01-01", // 过去的时间 "hobbies": ["吃饭", "睡觉", "打豆豆", "刷手机", "发呆"] // 爱好太多 } """; mockMvc.perform(MockMvcRequestBuilders.post("/api/users/register") .contentType(MediaType.APPLICATION_JSON) .content(invalidUserJson)) .andExpect(status().isBadRequest()) // 应该返回400 .andExpect(jsonPath("$.code").value(400)) .andExpect(jsonPath("$.data").exists()) // 错误详情 .andDo(print()); // 打印响应,看看“保镖”怎么怼你 } }

四、性能优化小贴士

/** * 校验配置 - 让校验既严格又高效 */ @Configuration public class ValidationConfig { @Bean public Validator validator() { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); // 可以在这里配置一些自定义设置 // 比如缓存校验器,避免重复创建 return validator; } /** * 快速失败模式 - 发现一个错误就立即返回 * 就像考试发现第一题错了就交卷(不建议真人尝试) */ @Bean public Validator fastFailValidator() { return Validation.byDefaultProvider() .configure() .addProperty("hibernate.validator.fail_fast", "true") .buildValidatorFactory() .getValidator(); } }

总结:参数校验的“人生哲理”

  1. 为什么需要参数校验?
    • 防止GIGO(垃圾进,垃圾出)——输入决定输出质量
    • 安全第一:很多安全漏洞都源于不可信的输入
    • 用户体验:早发现错误,早提示用户,别让用户猜谜
  2. 注解校验的优点:
    • 声明式:像贴标签一样简单,告别一堆if-else
    • 集中管理:规则在实体类上一目了然
    • 易于维护:改注解就能改规则,不用翻业务代码
    • 丰富内置:Spring提供了几十种注解,总有一款适合你
  3. 最佳实践建议:
    • 在DTO层做校验,保持业务层纯洁
    • 错误消息要友好,说人话,别甩技术术语
    • 区分必填和非必填字段,别要求用户填宇宙
    • 复杂逻辑用自定义校验器,别硬塞到一个注解里
    • 记得处理异常,给前端统一的错误格式
  4. 总结:
    参数校验就像给你的代码请了个:
    • 门卫大爷:不合格的一律不让进
    • 语文老师:检查格式对不对,内容全不全
    • 健身教练:严格要求,不容马虎
    • 相声演员:出错时还能用幽默的方式告诉你

严谨的程序员对待输入就像猫奴对待猫主子,既要有爱,也要有规矩!你的API会因为良好的参数校验而变得更加健壮、安全、用户友好。

谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。

您的一键三连,是我更新的最大动力,谢谢

山水有相逢,来日皆可期,谢谢阅读,我们再会

我手中的金箍棒,上能通天,下能探海

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1184195.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

筑牢智慧职教实训底座,无人机电力巡检 AI+虚仿 创新实训室特色架构

传统巡检模式依赖人工“爬塔走线”&#xff0c;不仅风险高、效率低&#xff0c;且实训多局限于理论教学&#xff0c;缺乏真实实操环境&#xff0c;难以系统提升技能水平。与此同时&#xff0c;低空经济兴起与科技持续推动&#xff0c;促使无人机电力巡检逐步成为行业主流&#…

每天一个网络知识:什么是MSTP?

在网络技术不断演进的今天&#xff0c;生成树协议&#xff08;Spanning Tree Protocol, STP&#xff09;作为防止二层环路的关键机制&#xff0c;早已成为网络工程师必须掌握的基础知识。然而&#xff0c;传统的STP存在资源利用率低、收敛速度慢等问题。为了解决这些问题&#…

氯离子计哪家性价比高?从上海仪电雷磁产品线看国产高性价比选择 - 品牌推荐大师1

在实验室和企业的设备采购中,“性价比”从来不是“谁价格低”那么简单,而是在满足技术要求、标准符合性、稳定性和售后服务的前提下,尽可能降低全生命周期成本。氯离子计也不例外。很多用户会发现:进口品牌虽然性能…

抖音团购入驻避坑指南:优选服务商合集 - 野榜数据排行

《2026 年中国本地生活服务行业发展白皮书》数据表明,2026 年国内本地生活服务市场规模成功突破 20 万亿大关。抖音团购凭借流量核心入口的优势,吸引大批商家争相入局,入驻需求年增长率超 60%。 不过,绝大多数商家…

预测一下,微软最终会推出一款以 Windows 为主题的 Linux 发行版

在技术圈里,有一个“周期性出现”的话题:微软最终会不会放弃 Windows NT 内核,转而基于 Linux 推出一个“Windows 发行版”。 三十年来,这个预测几乎每隔几年就会被重新拿出来鞭尸一次。 过去,这通常会被当作笑话。 但今天,随着 WSL2、Azure Linux(CBL-Mariner)、Li…

GESP认证C++编程真题解析 | 202312 五级

​欢迎大家订阅我的专栏:算法题解:C++与Python实现! 本专栏旨在帮助大家从基础到进阶 ,逐步提升编程能力,助力信息学竞赛备战! 专栏特色 1.经典算法练习:根据信息学竞赛大纲,精心挑选经典算法题目,提供清晰的…

str与[u8]区别

在Rust 开发实践中,理解 &str 与 &[u8] 的关系是处理高性能文本和网络协议的基础。 这两者本质上都是切片(Slice),即“指针 + 长度”,但它们在语义、验证和用途上有着严格的区别。 1. 核心区别对比表特性…

基于Python的外卖配送分析与可视化系统的设计与实现

随着大数据技术加速发展&#xff0c;数据分析与可视化成为各行业数字化转型的核心手段。外卖行业作为互联网经济支柱&#xff0c;积累了海量订单、用户行为及配送数据&#xff0c;如何高效分析并提升用户体验亟待解决。本研究聚焦“基于Python的外卖配送分析与可视化系统”&…

seaweedFs集群部署

SeaweedFS 分布式文件系统:全面解析与高可用部署指南 1. SeaweedFS 简介与核心优势 SeaweedFS(又称草鱼文件系统)是一款用 Go 语言开发的高性能、高可扩展的​分布式文件系统​,专为海量小文件存储而优化。它最初的…

2026年全屋定制品牌权威推荐榜:整体家居/定制柜类/环保定制/高端整装等源头实力厂家综合评估

诗尼曼在全国近2000家经销服务网点中,有一套高效供应链正在运行,从广州番禺的智能工厂到临沂、荆门的生产基地,他们构建起一个响应快速的全屋定制生态。近几年,诗尼曼展示的高净抗菌板连续三年通过育儿环境优标认证…

LangBot:五分钟打造你的专属IM机器人,支持10+聊天平台!

LangBot:五分钟打造你的专属IM机器人,支持10+聊天平台! LangBot 到底是什么? 简单说,它就是... LangBot 是一个开源的大语言模型原生即时通信机器人开发平台,简单来说,它就像一个“万能遥控器”,让你能够轻松连…

油品分析仪生产厂家,谁家的技术先进/实力强? - 品牌推荐大师

在石油化工及相关领域,油品分析仪作为保障产品质量、优化生产工艺的关键设备,其技术先进性与生产厂家的综合实力直接影响着行业的发展水平。在众多生产厂家中,北京杜克泰克科技有限公司凭借其卓越的技术和强大的实力…

实用指南:光谱共焦传感器 LTC2400/LTC4000F 对手机镜头镜片的圆角倒角厚度测量检测

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

GESP认证C++编程真题解析 | 202312 四级

​欢迎大家订阅我的专栏:算法题解:C++与Python实现! 本专栏旨在帮助大家从基础到进阶 ,逐步提升编程能力,助力信息学竞赛备战! 专栏特色 1.经典算法练习:根据信息学竞赛大纲,精心挑选经典算法题目,提供清晰的…

2026 年靠谱的一键闪测仪厂家推荐及选购指南 - 工业仪器权威说

在制造业蓬勃发展的当下,工业生产中的测量检测环节愈发关键。一键闪测仪作为这一环节的重要工具,其性能直接影响着产品质量和生产效率。一台靠谱的一键闪测仪能够为企业节省大量时间和成本,提升生产的精准度和稳定性…

迪赛福闪测仪:高效测量与精度稳定,助力制造升级 - 工业仪器权威说

在工业测量领域,闪测仪(又称一键式影像测量仪)正以其高效、精准的检测能力,成为现代智能制造的关键装备。随着制造业向高精度、高效率方向发展,对测量设备的要求也日益严苛。迪赛福工业互联(深圳)有限公司,作为…

我花了 2 周用 cursor 把 Couple AI 重新做了一遍:从“能用”到“值得用”

今天想真诚地和大家分享一件事: 我把 Couple AI 彻底重做了,并正式发布了 1.0 版本。 老版本其实是一个“快速验证”的原型,我们做得很快,但也很清楚它有很多不足: 生成效果不稳定、体验不够顺畅、对“情侣记忆”…

32432423

您好: 1.首先,非常抱歉,我猜,您应该知道,我确实长时间在一个地方发不利于您的信息,非常恶劣的信息。非常抱歉,非常对不起。之前得罪您的次数比较多,您可以回复的骂我,侮辱我,哪怕打我都行,或者我给您当面道…

GESP认证C++编程真题解析 | 202312 三级

​欢迎大家订阅我的专栏:算法题解:C++与Python实现! 本专栏旨在帮助大家从基础到进阶 ,逐步提升编程能力,助力信息学竞赛备战! 专栏特色 1.经典算法练习:根据信息学竞赛大纲,精心挑选经典算法题目,提供清晰的…

详细介绍:安全体检 | 服务器的终极卫士

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …