最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot之controller參數(shù)校驗詳解

 更新時間:2024年11月11日 11:18:56   作者:FlyLikeButterfly  
介紹了Java中使用@Validated和@Valid進行參數(shù)校驗的方法,包括不同標(biāo)簽的使用場景、基本屬性和一些常用的注解類型,同時,還討論了如何在控制器中使用這些校驗標(biāo)簽,以及如何處理校驗結(jié)果和自定義錯誤消息,最后,還介紹了如何實現(xiàn)分組校驗和嵌套校驗,并提供了一些示例代碼

controller參數(shù)校驗

參數(shù)校驗主要使用兩個標(biāo)簽@Validated和@Valid;

@Valid是Hibernate的注解校驗,@Validated是spring的,是@Valid的增強;這兩個標(biāo)簽也有一些不同之處,@Valid可以標(biāo)注在成員屬性上也可以嵌套校驗,而@Validated不行,但是@Validated可以使用分組校驗;

maven導(dǎo)入:

	<dependency>
	    <groupId>org.springframework.boot</groupId>
	    <artifactId>spring-boot-starter-validation</artifactId>
	    <version>2.7.5</version>
	</dependency>

通常用到的注解基本都在javax.validation.constraints包下,基本都有value(設(shè)定值)、message(設(shè)置錯誤消息)、groups(指定分組)屬性:

  • @AssertFalse:必須為false,支持boolean和Boolean,null是有效的;
  • @AssertTrue:必須為true,支持boolean和Boolean,null是有效的;
  • @DecimalMax:必須是一個小于或者小于等于設(shè)定值的數(shù)字,可以用inclusive指定是否包含數(shù)字(默認(rèn)true),并且value是String類型的,支持BigDecimal、BigInteger、CharSequence、byte / short / int / long以及它們的包裝類(由于舍入原因不支持double和float),null是有效的;
  • @DecimalMin:必須是一個大于或者大于等于設(shè)定值的數(shù)字,其他同@DecimalMax;
  • @Digits:設(shè)定可接受范圍內(nèi)的數(shù)字,必須指定integer(整數(shù)位數(shù))和fraction(小數(shù)位數(shù)),支持BigDecimal、BigInteger、CharSequence、byte / short / int / long以及它們的包裝類,null是有效的;
  • @Email:必須是一個正確格式的郵箱,可以使用regexp指定正則表達(dá)式(默認(rèn)是任意字符串),可以使用flags指定正則表達(dá)式的選項,null是有效的;
  • @Future:必須是一個未來的瞬間、日期或時間(Now是虛擬機默認(rèn)的當(dāng)前時區(qū)的時間),支持java.util.Date、java.util.Calendar、java.time.Instant、java.time.LocalDate、java.time.LocalDateTime、java.time.LocalTime、java.time.MonthDay、java.time.OffsetDateTime、java.time.OffsetTime、java.time.Year、java.time.YearMonth、java.time.ZonedDateTime、java.time.chrono.HijrahDate、java.time.chrono.JapaneseDate、java.time.chrono.MinguoDate、java.time.chrono.ThaiBuddhistDate,null是有效的;
  • @FutureOrPresent:必須是現(xiàn)在或未來的瞬間、日期或時間,其他同@Future;
  • @Max:必須是小于等于指定值的數(shù)字,value是long類型,支持BigDecimal、BigInteger、byte / short / int / long以及它們的包裝類(不支持float和double),null是有效的;
  • @Min:必須是大于等于指定值的數(shù)字,其他同@Max;
  • @Negative:必須是一個嚴(yán)格的負(fù)數(shù),0為無效值,支持BigDecimal、BigInteger、byte / short / int / long / float / double以及它們的包裝類,null是有效的;
  • @NegativeOrZero,必須是負(fù)數(shù)或者0,其他同@Negative;
  • @NotBlank:不能為null,并且至少包含一個非空白字符,接受CharSequence;
  • @NotEmpty:不能為null或空(集合),支持CharSequence(字符序列長度)、Collection(集合size)、Map(map size)、Array(數(shù)組長度);
  • @NotNull:不能為null,支持所有類型;
  • @Null:必須為null,支持所有類型;
  • @Past:必須是一個過去的瞬間、日期或時間,其他同@Future;
  • @PastOrPresent:必須是現(xiàn)在或過去的瞬間、日期或時間,其他同@Future;
  • @Pattern:必須符合指定的正則表達(dá)式,必須使用regexp參數(shù)指定正則表達(dá)式;
  • @Positive:必須是一個嚴(yán)格的正數(shù),0為無效值,其他同@Negative;
  • @PositiveOrZero:必須是正數(shù)或者0,其他同@Negative;
  • @Size:指定元素大小必須在指定范圍內(nèi)(包括邊界值),使用min指定下邊界(默認(rèn)0),使用max指定上邊界(默認(rèn)Integer.MAX_VALUE),支持CharSequence、Collection、Map、Array,null是有效的;

單參數(shù)校驗

在controller類上添加@Validated標(biāo)簽,在方法的參數(shù)前加驗證標(biāo)簽,并且同一個參數(shù)可以添加多個標(biāo)簽;

啟動類:(使用默認(rèn)配置,端口8080)

/**
 * 2022年12月2日下午4:00:48
 */
package testspringboot.test6paramvalidation;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author XWF
 *
 */
@SpringBootApplication
public class Test6Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		SpringApplication.run(Test6Main.class, args);
		
	}

}

controller類:

/**
 * 2022年12月2日下午4:05:34
 */
package testspringboot.test6paramvalidation;

import java.util.List;
import java.util.stream.Collectors;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author XWF
 *
 */
@RestController
@RequestMapping("/test6")
@Validated
public class Test6Controller {
	
	@RequestMapping("/a")
	public String a(@NotNull(message = "參數(shù)s不能為null") String s, @Min(5) @Max(value = 10) long a) {
		System.out.println(s);
		System.out.println(a);
		return String.format("s:%s a:%d", s, a);
	}
	
}

postman測試:

返回的錯誤msg也可以使用自定義設(shè)定,使用@RestControllerAdvice注釋一個類,然后在類里定義各種錯誤msg,就像這樣:

package testspringboot.test6paramvalidation;

import java.util.List;
import java.util.stream.Collectors;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class ValidException {

	@ExceptionHandler(value = MethodArgumentNotValidException.class)
    public String handleValidException(MethodArgumentNotValidException e) {
        List<String> msgList = e.getBindingResult().getAllErrors()
        		.stream()
        		.map(ObjectError::getDefaultMessage)
        		.collect(Collectors.toList());
        return "MethodArgumentNotValidException: " + msgList.toString();
    }

    @ExceptionHandler(value = ConstraintViolationException.class)
    public String handleConstraintViolationException(ConstraintViolationException e) {
        List<String> msgList = e.getConstraintViolations()
                .stream()
                .map(ConstraintViolation::getMessage)
            	.collect(Collectors.toList());
        return "ConstraintViolationException: " + msgList.toString();//返回錯誤描述
    }
    
}

再次測試結(jié)果:

默認(rèn)驗證所有參數(shù),即使前面驗證不通過也會繼續(xù)驗證,可以設(shè)置快速失敗,使驗證失敗立即返回不繼續(xù)驗證;

自定義注入Validator類:

package testspringboot.test6paramvalidation;

import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ValidatConfig {

	@Bean
	public Validator validator() {
		ValidatorFactory vfactory = Validation.byProvider(HibernateValidator.class)
				.configure()
				.failFast(true)//開啟快速失敗
				.buildValidatorFactory();
		return vfactory.getValidator();
		
	}
	
}

再次測試結(jié)果,只顯示一個錯誤msg了:

實體類校驗

只需要在controller類的方法實體類參數(shù)前加@Validated或者@Valid標(biāo)簽,實體類里的屬性前加驗證標(biāo)簽,controller類上可以不用@Validated標(biāo)簽也行;

實體類:

package testspringboot.test6paramvalidation;

import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;

public class Bparam {

	@NotNull
	public String s;
	
	@Max(value = 10, message = "Bparam的x參數(shù)不能超過10")
	public int x;

	public String getS() {
		return s;
	}

	public void setS(String s) {
		this.s = s;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	@Override
	public String toString() {
		return "Bparam [s=" + s + ", x=" + x + "]";
	}
	
}

controller類里的方法:

	@RequestMapping("/b")
	public String b(@Valid Bparam b) {
		return b.toString();
	}

測試:

另外錯誤消息也可以在controller類的方法參數(shù)里接收,參數(shù)里使用BindingResult就可以處理:

	@RequestMapping("/b")
	public String b(@Valid Bparam b, BindingResult result) {
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return b.toString();
	}

使用post的消息體接收參數(shù)也一樣,在參數(shù)前多加一個@RequestBody:

	@RequestMapping("/b")
	public String b(@RequestBody @Validated Bparam b, BindingResult result) {
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return b.toString();
	}

分組校驗

可以為同一屬性設(shè)置不同情況下應(yīng)用不同的注解標(biāo)簽,需要在注解標(biāo)簽里使用groups參數(shù),groups是一個class集合,一個標(biāo)簽可以設(shè)置多個group,在controller類里方法的參數(shù)前的@Validated標(biāo)簽里使用value指定要使用的group驗證(可以指定多個group驗證),沒有設(shè)置groups的標(biāo)簽?zāi)J(rèn)屬于Default.class的group,設(shè)置group的class通常使用interface,可以寫在外面或者直接寫到實體類內(nèi)部;

實體類:

/**
 * 2023年1月13日上午11:08:47
 */
package testspringboot.test6paramvalidation;

import javax.validation.constraints.AssertFalse;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

/**
 * @author XWF
 *
 */
public class Cparam {

	@AssertTrue(message = "b應(yīng)為true", groups = CparamBTrue.class)
	@AssertFalse(message = "b應(yīng)為false", groups = CparamBFalse.class)
	public boolean b;
	
	@NotBlank
	@Size(min = 1, max = 5, message = "s的長度1~5")
	public String s;
	
	@Min(20)
	public int i;
	
//	interface CparamBTrue{}
//	interface CparamBFalse{}
}
interface CparamBTrue{}
interface CparamBFalse{}

controller方法:

	@RequestMapping("/c1")
	public String c1(@RequestBody @Validated(CparamBTrue.class) Cparam c, BindingResult result) {
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return "OK";
	}
	
	@RequestMapping("/c2")
	public String c2(@RequestBody @Validated(value = {CparamBFalse.class, Default.class}) Cparam c, BindingResult result) {
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return "OK";
	}

分組測試:

c1只驗證了group是CparamBTrue的成員b,c2除了驗證了group是CparamBFalse的成員b,也驗證了沒有設(shè)置groups的s和i;

另外也可以設(shè)置動態(tài)組校驗,根據(jù)某些條件和情況設(shè)置驗證的groups,需要在實體類上添加@GroupSequenceProvider標(biāo)簽指定實現(xiàn)了DefaultGroupSequenceProvider接口并實現(xiàn)接口里getValidationGroups方法的class,getValidationGroups方法返回List<Class<?>>,即為當(dāng)前請求需要使用的groups(返回值相當(dāng)于controller類方法參數(shù)前@Validated標(biāo)簽里的value的作用);

例如根據(jù)實體類內(nèi)boolean值指定int值使用正負(fù)數(shù):

實體類:

/**
 * 2023年1月13日下午3:03:56
 */
package testspringboot.test6paramvalidation;

import javax.validation.constraints.Negative;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;

import org.hibernate.validator.group.GroupSequenceProvider;

/**
 * @author XWF
 *
 */
@GroupSequenceProvider(value = C3paramGroupProvider.class)
public class C3param {

	@NotNull(message = "b不能為null")
	public boolean b;
	
	@NotNull
	@Positive(message = "b為true時i應(yīng)大于0", groups = BTrue.class)
	@Negative(message = "b為false時i應(yīng)小于0", groups = BFalse.class)
	public int i;
	
	@Override
	public String toString() {
		return "C3param [b=" + b + ", i=" + i + "]";
	}
	interface BTrue{}
	interface BFalse{}
	
}

GroupProvider:

/**
 * 2023年1月13日下午3:10:32
 */
package testspringboot.test6paramvalidation;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.validator.spi.group.DefaultGroupSequenceProvider;

/**
 * @author XWF
 *
 */
public class C3paramGroupProvider implements DefaultGroupSequenceProvider<C3param> {

	@Override
	public List<Class<?>> getValidationGroups(C3param object) {
		System.out.println("obj:" + object);
		List<Class<?>> groupList = new ArrayList<>();
		groupList.add(C3param.class);//實體類需要加入
		if (object != null) {//該方法會調(diào)用多次,object可能為null
			//b為true時使用BTrue.class組,b為false時使用BFalse.class組
			groupList.add(object.b ? C3param.BTrue.class : C3param.BFalse.class);
		}
		return groupList;
	}

}

controller方法:

	@RequestMapping("/c3")
	public String c3(@RequestBody @Validated C3param c3, BindingResult result) {
		System.out.println("param:" + c3);
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return "OK";
	}

測試:

嵌套校驗

實體類成員為另一個級聯(lián)的類時,需要在成員前使用@Valid標(biāo)簽(支持嵌套),并且提供該級聯(lián)的成員屬性的get方法,另外級聯(lián)類內(nèi)部也需要提供需要驗證的成員屬性的get方法(不驗證的成員不用get方法)

第一層實體類:

/**
 * 2023年1月13日下午3:27:12
 */
package testspringboot.test6paramvalidation;

import javax.validation.Valid;
import javax.validation.constraints.AssertTrue;

/**
 * @author XWF
 *
 */
public class D1param {

	@AssertTrue(message = "D1param.b必須為true")
	public boolean b;
	
	@Valid
	public D2param d2;
	
	public D2param getD2() {//級聯(lián)對象需要get方法
		return d2;
	}
	
}

第二層實體類:

/**
 * 2023年1月13日下午3:27:28
 */
package testspringboot.test6paramvalidation;

import javax.validation.Valid;
import javax.validation.constraints.Positive;

/**
 * @author XWF
 *
 */
public class D2param {

	@Positive(message = "D2param.i必須為正數(shù)")
	public int i;
	
	public String s;//不驗證,不需get方法
	
	@Valid
	public D3param d3;
	
	public int getI() {//成員需要get方法
		return i;
	}

	public D3param getD3() {//級聯(lián)對象需要get方法
		return d3;
	}

}

第三層實體類:

/**
 * 2023年1月13日下午3:37:33
 */
package testspringboot.test6paramvalidation;

import javax.validation.constraints.NotNull;

/**
 * @author XWF
 *
 */
public class D3param {

	@NotNull(message = "D3param.s不能為null")
	public String s;

	public String getS() {//成員需要get方法
		return s;
	}
	
}

controller方法:

	@RequestMapping("/d")
	public String d(@RequestBody @Validated D1param d1, BindingResult result) {
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return "OK";
	}

測試:

自定義注解

定義一個注解,使用@Retention、@Target、@Constraint標(biāo)簽注釋,并攜帶三個方法message()、groups()、payload(),并在@Constraint標(biāo)簽里使用validatedBy屬性指定自定義驗證類,自定義驗證類實現(xiàn)ConstraintValidator<A extends Annotation, T>接口的boolean isValid(T value, ConstraintValidatorContext context)方法,判斷驗證是否通過;

自定義注解:(功能:驗證是偶數(shù))

/**
 * 2023年1月13日下午4:24:06
 */
package testspringboot.test6paramvalidation;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Retention(RUNTIME)
@Target(FIELD)
@Constraint(validatedBy = EValidator.class)
/**
 * @author XWF
 *
 */
public @interface EAnnotation {

	String message() default "應(yīng)該是偶數(shù)";
	
	Class<?>[] groups() default {};
	
	Class<? extends Payload>[] payload() default {};
	
}

對應(yīng)的驗證類:

/**
 * 2023年1月13日下午4:25:39
 */
package testspringboot.test6paramvalidation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 * @author XWF
 *
 */
public class EValidator implements ConstraintValidator<EAnnotation, Integer> {

	@Override
	public boolean isValid(Integer value, ConstraintValidatorContext context) {
		return value % 2 == 0;
	}

}

實體類:

/**
 * 2023年1月13日下午3:52:20
 */
package testspringboot.test6paramvalidation;

/**
 * @author XWF
 *
 */
public class Eparam {

	@EAnnotation
	public int i;
	
}

controller方法:

	@RequestMapping("/e")
	public String e(@RequestBody @Validated Eparam e, BindingResult result) {
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return "OK";
	}

測試:

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • @Value設(shè)置默認(rèn)值后,獲取不到配置值的原因分析

    @Value設(shè)置默認(rèn)值后,獲取不到配置值的原因分析

    這篇文章主要介紹了@Value設(shè)置默認(rèn)值后,獲取不到配置值的原因,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Spring Boot詳解配置文件的用途與用法

    Spring Boot詳解配置文件的用途與用法

    SpringBoot項目是一個標(biāo)準(zhǔn)的Maven項目,它的配置文件需要放在src/main/resources/下,其文件名必須為application,其存在兩種文件形式,分別是properties和yaml(或者yml)文件
    2022-06-06
  • 詳解Spring Boot實戰(zhàn)之Filter實現(xiàn)使用JWT進行接口認(rèn)證

    詳解Spring Boot實戰(zhàn)之Filter實現(xiàn)使用JWT進行接口認(rèn)證

    本篇文章主要介紹了詳解Spring Boot實戰(zhàn)之Filter實現(xiàn)使用JWT進行接口認(rèn)證,具有一定的參考價值,有興趣的可以了解一下
    2017-07-07
  • Java語言實現(xiàn)簡單FTP軟件 FTP軟件效果圖預(yù)覽之上傳功能(3)

    Java語言實現(xiàn)簡單FTP軟件 FTP軟件效果圖預(yù)覽之上傳功能(3)

    這篇文章主要為大家詳細(xì)介紹了Java語言實現(xiàn)簡單FTP軟件,F(xiàn)TP軟件效果圖預(yù)覽之上傳功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • SpringBoot簡單的SpringBoot后端實例

    SpringBoot簡單的SpringBoot后端實例

    這篇文章主要介紹了SpringBoot簡單的SpringBoot后端實例,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • java中年月日的加減法使用示例

    java中年月日的加減法使用示例

    這篇文章主要介紹了java中年月日的加減法使用示例的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • SpringBoot如何使用TraceId日志鏈路追蹤

    SpringBoot如何使用TraceId日志鏈路追蹤

    文章介紹了如何使用TraceId進行日志鏈路追蹤,通過在日志中添加TraceId關(guān)鍵字,可以將同一次業(yè)務(wù)調(diào)用鏈上的日志串起來,本文通過實例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • 淺談java中Map的用法

    淺談java中Map的用法

    Map簡介:將鍵映射到值的對象。一個映射不能包含重復(fù)的鍵;每個鍵最多只能映射到一個值。此接口取代 Dictionary 類,后者完全是一個抽象類,而不是一個接口。
    2015-09-09
  • Java中的CompletionService批量異步執(zhí)行詳解

    Java中的CompletionService批量異步執(zhí)行詳解

    這篇文章主要介紹了Java中的CompletionService批量異步執(zhí)行詳解,我們知道線程池可以執(zhí)行異步任務(wù),同時可以通過返回值Future獲取返回值,所以異步任務(wù)大多數(shù)采用ThreadPoolExecutor+Future,需要的朋友可以參考下
    2023-12-12
  • Java 線程池ExecutorService詳解及實例代碼

    Java 線程池ExecutorService詳解及實例代碼

    這篇文章主要介紹了Java 線程池ExecutorService詳解及實例代碼的相關(guān)資料,線程池減少在創(chuàng)建和銷毀線程上所花的時間以及系統(tǒng)資源的開銷.如果不使用線程池,有可能造成系統(tǒng)創(chuàng)建大量線程而導(dǎo)致消耗系統(tǒng)內(nèi)存以及”過度切換“
    2016-11-11

最新評論

疏附县| 师宗县| 孟连| 荔浦县| 若尔盖县| 衡水市| 左权县| 黎平县| 丽水市| 河津市| 左云县| 讷河市| 明星| 油尖旺区| 正宁县| 阳曲县| 瓮安县| 微山县| 固镇县| 阳原县| 莎车县| 三门峡市| 临朐县| 阿拉善右旗| 绥中县| 甘肃省| 陇川县| 南宁市| 二连浩特市| 天峻县| 紫金县| 丰城市| 河北区| 通渭县| 如东县| 丰宁| 丹巴县| 婺源县| 阿瓦提县| 恩平市| 平利县|