优雅的处理参数校验以及异常

news/2024/5/21 12:31:03/文章来源:https://blog.csdn.net/static_coder/article/details/127207356

1、前言

 编写控制层时,我们可能会自己去校验请求参数,就会出现这样的代码:

if (StringUtils.isEmpty(memberSid)) {return new JsonResult(false, "参数memberSid为空");
}
if (null == test) {return new JsonResult(false, "参数test为空");
}

相同的参数在不同的地方运用就是出现类型的冗余的代码。如果我们要快速开发要么把参数校验复制一份出来,要么抽成公用的方法 。重复的代码本来就是代码重构和优化的一个表象,所以这种方式本身不可取。抽成公用方法确实是一个不错的方法,但是未能从本质像解决。

       由此,看能不能使用框架的技术去解决这样问题。试着使用【Spring Validation】能否解决问题。

2、引入依赖

非springboot 项目需要引入一下依赖

<dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId><version>1.1.0.Final</version>
</dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>5.4.1.Final</version>
</dependency>

springboot 项目需要区分版本:

springboot2.3之前,只需要引入一下依赖即可:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.3之前的版本</version>
</dependency>

springboot2.3之后(含2.3),取消了【hibernate-validator】相关的依赖,需要手动引入一下依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>

以下为官方的的说明:

3、了解【Spring Validation】的相关注解

Spring Validation验证框架对参数的验证机制提供了@Validated(Spring's JSR-303规范,是标准JSR-303的一个变种),javax提供了@Valid(标准JSR-303规范),配合BindingResult可以直接提供参数验证结果。

针对参数的注解:

 

@Validated和@Valid的区别:

@Validated

  • 提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制,可参考高效使用hibernate-validator校验框架。
  • 可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上。

@Valid

  • 作为标准JSR-303规范,不支持分组的功能。
  • 可以用在方法、构造函数、方法参数和成员属性(字段)上。

* 因为@Valid可以用来成员属性上,该注解也可以用来校验嵌套的校验。

4、最佳实践

4.1 请求参数的实体

      实体中针对需要校验的字段使用相应的注解,指定输出的message,以及分组。分组是为了区分不同业务场景实体的公用。

@Data
public class BookDTO implements Serializable {private static final long serialVersionUID = 6833185176640090531L;private Integer id;@Max(value = 30L, message = "最高价格不超过30!", groups = {SaveAction.class})private Double price;@NotNull(message = "作者信息不能为空!", groups = {UpdateAction.class})private String author;@Length(min = 5, max = 10, message = "书名的长度必须在5~10之间")private String name;private Date buyDate;// 开启嵌套校验@Validprivate BookContent bookContent;
}

4.2 嵌套类

@Data
public class BookContent implements Serializable {private static final long serialVersionUID = -3018013509162052516L;@NotBlank(message = "书的内容不能为空!")private String content;private Integer pageCount;
}

4.3 分组接口

分组接口只是为了标识使用的场景,接口中没有任何的实现。

public interface SaveAction {}public interface UpdateAction {}

4.4 控制层的实现

      @RequestBody是为了测试方便,使用的json参数提交,也可以使用表单提交。

      参数中没有加分组的都属于默认分组,使用Default.class即可。

@RestController
@RequestMapping("/foo")
public class FooController {@PostMapping ("/test01")public String test01(@Validated({SaveAction.class, Default.class}) @RequestBody BookDTO bookDTO){System.out.println(JSON.toJSONString(bookDTO));Assert.notNull(bookDTO.getId(), "ID信息不能为空!");return "success";}@GetMapping("/test02")public String test02(@RequestParam String a, Date date){if (date != null) {System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(date));}return "success:" + a;}
}

4.5 统一参数处理

     参数的校验不通过,如果控制层不处理的话,都会抛出异常,只需要针对异常处理,获取异常的报错信息响应即可。

     @ControllerAdvice是针对所有的控制Controller。因为前端传递的参数有可能是日期。那我们需要将对应的字符串转成日期,可以使用@InitBinder完成对日期的解析。

     @InitBinder对日期的解析只是针对form-data结构有效,如果是JSON数据的话则无效。

@ControllerAdvice
@Slf4j
public class GlobalHandler {@ExceptionHandler(Exception.class)public ResponseEntity<String> globalExceptionHandler(Exception e){log.warn("异常信息:{}", e);String msg = e.getMessage();if (e instanceof BindException) {msg = ((BindException)e).getBindingResult().getFieldError().getDefaultMessage();}else if (e instanceof MissingServletRequestParameterException) {MissingServletRequestParameterException me = (MissingServletRequestParameterException)e;msg = "参数缺失,缺失的参数:" + me.getParameterName();}return ResponseEntity.ok(msg);}@InitBinderpublic void globalWebDataBinder(WebDataBinder binder){DateFormatter dateFormatter = new DateFormatter("yyyy-MM-dd");String[] patterns = {"yyyy/MM/dd", "yyyyMMdd", "yyyy-MM-dd HH:mm:ss"};dateFormatter.setFallbackPatterns(patterns);binder.addCustomFormatter(dateFormatter, Date.class);}
}

5、异常的处理

       对于绑定参数的处理,归根到底是对异常的处理。对于异常的处理,我们最终需要获取到异常的信息,那我们只需要处理有差异的异常即可。

      曾看到很多文档这对异常逐个处理,但是最终的结果都是 e.getMessage() 。个人觉得没有必要。

      异常的处理包括框架的异常,以及自定义异常。最终包装成用户可以识别的错误信息返回。这也是异常处理的目的。

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

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

相关文章

油溶性PbS量子点近红外发射光PL800nm-1600nm

油溶性PbS量子点近红外发射光PL800nm-1600nm 油溶性PbS量子点产品&#xff0c;表面由疏水配体包覆&#xff0c;平均的量子产率为50%&#xff0c;储存时应避免阳光直射&#xff0c;4度密封暗处保存&#xff0c;可以为客户订制生产800nm&#xff5e;1600nm任一波长不同克数的产品…

叶毓睿:元宇宙发展与治理中,治理的主体是谁?治理的对象是谁?

中国移联元宇宙产业委员会联席秘书长、《元宇宙十大技术》著者之一、高效能服务器和存储技术国家重点实验室首席研究员叶毓睿&#xff1a;治理之可能性的关键在于延续性和开创性。 2022年9月24日&#xff0c;元宇宙产业委特别筹备的“发展与治理”2022元宇宙共治大会暨《元宇宙…

【JT-1/2电子式同步检查继电器】

1 用途 JT-1型同步检查继电器用于两端供电线路的自动重合闸线路中&#xff0c;其作用在于检查线路上电压的存在及线路上和变电站汇流排上电压向量间的相角差。 2 结构和原理 2.1 本继电器采用嵌入式安装&#xff0c;其主体部分系插拔式结构 2.2 本继电器主体部分与DT-1型同…

【Python基础面向对象】self、类变量和实例变量、__init__

哈喽兄弟们&#xff0c;我们接着上篇继续学习面向对象。 面向对象化编程所有的实例对象和实例方法都必须以self作为第一个参数&#xff0c;文章内容接上一章&#xff1a;Python面向对象编程基础之面向对象思想和特点、类和对象。这个系列将会很详细的解释清楚Python面向对象编程…

java实现多层级目录树详解

一&#xff0c;引言 在开发中&#xff0c;经常遇到前端需要实现一个多层级的目录树&#xff0c;那么后端就需要根据这种结构返回对应的数据&#xff0c;因此在这里记录一下本人在开发中是如何实现这个多层级的目录树。 二&#xff0c;建表建库 在建表时&#xff0c;需要注意…

(附源码)计算机毕业设计SSM悠哈出租车管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

模拟IC设计到底怎么学?给初学者一点建议

想必大家都知道&#xff0c;模拟IC设计非常难学。就拿最普遍的晶体管来说&#xff0c;我们分析它的时候必须首先分析直流偏置&#xff0c;其次在分析交流输出电压。可以说&#xff0c;这是一项相当复杂的工作。有些朋友一直吐槽模拟IC设计真的非常难学&#xff0c;那么到底该怎…

SWAT模型 建模方法、实例应用、高级进阶

目录 第一部分&#xff1a;【建模及实践】SWAT模型在水文水资源、面源污染模拟中的实践技术应用及典型案例分析 第二部分&#xff1a;【高级进阶】SWAT模型高阶应用暨无资料地区建模、不确定分析与气候变化、土地利用对面源污染影响模型改进及案例分析 基于ArcGIS的SWAT模型是…

yolov5-6.1的完全使用手册,含模型训练测试(可训练自己的数据集)

安装yolov5 安装命令如下下所示&#xff0c;包含了下载yolov5-6.1&#xff0c;及相关包安装命令。yolov5项目目前已经更新到6.2&#xff0c;支持对图像数据的分类&#xff0c;但使用较为麻烦&#xff0c;因此仅以6.1为例进行说明。安装yolov5后&#xff0c;切记不要安装wandb&…

条件区域循环的Sumif

问题:Sumif条件为D12:D16,求和区域从E3:E8向右,条件区域为B3:D8三列循环 函数解决:=SUMIF(OFFSET($B$3:$B$8,,MOD(COLUMN(C1),3)),$D12,E$3:E$8) 思路: 利用Mod(Column(C1),3),右拉生成0、1、2、0、1、2……这样的循环数 利用Offset,从B3:B8起,右拉生成向右偏移0、1、…

国民技术MCU之串口烧录

国民技术MCU串口烧录 前言 在我们使用国民技术单片机的时候&#xff0c;一般是用JLink SWD来烧录调试固件。 但是在某些情况下&#xff0c;比如需要刷写固件的现场没有JLink工具&#xff0c;采用批量生产、或者MCU在程序上电后SWD功能没有正常运行&#xff08;变砖&#xff0…

数据库概述06(视图)

视图 常见的数据库对象 表TABLE 表是存储数据的逻辑单元&#xff0c;以行和列的形式存在&#xff0c;列就是字段&#xff0c;行就是记录 数据字典 就是系统表&#xff0c;存放数据库相关信息的表。系统表的数据通常由数据库系统维护&#xff0c;程序员通常不应该修改&#xf…

一些有关多线程的‘‘八股文‘‘?!

目录 一. 常见的锁策略: 二. CAS 三.synchronized原理 四. HashTable, HashMap, ConcurrentHashMap 之间的区别: 五. 死锁的成因, 和解决方案: 一. 常见的锁策略: 1.乐观锁 vs 悲观锁: 描述的是两种不同的加锁态度 乐观:预测锁冲突概率不高,因此做的工…

2022年NPDP新版教材知识集锦--【第一章节】(2)

【制定战略的工具】 SWOT分析&#xff1a;由四个英文单词的首字母组合而成&#xff0c;分别是优势(Strengths)、劣势(Weaknesses)、机会(Opportunities)和威胁(Threats)。 ⚫优势&#xff1a;某企业或项目优于其他企业或项目的特点。 ⚫劣势&#xff1a;某企业或项目不如其他…

python学习笔记:numpy库,使用matpotlib库绘图

目录 一.Numpy库 1.什么是numpy? 2.Numpy数组和原生Python array数组之间的区别 3.Numpy数组 ​编辑 4.numpy数组的运算 5.numpy的索引&#xff0c;切片 二.matplotlib 1.绘制直线 2.绘制曲线 3.散点图绘制 4.多界面绘制 5.柱形图绘制 6.3D图形绘制 一.Numpy库 1.…

数据库与MPP数仓(三十):pigsty部署

pigsty是pg的开箱即用版本,提供完善监控和高可用功能,高质量的国产开源工程,监控面板非常详尽,保姆级别的文档; 参考:腾讯云VPC部署 | Pigsty 参考:Releases Vonng/pigsty GitHub pigsty源码基本上都是使用ansible的playbook编写,使用ansible同时配置多台机器,在角…

基于Ubuntu20.04安装Nvidia驱动、Cuda和CudNN

基于Ubuntu20.04安装Nvidia驱动、Cuda和CudNN 前言 nvidia驱动&#xff0c;cuda&#xff0c;cudnn三者关系 1 nvidia驱动 1.1 nvidia驱动安装 首先Nvidia驱动应该是最好理解的&#xff0c;它就是GPU显卡的软件驱动程序&#xff0c;和计算机其他的硬件驱动一样。Nvidia官网提…

设计管理工具的三个基本类别

什么是用于管理设计过程的优质设计管理工具?成功管理设计项目需要正确的工具和软件。设计管理工具的三个基本类别是&#xff1a;通讯工具、时间线管理工具、文件和资源管理工具。 1、通讯工具 沟通工具使团队成员能够保持在同一页面上&#xff0c;无论他们的工作地点如何。他们…

app自动化测试之Andriod WebView如何测试

Hybrid App&#xff08;混合模式移动应用&#xff09;是介于 Web-app、Native-app 之间的 app&#xff0c;本质上是 Native-app 中嵌入 WebView 组件&#xff0c;在 WebView 组件里可以访问 Web App。Hybrid App 在给用户良好交互体验的同时&#xff0c;还具备了 Web App 的跨平…

在RTL书写中如何考虑延迟,面积等

在RTL书写中如何考虑延迟&#xff0c;面积等 文章目录在RTL书写中如何考虑延迟&#xff0c;面积等reference在RTL编码中考虑时延对多if语句&#xff1a;对单if语句case和if嵌套“先加后选”和“先选后加”调整计算顺序在RTL编码中考虑面积操作符优化资源共享多比特逻辑优化在RT…