Java参数校验validation和validator区别

article/2025/10/6 20:23:21

Java参数校验validation和validator区别

  • 1. 参数校验概述
  • 2. validation与validator区别
  • 3. validation注解说明
  • 4. validator注解说明
  • 5. 日期格式化说明
  • 6. 实现验证
    • 6.1 引入依赖
    • 6.2 代码实现
    • 6.3 实现验证

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;}@Autowiredpublic 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 实现验证

在这里插入图片描述在这里插入图片描述


http://chatgpt.dhexx.cn/article/9ZRFV9L6.shtml

相关文章

hibernate-validator

validator 简介各种注解好处 validator.validate方法业务逻辑代码中检查传入的参数时为传入的参数类型中各个属性添加注解NotNull、NotBlank、NotEmpty间的区别 简介 validator&#xff0c;翻译过来&#xff0c;就是“验证器”的意思。它是一种注解式参数校验&#xff0c;包名…

validator自定义校验注解及使用

validator自定义校验注解及使用 官方文档&#xff1a;https://docs.jboss.org/hibernate/validator/8.0/reference/en-US/html_single/#validator-customconstraints 用到依赖: <!--validator的依赖如果项目使用的springBoot的依赖可以不用再引入 hibernate-validator 因为…

spring之Validator

初步认识 spring数据验证核心类&#xff1a;①&#xff1a;Validator ②&#xff1a;Errors,两者之间的纽带是Validator中定义的validate方法。 public interface Validator {// 限定Validator的职责&#xff0c;不可能所有的校验全部交给一个Validator来做boolean supports(…

Hibernate-Validator的学习

Hibernate-Validator的学习 此教程基于黑马程序员Java品达通用权限项目&#xff0c;哔哩哔哩链接&#xff1a;https://www.bilibili.com/video/BV1tw411f79E?p49 1.hibernate-validator介绍 早期的网站&#xff0c;用户输入一个邮箱地址&#xff0c;需要将邮箱地址发送到服…

Hibernate Validator源码解析

一、引言 问题&#xff1a;在代码编写的过程中&#xff0c;数据值的校验在JavaEE三层架构&#xff08;展示层、业务层、数据访问层&#xff09;均有涉及&#xff0c;各层的校验需求又是不尽相同的&#xff0c;因此往往会伴随着代码冗余&#xff0c;重复的校验逻辑出现在三层代…

Hibernate Validator简介

亲爱的小伙伴们我来填坑啦&#xff0c;java中优雅的参数校验方法中的校验的实现原理。 1.前言 验证数据是发生在所有应用程序层&#xff08;从表示层到持久层&#xff09;的常见任务。通常在每一层中实现相同的验证逻辑&#xff0c;这既耗时又容易出错。为了避免重复这些验证&…

bootstrapValidator验证最大值最小值范围限制

录入该值的最大值与最小值 bootstrapValidator进行效验&#xff0c;使最小值不可大于最大值&#xff0c;最大值不可小于最小值 刚开始的验证还是没事的&#xff0c;符合正常的验证规则 再把不符合规则的最大值改变&#xff0c;现在最小值已经比最大值小了&#xff0c;但是最大…

class-validator中文教程

官方文档&#xff1a; https://www.npmjs.com/package/class-validator class-validator可以说是一个简化验证的依赖库 &#xff08;采用注释的方式进行校验&#xff09; 但是缺少中文文档和过程&#xff0c;以自己的理解和对官网文档的阅读进行整理输出。 它的好兄弟class-t…

Hibernate Validator 总结大全

背景 代码开发过程中&#xff0c;参数的有效性校验是一项很繁琐的工作&#xff0c; 如果参数简单&#xff0c;就那么几个参数&#xff0c;直接通过ifelse可以搞定&#xff0c;如果参数太多&#xff0c;比如一个大对象有100多个字段作为入参&#xff0c;你如何校验呢&#xff1…

java使用validator进行校验

不管是html页面表单提交的对象数据还是和第三方公司进行接口对接&#xff0c;都需要对接收到的数据进行校验&#xff08;非空、长度、格式等等&#xff09;。如果使用if一个个进行校验&#xff08;字段非常多&#xff09;&#xff0c;这是让人崩溃的过程。幸好jdk或hibernate都…

java validator_Spring中校验器(Validator)的深入讲解

前言 Spring框架的 validator 组件,是个辅助组件,在进行数据的完整性和有效性非常有用,通过定义一个某个验证器,即可在其它需要的地方,使用即可,非常通用。 应用在执行业务逻辑之前,必须通过校验保证接受到的输入数据是合法正确的,但很多时候同样的校验出现了多次,在不…

springboot使用hibernate validator校验

目录 一、参数校验二、hibernate validator校验demo三、hibernate的校验模式 1、普通模式&#xff08;默认是这个模式&#xff09;2、快速失败返回模式四、hibernate的两种校验 1、请求参数校验2、GET参数校验(RequestParam参数校验)3、model校验4、对象级联校验5、分组校验五…

Validator 使用总结

介绍 首先说下大家常用的hibernate-validator&#xff0c;它是对JSR-303/JSR-349标准的实现&#xff0c;然后spring为了给开发者提供便捷集成了hibernate-validator&#xff0c;默认在springmvc模块。 依赖 本文所介绍皆在springboot应用的基础上&#xff0c;首先加上web模块…

浅谈 Android Tombstone(墓碑日志)分析步骤

最近项目产品刚刚出货&#xff0c;客户退机、死机事件频发。日常解决bug中&#xff0c;少不了和墓碑日志打交道&#xff0c;截止今天之前&#xff0c;见到墓碑日志都是一脸懵逼&#xff0c;不知道怎么分析。最近又有了两个日志&#xff0c;硬着头皮看吧。之所以称之为浅谈&…

Android tombstone文件是如何生成的

本节内容我们聚焦到androidQ上&#xff0c;分析android中一个用于debug的功能&#xff0c;那就是tombstone&#xff0c;俗称“墓碑”。现实生活中墓碑一般是给死人准备的&#xff0c;而在android系统中“墓碑”则是给进程准备的。 为何Android要设计出这样一个东西呢&#xff…

【Android NDK 开发】NDK C/C++ 代码崩溃调试 - Tombstone 报错信息日志文件分析 ( 获取 tombstone_0X 崩溃日志信息 )

文章目录 一、崩溃信息描述二、手机命令行操作三、电脑命令行操作四、Tombstone 内容 Tombstone 报错信息日志文件被保存在了 /data/tombstones/ 目录下 , 先 ROOT 再说 , 没有 ROOT 权限无法访问该目录中的信息 ; 使用 Pixel 2 手机进行调试 , 其它 ROOT 后的手机也可以使用 …

Android tombstone 分析案例

Android tombstone 分析案例 tombstone文件内容1. 体系结构2. 发生Crash线程3. 原因4. 寄存器状态4.1 处理器工作模式下的寄存器4.2 未分组寄存器r0 – r74.3 分组寄存器r8 – r144.4 程序计数器pc(r15)4.5 程序状态寄存器4.6 ARM参数规则 5. 回溯栈6. 程序栈7. 寄存器地址附近…

RocksDB Tombstone 详解

目录 为什么会有墓碑&#xff1f; 使用场景 原理 描述 分段 查询 优化点 总结 为什么会有墓碑&#xff1f; 我们知道 TP 数据库一般选择 KV 引擎作为存储引擎&#xff0c;数据库的元数据和数据通过一定的编码规则变成 KV 对存储在存储引擎中&#xff0c;比如 CockroachD…

Tombstone 文件分析

Tombstone 文件分析 /* * 下面信息是dropbox负责添加的 **/ isPrevious: true Build: Rock/odin/odin:7.1.1/NMF26F/1500868195:user/dev-keys Hardware: msm8953 Revision: 0 Bootloader: unknown Radio: unknown Kernel: Linux version 3.18.31-perf-g34cb3d1 (smartcmhardc…

android Tombstone 流程

一 总述 下面是一份dump 的log&#xff1a; 810 876 I system_server: libdebuggerd_client: started dumping process 678 740 740 I /system/bin/tombstoned: registered intercept for pid 678 and type kDebuggerdNativeBacktrace 678 678 I libc : Requested du…