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

org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor Maven / Gradle / Ivy

There is a newer version: 6.1.6
Show newest version
/*
 * Copyright 2002-2020 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.servlet.mvc.method.annotation;

import java.util.Collections;
import java.util.Map;

import jakarta.servlet.ServletRequest;

import org.springframework.core.MethodParameter;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.validation.DataBinder;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.annotation.ModelAttributeMethodProcessor;
import org.springframework.web.servlet.HandlerMapping;

/**
 * A Servlet-specific {@link ModelAttributeMethodProcessor} that applies data
 * binding through a WebDataBinder of type {@link ServletRequestDataBinder}.
 *
 * 

Also adds a fall-back strategy to instantiate the model attribute from a * URI template variable or from a request parameter if the name matches the * model attribute name and there is an appropriate type conversion strategy. * * @author Rossen Stoyanchev * @author Juergen Hoeller * @since 3.1 */ public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodProcessor { /** * Class constructor. * @param annotationNotRequired if "true", non-simple method arguments and * return values are considered model attributes with or without a * {@code @ModelAttribute} annotation */ public ServletModelAttributeMethodProcessor(boolean annotationNotRequired) { super(annotationNotRequired); } /** * Instantiate the model attribute from a URI template variable or from a * request parameter if the name matches to the model attribute name and * if there is an appropriate type conversion strategy. If none of these * are true delegate back to the base class. * @see #createAttributeFromRequestValue */ @Override protected final Object createAttribute(String attributeName, MethodParameter parameter, WebDataBinderFactory binderFactory, NativeWebRequest request) throws Exception { String value = getRequestValueForAttribute(attributeName, request); if (value != null) { Object attribute = createAttributeFromRequestValue( value, attributeName, parameter, binderFactory, request); if (attribute != null) { return attribute; } } return super.createAttribute(attributeName, parameter, binderFactory, request); } /** * Obtain a value from the request that may be used to instantiate the * model attribute through type conversion from String to the target type. *

The default implementation looks for the attribute name to match * a URI variable first and then a request parameter. * @param attributeName the model attribute name * @param request the current request * @return the request value to try to convert, or {@code null} if none */ @Nullable protected String getRequestValueForAttribute(String attributeName, NativeWebRequest request) { Map variables = getUriTemplateVariables(request); String variableValue = variables.get(attributeName); if (StringUtils.hasText(variableValue)) { return variableValue; } String parameterValue = request.getParameter(attributeName); if (StringUtils.hasText(parameterValue)) { return parameterValue; } return null; } protected final Map getUriTemplateVariables(NativeWebRequest request) { @SuppressWarnings("unchecked") Map variables = (Map) request.getAttribute( HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST); return (variables != null ? variables : Collections.emptyMap()); } /** * Create a model attribute from a String request value (e.g. URI template * variable, request parameter) using type conversion. *

The default implementation converts only if there is a registered * {@link Converter} that can perform the conversion. * @param sourceValue the source value to create the model attribute from * @param attributeName the name of the attribute (never {@code null}) * @param parameter the method parameter * @param binderFactory for creating WebDataBinder instance * @param request the current request * @return the created model attribute, or {@code null} if no suitable * conversion found */ @Nullable protected Object createAttributeFromRequestValue(String sourceValue, String attributeName, MethodParameter parameter, WebDataBinderFactory binderFactory, NativeWebRequest request) throws Exception { DataBinder binder = binderFactory.createBinder(request, null, attributeName); ConversionService conversionService = binder.getConversionService(); if (conversionService != null) { TypeDescriptor source = TypeDescriptor.valueOf(String.class); TypeDescriptor target = new TypeDescriptor(parameter); if (conversionService.canConvert(source, target)) { return binder.convertIfNecessary(sourceValue, parameter.getParameterType(), parameter); } } return null; } /** * This implementation downcasts {@link WebDataBinder} to * {@link ServletRequestDataBinder} before binding. * @see ServletRequestDataBinderFactory */ @Override protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) { ServletRequest servletRequest = request.getNativeRequest(ServletRequest.class); Assert.state(servletRequest != null, "No ServletRequest"); ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder; servletBinder.bind(servletRequest); } @Override @Nullable public Object resolveConstructorArgument(String paramName, Class paramType, NativeWebRequest request) throws Exception { Object value = super.resolveConstructorArgument(paramName, paramType, request); if (value != null) { return value; } ServletRequest servletRequest = request.getNativeRequest(ServletRequest.class); if (servletRequest != null) { String attr = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE; @SuppressWarnings("unchecked") Map uriVars = (Map) servletRequest.getAttribute(attr); return uriVars.get(paramName); } return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy