Java參數(shù)校驗(yàn)中validation和validator的區(qū)別詳解
1. 參數(shù)校驗(yàn)概述
常見的業(yè)務(wù)開發(fā)中無可避免的會進(jìn)行請求參數(shù)校驗(yàn),一般對于復(fù)雜的業(yè)務(wù)參數(shù)校驗(yàn),可以通過校驗(yàn)類單獨(dú)的校驗(yàn)方法進(jìn)行處理,通常對于一些與業(yè)務(wù)無關(guān)簡單的參數(shù)校驗(yàn)可以采用javax.validation 和 hibernate-validator通過注解的方式實(shí)現(xiàn)校驗(yàn)。
2. validation與validator區(qū)別
javax的validation是Java定義的一套基于注解的數(shù)據(jù)校驗(yàn)規(guī)范,目前已經(jīng)從JSR 303的1.0版本升級到JSR 349的1.1版本,再到JSR 380的2.0版本(2.0完成于2017.08),已經(jīng)經(jīng)歷了三個(gè)版本。 需要注意的是,JSR只是一項(xiàng)標(biāo)準(zhǔn),它規(guī)定了一些校驗(yàn)注解的規(guī)范,但沒有實(shí)現(xiàn),比如@Null、@NotNull、@Pattern等,它們位于 javax.validation.constraints這個(gè)包下。而hibernate validator是對這個(gè)規(guī)范的實(shí)現(xiàn),并增加了一些其他校驗(yàn)注解,如 @NotBlank、@NotEmpty、@Length等,它們位于org.hibernate.validator.constraints這個(gè)包下。
如果我們的項(xiàng)目使用了Spring Boot,hibernate validator框架已經(jīng)集成在 spring-boot-starter-web中,所以無需再添加其他依賴。如果不是Spring Boot項(xiàng)目,需要添加如下依賴。
<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) | 被注釋的元素必須是一個(gè)數(shù)字,其值必須大于等于指定的最小值 |
| @Max(value) | 被注釋的元素必須是一個(gè)數(shù)字,其值必須小于等于指定的最大值 |
| @DecimalMin(value) | 被注釋的元素必須是一個(gè)數(shù)字,其值必須大于等于指定的最小值 |
| @DecimalMax(value) | 被注釋的元素必須是一個(gè)數(shù)字,其值必須小于等于指定的最大值 |
| @Size(max,min) | 被注釋的元素的大小必須在指定的范圍內(nèi) |
| @Digits(integer, fraction) | 被注釋的元素必須是一個(gè)數(shù)字,其值必須必須在可接受的范圍內(nèi) |
| @Past | 被注釋的元素必須是一個(gè)過去的日期 |
| @Future | 被注釋的元素必須是一個(gè)將來的日期 |
| @Pattern(value) | 被注釋的元素必須符合指定的正則表達(dá)式 |
4. validator注解說明
| 注解 | 說明 |
| @NotBlank | 被注釋的元素不能為null,去除空格( trim() 之后 size > 0) 且長度必須大于0,只能用于注解字符串 |
| @NotEmpty | 被注釋的元素值不為null且不為空,支持字符串、集合、Map和數(shù)組類型 |
| @Length(min=,max=) | 檢查所屬的字段的長度是否在min和max之間,只能用于字符串 |
| 被注釋的元素必須是電子郵箱地址 | |
| @Range(min=,max=,message=) | 被注釋的元素必須在合適的范圍內(nèi) |
| @Pattern(regex=,flag=) | 被注釋的元素必須符合指定的正則表達(dá)式 |
注意:
1.正則表達(dá)式@Pattern注解只用于String類型的字段上。數(shù)字類型的可用@Range注解。
2.需要在Controller中請求對象或者參數(shù)前加@Validated或@Valid注解一起使用, @Validated和@Valid注解區(qū)別不是很大,一般情況下任選一個(gè)即可,區(qū)別如下:
注解 @Validated @Valid 所屬的包屬于org.springframework.validation.annotation包下的,是spring提供的屬于javax.validation包下,是jdk給提供的是否支持分組和排序是否
雖然@Validated比@Valid更加強(qiáng)大,在@Valid之上提供了分組功能和驗(yàn)證排序功能,不過在實(shí)際項(xiàng)目中一直沒有用到過 Hibernate-validate框架中的注解是需要加在實(shí)體中一起使用的
5. 日期格式化說明
java日期問題,針對Date類型字段。
1.接收前端校驗(yàn)注解,@DateTimeFormat 接受前臺的時(shí)間格式 傳到后臺的格式。
@DateTimeFormat(pattern="yyyy-MM-dd") private Date born;
2.后端返回給前端日期格式化,使用場景數(shù)據(jù)庫存儲的是yyyy-MM-dd HH:mm:ss,但是前端需要yyyy-MM-dd的時(shí)候可以使用此注解。
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") private Date born;
6. 實(shí)現(xiàn)驗(yàn)證
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>
<!--數(shù)據(jù)庫連接誒-->
<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>
<!--字段校驗(yàn)-->
<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 代碼實(shí)現(xiàn)
1.實(shí)體類
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.*;
/**
* 員工實(shí)體類
*
* @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基礎(chǔ)崗")
private String type;
@Pattern(regexp = "^[1][^0^1^2][0-9]{9}$", message = "員工手機(jī)號碼不合法")
@ApiModelProperty(value = "員工手機(jī)號碼")
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.結(jié)果集響應(yīng)碼
package com.example.category.entity;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 結(jié)果集封裝
*
* @author zrj
* @date 2021/6/2
* @since V1.0
**/
@Data
@Component
public class Response<T> {
private static ResponseCode responseCode;
/**
* 提示消息
*/
private String message;
/**
* 具體返回的數(shù)據(jù)
*/
private T data;
/**
* 狀態(tài)碼
*/
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);
}
/**
* 返回錯(cuò)誤Response對象
*/
public static <T> Response<T> fail(String errorMessage) {
return new Response<>(responseCode.getErrorCode(), errorMessage);
}
}import lombok.Data;
import org.springframework.stereotype.Component;
/**
* 響應(yīng)碼
*
* @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());
}
// 參數(shù)類型轉(zhuǎn)換異常處理
if (exception instanceof MethodArgumentTypeMismatchException) {
return Response.fail(((MethodArgumentTypeMismatchException) exception).getName() + " 類型不匹配");
}
if (exception instanceof JsonMappingException) {
return Response.fail("JSON格式錯(cuò)誤, " + exception.getLocalizedMessage());
}
if (exception instanceof HttpMessageNotReadableException) {
return Response.fail("請求體格式錯(cuò)誤, " + 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調(diào)用錯(cuò)誤,請稍后重試");
//}
return Response.fail("服務(wù)器內(nèi)部錯(cuò)誤,請聯(lián)系開發(fā)人員!");
}
}6.3 實(shí)現(xiàn)驗(yàn)證


到此這篇關(guān)于Java參數(shù)校驗(yàn)中validation和validator的區(qū)別詳解的文章就介紹到這了,更多相關(guān)validation和validator的區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Springboot項(xiàng)目javax.validation使用方法詳解
- java validation 后臺參數(shù)驗(yàn)證的使用詳解
- java使用Validation進(jìn)行數(shù)據(jù)校驗(yàn)的方式總結(jié)
- JAVA中通過Hibernate-Validation進(jìn)行參數(shù)驗(yàn)證
- JAVA中的字段校驗(yàn)(validation)
- 使用javax.validation.constraints對請求體進(jìn)行統(tǒng)一校驗(yàn)
- Java Validation Api實(shí)現(xiàn)原理解析
- Java Validation Api如何實(shí)現(xiàn)自定義注解
- Javax Validation自定義注解進(jìn)行身份證號校驗(yàn)
- Java使用validation攔截非法提交的數(shù)據(jù)的方法實(shí)現(xiàn)
相關(guān)文章
JavaWeb Session失效時(shí)間設(shè)置方法
這篇文章主要介紹了JavaWeb Session失效時(shí)間設(shè)置方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-12-12
一文了解SpringBoot是如何連接數(shù)據(jù)庫的
Spring Boot提供了一系列的開箱即用的功能和特性,使得開發(fā)人員可以快速構(gòu)建和部署應(yīng)用程序,下面這篇文章主要給大家介紹了關(guān)于SpringBoot是如何連接數(shù)據(jù)庫的相關(guān)資料,需要的朋友可以參考下2023-06-06
spring boot2結(jié)合mybatis增刪改查的實(shí)現(xiàn)
這篇文章主要給大家介紹了關(guān)于spring boot2結(jié)合mybatis增刪改查的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring boot2具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
spring項(xiàng)目對某條單據(jù)進(jìn)行加鎖處理的方法
這篇文章主要給大家介紹了關(guān)于spring項(xiàng)目對某條單據(jù)進(jìn)行加鎖處理的相關(guān)資料,用于對工單單據(jù)進(jìn)行加鎖和解鎖處理,以防止多用戶同時(shí)編輯同一單據(jù),前端傳遞參數(shù)包括單據(jù)ID、類型、鎖超時(shí)時(shí)間等,后端通過Redis實(shí)現(xiàn)鎖機(jī)制,需要的朋友可以參考下2024-11-11

