参考

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 自定义参数校验(这边以校验手机号为例)

  1. 编写注解类
//说明该注解将被包含在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 { }; }
  1. 编写校验规则
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;
}
}
  1. 使用自定义校验注解
    /**
* 手机号
*/
@IsMobile(message = "用户手机号不正确")
private String tel;

JSR-303 实现参数校验的更多相关文章

  1. SpringMVC中的 JSR 303 数据校验框架说明

    JSR 303 是java为Bean数据合法性校验提供的标准框架,它已经包含在JavaEE 6.0中. JSR 303 通过在Bean属性上标注类似于@NotNull.@Max等标准的注解指定校验规则 ...

  2. JSR 303 - Bean Validation 介绍及最佳实践

    JSR 303 - Bean Validation 介绍及最佳实践 JSR 303 – Bean Validation 是一个数据验证的规范,2009 年 11 月确定最终方案.2009 年 12 月 ...

  3. JSR 303 - Bean Validation 介绍及最佳实践(转)

    JSR 303 – Bean Validation 是一个数据验证的规范,2009 年 11 月确定最终方案.2009 年 12 月 Java EE 6 发布,Bean Validation 作为一个 ...

  4. JSR 303 - Bean Validation 简单介绍及用法

    一.JSR-303简单介绍 JSR-303 是 JAVA EE 6 中的一项子规范.叫做 Bean Validation,官方參考实现是Hibernate Validator. 此实现与 Hibern ...

  5. Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验,使用消息资源文件对消息国际化

    导包和配置 导入 JSR 303 的包.hibernate valid 的包 <dependency> <groupId>org.hibernate.validator< ...

  6. JSR 303 进行后台数据校验

    一.JSR 303 1.什么是 JSR 303? JSR 是 Java Specification Requests 的缩写,即 Java 规范提案. 存在各种各样的 JSR,简单的理解为 JSR 是 ...

  7. Spring基础系列-参数校验

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9953744.html Spring中使用参数校验 概述 ​ JSR 303中提出了Bea ...

  8. Spring Boot 2.x基础教程:JSR-303实现请求参数校验

    请求参数的校验是很多新手开发非常容易犯错,或存在较多改进点的常见场景.比较常见的问题主要表现在以下几个方面: 仅依靠前端框架解决参数校验,缺失服务端的校验.这种情况常见于需要同时开发前后端的时候,虽然 ...

  9. 如何在 Spring/Spring Boot 中做参数校验?你需要了解的都在这里!

    本文为作者原创,如需转载请在文首著名地址,公众号转载请申请开白. springboot-guide : 适合新手入门以及有经验的开发人员查阅的 Spring Boot 教程(业余时间维护中,欢迎一起维 ...

  10. 如何在 Spring/Spring Boot 中做参数校验

    数据的校验的重要性就不用说了,即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据. 本文结合自己在项目 ...

随机推荐

  1. 【SpringBoot】Spring Boot,开发社区讨论交流网站首页。

    初识Spring Boot,开发社区讨论交流网站首页. 文章目录 初识Spring Boot,开发社区讨论交流网站首页. 1.项目简介 2. 搭建开发环境 JDK Apache Maven Intel ...

  2. Assuming that agent dropped connection because of access permission

    Assuming that agent dropped connection because of access permission

  3. JavaScript入门-对象

    js对象 本篇主要介绍js里如何创建对象,以及for循环访问对象的成员... 什么是对象? 对象,并不是中文里有男女朋友意思,它是从英文里翻译来的,英文叫[Object],目标,物体,物品的意思. 在 ...

  4. 【Oracle】instr()函数详解

    1)instr()函数的格式  (俗称:字符查找函数) 格式一:instr( string1, string2 )    /   instr(源字符串, 目标字符串) 格式二:instr( strin ...

  5. oracle新增ID主键列,如何补全旧数据的ID值

    1.创建SEQUENCE CREATE SEQUENCE MONKEY.TEST_ADD_IDCOL_ID CACHE 100; 2.新增表栏位 ALTER TABLE MONKEY.TEST_ADD ...

  6. oracle ORA-00060死锁查询、表空间扩容

    --查看被锁住的表 select b.owner,b.object_name,a.session_id,a.locked_mode from v$locked_object a,dba_objects ...

  7. STL_string容器

    一.string概念 string是STL的字符串类型,通常用来表示字符串.而在使用string之前,字符串通常是用char*表示的.string与char*都可以用来表示字符串,那么二者有什么区别. ...

  8. LDAP 简介

    一.使用 Directory Services(目录服务)的目的 对于局域网内的一个用户来讲,工作等其它应用需要,我们必须凭帐号登录主机.用帐号收发E-mail,甚至为了管理需要公司还需要维护一个电子 ...

  9. 将ffmpeg编译为wasm版本且在浏览器中运行

    2020年大前端技术趋势解读 原创 IMWeb团队 腾讯IMWeb前端团队 5天前

  10. collections,random

    collections模块 在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter.deque.defaultdict. ...