hibernate-validator后端表單數(shù)據(jù)校驗(yàn)的使用示例詳解
hibernate-validator后端表單數(shù)據(jù)校驗(yàn)的使用
1、hibernate-validator介紹
早期的網(wǎng)站,用戶輸入一個(gè)郵箱地址,需要將郵箱地址發(fā)送到服務(wù)端,服務(wù)端進(jìn)行校驗(yàn),校驗(yàn)成功后,給前端一個(gè)響應(yīng)。
有了JavaScript后,校驗(yàn)工作可以放在前端去執(zhí)行。那么為什么還需要服務(wù)端校驗(yàn)?zāi)兀?因?yàn)榍岸藗鱽?lái)的數(shù)據(jù)不可信。前端很容易獲取到后端的接口,如果有人直接調(diào)用接口,就可能會(huì)出現(xiàn)非法數(shù)據(jù),所以服務(wù)端也要數(shù)據(jù)校驗(yàn)。
總的來(lái)說(shuō):
- 前端校驗(yàn):主要是提高用戶體驗(yàn)
- 后端校驗(yàn):主要是保證數(shù)據(jù)安全可靠
校驗(yàn)參數(shù)基本上是一個(gè)體力活,而且冗余代碼繁多,也影響代碼的可讀性,我們需要一個(gè)比較優(yōu)雅的方式來(lái)解決這個(gè)問(wèn)題。Hibernate Validator 框架剛好解決了這個(gè)問(wèn)題,可以以很優(yōu)雅的方式實(shí)現(xiàn)參數(shù)的校驗(yàn),讓業(yè)務(wù)代碼和校驗(yàn)邏輯分開(kāi),不再編寫(xiě)重復(fù)的校驗(yàn)邏輯。
hibernate-validator優(yōu)勢(shì):
- 驗(yàn)證邏輯與業(yè)務(wù)邏輯之間進(jìn)行了分離,降低了程序耦合度
- 統(tǒng)一且規(guī)范的驗(yàn)證方式,無(wú)需你再次編寫(xiě)重復(fù)的驗(yàn)證代碼
- 你將更專(zhuān)注于你的業(yè)務(wù),將這些繁瑣的事情統(tǒng)統(tǒng)丟在一邊
hibernate-validator的maven坐標(biāo):
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.18.Final</version>
</dependency>
提示:spring-boot-starter-web中已經(jīng)依賴(lài)了hibernate-validator
2、hibernate-validator常用注解
hibernate-validator提供的校驗(yàn)方式為在類(lèi)的屬性上加入相應(yīng)的注解來(lái)達(dá)到校驗(yàn)的目的。hibernate-validator提供的用于校驗(yàn)的注解如下:
| 注解 | 說(shuō)明 |
|---|---|
| @AssertTrue | 用于boolean字段,該字段只能為true |
| @AssertFalse | 用于boolean字段,該字段只能為false |
| @CreditCardNumber | 對(duì)信用卡號(hào)進(jìn)行一個(gè)大致的驗(yàn)證 |
| @DecimalMax | 只能小于或等于該值 |
| @DecimalMin | 只能大于或等于該值 |
| 檢查是否是一個(gè)有效的email地址 | |
| @Future | 檢查該字段的日期是否是屬于將來(lái)的日期 |
| @Length(min=,max=) | 檢查所屬的字段的長(zhǎng)度是否在min和max之間,只能用于字符串 |
| @Max | 該字段的值只能小于或等于該值 |
| @Min | 該字段的值只能大于或等于該值 |
| @NotNull | 不能為null |
| @NotBlank | 不能為空,檢查時(shí)會(huì)將空格忽略 |
| @NotEmpty | 不能為空,這里的空是指空字符串 |
| @Pattern(regex=) | 被注釋的元素必須符合指定的正則表達(dá)式 |
| @URL(protocol=,host,port) | 檢查是否是一個(gè)有效的URL,如果提供了protocol,host等,則該URL還需滿足提供的條件 |
3、 hibernate-validator入門(mén)案例
3.1、第一步:創(chuàng)建maven工程hibernate-validator_demo并配置pom.xml文件
spring-boot-starter-web中已經(jīng)依賴(lài)了hibernate-validator
<?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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>
<groupId>org.example</groupId>
<artifactId>hibernate-validator_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--spring-boot-starter-web中已經(jīng)依賴(lài)了hibernate-validator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.18.Final</version>
</dependency>
-->
</dependencies>
</project>
3.2、創(chuàng)建實(shí)體類(lèi)
NotEmpty:不能為空字符串
package com.zcl.entity;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.*;
/**
* 項(xiàng)目名稱(chēng):hibernate-validator_demo
* 描述:用戶實(shí)體類(lèi)
*
* @author zhong
* @date 2022-08-29 12:48
*/
@Data
public class User {
@NotNull(message = "用戶id不能為空")
private Integer id;
@NotEmpty(message = "用戶名不能為空")
@Length(max = 50, message = "用戶名長(zhǎng)度不能超過(guò)50")
private String username;
@Max(value = 80,message = "年齡最大為80")
@Min(value = 18,message = "年齡最小為18")
private int age;
@Pattern(regexp = "[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$",
message = "郵箱格式不正確")
private String email;
}3.3、創(chuàng)建UserController
package com.zcl.controller;
import com.zcl.entity.User;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotBlank;
/**
* 項(xiàng)目名稱(chēng):hibernate-validator_demo
* 描述:用戶控制器
*
* @author zhong
* @date 2022-08-29 12:53
*/
@RestController
@RequestMapping("/user")
@Validated
public class UserController {
/**
* 簡(jiǎn)單數(shù)據(jù)類(lèi)型校驗(yàn)
* @param id
* @return
*/
@RequestMapping("/delete")
public String delete(@NotBlank(message = "id不能為空") String id){
System.out.println("delete..." + id);
return "OK";
}
/**
* 對(duì)象屬性校驗(yàn)
* @param user
* @return
*/
@RequestMapping("/save")
public String save(@RequestBody @Validated User user){
System.out.println("save..." + user);
return "OK";
}
}
3.4、創(chuàng)建項(xiàng)目啟動(dòng)類(lèi)
package com.zcl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 項(xiàng)目名稱(chēng):hibernate-validator_demo
* 描述:項(xiàng)目啟動(dòng)類(lèi)
*
* @author zhong
* @date 2022-08-29 13:04
*/
@SpringBootApplication
public class HibernateValidatorApp {
public static void main(String[] args) {
SpringApplication.run(HibernateValidatorApp.class, args);
}
}3.5、創(chuàng)建application.yml配置文件
該配置文件可有可無(wú)
server: port: 8080
4、啟動(dòng)項(xiàng)目測(cè)試
使用測(cè)試工具或插件進(jìn)行訪問(wèn):http://localhost:8080/user/delete
4.1、刪除控制器沒(méi)有攜帶數(shù)據(jù)
當(dāng)id為空的時(shí)候會(huì)直接報(bào)錯(cuò)響應(yīng)到前端頁(yè)面

4.2、刪除控制器攜帶id時(shí)

4.2、訪問(wèn)對(duì)象屬性校驗(yàn)不攜帶數(shù)據(jù)時(shí)
提示有三個(gè)報(bào)錯(cuò)信息

IDEA控制臺(tái)查看

4.3、訪問(wèn)對(duì)象屬性校驗(yàn)攜帶數(shù)據(jù)時(shí)

5、處理異常信息
在
config包下創(chuàng)建全局的異常處理器,全局捕獲@RestController或@Controller的注解控制器
package com.zcl.config;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
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.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;
/**
* 項(xiàng)目名稱(chēng):hibernate-validator_demo
* 描述:全局的異常處理
*
* @author zhong
* @date 2022-08-29 13:17
*/
@ControllerAdvice(annotations = {RestController.class, Controller.class})
@ResponseBody
public class ExceptionConfiguration {
// 定義只捕獲著兩種異常
@ExceptionHandler({ConstraintViolationException.class, BindException.class})
public String validateException(Exception ex, HttpServletRequest request) {
ex.printStackTrace();
String msg = null;
if(ex instanceof ConstraintViolationException){
// 異常信息強(qiáng)轉(zhuǎn)
ConstraintViolationException constraintViolationException =
(ConstraintViolationException)ex;
// 獲取異常信息
Set<ConstraintViolation<?>> violations =
constraintViolationException.getConstraintViolations();
ConstraintViolation<?> next = violations.iterator().next();
msg = next.getMessage();
}else if(ex instanceof BindException){
BindException bindException = (BindException)ex;
msg = bindException.getBindingResult().getFieldError().getDefaultMessage();
}
return msg;
}
}
6、重新啟動(dòng)項(xiàng)目測(cè)試

注意:當(dāng)我們的請(qǐng)求【http://localhost:8080/user/save?id=1】控制器的時(shí)候,不是使用get請(qǐng)求或者路徑的方式提交參數(shù),后端的全局?jǐn)r截代碼是捕獲不到異常信息的,返回的還是之前的直接錯(cuò)誤顯示在前端的瀏覽器上。通過(guò)get請(qǐng)求以及路徑參數(shù)的方式提交就可以了
7、修改代碼,一次校驗(yàn)不通過(guò)就不再執(zhí)行
創(chuàng)建ValidatorConfiguration類(lèi),指定校驗(yàn)時(shí)使用快速失敗返回模式
package com.zcl.config;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
/**
* 項(xiàng)目名稱(chēng):hibernate-validator_demo
* 描述:指定校驗(yàn)時(shí)使用快速失敗返回模式
*
* @author zhong
* @date 2022-08-29 13:38
*/
public class ValidatorConfiguration {
@Bean
public Validator validator() {
ValidatorFactory validatorFactory =
Validation.byProvider(HibernateValidator.class)
.configure()
//快速失敗返回模式
.addProperty("hibernate.validator.fail_fast", "true")
.buildValidatorFactory();
return validatorFactory.getValidator();
}
/**
* 開(kāi)啟快速返回
* 如果參數(shù)校驗(yàn)有異常,直接拋異常,不會(huì)進(jìn)入到 controller,使用全局異常攔截進(jìn)行攔截
*/
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor postProcessor =
new MethodValidationPostProcessor();
/**設(shè)置validator模式為快速失敗返回*/
postProcessor.setValidator(validator());
return postProcessor;
}
}
注意:上面創(chuàng)建的類(lèi)并不是配置類(lèi),所以到目前為止快速失敗返回模式并不會(huì)生效,為了使其生效需要?jiǎng)?chuàng)建一個(gè)注解用于控制此模式的開(kāi)啟
8、創(chuàng)建注解EnableFormValidator用于控制快速失敗返回模式的開(kāi)啟
package com.zcl.config;
import org.springframework.context.annotation.Import;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 項(xiàng)目名稱(chēng):hibernate-validator_demo
* 描述:在啟動(dòng)類(lèi)上添加該注解來(lái)啟動(dòng)表單驗(yàn)證功能---快速失敗返回模式
*
* @author zhong
* @date 2022-08-29 13:41
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ValidatorConfiguration.class)
public @interface EnableFormValidator {
}在啟動(dòng)類(lèi)上加上上面的注解
package com.zcl;
import com.zcl.config.EnableFormValidator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 項(xiàng)目名稱(chēng):hibernate-validator_demo
* 描述:項(xiàng)目啟動(dòng)類(lèi)
*
* @author zhong
* @date 2022-08-29 13:04
*/
@SpringBootApplication
@EnableFormValidator
public class HibernateValidatorApp {
public static void main(String[] args) {
SpringApplication.run(HibernateValidatorApp.class, args);
}
}再次啟動(dòng)項(xiàng)目的時(shí)候通過(guò)測(cè)試對(duì)象屬性,少傳遞兩個(gè)參數(shù)集合看出效果,當(dāng)前面的驗(yàn)證不通過(guò)的時(shí)候后面的就不會(huì)再次驗(yàn)證了
到此這篇關(guān)于hibernate-validator后端表單數(shù)據(jù)校驗(yàn)的使用的文章就介紹到這了,更多相關(guān)hibernate-validator數(shù)據(jù)校驗(yàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
源碼解讀Spring-Integration執(zhí)行過(guò)程
Spring-Integration基于Spring,在應(yīng)用程序中啟用了輕量級(jí)消息傳遞,并支持通過(guò)聲明式適配器與外部系統(tǒng)集成,今天主要是看個(gè)簡(jiǎn)單的hello word進(jìn)來(lái)分析下整個(gè)執(zhí)行過(guò)程,感興趣的朋友一起看看吧2021-06-06
springmvc項(xiàng)目使用@Valid+BindingResult遇到的問(wèn)題
這篇文章主要介紹了springmvc項(xiàng)目使用@Valid+BindingResult遇到的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
java多線程編程之為什么要進(jìn)行數(shù)據(jù)同步
數(shù)據(jù)同步就是指在同一時(shí)間,只能由一個(gè)線程來(lái)訪問(wèn)被同步的類(lèi)變量,當(dāng)前線程訪問(wèn)完這些變量后,其他線程才能繼續(xù)訪問(wèn),下面看一下為什么要進(jìn)行數(shù)據(jù)同步2014-01-01
SpringMVC框架實(shí)現(xiàn)Handler處理器的三種寫(xiě)法
這篇文章主要介紹了SpringMVC框架實(shí)現(xiàn)Handler處理器的三種寫(xiě)法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
Java實(shí)現(xiàn)獲取內(nèi)網(wǎng)的所有IP地址
這篇文章主要介紹了如何利用Java語(yǔ)言實(shí)現(xiàn)獲取內(nèi)網(wǎng)的所有IP地址,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)有一定的參考價(jià)值,快跟隨小編一起學(xué)習(xí)一下吧2022-06-06
Java探索之Hibernate主鍵生成策略詳細(xì)介紹
這篇文章主要介紹了Java探索之Hibernate主鍵生成策略詳細(xì)介紹,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10

