如何将自定义版本的WebDataBinder注入Spring 3 MVC? [英] How do I inject a custom version of WebDataBinder into Spring 3 MVC?

查看:97
本文介绍了如何将自定义版本的WebDataBinder注入Spring 3 MVC?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了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.

您需要扩展您需要返回自定义的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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆