IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringBoot 使用 Validation 数据校验,自定义校验 -> 正文阅读

[Java知识库]SpringBoot 使用 Validation 数据校验,自定义校验

目录

@Validated跟@Valid的区别

实际生产应用

ConstraintViolationException和 MethodArgumentNotValidException异常



@Validated跟@Valid的区别

? ? 在使用前先了解下@Validated跟@Valid的区别,我们点开注解就能看出两者的不同

// Target代表这个注解能使用在类/接口/枚举上,方法上以及方法的参数上
// 注意注意!!!! 它不能注解到字段上
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
// 在运行时期仍然生效(注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在)
@Retention(RetentionPolicy.RUNTIME)
// 这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中,是一个标记注解,没有成员。
@Documented
public @interface Validated {
	// 校验时启动的分组
	Class<?>[] value() default {};

}
// 可以作用于类,方法,字段,构造函数,参数,以及泛型类型上(例如:Main<@Valid T> )
// 简单来说,哪里都可以放
@Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
public @interface Valid {
    //没有提供任何属性
}

1、来源不同?@Valid 是javax.validation包下,而@Validated是spring自生的注解

2、作用范围不同?@Validated无法作用在字段上面

3、注解中的属性不同,如果我们需要分组校验,就需要使用@Validated

实际生产应用

? ? ? ?接下来我们在使用中去了解?Validation ,我们先实现自定义的校验,项目中会有很多状态枚举,我们规定前端传入状态规定特定的值,去实现校验。

首先引入jar

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

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

?先自定义个注解

package com.example.demotest.validator.annotate;

import com.example.demotest.validator.StatusValidator;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;


@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy ={StatusValidator.class})
public @interface Status {

    String[] statusType() default {};

    String message() default "状态传递有误";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

新建自定义校验器,也是注解中validatedBy?指定的

package com.example.demotest.validator;

import com.example.demotest.validator.annotate.Status;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.List;

public class StatusValidator implements ConstraintValidator<Status, Integer> {

    private List<String> typeStatus ;

    @Override
    public void initialize(Status constraintAnnotation) {
        typeStatus = Arrays.asList(constraintAnnotation.statusType());
        ConstraintValidator.super.initialize(constraintAnnotation);
    }

    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {
       if(value !=null){
           if(!typeStatus.contains(String.valueOf(value))){
               return false;
           }
       }
        return true;
    }
}

测试实体类新建

package com.example.demotest.vo;

import com.example.demotest.validator.annotate.Status;
import lombok.Data;

import javax.validation.constraints.NotBlank;

@Data
public class IndexVO {


    @Status(statusType = {"1","2"})
    private Integer loginStatus;

    @NotBlank(message = "id不能为空")
    private String id;

    @NotBlank(message = "名称不能为空")
    private String name;

}

测试接口新建

package com.example.demotest.controller;

import com.example.demotest.vo.IndexVO;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@RestController
@RequestMapping("test")
public class TestController {

    @RequestMapping("index")
    public String test(@Valid @RequestBody IndexVO indexVO){
       return indexVO.getName()+" login success";
    }


}

这里我们统一捕获下异常,这里需要捕获两种校验异常,具体什么时候会出现下面的异常,后面再说

package com.example.demotest.config;

import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;

@RestControllerAdvice
public class ExceptionHandle {



    @ExceptionHandler(value = {ConstraintViolationException.class, MethodArgumentNotValidException.class})
    public String handleValidator(Exception e){
        String msg = null;
        if (e instanceof MethodArgumentNotValidException) {
            BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
            // getFieldError获取的是第一个不合法的参数(P.S.如果有多个参数不合法的话)
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                msg = fieldError.getDefaultMessage();
            }
        } else if (e instanceof ConstraintViolationException) {
            /*
             * ConstraintViolationException的e.getMessage()形如
             *     {方法名}.{参数名}: {message}
             *  这里只需要取后面的message即可
             */
            msg = e.getMessage();
            if (msg != null) {
                int lastIndex = msg.lastIndexOf(':');
                if (lastIndex >= 0) {
                    msg = msg.substring(lastIndex + 1).trim();
                }
            }
            /// ValidationException 的其它子类异常
        } else {
            msg = "处理参数时异常";
        }
        return msg;
    }
}

执行结果:

ConstraintViolationException和 MethodArgumentNotValidException异常

不仅可以校验controller这种,也可以校验普通的方法,上面说的?ConstraintViolationException异常就是通过普通方法校验抛出的异常,普通方法校验,只有类上添加了@Vlidated注解,并且待校验的JavaBean上添加了@Valid的情况下校验才会生效。

?如果我们在校验逻辑中使用到了springBean对象,我们可以在校验器中使用注解生成bean

例如上面的检验器,就可以和数据库或者中间件打交道了

package com.example.demotest.validator;

import com.example.demotest.validator.annotate.Status;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.List;

@Component
public class StatusValidator implements ConstraintValidator<Status, Integer> {

    @Autowired
    private UserService userService;

    private List<String> typeStatus ;

    @Override
    public void initialize(Status constraintAnnotation) {
        typeStatus = Arrays.asList(constraintAnnotation.statusType());
        ConstraintValidator.super.initialize(constraintAnnotation);
    }

    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {
       if(value !=null){
           if(!typeStatus.contains(String.valueOf(value))){
               return false;
           }
       }
        return true;
    }
}

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 20:42:44  更:2022-09-24 20:45:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 9:31:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码