詳解SpringBoot中的參數(shù)校驗(項目實戰(zhàn))
Java后端發(fā)工作中經(jīng)常會對前端傳遞過來的參數(shù)做一些校驗,在業(yè)務中還要拋出異常或者不斷的返回異常時的校驗信息,充滿了if-else這種校驗代碼,在代碼中相當冗長。例如說,用戶注冊時,會校驗手機格式的正確性,用戶名的長度等等。雖說前端也可以做參數(shù)校驗,但是為了保證我們API接口的可靠性,以保證最終數(shù)據(jù)入庫的正確性,后端進行參數(shù)校驗不可忽視。 Hibernate Validator 提供了一種統(tǒng)一方便的方式,讓我們快速的實現(xiàn)參數(shù)校驗。
Hibernate Validator 使用注解,實現(xiàn)聲明式校驗。而在實現(xiàn)原理上,也是基于 Spring AOP 攔截,實現(xiàn)校驗相關的操作。 javax.validation.constraints 包下,定義了一系列的約束( constraint )注解。文末會貼上一些常用的注解。 如果項目的框架是 spring boot 的話,在 spring-boot-starter-web 中已經(jīng)包含了 Hibernate-validator 的依賴( 版本<2.3 )。 2.3 以后的版本中 spring-boot-starter-web 已經(jīng)去除了這個依賴,需要手動引入 Hibernate-validator 依賴,并且有一些變化,因此 2.3.x 的版本暫不研究。本文使用的版本是 2.2.8 。
實戰(zhàn)
1、創(chuàng)建實體類
package com.yese.pojo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.*;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {
/**
* 用戶ID
*/
@NotNull(message = "用戶id不能為空")
private Long userId;
/**
* 用戶名
*/
@NotBlank(message = "用戶名不能為空")
@Length(max = 20, message = "用戶名不能超過10個字符")
@Pattern(regexp = "^[\\u4E00-\\u9FA5A-Za-z0-9\\*]*$", message = "用戶名限制:最多10字符,包含文字、字母和數(shù)字")
private String username;
/**
* 密碼
*/
@NotBlank(message = "密碼不能為空")
private String password;
/**
* 手機號
*/
@NotBlank(message = "手機號不能為空")
@Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手機號格式有誤")
private String mobile;
/**
* 性別
*/
@NotNull(message = "性別不能為空")
private Integer sex;
/**
* 年齡
*/
@NotNull(message = "年齡不能為空")
@Min(value = 1, message = "年齡最小為1歲")
@Max(value = 120, message = "年齡最大為120歲")
private Integer age;
/**
* 郵箱
*/
@NotBlank(message = "郵箱不能為空")
@Email(message = "郵箱格式錯誤")
private String email;
}
2、創(chuàng)建controller
package com.yese.controller;
import com.yese.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class UserController {
/**
* controller方法的入?yún)⒗锩嬖趯嶓w類前面加上@Validated
*/
@PostMapping("/user")
public void add(@RequestBody @Validated User user) {
log.info("user====={}", user);
}
}
3、創(chuàng)建全局異常處理器
package com.yese.config;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;
/**
* 全局異常處理器
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* post方式提交json數(shù)據(jù),參數(shù)校驗失敗后,會拋出一個MethodArgumentNotValidException
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Map<String, Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
// 獲取所有的錯誤
// List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
// 獲取錯誤提示
// System.out.println(fieldErrors.get(0).getDefaultMessage());
// 獲取錯誤字段
// System.out.println(fieldErrors.get(0).getField());
// 將所有的錯誤提示使用";"拼接起來并返回
StringJoiner sj = new StringJoiner(";");
e.getBindingResult().getFieldErrors().forEach(x -> sj.add(x.getDefaultMessage()));
// 此處通常定義一個全局相應對象返回
Map<String, Object> map = new HashMap<>();
// 此處狀態(tài)碼可以通過枚舉或者常量定義
map.put("code", 1001);
map.put("msg", sj.toString());
return map;
}
/**
* get方式提交參數(shù),參數(shù)校驗失敗后,會拋出一個ConstraintViolationException
*/
@ExceptionHandler(ConstraintViolationException.class)
public Map<String, Object> handleConstraintViolationException(ConstraintViolationException e) {
StringJoiner sj = new StringJoiner(";");
e.getConstraintViolations().forEach(x -> sj.add(x.getMessage()));
Map<String, Object> map = new HashMap<>();
map.put("code", 1001);
map.put("msg", sj.toString());
return map;
}
}
4、測試

效果符合預期!
@Valid和@Validated
絕大多數(shù)場景下,我們使用 @Validated 注解即可。
而在有嵌套校驗的場景,我們使用 @Valid 注解添加到成員屬性上。
附常用注解
javax.validation.constraints 包下
| 注解 | 驗證的數(shù)據(jù)類型 | 說明 |
|---|---|---|
| @Null | 任意類型 | 驗證注解的元素值必須是null |
| @NotNull | 任意類型 | 驗證注解的元素值不是null |
| @NotBlank | 字符串 | 驗證注解的元素值不為空(不為null、去除首位空格后長度大于0) |
| @NotEmpty | CharSequence子類型、Collection、Map、數(shù)組 | 驗證注解的元素值不為null且不為空(字符串長度不為0、集合大小不為0) |
| @Min(value=值) | 數(shù)值類型 | 驗證注解的元素值大于等于@Min指定的value值 |
| @Max(value=值) | 和@Min要求一樣 | 驗證注解的元素值小于等于@Max指定的value值 |
| @DecimalMin(value=值) | 和@Min要求一樣 | 驗證注解的元素值大于等于@ DecimalMin指定的value值 |
| @DecimalMax(value=值) | 和@Min要求一樣 | 驗證注解的元素值小于等于@ DecimalMax指定的value值 |
| @Digits(integer=整數(shù)位數(shù), fraction=小數(shù)位數(shù)) | 和@Min要求一樣 | 驗證注解的元素值的整數(shù)位數(shù)和小數(shù)位數(shù)上限 |
| @Size(min=下限, max=上限) | 字符串、Collection、Map、數(shù)組等 | 驗證注解的元素值的在min和max(包含)指定區(qū)間之內(nèi),如字符長度、集合大小 |
| @Positive | 判斷正數(shù) | |
| @PositiveOrZero | 判斷正數(shù)或 0 。 | |
| @Negative | 判斷負數(shù)。 | |
| @NegativeOrZero | 判斷負數(shù)或 0 。 | |
| @Past | 日期類型 | 驗證注解的元素值(日期類型)比當前時間早 |
| @Future | 與@Past要求一樣 | 驗證注解的元素值(日期類型)比當前時間晚 |
| @AssertFalse | Boolean | 驗證注解的元素值是false |
| @AssertTrue | Boolean | 驗證注解的元素值是true |
| @Range(min=最小值, max=最大值) | BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子類型和包裝類型 | 驗證注解的元素值在最小值和最大值之間 |
| 字符串 | 驗證注解的元素值是Email,也可以通過regexp和flag指定自定義的email格式 | |
| @Pattern(regexp=正則表達式,flag=標志的模式) | 字符串 | 驗證注解的元素值與指定的正則表達式匹配 |
| @Valid | 任何非原子類型 | 指定遞歸驗證關聯(lián)的對象如用戶對象中有個地址對象屬性,如果想在驗證用戶對象時一起驗證地址對象的話,在地址對象上加@Valid注解即可級聯(lián)驗證 |
org.hibernate.validator.constraints 包下,定義了一系列的約束( constraint )注解。如下:
@Range(min=, max=) :被注釋的元素必須在合適的范圍內(nèi)。
@Length(min=, max=) :被注釋的字符串的大小必須在指定的范圍內(nèi)。
@URL(protocol=,host=,port=,regexp=,flags=) :被注釋的字符串必須是一個有效的 URL 。
@SafeHtml :判斷提交的 HTML 是否安全。例如說,不能包含 javascript 腳本等等。
到此這篇關于詳解SpringBoot中的參數(shù)校驗(項目實戰(zhàn))的文章就介紹到這了,更多相關SpringBoot 參數(shù)校驗內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Springboot啟動后立即某個執(zhí)行方法的四種方式
spring項目如何在啟動項目是執(zhí)行一些操作,在spring中能通過那些操作實現(xiàn)這個功能呢,下面這篇文章主要給大家介紹了關于Springboot啟動后立即某個執(zhí)行方法的四種方式,需要的朋友可以參考下2022-06-06
IntelliJ IDEA 2018 最新激活碼(截止到2018年1月30日)
這篇文章主要介紹了IntelliJ IDEA 2018 最新激活碼(截止到2018年1月30日)的相關資料,需要的朋友可以參考下2018-01-01
java中Class.getMethods()和Class.getDeclaredMethods()方法的區(qū)別
這篇文章主要介紹了java中Class.getMethods()和Class.getDeclaredMethods()方法的區(qū)別 ,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2018-09-09
Spring Cloud Alibaba 本地調(diào)試介紹及方案設計
為了解決 本地調(diào)試 的問題,本文實現(xiàn)了一種簡單實用的策略,可以通過 Nacos 動態(tài)配置服務路由,還可以基于用戶,部門,組織等級別配置服務路由,實現(xiàn) 本地調(diào)試 的同時,實際上也實現(xiàn) 灰度發(fā)布,感興趣的朋友跟隨小編一起看看吧2021-07-07

