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:
Rossen Stoyanchev
2011-09-26 09:27:09 +00:00
parent 6bc4ea058c
commit 48f7dcc464
7 changed files with 123 additions and 80 deletions

View File

@@ -108,9 +108,20 @@ public class ServletRequestDataBinder extends WebDataBinder {
if (multipartRequest != null) {
bindMultipart(multipartRequest.getMultiFileMap(), mpvs);
}
addBindValues(mpvs, request);
doBind(mpvs);
}
/**
* Extension point that subclasses can use to add extra bind values for a
* request. Invoked before {@link #doBind(MutablePropertyValues)}.
* The default implementation is empty.
* @param mpvs the property values that will be used for data binding
* @param request the current request
*/
protected void addBindValues(MutablePropertyValues mpvs, ServletRequest request) {
}
/**
* Treats errors as fatal.
* <p>Use this method only if it's an error if the input isn't valid.

View File

@@ -41,10 +41,12 @@ public class DefaultDataBinderFactory implements WebDataBinderFactory {
/**
* Create a new {@link WebDataBinder} for the given target object and
* initialize it through a {@link WebBindingInitializer}.
* @throws Exception in case of invalid state or arguments
*/
public final WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName) throws Exception {
public final WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName)
throws Exception {
WebDataBinder dataBinder = createBinderInstance(target, objectName, webRequest);
if (initializer != null) {
if (this.initializer != null) {
this.initializer.initBinder(dataBinder, webRequest);
}
initBinder(dataBinder, webRequest);
@@ -52,13 +54,15 @@ public class DefaultDataBinderFactory implements WebDataBinderFactory {
}
/**
* Extension point to create the WebDataBinder instance, which is
* {@link WebRequestDataBinder} by default.
* Extension point to create the WebDataBinder instance.
* By default this is {@code WebRequestDataBinder}.
* @param target the binding target or {@code null} for type conversion only
* @param objectName the binding target object name
* @param webRequest the current request
* @throws Exception in case of invalid state or arguments
*/
protected WebDataBinder createBinderInstance(Object target, String objectName, NativeWebRequest webRequest) {
protected WebDataBinder createBinderInstance(Object target, String objectName, NativeWebRequest webRequest)
throws Exception {
return new WebRequestDataBinder(target, objectName);
}

View File

@@ -58,12 +58,11 @@ public class InitBinderDataBinderFactory extends DefaultDataBinderFactory {
@Override
public void initBinder(WebDataBinder binder, NativeWebRequest request) throws Exception {
for (InvocableHandlerMethod binderMethod : this.binderMethods) {
if (!invokeInitBinderMethod(binderMethod, binder)) {
continue;
}
Object returnValue = binderMethod.invokeForRequest(request, null, binder);
if (returnValue != null) {
throw new IllegalStateException("@InitBinder methods should return void: " + binderMethod);
if (isBinderMethodApplicable(binderMethod, binder)) {
Object returnValue = binderMethod.invokeForRequest(request, null, binder);
if (returnValue != null) {
throw new IllegalStateException("@InitBinder methods should return void: " + binderMethod);
}
}
}
}
@@ -74,8 +73,8 @@ public class InitBinderDataBinderFactory extends DefaultDataBinderFactory {
* <p>The default implementation checks if target object name is included
* in the attribute names specified in the {@code @InitBinder} annotation.
*/
protected boolean invokeInitBinderMethod(HandlerMethod binderMethod, WebDataBinder binder) {
InitBinder annot = binderMethod.getMethodAnnotation(InitBinder.class);
protected boolean isBinderMethodApplicable(HandlerMethod initBinderMethod, WebDataBinder binder) {
InitBinder annot = initBinderMethod.getMethodAnnotation(InitBinder.class);
Collection<String> names = Arrays.asList(annot.value());
return (names.size() == 0 || names.contains(binder.getObjectName()));
}