Java参数校验(最佳实践)

验证参数

关于JSR-303规范 JSR-303是JAVA
EE6中的一项子规范,validation-api是一套标准(JSR-303),叫做Bean
Validation,Hibernate
Validator是Bean Validation的参考实现,提供了JSR-303
规范中所有内置constraint的实现,除此之外Hibernate Validator还附加了一些constraint。

1、校验常用的值Apache Commons Validator完成常用的校验

<dependency><groupId>commons-validator</groupId><artifactId>commons-validator</artifactId><version>1.7</version>
</dependency>
分类项目说明
分类项目
日期和时间校验日期-时间
格式校验
时区支持
日期和时间比较
数字校验各种数字包装类型格式转换校验BigInteger和BigDecimal格式转换校验
数字字符串格式校验(比如带千分隔符)
范围校验
货币格式校验
百分比格式及范围校验
其他校验正则校验
特殊规格数字格式校验
IPV4格式校验
电子邮件地址格式校验
URL校验
域名校验

2、校验非空,大小,数字,布尔,范围等使用(javax.validation.validation-api)

如果是Spring Boot项目工程,可忽略此步骤,因为在Spring Boot组件内部已经内置了validation-api

<dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId><version>1.1.0.Final</version>
</dependency>
Validation-API概述
@AssertFalse被注释的元素必须为 false
@AssertTrue被注释的元素必须为 true
@DecimalMax被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Digits被注释的元素必须是一个在可接受范围内的数字
@Email被注释的元素必须是正确格式的电子邮件地址
@Future被注释的元素必须是将来的日期
@FutureOrPresent被注释的元素必须是现在或将来的日期
@Max被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Min被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Negative被注释的元素必须是一个严格的负数(0为无效值)
@NegativeOrZero被注释的元素必须是一个严格的负数(包含0)
@NotBlank被注释的元素同StringUtils.isNotBlank,只作用在String上,在String属性上加上@NotBlank约束后,该属性不能为null且trim()之后size>0
@NotEmpty被注释的元素同StringUtils.isNotEmpty,作用在集合类上面,在Collection、Map、数组上加上@NotEmpty约束后,该集合对象是不能为null的,并且不能为空集,即size>0
@NotNull被注释的元素不能是Null,作用在Integer上(包括其它基础类),在Integer属性上加上@NotNull约束后,该属性不能为null,没有size的约束;@NotNull作用在Collection、Map或者集合对象上,该集合对象不能为null,但可以是空集,即size=0(一般在集合对象上用@NotEmpty约束)
@Null被注释的元素元素是Null
@Past被注释的元素必须是一个过去的日期
@PastOrPresent被注释的元素必须是过去或现在的日期
@Pattern被注释的元素必须符合指定的正则表达式
@Positive被注释的元素必须严格的正数(0为无效值)
@PositiveOrZero被注释的元素必须严格的正数(包含0)
@Szie被注释的元素大小必须介于指定边界(包括)之间

3、校验非空,大小,数字,布尔,范围等使用(org.hibernate.hibernate-validator)

如果是Spring Boot项目工程,可忽略此步骤,因为在Spring Boot组件内部已经内置了hibernate-validator

<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>5.2.0.Final</version>
</dependency>
hibernate-validator概述
@CodePointLength验证字符序列的编码点长度在min和max之间,可以通过设置规范化策略来验证规范化值
@ConstraintComposition布尔运算符,应用于合成约束注释的所有约束,组合约束注释可以定义组成它的约束的布尔组合,参考ConstraintComposition实现
@CreditCardNumber被注释元素必须是一个有效的信用卡号码,这是Luhn算法的实现,目的是检查用户的错误,而不是信用卡的有效性
@Currency参考moneyaryamount和CurrencyUnit实现
@EAN检查被注释的字符序列是否有效,EAN长度为13,支持的类型是String,当字符串为null被认为有效的
@Email被注释的字符串必须是正确格式的电子邮件地址【已禁用】
@ISBN检查被注释字符序列是否有效,支持的类型是String,null将被认为有效的,在验证过程中,忽略所有非ISBN字符,所有数字和“X”都被认为是有效的ISBN字符。主要用于证以破折号分隔的ISBN时,这很有用,例如:239-992-190-873-492
@Length被注释的字符串的长度必须在指定的范围内
@LuhnCheckLuhn算法检查约束,用于验证一系列数字通过Luhn Modulo 10校验算法。Luhn Modulo 10的计算方法是把每一个数字加起来,每个数字都是奇数,数字(从右到左)的值乘以2,如果值大于9的,则结果数字的总和在总和之前,支持的类型是String,null被认为有效的
@Mod10Check允许验证一系列数字通过Mod10校验和算法。经典的Mod10是通过把每一个奇数加起来计算出来的数字(从右到左)的值乘以乘数,例如:ISBN-13是Modulo 10校验和乘数= 3,在已知的情况下,代码使用乘数的偶数和奇数数字;为了支持这种实现,Mod10约束使用权重选项,它具有与乘数相同的效果,但为偶数数字,支持的类型是String。null被认为有效的
@Mod11Check允许验证一系列数字通过Mod11校验和算法,对于最常见的Mod11变体的总和计算是通过乘以一个权重最右边的数字(不包括校验数字)到最左边。权重从2开始,每个数字加1。然后结果为11 - (sum % 11)计算校验数字。例如:24187的校验位是3 Sum = 7x2 + 8x3 + 1x4 + 4x5 + 2x6 = 74 11 - (74% 11) = 11 - 8 = 3,所以“24187-3”是一个有效的字符序列
@ModCheck被注解的元素表示验证一系列数字通过mod 10或mod 11校验和算法,支持的类型是String,null被认为有效的【已禁用】
@Normalized验证字符序列是否为规范化形式,可以通过设置规范化策略来验证规范化值
@NotBlank同StringUtils.isNotBlank,只作用在String上,在String属性上加上@NotBlank约束后,该属性不能为null且trim()之后size>0(同validation-api)【已禁用】
@NotEmpty同StringUtils.isNotEmpty,作用在集合类上面,在Collection、Map、数组上加上@NotEmpty约束后,该集合对象是不能为null的,并且不能为空集,即size>0【已禁用】
@Range被注释的元素必须在合适的范围内
@SafeHtml验证用户提供的富文本,以确保它不包含恶意代码,如嵌入式元素。注意,这个约束假设您想要验证代表HTML文档正文片段的输入。如果你想要验证代表一个完整HTML文档的输入,在校验的白名单中添加HTML、head和body标记【已禁用】
@ScriptAssert类级约束,它对脚本表达式求值注释的元素。此约束可用于实现验证日常活动,依赖于注释元素的多个属性。脚本表达式可以写在任何脚本或表达式语言中,其中的JSR 223兼容的引擎可以在类路径中找到
@UniqueElements验证集合中的每个对象都是唯一的,即不能找到两个相等的元素集合,这对于JAX-RS很有用,它总是将集合反序列化为一个列表。因此,当重复的将其转换为一个集合时,会被隐式或默认的删除掉
@URL验证带注释的字符串是一个URL,参数protocol、host和port对应URL的相应部分。可以加上一个额外的正则表达式regexp和flags可以进一步定制URL的验证标准。默认情况下,约束验证使用java.net.URL构造函数来验证字符串,这意味着匹配的协议处理程序需要可用,需要保证程序中以下协议的处理程序在默认JVM-HTTP、HTTPS、FTP文件和JAR中存在的

使用

package com.b2c.aiyou.device.inventory.dto;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;import javax.validation.constraints.*;
import java.io.Serializable;
import java.util.Date;
import java.util.List;@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel
public class InventoryEntity implements Serializable {private static final long serialVersionUID = 1L;/*** 类别CODE*/@NotBlank(message = "类别CODE不能为Null")@Size(min = 8, max = 32, message = "类别CODE长度必须在{min}~{max}之间")@ApiModelProperty(value = "类别CODE")private String categoryCode;/*** 类型CODE*/@NotBlank(message = "类型CODE不能为Null")@Size(min = 8, max = 32, message = "类型长度必须在{min}~{max}之间")@ApiModelProperty(value = "类型CODE")private String typeCode;/*** 最高库存量*/@DecimalMax(value = "100000", message = "最高库存量必须小于或等于{value}")@ApiModelProperty(value = "最高库存量")private Integer inventoryMax;/*** 最低库存量*/@DecimalMin(value = "100", message = "最低库存量必须大于或等于{value}")@ApiModelProperty(value = "最低库存量")private Integer inventoryMin;/*** 最小进货量*/@Min(value = 100, message = "最小进货量必须大于或等于{value}")@ApiModelProperty(value = "最小进货量")private Integer restockMin;/*** 最大进货量*/@Max(value = 10000, message = "最大进货量必须小于或等于{value}")@ApiModelProperty(value = "最大进货量")private Integer restockMax;/*** 进货日期*/@Future(message = "进货日期必须大于当前日期")@ApiModelProperty(value = "进货日期")private Date restockTime;/*** 进货周期*/@NotEmpty(message = "进货周期不能为Null")@ApiModelProperty(value = "进货日期")private List<String> periodTime;/*** 备注*/@ApiModelProperty(value = "备注")@Size(min = 50, max = 500, message = "备注内容必须在{min}~{max}之间")private String remark;}
package com.b2c.aiyou.device.inventory.dto;import com.b2c.aiyou.device.common.annotation.Log;
import com.b2c.aiyou.device.inventory.service.IInventoryService;
import com.b2c.aiyou.common.constant.ResultCodeEnum;
import com.b2c.aiyou.common.result.AppException;
import com.b2c.aiyou.common.result.JSONResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;@Slf4j
@RestController
@RequestMapping("/inventory")
public class InventoryController {@PostMapping("/addInventory")public JSONResult addInventory(@Valid @RequestBody InventoryDTO inventoryDTO, BindingResult bindingResult) {try {// 字段校验if (bindingResult.hasErrors()) {return JSONResult.failure(bindingResult);}// TODO 其它校验int result = this.inventoryService.insertInventory(inventoryDTO);if (result > 0) {// 成功处理逻辑return JSONResult.success();} else {// 失败处理逻辑return JSONResult.failure();}} catch (AppException e) {log.info("异常信息:{}", e);return JSONResult.failure(ResultCodeEnum.Failure.getCode(), e.getMessage());}}}

注意:在需要校验的对象后面,必须添加BindingResult来接收校验结果,并对校验结果进行处理bindingResult.hasErrors(),否则校验无意义。

直接在controller里面使用BindingResult,来处理结果,不是太友好。一般在controller里面不加BindingResult,校验参数出现的异常,通过全局异常进行捕获处理

/*** 方法参数校验* @param exception 参数校验异常* @return 错误信息*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<String> handleMethodArgumentNotValidException(final MethodArgumentNotValidException exception) {final String errorMessage = exception.getBindingResult().getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining("; "));log.error("参数校验异常: {}", errorMessage, exception);return ResultUtil.fail(errorMessage);
}

4、总结

1、不管项目是springmvc还是springboot项目,都是可以使用validation-api来做参数校验,校验出现的异常,可以通过全局异常进行捕获处理。

2、在controller层校验成功的前提是,对传入的参数,前面加上@Valid注解

3、在 Controller 类中添加接口,POST 方法中接收设置了 @Valid 相关注解的实体对象,然后在参数中添加 @Valid 注解来开启效验功能,需要注意的是, @ValidGet 请求中接收的平面参数请求无效,一般可以进行手动校验参数,抛出自定义参数错误异常

4、对于一些校验邮箱、ip等,可以使用Apache Commons Validator完成常用的校验

5、一般hibernate-validator校验参数使用的比较少,一般使用其他两个即可

6、如果实体类有嵌套的话,嵌套实体类上要加上@Valid注解

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

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

相关文章

Spring Security 6如何使用?

Spring Security 6 是一个功能强大且高度可定制的身份验证和访问控制框架&#xff0c;它专注于为基于Java的应用程序提供全面的安全解决方案。以下是对Spring Security 6的详细解析&#xff1a; 一、核心功能 身份验证&#xff08;Authentication&#xff09;&#xff1a; 验…

2024最新50道NLP和人工智能领域面试题+答案(中文+英文双版本)

编者按&#xff1a;分享一个很硬核的免费人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 可以当故事来看&#xff0c;轻松学习。 中文版本 自然语言处理 (NLP)已成为语言学、人工智能和计算机科学交叉领域的变革性领域。随着文本数据量的不断增加&…

树莓派5 笔记26:ollama大型语言模型_中文输入法_Python_espeak文字转语音

今日继续学习树莓派5 8G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 与 python 版本如下&#xff1a; 下载大语言模型&#xff0c;下载中文输入法&#…

遗传算法原理与实战(python、matlab)

遗传算法 1.什么是遗传算法 遗传算法&#xff08;Genetic Algorithm&#xff0c;简称GA&#xff09;是一种基于生物进化论和遗传学原理的全局优化搜索算法。它通过模拟自然界中生物种群的遗传机制和进化过程来解决复杂问题&#xff0c;如函数优化、组合优化、机器学习等。遗传…

Anki如何安装插件

文章目录 前言如何安装 Anki 插件开始安装如何获取插件代码安装成功 前言 如果需要扩展 Anki 可能就需要安装一些插件。 这里介绍如何安装插件。 如何安装 Anki 插件 当下载完 anki 后打开软件。 开始安装 点击上面的工具栏&#xff0c;然后点击插件。 这时候会跳出新的弹…

【esp32程序编译提示undefined reference to ‘xxxx‘】

案例1&#xff1a; 【背景】 在使用SquareLine Studio设计UI时&#xff0c;成功导出UI代码&#xff0c;在编译代码的时候提示undefined reference to ‘ui_img_1869164015’&#xff0c;有一个变量无法识别&#xff0c;没有定义。 【定位步骤】 1.首先找到用这个变量的.c文件…

spring中事务介绍

shttps://download.csdn.net/blog/column/12302624/131993937 spring中事务介绍&#xff0c;参考链接如上

Vue3+ElementUI中的Table组件的使用

Vue3ElementUI中的Table组件的使用 校验表格内多个输入框校验 表格滚动到底部 校验 表格内多个输入框校验 注意prop如何写。实现&#xff1a;一旦输入框内部有更改&#xff0c;清空校验&#xff1b;实现&#xff1a;自定义校验错误提示信息样式&#xff1b;实现&#xff1a;在…

html文件运行后界面反馈xxx拒绝连接

概述&#xff1a;我的html代码中包含了外站界面&#xff0c;运行后界面反馈到xxx拒绝连接&#xff0c;我尝试了网上的诸多方法&#xff0c;例如换一个浏览器运行&#xff0c;修改主机网络设置&#xff0c;更改浏览器DNS都没有作用。 <!DOCTYPE html> <html> <h…

MySQL数据库专栏(三)数据库服务维护操作

1、界面维护&#xff0c;打开服务窗口找到MySQL服务&#xff0c;右键单击可对服务进行启动、停止、重启等操作。 选择属性&#xff0c;还可以设置启动类型为自动、手动、禁用。 2、指令维护 卸载服务&#xff1a;sc delete [服务名称] 例如&#xff1a;sc delete MySQL 启动服…

REF_PIN_NAME

REF_PIN_NAME是设计中引脚上的只读属性&#xff0c;表示一个逻辑名称 唯一标识该引脚。 该属性由引脚的名称或层次名称自动定义&#xff0c; 并且不能由用户在HDL或XDC中修改。仅供参考。 该属性不影响任何步骤&#xff0c;但在定义过滤器和其他方面非常有用 Vivado Tcl命令查询…

实验五之用Processing绘画

1.案例代码如下&#xff1a; import generativedesign.*; import processing.pdf.*; import java.util.Calendar; Tablet tablet; boolean recordPDF false; float x 0, y 0; float stepSize 5.0; PFont font; String letters "Sie hren nicht die folgenden Gesnge…

灵神题单——定长滑动窗口

滑动窗口 1343&#xff1a;大小为k且平均值大于等于阈值的子数组数目 class Solution { public:int numOfSubarrays(vector<int>& arr, int k, int threshold) { int ant0;int q[100005],hh0,tt-1;int sum0;for(int i0;i<arr.size();i){if(hh<tt&&i-…

解决方案上新了丨趋动科技推出基于银河麒麟操作系统的异构算力池化解决方案

趋动科技携手麒麟软件打造基于银河麒麟操作系统的异构算力池化解决方案&#xff0c;共同探索AI领域新场景。 人工智能技术作为数字经济发展的重要推手&#xff0c;在各行业业务场景中落地需要大量AI算力资源的有效保障。在IT基础设施普遍云化的今天&#xff0c;AI算力一方面需…

CDN劫持总结

CDN劫持是指黑客通过各种手段&#xff0c;如DNS缓存污染、中间人攻击等&#xff0c;对内容分发网络&#xff08;CDN&#xff09;进行非法控制&#xff0c;导致用户访问被重定向至恶意服务器&#xff0c;从而遭受数据泄露或恶意软件感染的风险。 一、CDN劫持的定义与影响 定义…

【Python】APScheduler:Python中强大的任务调度库

我听见有人猜 你是敌人潜伏的内线 和你相知多年 我确信对你的了解 你舍命救我画面 一一在眼前浮现 司空见惯了鲜血 你忘记你本是娇娆的红颜 感觉你我彼此都那么依恋 &#x1f3b5; 许嵩《内线》 在 Python 开发中&#xff0c;定时任务是非常常见的需求&am…

AI学习记录 - transformers 的 linear 词映射层的详细分析, CrossEntropyLoss 函数解析

创作不易&#xff0c;有用的话点个赞。。。。。。 1. 假设条件 词汇表&#xff1a;假设词汇表包含四个词汇&#xff1a;[token_0, token_1, token_2, token_3]。 模型的输出概率分布&#xff1a;模型的输出经过 Softmax 转换后&#xff0c;得到概率分布&#xff1a;[0.1,0.5,…

88.SAPUI5 Model Binding的问题-在view更改数据,model却不变

目录 1.背景 2.sap.ui.model.BindingMode sap.ui.model.BindingMode.OneWay sap.ui.model.BindingMode.TwoWay 3.oModel.setDefaultBindingMode 方法说明 execOneWay方法 execTwoWay方法 1.背景 在做一个UI5项目&#xff0c;后台读取sap.ui.model.Model后&#xff0c;把…

qt-12工具盒(ToolBox)

工具盒--ToolBox drawer.hdrawer.cppmain.cpp运行图 drawer.h #ifndef DRAWER_H #define DRAWER_H #include <QWidget> #include <QToolBox> #include <QToolButton> #include <QGroupBox> #include <QVBoxLayout>class Drawer : public QToolB…

MiniCPM-V: A GPT-4V Level MLLM on Your Phone论文阅读

大模型的趋势&#xff1a;模型性能越来越好&#xff0c;模型参数变小&#xff0c;端边设备计算能力变强。 MiniCPM-V优点 结果好、OCR能力突出、多分辨率、多语言、易于部署 模型结构 图片encoder适用vit。输入整体以及切片。切片使用自适应算法&#xff0c;通过计算分数&am…