Spring?Boot集成validation實(shí)現(xiàn)參數(shù)校驗(yàn)功能
1.什么是Bean Validation?
Bean Validation 是一個(gè)運(yùn)行時(shí)的數(shù)據(jù)驗(yàn)證框架,在驗(yàn)證之后驗(yàn)證的錯(cuò)誤信息會(huì)被馬上返回。java 在2009年的 JAVAEE 6 中發(fā)布了 JSR303以及javax下的validation包內(nèi)容。這項(xiàng)工作的主要目標(biāo)是為java應(yīng)用程序開(kāi)發(fā)人員提供 基于java對(duì)象的 約束(constraints)聲明 和 對(duì)約束的驗(yàn)證工具(validator),以及約束元數(shù)據(jù)存儲(chǔ)庫(kù)和查詢(xún)API。但是該內(nèi)容并沒(méi)有具體的實(shí)現(xiàn), Hibernate-Validator框架 提供了 JSR 303 規(guī)范中所有內(nèi)置 constraint 的實(shí)現(xiàn),除此之外還有一些附加的 constraint。
常用的Validation注解
一些最常見(jiàn)的驗(yàn)證注解如下:
@NotNull: 標(biāo)記字段不能為null@NotEmpty: 標(biāo)記集合字段不為空(至少要有一個(gè)元素)@NotBlank: 標(biāo)記字段串字段不能是空字符串(即它必須至少有一個(gè)字符)@Min/@Max: 標(biāo)記數(shù)字類(lèi)型字段必須大于/小于指定的值@Pattern: 標(biāo)記字符串字段必須匹配指定的正則表達(dá)式@Email: 標(biāo)記字符串字段必須是有效的電子郵件地址
2.代碼工程
實(shí)驗(yàn)?zāi)繕?biāo):校驗(yàn)controller傳遞的參數(shù)
pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springboot-demo</artifactId>
<groupId>com.et</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>validtion</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
</dependencies>
</project>controller
Spring 自動(dòng)將傳入的 JSON 映射到 Java 對(duì)象參數(shù)上。 現(xiàn)在,我們要校驗(yàn)傳入的 Java 對(duì)象是否滿(mǎn)足我們預(yù)先定義的約束條件。 為了校驗(yàn)傳入 HTTP 請(qǐng)求的請(qǐng)求實(shí)體,我們?cè)?REST 控制器中使用 @Valid 注解對(duì)請(qǐng)求實(shí)體進(jìn)行標(biāo)記:
package com.et.validation.controller;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.et.validation.entity.UserInfoReq;
import com.fasterxml.jackson.databind.util.JSONPObject;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class HelloWorldController {
@RequestMapping("/hello")
public Map<String, Object> showHelloWorld(@RequestBody @Validated UserInfoReq req){
Map<String, Object> map = new HashMap<>();
map.put("msg", JSONUtil.toJsonStr(req));
return map;
}
}enttiy
我們有一個(gè) int類(lèi)型 字段,它的值必須介于 1 和 10200之間,如@Min 和@Max 注解所定義的那樣。 我們還有一個(gè) String 類(lèi)型字段,它必須是一個(gè) IP 地址,正如@Pattern 注解中的正則表達(dá)式所定義的那樣(正則表達(dá)式實(shí)際上仍然允許大于 255 的無(wú)效 IP 地址,但在我們創(chuàng)建自定義驗(yàn)證器時(shí),我們將在本教程的后面修復(fù)這個(gè)BUG)。
package com.et.validation.entity;
import com.et.validation.validate.IpAddress;
import lombok.Data;
import lombok.ToString;
import javax.validation.constraints.*;
@Data
@ToString
public class UserInfoReq {
@NotNull(message = "id不能為null")
private Long id;
@NotBlank(message = "username不能為空")
private String username;
@NotNull(message = "age不能為null")
@Min(value = 1, message = "年齡不符合要求")
@Max(value = 200, message = "年齡不符合要求")
private Integer age;
@Email(message = "郵箱不符合規(guī)范")
private String email;
@IpAddress(message = "ip不符合規(guī)范")
//@Pattern(regexp = "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$")
private String ip;
}自定義error捕獲
當(dāng)校驗(yàn)失敗時(shí),我們通常希望向客戶(hù)端返回一條有意義的錯(cuò)誤消息。 為了使客戶(hù)端能夠顯示有用的錯(cuò)誤消息,我們應(yīng)該返回一個(gè)統(tǒng)一的數(shù)據(jù)結(jié)構(gòu),其中包含每個(gè)校驗(yàn)失敗的錯(cuò)誤消息。 我們?cè)谶@里所做的只是從異常中讀取有關(guān)校驗(yàn)失敗信息并將它們轉(zhuǎn)換到我們的 ValidationErrorResponse 數(shù)據(jù)結(jié)構(gòu)中。 請(qǐng)注意@ControllerAdvice 注解,它使得上述類(lèi)型異常的異常處理機(jī)制對(duì)所有Controller全局可用。
package com.et.validation.error;
import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
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.ResponseStatus;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
@ControllerAdvice
class ErrorHandlingControllerAdvice {
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
ValidationErrorResponse onConstraintValidationException(
ConstraintViolationException e) {
ValidationErrorResponse error = new ValidationErrorResponse();
for (ConstraintViolation violation : e.getConstraintViolations()) {
error.getViolations().add(
new Violation(violation.getPropertyPath().toString(), violation.getMessage()));
}
return error;
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
ValidationErrorResponse onMethodArgumentNotValidException(
MethodArgumentNotValidException e) {
ValidationErrorResponse error = new ValidationErrorResponse();
for (FieldError fieldError : e.getBindingResult().getFieldErrors()) {
error.getViolations().add(
new Violation(fieldError.getField(), fieldError.getDefaultMessage()));
}
return error;
}
}package com.et.validation.error;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Data
public class ValidationErrorResponse implements Serializable {
private List<Violation> violations = new ArrayList<>();
}package com.et.validation.error;
import lombok.Data;
import java.io.Serializable;
@Data
public class Violation implements Serializable {
private final String fieldName;
private final String message;
public Violation(String fieldName, String message) {
this.fieldName = fieldName;
this.message = message;
}
}自定義validator
如果官方提供可用的校驗(yàn)注解不能滿(mǎn)足我們的需要,我們自己可以定義一個(gè)自定義校驗(yàn)器。 自定義校驗(yàn)注解需要包含以下要素:
- 參數(shù)
message, 指定 ValidationMessages.properties 文件中的屬性鍵,用于在校驗(yàn)失敗時(shí)解析提示消息, - 參數(shù)
groups, 允許定義在何種情況下觸發(fā)此校驗(yàn)(稍后我們將討分組校驗(yàn)) - 參數(shù)
payload, 允許定義要通過(guò)此校驗(yàn)傳遞的Payload(因?yàn)檫@是一個(gè)很少使用的功能,我們不會(huì)在本教程中介紹它) - 一個(gè)
@Constraint注解, 指定實(shí)現(xiàn) ConstraintValidator 接口的校驗(yàn)邏輯類(lèi)。
校驗(yàn)器的實(shí)現(xiàn)如下所示:
package com.et.validation.validate;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Target({ FIELD })
@Retention(RUNTIME)
@Constraint(validatedBy = IpAddressValidator.class)
@Documented
public @interface IpAddress {
String message() default "{IpAddress.invalid}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}package com.et.validation.validate;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class IpAddressValidator implements ConstraintValidator<IpAddress, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
Pattern pattern =
Pattern.compile("^([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$");
Matcher matcher = pattern.matcher(value);
try {
if (!matcher.matches()) {
return false;
} else {
for (int i = 1; i <= 4; i++) {
int octet = Integer.valueOf(matcher.group(i));
if (octet > 255) {
return false;
}
}
return true;
}
} catch (Exception e) {
return false;
}
}
}以上只是一些關(guān)鍵代碼,所有代碼請(qǐng)參見(jiàn)下面代碼倉(cāng)庫(kù)
代碼倉(cāng)庫(kù)
3.測(cè)試
啟動(dòng)spring boot應(yīng)用
測(cè)試參數(shù)校驗(yàn)接口
訪問(wèn)http://127.0.0.1:8088/hello,返回結(jié)果如下

4.引用
到此這篇關(guān)于Spring Boot集成validation實(shí)現(xiàn)參數(shù)校驗(yàn)功能的文章就介紹到這了,更多相關(guān)Spring Boot集成validation參數(shù)校驗(yàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- spring?參數(shù)校驗(yàn)Validation示例詳解
- SpringBoot使用validation進(jìn)行自參數(shù)校驗(yàn)的方法
- SpringBoot使用Validation包進(jìn)行輸入?yún)?shù)校驗(yàn)
- springboot之Validation參數(shù)校驗(yàn)詳細(xì)解讀
- SpringBoot使用Validation進(jìn)行參數(shù)校驗(yàn)的示例詳解
- SpringBoot集成Validation參數(shù)校驗(yàn)
- 基于Spring Validation實(shí)現(xiàn)全局參數(shù)校驗(yàn)異常處理的示例詳解
相關(guān)文章
教你用MAT工具分析Java堆內(nèi)存泄漏問(wèn)題的解決方法
今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著如何使用MAT工具分析Java堆內(nèi)存泄漏問(wèn)題的解決方法展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06
兩個(gè)小例子輕松搞懂 java 中遞歸與尾遞歸的優(yōu)化操作
這篇文章主要介紹了兩個(gè)小例子輕松搞懂 java 中遞歸與尾遞歸的優(yōu)化操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
intellij IDEA配置springboot的圖文教程
Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架,其設(shè)計(jì)目的是用來(lái)簡(jiǎn)化新Spring應(yīng)用的初始搭建以及開(kāi)發(fā)過(guò)程。接下來(lái)通過(guò)本文給大家介紹intellij IDEA配置springboot的圖文教程,感興趣的朋友一起看看吧2018-03-03
java 利用java反射機(jī)制動(dòng)態(tài)加載類(lèi)的簡(jiǎn)單實(shí)現(xiàn)
下面小編就為大家?guī)?lái)一篇java 利用java反射機(jī)制動(dòng)態(tài)加載類(lèi)的簡(jiǎn)單實(shí)現(xiàn)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-09-09
Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(40)
下面小編就為大家?guī)?lái)一篇Java基礎(chǔ)的幾道練習(xí)題(分享)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧,希望可以幫到你2021-07-07
解決resultMap映射數(shù)據(jù)錯(cuò)誤的問(wèn)題
這篇文章主要介紹了解決resultMap映射數(shù)據(jù)錯(cuò)誤的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
解決kafka:org.apache.kafka.common.errors.TimeoutException問(wèn)題
這篇文章主要介紹了解決kafka:org.apache.kafka.common.errors.TimeoutException問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01

