springboot后端数据校验JSR303规范详解

后端数据校验JSR303规范详解

本文内容说明:
1、JSR303是规范,定义了一些校验注解
2、hibernate也提供了一些校验注解
3、自定义校验规则(正则)
4、后端获取校验的结果
5、Hibernate Validator官方参考链接
6、其他文章在编写JSR303分组校验,和自定义注解校验



Tip

前端防君子,后端防小人

所以在项目中是采用前端校验+后端校验+全局异常捕获
本文先讲解基础校验和统一异常处理,其他文章在编写
JSR303分组校验
编写自定义校验注解

前端自定义校验请查看我这篇文件入口
JSR303数据校验之分组校验-入口
JSR303自定义校验注解


一:基础校验

1、给bean添加注解

	//包
	import org.hibernate.validator.constraints.URL;
    import javax.validation.constraints.*;

	//使用	
	@NotEmpty//代表字段不为空--会采用默认的消息提示
	private String firstLetter;
	
	@URL(message = "logo必须是地址")//自定义消息提示
	private String logo;

	@NotEmpty//不为空
	@Pattern(regexp = "/^[a-zA-Z]$/",message = "必须是a-z或者A-Z的字母")	//自定义规则-使用正则
	private String firstLetter;
	
	@NotNull//Integer类型使用@NotNull不能使用@NotEmpty
	@Min(value = 0,message = "必须大于等于0")
	private Integer sort;
	
	//友情提取最好是多注解校验-非空+其他

2、在controller开启校验 @Vaild

@Vaild是规范提供的注解
@Validated是spring提供的注解

 public R save( @Valid @RequestBody BrandEntity brand) {}

3、在controller使用BindingResult接收校验结果

  public R save(@Valid @RequestBody BrandEntity brand,BindingResult result) {}

4、将校验结构封装成map返回

代码如下-直接看注释

	//R是自己定义的ResponseJson
 	@RequestMapping("/save")
    public R save(@Valid @RequestBody BrandEntity brand,BindingResult result) {
    	//如果校验失败
        if (result.hasErrors()){
            Map<String, String> map = new HashMap<>();
            //获取校验结果
            result.getFieldErrors().forEach((item)->{
                //FieldError -获取到错误提示
                String message = item.getDefaultMessage();
                //获取错误字段属性的名字
                String field = item.getField();
                map.put(field,message);
            });
            return R.error(400,"数据不合法").put("data",map);
        }else {
            brandService.save(brand);
        }
        return R.ok();
    }

5、效果如图

在这里插入图片描述

6、常用的校验注解

空检查
@Null       验证对象是否为null
@NotNull    验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank   检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty   检查约束元素是否为NULL或者是EMPTY.
    
Booelan检查
@AssertTrue     验证 Boolean 对象是否为 true  
@AssertFalse    验证 Boolean 对象是否为 false  
    
长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内  
@Length(min=, max=) string is between min and max included.

日期检查
@Past       验证 Date 和 Calendar 对象是否在当前时间之前  
@Future     验证 Date 和 Calendar 对象是否在当前时间之后  
@Pattern    验证 对象是否符合正则表达式的规则--自定义校验

自定义校验例如:
@Pattern(regexp = "/^[a-zA-Z]$/",message = "必须是a-z或者A-Z的字母")
private String firstLetter;

7、校验默认的提示消息来源

英文
在这里插入图片描述
中文
在这里插入图片描述

8、在配置中参看有什么校验注解

在这里插入图片描述

9、细节说明:

如果注解爆红是因为新的版本需要是validation启动器
小编使用springboot2.1.8.RELEASE

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

10、更多校验 Hibernate Validator

文档入口

二:全局异常捕获+校验

1、在controller使用@Valid注解

说明:这个方法,实体类的字段需要检验

 public R save(@Valid @RequestBody BrandEntity brand) {
 	 brandService.save(brand);
     return R.ok();
}

2、创建公共异常处理类

说明:
1、MethodArgumentNotValidException.class是校验失败的异常
2、不能精确匹配异常的话,就去大的异常进行处理
3、其余看注释
4、消息提示,小编采用了枚举也附上自定义枚举的代码

package com.atguigu.gulimall.product.exception;
import com.atguigu.common.exception.BizCodeEnume;
import com.atguigu.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;

/**
 * @author suqinyi
 * @Date 2021/4/8
 * 统一处理异常
 */
@Slf4j
//@ResponseBody
//@ControllerAdvice(basePackages = "com.atguigu.gulimall.product.controller")
@RestControllerAdvice(basePackages = "com.atguigu.gulimall.product.controller")//指定位置
public class GulimallExceptionControllerAdvice {

	//注明:R是自定义的Json响应工具类
	
    //数据校验的异常
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R handleVildException(MethodArgumentNotValidException e){
        log.error("数据校验出现异常{},异常类型{}",e.getMessage(),e.getClass());
        BindingResult bindingResult = e.getBindingResult();
        HashMap<String, String> map = new HashMap<>();
        bindingResult.getFieldErrors().forEach(item->{
            map.put(item.getField(),item.getDefaultMessage());
        });
//        return R.error(400,"数据校验出错,不要瞎搞哦").put("data",map);
        return R.error(BizCodeEnume.VALID_EXCEPTION.getCode(),BizCodeEnume.VALID_EXCEPTION.getMsg()).put("data",map);

    }

    //不能精确匹配异常就来这个最大的异常
    @ExceptionHandler(value = Throwable.class)//任意类型的异常
    public R handleException( Throwable throwable){
        //return R.error(400,"出异常了");
        return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
    }

}

自定义异常枚举类

package com.atguigu.common.exception;

/**
 * @author suqinyi
 * @Date 2021/4/8
 */
/***
* 错误码和错误信息定义类
*/
//枚举最大的特点--是私有构造器
public enum BizCodeEnume {

    UNKNOW_EXCEPTION(10000,"系统未知异常"),
    VALID_EXCEPTION(100001,"参数校验失败");

    private int code;
    private String msg;

    //编写构造器
    BizCodeEnume(int code,String msg){
        this.code=code;
        this.msg=msg;
    }

    public int getCode(){
        return code;
    }

    public String getMsg(){
        return msg;
    }
}


3、说明

这样在controller出现校验失败就会抛出异常,公共异常处理类就能捕获,封装成map返回提示。

总结

JSR303是规范,hibernate也提供的一些注解

  • 给bean添加注解: javax.validation.constraints; 定义消息提示
  • 开启校验 @Vaild
  • 使用BindingResult result 拿到校验结果

全局异常捕获

  • 注解@RestControllerAdvice=@ResponseBody+@ControllerAdvice
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

suqinyi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值