如何将自定义版本的WebDataBinder注入Spring 3 MVC?

我写了一个WebDataBinder的自定义实现。 在将来,我想对它进行增强,以便它在类本身上寻找注释,并确定它是否应该绑定数据。

如何将此类注入到Spring上下文中以代替WebDataBinder?

我想要的是,如果我运行此代码,我的WebDataBinder版本将被注入,而不是默认的Spring。

@Controller public class MyFormController { @InitBinder public void initBinder(WebDataBinder binder) { // ... } // ... } 

我自定义的WebDataBinder实现。 它允许我按类而不是方法名称排除数据绑定。

  package com.companyname.spring; import org.springframework.beans.MutablePropertyValues; import org.springframework.util.StringUtils; import org.springframework.web.bind.WebDataBinder; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class CustomDataBinder extends WebDataBinder { List disallowedClasses = new ArrayList(); public CustomDataBinder(Object target) { super(target); } public CustomDataBinder(Object target, String objectName) { super(target, objectName); } public CustomDataBinder disallowClass(Class... classes) { Collections.addAll(disallowedClasses, classes); return this; } @Override protected void doBind(MutablePropertyValues mpvs) { if(disallowedClasses.contains(getTarget().getClass())) { if (logger.isDebugEnabled()) { logger.debug("DataBinder will not bind class [" + getTarget().getClass().getSimpleName() + "] because it appears in the list of disallowed classes [" + StringUtils.collectionToCommaDelimitedString(disallowedClasses) + "]"); } } else { super.doBind(mpvs); } } } 

EDIT1

第一次通过,遇到AsyncSupportConfigurer问题

 @Configuration @ComponentScan(basePackageClasses = RootContextConfig.class) @EnableTransactionManagement @EnableWebSecurity @EnableAsync @EnableSpringConfigured @EnableLoadTimeWeaving public class RootContextConfig extends WebMvcConfigurationSupport { @Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { List argumentResolvers = new ArrayList(); addArgumentResolvers(argumentResolvers); List returnValueHandlers = new ArrayList(); addReturnValueHandlers(returnValueHandlers); RequestMappingHandlerAdapter adapter = new CustomRequestMappingHandlerAdapter(); adapter.setContentNegotiationManager(mvcContentNegotiationManager()); adapter.setMessageConverters(getMessageConverters()); adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer()); adapter.setCustomArgumentResolvers(argumentResolvers); adapter.setCustomReturnValueHandlers(returnValueHandlers); AsyncSupportConfigurer configurer = new AsyncSupportConfigurer(); configureAsyncSupport(configurer); //All the methods called off of configurer are giving me errors because they have protected level access. I'm not really sure how they're being called in the code I copied this from. if (configurer.getTaskExecutor() != null) { adapter.setTaskExecutor(configurer.getTaskExecutor()); } if (configurer.getTimeout() != null) { adapter.setAsyncRequestTimeout(configurer.getTimeout()); } adapter.setCallableInterceptors(configurer.getCallableInterceptors()); adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors()); return adapter; } 

自定义RequestMappingHandlerAdapter

 package com.companyname.dirtylibs.spring; import org.springframework.web.method.annotation.InitBinderDataBinderFactory; import org.springframework.web.method.support.InvocableHandlerMethod; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory; import java.util.List; public class CustomRequestMappingHandlerAdapter extends RequestMappingHandlerAdapter { @Override protected InitBinderDataBinderFactory createDataBinderFactory(List binderMethods) throws Exception { return new CustomInitBinderDataBinderFactory(binderMethods, getWebBindingInitializer()); } } 

自定义InitBinderDataBinderFactory

 package com.companyname.dirtylibs.spring; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.support.WebBindingInitializer; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.bind.support.WebRequestDataBinder; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.annotation.InitBinderDataBinderFactory; import org.springframework.web.method.support.InvocableHandlerMethod; import org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory; import java.util.List; public class CustomInitBinderDataBinderFactory extends InitBinderDataBinderFactory { /** * Create a new instance. * * @param binderMethods {@code @InitBinder} methods, or {@code null} * @param initializer for global data binder intialization */ public CustomInitBinderDataBinderFactory(List binderMethods, WebBindingInitializer initializer) { super(binderMethods, initializer); } @Override protected CustomDataBinder createBinderInstance(Object target, String objectName, NativeWebRequest webRequest) throws Exception { return new CustomDataBinder(target, objectName); } } 

这不是一项简单的任务。 Spring允许进行大量的自定义,但是,该死的,这种变化并不好玩。

您需要扩展RequestMappingHandlerAdapter类并重写以下方法

 /** * Template method to create a new InitBinderDataBinderFactory instance. * 

The default implementation creates a ServletRequestDataBinderFactory. * This can be overridden for custom ServletRequestDataBinder subclasses. * @param binderMethods {@code @InitBinder} methods * @return the InitBinderDataBinderFactory instance to use * @throws Exception in case of invalid state or arguments */ protected InitBinderDataBinderFactory createDataBinderFactory(List binderMethods) throws Exception { return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer()); }

您需要返回返回自定义WebDataBinder实例的自定义InitBinderDataBinderFactory ,而不是返回ServletRequestDataBinderFactory

此更改意味着您无法使用默认的@EnableWebMvc配置。 这是因为默认情况下它们使用RequestMappingHandlerAdapter ,但您需要注册自己的类。

但是,您可以覆盖@Bean注释的WebMvcConfigurationSupport#requestMappingHandlerAdapter()方法,并提供自己的实现来返回自己的类型。 查看该实现对提示的作用。