POLISH CREATION OF DATA BINDERS FOR @RequestMapping METHODS
Make it possible to hook in custom ServletRequestDataBinderFactory by overriding RequestMappingHandlerAdapter. Create ExtendedServletRequestDataBinder to add URI template vars to the binding values taking advantage of a new extension hook in ServletRequestDataBinder to provide additional values to bind.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.servlet.mvc.method.annotation;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.web.bind.ServletRequestDataBinder;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
/**
|
||||
* Subclass of {@link ServletRequestDataBinder} that adds URI template variables
|
||||
* to the values used for data binding.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.1
|
||||
*/
|
||||
public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
|
||||
|
||||
/**
|
||||
* Create a new instance, with default object name.
|
||||
* @param target the target object to bind onto (or <code>null</code>
|
||||
* if the binder is just used to convert a plain parameter value)
|
||||
* @see #DEFAULT_OBJECT_NAME
|
||||
*/
|
||||
public ExtendedServletRequestDataBinder(Object target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
* @param target the target object to bind onto (or <code>null</code>
|
||||
* if the binder is just used to convert a plain parameter value)
|
||||
* @param objectName the name of the target object
|
||||
* @see #DEFAULT_OBJECT_NAME
|
||||
*/
|
||||
public ExtendedServletRequestDataBinder(Object target, String objectName) {
|
||||
super(target, objectName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add URI template variables to the property values used for data binding.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void addBindValues(MutablePropertyValues mpvs, ServletRequest request) {
|
||||
String attr = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
|
||||
mpvs.addPropertyValues((Map<String, String>) request.getAttribute(attr));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -676,7 +676,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
||||
return modelFactory;
|
||||
}
|
||||
|
||||
private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) {
|
||||
private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
|
||||
Class<?> handlerType = handlerMethod.getBeanType();
|
||||
WebDataBinderFactory binderFactory = this.dataBinderFactoryCache.get(handlerType);
|
||||
if (binderFactory == null) {
|
||||
@@ -688,12 +688,25 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
|
||||
binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
|
||||
binderMethods.add(binderMethod);
|
||||
}
|
||||
binderFactory = new ServletRequestDataBinderFactory(binderMethods, this.webBindingInitializer);
|
||||
binderFactory = createDataBinderFactory(binderMethods);
|
||||
this.dataBinderFactoryCache.put(handlerType, binderFactory);
|
||||
}
|
||||
return binderFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method to create a new ServletRequestDataBinderFactory instance.
|
||||
* <p>The default implementation creates a ServletRequestDataBinderFactory.
|
||||
* This can be overridden for custom ServletRequestDataBinder subclasses.
|
||||
* @param binderMethods {@code @InitBinder} methods
|
||||
* @return the ServletRequestDataBinderFactory instance to use
|
||||
* @throws Exception in case of invalid state or arguments
|
||||
*/
|
||||
protected ServletRequestDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> binderMethods)
|
||||
throws Exception {
|
||||
return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer());
|
||||
}
|
||||
|
||||
/**
|
||||
* MethodFilter that matches {@link InitBinder @InitBinder} methods.
|
||||
*/
|
||||
|
||||
@@ -17,21 +17,15 @@
|
||||
package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.web.bind.ServletRequestDataBinder;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.support.WebBindingInitializer;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.method.annotation.InitBinderDataBinderFactory;
|
||||
import org.springframework.web.method.support.InvocableHandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
/**
|
||||
* Creates a WebDataBinder of type {@link ServletRequestDataBinder} that can
|
||||
* also use URI template variables values for data binding purposes.
|
||||
* Creates a {@code ServletRequestDataBinder}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.1
|
||||
@@ -43,45 +37,16 @@ public class ServletRequestDataBinderFactory extends InitBinderDataBinderFactory
|
||||
* @param binderMethods one or more {@code @InitBinder} methods
|
||||
* @param initializer provides global data binder initialization
|
||||
*/
|
||||
public ServletRequestDataBinderFactory(List<InvocableHandlerMethod> binderMethods,
|
||||
WebBindingInitializer initializer) {
|
||||
public ServletRequestDataBinderFactory(List<InvocableHandlerMethod> binderMethods, WebBindingInitializer initializer) {
|
||||
super(binderMethods, initializer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a WebDataBinder of type {@link ServletRequestDataBinder} that can
|
||||
* also use URI template variables values for data binding purposes.
|
||||
* Returns an instance of {@link ExtendedServletRequestDataBinder}.
|
||||
*/
|
||||
@Override
|
||||
protected WebDataBinder createBinderInstance(Object target, String objectName, final NativeWebRequest request) {
|
||||
return new ServletRequestDataBinder(target, objectName) {
|
||||
@Override
|
||||
protected void doBind(MutablePropertyValues mpvs) {
|
||||
mergeUriTemplateVariables(mpvs, request);
|
||||
super.doBind(mpvs);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge URI variable values into the given PropertyValues.
|
||||
* @param mpvs the PropertyValues to add to
|
||||
* @param request the current request
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected final void mergeUriTemplateVariables(MutablePropertyValues mpvs, NativeWebRequest request) {
|
||||
|
||||
Map<String, String> uriTemplateVars =
|
||||
(Map<String, String>) request.getAttribute(
|
||||
HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
|
||||
|
||||
if (uriTemplateVars != null){
|
||||
for (String variableName : uriTemplateVars.keySet()) {
|
||||
if (!mpvs.contains(variableName)) {
|
||||
mpvs.addPropertyValue(variableName, uriTemplateVars.get(variableName));
|
||||
}
|
||||
}
|
||||
}
|
||||
protected ServletRequestDataBinder createBinderInstance(Object target, String objectName, NativeWebRequest request) {
|
||||
return new ExtendedServletRequestDataBinder(target, objectName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user