@RequestParam and co support placeholders and expressions in their defaultValue attributes (SPR-5922); @Value expressions supported as MVC handler method arguments as well (against request scope)
This commit is contained in:
@@ -46,6 +46,11 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
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.ParameterNameDiscoverer;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
@@ -88,6 +93,7 @@ import org.springframework.web.bind.support.SessionAttributeStore;
|
||||
import org.springframework.web.bind.support.WebArgumentResolver;
|
||||
import org.springframework.web.bind.support.WebBindingInitializer;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.RequestScope;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
@@ -120,18 +126,16 @@ import org.springframework.web.util.WebUtils;
|
||||
* @see #setWebBindingInitializer
|
||||
* @see #setSessionAttributeStore
|
||||
*/
|
||||
public class AnnotationMethodHandlerAdapter extends WebContentGenerator implements HandlerAdapter {
|
||||
public class AnnotationMethodHandlerAdapter extends WebContentGenerator implements HandlerAdapter, BeanFactoryAware {
|
||||
|
||||
/**
|
||||
* Log category to use when no mapped handler is found for a request.
|
||||
*
|
||||
* @see #pageNotFoundLogger
|
||||
*/
|
||||
public static final String PAGE_NOT_FOUND_LOG_CATEGORY = "org.springframework.web.servlet.PageNotFound";
|
||||
|
||||
/**
|
||||
* Additional logger to use when no mapped handler is found for a request.
|
||||
*
|
||||
* @see #PAGE_NOT_FOUND_LOG_CATEGORY
|
||||
*/
|
||||
protected static final Log pageNotFoundLogger = LogFactory.getLog(PAGE_NOT_FOUND_LOG_CATEGORY);
|
||||
@@ -156,13 +160,17 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
|
||||
|
||||
private ModelAndViewResolver[] customModelAndViewResolvers;
|
||||
|
||||
private final Map<Class<?>, ServletHandlerMethodResolver> methodResolverCache =
|
||||
new ConcurrentHashMap<Class<?>, ServletHandlerMethodResolver>();
|
||||
|
||||
private HttpMessageConverter<?>[] messageConverters =
|
||||
new HttpMessageConverter[] {new ByteArrayHttpMessageConverter(), new StringHttpMessageConverter(),
|
||||
new FormHttpMessageConverter(), new SourceHttpMessageConverter()};
|
||||
|
||||
private ConfigurableBeanFactory beanFactory;
|
||||
|
||||
private BeanExpressionContext expressionContext;
|
||||
|
||||
private final Map<Class<?>, ServletHandlerMethodResolver> methodResolverCache =
|
||||
new ConcurrentHashMap<Class<?>, ServletHandlerMethodResolver>();
|
||||
|
||||
|
||||
public AnnotationMethodHandlerAdapter() {
|
||||
// no restriction of HTTP methods by default
|
||||
@@ -318,6 +326,13 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
|
||||
this.messageConverters = messageConverters;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (beanFactory instanceof ConfigurableBeanFactory) {
|
||||
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
|
||||
this.expressionContext = new BeanExpressionContext(this.beanFactory, new RequestScope());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean supports(Object handler) {
|
||||
return getMethodResolver(handler).hasHandlerMethods();
|
||||
@@ -595,6 +610,19 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
|
||||
throw new HttpSessionRequiredException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object resolveDefaultValue(String value) {
|
||||
if (beanFactory == null) {
|
||||
return value;
|
||||
}
|
||||
String placeholdersResolved = beanFactory.resolveEmbeddedValue(value);
|
||||
BeanExpressionResolver exprResolver = beanFactory.getBeanExpressionResolver();
|
||||
if (exprResolver == null) {
|
||||
return value;
|
||||
}
|
||||
return exprResolver.evaluate(placeholdersResolved, expressionContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest) throws Exception {
|
||||
HttpServletRequest servletRequest = (HttpServletRequest) webRequest.getNativeRequest();
|
||||
|
||||
@@ -51,11 +51,12 @@ import org.junit.Test;
|
||||
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
|
||||
import org.springframework.aop.interceptor.SimpleTraceInterceptor;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.DerivedTestBean;
|
||||
import org.springframework.beans.ITestBean;
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
||||
import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||
@@ -186,7 +187,7 @@ public class ServletAnnotationControllerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultParamMissing() throws Exception {
|
||||
public void defaultParameters() throws Exception {
|
||||
initServlet(DefaultValueParamController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath.do");
|
||||
@@ -195,6 +196,23 @@ public class ServletAnnotationControllerTests {
|
||||
assertEquals("foo-bar", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultExpressionParameters() throws Exception {
|
||||
initServlet(DefaultExpressionValueParamController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myPath.do");
|
||||
request.setContextPath("/myApp");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
System.setProperty("myHeader", "bar");
|
||||
try {
|
||||
servlet.service(request, response);
|
||||
}
|
||||
finally {
|
||||
System.clearProperty("myHeader");
|
||||
}
|
||||
assertEquals("foo-bar-/myApp", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodNotAllowed() throws Exception {
|
||||
initServlet(MethodNotAllowedController.class);
|
||||
@@ -281,13 +299,15 @@ public class ServletAnnotationControllerTests {
|
||||
doTestAdaptedHandleMethods(MyAdaptedController3.class);
|
||||
}
|
||||
|
||||
private void initServlet(final Class<?> controllerclass) throws ServletException {
|
||||
private void initServlet(final Class<?> controllerClass) throws ServletException {
|
||||
servlet = new DispatcherServlet() {
|
||||
@Override
|
||||
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)
|
||||
throws BeansException {
|
||||
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
|
||||
GenericWebApplicationContext wac = new GenericWebApplicationContext();
|
||||
wac.registerBeanDefinition("controller", new RootBeanDefinition(controllerclass));
|
||||
wac.registerBeanDefinition("controller", new RootBeanDefinition(controllerClass));
|
||||
RootBeanDefinition ppc = new RootBeanDefinition(PropertyPlaceholderConfigurer.class);
|
||||
ppc.getPropertyValues().addPropertyValue("properties", "myKey=foo");
|
||||
wac.registerBeanDefinition("ppc", ppc);
|
||||
wac.refresh();
|
||||
return wac;
|
||||
}
|
||||
@@ -1615,6 +1635,18 @@ public class ServletAnnotationControllerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
public static class DefaultExpressionValueParamController {
|
||||
|
||||
@RequestMapping("/myPath.do")
|
||||
public void myHandle(@RequestParam(value = "id", defaultValue = "${myKey}") String id,
|
||||
@RequestHeader(defaultValue = "#{systemProperties.myHeader}") String header,
|
||||
@Value("#{request.contextPath}") String contextPath, HttpServletResponse response)
|
||||
throws IOException {
|
||||
response.getWriter().write(String.valueOf(id) + "-" + String.valueOf(header) + "-" + contextPath);
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
public static class MethodNotAllowedController {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user