All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.web.method.annotation.HandlerMethodValidator Maven / Gradle / Ivy

There is a newer version: 6.1.10
Show newest version
/*
 * Copyright 2002-2024 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.method.annotation;

import java.lang.reflect.Method;
import java.util.function.Predicate;

import jakarta.validation.Validator;

import org.springframework.core.Conventions;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.lang.Nullable;
import org.springframework.validation.BindingResult;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.SmartValidator;
import org.springframework.validation.beanvalidation.MethodValidationAdapter;
import org.springframework.validation.method.MethodValidationResult;
import org.springframework.validation.method.MethodValidator;
import org.springframework.validation.method.ParameterErrors;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.bind.support.WebBindingInitializer;

/**
 * {@link MethodValidator} that
 * uses Bean Validation to validate {@code @RequestMapping} method arguments.
 *
 * 

Handles validation results by populating {@link BindingResult} method * arguments with errors from {@link MethodValidationResult#getBeanResults() * beanResults}. Also, helps to determine parameter names for * {@code @ModelAttribute} and {@code @RequestBody} parameters. * * @author Rossen Stoyanchev * @since 6.1 */ public final class HandlerMethodValidator implements MethodValidator { private static final MethodValidationAdapter.ObjectNameResolver objectNameResolver = new WebObjectNameResolver(); private final MethodValidationAdapter validationAdapter; private final Predicate modelAttributePredicate; private final Predicate requestParamPredicate; private HandlerMethodValidator(MethodValidationAdapter validationAdapter, Predicate modelAttributePredicate, Predicate requestParamPredicate) { this.validationAdapter = validationAdapter; this.modelAttributePredicate = modelAttributePredicate; this.requestParamPredicate = requestParamPredicate; } @Override public Class[] determineValidationGroups(Object target, Method method) { return this.validationAdapter.determineValidationGroups(target, method); } @Override public void applyArgumentValidation( Object target, Method method, @Nullable MethodParameter[] parameters, Object[] arguments, Class[] groups) { MethodValidationResult result = validateArguments(target, method, parameters, arguments, groups); if (!result.hasErrors()) { return; } if (!result.getBeanResults().isEmpty()) { int bindingResultCount = 0; for (ParameterErrors errors : result.getBeanResults()) { for (Object arg : arguments) { if (arg instanceof BindingResult bindingResult) { if (bindingResult.getObjectName().equals(errors.getObjectName())) { bindingResult.addAllErrors(errors); bindingResultCount++; break; } } } } if (result.getAllValidationResults().size() == bindingResultCount) { return; } } throw new HandlerMethodValidationException( result, this.modelAttributePredicate, this.requestParamPredicate); } @Override public MethodValidationResult validateArguments( Object target, Method method, @Nullable MethodParameter[] parameters, Object[] arguments, Class[] groups) { return this.validationAdapter.validateArguments(target, method, parameters, arguments, groups); } @Override public void applyReturnValueValidation( Object target, Method method, @Nullable MethodParameter returnType, @Nullable Object returnValue, Class[] groups) { MethodValidationResult result = validateReturnValue(target, method, returnType, returnValue, groups); if (result.hasErrors()) { throw new HandlerMethodValidationException(result); } } @Override public MethodValidationResult validateReturnValue(Object target, Method method, @Nullable MethodParameter returnType, @Nullable Object returnValue, Class[] groups) { return this.validationAdapter.validateReturnValue(target, method, returnType, returnValue, groups); } /** * Static factory method to create a {@link HandlerMethodValidator} when Bean * Validation is enabled for use via {@link ConfigurableWebBindingInitializer}, * for example in Spring MVC or WebFlux config. */ @Nullable public static MethodValidator from( @Nullable WebBindingInitializer initializer, @Nullable ParameterNameDiscoverer paramNameDiscoverer, Predicate modelAttributePredicate, Predicate requestParamPredicate) { if (initializer instanceof ConfigurableWebBindingInitializer configurableInitializer) { Validator validator = getValidator(configurableInitializer); if (validator != null) { MethodValidationAdapter adapter = new MethodValidationAdapter(validator); adapter.setObjectNameResolver(objectNameResolver); if (paramNameDiscoverer != null) { adapter.setParameterNameDiscoverer(paramNameDiscoverer); } MessageCodesResolver codesResolver = configurableInitializer.getMessageCodesResolver(); if (codesResolver != null) { adapter.setMessageCodesResolver(codesResolver); } return new HandlerMethodValidator(adapter, modelAttributePredicate, requestParamPredicate); } } return null; } @Nullable private static Validator getValidator(ConfigurableWebBindingInitializer initializer) { if (initializer.getValidator() instanceof Validator validator) { return validator; } if (initializer.getValidator() instanceof SmartValidator smartValidator) { return smartValidator.unwrap(Validator.class); } return null; } /** * ObjectNameResolver for web controller methods. */ private static class WebObjectNameResolver implements MethodValidationAdapter.ObjectNameResolver { @Override public String resolveName(MethodParameter param, @Nullable Object value) { if (param.hasParameterAnnotation(RequestBody.class) || param.hasParameterAnnotation(RequestPart.class)) { return Conventions.getVariableNameForParameter(param); } else { return (param.getParameterIndex() != -1 ? ModelFactory.getNameForParameter(param) : ModelFactory.getNameForReturnValue(value, param)); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy