How to Add a Filter in Spring Boot

Spread the love

1. Overview

In this quick tutorial, we’ll explore how to define custom filters and specify their invocation order with the help of Spring Boot.

Filters as the name suggest used to perform filtering on either the request to a resource or on the response from a resource, or both. Spring Boot provides few options to register custom filters in the Spring Boot application. Let’s look at the different options.

2. Defining Filters and the Invocation Order

In order to create a filter, we need to simply implement the Filter interface:

@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomFilter implements Filter {

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        LOGGER.info("########## Initiating Custom filter ##########");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        LOGGER.info("Logging Request - #### --->  {} : {}", request.getMethod(), request.getRequestURI());

        //call next filter in the filter chain
        filterChain.doFilter(request, response);

        LOGGER.info("Logging Response - ##### -->   :{}", response.getContentType());

    }

    @Override
    public void destroy() {

        LOGGER.info("########## Destroying Custom filter ##########");
    }
}

Let’s quickly look at some important points in the above code

  • The filter registered by @Component annotation.
  • To fire filters in the right order–we needed to use the @Order annotation.

The highest order filter runs first. This is useful when we want to execute our custom filters on a pre-defined order.

@Component
@Order(1)
public class CustomFirstFilter implements Filter {

}

@Component
@Order(2)
public class CustomSecondFilter implements Filter {

}

In the above code, CustomFirstFilter will run before the CustomSecondFilter.

The lower the number, the higher the precedence

2.1. Filter with URL Pattern

In the example above, our filters are registered by default for all the URL’s in our application. However, we may sometimes want a filter to only apply to certain URL patterns.

In this case, we have to remove the @Component annotation from the filter class definition and register the filter using a FilterRegistrationBean:

public class MyCustomFilter implements Filter {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyCustomFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

        LOGGER.info("########## Initiating MyCustomFilter filter ##########");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        LOGGER.info("This Filter is only called when request is mapped for /filterExample resource");

        //call next filter in the filter chain
        filterChain.doFilter(request, response);
    }

    @Override
    public void destroy() {

        LOGGER.info("########## Destroying MyCustomFilter filter ##########");
    }
}

Register the custom Filter using FilterRegistrationBean.

@Configuration
public class ApplicationConfig {

    @Bean
    public FilterRegistrationBean<MyCustomFilter> filterRegistrationBean() {
        FilterRegistrationBean < MyCustomFilter > registrationBean = new FilterRegistrationBean();
        MyCustomFilter myCustomFilter = new MyCustomFilter();

        registrationBean.setFilter(myCustomFilter);
        registrationBean.addUrlPatterns("/filterExample/*");
        registrationBean.setOrder(2); //set precedence
        return registrationBean;
    }
}

Creating a Controller

Let’s now create a simple Spring MVC controller and send an HTTP request to it:

@Controller
public class FilterExampleController {

    @GetMapping(value = "/filterExample")
    public String customGreetings() {
        return "Hello From Custom Filter Example";
    }
}

Run Application

We can run our Spring Boot application in the following ways.
1. Using Maven Command: Download the project source code. Go to the root folder of the project using command prompt and run the command.

mvn spring-boot:run 

The Tomcat server will be started.

2. Using Eclipse: Download the project source code using the download link given at the end of the article. Import the project into eclipse. Using command prompt, go to the root folder of the project and run.

mvn clean eclipse:eclipse 

and then refresh the project in eclipse. Run Main class SpringBootMainClassApplication by clicking Run as -> Java Application. The Tomcat server will be started.

3. Using Executable JAR: Using command prompt, go to the root folder of the project and run the command.

mvn clean package 

We will get executable JAR Spring-Boot-Main-Class-0.0.1-SNAPSHOT.jar in the target folder. Run this JAR as

java -jar target/Spring-Boot-Main-Class-0.0.1-SNAPSHOT.jar 

The Tomcat server will be started.

Now we are ready to test the application. Run the following URL.

http://localhost:8081
2019-10-07 19:58:10.329  INFO 1896 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-10-07 19:58:10.333  INFO 1896 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2019-10-07 19:58:10.368  INFO 1896 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 35 ms
2019-10-07 19:58:10.388  INFO 1896 --- [nio-8081-exec-1] c.d.e.S.filter.CustomFilter              : Logging Request - #### --->  GET : /home
2019-10-07 19:58:10.481  INFO 1896 --- [nio-8081-exec-1] c.d.e.S.filter.CustomFilter              : Logging Response - ##### -->   :null
2019-10-07 19:58:21.092  INFO 1896 --- [nio-8081-exec-3] c.d.e.S.filter.CustomFilter              : Logging Request - #### --->  GET : /filterExample
2019-10-07 19:58:21.092  INFO 1896 --- [nio-8081-exec-3] c.d.e.S.filter.MyCustomFilter            : This Filter is only called when request is mapped for /filterExample resource
2019-10-07 19:58:21.116  INFO 1896 --- [nio-8081-exec-3] c.d.e.S.filter.CustomFilter              : Logging Response - ##### -->   :null

3. Conclusion

In this article, we’ve summarized how to define custom filters in a Spring Boot webapp.

As always, code snippets can be found over on GitHub.