日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringBoot从入门到精通教程(二十七)- @Valid注解用法详解+全局处理器Exception优雅处理参数验证用法

發布時間:2024/1/1 javascript 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringBoot从入门到精通教程(二十七)- @Valid注解用法详解+全局处理器Exception优雅处理参数验证用法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題痛點

用?Spring 框架寫代碼時,寫接口類,相信大家對該類的寫法非常熟悉。在寫接口時要寫效驗請求參數邏輯,這時候我們會常用做法是寫大量的 if 與 if else 類似這樣的代碼來做判斷,如下所示:

@RestController public class TestController {@PostMapping("/user")public String addUserInfo(@RequestBody User user) {if (user.getName() == null || "".equals(user.getName()) {......} else if(user.getSex() == null || "".equals(user.getSex())) {......} else if(user.getUsername() == null || "".equals(user.getUsername())) {......} else {......}......}}

這樣的代碼如果按正常代碼邏輯來說,是沒有什么問題的,不過按優雅來說,簡直糟糕透了。不僅不優雅,而且如果存在大量的驗證邏輯,這會使代碼看起來亂糟糟,大大降低代碼可讀性。

那么有沒有更好的方法能夠簡化這個過程呢?

答案當然是有,推薦的是使用?@Valid?注解來幫助我們簡化驗證邏輯。

Tips技術點

1. @Valid注解

  • 注解 @Valid 的主要作用是用于數據效驗,可以在定義的實體中的屬性上,添加不同的注解來完成不同的校驗規則,而在接口類中的接收數據參數中添加 @valid 注解,這時你的實體將會開啟一個校驗的功能。

2. @Valid 的相關注解

下面是 @Valid 相關的注解,在實體類中不同的屬性上添加不同的注解,就能實現不同數據的效驗功能

注解名稱 作用描述 @Null 限制只能為null @NotNull 限制必須不為null @AssertFalse 限制必須為false @AssertTrue 限制必須為true @DecimalMax(value) 限制必須為一個不大于指定值的數字 @DecimalMin(value) 限制必須為一個不小于指定值的數字 @Digits(integer,fraction) 限制必須為一個小數,且整數部分的位數不能超過integer,小數部分的位數不能超過fraction @Future 限制必須是一個將來的日期 @Max(value) 限制必須為一個不大于指定值的數字 @Min(value) 限制必須為一個不小于指定值的數字 @Past 限制必須是一個過去的日期 @Pattern(value) 限制必須符合指定的正則表達式 @Size(max,min) 限制字符長度必須在min到max之間 @Past 驗證注解的元素值(日期類型)比當前時間早 @NotEmpty 驗證注解的元素值不為null且不為空(字符串長度不為0、集合大小不為0) @NotBlank 驗證注解的元素值不為空(不為null、去除首位空格后長度為0),不同于@NotEmpty,@NotBlank只應用于字符串且在比較時會去除字符串的空格 @Email 驗證注解的元素值是Email,也可以通過正則表達式和flag指定自定義的email格式

3.?使用 @Valid 進行參數效驗步驟

整個過程如下圖所示,用戶訪問接口,然后進行參數效驗,因為 @Valid 不支持平面的參數效驗(直接寫在參數中字段的效驗)所以基于 GET 請求的參數還是按照原先方式進行效驗,而 POST 則可以以實體對象為參數,可以使用 @Valid 方式進行效驗。如果效驗通過,則進入業務邏輯,否則拋出異常,交由全局異常處理器進行處理。

案例用法

1.?實體類中添加 @Valid 相關注解

使用?@Valid?相關注解非常簡單,只需要在參數的實體類中屬性上面添加如?@NotBlank、@Max、@Min?等注解來對該字段進限制,如下:

User:

public class User {@NotBlank(message = "姓名不為空")private String username;@NotBlank(message = "密碼不為空")private String password; }

如果是嵌套的實體對象,則需要在最外層屬性上添加?@Valid?注解:

User:

public class User {@NotBlank(message = "姓名不為空")private String username;@NotBlank(message = "密碼不為空")private String password;//嵌套必須加 @Valid,否則嵌套中的驗證不生效@Valid@NotNull(message = "用戶信息不能為空")private UserInfo userInfo; }

UserInfo:

public class User {@NotBlank(message = "年齡不為空")@Max(value = 18, message = "不能超過18歲")private String age;@NotBlank(message = "性別不能為空")private String gender; }

2.?接口類中添加 @Valid 注解

在?Controller?類中添加接口,POST?方法中接收設置了 @Valid 相關注解的實體對象,然后在參數中添加?@Valid?注解來開啟效驗功能,需要注意的是,?@Valid?對?Get?請求中接收的平面參數請求無效,稍微略顯遺憾。

@RestController public class TestController {@PostMapping("/user")public String addUserInfo(@Valid @RequestBody User user) {return "調用成功!";}}

3.?全局異常處理類中處理 @Valid 拋出的異常

最后,我們寫一個全局異常處理類,然后對接口中拋出的異常進行處理,而?@Valid?配合?Spring?會拋出?MethodArgumentNotValidException?異常,這里我們需要對該異常進行處理即可。

package com.md.demo.exception;import java.util.List;import org.springframework.http.HttpStatus; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.util.StringUtils; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice;import com.md.demo.util.JsonResult; import com.md.demo.util.ResultCode;import lombok.extern.slf4j.Slf4j;@Slf4j @RestControllerAdvice("com.md") //指定異常處理的包名 public class GlobalExceptionHandler {/*** 參數效驗異常處理器** @param e 參數驗證異常* @return ResponseInfo*/@ResponseStatus(HttpStatus.BAD_REQUEST) //設置狀態碼為 400@ExceptionHandler(MethodArgumentNotValidException.class)public JsonResult parameterExceptionHandler(MethodArgumentNotValidException e) {log.error("數驗證異常", e);// 獲取異常信息BindingResult exceptions = e.getBindingResult();// 判斷異常中是否有錯誤信息,如果存在就使用異常中的消息,否則使用默認消息if (exceptions.hasErrors()) {List<ObjectError> errors = exceptions.getAllErrors();if (!errors.isEmpty()) {// 這里列出了全部錯誤參數,按正常邏輯,只需要第一條錯誤即可FieldError fieldError = (FieldError) errors.get(0);return new JsonResult(ResultCode.PARAM_ERROR, fieldError.getDefaultMessage());}}return new JsonResult(ResultCode.PARAM_ERROR);} }

代碼演示

1. 項目目錄結構

2.?pom.xml依賴組件(使用Lombok 包來簡化開發過程)

<?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"><modelVersion>4.0.0</modelVersion><parent><groupId>com.md</groupId><artifactId>spring-boot2-parent</artifactId><version>0.0.1-SNAPSHOT</version><relativePath>../pom.xml</relativePath></parent><artifactId>spring-boot2-valid</artifactId><packaging>jar</packaging><name>spring-boot2-valid</name><description>Spring Boot, MVC, Rest API for App</description><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- 構建成可運行的Web項目 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>net.sf.json-lib</groupId><artifactId>json-lib-ext-spring</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId></dependency><dependency><groupId>com.github.xiaoymin</groupId><artifactId>swagger-bootstrap-ui</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

3. 自定義個異常類

自定義個異常類,方便我們處理 GET 請求(GET 請求參數中一般是沒有實體對象的,所以不能使用 @Valid),當請求驗證失敗時,手動拋出自定義異常,交由全局異常處理。

package com.md.demo.exception;public class ParamaErrorException extends RuntimeException {private static final long serialVersionUID = 1L;public ParamaErrorException() {}public ParamaErrorException(String message) {super(message);}}

4. 自定義DTO類中添加 @Valid 相關注解

GetUserByIdDTO:

package com.md.demo.dto;import javax.validation.constraints.NotEmpty;import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data;@Data @ApiModel("測試-查詢條件") public class GetUserByIdDTO {@ApiModelProperty(value = "id標識值", required = true)@NotEmpty(message = "[userId值]不能為空")private String userId;@ApiModelProperty(value = "用戶名")private String userName; }

5. Controller 中添加 @Valid 注解(這里我定義了一個BaseDTO基本請求數據模型)

GetController:

package com.md.demo.controller;import javax.validation.Valid;import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; 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.md.demo.controller.base.BaseDTO; import com.md.demo.dto.GetUserByIdDTO; import com.md.demo.exception.ParamaErrorException; import com.md.demo.util.JsonResult; import com.md.demo.util.ResultCode;import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j;/*** @author Minbo*/ @RestController @RequestMapping("/api/") @Api(tags = { "查詢接口" }) @Slf4j public class GetController {/*** 測試Post請求*/@ApiOperation(value = "TestPost接口", httpMethod = "POST")@PostMapping("/test/post")public JsonResult testPost(@Valid @RequestBody BaseDTO<GetUserByIdDTO> dto) {log.debug("enter test post api...");return new JsonResult(ResultCode.SUCCESS);}/*** 測試Get請求*/@Validated@ApiOperation(value = "TestGet接口", httpMethod = "GET")@GetMapping("/test/get/{userName}")public JsonResult testGet(@PathVariable String userName) {log.debug("enter test get api...");if (userName == null || "".equals(userName)) {throw new ParamaErrorException("userName 不能為空");}return new JsonResult(ResultCode.SUCCESS);}}

6. 定義全局異常處理類

這里創建一個全局異常處理類,方便統一處理異常錯誤信息。里面添加了不同異常處理的方法,專門用于處理接口中拋出的異常信息

GlobalExceptionHandler:

package com.md.demo.exception;import java.util.List;import org.springframework.http.HttpStatus; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.util.StringUtils; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice;import com.md.demo.util.JsonResult; import com.md.demo.util.ResultCode;import lombok.extern.slf4j.Slf4j;@Slf4j @RestControllerAdvice("com.md") public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)public JsonResult handleException(Exception e) {log.error("系統異?!救之惓L幚怼?#xff1a;" + e.getMessage(), e);return new JsonResult(ResultCode.SYS_EXCEPTION, "系統異常:" + e.getMessage());}/*** 忽略參數異常處理器** @param e 忽略參數異常* @return ResponseResult*/@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler(MissingServletRequestParameterException.class)public JsonResult parameterMissingExceptionHandler(MissingServletRequestParameterException e) {log.error("忽略參數異常", e);return new JsonResult(ResultCode.PARAM_ERROR, "請求參數 " + e.getParameterName() + " 不能為空");}/*** 缺少請求體異常處理器** @param e 缺少請求體異常* @return ResponseResult*/@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler(HttpMessageNotReadableException.class)public JsonResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {log.error("缺少請求體異常", e);return new JsonResult(ResultCode.PARAM_ERROR, "參數體不能為空");}/*** 參數效驗異常處理器** @param e 參數驗證異常* @return ResponseInfo*/@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler(MethodArgumentNotValidException.class)public JsonResult parameterExceptionHandler(MethodArgumentNotValidException e) {log.error("數驗證異常", e);// 獲取異常信息BindingResult exceptions = e.getBindingResult();// 判斷異常中是否有錯誤信息,如果存在就使用異常中的消息,否則使用默認消息if (exceptions.hasErrors()) {List<ObjectError> errors = exceptions.getAllErrors();if (!errors.isEmpty()) {// 這里列出了全部錯誤參數,按正常邏輯,只需要第一條錯誤即可FieldError fieldError = (FieldError) errors.get(0);return new JsonResult(ResultCode.PARAM_ERROR, fieldError.getDefaultMessage());}}return new JsonResult(ResultCode.PARAM_ERROR);}/*** 自定義參數錯誤異常處理器** @param e 自定義參數* @return ResponseInfo*/@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler({ ParamaErrorException.class })public JsonResult paramExceptionHandler(ParamaErrorException e) {log.error("自定義參數參數", e);// 判斷異常中是否有錯誤信息,如果存在就使用異常中的消息,否則使用默認消息if (!StringUtils.isEmpty(e.getMessage())) {return new JsonResult(ResultCode.PARAM_ERROR, e.getMessage());}return new JsonResult(ResultCode.PARAM_ERROR);}}

7. 啟動類

Application:

package com.md.demo;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter;import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;/*** 程序主入口* * @author Minbo**/ @SpringBootApplication @EnableSwaggerBootstrapUI @ComponentScan(basePackages = "com.md") public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}/*** 開啟過濾器功能* * @return*/private CorsConfiguration buildConfig() {CorsConfiguration corsConfiguration = new CorsConfiguration();corsConfiguration.addAllowedOrigin("*");corsConfiguration.addAllowedHeader("*");corsConfiguration.addAllowedMethod("*");return corsConfiguration;}/*** 跨域過濾器* * @return*/@Beanpublic CorsFilter corsFilter() {UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", buildConfig());return new CorsFilter(source);} }

接口測試

1. 啟動后,訪問地址:http://localhost:9090/doc.html?(已集成了swagger2框架,Swagger集成用法教程)

2. 測試post接口

可以看到在執行 POST 請求,也能正常按我們全局異常處理器中的設置處理異常信息,且提示信息為我們設置在實體類中的 Message

3. 測試get接口

完整源碼下載

我的Github源碼地址:

https://github.com/hemin1003/spring-boot-study/tree/master/spring-boot2-study/spring-boot2-parent/spring-boot2-valid

下一章教程

SpringBoot從入門到精通教程(二十八)- 動態修改日志輸出級別用法

該系列教程

SpringBoot從入門到精通教程

?

我的專欄

  • SpringBoot系列專欄
  • 高可用高并發實戰專欄
  • 微服務架構實戰
  • DevOps實戰專欄
  • 程序化廣告實戰專欄

?

?

至此,全部介紹就結束了

?

?

-------------------------------

-------------------------------

?

我的CSDN主頁

關于我(個人域名)

我的開源項目集Github

?

期望和大家一起學習,一起成長,共勉,O(∩_∩)O謝謝

歡迎交流問題,可加個人QQ 469580884,

或者,加我的群號?751925591,一起探討交流問題

不講虛的,只做實干家

Talk is cheap,show me the code

總結

以上是生活随笔為你收集整理的SpringBoot从入门到精通教程(二十七)- @Valid注解用法详解+全局处理器Exception优雅处理参数验证用法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。