springspring-mvcspring-boottilestiles-3

Spring Boot - Why is MyFilter called many times in a single request when using Tiles+JSP?


Given this filter:

public class MyFilter implements Filter{

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("FILTERING!!!!!!!!!!!!!!!!!!!"+((HttpServletRequest)request).getRequestURI());
        chain.doFilter(request, response);
    }

I've seen that is is called many times in the same request

Spring Boot App:

@SpringBootApplication(scanBasePackageClasses={MySpringBootDemoApplication .class, TilesConfiguration.class})
public class MySpringBootDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(MySpringBootDemoApplication .class, args);
    }

    @Bean
    public Filter myFilter(){
        return new MyFilter();
    }
}

TilesConfiguration:

@Configuration
public class TilesConfiguration {

     @Bean
     public TilesConfigurer tilesConfigurer() {
         final TilesConfigurer configurer = new TilesConfigurer();
         configurer.setDefinitions(new String[] { "WEB-INF/**/tiles.xml" });
         configurer.setCheckRefresh(true);
         return configurer;
     }

     @Bean
     public TilesViewResolver tilesViewResolver() {
         final TilesViewResolver resolver = new TilesViewResolver();
         resolver.setViewClass(TilesView.class);
         return resolver;
     }

}

This is what I see in the logs:

FILTERING!!!!!!!!!!!!!!!!!!!/spring-boot-demo/home
FILTERING!!!!!!!!!!!!!!!!!!!/spring-boot-demo/WEB-INF/layouts/standard.jsp
FILTERING!!!!!!!!!!!!!!!!!!!/spring-boot-demo/WEB-INF/layouts/standard.jsp
FILTERING!!!!!!!!!!!!!!!!!!!/spring-boot-demo/WEB-INF/layouts/standard.jsp

The only real request made by the browser is:

FILTERING!!!!!!!!!!!!!!!!!!!/spring-boot-demo/home

Where do the tiles related (/standard.jsp) come from? In traditional Spring MVC applications they never showed up.

I know that MyFilter could extend OncePerRequestFilter but I can't modify the real filters I have to use, they come from legacy libraries.


Solution

  • I just realized that since MyFilter is mapped against /* it'll also be called on container forwards (hence Tile's standard.jsp...). I changed the DispatcherServlet to match /action/*, and so did with the filter:

    @Bean
    public FilterRegistrationBean myFilter(){
        FilterRegistrationBean frb = new FilterRegistrationBean();
        frb.setFilter(new MyFilter());
        frb.setUrlPatterns(Arrays.asList(new String[]{"/action/*"}));
        return frb;
    
    @Bean
    public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet) {
        ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet);
        registration.addUrlMappings("/action/*");
        return registration;
    }