详解SpringBoot中的参数校验(项目实战)

 更新时间:2020年07月29日 09:18:52   作者:yese777  
这篇文章主要介绍了SpringBoot中的参数校验,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

Java后端发工作中经常会对前端传递过来的参数做一些校验,在业务中还要抛出异常或者不断的返回异常时的校验信息,充满了if-else这种校验代码,在代码中相当冗长。例如说,用户注册时,会校验手机格式的正确性,用户名的长度等等。虽说前端也可以做参数校验,但是为了保证我们API接口的可靠性,以保证最终数据入库的正确性,后端进行参数校验不可忽视。 Hibernate Validator 提供了一种统一方便的方式,让我们快速的实现参数校验。

Hibernate Validator 使用注解,实现声明式校验。而在实现原理上,也是基于 Spring AOP 拦截,实现校验相关的操作。 javax.validation.constraints 包下,定义了一系列的约束( constraint )注解。文末会贴上一些常用的注解。 如果项目的框架是 spring boot 的话,在 spring-boot-starter-web 中已经包含了 Hibernate-validator 的依赖( 版本<2.3 )。 2.3 以后的版本中 spring-boot-starter-web 已经去除了这个依赖,需要手动引入 Hibernate-validator 依赖,并且有一些变化,因此 2.3.x 的版本暂不研究。本文使用的版本是 2.2.8

实战

1、创建实体类

package com.yese.pojo;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.*;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {
 /**
 * 用户ID
 */
 @NotNull(message = "用户id不能为空")
 private Long userId;

 /**
 * 用户名
 */
 @NotBlank(message = "用户名不能为空")
 @Length(max = 20, message = "用户名不能超过10个字符")
 @Pattern(regexp = "^[\\u4E00-\\u9FA5A-Za-z0-9\\*]*$", message = "用户名限制:最多10字符,包含文字、字母和数字")
 private String username;

 /**
 * 密码
 */
 @NotBlank(message = "密码不能为空")
 private String password;

 /**
 * 手机号
 */
 @NotBlank(message = "手机号不能为空")
 @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误")
 private String mobile;

 /**
 * 性别
 */
 @NotNull(message = "性别不能为空")
 private Integer sex;

 /**
 * 年龄
 */
 @NotNull(message = "年龄不能为空")
 @Min(value = 1, message = "年龄最小为1岁")
 @Max(value = 120, message = "年龄最大为120岁")
 private Integer age;

 /**
 * 邮箱
 */
 @NotBlank(message = "邮箱不能为空")
 @Email(message = "邮箱格式错误")
 private String email;

}

2、创建controller

package com.yese.controller;

import com.yese.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class UserController {

 /**
 * controller方法的入参里面在实体类前面加上@Validated
 */
 @PostMapping("/user")
 public void add(@RequestBody @Validated User user) {
 log.info("user====={}", user);
 }

}

3、创建全局异常处理器

package com.yese.config;


import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;

/**
 * 全局异常处理器
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
 /**
 * post方式提交json数据,参数校验失败后,会抛出一个MethodArgumentNotValidException
 */
 @ExceptionHandler(MethodArgumentNotValidException.class)
 public Map<String, Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
 // 获取所有的错误
 // List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
 // 获取错误提示
 // System.out.println(fieldErrors.get(0).getDefaultMessage());
 // 获取错误字段
 // System.out.println(fieldErrors.get(0).getField());

 // 将所有的错误提示使用";"拼接起来并返回
 StringJoiner sj = new StringJoiner(";");
 e.getBindingResult().getFieldErrors().forEach(x -> sj.add(x.getDefaultMessage()));

 // 此处通常定义一个全局相应对象返回
 Map<String, Object> map = new HashMap<>();
 // 此处状态码可以通过枚举或者常量定义
 map.put("code", 1001);
 map.put("msg", sj.toString());
 return map;
 }

 /**
 * get方式提交参数,参数校验失败后,会抛出一个ConstraintViolationException
 */
 @ExceptionHandler(ConstraintViolationException.class)
 public Map<String, Object> handleConstraintViolationException(ConstraintViolationException e) {
 StringJoiner sj = new StringJoiner(";");
 e.getConstraintViolations().forEach(x -> sj.add(x.getMessage()));

 Map<String, Object> map = new HashMap<>();
 map.put("code", 1001);
 map.put("msg", sj.toString());
 return map;
 }

}

4、测试

效果符合预期!

@Valid和@Validated

绝大多数场景下,我们使用 @Validated 注解即可。

而在有嵌套校验的场景,我们使用 @Valid 注解添加到成员属性上。

附常用注解

javax.validation.constraints 包下

注解 验证的数据类型 说明
@Null 任意类型 验证注解的元素值必须是null
@NotNull 任意类型 验证注解的元素值不是null
@NotBlank 字符串 验证注解的元素值不为空(不为null、去除首位空格后长度大于0)
@NotEmpty CharSequence子类型、Collection、Map、数组 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@Min(value=值) 数值类型 验证注解的元素值大于等于@Min指定的value值
@Max(value=值) 和@Min要求一样 验证注解的元素值小于等于@Max指定的value值
@DecimalMin(value=值) 和@Min要求一样 验证注解的元素值大于等于@ DecimalMin指定的value值
@DecimalMax(value=值) 和@Min要求一样 验证注解的元素值小于等于@ DecimalMax指定的value值
@Digits(integer=整数位数, fraction=小数位数) 和@Min要求一样 验证注解的元素值的整数位数和小数位数上限
@Size(min=下限, max=上限) 字符串、Collection、Map、数组等 验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小
@Positive 判断正数
@PositiveOrZero 判断正数或 0 。
@Negative 判断负数。
@NegativeOrZero 判断负数或 0 。
@Past 日期类型 验证注解的元素值(日期类型)比当前时间早
@Future 与@Past要求一样 验证注解的元素值(日期类型)比当前时间晚
@AssertFalse Boolean 验证注解的元素值是false
@AssertTrue Boolean 验证注解的元素值是true
@Range(min=最小值, max=最大值) BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型 验证注解的元素值在最小值和最大值之间
@Email 字符串 验证注解的元素值是Email,也可以通过regexp和flag指定自定义的email格式
@Pattern(regexp=正则表达式,flag=标志的模式) 字符串 验证注解的元素值与指定的正则表达式匹配
@Valid 任何非原子类型 指定递归验证关联的对象如用户对象中有个地址对象属性,如果想在验证用户对象时一起验证地址对象的话,在地址对象上加@Valid注解即可级联验证

org.hibernate.validator.constraints 包下,定义了一系列的约束( constraint )注解。如下:

@Range(min=, max=) :被注释的元素必须在合适的范围内。

@Length(min=, max=) :被注释的字符串的大小必须在指定的范围内。

@URL(protocol=,host=,port=,regexp=,flags=) :被注释的字符串必须是一个有效的 URL 。

@SafeHtml :判断提交的 HTML 是否安全。例如说,不能包含 javascript 脚本等等。

到此这篇关于详解SpringBoot中的参数校验(项目实战)的文章就介绍到这了,更多相关SpringBoot 参数校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java编程Nashorn实例代码

    Java编程Nashorn实例代码

    这篇文章主要介绍了Java编程Nashorn实例代码,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • Java中的OkHttpClient 工具类

    Java中的OkHttpClient 工具类

    这篇文章主要介绍了Java中的OkHttpClient工具类,具有很好的参考价值,希望杜大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Springboot启动后立即某个执行方法的四种方式

    Springboot启动后立即某个执行方法的四种方式

    spring项目如何在启动项目是执行一些操作,在spring中能通过那些操作实现这个功能呢,下面这篇文章主要给大家介绍了关于Springboot启动后立即某个执行方法的四种方式,需要的朋友可以参考下
    2022-06-06
  • 详解maven配置多仓库的方法示例

    详解maven配置多仓库的方法示例

    这篇文章主要介绍了详解maven配置多仓库的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • springboot整合JPA过程解析

    springboot整合JPA过程解析

    这篇文章主要介绍了springboot整合JPA过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • IntelliJ IDEA 2018 最新激活码(截止到2018年1月30日)

    IntelliJ IDEA 2018 最新激活码(截止到2018年1月30日)

    这篇文章主要介绍了IntelliJ IDEA 2018 最新激活码(截止到2018年1月30日)的相关资料,需要的朋友可以参考下
    2018-01-01
  • java中Class.getMethods()和Class.getDeclaredMethods()方法的区别

    java中Class.getMethods()和Class.getDeclaredMethods()方法的区别

    这篇文章主要介绍了java中Class.getMethods()和Class.getDeclaredMethods()方法的区别 ,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-09-09
  • SpringBoot的三大开发工具小结

    SpringBoot的三大开发工具小结

    本文主要介绍了SpringBoot的三大开发工具,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-02-02
  • IDEA实现添加 前进后退 到工具栏的操作

    IDEA实现添加 前进后退 到工具栏的操作

    这篇文章主要介绍了IDEA 前进 后退 添加到工具栏的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • Spring Cloud Alibaba 本地调试介绍及方案设计

    Spring Cloud Alibaba 本地调试介绍及方案设计

    为了解决 本地调试 的问题,本文实现了一种简单实用的策略,可以通过 Nacos 动态配置服务路由,还可以基于用户,部门,组织等级别配置服务路由,实现 本地调试 的同时,实际上也实现 灰度发布,感兴趣的朋友跟随小编一起看看吧
    2021-07-07

最新评论