问题描述
我编写了WebDataBinder的自定义实现.将来,我想对其进行增强,以便它在类本身上查找注释,并弄清楚是否应将数据绑定到它上.
I wrote a custom implementation of the WebDataBinder. In the future I'd like to enhance it so that it looks for an annotation on the class itself and figures out if it should be binding data to it or not.
如何将此类代替WebDataBinder注入到Spring上下文中?
How do I get this class injected into the Spring context in place of the WebDataBinder?
我想要的是,如果运行此代码,则将注入我的WebDataBinder版本,而不是默认的Spring版本.
What I want is that if I run this code, my version of the WebDataBinder gets injected instead of the default Spring one.
@Controller
public class MyFormController {
@InitBinder
public void initBinder(WebDataBinder binder) {
// ...
}
// ...
}
我对WebDataBinder的自定义实现.它使我可以按类而不是按方法名称来排除数据绑定.
My custom implementation of the WebDataBinder. It lets me exclude data binding by class instead of by method names.
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<Class> 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<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<HandlerMethodArgumentResolver>();
addArgumentResolvers(argumentResolvers);
List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList<HandlerMethodReturnValueHandler>();
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<InvocableHandlerMethod> 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<InvocableHandlerMethod> binderMethods, WebBindingInitializer initializer) {
super(binderMethods, initializer);
}
@Override
protected CustomDataBinder createBinderInstance(Object target, String objectName, NativeWebRequest webRequest) throws Exception {
return new CustomDataBinder(target, objectName);
}
}
推荐答案
这不是简单的任务. Spring允许进行很多自定义,但是,该死,这种更改并不有趣.
This is not a simple task. Spring allows for a lot of customization, but, damn, this change is not fun.
您需要扩展 RequestMappingHandlerAdapter
类,并覆盖以下方法
/**
* Template method to create a new InitBinderDataBinderFactory instance.
* <p>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<InvocableHandlerMethod> binderMethods)
throws Exception {
return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer());
}
您需要返回自定义的InitBinderDataBinderFactory
来返回自定义的WebDataBinder
实例,而不是返回ServletRequestDataBinderFactory
.
Instead of returning a ServletRequestDataBinderFactory
, you'll need to return a custom InitBinderDataBinderFactory
that returns your custom WebDataBinder
instances.
此更改意味着您不能使用默认的@EnableWebMvc
或<mvc:annotation-driven/>
配置.这是因为它们默认情况下使用RequestMappingHandlerAdapter
,但是您需要注册自己的类.
This change means you can't use the default @EnableWebMvc
or <mvc:annotation-driven/>
configuration. That's because they use RequestMappingHandlerAdapter
by default, but you need to register your own class.
但是,您可以覆盖@Bean
带注释的WebMvcConfigurationSupport#requestMappingHandlerAdapter()
方法,并提供自己的实现以返回自己的类型.查看该实现对提示的作用.
You can, however, override the @Bean
annotated WebMvcConfigurationSupport#requestMappingHandlerAdapter()
method and provide your own implementation to return your own type. Look into what that implementation does for hints.
这篇关于如何将自定义版本的WebDataBinder注入Spring 3 MVC?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!