03 后端入参校验:自定义注解实现

03 后端入参校验:自定义注解实现

  • 一、前言
  • 二、实现
    • 1、新建Spring Boot项目
    • 2、引入依赖
    • 3、新建注解类
    • 4、新建校验器
    • 5、全局异常处理器
    • 6、编写Controller
    • 7、新建实体类
    • 8、启动并测试

在这里插入图片描述

一、前言

Java 后端开发中,为了实现入参校验,常常会使用一些特定的注解来标记参数的约束条件。这些注解通常与一个校验框架(如 Spring Boot 提供的 @Valid 等)配合使用,以便在方法调用前自动进行参数校验。以下是一些常见的用于入参校验的注解:

  • @NotNull: 适用于任何对象,包括基本类型、包装类型、集合类、Map等,判断对象本身是否为null,但是无法校验空字符串。

  • @NotEmpty: 适用于集合类(如 ListSet)、数组、MapCharSequence(如 String )等,判断是否非空(即长度不为0)。

  • @NotBlank: 专门用于 CharSequence(如 String )。不仅可以校验null,同时还可以校验空字符串

如果以上注解实际情况都不能用,需要自定义注解取代它们。

二、实现

1、新建Spring Boot项目

此步骤略过~

2、引入依赖

可以根据 GAV坐标 ,去 Maven官网 查询依赖版本。
Maven Repository: Search/Browse/Explore

<!-- Hibernate Validator: 强大的数据验证框架 -->
<dependency>  <groupId>org.hibernate.validator</groupId>  <artifactId>hibernate-validator</artifactId>  <version>版本号</version>  
</dependency><!-- Spring Messaging: 处理消息传递相关的注解。如:@Payload -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-messaging</artifactId><version>当前Spring框架版本号</version>
</dependency>

3、新建注解类

package com.demo.springboot3.ParamValid;import jakarta.validation.Constraint;
import org.springframework.messaging.handler.annotation.Payload;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @Description: // 参数校验:注解* @Author: M.* @Date: 2024-04-25 18:35*/
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ParamValidator.class)
public @interface ParamValid {// message支持自定义String message() default  "该字段不能为空!";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
}
  • @Target
    定义: 指定一个注解能够合法应用的位置。
属性简述
ANNOTATION_TYPE可应用于其他注解类型的定义
CONSTRUCTOR可应用于构造函数声明
FIELD可应用于字段(变量)声明,包括实例变量、静态变量和枚举常量
LOCAL_VARIABLE可应用于方法或块内部的局部变量声明
METHOD可应用于方法声明,包括实例方法、静态方法和抽象方法
PACKAGE可应用于源文件或目录结构开头的包声明
PARAMETER可应用于方法、构造函数或lambda表达式中的参数声明
METHOD可应用于类、接口(包括注解类型)或枚举声明
  • @Retention:
    定义: 指定一个自定义注解在何时何地保持其存在性。
属性简述详细描述
SOURCE源码级别保留这种策略下,注解只存在于源代码中,编译器不会把它们写入到编译后的字节码文件(.class 文件)中。因此,这些注解对于编译器在编译时有用(例如,触发代码生成或编译时检查),但在编译后的任何阶段(如类加载、运行时)都不可见。适用于编译时辅助工具和 IDE 插件。
CLASS类文件级别保留这是默认的保留策略,如果未明确指定 @Retention,则采用此策略。在这种情况下,注解会保留在编译后的字节码文件中,但对运行时环境不可见。这对于编译器、类加载器等工具在加载类时进行处理非常有用,如代码分析工具、构建工具或某些依赖于字节码分析的框架。
RUNTIME运行时级别保留当注解指定为运行时保留时,它们不仅存在于源代码中,而且会被编译器写入字节码文件,并且在程序运行时仍可通过反射 API 被访问到。这意味着应用程序或其他运行时库可以通过查询类或对象的注解来做出运行时决策,实现动态行为或元数据驱动的功能。
  • @Constraint:
    定义:Bean Validation框架中@Constraint 是一个元注解,用于标记一个类为自定义验证约束注解。
属性简述
validatedBy指定实现验证逻辑的校验器类
message定义当约束验证失败时显示的错误消息
groups用于分组验证,允许在不同上下文中执行不同的验证集
payload携带额外信息,供验证引擎或校验器使用,通常不直接使用

4、新建校验器

package com.demo.springboot3.ParamValid;import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;import java.util.Collection;
import java.util.Map;/*** @Description: // 参数校验:校验器* @Author: M.* @Date: 2024-04-25 19:17*/
public class ParamValidator implements ConstraintValidator<ParamValid, Object> {@Overridepublic void initialize(ParamValid constraintAnnotation) {ConstraintValidator.super.initialize(constraintAnnotation);}@Overridepublic boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {return value != null // 参数不为null&& !((value instanceof CharSequence && ((CharSequence) value).length() == 0) // 字符串不为空,同时校验了空字符串|| (value instanceof Collection && ((Collection<?>) value).isEmpty()) // 集合不为空|| (value instanceof Map && ((Map<?,?>) value).isEmpty())); // Map不为空}
}
  • ParamValid: 上文定义的注解名称
  • Object: 校验器的入参,需要检验的参数。

5、全局异常处理器

package com.demo.springboot3.ParamValid;import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;/*** @Description: // 参数校验:全局异常处理器* @Author: M.* @Date: 2024-04-25 19:35*/
@ControllerAdvice
public class PVGlobalExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)public ResponseEntity<Map<String, Object>> handleValidationExceptions(MethodArgumentNotValidException ex, HttpServletRequest request){Map<String, Object> body = new HashMap<>();body.put("timestamp", new Date());body.put("status", HttpStatus.BAD_REQUEST.value());body.put("path",request.getRequestURI());List<Map<String, String>> errorMessages = ex.getBindingResult().getFieldErrors().stream().map(fileError -> {Map<String, String> error = new HashMap<>();error.put("field", fileError.getField());error.put("message", fileError.getDefaultMessage());return error;}).collect(Collectors.toList());body.put("errors", errorMessages);return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);}
}
  • @ControllerAdvice
    定义:Spring 框架中用于全局处理控制器(@Controller 或其派生注解如 @RestController)中异常和数据绑定问题的一个特殊注解。
    使用场景: 全局异常处理、数据绑定验证、模型属性添加。

  • @ExceptionHandler
    定义: @ExceptionHandler 注解的方法会在目标控制器方法抛出指定异常类型时被调用,用于捕获和处理异常,生成合适的响应结果返回给客户端。

  • @ResponseStatus
    定义:@ExceptionHandler 方法上,当该方法处理异常并返回时,应返回的 HTTP 状态码。

📣拓展:
如果各位同学使用了 jdk9 及以上版本,可以使用一下jdk新特性 Map.of() 方法。

List<Map<String, String>> errorMessages = ex.getBindingResult().getFieldErrors().stream().map(fileError -> {Map<String, String> error = new HashMap<>();error.put("field", fileError.getField());error.put("message", fileError.getDefaultMessage());return error;}).collect(Collectors.toList());

优化后代码如下:

List<Map<String, String>> errorMessages = ex.getBindingResult().getFieldErrors().stream().map(fileError -> Map.of("field", fileError.getField(),"message", fileError.getDefaultMessage())).collect(Collectors.toList());

6、编写Controller

package com.demo.springboot3.controller;import com.demo.springboot3.entity.User;
import jakarta.validation.Valid;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;/*** @Description: // 用户信息:Controller* @Author: M.* @Date: 2024-04-25 20:11*/
@RestController
@Validated
public class UserController {@PostMapping("/query")public String queryUser(@Valid @RequestBody User user) {System.out.println(user);return "success";}
}
  • @Validated
    定义: Spring 提供的一个批注,用于启用 JSR-303/JSR-349Bean Validation 规范)数据校验功能。它通常应用于控制器方法的参数、控制器类或服务类上,指示 Spring 在方法调用前对指定的 Java 对象进行数据验证。@Validated@Valid 注解配合使用,后者用于标记需要验证的参数或字段。

7、新建实体类

package com.demo.springboot3.entity;import com.demo.springboot3.ParamValid.ParamValid;
import lombok.Data;import java.util.List;/*** @Description: // 用户类* @Author: M.* @Date: 2024-04-25 20:00*/
@Data
public class User implements java.io.Serializable{@ParamValid(message = "用户名(name)不能为空!!!")private String name;@ParamValid(message = "用户名(age)不能为空!!!")private Integer age;@ParamValid(message = "用户名(addressList)不能为空!!!")private List<String> addressList;
}
  • @ParamValid: 此注解就是上文新建的参数校验注解。需要放在实体类属性上方。

8、启动并测试

在这里插入图片描述
在这里插入图片描述


本文隶属于个人专栏:00 个人小笔记📋📋📋
到这里 03 后端入参校验:自定义注解实现 就结束了!!!🎉🎉🎉
欢迎小伙伴们学习和指正!!!😊😊😊
祝大家学习和工作一切顺利!!!😎😎😎

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

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

相关文章

4月26(信息差)

&#x1f30d; 1170万台 华为跃升重回首位&#xff01;苹果跌至第五位 &#x1f384;工业软件大事件 —— OGG 1.0 发布&#xff0c;华为贡献全部源代码 ✨ 苹果发布 OpenELM&#xff1a;专为在设备端运行而设计的小型开源 AI 模型 1.FisheyeDetNet&#xff1a;首个基于鱼眼相…

GraspNet-1Billion 论文阅读

这里写自定义目录标题 GraspNet-1Billion总体数据集评价指标网络pointnet&#xff1a;Approach Network:Operation Network&#xff1a;Tolerance Network 摘要相关工作基于深度学习的抓取预测算法抓取数据集点云深度学习 GraspNet-1Billion CVPR2020 上海交大 论文和数据集地…

MATLAB中左边的大括号最后一行为什么会留很大的空白——解决

看了一些帖子说改字体&#xff0c;但是并没有什么用&#xff0c;在此给出亲测有效的方法&#xff1a;改变矩阵的行间距 先说一下问题 上图中留有大块空白 **解决办法&#xff1a;**光标放在矩阵上 格式——矩阵——更改矩阵&#xff0c;在矩阵设置中选中“行高相等”&#xff…

专项学习:软件开发

数据结构 &#xff08;一&#xff09;、字符串 当是数字的时候直接入栈 当是运算符号的时候 就将栈的最上面两个数拿出进行运算 后 再将结果进栈 记住&#xff08;栈顶元素永远在运算符号的右边&#xff09; &#xff08;二&#xff09;、数组 &#xff08;三&#xff09;、树…

k8s calico vxlan式详解

之前的文章讲了k8s ipip模式的使用以及流量路径&#xff0c;本篇文章主要是来讲解一下vxlan 模式下pod 流量是如何通信的。 一、ipip模式转vxlan 修改calico backend参数 将calico_backend参数由bird设置为vxlan,因为vxlan部署不使用bgp 修改calico controllers的configmap…

G1垃圾收集器详解

G1收集器 G1(Garbage-Frist)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器,以及高概率满足GC停顿时间要求的同时,还具备高吞吐量性能的特性. G1将Java堆划分为多个大小相等的独立区域(Region),JVM目标似乎不超过2048个Region(JVM源码里TARGET_REGIO…

STM32自己从零开始实操01:原理图

在听完老师关于 STM32 物联网项目的所有硬件课程之后&#xff0c;就是感觉自己云里雾里&#xff0c;明明课程都认真听完了&#xff0c;笔记也认真记录&#xff0c;但是就是感觉学到的知识还不是自己。 遂决定站在老师的肩膀上自己开始设计项目&#xff0c;将知识变成自己的&am…

WSL2无法ping通本地主机ip的解决办法

刚装完WSL2的Ubuntu子系统时&#xff0c;可能无法ping通本地主机的ip&#xff1a; WSL2系统ip&#xff1a; 本地主机ip&#xff1a; 在powershell里输入如下的命令&#xff1a; New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias &quo…

http基础了解

超文本传输协议&#xff08;HTTP&#xff09;是一个用于传输超媒体文档&#xff08;例如 HTML&#xff09;的应用层协议。它是为 Web 浏览器与 Web 服务器之间的通信而设计的&#xff0c;但也可以用于其他目的。HTTP 遵循经典的客户端—服务端模型&#xff0c;客户端打开一个连…

Nginx入门-01

必备知识 DNS域名解析 hostName主机名称其实就是我们的域名 www.baidu.com是一个域名 www.taobao.com也是一个域名 localhost也是一个域名 我们可以根据域名dns解析成ip地址 域名的存在就是为了方便我们的记忆&#xff0c;最终访问的时候还是要转换成服务器的IP地址进行…

Tomcat架构设计精髓分析-Connector高内聚低耦合设计

优秀的模块化设计通常都会采用高内聚、低耦合 高内聚是指相关度比较高的功能要尽可能集中&#xff0c;不要分散。低耦合是指两个相关的模块要尽可能减少依赖的部分和降低依赖的程序&#xff0c;不要让两个模块产中强依赖。 Tomca连接器需要实现的功能: 监听网络端口 接受网络…

STM32的GPIO输入和输出函数详解

系列文章目录 STM32单片机系列专栏 C语言术语和结构总结专栏 文章目录 1. GPIO模式 2. GPIO输出 2.1 RCC 2.2 GPIO 3. 代码示例 3.1 RCC时钟 3.2 GPIO初始化 3.3 GPIO输出函数 3.4 推挽输出和开漏输出 4. GPIO输入 4.1 输入模式 4.2 数据读取函数 5. C语言语法 1…

【Linux系统编程】第八弹---权限管理操作(中)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、修改文件权限的做法(二) 2、文件类型 3、可执行权限 4、创建文件/目录的默认权限 4.1、权限掩码 总结 前面一弹我们学…

PostgreSQL的扩展(extensions)-常用的扩展之pg_repack

PostgreSQL的扩展&#xff08;extensions&#xff09;-常用的扩展之pg_repack pg_repack 是一款非常有用的 PostgreSQL 扩展工具&#xff0c;它能够重新打包&#xff08;repack&#xff09;表和索引以回收空间并减少碎片&#xff0c;而且在这个过程中不会锁定表&#xff0c;允…

基于SpringBoot + Vue实现的校园(通知、投票)管理系统设计与实现+毕业论文(12000字)+答辩PPT+指导搭建视频

目录 项目介绍 运行环境 技术栈 效果展示 论文展示 总结 项目介绍 本系统包含管理员、用户、院校管理员三个角色。 管理员角色&#xff1a;用户管理、院校管理、单位类别管理、院校管理员管理、单位管理、通知推送管理、投票信息管理、通知回复管理等。 用户角色&#…

深入OceanBase内部机制:分区机制构建高可用、高性能的分布式数据库基石

码到三十五 &#xff1a; 个人主页 在数据库技术的发展历程中&#xff0c;随着数据量的不断增长和业务需求的日益复杂&#xff0c;如何高效地存储、查询和处理数据成为了关键挑战。OceanBase作为一款高性能、高可用的分布式关系数据库&#xff0c;通过其独特的分区机制&#xf…

Unity对应的c#版本

本文主要是记录一下unity已经开始兼容c#的版本和.net版本&#xff0c;以便更好的利用c#的特性。 c#和.net对应情况 微软已经将.net开发到.net 9了&#xff0c;但是unity的迭代速度远没有c#迭代速度快&#xff0c;已知unity最新的LTS版本unity2023已经兼容了c#9 可以在unity手册…

8K+/月!学习就业一把梭,祝贺誉天数通陈同学收获心仪offer !

大家好&#xff0c;我是誉天数通的陈同学。 在武汉&#xff0c;网络运维圈的人应该都会听过誉天的名字。作为华为的授权培训合作伙伴&#xff0c;誉天不仅提供专业全面的工程师培训&#xff0c;还以其独特的环境和氛围吸引着无数有志于在网络领域发展的朋友。 一年前的我&#…

PDF加密了无法编辑?解密方法来了!

一下午都在捣鼓各种格式问题&#xff0c;首先是需要合并几个 PDF&#xff0c;然而有一个文件加密了无法操作&#xff0c;碰到加密不能编辑就很头痛&#xff0c;终于让我找到一个可行的方法了&#xff0c; 首先就这个加密文件右键选择打开方式-Google Chrome>>打开>>…

“无媒体,不活动”,这句话怎么理解?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 “无媒体&#xff0c;不活动”通常指的是在现代社会中&#xff0c;媒体对于各种活动&#xff0c;尤其是公共活动和事件的推广、宣传和影响力是至关重要的。它强调了媒体在塑造公众意识、…