【业务功能篇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…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
