SpringBoot使用Validation校验参数

 

目录

简单介绍

准备工作

常用注解说明

参数校验(校验失败不会进入controller,可以直接返回)

 普通实体类

 实体类嵌套 

 resultful风格校验

总结

 使用流程

 注意事项

Result实体类


简单介绍

   数据校验很重要,在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据。

   本文在vue+springboot的基础上校验请求数据

准备工作

   springboot2.3 版本之前无需导入此jar包, spring-boot-starter-web中自带了

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

常用注解说明

   注意:下列注解可同时使用多个

注解校验功能
@Null必须为null
@NotNull不能为null,可以是空
@NotBlank只能作用在String上,字符串不能为null,字符串trim()后也不能等于“”
@NotEmpty不能为null,集合、数组、map等size()不能为0;字符串trim()后可以等于“”
@Length(min = 6, max = 16)指定传入的字符串长度
@Size(max, min)检测容器元素个数
@Pattern必须满足指定的正则表达式
@Max最大值
@Min最小值
@DecimalMax设置不能超过最大值
@DecimalMin设置不能超过最小值
@Range设置最大和最小值
@Negative负数不包括0
@NegativeOrZero负数或0
@PositiveOrZero正数或0
@Digits(integer, fraction)限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@AssertFalse限制必须为false
@AssertTrue限制必须为true
@Past被注释的元素必须是一个过去的日期
@PastOrPresent被注释的元素必须是一个过去或当前的日期
@Future被注释的元素必须是一个将来的日期
@FutureOrPresent被注释的元素必须是一个将来或当前的日期
@Email被注释的元素必须是电子邮件地址

参数校验(校验失败不会进入controller,可以直接返回)

  普通实体类

  1.     在实体类字段上添加注解校验
  2.     在@RequestBody后添加@Validated注解
  3.    编写异常控制器统一收集异常

实体类

import lombok.Data;
import lombok.ToString;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.*;
import java.util.List;

@Data
@ToString
public class Student {
    //姓名不可为空
    @NotBlank(message = "姓名不可为空")
    private String name;

    //年龄不可为空且必须在0-200之间
    @NotNull(message = "年龄不可为空")
    @Max(value = 200,message = "年龄不可大于200")
    @Min(value = 0,message = "年龄不可小于0")
    private Integer age;

    //时间传入格式为yyyyMMddHHmmss
    @Pattern(regexp = "^((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229))([0-1]?[0-9]|2[0-3])([0-5][0-9])([0-5][0-9])$",message = "时间格式有误")
    @Length(min = 14, max = 14,message = "时间格式有误")
    @NotBlank(message = "时间不可为空")
    private String time;

    //邮箱不可为空且格式正确
    @NotBlank(message = "邮箱不可为空")
    @Email(message = "邮箱格式有误")
    private String email;

    //爱好不可为空
    @Size(min = 1,message = "爱好不可为空")
    @NotNull(message = "爱好不可为空")
    private List<String> likeList;
}

 controller

@RestController
@RequestMapping("student")
public class StudentController {

    @PostMapping("add")
    public Result add(@RequestBody @Validated Student student){
        System.out.println("student = " + student);
        return new Result("0000","添加成功");
    }

}

统一异常处理

import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Path;
import java.util.*;


@RestControllerAdvice
public class GlobalControllerAdvice {

    /**
     * 校验@RequestBody异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(BindException.class)
    public Result bindExceptionHandler(BindException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        Map map = new HashMap();
        for(FieldError fieldError:fieldErrors){
            //字段名
            String field = fieldError.getField();
            //字段传值错误信息
            String message = fieldError.getDefaultMessage();
            map.put(field,message);
        }
        return new Result("400","输入参数有误", map);
    }


    /**
     * 校验@PathVariable异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result handleConstraintViolationException(ConstraintViolationException e) {
        Map map = new HashMap();
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        Iterator<ConstraintViolation<?>> iterator = violations.iterator();
        while(iterator.hasNext()){
            ConstraintViolation<?> violation = iterator.next();

            //resultful路径
            Path path = violation.getPropertyPath();
            //字段传值错误信息
            String message = violation.getMessage();
            String p = "resultful-"+path;
            map.put(p,message);
        }
        return new Result("400","输入参数有误", map);
    }

}

测试结果

  实体类嵌套 

      假设一个学生有多本书,要求前台同时传入学生与图书信息

  1.    在引用实体类变量上添加@Valid注解即可

图书实体类

import lombok.Data;
import lombok.ToString;

import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;

@Data
@ToString
public class Book {
    @NotBlank(message = "图书名称不可为空")
    private String name;

    @DecimalMin(value = "0.00",message = "图书价格不小于0")
    @DecimalMax(value = "300.00",message = "图书价格不大于300")
    @NotNull
    private BigDecimal price;
}

学生实体类

 测试结果

 resultful风格校验

  1.  直接在@PathVariable添加规则校验
  2.  在controller层添加@Validated注解

 

 测试结果

总结

 使用流程

  1.   导入jar包
  2.   在实体类上添加规则校验注解
  3.   在controller参数上添加@Validated注解
  4.   编写统一校验异常处理

 注意事项

  1.   上面提供的统一异常处理类已经同时处理了@RequestBody@PathVariable参数的处理
  2.   处理@RequestBody参数校验在@RequestBody后添加@Validated注解
  3.   处理@PathVariable参数校验在controller添加@Validated注解

Result实体类

import lombok.Data;
import lombok.ToString;

@Data
@ToString
public class Result {

    private String code;
    private String message;
    private Object data;

    public Result(String code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public Result(String code, String message) {
        this.code = code;
        this.message = message;
    }

    public Result() {
    }
}

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值