How to add a Filter with WebMvcConfigurerAdapter i

2020-05-24 05:48发布

With WebApplicationInitializer, I can easily add a filter to the ServletContext within the onStartup() method.

How to add a filter with WebMvcConfigurerAdapter? Do I have to use XML?

ADD 1

To help others understand the Spring Web Configuration more easily, I draw the following illustration.

Now you just need to first understand the rational behind Spring Web configuration. And then pick up which config class to inherit and which method to override from below.

It's less painful to look it up than to remember so many things.

enter image description here

And a good article on Spring Web Initialization:

http://www.kubrynski.com/2014/01/understanding-spring-web-initialization.html

ADD 2

Based on Tunaki's reply, I checked the AbstractDispatcherServletInitializer. The filter registration happens in the following code:

enter image description here

Even I override the green getServletFilters() method, I still cannot access the Dyanmic result of the registerServletFilter(). So how can I configure the filter by addMappingForUrlPatterns()?

It seems I have to override the whole registerDispatcherServlet() method.

3条回答
霸刀☆藐视天下
2楼-- · 2020-05-24 06:04

WebMvcConfigurer is an interface that is used to customize the Java-based configuration for Spring MVC enabled via @EnableWebMvc. WebMvcConfigurerAdapter is just an adapter providing default empty methods for this interface.

It does not configure the DispatcherServlet, which is what filters are used by. As such, you can't use WebMvcConfigurer to configure servlet filters.

To easily configure filters, you can inherit from AbstractDispatcherServletInitializer and override getServletFilters():

public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {

    @Override
    protected Filter[] getServletFilters() {
        return new Filter[] { new CharacterEncodingFilter() };
    }

}

If you want to further configure a filter, you will have to override onStartup instead:

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
    super.onStartup(servletContext);
    servletContext.addFilter("name", CharacterEncodingFilter.class)
                  .addMappingForUrlPatterns(null, false, "/*");
}
查看更多
在下西门庆
3楼-- · 2020-05-24 06:10

You can access the Dyanmic result of the registerServletFilter() as follows in your app config (specifically, WebApplicationInitializer):

@Override
public void onStartup(ServletContext servletContext) throws ServletException {

    // Create the 'root' Spring application context
    AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();

    rootContext.register(
        AppConfig.class,
        SecurityConfiguration.class,
        HibernateConfiguration.class 
    );

    // Add cuatom filters to servletContext
    FilterRegistration.Dynamic filterRegistration = servletContext.addFilter("recaptchaResponseFilter", new RecaptchaResponseFilter());
    filterRegistration.setInitParameter("encoding", "UTF-8");
    filterRegistration.setInitParameter("forceEncoding", "true");
    filterRegistration.addMappingForUrlPatterns(null, true, "/*");

    // Create the dispatcher servlet's Spring application context
    AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
    dispatcherServlet.register(MVCConfig.class);

    // Register and map the dispatcher servlet
    ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet));
    dispatcher.setLoadOnStartup(1);
    dispatcher.addMapping("/");
查看更多
贼婆χ
4楼-- · 2020-05-24 06:16

You can create spring beans that implements Filter and @Inject ServletContext inside of them. Then in a @PostConstruct method, you can register them with servletContext.addServlet("myFilter",this);

public class MyFilter implements Filter {
    @Inject
    private ServletContext servletContext;

    @PostConstruct
    public void init(){
        ServletRegistration.Dynamic filter = servletContext.addServlet("myFilter",this);
        filter.addMapping("/myMapping");
    }
}

The bean must not be declared in the rootContext that is initialised with ContextLoaderListener(rootContext) because the servlet 3.0 api forbids using dynamic registration for the listeners. So it must be declared in the dispatcherContext that is given to DispatcherServlet(dispatcherContext )

public class MyWebAppInitializer implements WebApplicationInitializer {

   @Override
   public void onStartup(ServletContext container) {
     // Create the 'root' Spring application context
     AnnotationConfigWebApplicationContext rootContext =
       new AnnotationConfigWebApplicationContext();
     rootContext.register(AppConfig.class);

     // Manage the lifecycle of the root application context
     container.addListener(new ContextLoaderListener(rootContext));

     // Create the dispatcher servlet's Spring application context
     AnnotationConfigWebApplicationContext dispatcherContext =
       new AnnotationConfigWebApplicationContext();
     dispatcherContext.register(DispatcherConfig.class);

     // Register and map the dispatcher servlet
     ServletRegistration.Dynamic dispatcher =
       container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
     dispatcher.setLoadOnStartup(1);
     dispatcher.addMapping("/");
   }

}

spring doc

查看更多
登录 后发表回答