欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?controller校驗入?yún)⒌姆椒ㄔ斀?/h1>
 更新時間:2024年06月07日 08:27:02   作者:有信仰  
項目中使用Springboot,在Controller中配置了@NotNull和@Valid,@Notnull不生效,@Valid生效,返回http?status為400,本文給大家介紹了Spring?controller校驗入?yún)⒌姆椒?需要的朋友可以參考下

問題描述

項目中使用Springboot,在Controller中配置了@NotNull和@Valid,@Notnull不生效,@Valid生效,返回http status為400。

@RestController
@RequestMapping("/demo")
public class DemoController {
    @Override
    @PostMapping("/user")
    public CreateUserRsp createUser(
        @NotNull @Size(min = 1, max = 64) @RequestHeader(value = "token") String token,
        @NotNull @Valid @RequestBody CreateUserReq createUserReq) {
        // 業(yè)務邏輯
    }
}

原因分析

controller接收到請求,首先會進行參數(shù)解析,解析相關(guān)的類:

為什么@RequestBody中的@Valid生效了?

參數(shù)中@RequestBody注解是使用RequestResponseBodyMethodProcessor解析的,下面重點看下這個。

public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
	parameter = parameter.nestedIfOptional();
	Object arg = this.readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
	String name = Conventions.getVariableNameForParameter(parameter);
	if (binderFactory != null) {
		WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
		if (arg != null) {
                // 重點
			this.validateIfApplicable(binder, parameter);
			if (binder.getBindingResult().hasErrors() && this.isBindExceptionRequired(binder, parameter)) {
				throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
			}
		}

		if (mavContainer != null) {
			mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
		}
	}

	return this.adaptArgumentIfNecessary(arg, parameter);
}
protected void validateIfApplicable(WebDataBinder binder, MethodParameter parameter) {
	Annotation[] annotations = parameter.getParameterAnnotations();
	Annotation[] var4 = annotations;
	int var5 = annotations.length;

	for(int var6 = 0; var6 < var5; ++var6) {
		Annotation ann = var4[var6];
        // 重點,解析參數(shù)的注解
		Object[] validationHints = ValidationAnnotationUtils.determineValidationHints(ann);
		if (validationHints != null) {
            // 執(zhí)行校驗
			binder.validate(validationHints);
			break;
		}
	}

}

可以看出,@Valid和@Validated注解都可以解析到:

public static Object[] determineValidationHints(Annotation ann) {
	if (ann instanceof Validated) {
		return ((Validated)ann).value();
	} else {
		Class<? extends Annotation> annotationType = ann.annotationType();
		if ("javax.validation.Valid".equals(annotationType.getName())) {
			return EMPTY_OBJECT_ARRAY;
		} else {
			Validated validatedAnn = (Validated)AnnotationUtils.getAnnotation(ann, Validated.class);
			if (validatedAnn != null) {
				return validatedAnn.value();
			} else {
				return annotationType.getSimpleName().startsWith("Valid") ? convertValidationHints(AnnotationUtils.getValue(ann)) : null;
			}
		}
	}
}

為什么@RequestHeader中的@NotNull沒有生效?

按照上面的思路,我們看下RequestHeaderMapMethodArgumentResolver,里面并沒有調(diào)用validate相關(guān)的代碼。

怎么樣才能生效?

在類上加@Validated。并且加maven依賴

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

@Validated生效原理

后處理器MethodValidationPostProcessor中給使用了@Validated注解的類創(chuàng)建了個切面。實際執(zhí)行切面邏輯的是MethodValidationInterceptor

public class MethodValidationPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor implements InitializingBean {
    private Class<? extends Annotation> validatedAnnotationType = Validated.class;
	public void afterPropertiesSet() {
		Pointcut pointcut = new AnnotationMatchingPointcut(this.validatedAnnotationType, true);
		this.advisor = new DefaultPointcutAdvisor(pointcut, this.createMethodValidationAdvice(this.validator));
	}

	protected Advice createMethodValidationAdvice(@Nullable Validator validator) {
		return validator != null ? new MethodValidationInterceptor(validator) : new MethodValidationInterceptor();
	}
}

請求執(zhí)行時,MethodValidationInterceptor中先判斷方法和類上有沒有@Validated,

public Object invoke(MethodInvocation invocation) throws Throwable {
	if (this.isFactoryBeanMetadataMethod(invocation.getMethod())) {
		return invocation.proceed();
	} else {
        // 方法和類上有沒有@Validated
		Class<?>[] groups = this.determineValidationGroups(invocation);
		ExecutableValidator execVal = this.validator.forExecutables();
		Method methodToValidate = invocation.getMethod();
		Object target = invocation.getThis();
		Assert.state(target != null, "Target must not be null");

		Set result;
		try {
            // 校驗
			result = execVal.validateParameters(target, methodToValidate, invocation.getArguments(), groups);
		} catch (IllegalArgumentException var8) {
			methodToValidate = BridgeMethodResolver.findBridgedMethod(ClassUtils.getMostSpecificMethod(invocation.getMethod(), target.getClass()));
			result = execVal.validateParameters(target, methodToValidate, invocation.getArguments(), groups);
		}

		if (!result.isEmpty()) {
            // 校驗失敗的異常
			throw new ConstraintViolationException(result);
		} else {
			Object returnValue = invocation.proceed();
			result = execVal.validateReturnValue(target, methodToValidate, returnValue, groups);
			if (!result.isEmpty()) {
				throw new ConstraintViolationException(result);
			} else {
				return returnValue;
			}
		}
	}
}

實際校驗的類是ValidatorImpl。代碼一直跟下去,能找到最終執(zhí)行校驗的地方。---注意,ValidatorImpl已經(jīng)是hibernate-validator提供的了。

private void validateMetaConstraints(BaseBeanValidationContext<?> validationContext, ValueContext<?, Object> valueContext, Object parent, Iterable<MetaConstraint<?>> constraints) {
	Iterator var5 = constraints.iterator();

	while(var5.hasNext()) {
		MetaConstraint<?> metaConstraint = (MetaConstraint)var5.next();
		this.validateMetaConstraint(validationContext, valueContext, parent, metaConstraint);
		if (this.shouldFailFast(validationContext)) {
			break;
		}
	}

}

總結(jié)

controller中requestBody中直接可以用@Valid或@Validated校驗,如果想校驗方法中單個參數(shù),需要在方法或類上加@Validated,這樣會開啟方法校驗的切面,切面中會拿到方法簽名中每個字段的注解然后進行校驗。

以上就是Spring controller校驗入?yún)⒌姆椒ㄔ斀獾脑敿殐?nèi)容,更多關(guān)于Spring controller校驗入?yún)⒌馁Y料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • springboot引用kettle實現(xiàn)對接oracle數(shù)據(jù)的示例代碼

    springboot引用kettle實現(xiàn)對接oracle數(shù)據(jù)的示例代碼

    這篇文章主要介紹了springboot引用kettle實現(xiàn)對接oracle數(shù)據(jù),其實kettle集成到springboot里面沒有多少代碼,這個功能最主要的還是ktr文件的編寫,只要ktr編寫好了,放到指定文件夾下,寫個定時任務就完事了,需要的朋友可以參考下
    2022-12-12
  • MyBatis常用標簽大全

    MyBatis常用標簽大全

    這篇文章主要介紹了MyBatis常用標簽大全的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-12-12
  • spring項目對某條單據(jù)進行加鎖處理的方法

    spring項目對某條單據(jù)進行加鎖處理的方法

    這篇文章主要給大家介紹了關(guān)于spring項目對某條單據(jù)進行加鎖處理的相關(guān)資料,用于對工單單據(jù)進行加鎖和解鎖處理,以防止多用戶同時編輯同一單據(jù),前端傳遞參數(shù)包括單據(jù)ID、類型、鎖超時時間等,后端通過Redis實現(xiàn)鎖機制,需要的朋友可以參考下
    2024-11-11
  • Java開發(fā)基礎(chǔ)日期類代碼詳解

    Java開發(fā)基礎(chǔ)日期類代碼詳解

    這篇文章主要介紹了Java開發(fā)基礎(chǔ)日期類的相關(guān)內(nèi)容,代碼通過日期工具類獲取指定月份的星期與日期對應關(guān)系,以及獲取指定月份的所有日期與星期集合等,具有一定參考價值,需要的朋友可以了解下。
    2017-10-10
  • Java中的==使用方法詳解

    Java中的==使用方法詳解

    這篇文章主要給大家介紹了關(guān)于Java中的==使用方法的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-09-09
  • 如何解決java.util.zip.ZipFile解壓后被java占用問題

    如何解決java.util.zip.ZipFile解壓后被java占用問題

    這篇文章主要介紹了如何解決java.util.zip.ZipFile解壓后被java占用問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • 并發(fā)編程之Java內(nèi)存模型

    并發(fā)編程之Java內(nèi)存模型

    這篇文章主要介紹了Java并發(fā)編程之內(nèi)存模型,Java內(nèi)存模型中的順序一致性,主要介紹重排序與順序一致性內(nèi)存模型,下面文章將圍繞Java內(nèi)存模型展開內(nèi)容,需要的小伙伴可以參考一下
    2021-11-11
  • 詳解RestTemplate的三種使用方式

    詳解RestTemplate的三種使用方式

    這篇文章主要介紹了詳解RestTemplate的三種使用方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-10-10
  • 解決SpringBoot中的Scheduled單線程執(zhí)行問題

    解決SpringBoot中的Scheduled單線程執(zhí)行問題

    在一次SpringBoot中使用Scheduled定時任務時,發(fā)現(xiàn)某一個任務出現(xiàn)執(zhí)行占用大量資源,會導致其他任務也執(zhí)行失敗,這篇文章主要介紹了SpringBoot中的Scheduled單線程執(zhí)行問題及解決方法,需要的朋友可以參考下
    2022-06-06
  • IDEA與模擬器安裝調(diào)試失敗的處理方法:INSTALL_PARSE_FAILED_NO_CERTIFICATES

    IDEA與模擬器安裝調(diào)試失敗的處理方法:INSTALL_PARSE_FAILED_NO_CERTIFICATES

    這篇文章主要介紹了IDEA與模擬器安裝調(diào)試失敗的處理方法:INSTALL_PARSE_FAILED_NO_CERTIFICATES,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09

最新評論