JSR303基本使用以及整合springboot统一异常处理

news2024/9/20 18:36:49

目录

一、前言

什么是JSR303

二、JSR303基本使用(普通使用)

1)、引入jar包

2)、实体类对需要校验的数据进行校验

3)、对前端传递过来的参数进行限制

 三、JSR303基本使用(分组校验)

1)、创建分组

2)、实体类

3)、controller代码

四、统一异常拦截器配合使用

代码:

说明:

结果:


一、前言

在之前,我对参数进行校验的时候,都是通过StringUtills.isblank方法将参数进行是否为空判断,需要不断的使用if对前端传递过来的数值进行判断以及是很麻烦,更不用说rul,email等格式的判断,并且这对于性能以及代码的美观都是很严重的减分项。现在使用了JSR303做参数校验,发现颇为顺手,再次记下笔记以便以后用时回顾

什么是JSR303

JSR-303 是JAVA EE 6 中的一项子规范,叫做Bean Validation,Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constrain

@NotNull任何类型属性不能为null
@NotEmpty集合集合不能为null,且size大于0
@NotBlanck字符串、字符字符类不能为null,且去掉空格之后长度大于0
@AssertTrueBoolean布尔属性必须是true
@Min数字类型限定数字的最小值(整型)
 @Max同@Min限定数字的最大值(整型)
@DecimalMin同@Min限定数字的最小值(字符串,可以是小数)
@DecimalMax同@Min限定数字的最大值(字符串,可以是小数)
@Range数字类型限定数字范围(长整型)
@Length字符串限定字符串长度
@Size集合限定集合大小
@Past时间、日期必须是一个过去的时间或日期
@Future时期、时间必须是一个未来的时间或日期
@Email字符串必须是一个邮箱格式
@Pattern字符串、字符正则匹配字符串

JSR-303 是JAVA EE 6 中的一项子规范,叫n V

二、JSR303基本使用(普通使用)

1)、引入jar包

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

2)、实体类对需要校验的数据进行校验



import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.io.Serializable;

import lombok.Data;
import org.hibernate.validator.constraints.URL;

import javax.validation.constraints.*;

/**
 * 品牌
 *
 * @author jjs
 * @email 
 * @date 2021-07-26 14:51:27
 */
@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 品牌id
     */
    @TableId
    private Long brandId;
    /**
     * 品牌名
     */
    @NotBlank(message = "品牌名不能为空")  //至少包含一个非空字符
    private String name;
    /**
     * 品牌logo地址
     */
    @URL(message = "logo必须是一个合法的url")
    @NotBlank(message = "品牌名不能为空")
    private String logo;
    /**
     * 介绍
     */
    private String descript;
    /**
     * 显示状态[0-不显示;1-显示]
     */
    private Integer showStatus;
    /**
     * 检索首字母
     */
    @Pattern(regexp =  "^[a-zA-Z]$",message = "检索首字母必须是一个字母")
    @NotBlank(message = "检索首字母不能为空")
    private String firstLetter;
    /**
     * 排序
     */
    @Min(value = 0,message = "sort的最小值是0")
    @org.hibernate.validator.constraints.NotBlank(message = "排序不能为空" )//org.hibernate.validator.constraints下的NotBlank可以支持数值类型,javax.validation.constraints下的NotBlank是不支持数值类型的校验的
    private Integer sort;

}

其中message是校验不通过的提示语句,有默认值。

3)、对前端传递过来的参数进行限制

  @RequestMapping("/save")
    public R save(@Valid @RequestBody BrandEntity brand,BindingResult result) {
            if(result.hasErrors()){
                Map m = new HashMap();
                result.getFieldErrors().forEach(item->{
                    //获取到校验不通过错误消息
                    String message = item.getDefaultMessage();
                    //获取到校验不通过字段名称
                    String field= item.getField();
                    m.put(field,message);

                });
                return  R.error(400,"提交的数据不合法").put("data",m);
            }
        brandService.save(brand);

        return R.ok();
    }

* 在校验的对象前添加注解@Valid打开JSR303数据校验,在校验的对象后面紧跟着BindingResult对象,用于保存校验的结构
* !!!BindingResult必须跟在校验的对象后面!!!(如果添加了BindingResult,会将异常值存入其中,否则会直接抛出异常)

 三、JSR303基本使用(分组校验)

在实体类上标注校验注解的时候,可以给groups属性进行赋值,然后在需要校验的controller类的方法中的实体类前加上@Validated注解,先附上代码再细细说明

1)、创建分组

只需要创建两个空的接口用于做标记即可,不需要有内容。

2)、实体类

@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 品牌id
     * POSTman:{"name":"aaa","logo":"abc","brandId":1}
     */
    @NotNull(message = "修改必须定制品牌id", groups = {UpdateGroup.class})
    @Null(message = "新增不能指定id", groups = {AddGroup.class})
    @TableId
    private Long brandId;
    /**
     * 品牌名
     */
    @NotBlank(message = "品牌名必须提交", groups = {AddGroup.class, UpdateGroup.class})
    private String name;

    /**
     * 品牌logo地址 修改可以不带上logoURL
     */
    @NotBlank(groups = {AddGroup.class})
    @URL(message = "logo必须是一个合法的URL地址", groups={AddGroup.class, UpdateGroup.class})
    private String logo;
    /**
     * 介绍
     */
    private String descript;
    /**
     * 显示状态[0-不显示;1-显示]
     */
    @NotNull(groups = {AddGroup.class, UpdateStatusGroup.class})
//    @ListValue(vals = {0,1}, groups = {AddGroup.class, UpdateGroup.class, UpdateStatusGroup.class})
    private Integer showStatus;

    /**
     * 检索首字母  修改可以不带, 不管是新增还是修改都必须是一个字母
     */
    @NotEmpty(groups = {AddGroup.class})
    @Pattern(regexp = "^[a-zA-Z]$", message = "检索首字母必须是一个字母", groups = {AddGroup.class, UpdateGroup.class})
    private String firstLetter;
    /**
     * 排序
     */
    @NotNull(groups = {AddGroup.class})
    @Min(value = 0, message = "排序必须是一个正整数" , groups = {AddGroup.class, UpdateGroup.class})
    private Integer sort;

}

由代码不难看出,每个注解后面我都加上了分组,groups里可以添加多个.class文件,标记对应分组,例如

/**
     * 品牌id
     * POSTman:{"name":"aaa","logo":"abc","brandId":1}
     */
    @NotNull(message = "修改必须定制品牌id", groups = {UpdateGroup.class})
    @Null(message = "新增不能指定id", groups = {AddGroup.class})
    @TableId
    private Long brandId;

这段代码中,@notNull对应了当分组时UpdateGroup的时候,触发该校验,当接收到的brandId字段为空时,就会出现校验异常。@null则对应AddGroup分组。

3)、controller代码

    @RequestMapping("/save")
    public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand) {
        brandService.save(brand);

        return R.ok();
    }

在需要校验的对象前面加上@Validated({AddGroup.class})表明这个对象要进行数据校验,并且仅对分组时AddGroup的分组进行校验。

特别说明:

JSR303对注释要求相对较为严格,controller类的方法中,需要校验的字段前面可以添加两种注解:

1、@Validated。

对应分组校验,并且仅当对该注解配置分组,实体类也配置分组时才起作用,如果@Validated注解不对它的参数添加分组信息,则默认不校验。一一对应关系十分严格。
2、@Valid。

对应非分组校验,仅当实体类的注释中没有配置分组时才会起作用

四、统一异常拦截器配合使用

代码:


import com.atguigu.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
 
import java.util.HashMap;
import java.util.Map;
 
/**
 * 集中处理所有异常
 */
@Slf4j
//@ResponseBody//最终以json的格式返回
//@ControllerAdvice(basePackages ="com.product.controller" ) 标准该类是统一异常处理类,basePackages标注的包都是我们设置异常处理的作用域
@RestControllerAdvice(basePackages ="com.product.controller" )//该注解等于上面两个注解结合
public class GulimallExceptionControllerAdvice {
 
    @ExceptionHandler(value = MethodArgumentNotValidException.class)//该注解用于表明这个方法要用来处理哪些异常
    public R handleVaildException(MethodArgumentNotValidException e){
            log.error("数据校验出现问题{},异常类型",e.getMessage(),e.getClass());
        BindingResult bindingResult = e.getBindingResult();//获取到数据校验的错误结果
        Map<String,String> errorMap = new HashMap<>();
        bindingResult.getFieldErrors().forEach(fieldError->{
                errorMap.put(fieldError.getField(),fieldError.getDefaultMessage());
        });
 
        return R.error(400,"校验出现问题").put("data",errorMap);
 
 
    }
    @ExceptionHandler(value = Throwable.class)
    public R handleVaildOtheException(Throwable e){
        return R.error(401,"未知异常");
 
    }
 
}

说明:

  • @RestControllerAdvice注解标志了该类会拦截所有异常(具体异常由@ExceptionHandler注解指定,有它注解的方法执行异常处理)并最终以JSON的数据格式返回,参数'basePackages'写明了从哪些包中拦截异常
  • @ExceptionHandler注解表明该方法用来拦截哪些异常,上面代码中创建了两个方法,第一个方法'handleVaildException()'用来专门处理数据校验异常,而第二个方法handleVaildOtheException 用来处理其他所有异常
  • 如果某个方法标记了特地的处理某个异常,当出现异常时,会由该方法处理,如果没有特定指定某个异常,则会往下跟大范围的方法中去处理,例如Throwable。(第二个方法写的较为粗略,可以根据自己想要返回的数据格式进行封装代码)

结果:

经过上面的处理之后原来的代码就可以变成(入参BindingResult result,把异常抛出以便被拦截器拦截)

 只需要专心处理业务逻辑即可

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

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

相关文章

leaflet 根据两个坐标值,设置arc弧线和Marker(079)

第069个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中根据提供的两个点,绘制出marker,同时将两点间绘制出一条弧线。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共88行)安装插件相关API参考…

最全面的SpringBoot教程(六)——SpringBoot运行原理分析

前言 本文为 最全面的SpringBoot教程&#xff08;六&#xff09;——SpringBoot运行原理分析 相关知识&#xff0c;下边将对SpringBoot运行原理以及自动配置原理进行详尽的分析介绍~ &#x1f4cc;博主主页&#xff1a;小新要变强 的主页 &#x1f449;Java全栈学习路线可参考…

计算机网络 物理层

1&#xff0c;物理层的基本概念 物理层考虑的是怎样才能在连接各种计算机的传输媒体上传输数据比特流&#xff0c;而不是指具体的传输媒体。现有的计算机网络中的硬件设备和传输媒体的种类非常繁多&#xff0c;而通信手段也有许多不同方式。物理层的作用正是要尽可能地屏蔽掉这…

【ts + webpack】贪吃蛇小游戏

目录 一、项目搭建 1.1 初始化项目 二、项目界面布局 三、完成Food类 四、完成记分牌类 五、初步完成snake类 六、创建游戏控制器类 - 键盘事件 七、GameControl - 使蛇移动 八、蛇撞墙和吃食检测 一、项目搭建 1.1 初始化项目 1.使用init命令生成package.json文件 …

日期时间控件my97初步探索

因为要写period entry 的项目&#xff0c;需要Report StartDate 和 Report EndDate&#xff0c;于是乎咨询前端同学&#xff0c;推荐my97 官方网站 http://www.my97.net/ 确实有点看起来古老的网站 点击下载能够下载包的资源&#xff0c;以及示例文件 demo示例、Api等 http…

Vue3使用Echarts实现自定义地图(使用阿里云数据可视化平台)

Vue3使用Echarts实现自定义地图 1.获取地图JSON文件 推荐使用 阿里云数据可视化平台 选择你想要使用地图区域并下载JSON文件 2.把地图JSON文件引入Vue3项目中 放在src/assets中 引入你想要使用地图的组件中 3.使用Echarts创建地图 准备地图容器 <template> <…

链路聚合基本概念

聚合组&#xff08;Link Aggregation Group&#xff0c;LAG&#xff09;&#xff1a;若干条链路捆绑在一起所形成的的逻辑链路。每个聚合组唯一对应着一个逻辑接口&#xff0c;这个逻辑接口又被称为链路聚合接口或Eth-Trunk接口。成员接口和成员链路&#xff1a;组成Eth-Trunk接…

win11/10+Azure kinect DK配置 VS2019/2017/2015的方法(简单,亲测可以)

首先下载文件&#xff1a;文件的下载和安装方法参考我的博客(131条消息) WIN11/win10Azure Kinect DK详细驱动配置教程&#xff08;亲测&#xff09;_Vertira的博客-CSDN博客安装好VS2019,创建好控制台c工程。这些都很简单&#xff0c;不细说。配置&#xff1a;首先配置环境变量…

如何快速掌握DDT数据驱动测试?

如何快速掌握DDT数据驱动测试&#xff1f; 目录&#xff1a;导读 前言 实施数据驱动步骤 数据驱动测试环境准备 测试步骤 数据存储 数据存在当前脚本中 json文件读取测试数据进行数据驱动测试 从xml读取数据进行数据驱动测试 总结 写在最后 前言 网盗概念相同的测试…

《Linux运维实战:Centos7.6基于docker-compose一键离线部署rabbitmq3.9.16+haproxy镜像模式高可用负载均衡集群》

一、部署背景 由于业务系统的特殊性&#xff0c;我们需要面向不通的客户安装我们的业务系统&#xff0c;而作为基础组件中的重要的一环&#xff0c;我们需要针对不同的客户环境需要多次部署 rabbitmq镜像模式高可用负载均衡集群&#xff0c;作为一个运维工程师&#xff0c;提升…

LeetCode 793. 阶乘函数后 K 个零

f(x) 是 x! 末尾是 0 的数量。回想一下 x! 1 * 2 * 3 * ... * x&#xff0c;且 0! 1 。 例如&#xff0c; f(3) 0 &#xff0c;因为 3! 6 的末尾没有 0 &#xff1b;而 f(11) 2 &#xff0c;因为 11! 39916800 末端有 2 个 0 。 给定 k&#xff0c;找出返回能满足 f(x) …

Django框架之类视图

类视图 思考&#xff1a;一个视图&#xff0c;是否可以处理两种逻辑&#xff1f;比如get和post请求逻辑。 如何在一个视图中处理get和post请求 注册视图处理get和post请求 以函数的方式定义的视图称为函数视图&#xff0c;函数视图便于理解。但是遇到一个视图对应的路径提供…

【Vue/基础知识】Vue基础知识(一)

如果觉得我的分享有一定帮助&#xff0c;欢迎关注我的微信公众号 “码农的科研笔记”&#xff0c;了解更多我的算法和代码学习总结记录。或者点击链接扫码关注 【Vue/基础知识】Vue基础知识&#xff08;一&#xff09; 1、v-show 和 v-if 指令的共同点和不同点&#xff1f; 共…

【建议收藏】2023年最新最全PMP 报考条件和流程在这里!

PMP考试是由美国项目管理协会PMI发起的项目管理专业人士资格认证考试&#xff0c;在中国国内由中国国际人才交流基金会举办考试&#xff0c;考生在报名参加PMP考试前了解下PMP考试报名条件和流程是必须要做的功课&#xff0c;下面我为大家详细介绍2023年PMP考试报名条件和流程&…

音频信号处理笔记(二)

文章目录1.1.3 过零率1.1.4 谱质心和子带带宽1.1.5 短时傅里叶分析法1.1.6 小波变换相关课程&#xff1a; 音频信号处理及深度学习教程傅里叶分析之掐死教程&#xff08;完整版&#xff09;更新于2014.06.06 - 知乎 (zhihu.com)1.1.3 过零率 过零率&#xff1a;是一个信号符号…

[软件工程导论(第六版)]第7章 实现(复习笔记)

文章目录7.1 编码7.2 软件测试基础7.2.1 软件测试的目标7.2.2 软件测试的准则7.2.3 测试方法7.2.4 测试步骤7.2.5 测试阶段的信息流7.3 单元测试&#xff08;模块测试&#xff09;7.4 集成测试7.5 确认测试&#xff08;验收测试&#xff09;7.6 白盒测试技术7.7 黑盒测试技术7.…

微型光纤光谱仪的光路性能指标

标题光路指标波长范围灵敏度分辨率&#xff08;波长&#xff09;波长准确度与波长重复性光路稳定性杂散光与二级衍射效应光路指标 波长范围 对于微型光纤光谱仪来说&#xff0c;波长范围的概念有两个层面&#xff1a; 由灵敏度所限制的范围&#xff08;Useable range&#xf…

python学习之10行代码制作炫酷的词云图(匹配指定图形形状)

文章目录前言一、需要准备什么&#xff1f;二、代码实现&#xff08;示例&#xff09;三、读入数据四、结果展示五、修改词云颜色后的运行结果展示&#xff1a;总结前言 想必大家有一个问题&#xff1a;什么是词云呢&#xff1f; 词云又叫名字云&#xff0c;是对文本数据中出…

java调用elasticSearch api

java操作es有两种方式 通过操作es的9300端口&#xff0c;9300是tcp端口&#xff0c;集群节点之间通信也是通过9300端口&#xff0c;会通过9300和es建立一个长连接&#xff0c;下面的es的依赖可以直接操作 但是随着es的版本的提升spring-data需要封装不同版本的es的jar包&#x…

Windows命令大全

Windows命令大全命令简介运行流程CMD命令—文件管理CMD命令—磁盘管理CMD命令—系统管理CMD命令—进程管理CMD命令—控制台管理CMD命令—其他管理Windows运行工具操作示例命令简介 CMD命令是一种命令提示符&#xff0c;CMD是command的缩写&#xff0c;即命令提示符&#xff08…