spring-boot-starter-validation?校驗參數(shù)的實現(xiàn)
一、前言
本章介紹使用spring-boot-starter-validation 校驗 SpringMVC 的入?yún)ⅰ?/p>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.2</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
二、常用注解
三、定義分組
用于分組校驗。
使用場景,對同一個對象例如User(username , id) 在不同的接口時 需要的校驗規(guī)則不同。
例如,訪問一個接口需要 username 不為null且長度大于0 ,id>=0 ; 訪問另一個接口 需要 username 參數(shù)的長度 在 [1,3]之間。
public class ValidateGroup { public interface FirstGroup { } public interface SecondeGroup { } public interface ThirdGroup { } }
四、定義需要校驗的對象
import javax.validation.constraints.Min; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Size; import lombok.Data; @Data public class User { @NotEmpty(message = "用戶名不能為空") @Size(message = "用戶名長度 [1-3] ", min = 1, max = 3,groups = ValidateGroup.FirstGroup.class) private String username; @Min(message = "id不得小于0", value = 0) private Integer id; }
五、在handler 即 Controller中 校驗
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.nbpicc.controller.ValidateGroup.FirstGroup; @RestController @RequestMapping("/") public class TestController { @PostMapping("test3") public User test3(@RequestBody @Validated({ FirstGroup.class }) User u) { System.out.println(u); return u; } @PostMapping("test4") public User test4(@Validated User u) { System.out.println(u); return u; } }
校驗失敗,會直接拋出異常。這樣不太友好,可以使用@ControllerAdvice處理全局異常。
六、定義全局異常處理類
import java.util.List; 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.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import lombok.extern.slf4j.Slf4j; @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(value = BindException.class) public JsonResult exceptionHandle(BindException exception) { BindingResult result = exception.getBindingResult(); StringBuilder errorMsg = new StringBuilder(); List<FieldError> fieldErrors = result.getFieldErrors(); fieldErrors.forEach(error -> { log.error("field: " + error.getField() + ", msg:" + error.getDefaultMessage()); errorMsg.append(error.getDefaultMessage()).append("!"); }); return JsonResult.fail(errorMsg.toString()); } @ExceptionHandler(value = MethodArgumentNotValidException.class) public JsonResult MyExceptionHandle(MethodArgumentNotValidException exception) { BindingResult result = exception.getBindingResult(); StringBuilder errorMsg = new StringBuilder(); List<FieldError> fieldErrors = result.getFieldErrors(); fieldErrors.forEach(error -> { log.error("field: " + error.getField() + ", msg:" + error.getDefaultMessage()); errorMsg.append(error.getDefaultMessage()).append("!"); }); return JsonResult.fail(errorMsg.toString()); } // 處理運行時異常 @ExceptionHandler(RuntimeException.class) public JsonResult doHandleRuntimeException(RuntimeException e) { log.error(e.getMessage(), e); e.printStackTrace(); return JsonResult.fail(e.getMessage()); } }
另外JsonResult.java用于接口返回統(tǒng)一個json格式
import com.fasterxml.jackson.annotation.JsonInclude; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; /** *@author wang *@Date 2020-9-14 * **/ @Data @Accessors(chain = true) @NoArgsConstructor @AllArgsConstructor @JsonInclude(JsonInclude.Include.NON_NULL) public class JsonResult<T> { /** 成功 */ public static final int SUCCESS=200; /**內(nèi)部服務(wù)器錯誤**/ public static final int FAIL=500; /** 沒有登錄 */ public static final int NOT_LOGIN = 400; /** 發(fā)生異常 */ public static final int EXCEPTION = 401; /** 系統(tǒng)錯誤 */ public static final int SYS_ERROR = 402; /** 參數(shù)錯誤 */ public static final int PARAMS_ERROR = 403; /** 不支持或已經(jīng)廢棄 */ public static final int NOT_SUPPORTED = 410; /** AuthCode錯誤 */ public static final int INVALID_AUTHCODE = 444; /** 太頻繁的調(diào)用 */ public static final int TOO_FREQUENT = 445; /** 未知的錯誤 */ public static final int UNKNOWN_ERROR = 499; private Integer code; private String msg; private T data; public static JsonResult fail() { return new JsonResult(FAIL, "請求處理失敗",null); } public static JsonResult fail(String msg) { return new JsonResult(FAIL, msg,null); } public static JsonResult fail(Integer code,String msg) { return new JsonResult(code, msg,null); } public static JsonResult success() { return new JsonResult(SUCCESS,"請求處理成功",null); } public static JsonResult success(String msg) { return new JsonResult(SUCCESS,msg,null); } public static <T> JsonResult success(T data) { return new JsonResult<T> (SUCCESS,"請求處理成功",data); } public static <T> JsonResult success(String msg,T data) { return new JsonResult<T>(SUCCESS, msg,data); } public static JsonResult err() { return build(EXCEPTION); } public static JsonResult err(String msg) { return build(EXCEPTION, msg); } public JsonResult<T> code(int code) { this.code = code; return this; } public JsonResult<T> msg(String msg) { this.msg = msg; return this; } public JsonResult<T> data(T data) { this.data = data; return this; } public static JsonResult build() { return new JsonResult(); } public static JsonResult build(int code) { return new JsonResult().code(code); } public static JsonResult build(int code, String msg) { return new JsonResult<String>().code(code).msg(msg); } public static <T> JsonResult<T> build(int code, T data) { return new JsonResult<T>().code(code).data(data); } public static <T> JsonResult<T> build(int code, String msg, T data) { return new JsonResult<T>().code(code).msg(msg).data(data); } }
當(dāng)然還有其他異常處理方式可以參考:http://www.dbjr.com.cn/article/244379.htm
七、測試效果
八、嵌套對象的校驗
import lombok.Data; import javax.validation.Valid; import javax.validation.constraints.*; @Data public class User { @NotEmpty(message = "用戶名不能為空") @Size(message = "長度 [1-3] ", min = 1, max = 3, groups = ValidateGroup.FirstGroup.class) private String username; @Min(message = "id不得小于0", value = 0) private Integer id; @NotBlank(message = "地址不能為空", groups = {ValidateGroup.ThirdGroup.class, ValidateGroup.SecondeGroup.class}) private String address; //在內(nèi)部屬性是自定義對象的時候添加 @Valid 注解 ,即可開啟對In對象的校驗。 //記得添加@NotNull注解,否則該對象可以為null,并且此時In對象的校驗規(guī)則也不會拋出異常 。 @Valid @NotNull(message = "In 對象不能為null ", groups = {ValidateGroup.ThirdGroup.class, ValidateGroup.SecondeGroup.class}) private In in; }
/** *自定義的對象,User對象中的一個屬性。 */ @Data public class In { @NotBlank(message = "str不能為空", groups = {ValidateGroup.ThirdGroup.class, ValidateGroup.SecondeGroup.class}) private String str; }
九、自定義注解(自定義校驗規(guī)則)
9.1 實現(xiàn)ConstraintValidator接口
import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; public class WordConstraintValidator implements ConstraintValidator<CustomValidaor, Object> { @Override public boolean isValid(Object value, ConstraintValidatorContext context) { // 具體的校驗規(guī)則 return value.toString().length() == 10; } }
9.2 自定義注解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; @Target({ ElementType.METHOD, ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = WordConstraintValidator.class) public @interface CustomValidaor { String message(); // groups 和 payload 這兩個parameter 必須包含,不然會報錯 Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
9.3 使用
@Data public class Inner { @NotBlank(message = "str不能為空", groups = { ValidateGroup.ThirdGroup.class, ValidateGroup.SecondeGroup.class }) @CustomValidaor(message = "長度必須為10", groups = { ValidateGroup.ThirdGroup.class, ValidateGroup.SecondeGroup.class }) private String str; }
9.4測試
訪問接口
@PostMapping("test6") public User test6(@Validated({ValidateGroup.SecondeGroup.class}) @RequestBody User u) { System.out.println(u); return u; }
到此這篇關(guān)于spring-boot-starter-validation 校驗參數(shù)的實現(xiàn)的文章就介紹到這了,更多相關(guān)spring-boot-starter-validation 校驗參數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot + validation 接口參數(shù)校驗的思路詳解
- Spring?Boot集成validation實現(xiàn)參數(shù)校驗功能
- SpringBoot使用Validation包進(jìn)行輸入?yún)?shù)校驗
- spring?boot?validation參數(shù)校驗與分組嵌套各種類型及使用小結(jié)
- springboot中使用Hibernate-Validation校驗參數(shù)詳解
- SpringBoot使用Validation進(jìn)行參數(shù)校驗的示例詳解
- spring boot輸入數(shù)據(jù)校驗(validation)的實現(xiàn)過程
- 從零到掌握Spring Boot Validation 接口校驗的詳細(xì)過程
相關(guān)文章
Java實現(xiàn)郵箱發(fā)送功能實例(阿里云郵箱推送)
這篇文章主要給大家介紹了關(guān)于Java實現(xiàn)郵箱發(fā)送功能的相關(guān)資料,利用阿里云郵箱推送,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09關(guān)于jdk9、jdk10、jdk11、jdk12、jdk13新特性說明
這篇文章主要介紹了關(guān)于jdk9、jdk10、jdk11、jdk12、jdk13新特性說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05SpringBoot過濾器實現(xiàn)項目內(nèi)接口過濾詳解
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何利用過濾器實現(xiàn)項目內(nèi)接口過濾,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-04-04Java 8對LinkedList元素進(jìn)行排序的方法詳解
在Java中,LinkedList是一種基于鏈表的數(shù)據(jù)結(jié)構(gòu),與ArrayList相比,它在進(jìn)行插入和刪除操作時表現(xiàn)出更好的性能,然而,LinkedList的元素排序也是開發(fā)中常見的需求之一,本文介紹了Java8對LinkedList元素進(jìn)行排序的方法,需要的朋友可以參考下2024-11-11SpringCloudAlibaba整合Feign實現(xiàn)遠(yuǎn)程HTTP調(diào)用的簡單示例
這篇文章主要介紹了SpringCloudAlibaba 整合 Feign 實現(xiàn)遠(yuǎn)程 HTTP 調(diào)用,文章中使用的是OpenFeign,是Spring社區(qū)開發(fā)的組件,需要的朋友可以參考下2021-09-09如何使用IntelliJ IDEA的HTTP Client進(jìn)行接口驗證
這篇文章主要介紹了如何使用IntelliJ IDEA的HTTP Client進(jìn)行接口驗證,本文給大家分享最新完美解決方案,感興趣的朋友跟隨小編一起看看吧2024-06-06Spring Security Remember me使用及原理詳解
這篇文章主要介紹了Spring Security Remember me使用及原理詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09java創(chuàng)建線程池的7種實現(xiàn)方法
在Java中線程池是一種管理線程的機(jī)制,它可以創(chuàng)建一組線程并重復(fù)使用它們,避免了創(chuàng)建和銷毀線程的開銷,這篇文章主要給大家介紹了關(guān)于java創(chuàng)建線程池的7種實現(xiàn)方法,需要的朋友可以參考下2023-10-10