【业务功能篇78】微服务-前端后端校验- 统一异常处理-JSR-303-validation注解
5. 前端校验
我们在前端提交的表单数据,我们也是需要对提交的数据做相关的校验的
Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可

校验的页面效果

前端数据校验就搞定了。后端校验也是不可避免的
6. 后端服务校验
6.1 JSR-303介绍
JSR是Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。
JSR-303 是JAVA EE 6 中的一项子规范,叫做Bean Validation,Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint。
Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint。

Hibernate 中填充一部分

6.2 后端校验实现
1.需要在commons服务中添加对应的依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId><version>2.4.12</version></dependency>
2.在需要校验的Bean的字段头部添加对应的注解

3.通过@Valid注解来开启JSR303的校验

4.测试,通过postman提交空的数据

当我们提交一个非空的数据是可以通过的

5.校验不合法的提示信息,在Controller中通过 BindingResult对象来获取校验的结果信息,然后解析出来后封装为R对象响应
@RequestMapping("/save")//@RequiresPermissions("product:brand:save")public R save(@Valid @RequestBody BrandEntity brand, BindingResult result){if(result.hasErrors()){// 提交的数据经过JSR303校验后有非法的字段Map<String,String> map = new HashMap<>();List<FieldError> fieldErrors = result.getFieldErrors();for (FieldError fieldError : fieldErrors) {// 获取非法数据的 fieldString field = fieldError.getField();// 获取非法的field的提示信息String defaultMessage = fieldError.getDefaultMessage();map.put(field,defaultMessage);}return R.error(400,"提交的品牌表单数据不合法").put("data",map);}brandService.save(brand);return R.ok();}

然后完善其他字段你的校验规则
@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {private static final long serialVersionUID = 1L;/*** 品牌id*/@TableIdprivate Long brandId;/*** 品牌名*///@NotEmpty//@NotNull@NotBlank(message = "品牌的名称不能为空")private String name;/*** 品牌logo地址*/@NotBlank(message = "logo不能为空")@URL(message = "logo必须是一个合法URL地址")private String logo;/*** 介绍*/private String descript;/*** 显示状态[0-不显示;1-显示]*/private Integer showStatus;/*** 检索首字母*/@NotBlank(message = "检索首字母不能为空")@Pattern(regexp = "/^[a-zA-Z]$/",message = "检索首字母必须是单个的字母")private String firstLetter;/*** 排序*/@NotNull(message = "排序不能为null")@Min(value = 0,message = "排序不能小于0")private Integer sort;}

6.3 统一的异常处理
在SpringMVC中的统一异常处理我们通过ControllerAdvice来处理
/*** 统一的异常处理类*/
/*@ResponseBody
@ControllerAdvice*/
@Slf4j
@RestControllerAdvice(basePackages = "com.msb.mall.product.controller")
public class ExceptionControllerAdvice {/*** 处理验证异常的方法* @param e*/@ExceptionHandler(value = MethodArgumentNotValidException.class)public R handlerValidExecption(MethodArgumentNotValidException e){Map<String,String> map = new HashMap<>();e.getFieldErrors().forEach((fieldError)->{map.put(fieldError.getField(),fieldError.getDefaultMessage());});return R.error(400,"提交的数据不合法").put("data",map);}/*** 系统其他的异常处理* @param throwable* @return*/@ExceptionHandler(Throwable.class)public R handlerExecption(Throwable throwable){log.error("错误信息:",throwable);return R.error(400,"未知异常信息").put("data",throwable.getMessage());}
}
响应编码的规制制订,因为随着后面的业务越来越复杂,我们在响应异常信息的时候尽量准确的给客户端有用的提示信息。
通用的错误列表,响应的编码统一为5位数字,前面两位约定为业务场景,最后三位约定为错误码
10:表示通用
/001:参数格式错误 10001
/002:未知异常 10002
11:商品
12:订单
13:物流
14:会员
…
定义对应的枚举类
package com.msb.common.exception;/*** 错误编码和错误信息的枚举类*/
public enum BizCodeEnume {UNKNOW_EXCEPTION(10000,"系统未知异常"),VALID_EXCEPTION(10001,"参数格式异常");private int code;private String msg;BizCodeEnume(int code,String msg){this.code = code;this.msg = msg;}public int getCode(){return code;}public String getMsg(){return msg;}
}
在统一异常处理中我们就可以使用通用的编码
package com.msb.mall.product.exception;import com.msb.common.exception.BizCodeEnume;
import com.msb.common.utils.R;
import lombok.extern.slf4j.Slf4j;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;import java.util.HashMap;
import java.util.Map;/*** 统一的异常处理类*/
/*@ResponseBody
@ControllerAdvice*/
@Slf4j
@RestControllerAdvice(basePackages = "com.msb.mall.product.controller")
public class ExceptionControllerAdvice {/*** 处理验证异常的方法* @param e*/@ExceptionHandler(value = MethodArgumentNotValidException.class)public R handlerValidExecption(MethodArgumentNotValidException e){Map<String,String> map = new HashMap<>();e.getFieldErrors().forEach((fieldError)->{map.put(fieldError.getField(),fieldError.getDefaultMessage());});//return R.error(400,"提交的数据不合法").put("data",map);return R.error(BizCodeEnume.VALID_EXCEPTION.getCode(), BizCodeEnume.VALID_EXCEPTION.getMsg()).put("data",map);}/*** 系统其他的异常处理* @param throwable* @return*/@ExceptionHandler(Throwable.class)public R handlerExecption(Throwable throwable){log.error("错误信息:",throwable);//return R.error(400,"未知异常信息").put("data",throwable.getMessage());return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(), BizCodeEnume.UNKNOW_EXCEPTION.getMsg()).put("data",throwable.getMessage());}
}

6.4 分组校验
在实际的业务场景中同一个Entity的校验可能会有不同的规则,比如添加数据品牌id必须为空,而更新数据品牌Id必须不为空,针对这种情况我们需要使用分组校验来实现
1>定义标志类

2>在Entity中指定分组规则

3>通过@Validated注解来实现分组校验

6.5 自定义校验注解
面临特殊的校验需要我们可以通过正则表达式来处理,当然我们也可以通过自定义校验注解的方式来实现。
1> 创建自定义的校验注解
/*** 自定义的校验注解*/
@Documented
@Constraint(validatedBy = { })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ListValue {String message() default "{com.msb.common.valid.ListValue.message}";Class<?>[] groups() default { };Class<? extends Payload>[] payload() default { };int[] val() default {};
}
对应需要创建提示信息的属性文件

2>创建一个自定义的校验器
package com.msb.common.valid;import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.annotation.Annotation;
import java.sql.ClientInfoStatus;
import java.util.HashSet;/*** 对应的校验注解的校验器*/
public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {private HashSet<Integer> set = new HashSet<>();/*** 初始化的方法* 举例:@ListValue(val={1,0})* 获取到 1 0* @param constraintAnnotation*/@Overridepublic void initialize(ListValue constraintAnnotation) {int[] val = constraintAnnotation.val();// 0 1for (int i : val) {set.add(i);}}/*** 判断校验是否成功的方法* @param value 客户端传递的对应的属性的值 判断value是否在0 , 1 中* @param context* @return*/@Overridepublic boolean isValid(Integer value, ConstraintValidatorContext context) {return set.contains(value);}
}
3>关联自定义的校验注解和校验器

相关文章:
【业务功能篇78】微服务-前端后端校验- 统一异常处理-JSR-303-validation注解
5. 前端校验 我们在前端提交的表单数据,我们也是需要对提交的数据做相关的校验的 Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可 校验的页面效果 前端数据…...
pytorch的用法
...
Qt 设置窗口背景
窗口背景无非两种:背景色、背景图片。Qt中窗口背景如何设置? 一、QPalette设置背景 二、实现paintEvent,使用QPainter来绘制背景 三、使用QSS来设置背景 关于QSS的使用不想多说,一般我不用QSS设置窗口背景,也不建议…...
大模型是什么?泰迪大模型能够解决企业哪些痛点?
什么是大模型? 大模型是指模型具有庞大的参数规模和复杂程度的机器学习模型。在深度学习领域,大模型通常是指具有数百万到数十亿参数的神经网络模型。这些模型需要大量的计算资源和存储空间来训练和存储,并且往往需要进行分布式计算和特殊…...
YOLOv7-tracker 目标追踪 输入视频帧
目录 1 项目安装1.1 环境搭建1.2 项目下载1.3 权重下载1.4 环境安装1.5 上传待检测的视频帧 2 视频帧检测与追踪2.1 检测与追踪2.3 结果 参考项目:https://github.com/JackWoo0831/Yolov7-tracker/tree/master github链接:https://github.com/Whiffe/Yo…...
C语言二——C语言编写一段代码,求一元二次方程的根
这段代码实现了解一元二次方程的根的计算。用户需要输入方程的系数a、b、c,然后根据判别式的值确定方程的根的情况,并进行相应的输出。 如果判别式大于0,说明方程有两个实根,分别计算并输出。如果判别式等于0,说明方程…...
用Idea把SpringBoot项目打包镜像上传至docker
1、设置docker把2375端口开起来 命令查看docker装在哪里 vim docker.service 新增 -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock 2、配置Dockerfile 我在跟pom同一层 3、配置docker-maven-plugin <plugin><groupId>com.spotify</groupId><arti…...
基于 SVG 的图形交互方案实践
不知道从什么时候起,人们开始喜欢上数字大屏这种“花里胡哨”的东西,仿佛只要用上“科技蓝”这样神奇的色调,就可以让一家公司焕然一新,瞬间变得科技感满满。不管数字大屏的实际意义,是用来帮助企业监控和决策…...
微服务(rpc)
微服务(rpc) 微服务必备的模块生产者消费者管理平台流量控制集群情况下如何做到流量监控 负载均衡服务发现和治理序列化传输序列化和反序列化 微服务是一种架构风格,将一个应用程序拆分为一组小型、独立的服务,每个服务都可以独立…...
ThinkPHP 多应用配置,及不同域名访问不同应用的配置【详解】
ThinkPHP 多应用配置,及不同域名访问不同应用的配置【详解】 一、安装多应用扩展二、删除项目的中默认的controller文件夹三、创建多应用四、修改config/app.php文件五、测试并且访问多应用六、配置小皮,不同域名访问不同的应用七、小结 一、安装多应用扩…...
Springboot+Mybatis框架是否会取代SSM框架?
个人认真思考的观点:从市场使用来说,会有这个趋势。从技术上来说,不存在被替代这一说。 Spring BootMybatis框架是指使用Spring Boot作为基础框架,并集成Mybatis作为持久层框架的组合,它是一个基于Spring框架的快速开发…...
使用windeployqt和InstallShield打包发布Qt软件的流程
前言 Qt编译之后需要打包发布,并且发布给用户后需要增加一个安装软件,通过安装软件可以实现Qt软件的安装;用于安装软件的软件有很多,这里主要介绍InstallShield使用的流程; 使用windeployqt打包Qt编译后的程序 Qt程序…...
解决selenium的getdrive()方法阻塞问题
selenium里面的Webdriver的get()方法默认是阻塞的,也就是说要等整个页面全都加载完它才会相应。但我们大部分时候不需要用到页面里的所有东西,也许只需要用到里面的一个元素就行了 所以下面是我的解决方法: 初始化代码: # 设置…...
js的闭包
闭包是有权限访问其他函数作用域的局部变量的一个函数 代码 function outer(){const a1;function f(){console.log(a)}f()}outer() 简单来说:闭包内层函数引用的外层函数变量 为什么要使用闭包? 用此方法可以来统计函数调用次数, 但是如…...
ubuntu20.04 直接安装vpp23.06 测试双 VPP Tunnel Ike2
环境信息:VMware Workstation 17 Pro ubuntu20.04 (清华源) ubuntu 源点进去选:ubuntu-22.04.3-desktop-amd64.iso 如果之前装过VPP,用以下命令确定是否卸载干净: dpkg -l | grep vpp dpkg -l | grep DPDK 卸载: …...
mysql sql 执行流程
监控查询缓存的命中率 show status like ‘%qcache%’; mysql 缓存机制,以及 8.0 为啥取消 select sql_NO_Cache * from 表 where xxx; # 不使用缓存...
go-kafka
go kafka包 本文使用的是kafka-go 6.5k 这个包 其他包参考: 我们在细分市场中非常依赖GO和Kafka。不幸的是,在撰写本文时,Kafka的GO客户库的状态并不理想。可用选项是: 萨拉玛(Sarama) 10k,这…...
如何在windows电脑上安装多个node,并可以进行随意切换
一、进入官网http://nvm.uihtm.com/ 下载 二、启动解压后的程序 1.开始安装nvm 选择要安装的目录 一直下一步–下一步–最后点击完成 3.最后点击完成即可  {$file $request->file(attachment);/*echo count($file);dd($file);*/$filenam…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
