SpringMVC實(shí)現(xiàn)參數(shù)校驗(yàn)配置方法
在 Web 應(yīng)用的三層架構(gòu)中,確保在表述層(Presentation Layer)對(duì)數(shù)據(jù)進(jìn)行檢查和校驗(yàn)是非常重要的。正確的數(shù)據(jù)校驗(yàn)可以確保業(yè)務(wù)邏輯層(Business Logic Layer)基于有效和合法的數(shù)據(jù)進(jìn)行處理,同時(shí)將錯(cuò)誤的數(shù)據(jù)隔離在業(yè)務(wù)邏輯層之外。這有助于提高系統(tǒng)的健壯性、安全性和可維護(hù)性。
校驗(yàn)概述
JSR-303是Java EE 6中的一項(xiàng)子規(guī)范,也被稱(chēng)為Bean Validation。這個(gè)規(guī)范主要用于對(duì)Java Bean中的字段值進(jìn)行驗(yàn)證。JSR-303提供了一套注解和API,方便開(kāi)發(fā)者在實(shí)體類(lèi)中對(duì)字段進(jìn)行驗(yàn)證,以確保數(shù)據(jù)的合法性。
在JSR-303中,內(nèi)置了許多常用的約束規(guī)則,如@NotNull(非空驗(yàn)證)、@Size(長(zhǎng)度驗(yàn)證)、@Range(范圍驗(yàn)證)等。這些注解可以直接應(yīng)用于實(shí)體類(lèi)的字段上,以聲明驗(yàn)證規(guī)則。同時(shí),JSR-303還提供了驗(yàn)證器(Validator)接口,用于執(zhí)行驗(yàn)證操作。開(kāi)發(fā)者可以通過(guò)注入Validator實(shí)例,或者使用Validation工具類(lèi)來(lái)觸發(fā)驗(yàn)證。
在Spring MVC中,JSR-303得到了很好的支持。開(kāi)發(fā)者可以在控制器的方法參數(shù)上使用JSR-303的注解,以實(shí)現(xiàn)表單數(shù)據(jù)的自動(dòng)驗(yàn)證。如果參數(shù)不滿(mǎn)足約束條件,Spring MVC會(huì)拋出MethodArgumentNotValidException異常,并將錯(cuò)誤信息綁定到相應(yīng)的字段上。
常用注解
@NotNull:確保字段值不為null。@NotBlank:用于String類(lèi)型參數(shù)校驗(yàn),檢查字符串不能為null且去除首尾空格后長(zhǎng)度大于0。@NotEmpty:主要用于集合校驗(yàn),校驗(yàn)集合不能為null且size大于0,也可以用于String的校驗(yàn),確保字@Null:確保字段值為null。@AssertTrue 和 @AssertFalse:用于boolean字段,確保字段值為true或false。@Min 和 @Max:用于Number和String字段,確保字段值在指定的范圍內(nèi)。@DecimalMin 和 @DecimalMax:用于BigDecimal,BigInteger,String,byte,short,int,long字段,確保字段值在指定的小數(shù)范圍內(nèi)。需要注意的是,小數(shù)驗(yàn)證存在精度問(wèn)題。@Size:用于Collection,Map,Array,String字段,確保字段的長(zhǎng)度(或大?。┰谥付ǖ姆秶鷥?nèi)。@Digits:用于BigDecimal,BigInteger,String,byte,short,int,long字段,驗(yàn)證值的數(shù)字構(gòu)成是否合法。它有兩個(gè)參數(shù),integer表示整數(shù)部分的數(shù)字的位數(shù),fraction表示小數(shù)部分的數(shù)字的位數(shù)。@Email:用于String字段,驗(yàn)證字段值是否為有效的電子郵件地址。@Past 和 @Future:用于日期和時(shí)間字段,確保日期在過(guò)去或未來(lái)。@Pattern:用于String字段,驗(yàn)證字段值是否匹配指定的正則表達(dá)式。@Range:控制一個(gè)數(shù)值的范圍,如數(shù)字、日期等。@Valid:遞歸地對(duì)關(guān)聯(lián)對(duì)象進(jìn)行校驗(yàn),如果關(guān)聯(lián)對(duì)象是個(gè)集合或者數(shù)組,那么對(duì)其中的元素進(jìn)行遞歸校驗(yàn);如果是一個(gè)map,則對(duì)其中的值部分進(jìn)行校驗(yàn)。@CreditCardNumber:信用卡驗(yàn)證。@URL:驗(yàn)證一個(gè)字符串是否符合URL格式。@ScriptAssert:使用腳本語(yǔ)言進(jìn)行自定義驗(yàn)證。
@NotNull、@NotEmpty和@NotBlank注解說(shuō)明
@NotNull、@NotEmpty和@NotBlank都是Java中的注解,用于在運(yùn)行時(shí)檢查屬性值是否符合特定條件。它們的使用場(chǎng)景如下:
@NotNull:這個(gè)注解用于基本數(shù)據(jù)類(lèi)型和它們的包裝類(lèi)(如Integer、Long、Double等),以及String類(lèi)型。當(dāng)它被用在String類(lèi)型上時(shí),表示該數(shù)據(jù)不能為null,但可以為空字符串。這個(gè)注解一般用在基本數(shù)據(jù)類(lèi)型的非空校驗(yàn)上,如果被其標(biāo)注的字段使用了@Size、@Max或@Min等注解,那么還可以對(duì)字段的數(shù)值大小進(jìn)行控制。此外,@NonNull是JSR 305(缺陷檢查框架)的注解,用于方法或構(gòu)造函數(shù)的參數(shù)上,表明所修飾的參數(shù)不能為null。它會(huì)在代碼檢查(靜態(tài)檢查)時(shí)給出一個(gè)風(fēng)險(xiǎn)警告,但運(yùn)行時(shí)不會(huì)報(bào)錯(cuò)。
@NotEmpty:這個(gè)注解用于String、Collection集合、Map、數(shù)組等類(lèi)型。加了@NotEmpty注解的參數(shù)不能為null,而且長(zhǎng)度或大小必須大于0。這個(gè)注解一般用在集合類(lèi)上。
@NotBlank:這個(gè)注解只能用于String類(lèi)型。加了@NotBlank注解的字符串不能為null,而且去除兩端空白字符后的長(zhǎng)度(trimmed length)必須大于0。這個(gè)注解通常用于前端發(fā)送過(guò)來(lái)的數(shù)據(jù),先進(jìn)行校驗(yàn)處理,再進(jìn)行邏輯判斷。
總結(jié)來(lái)說(shuō),@NotNull、@NotEmpty和@NotBlank的使用場(chǎng)景主要取決于你想要驗(yàn)證的數(shù)據(jù)類(lèi)型和約束條件。@NotNull主要用于基本數(shù)據(jù)類(lèi)型和String的非空檢查,@NotEmpty主要用于集合類(lèi),而@NotBlank則主要用于String類(lèi)型,要求字符串不為null且去除空白字符后的長(zhǎng)度大于0。在實(shí)際開(kāi)發(fā)中,一定要根據(jù)具體需求選擇合適的注解,否則可能會(huì)導(dǎo)致驗(yàn)證邏輯出錯(cuò)。
操作演示
1.導(dǎo)入依賴(lài)
<!--validation-api接口的實(shí)現(xiàn)-->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
<!--Java Bean Validation 的規(guī)范接口-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!--Java 注解處理器,它用于在編譯時(shí)檢查 JSR-303 注解的正確性和一致性-->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>6.2.5.Final</version>
</dependency>
2.校驗(yàn)實(shí)體對(duì)象參數(shù)
實(shí)體類(lèi)
@Data
public class User {
@NotBlank
private String name;
@NotNull(message = "年齡最小1歲,最大100歲")
@Range(min = 1 , max = 100)
private Integer age;
@NotNull(message = "郵箱不能為空,并且要符合規(guī)范")
@Email
private String email;
@NotNull
@Size(min = 2,max = 50)
private String address;
@Past
private Date birthday;
@NotEmpty
private List<String> users;
}controller
//實(shí)體對(duì)象校驗(yàn)
//在實(shí)體類(lèi)參數(shù)和 BindingResult 之間不能有任何其他參數(shù), BindingResult可以接受錯(cuò)誤信息,避免信息拋出!
//@Validated 或 @Valid 代表應(yīng)用校驗(yàn)注解!
@PostMapping("validateObject")
private String validateObject(@Valid @RequestBody User user, BindingResult result) {
//判斷是否有信息綁定錯(cuò)誤! 有可以自行處理!
if (result.hasErrors()) {
String errorMsg = Objects.requireNonNull(result.getFieldError()).toString();
System.out.println(errorMsg);
return "error";
}
System.out.println("user=" + user);
return "success";
}說(shuō)明:
@Validated注解是SpringMVC提供的。
@Valid注解是JSR-303提供的。
3.基本類(lèi)型校驗(yàn)
//基本類(lèi)型校驗(yàn)
@GetMapping("validate")
public String validateBasic(@RequestBody @Min(18) Integer age, @RequestBody @NotBlank String name) {
return "success";
}配置校驗(yàn)器
說(shuō)明:一般情況下不需要配置,SpringMVC已經(jīng)配置好默認(rèn)校驗(yàn)器
基于xml配置方式
LocalValidatorFactoryBean 是 Spring 框架提供的一個(gè)類(lèi),它實(shí)現(xiàn)了 ValidatorFactory 接口。在 Spring 環(huán)境中,LocalValidatorFactoryBean 通常被用作 Bean Validation 的默認(rèn)實(shí)現(xiàn)。Spring 的自動(dòng)配置通常會(huì)為你創(chuàng)建一個(gè) LocalValidatorFactoryBean 實(shí)例,并將其配置為應(yīng)用的默認(rèn) ValidatorFactory。這意味著,當(dāng)你在 Spring 控制器或服務(wù)中使用 @Valid 或 @Validated 注解時(shí),背后實(shí)際上是 LocalValidatorFactoryBean 在執(zhí)行驗(yàn)證邏輯。
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/> <mvc:annotation-driven validator="validator"/>
基于配置類(lèi)方式構(gòu)建 ValidatorFactory 實(shí)例。
ValidatorFactory 是一個(gè)工廠類(lèi),用于生產(chǎn) Validator 實(shí)例,這些 Validator 實(shí)例用于執(zhí)行實(shí)際的驗(yàn)證邏輯。當(dāng)你需要在非 Spring 環(huán)境中進(jìn)行 Bean Validation,或者當(dāng) Spring 的自動(dòng)配置不能滿(mǎn)足你的需求時(shí),你可以使用這個(gè)方法手動(dòng)配置和獲取 Validator。
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Bean
public Validator validator() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
return factory.getValidator();
}
}結(jié)論:
Validation.buildDefaultValidatorFactory():這是 Bean Validation API 的標(biāo)準(zhǔn)方法,用于在非 Spring 環(huán)境中創(chuàng)建 ValidatorFactory。在 Spring 中,除非你有特殊需求需要繞過(guò) Spring 的自動(dòng)配置,否則通常不會(huì)直接使用這個(gè)方法。
LocalValidatorFactoryBean:這是 Spring 框架特有的類(lèi),用于在 Spring 應(yīng)用中作為默認(rèn)的 ValidatorFactory。在 Spring 應(yīng)用中,你通常不需要直接操作 LocalValidatorFactoryBean,因?yàn)?Spring 會(huì)自動(dòng)為你配置和注入它。但是,如果你需要自定義驗(yàn)證器的配置(例如,更改消息插值器、遍歷提供者等),你可以創(chuàng)建一個(gè) LocalValidatorFactoryBean 的 Bean 并進(jìn)行相應(yīng)的配置。
4.集合校驗(yàn)
//集合校驗(yàn)
@PostMapping("validateList")
public Object validateList(@Valid @RequestBody List<@Positive User> users, BindingResult result) {
if (result.hasErrors()) {
Map<String,Object> map = new HashMap<>();
map.put("code","400");
map.put("msg","參數(shù)校驗(yàn)失敗,不符合規(guī)則");
return map;
}
System.out.println(users);
return users;
}自定義校驗(yàn)注解
1.定義一個(gè)注解類(lèi),并使用@interface關(guān)鍵字。
2.在注解類(lèi)上添加@Constraint注解,并指定校驗(yàn)器類(lèi)。
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MyCustomValidator.class)
public @interface MyCustomValidation {
String message() default "該字段不能為空";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}3.創(chuàng)建一個(gè)實(shí)現(xiàn)ConstraintValidator接口的校驗(yàn)器類(lèi),實(shí)現(xiàn)校驗(yàn)邏輯。
public class MyCustomValidator implements ConstraintValidator<MyCustomValidation,String> {
@Override
public void initialize(MyCustomValidation constraintAnnotation) {
//可以在這里進(jìn)行一些初始化操作
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// 自定義校驗(yàn)邏輯:檢查字符串是否為空或僅包含空白字符
return value != null && !value.trim().isEmpty();
}
}4.在需要校驗(yàn)的字段上應(yīng)用自定義注解。
public class CustomValidationEntity {
@MyCustomValidation
private String customField;
}全局異常校驗(yàn)配置
為了優(yōu)雅地處理校驗(yàn)失敗的情況,你可以實(shí)現(xiàn)一個(gè)全局異常處理器來(lái)捕獲MethodArgumentNotValidException異常,并從中提取錯(cuò)誤信息。這個(gè)異常是如果控制器方法形參不滿(mǎn)足約束條件,Spring MVC會(huì)拋出MethodArgumentNotValidException異常,并將錯(cuò)誤信息綁定到相應(yīng)的字段上。例如:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Object> handleValidationExceptions(MethodArgumentNotValidException ex) {
BindingResult bindingResult = ex.getBindingResult();
Map<String, String> errors = new HashMap<>();
for (FieldError fieldError : bindingResult.getFieldErrors()) {
errors.put(fieldError.getField(), fieldError.getDefaultMessage());
}
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}
}在這個(gè)例子中,GlobalExceptionHandler類(lèi)使用@ControllerAdvice注解標(biāo)記為一個(gè)全局異常處理器。handleValidationExceptions方法則用于處理MethodArgumentNotValidException異常。它從BindingResult中提取錯(cuò)誤信息,并將這些信息作為響應(yīng)返回給客戶(hù)端。
這樣,當(dāng)客戶(hù)端發(fā)送一個(gè)包含無(wú)效數(shù)據(jù)的請(qǐng)求時(shí),服務(wù)器會(huì)返回一個(gè)包含錯(cuò)誤信息的響應(yīng),而不是直接拋出異常。
到此這篇關(guān)于SpringMVC實(shí)現(xiàn)參數(shù)校驗(yàn)的文章就介紹到這了,更多相關(guān)SpringMVC參數(shù)校驗(yàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信游戲打飛機(jī)游戲制作(java模擬微信打飛機(jī)游戲)
java模擬微信打飛機(jī)游戲,大家參考使用吧2013-12-12
JAVA中關(guān)于Long類(lèi)型返回前端精度丟失問(wèn)題處理辦法
這篇文章主要介紹了后端JavaBean的id屬性從Long類(lèi)型改為雪花算法后出現(xiàn)的精度丟失問(wèn)題,解決方案包括將id字段類(lèi)型改為字符串或使用Jackson序列化方式,需要的朋友可以參考下2024-11-11
Spring實(shí)戰(zhàn)之獲取方法返回值操作示例
這篇文章主要介紹了Spring實(shí)戰(zhàn)之獲取方法返回值操作,涉及spring配置文件與方法返回值操作相關(guān)使用技巧,需要的朋友可以參考下2019-12-12
java觀察者模式實(shí)現(xiàn)和java觀察者模式演化
觀察者模式是經(jīng)典設(shè)計(jì)模式中很常用的一種,平常我們看到的監(jiān)聽(tīng)器,基本上都是采用這種設(shè)計(jì)模式實(shí)現(xiàn)的,這里探討一下觀察者模式的演化2014-02-02
SpringMVC中利用@InitBinder來(lái)對(duì)頁(yè)面數(shù)據(jù)進(jìn)行解析綁定的方法
本篇文章主要介紹了SpringMVC中利用@InitBinder來(lái)對(duì)頁(yè)面數(shù)據(jù)進(jìn)行解析綁定的方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-03-03
使用Java解決數(shù)組旋轉(zhuǎn)問(wèn)題的方法詳解
給定一個(gè)包含n個(gè)整數(shù)的數(shù)組,要求將數(shù)組中的元素向前移動(dòng)m個(gè)位置,即數(shù)組的前n-m個(gè)元素順序向后移動(dòng)m個(gè)位置,最后m個(gè)元素移動(dòng)到數(shù)組的最前面,本文給大家介紹了如何使用Java解決數(shù)組旋轉(zhuǎn)問(wèn)題,需要的朋友可以參考下2026-03-03
SpringBoot集成Redis并實(shí)現(xiàn)主從架構(gòu)的實(shí)踐
本文主要和大家分享一下在springboot中如何集成redis,并實(shí)現(xiàn)主從架構(gòu),進(jìn)行數(shù)據(jù)的簡(jiǎn)單存儲(chǔ),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12

