JSR-303 实现参数校验
1. 什么是JSR-303
JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是Hibernate Validator。
此实现与 Hibernate ORM 没有任何关系。
JSR-303 用于对 Java Bean 中的字段的值进行验证。
Spring MVC 3.x 之中也大力支持 JSR-303,可以在控制器中对表单提交的数据方便地验证。
JSR-303官网
2. JSR-303内置校验规则
3. SpringBoot整合JSR-303
3.1 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
3.2 在类的属性上加上相应校验注解
@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;
3.3 实现校验
在Controller的处理方法的参数前,加@Valid注解,出错后,错误信息会放置在 Errors或BindingResult 的对象参数中
@RequestMapping("/login")
public String testValid(@Valid User user, BindingResult result){
if (result.hasErrors()){
List<ObjectError> errorList = result.getAllErrors();
for(ObjectError error : errorList){
System.out.println(error.getDefaultMessage());
}
}
return "test";
}
3.4 通过全局统一异常替换BindingResult写法
给controller后的需要校验的bean后加一个BindingResult类就可以获得校验的结果,但是相对麻烦,每次都要写BindingResult。在大项目中一般使用统一异常处理校验结果,返回json格式,如下所示
//后端校验异常
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public RtnResult handValidException(MethodArgumentNotValidException e){
BindingResult bindingResult = e.getBindingResult();
Map<String, Object> map = new HashMap<>();
bindingResult.getFieldErrors().forEach(fieldError -> {
map.put(fieldError.getField(),fieldError.getDefaultMessage());
});
return RtnResult.fail(map);
}
3.5 分组校验(多场景的复杂校验)
分组校验应用场景:添加和更新需要不同的校验规则时
3.5.1 先创建添加和更新的接口,该接口仅仅是多场景的一个标识,接口内容为空即可。
public interface AddGroup {
}
public interface UpdateGroup {
}
3.5.2 在 @NotBlank(message = “密码不能为空”) 后加上groups 用于表示给校验注解标注什么情况下需要校验(添加/更新)
//AddGroup.class是添加的标识组,可以有多个
@NotBlank(message = "密码不能为空", groups = {AddGroup.class})
private String password;
@NotBlank(message = "姓名不能为空", groups = {AddGroup.class,UpdateGroup.class})
private String name;
3.5.3 替换controller层原来的@Valid注解,使用mvc提供的@Validated注解,否则不生效
//添加用户 @Validated指定哪个操作使用校验
@PostMapping("/addUser")
public RtnResult addUser(@Validated(AddGroup.class) @RequestBody ClaimUser claimUser){
return claimUserService.addUser(claimUser);
}
如果使用分组校验,校验注解没有使用groups,则校验不生效,一定要使用groups!!
4. 自定义校验注解
当给出的校验规则不能满足需求,可以通过自定义校验来实现,如某个字段只能为0或1。
举例场景:当显示和隐藏的属性showStatus只能时0或1,需要自定义校验注解和自定义校验器
4.1 导入依赖
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
4.2 编写自定义校验注解
PS:可以参考JSR-303原本的校验
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME) //运行环境
@Repeatable(List.class)
@Documented
@Constraint(validatedBy = { }) // 指定自定义校验器,可以适配多个校验器,一个注解完成多种校验
public @interface NotNull {
String message() default "{javax.validation.constraints.NotNull.message}"; // 校验失败的提示信息
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
int[] vals() default {}; //标注在属性上的vals={0,1}
}
4.3 编写自定义校验注解
//自定义校验器 必须实现ConstraintValidator
//ConstraintValidator中的 泛型1:绑定的泛型注解 泛型2:校验的数据类型
public class ListValueConstraintValidator implements ConstraintValidator<ListValue, Integer> {
private Set<Integer> set = new HashSet<>();
//初始化方法,获取在Entity类的属性上标注的符合条件的Integer的值:{0,1}
@Override
public void initialize(ListValue constraintAnnotation) {
int[] vals = constraintAnnotation.vals();
for (int val : vals) {
set.add(val);
}
}
//判断是否校验成功方法
//integer:传进来的值
//判断依据:看integer是否在初始化方法的数组中
@Override
public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
if (set.contains(integer)) {
return true;
}
return false;
}
}
4.4 在需要校验的属性上添加自定义注解
@ListValue(vals={0,1},message = "开关状态只能是0或1")
private Integer showStatus;
4.5 自定义参数校验(这边以校验手机号为例)
- 编写注解类
//说明该注解将被包含在javadoc中
@Documented
// 注解的作用目标 类上、方法上、属性上
@Target({ElementType.FIELD, ElementType.PARAMETER})
// 注解的保留位置
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {IsMobileValidator.class }) // 与约束注解关联的验证器
public @interface IsMobile {
boolean required() default true;
String message() default "手机号不正确";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
- 编写校验规则
public class IsMobileValidator implements ConstraintValidator<IsMobile, String> {
private boolean required;
/**
* 重写initialize方法获取注解实例
* @param ca
*/
@Override
public void initialize(IsMobile ca) {
// 重注解实例中获信息
required = ca.required();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// value就是要校验的数据了
if (value != null && required) {
// 手机号校验规则
System.out.println(value);
String regexp= "^(((\\+\\d{2}-)?0\\d{2,3}-\\d{7,8})|((\\+\\d{2}-)?(\\d{2,3}-)?([1][3,4,5,7,8][0-9]\\d{8})))$";
boolean matches = Pattern.matches(regexp, value);
System.out.println(matches);
return matches;
}
return false;
}
}
- 使用自定义校验注解
/**
* 手机号
*/
@IsMobile(message = "用户手机号不正确")
private String tel;
JSR-303 实现参数校验的更多相关文章
- SpringMVC中的 JSR 303 数据校验框架说明
JSR 303 是java为Bean数据合法性校验提供的标准框架,它已经包含在JavaEE 6.0中. JSR 303 通过在Bean属性上标注类似于@NotNull.@Max等标准的注解指定校验规则 ...
- JSR 303 - Bean Validation 介绍及最佳实践
JSR 303 - Bean Validation 介绍及最佳实践 JSR 303 – Bean Validation 是一个数据验证的规范,2009 年 11 月确定最终方案.2009 年 12 月 ...
- JSR 303 - Bean Validation 介绍及最佳实践(转)
JSR 303 – Bean Validation 是一个数据验证的规范,2009 年 11 月确定最终方案.2009 年 12 月 Java EE 6 发布,Bean Validation 作为一个 ...
- JSR 303 - Bean Validation 简单介绍及用法
一.JSR-303简单介绍 JSR-303 是 JAVA EE 6 中的一项子规范.叫做 Bean Validation,官方參考实现是Hibernate Validator. 此实现与 Hibern ...
- Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验,使用消息资源文件对消息国际化
导包和配置 导入 JSR 303 的包.hibernate valid 的包 <dependency> <groupId>org.hibernate.validator< ...
- JSR 303 进行后台数据校验
一.JSR 303 1.什么是 JSR 303? JSR 是 Java Specification Requests 的缩写,即 Java 规范提案. 存在各种各样的 JSR,简单的理解为 JSR 是 ...
- Spring基础系列-参数校验
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9953744.html Spring中使用参数校验 概述 JSR 303中提出了Bea ...
- Spring Boot 2.x基础教程:JSR-303实现请求参数校验
请求参数的校验是很多新手开发非常容易犯错,或存在较多改进点的常见场景.比较常见的问题主要表现在以下几个方面: 仅依靠前端框架解决参数校验,缺失服务端的校验.这种情况常见于需要同时开发前后端的时候,虽然 ...
- 如何在 Spring/Spring Boot 中做参数校验?你需要了解的都在这里!
本文为作者原创,如需转载请在文首著名地址,公众号转载请申请开白. springboot-guide : 适合新手入门以及有经验的开发人员查阅的 Spring Boot 教程(业余时间维护中,欢迎一起维 ...
- 如何在 Spring/Spring Boot 中做参数校验
数据的校验的重要性就不用说了,即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据. 本文结合自己在项目 ...
随机推荐
- 使用 TensorBoard 可视化模型、数据和训练
使用 TensorBoard 可视化模型.数据和训练 在 60 Minutes Blitz 中,我们展示了如何加载数据,并把数据送到我们继承 nn.Module 类的模型,在训练数据上训练模型,并在测 ...
- Nginx和Tomcat配置SSL实现https访问
环境:CentOS 7 Nginx版本: nginx/1.18.0 1. 安装nginx 详细步骤可以参考如下官网:http://nginx.org/en/linux_packages.html#RH ...
- 全球城市ZoneId和UTC时间偏移量的最全对照表
前言 你好,我是A哥(YourBatman). 如你所知,现行的世界标准时间是UTC世界协调时,时区已不直接参与时间计算.但是呢,城市名称or时区是人们所能记忆和容易沟通的名词,因此我们迫切需要一个对 ...
- Java并发包源码学习系列:JDK1.8的ConcurrentHashMap源码解析
目录 为什么要使用ConcurrentHashMap? ConcurrentHashMap的结构特点 Java8之前 Java8之后 基本常量 重要成员变量 构造方法 tableSizeFor put ...
- 消息队列之kafka
消息队列之activeMQ 消息队列之RabbitMQ 1.kafka介绍 kafka是由scala语言开发的一个多分区,多副本的并且居于zookeeper协调的分布式的发布-订阅消息系统.具有高吞吐 ...
- [从源码学设计]蚂蚁金服SOFARegistry之延迟操作
[从源码学设计]蚂蚁金服SOFARegistry之延迟操作 0x00 摘要 SOFARegistry 是蚂蚁金服开源的一个生产级.高时效.高可用的服务注册中心. 本系列文章重点在于分析设计和架构,即利 ...
- 笔记 | pandas之时间序列学习随笔1
1. 时间序列自动生成 ts = pd.Series(np.arange(1, 901), index=pd.date_range('2010-1-1', periods=900)) 最终生成了从20 ...
- JavaScript中的异步函数
JavaScript中的异步函数 ES8 的 async/await 旨在解决利用异步结构组织代码的问题.为此, ECMAScript 对函数进行了扩展,为其增加了两个新关键字: async 和 aw ...
- LOJ10065 北极通讯站
Waterloo University 2002 北极的某区域共有 n 座村庄,每座村庄的坐标用一对整数 (x,,y) 表示.为了加强联系,决定在村庄之间建立通讯网络.通讯工具可以是无线电收发机,也可 ...
- Spark练习之Transformation操作开发
Spark练习之Transformation操作开发 一.map:将集合中的每个元素乘以2 1.1 Java 1.2 Scala 二.filter:过滤出集合中的偶数 2.1 Java 2.2 Sca ...