数据校验(JSR303、SpringBoot、自定义注解)

在一个项目中,不仅前端要对用户输入的数据进行校验,避免发送不必要的请求,而且后端也要对数据进行对应的校验,因为操作不都是通过页面过来的。

前端

不是很了解

  • 正则表达式

  • 配合各种组件使用

后端

这里以Java为例,这里主要说声明式,JSR303校验。

常用的注解

  • @Null 验证对象是否为null

  • @NotNull 验证对象是否不为null

  • @Max 对Number和String的最大值进行限制

  • @Min 对Number和String的最小值进行限制

  • @NotBlank 检查字符串是否不为空,即不是null,也不是""

  • @URL 检查是否符合路径规则。

对数据进行校验

  1. 第一步引入对应的依赖

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.0.5.RELEASE</version>
    </dependency>

  2. 在实体类中的属性加上对应的注解

    /*** 品牌名*/
    @NotBlank(message = "name参数校验错误")
    private String name;

    message是在校验不正确的时候,响应的信息。

  3. 在对应的Controller中使用@Valid注解

      
    /*** 修改*/@RequestMapping("/update")//@RequiresPermissions("product:brand:update")public R update(@Valid @RequestBody BrandEntity brand){
    brandService.updateById(brand);return R.ok();}

    数据校验不通过,就会朝前断响应400 Bad Request,参数不正确。

    当然,你也可以自定义返回的结果:

    1. 在要校验的参数后面,紧跟一个BindingResult ,就可以拿到校验的结果。

    /*** 修改*/@RequestMapping("/update")//@RequiresPermissions("product:brand:update")public R update(@Valid @RequestBody BrandEntity brand,BindingResult result){
    brandService.updateById(brand);if(result.hasErrors()){//1. 获得所有的错误result.getFieldErrors().forEach((item) -> {//TODO:进行操作。})//TODO:返回自定义的信息即可。  }return R.ok();}

  4. 这样写,显然不合适,每个Controller都有错误校验的话,重复代码太多了,而且这些代码都和我们业务代码耦合了。所以最佳实践:全局异常处理。

     /*** 修改*/@RequestMapping("/update")//@RequiresPermissions("product:brand:update")public R update(@Valid @RequestBody BrandEntity brand){
    brandService.updateById(brand);return R.ok();}

    还是上面的一段代码

    全局异常使用SpringBoot的ControllerAdvice注解。

    1. 编写一个类,加上@ControllerAdvice注解。

    2. 编写对应的方法,加上@ExceptionHandler注解,并写上能处理的异常。

    3. 在方法里写上对应的逻辑。

      //集中处理所有异常  
      @Slf4j
      @RestControllerAdvice(basePackages = "com.atguigu.gulimail.product.app")
      public class GulimailExcdeptionControllerAdvice {
      ​@ExceptionHandler(value = MethodArgumentNotValidException.class)public R handleVaildException(MethodArgumentNotValidException e) {log.error("数据校验出现问题{},异常类型:{}", e.getMessage(), e.getClass());BindingResult bindingResult = e.getBindingResult();//TODO :进行操作即可}
      ​@ExceptionHandler(value = Throwable.class)public R handleException(Throwable throwable) {log.error("错误", throwable);//TODO:进行操作即可。}
      }

  5. 分组校验

    对于一个实体类的属性,在不同的方法下,标准可能是不一样的,比如一个商品的ID,在创建时应该是@Null(前端不用传,数据库自己生成),但在更新修改方法中就得是@NotNull了,所以分组校验就十分重要了。

    那注解就可以这样写:

    /*** 品牌id*/
    @NotNull(message = "修改id不能为空",groups = {UpdateGroup.class})
    @Null(message = "新增id要为空")
    private Long brandId;

    groups接受一个数组,数组里面的是接口,自己定义接口即可,不用做任何操作,就相当于一个标识。

    @Controller层的@valid注解不支持分组,这是就得使用@valiated(Spring提供的注解)注解了。

     /*** 修改*/@RequestMapping("/update")//@RequiresPermissions("product:brand:update")public R update(@Validated({UpdateStatusGroup.class}) @RequestBody BrandEntity brand){
    brandService.updateById(brand);return R.ok();}

    {}里的就是校验分组的标识。

    注意

    @NotBlank在分组情况下不生效,只有在@Validated情况下生效

  6. 自定义注解:

    先看一下@NotBlank注解:

    @Documented
    @Constraint(validatedBy = {}
    )//指定的校验方法。
    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME) //触发的时机
    @Repeatable(List.class)
    public @interface NotBlank {String message() default "{javax.validation.constraints.NotBlank.message}"; //默认去找的信息
    ​Class<?>[] groups() default {};   //分组情况
    ​Class<? extends Payload>[] payload() default {};//上面三个是必须要有的。​@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface List {NotBlank[] value();}
    }

    自己写一个类

    1. 首先需要引入对应的依赖:

      <dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId><version>2.0.1.Final</version>
      </dependency>

    2. 编写一个注解

      @Documented
      @Constraint(validatedBy = {ListValueConstraintValidator.class}
      )
      @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
      @Retention(RetentionPolicy.RUNTIME)
      public @interface ListValue {String message() default "{com.atguigu.common.valid.ListValue.message}";
      ​Class<?>[] groups() default {};Class<? extends Payload>[] payload() default  {};
      ​int[] vals() default {};
      }

      String message() default "{com.atguigu.common.valid.ListValue.message}"; 是默认错误信息的路径地址,在resource包下创建一个properties文件即可。

      ValidationMessages.properties

      com.atguigu.common.valid.ListValue.message=信息有误

    3. 创建处理方法

      这两个泛型分别是:注解和需要添加注解的数据的类型。

      public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {private Set<Integer> set = new HashSet<>();//初始化方法@Overridepublic void initialize(ListValue constraintAnnotation) {int[] vals = constraintAnnotation.vals();for(int val : vals){set.add(val);}}
      ​//判断是否校验成功@Overridepublic boolean isValid(Integer value, ConstraintValidatorContext context) {return set.contains(value);}
      }

    4. 使用注解:

      /*** 显示状态[0-不显示;1-显示]*/
      @ListValue(vals = {0,1})
      private Integer showStatus;

      在ListValueConstraintValidator的initialize方法中,会将vals里的所有值放到set集合中,然后isValid判断实体属性是否在这个set里面,这里可以根据自己的逻辑修改。

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

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

相关文章

winform 限制TextBox中只能输入正整数

txt_n是文本框的名字 private void txt_n_KeyPress(object sender, KeyPressEventArgs e){if (e.KeyChar ! \b)//这是允许输入退格键 {int len txt_n.Text.Length;if (len < 1 && e.KeyChar 0){e.Handled true ;}else if ((e.KeyChar < 0) || (e.KeyChar >…

WebStorm 环境配置带@符号的相对路径穿透

在使用WebStorm 环境开发web页面项目时有时想快速查看页面的引用代码&#xff0c;只能手工找到引入文件路径&#xff0c;这很不方便&#xff0c;只需通过配置webStorm单击打开。 1 使用符号相对路径&#xff0c;在默认情况下没有配置环境是无法打开&#xff0c;如下图&#xf…

AI全栈之coze的logo生成

前言 前几日体验了国产的AI-Agents产品coze 它是一种能够自主执行任务、与环境进行交互并根据所获取的信息做出决策和采取行动的软件程序 并且可以自己去创建属于自己的AIBot&#xff0c;还是很有意思的&#xff0c;大家可以去体验体验 在体验过程中&#xff0c;我发现在创…

适合爬虫开发用的性价比高的代理推荐

在爬虫开发过程中&#xff0c;使用代理可以有效地隐藏爬虫的真实来源&#xff0c;并绕过一些可能对爬虫设置的限制。然而&#xff0c;市面上的代理服务众多&#xff0c;选择一款性价比高且适合爬虫开发的代理服务显得尤为重要。以下是一些适合爬虫开发用的性价比比较高的代理推…

Linux操作系统进程同步的几种方式及基本原理

1&#xff0c;进程同步的几种方式 1.1信号量 用于进程间传递信号的一个整数值。在信号量上只有三种操作可以进行&#xff1a;初始化&#xff0c;P操作和V操作&#xff0c;这三种操作都是原子操作。 P操作(递减操作)可以用于阻塞一个进程&#xff0c;V操作(增加操作)可以用于…

【华为OD机试】递增字符串(C++/Java/Python)

题目 题目描述 [定义字符串]完全由 ‘A’ 和 ‘B’组成,当然也可以全是’A’或全是’B’。如果字符串从前往后都是以字典序排列的,那么我们称之为严格递增字符串。 给出一个字符串s,允许修改字符串中的任意字符,即可以将任何的’A’修改成’B’,也可以将任何的’B’修改成…

Go 实现继承的方式

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

Java高级重点知识点-12-Collection、iterator迭代器、泛型

文章目录 Collection集合Iterator迭代器泛型&#xff08;难点&#xff09; Collection集合 集合是java中提供的一种容器&#xff0c;可以用来存储多个数据。 集合框架 单列集合java.util.Collection双列集合java.util.Map 集合类继承体系图&#xff1a; List集合的特点&am…

Interview preparation--Elasticsearch并发控制

Elasticsearch 并发控制 Elasticsearch是分布式的。创建&#xff0c;更新&#xff0c;删除文档时&#xff0c;必须将文档的新版本复制到集群中的其他节点。ES也是异步并行的&#xff0c;所有这些复制请求是并行发送的&#xff0c;并且可能不安顺序执行到每一个节点。ES需要一种…

新品发布 | TC1018Pro和TC1034Pro正式发布,功能升级,多设备时间同步

新品发布/New products release 同星智能最新推出TC1018Pro和TC1034Pro两款产品&#xff0c;新版本在保留原来基本功能的基础上做了升级&#xff0c;主要新增IO功能、错误帧ID检测、多设备间时间同步等功能。 接下来&#xff0c;让我们看看这两款产品带来了哪些具体功能升级&a…

玄奘取经线路矢量图分享

我们在《透过丝绸之路&#xff0c;看古人都走过哪些地方》一文中&#xff0c;为你分享过丝绸之路的矢量图数据。 现在&#xff0c;我们再为你分享一下玄奘取经线路的矢量图&#xff0c;你可以在文末查看这些数据的领取方式。 玄奘取经线路 《西游记》的故事相信大家都不陌生…

ABC234G Divide a Sequence 题解

题目来源 ABC234G 洛谷 Description 给定长度为 n n n 的序列 { a n } \{a_n\} {an​}。定义一种将 { a n } \{a_n\} {an​} 划分为若干段的方案的价值为每段的最大值减去最小值的差的乘积。求所有划分方案的价值的总和并对 998244353 998244353 998244353 取模。 1 ≤…

项目实训-vue(十一)

项目实训-vue&#xff08;十一&#xff09; 文章目录 项目实训-vue&#xff08;十一&#xff09;1.概述2.页顶导航栏3.导航信息4.总结 1.概述 本篇博客将记录我在图片上传页面中的工作。 2.页顶导航栏 <divstyle"display: flex;justify-content: space-between;alig…

如何挑选洗地机?盘点口碑最好的四大洗地机

在购买洗地机这种智能家电时&#xff0c;大家都应该格外谨慎。毕竟&#xff0c;洗地机价格不菲&#xff0c;精打细算&#xff0c;确保物尽其用才是最重要的。谁都不想花了高价买回来却让它闲置在墙角落灰尘。买之前我们还是需要对自己的需求做一个清晰的判断&#xff0c;实用性…

【GameFramework扩展应用】6-2、替换GameFramework.dll源码

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址QQ群:398291828大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 【GameFramework框架】系列教程目录: https://blog.csdn.net/q764424567/article/details/1…

9 个实用 Shell 脚本

Dos 攻击防范&#xff08;自动屏蔽攻击 IP&#xff09; #!/bin/bash DATE$(date %d/%b/%Y:%H:%M) LOG_FILE/usr/local/nginx/logs/demo2.access.log ABNORMAL_IP$(tail -n5000 $LOG_FILE |grep $DATE |awk {a[$1]}END{for(i in a)if(a[i]>10)print i}) for IP in $ABNORMA…

【unity笔记】六、UI实现下拉列表切换视角

具体步骤如下 1. 创建UI下拉列表&#xff1a; 在Unity场景中右键点击并选择UI -> 下拉列表 来创建一个新的下拉列表。 2. 添加摄像机选项&#xff1a; 在Dropdown的Options属性中添加新的选项&#xff0c;通过点击按钮来添加选项&#xff0c;并为每个选项设置一个显示名…

广告联盟撸包小游戏app开发 现有源码案例

广告联盟小游戏APP的开发涉及多个关键步骤和要素&#xff0c;以下是一个大致的开发流程&#xff1a; 市场调研与定位&#xff1a; 深入了解目标用户群体的需求、喜好以及游戏习惯&#xff0c;这有助于确定游戏的核心功能和特色123456。 分析市场上的类似产品和广告联盟平台&a…

sourceTree 和Tortoise git软件的对比,以及使用sourceTree管理公司托管的 gitlab 项目或github项目

文章目录 Tortoisegit 和sourcetree的比较如何添加 gitlab 的社区版账号总结参考资料 Tortoisegit 和sourcetree的比较 我在 window都是用 Git 小乌龟&#xff08;Tortoise git&#xff09;来可视化管理 Git 项目。这时是不区分 Git 平台的&#xff0c;也就是不管你用的是 Git…

用Rust开发一个类似SQL Server的数据库系统的步骤和关键技术

在开发一个类似SQL Server的数据库系统时&#xff0c;选择Rust作为编程语言有许多好处&#xff0c;包括安全性、性能和并发性。本文将探讨用Rust开发这样一个系统所需的关键步骤和技术。 1. 项目规划和设计 在开始编码之前&#xff0c;需要进行详细的规划和设计&#xff1a; …