springboot中使用Hibernate-Validation校驗參數(shù)詳解
1、說明
后端接口設(shè)計時候,需要對前端請求參數(shù)進行'先校驗后處理業(yè)務(wù)'情況,如果在業(yè)務(wù)代碼中通過類似if這里逐個校驗,會使得代碼變得繁瑣,開發(fā)工作者都是愛偷懶的。java中,Bean Validation 為JavaBean的驗證定義了相關(guān)的元數(shù)據(jù)模型和API。
基于Bean-Validation封裝,提供了更加豐富的Hibernate-Validation的校驗包。也有開發(fā)會把這類校驗交給前端來處理,但是接口暴露外網(wǎng)會存在直接調(diào)用情況(黃牛)。畢竟:前端校驗是為了提高用戶的體驗度,后端校驗則是為了保證數(shù)據(jù)的安全性
優(yōu)點
1.驗證邏輯與業(yè)務(wù)邏輯之間進行了分離,降低了程序耦合度
2.統(tǒng)一且規(guī)范的驗證方式,無需你再次編寫重復(fù)的驗證代碼
3.你將更專注于你的業(yè)務(wù),將這些繁瑣的事情統(tǒng)統(tǒng)丟在一邊
2、Bean Validation與Hibernate Validation
2.1 Bean Validation中內(nèi)置的constraint
包位置路徑:javax.validation.constraints

| 注解 | 說明 |
|---|---|
| @AssertFalse | 注釋的元素必須為False |
| @AssertTrue | 注釋的元素必須為True |
| 注釋的元素必須郵箱 | |
| @NotBlank | 注釋的元素不能為空,!null && size>0 |
| @NotEmpty | 注釋的元素不能為空,數(shù)組,集合等 |
| @NotNull | 注釋的元素必須為空,但可以為""字符串 |
| @DecimalMin | 注釋的元素數(shù)字,最小不得小于Min |
| @DecimalMax | 注釋的元素為數(shù)字,最大不超過Max值 |
其中NotNull、NotEmpty、NotBlank區(qū)別
- @NotNull
適用于基本數(shù)據(jù)類型(Integer,Long,Double等等),當(dāng) @NotNull 注解被使用在 String 類型的數(shù)據(jù)上,則表示該數(shù)據(jù)不能為 Null(但是可以為 Empty) - @NotBlank
適用于 String 類型的數(shù)據(jù)上,加了@NotBlank 注解的參數(shù)不能為 Null 且 trim() 之后 size > 0 - @NotEmpty
適用于 String、Collection集合、Map、數(shù)組等等,加了@NotEmpty 注解的參數(shù)不能為 Null 或者 長度為 0
2.1 Hibernate Validation中添加的constraint

| 注解 | 說明 |
|---|---|
| @Length | 注釋的元素字符串長度必須為制定返回內(nèi) |
| @Range | 注釋的元素必須在指定范圍內(nèi) |
| @URL | 注釋的元素必須為鏈接 |
3、基于Hibernate Validation的實現(xiàn)
(1)pom包引用
查看spring-boot-start-web中已經(jīng)集成了Hibernate Validation,所以可以不用額外引用包。同時spring-boot-start-validation也完成了Hibernate Validation的start封裝(校驗機制更加全面)。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>(2)Bean對象中使用注解注釋
...
@ApiModelProperty(value = "收貨人所在省",required = true)
@NotNull(message = "省不能為空")
private String recipientProvince;
@ApiModelProperty(value = "收貨人所在市")
@NotNull(message = "市不能為空")
private String recipientCity;
@ApiModelProperty(value = "收貨人所在區(qū)")
@NotNull(message = "區(qū)不能為空")
private String recipientDistrict;
...
(3)Controller層使用@Valid或者@Validated
@PostMapping("/add")
public UniformResultTemplate<Boolean> addAddress(@RequestBody @Validated AddressReqDto reqDto, HttpServletRequest request){
return null;
}
注意:Post請求方式區(qū)別,Get@Validated注解需要加在 所在方法類前
@RestController
@RequestMapping("/api/address")
@Validated
public class AddressController extends BaseController{
@ApiOperation("收獲地址詳情")
@GetMapping("/detail")
public UniformResultTemplate<AddressDetailRespDto> queryAddressList(@NotNull(message = "地址Id不能為空")
@RequestParam(value = "addressId") Long addressId, HttpServletRequest request){
return null;
}
}(4)使用@ControllerAdvice統(tǒng)一異常處理返回。
@Component
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
// Post請求Bean中的校驗拋出:MethodArgumentNotValidException
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public UniformResultTemplate handleBindException(MethodArgumentNotValidException ex) {
FieldError fieldError = ex.getBindingResult().getFieldError();
log.warn("參數(shù)校驗異常:{}({})", fieldError.getDefaultMessage(),fieldError.getField());
return new UniformResultTemplate("10002",fieldError.getDefaultMessage());
}
// Get請求的參數(shù)校驗,拋出的是ConstraintViolationException
@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
public UniformResultTemplate handleGetBindException(ConstraintViolationException ex) {
Set<ConstraintViolation<?>> eSet = ex.getConstraintViolations();
StringBuffer sb = new StringBuffer();
if(!CollectionUtils.isEmpty(eSet)) {
Iterator<ConstraintViolation<?>> iterator = eSet.iterator();
while (iterator.hasNext()) {
log.warn("參數(shù)校驗異常:{}({})", iterator.next().getMessage());
sb.append(iterator.next().getMessage()).append("::");
}
}
return new UniformResultTemplate("10002",sb.toString());
}
// 方法簽名參數(shù)錯誤
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseBody
public UniformResultTemplate handleGetBindException(MissingServletRequestParameterException ex) {
log.warn("參數(shù)校驗異常:{}", ex.getMessage());
return new UniformResultTemplate("10002",ex.getMessage());
}
}(5)結(jié)果現(xiàn)象
{
"code": "10002",
"message": "市不能為空",
"result": null,
"totalTimes": null,
"interfaceTimes": null
}
4、編譯器校驗工具
防止因使用錯誤Hibernate-Validation注解而導(dǎo)致程序運行時報錯,增加編譯器校驗工具,進行友好提示。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>6.1.5.Final</version>
</dependency>以上就是springboot中使用Hibernate-Validation校驗參數(shù)詳解的詳細(xì)內(nèi)容,更多關(guān)于springboot Hibernate-Validation的資料請關(guān)注腳本之家其它相關(guān)文章!
- SpringBoot + validation 接口參數(shù)校驗的思路詳解
- Spring?Boot集成validation實現(xiàn)參數(shù)校驗功能
- SpringBoot使用Validation包進行輸入?yún)?shù)校驗
- spring?boot?validation參數(shù)校驗與分組嵌套各種類型及使用小結(jié)
- SpringBoot使用Validation進行參數(shù)校驗的示例詳解
- spring-boot-starter-validation?校驗參數(shù)的實現(xiàn)
- spring boot輸入數(shù)據(jù)校驗(validation)的實現(xiàn)過程
- 從零到掌握Spring Boot Validation 接口校驗的詳細(xì)過程
相關(guān)文章
Java實戰(zhàn)之實現(xiàn)一個好用的MybatisPlus代碼生成器
這篇文章主要介紹了Java實戰(zhàn)之實現(xiàn)一個好用的MybatisPlus代碼生成器,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04
解決SpringBoot框架因post數(shù)據(jù)量過大沒反應(yīng)問題(踩坑)
這篇文章主要介紹了解決SpringBoot框架因post數(shù)據(jù)量過大沒反應(yīng)問題(踩坑),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
玩轉(zhuǎn)SpringBoot2快速整合攔截器的方法
這篇文章主要介紹了玩轉(zhuǎn)SpringBoot2快速整合攔截器的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
SpringBoot2整合Redis實現(xiàn)讀寫操作
Redis,對于大家來說應(yīng)該不陌生,是經(jīng)常使用的開發(fā)技術(shù)之一。本文將結(jié)合實例代碼,介紹SpringBoot2整合Redis實現(xiàn)讀寫操作,感興趣的小伙伴們可以參考一下2021-07-07
Java構(gòu)造方法實例詳解(動力節(jié)點java學(xué)院整理)
其實java構(gòu)造方法很簡單,下面通過示例給大家分享java構(gòu)造方法,非常不錯,具有參考借鑒價值,需要的朋友參考下2017-04-04

