diff --git a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerAdapter.java b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerAdapter.java index e8fa23d6ac5..5ece3bbc877 100644 --- a/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerAdapter.java +++ b/org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerAdapter.java @@ -59,6 +59,7 @@ import org.springframework.beans.factory.config.BeanExpressionContext; import org.springframework.beans.factory.config.BeanExpressionResolver; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; +import org.springframework.core.Ordered; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.style.StylerUtils; @@ -117,7 +118,8 @@ import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver; * @see #setWebBindingInitializer * @see #setSessionAttributeStore */ -public class AnnotationMethodHandlerAdapter extends PortletContentGenerator implements HandlerAdapter, BeanFactoryAware { +public class AnnotationMethodHandlerAdapter extends PortletContentGenerator + implements HandlerAdapter, Ordered, BeanFactoryAware { private static final String IMPLICIT_MODEL_ATTRIBUTE = "org.springframework.web.portlet.mvc.ImplicitModel"; @@ -136,6 +138,8 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator impl private ModelAndViewResolver[] customModelAndViewResolvers; + private int order = Ordered.LOWEST_PRECEDENCE; + private ConfigurableBeanFactory beanFactory; private BeanExpressionContext expressionContext; @@ -242,6 +246,19 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator impl this.customModelAndViewResolvers = customModelAndViewResolvers; } + /** + * Specify the order value for this HandlerAdapter bean. + *
Default value is Default is "false".
- *
* @see org.springframework.web.util.UrlPathHelper#setAlwaysUseFullPath
*/
public void setAlwaysUseFullPath(boolean alwaysUseFullPath) {
@@ -191,10 +196,10 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
/**
- * Set if context path and request URI should be URL-decoded. Both are returned undecoded by the Servlet API, in
- * contrast to the servlet path. Uses either the request encoding or the default encoding according to the Servlet
- * spec (ISO-8859-1).
- *
+ * Set if context path and request URI should be URL-decoded. Both are returned
+ * undecoded by the Servlet API, in contrast to the servlet path.
+ * Uses either the request encoding or the default encoding according
+ * to the Servlet spec (ISO-8859-1).
* @see org.springframework.web.util.UrlPathHelper#setUrlDecode
*/
public void setUrlDecode(boolean urlDecode) {
@@ -202,8 +207,9 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
/**
- * Set the UrlPathHelper to use for resolution of lookup paths. Use this to override the default UrlPathHelper with
- * a custom subclass, or to share common UrlPathHelper settings across multiple HandlerMappings and HandlerAdapters.
+ * Set the UrlPathHelper to use for resolution of lookup paths.
+ * Use this to override the default UrlPathHelper with a custom subclass,
+ * or to share common UrlPathHelper settings across multiple HandlerMappings and HandlerAdapters.
*/
public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
Assert.notNull(urlPathHelper, "UrlPathHelper must not be null");
@@ -211,10 +217,8 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
/**
- * Set the PathMatcher implementation to use for matching URL paths against registered URL patterns. Default is
- * AntPathMatcher.
- *
- * @see org.springframework.util.AntPathMatcher
+ * Set the PathMatcher implementation to use for matching URL paths against registered URL patterns.
+ * Default is {@link org.springframework.util.AntPathMatcher}.
*/
public void setPathMatcher(PathMatcher pathMatcher) {
Assert.notNull(pathMatcher, "PathMatcher must not be null");
@@ -222,8 +226,9 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
/**
- * Set the MethodNameResolver to use for resolving default handler methods (carrying an empty
- * Will only kick in when the handler method cannot be resolved uniquely
+ * Set the MethodNameResolver to use for resolving default handler methods
+ * (carrying an empty Will only kick in when the handler method cannot be resolved uniquely
* through the annotation metadata already.
*/
public void setMethodNameResolver(MethodNameResolver methodNameResolver) {
@@ -231,15 +236,16 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
/**
- * Specify a WebBindingInitializer which will apply pre-configured configuration to every DataBinder that this
- * controller uses.
+ * Specify a WebBindingInitializer which will apply pre-configured
+ * configuration to every DataBinder that this controller uses.
*/
public void setWebBindingInitializer(WebBindingInitializer webBindingInitializer) {
this.webBindingInitializer = webBindingInitializer;
}
/**
- * Specify the strategy to store session attributes with. Default is {@link org.springframework.web.bind.support.DefaultSessionAttributeStore},
+ * Specify the strategy to store session attributes with.
+ * Default is {@link org.springframework.web.bind.support.DefaultSessionAttributeStore},
* storing session attributes in the HttpSession, using the same attribute name as in the model.
*/
public void setSessionAttributeStore(SessionAttributeStore sessionAttributeStore) {
@@ -248,11 +254,11 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
/**
- * Cache content produced by In contrast to the "cacheSeconds" property which will apply to all
- * general handlers (but not to In contrast to the "cacheSeconds" property which will apply to all general handlers
+ * (but not to More specifically, the execution of each handler method will get synchronized if this flag is "true". The
- * best available session mutex will be used for the synchronization; ideally, this will be a mutex exposed by
- * HttpSessionMutexListener. The session mutex is guaranteed to be the same object during the entire lifetime of the
- * session, available under the key defined by the In many cases, the HttpSession reference itself a
- * safe mutex as well, since it will always be the same object reference for the same active logical session. However,
- * this is not guaranteed across different servlet containers; the only 100% safe way is a session mutex.
- *
+ * Set if controller execution should be synchronized on the session,
+ * to serialize parallel invocations from the same client.
+ * More specifically, the execution of the The session mutex is guaranteed to be the same object during
+ * the entire lifetime of the session, available under the key defined
+ * by the In many cases, the HttpSession reference itself is a safe mutex
+ * as well, since it will always be the same object reference for the
+ * same active logical session. However, this is not guaranteed across
+ * different servlet containers; the only 100% safe way is a session mutex.
* @see org.springframework.web.util.HttpSessionMutexListener
* @see org.springframework.web.util.WebUtils#getSessionMutex(javax.servlet.http.HttpSession)
*/
@@ -278,61 +289,76 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
/**
- * Set the ParameterNameDiscoverer to use for resolving method parameter names if needed (e.g. for default attribute
- * names). Default is a {@link org.springframework.core.LocalVariableTableParameterNameDiscoverer}.
+ * Set the ParameterNameDiscoverer to use for resolving method parameter names if needed
+ * (e.g. for default attribute names).
+ * Default is a {@link org.springframework.core.LocalVariableTableParameterNameDiscoverer}.
*/
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
this.parameterNameDiscoverer = parameterNameDiscoverer;
}
/**
- * Set a custom WebArgumentResolvers to use for special method parameter types. Such a custom WebArgumentResolver will
- * kick in first, having a chance to resolve an argument value before the standard argument handling kicks in.
+ * Set a custom WebArgumentResolvers to use for special method parameter types.
+ * Such a custom WebArgumentResolver will kick in first, having a chance to resolve
+ * an argument value before the standard argument handling kicks in.
*/
public void setCustomArgumentResolver(WebArgumentResolver argumentResolver) {
- this.customArgumentResolvers = new WebArgumentResolver[]{argumentResolver};
+ this.customArgumentResolvers = new WebArgumentResolver[] {argumentResolver};
}
/**
- * Set one or more custom WebArgumentResolvers to use for special method parameter types. Any such custom
- * WebArgumentResolver will kick in first, having a chance to resolve an argument value before the standard argument
- * handling kicks in.
+ * Set one or more custom WebArgumentResolvers to use for special method parameter types.
+ * Any such custom WebArgumentResolver will kick in first, having a chance to resolve
+ * an argument value before the standard argument handling kicks in.
*/
public void setCustomArgumentResolvers(WebArgumentResolver[] argumentResolvers) {
this.customArgumentResolvers = argumentResolvers;
}
/**
- * Set a custom ModelAndViewResolvers to use for special method return types. Such a custom ModelAndViewResolver will
- * kick in first, having a chance to resolve an return value before the standard ModelAndView handling kicks in.
+ * Set a custom ModelAndViewResolvers to use for special method return types.
+ * Such a custom ModelAndViewResolver will kick in first, having a chance to resolve
+ * a return value before the standard ModelAndView handling kicks in.
*/
public void setCustomModelAndViewResolver(ModelAndViewResolver customModelAndViewResolver) {
- this.customModelAndViewResolvers = new ModelAndViewResolver[]{customModelAndViewResolver};
+ this.customModelAndViewResolvers = new ModelAndViewResolver[] {customModelAndViewResolver};
}
/**
- * Set one or more custom ModelAndViewResolvers to use for special method return types. Any such custom
- * ModelAndViewResolver will kick in first, having a chance to resolve an return value before the standard ModelAndView
- * handling kicks in.
+ * Set one or more custom ModelAndViewResolvers to use for special method return types.
+ * Any such custom ModelAndViewResolver will kick in first, having a chance to resolve
+ * a return value before the standard ModelAndView handling kicks in.
*/
public void setCustomModelAndViewResolvers(ModelAndViewResolver[] customModelAndViewResolvers) {
this.customModelAndViewResolvers = customModelAndViewResolvers;
}
/**
- * Returns the message body converters to use. These converters are used to convert from and to HTTP requests and
- * responses.
+ * Set the message body converters to use.
+ * These converters are used to convert from and to HTTP requests and responses.
+ */
+ public void setMessageConverters(HttpMessageConverter>[] messageConverters) {
+ this.messageConverters = messageConverters;
+ }
+
+ /**
+ * Return the message body converters that this adapter has been configured with.
*/
public HttpMessageConverter>[] getMessageConverters() {
return messageConverters;
}
/**
- * Set the message body converters to use. These converters are used to convert from and to HTTP requests and
- * responses.
+ * Specify the order value for this HandlerAdapter bean.
+ * Default value is Integer.MAX_VALUE, meaning that it's non-ordered.
+ * @see org.springframework.core.Ordered#getOrder()
+ */
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ public int getOrder() {
+ return this.order;
+ }
+
public void setBeanFactory(BeanFactory beanFactory) {
if (beanFactory instanceof ConfigurableBeanFactory) {
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
@@ -362,6 +379,9 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator impl
}
+ /**
+ * Portlet-specific subclass of {@link HandlerMethodResolver}.
+ */
private static class PortletHandlerMethodResolver extends HandlerMethodResolver {
private final Map@RequestMapping annotation). @RequestMapping annotation).
+ * @SessionAttributes annotated handlers for the given number of seconds.
- * Default is 0, preventing caching completely. @SessionAttributes annotated handlers), this setting will apply to
- * @SessionAttributes annotated handlers only.
- *
+ * Cache content produced by @SessionAttributes annotated handlers
+ * for the given number of seconds. Default is 0, preventing caching completely.
+ * @SessionAttributes annotated handlers), this setting will
+ * apply to @SessionAttributes annotated handlers only.
* @see #setCacheSeconds
* @see org.springframework.web.bind.annotation.SessionAttributes
*/
@@ -261,15 +267,20 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
/**
- * Set if controller execution should be synchronized on the session, to serialize parallel invocations from the same
- * client. SESSION_MUTEX_ATTRIBUTE constant. It serves as a safe
- * reference to synchronize on for locking on the current session. handleRequestInternal
+ * method will get synchronized if this flag is "true". The best available
+ * session mutex will be used for the synchronization; ideally, this will
+ * be a mutex exposed by HttpSessionMutexListener.
+ * SESSION_MUTEX_ATTRIBUTE constant. It serves as a
+ * safe reference to synchronize on for locking on the current session.
+ * Integer.MAX_VALUE, meaning that it's non-ordered.
+ * @see org.springframework.core.Ordered#getOrder()
*/
- public void setMessageConverters(HttpMessageConverter>[] messageConverters) {
- this.messageConverters = messageConverters;
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ public int getOrder() {
+ return this.order;
}
public void setBeanFactory(BeanFactory beanFactory) {
@@ -342,6 +368,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
}
+
public boolean supports(Object handler) {
return getMethodResolver(handler).hasHandlerMethods();
}
@@ -393,7 +420,9 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
return -1;
}
- /** Build a HandlerMethodResolver for the given handler type. */
+ /**
+ * Build a HandlerMethodResolver for the given handler type.
+ */
private ServletHandlerMethodResolver getMethodResolver(Object handler) {
Class handlerClass = ClassUtils.getUserClass(handler);
ServletHandlerMethodResolver resolver = this.methodResolverCache.get(handlerClass);
@@ -404,7 +433,10 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
return resolver;
}
- /** Servlet-specific subclass of {@link HandlerMethodResolver}. */
+
+ /**
+ * Servlet-specific subclass of {@link HandlerMethodResolver}.
+ */
private class ServletHandlerMethodResolver extends HandlerMethodResolver {
private ServletHandlerMethodResolver(Class> handlerType) {
@@ -606,14 +638,17 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
}
- /** Servlet-specific subclass of {@link HandlerMethodInvoker}. */
+
+ /**
+ * Servlet-specific subclass of {@link HandlerMethodInvoker}.
+ */
private class ServletHandlerMethodInvoker extends HandlerMethodInvoker {
private boolean responseArgumentUsed = false;
private ServletHandlerMethodInvoker(HandlerMethodResolver resolver) {
super(resolver, webBindingInitializer, sessionAttributeStore, parameterNameDiscoverer,
- customArgumentResolvers, getMessageConverters());
+ customArgumentResolvers, messageConverters);
}
@Override
@@ -679,7 +714,6 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
@Override
protected Object resolveStandardArgument(Class parameterType, NativeWebRequest webRequest) throws Exception {
-
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
HttpServletResponse response = (HttpServletResponse) webRequest.getNativeResponse();
@@ -717,11 +751,8 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
@SuppressWarnings("unchecked")
- public ModelAndView getModelAndView(Method handlerMethod,
- Class handlerType,
- Object returnValue,
- ExtendedModelMap implicitModel,
- ServletWebRequest webRequest) throws Exception {
+ public ModelAndView getModelAndView(Method handlerMethod, Class handlerType, Object returnValue,
+ ExtendedModelMap implicitModel, ServletWebRequest webRequest) throws Exception {
ResponseStatus responseStatusAnn = AnnotationUtils.findAnnotation(handlerMethod, ResponseStatus.class);
if (responseStatusAnn != null) {
@@ -792,6 +823,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
@SuppressWarnings("unchecked")
private void handleResponseBody(Object returnValue, ServletWebRequest webRequest)
throws ServletException, IOException {
+
HttpInputMessage inputMessage = new ServletServerHttpRequest(webRequest.getRequest());
List