Drop Portlet MVC support

This commit also removes the corresponding deprecated Servlet MVC variant and updates DispatcherServlet.properties to point to RequestMappingHandlerMapping/Adapter by default.

Issue: SPR-14129
This commit is contained in:
Juergen Hoeller
2016-07-04 23:33:45 +02:00
parent ae0b7c26c5
commit 2b3445df81
235 changed files with 94 additions and 39747 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -27,8 +27,6 @@ import org.springframework.core.annotation.AliasFor;
/**
* Annotation which indicates that a method parameter should be bound to an HTTP cookie.
*
* <p>Supported for annotated handler methods in Servlet and Portlet environments.
*
* <p>The method parameter may be declared as type {@link javax.servlet.http.Cookie}
* or as cookie value type (String, int, etc.).
*
@@ -39,9 +37,6 @@ import org.springframework.core.annotation.AliasFor;
* @see RequestParam
* @see RequestHeader
* @see org.springframework.web.bind.annotation.RequestMapping
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -24,8 +24,7 @@ import java.lang.annotation.Target;
/**
* Annotation for handling exceptions in specific handler classes and/or
* handler methods. Provides consistent style between Servlet and Portlet
* environments, with the semantics adapting to the concrete environment.
* handler methods.
*
* <p>Handler methods which are annotated with this annotation are allowed to
* have very flexible signatures. They may have parameters of the following
@@ -34,16 +33,10 @@ import java.lang.annotation.Target;
* <li>An exception argument: declared as a general Exception or as a more
* specific exception. This also serves as a mapping hint if the annotation
* itself does not narrow the exception types through its {@link #value()}.
* <li>Request and/or response objects (Servlet API or Portlet API).
* <li>Request and/or response objects (typically from the Servlet API).
* You may choose any specific request/response type, e.g.
* {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest}
* or {@link javax.portlet.PortletRequest} / {@link javax.portlet.ActionRequest} /
* {@link javax.portlet.RenderRequest}. Note that in the Portlet case,
* an explicitly declared action/render argument is also used for mapping
* specific request types onto a handler method (in case of no other
* information given that differentiates between action and render requests).
* <li>Session object (Servlet API or Portlet API): either
* {@link javax.servlet.http.HttpSession} or {@link javax.portlet.PortletSession}.
* {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest}.
* <li>Session object: typically {@link javax.servlet.http.HttpSession}.
* An argument of this type will enforce the presence of a corresponding session.
* As a consequence, such an argument will never be {@code null}.
* <i>Note that session access may not be thread-safe, in particular in a
@@ -54,17 +47,17 @@ import java.lang.annotation.Target;
* <li>{@link org.springframework.web.context.request.WebRequest} or
* {@link org.springframework.web.context.request.NativeWebRequest}.
* Allows for generic request parameter access as well as request/session
* attribute access, without ties to the native Servlet/Portlet API.
* attribute access, without ties to the native Servlet API.
* <li>{@link java.util.Locale} for the current request locale
* (determined by the most specific locale resolver available,
* i.e. the configured {@link org.springframework.web.servlet.LocaleResolver}
* in a Servlet environment and the portal locale in a Portlet environment).
* in a Servlet environment).
* <li>{@link java.io.InputStream} / {@link java.io.Reader} for access
* to the request's content. This will be the raw InputStream/Reader as
* exposed by the Servlet/Portlet API.
* exposed by the Servlet API.
* <li>{@link java.io.OutputStream} / {@link java.io.Writer} for generating
* the response's content. This will be the raw OutputStream/Writer as
* exposed by the Servlet/Portlet API.
* exposed by the Servlet API.
* <li>{@link org.springframework.ui.Model} as an alternative to returning
* a model map from the handler method. Note that the provided model is not
* pre-populated with regular model attributes and therefore always empty,
@@ -73,7 +66,7 @@ import java.lang.annotation.Target;
*
* <p>The following return types are supported for handler methods:
* <ul>
* <li>A {@code ModelAndView} object (Servlet MVC or Portlet MVC).
* <li>A {@code ModelAndView} object (from Servlet MVC).
* <li>A {@link org.springframework.ui.Model} object, with the view name implicitly
* determined through a {@link org.springframework.web.servlet.RequestToViewNameTranslator}.
* <li>A {@link java.util.Map} object for exposing a model,
@@ -93,30 +86,19 @@ import java.lang.annotation.Target;
* <li>{@code void} if the method handles the response itself (by
* writing the response content directly, declaring an argument of type
* {@link javax.servlet.ServletResponse} / {@link javax.servlet.http.HttpServletResponse}
* / {@link javax.portlet.RenderResponse} for that purpose)
* or if the view name is supposed to be implicitly determined through a
* {@link org.springframework.web.servlet.RequestToViewNameTranslator}
* (not declaring a response argument in the handler method signature;
* only applicable in a Servlet environment).
* for that purpose) or if the view name is supposed to be implicitly determined
* through a {@link org.springframework.web.servlet.RequestToViewNameTranslator}
* (not declaring a response argument in the handler method signature).
* </ul>
*
* <p>In Servlet environments, you can combine the {@code ExceptionHandler} annotation
* with {@link ResponseStatus @ResponseStatus}, to define the response status
* for the HTTP response.
*
* <p><b>Note:</b> In Portlet environments, {@code ExceptionHandler} annotated methods
* will only be called during the render and resource phases - just like
* {@link org.springframework.web.portlet.HandlerExceptionResolver} beans would.
* Exceptions carried over from the action and event phases will be invoked during
* the render phase as well, with exception handler methods having to be present
* on the controller class that defines the applicable <i>render</i> method.
*
* @author Arjen Poutsma
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.web.context.request.WebRequest
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -40,8 +40,6 @@ import org.springframework.core.annotation.AliasFor;
* @see RequestMapping
* @see RequestParam
* @see CookieValue
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -27,34 +27,17 @@ import org.springframework.core.annotation.AliasFor;
/**
* Annotation for mapping web requests onto specific handler classes and/or
* handler methods. Provides a consistent style between Servlet and Portlet
* environments, with the semantics adapting to the concrete environment.
*
* <p><b>NOTE:</b> The set of features supported for Servlets is a superset
* of the set of features supported for Portlets. The places where this applies
* are marked with the label "Servlet-only" in this source file. For Servlet
* environments there are some further distinctions depending on whether an
* application is configured with {@literal "@MVC 3.0"} or
* {@literal "@MVC 3.1"} support classes. The places where this applies are
* marked with {@literal "@MVC 3.1-only"} in this source file. For more
* details see the note on the new support classes added in Spring MVC 3.1
* further below.
* handler methods.
*
* <p>Handler methods which are annotated with this annotation are allowed to
* have very flexible signatures. They may have parameters of the following
* types, in arbitrary order (except for validation results, which need to
* follow right after the corresponding command object, if desired):
* <ul>
* <li>Request and/or response objects (Servlet API or Portlet API).
* <li>Request and/or response objects (typically from the Servlet API).
* You may choose any specific request/response type, e.g.
* {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest}
* or {@link javax.portlet.PortletRequest} / {@link javax.portlet.ActionRequest} /
* {@link javax.portlet.RenderRequest}. Note that in the Portlet case,
* an explicitly declared action/render argument is also used for mapping
* specific request types onto a handler method (in case of no other
* information given that differentiates between action and render requests).
* <li>Session object (Servlet API or Portlet API): either
* {@link javax.servlet.http.HttpSession} or {@link javax.portlet.PortletSession}.
* {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest}.
* <li>Session object: typically {@link javax.servlet.http.HttpSession}.
* An argument of this type will enforce the presence of a corresponding session.
* As a consequence, such an argument will never be {@code null}.
* <i>Note that session access may not be thread-safe, in particular in a
@@ -65,17 +48,17 @@ import org.springframework.core.annotation.AliasFor;
* <li>{@link org.springframework.web.context.request.WebRequest} or
* {@link org.springframework.web.context.request.NativeWebRequest}.
* Allows for generic request parameter access as well as request/session
* attribute access, without ties to the native Servlet/Portlet API.
* attribute access, without ties to the native Servlet API.
* <li>{@link java.util.Locale} for the current request locale
* (determined by the most specific locale resolver available,
* i.e. the configured {@link org.springframework.web.servlet.LocaleResolver}
* in a Servlet environment and the portal locale in a Portlet environment).
* in a Servlet environment).
* <li>{@link java.io.InputStream} / {@link java.io.Reader} for access
* to the request's content. This will be the raw InputStream/Reader as
* exposed by the Servlet/Portlet API.
* exposed by the Servlet API.
* <li>{@link java.io.OutputStream} / {@link java.io.Writer} for generating
* the response's content. This will be the raw OutputStream/Writer as
* exposed by the Servlet/Portlet API.
* exposed by the Servlet API.
* <li>{@link org.springframework.http.HttpMethod} for the HTTP request method</li>
* <li>{@link PathVariable @PathVariable} annotated parameters (Servlet-only)
* for access to URI template values (i.e. /hotels/{hotel}). Variable values will be
@@ -94,13 +77,13 @@ import org.springframework.core.annotation.AliasFor;
* {@link java.util.Map Map&lt;String, String&gt;} to gain access to all
* matrix variables in the URL or to those in a specific path variable.
* <li>{@link RequestParam @RequestParam} annotated parameters for access to
* specific Servlet/Portlet request parameters. Parameter values will be
* specific Servlet request parameters. Parameter values will be
* converted to the declared method argument type. Additionally,
* {@code @RequestParam} can be used on a {@link java.util.Map Map&lt;String, String&gt;} or
* {@link org.springframework.util.MultiValueMap MultiValueMap&lt;String, String&gt;}
* method parameter to gain access to all request parameters.
* <li>{@link RequestHeader @RequestHeader} annotated parameters for access to
* specific Servlet/Portlet request HTTP headers. Parameter values will be
* specific Servlet request HTTP headers. Parameter values will be
* converted to the declared method argument type. Additionally,
* {@code @RequestHeader} can be used on a {@link java.util.Map Map&lt;String, String&gt;},
* {@link org.springframework.util.MultiValueMap MultiValueMap&lt;String, String&gt;}, or
@@ -177,7 +160,7 @@ import org.springframework.core.annotation.AliasFor;
*
* <p>The following return types are supported for handler methods:
* <ul>
* <li>A {@code ModelAndView} object (Servlet MVC or Portlet MVC),
* <li>A {@code ModelAndView} object (from Servlet MVC),
* with the model implicitly enriched with command objects and the results
* of {@link ModelAttribute @ModelAttribute} annotated reference data accessor methods.
* <li>A {@link org.springframework.ui.Model Model} object, with the view name implicitly
@@ -238,11 +221,9 @@ import org.springframework.core.annotation.AliasFor;
* <li>{@code void} if the method handles the response itself (by
* writing the response content directly, declaring an argument of type
* {@link javax.servlet.ServletResponse} / {@link javax.servlet.http.HttpServletResponse}
* / {@link javax.portlet.RenderResponse} for that purpose)
* or if the view name is supposed to be implicitly determined through a
* {@link org.springframework.web.servlet.RequestToViewNameTranslator}
* (not declaring a response argument in the handler method signature;
* only applicable in a Servlet environment).
* for that purpose) or if the view name is supposed to be implicitly determined
* through a {@link org.springframework.web.servlet.RequestToViewNameTranslator}
* (not declaring a response argument in the handler method signature).
* <li>Any other return type will be considered as single model attribute
* to be exposed to the view, using the attribute name specified through
* {@link ModelAttribute @ModelAttribute} at the method level (or the default attribute
@@ -253,9 +234,7 @@ import org.springframework.core.annotation.AliasFor;
*
* <p><b>NOTE:</b> {@code @RequestMapping} will only be processed if an
* an appropriate {@code HandlerMapping}-{@code HandlerAdapter} pair
* is configured. This is the case by default in both the
* {@code DispatcherServlet} and the {@code DispatcherPortlet}.
* However, if you are defining custom {@code HandlerMappings} or
* is configured. If you are defining custom {@code HandlerMappings} or
* {@code HandlerAdapters}, then you need to add
* {@code DefaultAnnotationHandlerMapping} and
* {@code AnnotationMethodHandlerAdapter} to your configuration.</code>.
@@ -293,8 +272,6 @@ import org.springframework.core.annotation.AliasFor;
* @see InitBinder
* @see org.springframework.web.context.request.WebRequest
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
* @see org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@@ -314,11 +291,9 @@ public @interface RequestMapping {
/**
* The primary mapping expressed by this annotation.
* <p>In a Servlet environment this is an alias for {@link #path}.
* For example {@code @RequestMapping("/foo")} is equivalent to
* <p>This is an alias for {@link #path}. For example
* {@code @RequestMapping("/foo")} is equivalent to
* {@code @RequestMapping(path="/foo")}.
* <p>In a Portlet environment this is the mapped portlet modes
* (i.e. "EDIT", "VIEW", "HELP" or any custom modes).
* <p><b>Supported at the type level as well as at the method level!</b>
* When used at the type level, all method-level mappings inherit
* this primary mapping, narrowing it for a specific handler method.
@@ -348,7 +323,6 @@ public @interface RequestMapping {
* When used at the type level, all method-level mappings inherit
* this HTTP method restriction (i.e. the type-level restriction
* gets checked before the handler method is even resolved).
* <p>Supported for Servlet environments as well as Portlet 2.0 environments.
*/
RequestMethod[] method() default {};
@@ -365,14 +339,10 @@ public @interface RequestMapping {
* When used at the type level, all method-level mappings inherit
* this parameter restriction (i.e. the type-level restriction
* gets checked before the handler method is even resolved).
* <p>In a Servlet environment, parameter mappings are considered as restrictions
* that are enforced at the type level. The primary path mapping (i.e. the
* specified URI value) still has to uniquely identify the target handler, with
* parameter mappings simply expressing preconditions for invoking the handler.
* <p>In a Portlet environment, parameters are taken into account as mapping
* differentiators, i.e. the primary portlet mode mapping plus the parameter
* conditions uniquely identify the target handler. Different handlers may be
* mapped onto the same portlet mode, as long as their parameter mappings differ.
* <p>Parameter mappings are considered as restrictions that are enforced at
* the type level. The primary path mapping (i.e. the specified URI value)
* still has to uniquely identify the target handler, with parameter mappings
* simply expressing preconditions for invoking the handler.
*/
String[] params() default {};
@@ -395,8 +365,6 @@ public @interface RequestMapping {
* When used at the type level, all method-level mappings inherit
* this header restriction (i.e. the type-level restriction
* gets checked before the handler method is even resolved).
* <p>Maps against HttpServletRequest headers in a Servlet environment,
* and against PortletRequest properties in a Portlet 2.0 environment.
* @see org.springframework.http.MediaType
*/
String[] headers() default {};

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -47,9 +47,6 @@ import org.springframework.core.annotation.AliasFor;
* @see RequestMapping
* @see RequestHeader
* @see CookieValue
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -1,44 +0,0 @@
/*
* Copyright 2002-2012 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
*
* http://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.bind.annotation.support;
import java.lang.reflect.Method;
import org.springframework.core.NestedRuntimeException;
/**
* Exception indicating that the execution of an annotated MVC handler method failed.
*
* @author Juergen Hoeller
* @since 2.5.6
* @see HandlerMethodInvoker#invokeHandlerMethod
* @deprecated as of 4.3, in favor of the {@code HandlerMethod}-based MVC infrastructure
*/
@Deprecated
@SuppressWarnings("serial")
public class HandlerMethodInvocationException extends NestedRuntimeException {
/**
* Create a new HandlerMethodInvocationException for the given Method handle and cause.
* @param handlerMethod the handler method handle
* @param cause the cause of the invocation failure
*/
public HandlerMethodInvocationException(Method handlerMethod, Throwable cause) {
super("Failed to invoke handler method [" + handlerMethod + "]", cause);
}
}

View File

@@ -1,901 +0,0 @@
/*
* Copyright 2002-2015 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
*
* http://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.bind.annotation.support;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.Conventions;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.ui.Model;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ReflectionUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ValueConstants;
import org.springframework.web.bind.support.DefaultSessionAttributeStore;
import org.springframework.web.bind.support.SessionAttributeStore;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.bind.support.SimpleSessionStatus;
import org.springframework.web.bind.support.WebArgumentResolver;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.bind.support.WebRequestDataBinder;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;
/**
* Support class for invoking an annotated handler method. Operates on the introspection
* results of a {@link HandlerMethodResolver} for a specific handler type.
*
* <p>Used by {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter}
* and {@link org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter}.
*
* @author Juergen Hoeller
* @author Arjen Poutsma
* @since 2.5.2
* @see #invokeHandlerMethod
* @deprecated as of 4.3, in favor of the {@code HandlerMethod}-based MVC infrastructure
*/
@Deprecated
public class HandlerMethodInvoker {
private static final String MODEL_KEY_PREFIX_STALE = SessionAttributeStore.class.getName() + ".STALE.";
/** We'll create a lot of these objects, so we don't want a new logger every time. */
private static final Log logger = LogFactory.getLog(HandlerMethodInvoker.class);
private final HandlerMethodResolver methodResolver;
private final WebBindingInitializer bindingInitializer;
private final SessionAttributeStore sessionAttributeStore;
private final ParameterNameDiscoverer parameterNameDiscoverer;
private final WebArgumentResolver[] customArgumentResolvers;
private final HttpMessageConverter<?>[] messageConverters;
private final SimpleSessionStatus sessionStatus = new SimpleSessionStatus();
public HandlerMethodInvoker(HandlerMethodResolver methodResolver) {
this(methodResolver, null);
}
public HandlerMethodInvoker(HandlerMethodResolver methodResolver, WebBindingInitializer bindingInitializer) {
this(methodResolver, bindingInitializer, new DefaultSessionAttributeStore(), null, null, null);
}
public HandlerMethodInvoker(HandlerMethodResolver methodResolver, WebBindingInitializer bindingInitializer,
SessionAttributeStore sessionAttributeStore, ParameterNameDiscoverer parameterNameDiscoverer,
WebArgumentResolver[] customArgumentResolvers, HttpMessageConverter<?>[] messageConverters) {
this.methodResolver = methodResolver;
this.bindingInitializer = bindingInitializer;
this.sessionAttributeStore = sessionAttributeStore;
this.parameterNameDiscoverer = parameterNameDiscoverer;
this.customArgumentResolvers = customArgumentResolvers;
this.messageConverters = messageConverters;
}
public final Object invokeHandlerMethod(Method handlerMethod, Object handler,
NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
try {
boolean debug = logger.isDebugEnabled();
for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
if (attrValue != null) {
implicitModel.addAttribute(attrName, attrValue);
}
}
for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
if (debug) {
logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
}
String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
continue;
}
ReflectionUtils.makeAccessible(attributeMethodToInvoke);
Object attrValue = attributeMethodToInvoke.invoke(handler, args);
if ("".equals(attrName)) {
Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
}
if (!implicitModel.containsAttribute(attrName)) {
implicitModel.addAttribute(attrName, attrValue);
}
}
Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
if (debug) {
logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
}
ReflectionUtils.makeAccessible(handlerMethodToInvoke);
return handlerMethodToInvoke.invoke(handler, args);
}
catch (IllegalStateException ex) {
// Internal assertion failed (e.g. invalid signature):
// throw exception with full handler method context...
throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
}
catch (InvocationTargetException ex) {
// User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
ReflectionUtils.rethrowException(ex.getTargetException());
return null;
}
}
public final void updateModelAttributes(Object handler, Map<String, Object> mavModel,
ExtendedModelMap implicitModel, NativeWebRequest webRequest) throws Exception {
if (this.methodResolver.hasSessionAttributes() && this.sessionStatus.isComplete()) {
for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
this.sessionAttributeStore.cleanupAttribute(webRequest, attrName);
}
}
// Expose model attributes as session attributes, if required.
// Expose BindingResults for all attributes, making custom editors available.
Map<String, Object> model = (mavModel != null ? mavModel : implicitModel);
if (model != null) {
try {
String[] originalAttrNames = model.keySet().toArray(new String[model.size()]);
for (String attrName : originalAttrNames) {
Object attrValue = model.get(attrName);
boolean isSessionAttr = this.methodResolver.isSessionAttribute(
attrName, (attrValue != null ? attrValue.getClass() : null));
if (isSessionAttr) {
if (this.sessionStatus.isComplete()) {
implicitModel.put(MODEL_KEY_PREFIX_STALE + attrName, Boolean.TRUE);
}
else if (!implicitModel.containsKey(MODEL_KEY_PREFIX_STALE + attrName)) {
this.sessionAttributeStore.storeAttribute(webRequest, attrName, attrValue);
}
}
if (!attrName.startsWith(BindingResult.MODEL_KEY_PREFIX) &&
(isSessionAttr || isBindingCandidate(attrValue))) {
String bindingResultKey = BindingResult.MODEL_KEY_PREFIX + attrName;
if (mavModel != null && !model.containsKey(bindingResultKey)) {
WebDataBinder binder = createBinder(webRequest, attrValue, attrName);
initBinder(handler, attrName, binder, webRequest);
mavModel.put(bindingResultKey, binder.getBindingResult());
}
}
}
}
catch (InvocationTargetException ex) {
// User-defined @InitBinder method threw an exception...
ReflectionUtils.rethrowException(ex.getTargetException());
}
}
}
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler,
NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
Class<?>[] paramTypes = handlerMethod.getParameterTypes();
Object[] args = new Object[paramTypes.length];
for (int i = 0; i < args.length; i++) {
MethodParameter methodParam = new SynthesizingMethodParameter(handlerMethod, i);
methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
String paramName = null;
String headerName = null;
boolean requestBodyFound = false;
String cookieName = null;
String pathVarName = null;
String attrName = null;
boolean required = false;
String defaultValue = null;
boolean validate = false;
Object[] validationHints = null;
int annotationsFound = 0;
Annotation[] paramAnns = methodParam.getParameterAnnotations();
for (Annotation paramAnn : paramAnns) {
if (RequestParam.class.isInstance(paramAnn)) {
RequestParam requestParam = (RequestParam) paramAnn;
paramName = requestParam.name();
required = requestParam.required();
defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());
annotationsFound++;
}
else if (RequestHeader.class.isInstance(paramAnn)) {
RequestHeader requestHeader = (RequestHeader) paramAnn;
headerName = requestHeader.name();
required = requestHeader.required();
defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue());
annotationsFound++;
}
else if (RequestBody.class.isInstance(paramAnn)) {
requestBodyFound = true;
annotationsFound++;
}
else if (CookieValue.class.isInstance(paramAnn)) {
CookieValue cookieValue = (CookieValue) paramAnn;
cookieName = cookieValue.name();
required = cookieValue.required();
defaultValue = parseDefaultValueAttribute(cookieValue.defaultValue());
annotationsFound++;
}
else if (PathVariable.class.isInstance(paramAnn)) {
PathVariable pathVar = (PathVariable) paramAnn;
pathVarName = pathVar.value();
annotationsFound++;
}
else if (ModelAttribute.class.isInstance(paramAnn)) {
ModelAttribute attr = (ModelAttribute) paramAnn;
attrName = attr.value();
annotationsFound++;
}
else if (Value.class.isInstance(paramAnn)) {
defaultValue = ((Value) paramAnn).value();
}
else {
Validated validatedAnn = AnnotationUtils.getAnnotation(paramAnn, Validated.class);
if (validatedAnn != null || paramAnn.annotationType().getSimpleName().startsWith("Valid")) {
validate = true;
Object hints = (validatedAnn != null ? validatedAnn.value() : AnnotationUtils.getValue(paramAnn));
validationHints = (hints instanceof Object[] ? (Object[]) hints : new Object[]{hints});
}
}
}
if (annotationsFound > 1) {
throw new IllegalStateException("Handler parameter annotations are exclusive choices - " +
"do not specify more than one such annotation on the same parameter: " + handlerMethod);
}
if (annotationsFound == 0) {
Object argValue = resolveCommonArgument(methodParam, webRequest);
if (argValue != WebArgumentResolver.UNRESOLVED) {
args[i] = argValue;
}
else if (defaultValue != null) {
args[i] = resolveDefaultValue(defaultValue);
}
else {
Class<?> paramType = methodParam.getParameterType();
if (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) {
if (!paramType.isAssignableFrom(implicitModel.getClass())) {
throw new IllegalStateException("Argument [" + paramType.getSimpleName() + "] is of type " +
"Model or Map but is not assignable from the actual model. You may need to switch " +
"newer MVC infrastructure classes to use this argument.");
}
args[i] = implicitModel;
}
else if (SessionStatus.class.isAssignableFrom(paramType)) {
args[i] = this.sessionStatus;
}
else if (HttpEntity.class.isAssignableFrom(paramType)) {
args[i] = resolveHttpEntityRequest(methodParam, webRequest);
}
else if (Errors.class.isAssignableFrom(paramType)) {
throw new IllegalStateException("Errors/BindingResult argument declared " +
"without preceding model attribute. Check your handler method signature!");
}
else if (BeanUtils.isSimpleProperty(paramType)) {
paramName = "";
}
else {
attrName = "";
}
}
}
if (paramName != null) {
args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);
}
else if (headerName != null) {
args[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);
}
else if (requestBodyFound) {
args[i] = resolveRequestBody(methodParam, webRequest, handler);
}
else if (cookieName != null) {
args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);
}
else if (pathVarName != null) {
args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);
}
else if (attrName != null) {
WebDataBinder binder =
resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
boolean assignBindingResult = (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));
if (binder.getTarget() != null) {
doBind(binder, webRequest, validate, validationHints, !assignBindingResult);
}
args[i] = binder.getTarget();
if (assignBindingResult) {
args[i + 1] = binder.getBindingResult();
i++;
}
implicitModel.putAll(binder.getBindingResult().getModel());
}
}
return args;
}
protected void initBinder(Object handler, String attrName, WebDataBinder binder, NativeWebRequest webRequest)
throws Exception {
if (this.bindingInitializer != null) {
this.bindingInitializer.initBinder(binder, webRequest);
}
if (handler != null) {
Set<Method> initBinderMethods = this.methodResolver.getInitBinderMethods();
if (!initBinderMethods.isEmpty()) {
boolean debug = logger.isDebugEnabled();
for (Method initBinderMethod : initBinderMethods) {
Method methodToInvoke = BridgeMethodResolver.findBridgedMethod(initBinderMethod);
String[] targetNames = AnnotationUtils.findAnnotation(initBinderMethod, InitBinder.class).value();
if (targetNames.length == 0 || Arrays.asList(targetNames).contains(attrName)) {
Object[] initBinderArgs =
resolveInitBinderArguments(handler, methodToInvoke, binder, webRequest);
if (debug) {
logger.debug("Invoking init-binder method: " + methodToInvoke);
}
ReflectionUtils.makeAccessible(methodToInvoke);
Object returnValue = methodToInvoke.invoke(handler, initBinderArgs);
if (returnValue != null) {
throw new IllegalStateException(
"InitBinder methods must not have a return value: " + methodToInvoke);
}
}
}
}
}
}
private Object[] resolveInitBinderArguments(Object handler, Method initBinderMethod,
WebDataBinder binder, NativeWebRequest webRequest) throws Exception {
Class<?>[] initBinderParams = initBinderMethod.getParameterTypes();
Object[] initBinderArgs = new Object[initBinderParams.length];
for (int i = 0; i < initBinderArgs.length; i++) {
MethodParameter methodParam = new SynthesizingMethodParameter(initBinderMethod, i);
methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
String paramName = null;
boolean paramRequired = false;
String paramDefaultValue = null;
String pathVarName = null;
Annotation[] paramAnns = methodParam.getParameterAnnotations();
for (Annotation paramAnn : paramAnns) {
if (RequestParam.class.isInstance(paramAnn)) {
RequestParam requestParam = (RequestParam) paramAnn;
paramName = requestParam.name();
paramRequired = requestParam.required();
paramDefaultValue = parseDefaultValueAttribute(requestParam.defaultValue());
break;
}
else if (ModelAttribute.class.isInstance(paramAnn)) {
throw new IllegalStateException(
"@ModelAttribute is not supported on @InitBinder methods: " + initBinderMethod);
}
else if (PathVariable.class.isInstance(paramAnn)) {
PathVariable pathVar = (PathVariable) paramAnn;
pathVarName = pathVar.value();
}
}
if (paramName == null && pathVarName == null) {
Object argValue = resolveCommonArgument(methodParam, webRequest);
if (argValue != WebArgumentResolver.UNRESOLVED) {
initBinderArgs[i] = argValue;
}
else {
Class<?> paramType = initBinderParams[i];
if (paramType.isInstance(binder)) {
initBinderArgs[i] = binder;
}
else if (BeanUtils.isSimpleProperty(paramType)) {
paramName = "";
}
else {
throw new IllegalStateException("Unsupported argument [" + paramType.getName() +
"] for @InitBinder method: " + initBinderMethod);
}
}
}
if (paramName != null) {
initBinderArgs[i] =
resolveRequestParam(paramName, paramRequired, paramDefaultValue, methodParam, webRequest, null);
}
else if (pathVarName != null) {
initBinderArgs[i] = resolvePathVariable(pathVarName, methodParam, webRequest, null);
}
}
return initBinderArgs;
}
@SuppressWarnings("unchecked")
private Object resolveRequestParam(String paramName, boolean required, String defaultValue,
MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
throws Exception {
Class<?> paramType = methodParam.getParameterType();
if (Map.class.isAssignableFrom(paramType) && paramName.length() == 0) {
return resolveRequestParamMap((Class<? extends Map<?, ?>>) paramType, webRequest);
}
if (paramName.length() == 0) {
paramName = getRequiredParameterName(methodParam);
}
Object paramValue = null;
MultipartRequest multipartRequest = webRequest.getNativeRequest(MultipartRequest.class);
if (multipartRequest != null) {
List<MultipartFile> files = multipartRequest.getFiles(paramName);
if (!files.isEmpty()) {
paramValue = (files.size() == 1 ? files.get(0) : files);
}
}
if (paramValue == null) {
String[] paramValues = webRequest.getParameterValues(paramName);
if (paramValues != null) {
paramValue = (paramValues.length == 1 ? paramValues[0] : paramValues);
}
}
if (paramValue == null) {
if (defaultValue != null) {
paramValue = resolveDefaultValue(defaultValue);
}
else if (required) {
raiseMissingParameterException(paramName, paramType);
}
paramValue = checkValue(paramName, paramValue, paramType);
}
WebDataBinder binder = createBinder(webRequest, null, paramName);
initBinder(handlerForInitBinderCall, paramName, binder, webRequest);
return binder.convertIfNecessary(paramValue, paramType, methodParam);
}
private Map<String, ?> resolveRequestParamMap(Class<? extends Map<?, ?>> mapType, NativeWebRequest webRequest) {
Map<String, String[]> parameterMap = webRequest.getParameterMap();
if (MultiValueMap.class.isAssignableFrom(mapType)) {
MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>(parameterMap.size());
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
for (String value : entry.getValue()) {
result.add(entry.getKey(), value);
}
}
return result;
}
else {
Map<String, String> result = new LinkedHashMap<String, String>(parameterMap.size());
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
if (entry.getValue().length > 0) {
result.put(entry.getKey(), entry.getValue()[0]);
}
}
return result;
}
}
@SuppressWarnings("unchecked")
private Object resolveRequestHeader(String headerName, boolean required, String defaultValue,
MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
throws Exception {
Class<?> paramType = methodParam.getParameterType();
if (Map.class.isAssignableFrom(paramType)) {
return resolveRequestHeaderMap((Class<? extends Map<?, ?>>) paramType, webRequest);
}
if (headerName.length() == 0) {
headerName = getRequiredParameterName(methodParam);
}
Object headerValue = null;
String[] headerValues = webRequest.getHeaderValues(headerName);
if (headerValues != null) {
headerValue = (headerValues.length == 1 ? headerValues[0] : headerValues);
}
if (headerValue == null) {
if (defaultValue != null) {
headerValue = resolveDefaultValue(defaultValue);
}
else if (required) {
raiseMissingHeaderException(headerName, paramType);
}
headerValue = checkValue(headerName, headerValue, paramType);
}
WebDataBinder binder = createBinder(webRequest, null, headerName);
initBinder(handlerForInitBinderCall, headerName, binder, webRequest);
return binder.convertIfNecessary(headerValue, paramType, methodParam);
}
private Map<String, ?> resolveRequestHeaderMap(Class<? extends Map<?, ?>> mapType, NativeWebRequest webRequest) {
if (MultiValueMap.class.isAssignableFrom(mapType)) {
MultiValueMap<String, String> result;
if (HttpHeaders.class.isAssignableFrom(mapType)) {
result = new HttpHeaders();
}
else {
result = new LinkedMultiValueMap<String, String>();
}
for (Iterator<String> iterator = webRequest.getHeaderNames(); iterator.hasNext();) {
String headerName = iterator.next();
for (String headerValue : webRequest.getHeaderValues(headerName)) {
result.add(headerName, headerValue);
}
}
return result;
}
else {
Map<String, String> result = new LinkedHashMap<String, String>();
for (Iterator<String> iterator = webRequest.getHeaderNames(); iterator.hasNext();) {
String headerName = iterator.next();
String headerValue = webRequest.getHeader(headerName);
result.put(headerName, headerValue);
}
return result;
}
}
/**
* Resolves the given {@link RequestBody @RequestBody} annotation.
*/
protected Object resolveRequestBody(MethodParameter methodParam, NativeWebRequest webRequest, Object handler)
throws Exception {
return readWithMessageConverters(methodParam, createHttpInputMessage(webRequest), methodParam.getParameterType());
}
private HttpEntity<?> resolveHttpEntityRequest(MethodParameter methodParam, NativeWebRequest webRequest)
throws Exception {
HttpInputMessage inputMessage = createHttpInputMessage(webRequest);
Class<?> paramType = getHttpEntityType(methodParam);
Object body = readWithMessageConverters(methodParam, inputMessage, paramType);
return new HttpEntity<Object>(body, inputMessage.getHeaders());
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Object readWithMessageConverters(MethodParameter methodParam, HttpInputMessage inputMessage, Class<?> paramType)
throws Exception {
MediaType contentType = inputMessage.getHeaders().getContentType();
if (contentType == null) {
StringBuilder builder = new StringBuilder(ClassUtils.getShortName(methodParam.getParameterType()));
String paramName = methodParam.getParameterName();
if (paramName != null) {
builder.append(' ');
builder.append(paramName);
}
throw new HttpMediaTypeNotSupportedException(
"Cannot extract parameter (" + builder.toString() + "): no Content-Type found");
}
List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
if (this.messageConverters != null) {
for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
if (messageConverter.canRead(paramType, contentType)) {
if (logger.isDebugEnabled()) {
logger.debug("Reading [" + paramType.getName() + "] as \"" + contentType
+"\" using [" + messageConverter + "]");
}
return messageConverter.read((Class) paramType, inputMessage);
}
}
}
throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes);
}
private Class<?> getHttpEntityType(MethodParameter methodParam) {
Assert.isAssignable(HttpEntity.class, methodParam.getParameterType());
ParameterizedType type = (ParameterizedType) methodParam.getGenericParameterType();
if (type.getActualTypeArguments().length == 1) {
Type typeArgument = type.getActualTypeArguments()[0];
if (typeArgument instanceof Class) {
return (Class<?>) typeArgument;
}
else if (typeArgument instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) typeArgument).getGenericComponentType();
if (componentType instanceof Class) {
// Surely, there should be a nicer way to do this
Object array = Array.newInstance((Class<?>) componentType, 0);
return array.getClass();
}
}
}
throw new IllegalArgumentException(
"HttpEntity parameter (" + methodParam.getParameterName() + ") is not parameterized");
}
private Object resolveCookieValue(String cookieName, boolean required, String defaultValue,
MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
throws Exception {
Class<?> paramType = methodParam.getParameterType();
if (cookieName.length() == 0) {
cookieName = getRequiredParameterName(methodParam);
}
Object cookieValue = resolveCookieValue(cookieName, paramType, webRequest);
if (cookieValue == null) {
if (defaultValue != null) {
cookieValue = resolveDefaultValue(defaultValue);
}
else if (required) {
raiseMissingCookieException(cookieName, paramType);
}
cookieValue = checkValue(cookieName, cookieValue, paramType);
}
WebDataBinder binder = createBinder(webRequest, null, cookieName);
initBinder(handlerForInitBinderCall, cookieName, binder, webRequest);
return binder.convertIfNecessary(cookieValue, paramType, methodParam);
}
/**
* Resolves the given {@link CookieValue @CookieValue} annotation.
* <p>Throws an UnsupportedOperationException by default.
*/
protected Object resolveCookieValue(String cookieName, Class<?> paramType, NativeWebRequest webRequest)
throws Exception {
throw new UnsupportedOperationException("@CookieValue not supported");
}
private Object resolvePathVariable(String pathVarName, MethodParameter methodParam,
NativeWebRequest webRequest, Object handlerForInitBinderCall) throws Exception {
Class<?> paramType = methodParam.getParameterType();
if (pathVarName.length() == 0) {
pathVarName = getRequiredParameterName(methodParam);
}
String pathVarValue = resolvePathVariable(pathVarName, paramType, webRequest);
WebDataBinder binder = createBinder(webRequest, null, pathVarName);
initBinder(handlerForInitBinderCall, pathVarName, binder, webRequest);
return binder.convertIfNecessary(pathVarValue, paramType, methodParam);
}
/**
* Resolves the given {@link PathVariable @PathVariable} annotation.
* <p>Throws an UnsupportedOperationException by default.
*/
protected String resolvePathVariable(String pathVarName, Class<?> paramType, NativeWebRequest webRequest)
throws Exception {
throw new UnsupportedOperationException("@PathVariable not supported");
}
private String getRequiredParameterName(MethodParameter methodParam) {
String name = methodParam.getParameterName();
if (name == null) {
throw new IllegalStateException(
"No parameter name specified for argument of type [" + methodParam.getParameterType().getName() +
"], and no parameter name information found in class file either.");
}
return name;
}
private Object checkValue(String name, Object value, Class<?> paramType) {
if (value == null) {
if (boolean.class == paramType) {
return Boolean.FALSE;
}
else if (paramType.isPrimitive()) {
throw new IllegalStateException("Optional " + paramType + " parameter '" + name +
"' is not present but cannot be translated into a null value due to being declared as a " +
"primitive type. Consider declaring it as object wrapper for the corresponding primitive type.");
}
}
return value;
}
private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam,
ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) throws Exception {
// Bind request parameter onto object...
String name = attrName;
if ("".equals(name)) {
name = Conventions.getVariableNameForParameter(methodParam);
}
Class<?> paramType = methodParam.getParameterType();
Object bindObject;
if (implicitModel.containsKey(name)) {
bindObject = implicitModel.get(name);
}
else if (this.methodResolver.isSessionAttribute(name, paramType)) {
bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);
if (bindObject == null) {
raiseSessionRequiredException("Session attribute '" + name + "' required - not found in session");
}
}
else {
bindObject = BeanUtils.instantiateClass(paramType);
}
WebDataBinder binder = createBinder(webRequest, bindObject, name);
initBinder(handler, name, binder, webRequest);
return binder;
}
/**
* Determine whether the given value qualifies as a "binding candidate", i.e. might potentially be subject to
* bean-style data binding later on.
*/
protected boolean isBindingCandidate(Object value) {
return (value != null && !value.getClass().isArray() && !(value instanceof Collection) &&
!(value instanceof Map) && !BeanUtils.isSimpleValueType(value.getClass()));
}
protected void raiseMissingParameterException(String paramName, Class<?> paramType) throws Exception {
throw new IllegalStateException("Missing parameter '" + paramName + "' of type [" + paramType.getName() + "]");
}
protected void raiseMissingHeaderException(String headerName, Class<?> paramType) throws Exception {
throw new IllegalStateException("Missing header '" + headerName + "' of type [" + paramType.getName() + "]");
}
protected void raiseMissingCookieException(String cookieName, Class<?> paramType) throws Exception {
throw new IllegalStateException(
"Missing cookie value '" + cookieName + "' of type [" + paramType.getName() + "]");
}
protected void raiseSessionRequiredException(String message) throws Exception {
throw new IllegalStateException(message);
}
protected WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName)
throws Exception {
return new WebRequestDataBinder(target, objectName);
}
private void doBind(WebDataBinder binder, NativeWebRequest webRequest, boolean validate,
Object[] validationHints, boolean failOnErrors) throws Exception {
doBind(binder, webRequest);
if (validate) {
binder.validate(validationHints);
}
if (failOnErrors && binder.getBindingResult().hasErrors()) {
throw new BindException(binder.getBindingResult());
}
}
protected void doBind(WebDataBinder binder, NativeWebRequest webRequest) throws Exception {
((WebRequestDataBinder) binder).bind(webRequest);
}
/**
* Return a {@link HttpInputMessage} for the given {@link NativeWebRequest}.
* <p>Throws an UnsupportedOperation1Exception by default.
*/
protected HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest) throws Exception {
throw new UnsupportedOperationException("@RequestBody not supported");
}
/**
* Return a {@link HttpOutputMessage} for the given {@link NativeWebRequest}.
* <p>Throws an UnsupportedOperationException by default.
*/
protected HttpOutputMessage createHttpOutputMessage(NativeWebRequest webRequest) throws Exception {
throw new UnsupportedOperationException("@Body not supported");
}
protected String parseDefaultValueAttribute(String value) {
return (ValueConstants.DEFAULT_NONE.equals(value) ? null : value);
}
protected Object resolveDefaultValue(String value) {
return value;
}
protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWebRequest webRequest)
throws Exception {
// Invoke custom argument resolvers if present...
if (this.customArgumentResolvers != null) {
for (WebArgumentResolver argumentResolver : this.customArgumentResolvers) {
Object value = argumentResolver.resolveArgument(methodParameter, webRequest);
if (value != WebArgumentResolver.UNRESOLVED) {
return value;
}
}
}
// Resolution of standard parameter types...
Class<?> paramType = methodParameter.getParameterType();
Object value = resolveStandardArgument(paramType, webRequest);
if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) {
throw new IllegalStateException("Standard argument type [" + paramType.getName() +
"] resolved to incompatible value of type [" + (value != null ? value.getClass() : null) +
"]. Consider declaring the argument type in a less specific fashion.");
}
return value;
}
protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest) throws Exception {
if (WebRequest.class.isAssignableFrom(parameterType)) {
return webRequest;
}
return WebArgumentResolver.UNRESOLVED;
}
protected final void addReturnValueAsModelAttribute(Method handlerMethod, Class<?> handlerType,
Object returnValue, ExtendedModelMap implicitModel) {
ModelAttribute attr = AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class);
String attrName = (attr != null ? attr.value() : "");
if ("".equals(attrName)) {
Class<?> resolvedType = GenericTypeResolver.resolveReturnType(handlerMethod, handlerType);
attrName = Conventions.getVariableNameForReturnType(handlerMethod, resolvedType, returnValue);
}
implicitModel.addAttribute(attrName, returnValue);
}
}

View File

@@ -1,172 +0,0 @@
/*
* Copyright 2002-2015 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
*
* http://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.bind.annotation.support;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
/**
* Support class for resolving web method annotations in a handler type.
* Processes {@code @RequestMapping}, {@code @InitBinder},
* {@code @ModelAttribute} and {@code @SessionAttributes}.
*
* <p>Used by {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter}
* and {@link org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter}.
*
* @author Juergen Hoeller
* @since 2.5.2
* @see org.springframework.web.bind.annotation.RequestMapping
* @see org.springframework.web.bind.annotation.InitBinder
* @see org.springframework.web.bind.annotation.ModelAttribute
* @see org.springframework.web.bind.annotation.SessionAttributes
* @deprecated as of 4.3, in favor of the {@code HandlerMethod}-based MVC infrastructure
*/
@Deprecated
public class HandlerMethodResolver {
private final Set<Method> handlerMethods = new LinkedHashSet<Method>();
private final Set<Method> initBinderMethods = new LinkedHashSet<Method>();
private final Set<Method> modelAttributeMethods = new LinkedHashSet<Method>();
private RequestMapping typeLevelMapping;
private boolean sessionAttributesFound;
private final Set<String> sessionAttributeNames = new HashSet<String>();
private final Set<Class<?>> sessionAttributeTypes = new HashSet<Class<?>>();
private final Set<String> actualSessionAttributeNames =
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(4));
/**
* Initialize a new HandlerMethodResolver for the specified handler type.
* @param handlerType the handler class to introspect
*/
public void init(final Class<?> handlerType) {
Set<Class<?>> handlerTypes = new LinkedHashSet<Class<?>>();
Class<?> specificHandlerType = null;
if (!Proxy.isProxyClass(handlerType)) {
handlerTypes.add(handlerType);
specificHandlerType = handlerType;
}
handlerTypes.addAll(Arrays.asList(handlerType.getInterfaces()));
for (Class<?> currentHandlerType : handlerTypes) {
final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType);
ReflectionUtils.doWithMethods(currentHandlerType, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) {
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
if (isHandlerMethod(specificMethod) &&
(bridgedMethod == specificMethod || !isHandlerMethod(bridgedMethod))) {
handlerMethods.add(specificMethod);
}
else if (isInitBinderMethod(specificMethod) &&
(bridgedMethod == specificMethod || !isInitBinderMethod(bridgedMethod))) {
initBinderMethods.add(specificMethod);
}
else if (isModelAttributeMethod(specificMethod) &&
(bridgedMethod == specificMethod || !isModelAttributeMethod(bridgedMethod))) {
modelAttributeMethods.add(specificMethod);
}
}
}, ReflectionUtils.USER_DECLARED_METHODS);
}
this.typeLevelMapping = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
SessionAttributes sessionAttributes = AnnotationUtils.findAnnotation(handlerType, SessionAttributes.class);
this.sessionAttributesFound = (sessionAttributes != null);
if (this.sessionAttributesFound) {
this.sessionAttributeNames.addAll(Arrays.asList(sessionAttributes.names()));
this.sessionAttributeTypes.addAll(Arrays.asList(sessionAttributes.types()));
}
}
protected boolean isHandlerMethod(Method method) {
return AnnotationUtils.findAnnotation(method, RequestMapping.class) != null;
}
protected boolean isInitBinderMethod(Method method) {
return AnnotationUtils.findAnnotation(method, InitBinder.class) != null;
}
protected boolean isModelAttributeMethod(Method method) {
return AnnotationUtils.findAnnotation(method, ModelAttribute.class) != null;
}
public final boolean hasHandlerMethods() {
return !this.handlerMethods.isEmpty();
}
public final Set<Method> getHandlerMethods() {
return this.handlerMethods;
}
public final Set<Method> getInitBinderMethods() {
return this.initBinderMethods;
}
public final Set<Method> getModelAttributeMethods() {
return this.modelAttributeMethods;
}
public boolean hasTypeLevelMapping() {
return (this.typeLevelMapping != null);
}
public RequestMapping getTypeLevelMapping() {
return this.typeLevelMapping;
}
public boolean hasSessionAttributes() {
return this.sessionAttributesFound;
}
public boolean isSessionAttribute(String attrName, Class<?> attrType) {
if (this.sessionAttributeNames.contains(attrName) || this.sessionAttributeTypes.contains(attrType)) {
this.actualSessionAttributeNames.add(attrName);
return true;
}
else {
return false;
}
}
public Set<String> getActualSessionAttributeNames() {
return this.actualSessionAttributeNames;
}
}

View File

@@ -1,4 +0,0 @@
/**
* Support classes for web annotation processing.
*/
package org.springframework.web.bind.annotation.support;

View File

@@ -40,7 +40,6 @@ import org.springframework.web.context.request.NativeWebRequest;
* @author Juergen Hoeller
* @since 2.5.2
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#setCustomArgumentResolvers
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter#setCustomArgumentResolvers
*/
public interface WebArgumentResolver {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -65,12 +65,6 @@ public interface WebApplicationContext extends ApplicationContext {
*/
String SCOPE_SESSION = "session";
/**
* Scope identifier for global session scope: "globalSession".
* Supported in addition to the standard scopes "singleton" and "prototype".
*/
String SCOPE_GLOBAL_SESSION = "globalSession";
/**
* Scope identifier for the global web application scope: "application".
* Supported in addition to the standard scopes "singleton" and "prototype".

View File

@@ -20,13 +20,11 @@ import java.lang.reflect.Method;
import java.util.Map;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.portlet.PortletSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.util.WebUtils;
@@ -52,9 +50,6 @@ import org.springframework.web.util.WebUtils;
*/
public class FacesRequestAttributes implements RequestAttributes {
private static final boolean portletApiPresent =
ClassUtils.isPresent("javax.portlet.PortletSession", FacesRequestAttributes.class.getClassLoader());
/**
* We'll create a lot of these objects, so we don't want a new logger every time.
*/
@@ -108,42 +103,22 @@ public class FacesRequestAttributes implements RequestAttributes {
@Override
public Object getAttribute(String name, int scope) {
if (scope == SCOPE_GLOBAL_SESSION && portletApiPresent) {
return PortletSessionAccessor.getAttribute(name, getExternalContext());
}
else {
return getAttributeMap(scope).get(name);
}
return getAttributeMap(scope).get(name);
}
@Override
public void setAttribute(String name, Object value, int scope) {
if (scope == SCOPE_GLOBAL_SESSION && portletApiPresent) {
PortletSessionAccessor.setAttribute(name, value, getExternalContext());
}
else {
getAttributeMap(scope).put(name, value);
}
getAttributeMap(scope).put(name, value);
}
@Override
public void removeAttribute(String name, int scope) {
if (scope == SCOPE_GLOBAL_SESSION && portletApiPresent) {
PortletSessionAccessor.removeAttribute(name, getExternalContext());
}
else {
getAttributeMap(scope).remove(name);
}
getAttributeMap(scope).remove(name);
}
@Override
public String[] getAttributeNames(int scope) {
if (scope == SCOPE_GLOBAL_SESSION && portletApiPresent) {
return PortletSessionAccessor.getAttributeNames(getExternalContext());
}
else {
return StringUtils.toStringArray(getAttributeMap(scope).keySet());
}
return StringUtils.toStringArray(getAttributeMap(scope).keySet());
}
@Override
@@ -237,58 +212,4 @@ public class FacesRequestAttributes implements RequestAttributes {
return mutex;
}
/**
* Inner class to avoid hard-coded Portlet API dependency.
*/
private static class PortletSessionAccessor {
public static Object getAttribute(String name, ExternalContext externalContext) {
Object session = externalContext.getSession(false);
if (session instanceof PortletSession) {
return ((PortletSession) session).getAttribute(name, PortletSession.APPLICATION_SCOPE);
}
else if (session != null) {
return externalContext.getSessionMap().get(name);
}
else {
return null;
}
}
public static void setAttribute(String name, Object value, ExternalContext externalContext) {
Object session = externalContext.getSession(true);
if (session instanceof PortletSession) {
((PortletSession) session).setAttribute(name, value, PortletSession.APPLICATION_SCOPE);
}
else {
externalContext.getSessionMap().put(name, value);
}
}
public static void removeAttribute(String name, ExternalContext externalContext) {
Object session = externalContext.getSession(false);
if (session instanceof PortletSession) {
((PortletSession) session).removeAttribute(name, PortletSession.APPLICATION_SCOPE);
}
else if (session != null) {
externalContext.getSessionMap().remove(name);
}
}
public static String[] getAttributeNames(ExternalContext externalContext) {
Object session = externalContext.getSession(false);
if (session instanceof PortletSession) {
return StringUtils.toStringArray(
((PortletSession) session).getAttributeNames(PortletSession.APPLICATION_SCOPE));
}
else if (session != null) {
return StringUtils.toStringArray(externalContext.getSessionMap().keySet());
}
else {
return new String[0];
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -155,11 +155,6 @@ public class FacesWebRequest extends FacesRequestAttributes implements NativeWeb
return false;
}
/**
* Last-modified handling not supported for portlet requests:
* As a consequence, this method always returns {@code false}.
* @since 4.2
*/
@Override
public boolean checkNotModified(String etag, long lastModifiedTimestamp) {
return false;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 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.
@@ -31,16 +31,12 @@ public interface NativeWebRequest extends WebRequest {
/**
* Return the underlying native request object, if available.
* @see javax.servlet.http.HttpServletRequest
* @see javax.portlet.ActionRequest
* @see javax.portlet.RenderRequest
*/
Object getNativeRequest();
/**
* Return the underlying native response object, if available.
* @see javax.servlet.http.HttpServletResponse
* @see javax.portlet.ActionResponse
* @see javax.portlet.RenderResponse
*/
Object getNativeResponse();
@@ -50,8 +46,6 @@ public interface NativeWebRequest extends WebRequest {
* @return the matching request object, or {@code null} if none
* of that type is available
* @see javax.servlet.http.HttpServletRequest
* @see javax.portlet.ActionRequest
* @see javax.portlet.RenderRequest
*/
<T> T getNativeRequest(Class<T> requiredType);
@@ -61,8 +55,6 @@ public interface NativeWebRequest extends WebRequest {
* @return the matching response object, or {@code null} if none
* of that type is available
* @see javax.servlet.http.HttpServletResponse
* @see javax.portlet.ActionResponse
* @see javax.portlet.RenderResponse
*/
<T> T getNativeResponse(Class<T> requiredType);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 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.
@@ -22,12 +22,11 @@ package org.springframework.web.context.request;
* attributes, with the optional notion of a "global session".
*
* <p>Can be implemented for any kind of request/session mechanism,
* in particular for servlet requests and portlet requests.
* in particular for servlet requests.
*
* @author Juergen Hoeller
* @since 2.0
* @see ServletRequestAttributes
* @see org.springframework.web.portlet.context.PortletRequestAttributes
*/
public interface RequestAttributes {
@@ -44,14 +43,6 @@ public interface RequestAttributes {
*/
int SCOPE_SESSION = 1;
/**
* Constant that indicates global session scope.
* <p>This explicitly refers to a globally shared session, if such
* a distinction is available (for example, in a Portlet environment).
* Else, it simply refers to the common session.
*/
int SCOPE_GLOBAL_SESSION = 2;
/**
* Name of the standard reference to the request object: "request".

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -31,9 +31,8 @@ import org.springframework.util.ClassUtils;
* <p>Use {@link RequestContextListener} or
* {@link org.springframework.web.filter.RequestContextFilter} to expose
* the current web request. Note that
* {@link org.springframework.web.servlet.DispatcherServlet} and
* {@link org.springframework.web.portlet.DispatcherPortlet} already
* expose the current request by default.
* {@link org.springframework.web.servlet.DispatcherServlet}
* already exposes the current request by default.
*
* @author Juergen Hoeller
* @author Rod Johnson
@@ -41,7 +40,6 @@ import org.springframework.util.ClassUtils;
* @see RequestContextListener
* @see org.springframework.web.filter.RequestContextFilter
* @see org.springframework.web.servlet.DispatcherServlet
* @see org.springframework.web.portlet.DispatcherPortlet
*/
public abstract class RequestContextHolder {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -25,11 +25,6 @@ package org.springframework.web.context.request;
* {@link org.springframework.web.filter.RequestContextFilter} or
* {@link org.springframework.web.servlet.DispatcherServlet}.
*
* <p>This {@code Scope} will also work for Portlet environments,
* through an alternate {@code RequestAttributes} implementation
* (as exposed out-of-the-box by Spring's
* {@link org.springframework.web.portlet.DispatcherPortlet}.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Rob Harrop
@@ -39,7 +34,6 @@ package org.springframework.web.context.request;
* @see RequestContextListener
* @see org.springframework.web.filter.RequestContextFilter
* @see org.springframework.web.servlet.DispatcherServlet
* @see org.springframework.web.portlet.DispatcherPortlet
*/
public class RequestScope extends AbstractRequestAttributesScope {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -27,58 +27,21 @@ import org.springframework.beans.factory.ObjectFactory;
* {@link org.springframework.web.filter.RequestContextFilter} or
* {@link org.springframework.web.servlet.DispatcherServlet}.
*
* <p>This {@code Scope} will also work for Portlet environments,
* through an alternate {@code RequestAttributes} implementation
* (as exposed out-of-the-box by Spring's
* {@link org.springframework.web.portlet.DispatcherPortlet}.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Rob Harrop
* @since 2.0
* @see RequestContextHolder#currentRequestAttributes()
* @see RequestAttributes#SCOPE_SESSION
* @see RequestAttributes#SCOPE_GLOBAL_SESSION
* @see RequestContextListener
* @see org.springframework.web.filter.RequestContextFilter
* @see org.springframework.web.servlet.DispatcherServlet
* @see org.springframework.web.portlet.DispatcherPortlet
*/
public class SessionScope extends AbstractRequestAttributesScope {
private final int scope;
/**
* Create a new SessionScope, storing attributes in a locally
* isolated session (or default session, if there is no distinction
* between a global session and a component-specific session).
*/
public SessionScope() {
this.scope = RequestAttributes.SCOPE_SESSION;
}
/**
* Create a new SessionScope, specifying whether to store attributes
* in the global session, provided that such a distinction is available.
* <p>This distinction is important for Portlet environments, where there
* are two notions of a session: "portlet scope" and "application scope".
* If this flag is on, objects will be put into the "application scope" session;
* else they will end up in the "portlet scope" session (the typical default).
* <p>In a Servlet environment, this flag is effectively ignored.
* @param globalSession {@code true} in case of the global session as target;
* {@code false} in case of a component-specific session as target
* @see org.springframework.web.portlet.context.PortletRequestAttributes
* @see ServletRequestAttributes
*/
public SessionScope(boolean globalSession) {
this.scope = (globalSession ? RequestAttributes.SCOPE_GLOBAL_SESSION : RequestAttributes.SCOPE_SESSION);
}
@Override
protected int getScope() {
return this.scope;
return RequestAttributes.SCOPE_SESSION;
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -52,11 +52,6 @@ import org.springframework.ui.ModelMap;
* @see org.springframework.web.servlet.DispatcherServlet
* @see org.springframework.web.servlet.handler.AbstractHandlerMapping#setInterceptors
* @see org.springframework.web.servlet.HandlerInterceptor
* @see org.springframework.web.portlet.context.PortletWebRequest
* @see org.springframework.web.portlet.DispatcherPortlet
* @see org.springframework.web.portlet.handler.AbstractHandlerMapping#setInterceptors
* @see org.springframework.web.portlet.handler.AbstractHandlerMapping#setApplyWebRequestInterceptorsToRenderPhaseOnly
* @see org.springframework.web.portlet.HandlerInterceptor
*/
public interface WebRequestInterceptor {

View File

@@ -177,8 +177,7 @@ public abstract class WebApplicationContextUtils {
*/
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory, ServletContext sc) {
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope(false));
beanFactory.registerScope(WebApplicationContext.SCOPE_GLOBAL_SESSION, new SessionScope(true));
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());
if (sc != null) {
ServletContextScope appScope = new ServletContextScope(sc);
beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 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.
@@ -23,10 +23,8 @@ import java.util.Map;
import org.springframework.util.MultiValueMap;
/**
* This interface defines the multipart request access operations
* that are exposed for actual multipart requests. It is extended
* by {@link MultipartHttpServletRequest} and the Portlet
* {@link org.springframework.web.portlet.multipart.MultipartActionRequest}.
* This interface defines the multipart request access operations that are exposed
* for actual multipart requests. It is extended by {@link MultipartHttpServletRequest}.
*
* @author Juergen Hoeller
* @author Arjen Poutsma

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -47,16 +47,10 @@ import org.springframework.web.util.WebUtils;
* as representation of uploaded files and a String-based parameter Map as
* representation of uploaded form fields.
*
* <p>Subclasses implement concrete resolution strategies for Servlet or Portlet
* environments: see CommonsMultipartResolver and CommonsPortletMultipartResolver,
* respectively. This base class is not tied to either of those APIs, factoring
* out common functionality.
*
* @author Juergen Hoeller
* @since 2.0
* @see CommonsMultipartFile
* @see CommonsMultipartResolver
* @see org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver
*/
public abstract class CommonsFileUploadSupport {

View File

@@ -55,7 +55,6 @@ import org.springframework.web.util.WebUtils;
* @since 29.09.2003
* @see #CommonsMultipartResolver(ServletContext)
* @see #setResolveLazily
* @see org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver
* @see org.apache.commons.fileupload.servlet.ServletFileUpload
* @see org.apache.commons.fileupload.disk.DiskFileItemFactory
*/