Java参数校验中validation和validator的区别详解

 更新时间:2023年10月09日 09:38:08   作者:靖节先生  
这篇文章主要介绍了Java参数校验中validation和validator的区别详解,一般对于复杂的业务参数校验,可以通过校验类单独的校验方法进行处理,通常对于一些与业务无关简单的参数校验可以采用validation和 validator通过注解的方式实现校验,需要的朋友可以参考下

1. 参数校验概述

常见的业务开发中无可避免的会进行请求参数校验,一般对于复杂的业务参数校验,可以通过校验类单独的校验方法进行处理,通常对于一些与业务无关简单的参数校验可以采用javax.validation 和 hibernate-validator通过注解的方式实现校验。

2. validation与validator区别

javax的validation是Java定义的一套基于注解的数据校验规范,目前已经从JSR 303的1.0版本升级到JSR 349的1.1版本,再到JSR 380的2.0版本(2.0完成于2017.08),已经经历了三个版本。 需要注意的是,JSR只是一项标准,它规定了一些校验注解的规范,但没有实现,比如@Null、@NotNull、@Pattern等,它们位于 javax.validation.constraints这个包下。而hibernate validator是对这个规范的实现,并增加了一些其他校验注解,如 @NotBlank、@NotEmpty、@Length等,它们位于org.hibernate.validator.constraints这个包下。

如果我们的项目使用了Spring Boot,hibernate validator框架已经集成在 spring-boot-starter-web中,所以无需再添加其他依赖。如果不是Spring Boot项目,需要添加如下依赖。

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.13.Final</version>
</dependency>

3. validation注解说明

注解说明
@Null被注释的元素必须为null
@NotNull被注释的元素不能为null
@AssertTrue被注释的元素必须为true
@AssertFalse被注释的元素必须为false
@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max,min)被注释的元素的大小必须在指定的范围内
@Digits(integer, fraction)被注释的元素必须是一个数字,其值必须必须在可接受的范围内
@Past被注释的元素必须是一个过去的日期
@Future被注释的元素必须是一个将来的日期
@Pattern(value)被注释的元素必须符合指定的正则表达式

4. validator注解说明

注解说明
@NotBlank被注释的元素不能为null,去除空格( trim() 之后 size > 0) 且长度必须大于0,只能用于注解字符串
@NotEmpty被注释的元素值不为null且不为空,支持字符串、集合、Map和数组类型
@Length(min=,max=)检查所属的字段的长度是否在min和max之间,只能用于字符串
@Email被注释的元素必须是电子邮箱地址
@Range(min=,max=,message=)被注释的元素必须在合适的范围内
@Pattern(regex=,flag=)被注释的元素必须符合指定的正则表达式

注意:

1.正则表达式@Pattern注解只用于String类型的字段上。数字类型的可用@Range注解。

2.需要在Controller中请求对象或者参数前加@Validated或@Valid注解一起使用, @Validated和@Valid注解区别不是很大,一般情况下任选一个即可,区别如下:

注解 @Validated @Valid 所属的包属于org.springframework.validation.annotation包下的,是spring提供的属于javax.validation包下,是jdk给提供的是否支持分组和排序是否

虽然@Validated比@Valid更加强大,在@Valid之上提供了分组功能和验证排序功能,不过在实际项目中一直没有用到过 Hibernate-validate框架中的注解是需要加在实体中一起使用的

5. 日期格式化说明

java日期问题,针对Date类型字段。

1.接收前端校验注解,@DateTimeFormat 接受前台的时间格式 传到后台的格式。

@DateTimeFormat(pattern="yyyy-MM-dd")
private Date born;

2.后端返回给前端日期格式化,使用场景数据库存储的是yyyy-MM-dd HH:mm:ss,但是前端需要yyyy-MM-dd的时候可以使用此注解。

@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
private Date born;

6. 实现验证

6.1 引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>category</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>category</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>
        <!--数据库连接诶-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--常用工具-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>30.1.1-jre</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.6.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>
        <!--swagger2-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.6.1</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.6.1</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <!--字段校验-->
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.13.Final</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

6.2 代码实现

1.实体类

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.*;
/**
 * 员工实体类
 *
 * @author zrj
 * @since 2021/7/31
 **/
@Data
@ApiModel(value = "Employee", description = "员工信息")
public class Employee {
    @NotNull(message = "userId is empty")
    @ApiModelProperty(value = "员工ID")
    private Integer id;
    @NotBlank(message = "员工姓名不能为空")
    @Length(min = 1, max = 100, message = "员工姓名长度不能超过50字")
    @ApiModelProperty(value = "员工姓名")
    private String name;
    @Range(min = 1, max = 200, message = "年龄范围[1,200]")
    @ApiModelProperty(value = "年龄")
    private Integer age;
    @Pattern(regexp = "^[0-1]$", message = "员工类型范围[0,1]")
    @ApiModelProperty(value = "员工类型(0行政岗;1基础岗")
    private String type;
    @Pattern(regexp = "^[1][^0^1^2][0-9]{9}$", message = "员工手机号码不合法")
    @ApiModelProperty(value = "员工手机号码")
    private String phone;
    @Email(message = "员工邮箱不合法")
    @Length(min = 1, max = 50, message = "员工邮箱长度")
    @ApiModelProperty(value = "员工邮箱")
    private String email;
    @Length(min = 0, max = 200, message = "备注长度不能超过100字")
    @ApiModelProperty(value = "备注")
    private String remarks;
}

2.控制类

import com.example.category.entity.Employee;
import com.example.category.entity.Response;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
 * 员工控制类
 *
 * @author zrj
 * @since 2021/7/31
 **/
@RestController
@RequestMapping("/employee")
@Api(value = "employee", description = "员工管理")
public class EmployeeController {
    @GetMapping("/test")
    @ApiOperation(value = "test测试", notes = "test测试", httpMethod = "GET")
    public Response test() {
        return Response.success("查询成功", null);
    }
    /**
     * Valid测试
     * 这里职位测试@Valid,所以不在写其他各层
     */
    @PostMapping("/validEpmloyee")
    @ApiOperation(value = "Valid测试", notes = "Valid测试", httpMethod = "POST")
    public Response<Employee> validEpmloyee(@Valid @RequestBody Employee employee) {
        System.out.println("测试请求对象:" + employee);
        if (employee != null) {
            return Response.success("查询成功", employee);
        }
        return Response.fail("查询失败");
    }
}

3.结果集响应码

package com.example.category.entity;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
 * 结果集封装
 *
 * @author zrj
 * @date 2021/6/2
 * @since V1.0
 **/
@Data
@Component
public class Response<T> {
    private static ResponseCode responseCode;
    /**
     * 提示消息
     */
    private String message;
    /**
     * 具体返回的数据
     */
    private T data;
    /**
     * 状态码
     */
    private String code;
    private Response(String code, String message, T data) {
        this.message = message;
        this.code = code;
        this.data = data;
    }
    private Response(String code, String msg) {
        this.message = msg;
        this.code = code;
    }
    @Autowired
    public Response(ResponseCode responseCode) {
        Response.responseCode = responseCode;
    }
    /**
     * 返回成功Response对象
     */
    public static <T> Response<T> success(String successMessage, T data) {
        return new Response<>(responseCode.getSuccessCode(), successMessage, data);
    }
    /**
     * 返回错误Response对象
     */
    public static <T> Response<T> fail(String errorMessage) {
        return new Response<>(responseCode.getErrorCode(), errorMessage);
    }
}
import lombok.Data;
import org.springframework.stereotype.Component;
/**
 * 响应码
 *
 * @author zrj
 * @date 2021/6/2
 * @since V1.0
 **/
@Data
@Component
public class ResponseCode {
    public String successCode = "200";
    public String errorCode = "500";
    public String authErrorCode = "300";
}

4.异常切面封装类

import com.example.category.entity.Response;
import com.fasterxml.jackson.databind.JsonMappingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
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.method.HandlerMethod;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;
/**
 * 异常切面封装类
 *
 * @author zrj
 * @since 2021/7/31
 **/
@ControllerAdvice
@ResponseBody
@Slf4j
public class ExceptionHandlerAdvice {
    /**
     * Exception
     */
    @ExceptionHandler(Exception.class)
    public Response<String> handleGlobalException(Exception exception, HandlerMethod handlerMethod) {
        if (exception instanceof MethodArgumentNotValidException) {
            List<ObjectError> errors = ((MethodArgumentNotValidException) exception).getBindingResult().getAllErrors();
            StringBuilder sb = new StringBuilder();
            if (!CollectionUtils.isEmpty(errors)) {
                for (ObjectError error : errors) {
                    if (sb.length() != 0) {
                        sb.append(",");
                    }
                    sb.append(error.getDefaultMessage());
                }
            }
            return Response.fail(sb.toString());
        }
        // 约束异常
        if (exception instanceof ConstraintViolationException) {
            Set<ConstraintViolation<?>> exceptionSet = ((ConstraintViolationException) exception).getConstraintViolations();
            StringBuilder sb = new StringBuilder();
            if (!CollectionUtils.isEmpty(exceptionSet)) {
                for (ConstraintViolation<?> set : exceptionSet) {
                    if (sb.length() != 0) {
                        sb.append(",");
                    }
                    sb.append(set.getMessageTemplate());
                }
            }
            return Response.fail(sb.toString());
        }
        // 参数类型转换异常处理
        if (exception instanceof MethodArgumentTypeMismatchException) {
            return Response.fail(((MethodArgumentTypeMismatchException) exception).getName() + " 类型不匹配");
        }
        if (exception instanceof JsonMappingException) {
            return Response.fail("JSON格式错误, " + exception.getLocalizedMessage());
        }
        if (exception instanceof HttpMessageNotReadableException) {
            return Response.fail("请求体格式错误, " + exception.getLocalizedMessage());
        }
        if (exception instanceof MissingServletRequestParameterException) {
            String paramName = ((MissingServletRequestParameterException) exception).getParameterName();
            return Response.fail(paramName + " 不能为空");
        }
        //if (exception instanceof MarketingException) {
        //    MarketingException marketingException = (MarketingException) exception;
        //    return RdfaResult.fail(marketingException.getErrorCodeEnum().getCode(), exception.getMessage());
        //}
        // 其他异常打印日志
        log.error("{}.{} error, ", handlerMethod.getBeanType().getSimpleName(), handlerMethod.getMethod().getName(), exception);
        //if (exception instanceof RpcException) {
        //    return RdfaResult.fail(ErrorCodeEnum.RPC_ERROR.getCode(), "RPC调用错误,请稍后重试");
        //}
        return Response.fail("服务器内部错误,请联系开发人员!");
    }
}

6.3 实现验证

在这里插入图片描述

在这里插入图片描述

到此这篇关于Java参数校验中validation和validator的区别详解的文章就介绍到这了,更多相关validation和validator的区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaWeb学习过程之MVC查询模式详解

    JavaWeb学习过程之MVC查询模式详解

    这篇文章主要介绍了JavaWeb学习过程之MVC查询模式详解的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-09-09
  • 超实用的Java快捷键(总结)

    超实用的Java快捷键(总结)

    下面小编就为大家带来一篇超实用的Java快捷键(总结)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • Java synchronize线程安全测试

    Java synchronize线程安全测试

    这篇文章主要介绍了Java synchronize线程安全测试,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • java邮件收发功能实现代码

    java邮件收发功能实现代码

    这篇文章主要为大家详细介绍了java邮件收发功能实现代码,具有一定的参考价值,感兴趣的朋友可以参考一下
    2016-06-06
  • Mybatis单个参数的if判断报异常There is no getter for property named ''xxx'' in ''class java.lang.Integer''的解决方案

    Mybatis单个参数的if判断报异常There is no getter for property named ''x

    今天小编就为大家分享一篇关于Mybatis单个参数的if判断报异常There is no getter for property named 'xxx' in 'class java.lang.Integer'的解决方案,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Java线程变量ThreadLocal源码分析

    Java线程变量ThreadLocal源码分析

    ThreadLocal用来提供线程内部的局部变量,不同的线程之间不会相互干扰,这种变量在多线程环境下访问时能保证各个线程的变量相对独立于其他线程内的变量,在线程的生命周期内起作用,可以减少同一个线程内多个函数或组件之间一些公共变量传递的复杂度
    2022-08-08
  • Springboot多数据源配置之整合dynamic-datasource方式

    Springboot多数据源配置之整合dynamic-datasource方式

    这篇文章主要介绍了Springboot多数据源配置之整合dynamic-datasource方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • 浅析Java中的内存泄漏

    浅析Java中的内存泄漏

    这篇文章主要介绍了Java中的内存泄漏,包括其基本概念和基本的预防措施,需要的朋友可以参考下
    2015-07-07
  • Java无法输出中文问题及解决

    Java无法输出中文问题及解决

    这篇文章主要介绍了Java无法输出中文问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • SpringBoot实现短信发送及手机验证码登录

    SpringBoot实现短信发送及手机验证码登录

    本文主要介绍了SpringBoot实现短信发送及手机验证码登录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07

最新评论