In this post, we will explore how to add a filter in Spring Boot and what are the options to configure these filters in Spring Boot.
How to add a filter in 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.With the help of filter, we can perform the following operations.
- Perform some request processing before the request is handed over to the controller.
- Processing response before it reaches the client.
Here is a sample code outlining a simple Servlet filter
@Component
public class MyFilter implements Filter {
@Override
public void destroy() {}
@Override
public void doFilter
(ServletRequest request, ServletResponse response, FilterChain filterchain)
throws IOException, ServletException {
//place to perform request processing.
}
@Override
public void init(FilterConfig filterconfig) throws ServletException {}
}
Let’s look at the different options to add filter in Spring Boot application.
1. Define Spring Boot Filter and Invocation Order
Implement Filter
interface to create a new filter in Spring Boot.
@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() {
}
}
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 run first. This is useful when we want to execute our custom filters on 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. Apply Spring Boot Filter based on URL Pattern
Once you create a filter in Spring Boot and annotated with @Component
annotation,it will automatically identified by Spring Boot.In some cases you many want to apple the Spring Boot filter based on a certain URL pattern and not for every request.
To run the filter for URL pattern, we can use FilterRegistrationBean
. Don’t use @Component
annotation for the filter class but register the filter using a FilterRegistrationBean
.
public class CustomURLFilter implements Filter {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomURLFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
LOGGER.info("########## Initiating CustomURLFilter 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 /customer resource");
//call next filter in the filter chain
filterChain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
Register the custom Filter using FilterRegistrationBean
.
@Configuration
public class AppConfig {
@Bean
public FilterRegistrationBean < CustomURLFilter > filterRegistrationBean() {
FilterRegistrationBean < CustomURLFilter > registrationBean = new FilterRegistrationBean();
CustomURLFilter customURLFilter = new CustomURLFilter();
registrationBean.setFilter(customURLFilter);
registrationBean.addUrlPatterns("/greeting/*");
registrationBean.setOrder(2); //set precedence
return registrationBean;
}
}
3. OncePerRequestFilter
If we want, we can also extend the abstract class OncePerRequestFilter
to add a filter in Spring Boot.
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class MyFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
The OncePerRequestFilter
filter base class that aims to guarantee a single execution per request dispatch, on any servlet container.You also have the option to configure it based on the URL pattern.
This filter is helpful while dealing with Spring security where we want to ensure that few filters are only executing once.
4. Controller
Let’s now create a simple spring mvc controller and send an HTTP request to it:
@RestController
public class FilterExampleController {
@GetMapping
public String greeting() {
return "Hello World";
}
@GetMapping(value = "/greeting")
public String customGreetings() {
return "Hello From Custom Greetings";
}
}
When we start and run our application, following logs can be found in the console.
#################################################################### On Server startup ####################################################################
2018-07-04 17:22:32.221 INFO 40519 --- [ost-startStop-1] c.j.filters.CustomURLFilter : ########## Initiating CustomURLFilter filter ##########
2018-07-04 17:22:32.222 INFO 40519 --- [ost-startStop-1] com.javadevjournal.filters.CustomFilter : ########## Initiating Custom filter ##########
################################################################### On Hitting http://host:port/ ##############################################################
2018-07-04 17:22:56.710 INFO 40519 --- [nio-8080-exec-1] com.javadevjournal.filters.CustomFilter : Logging Request GET : /
2018-07-04 17:22:56.743 INFO 40519 --- [nio-8080-exec-1] com.javadevjournal.filters.CustomFilter : Logging Response :text/html;charset=UTF-8
################################################################### On Hitting http://host:port/greeting #######################################################
2018-07-04 17:24:42.325 INFO 40519 --- [nio-8080-exec-5] com.javadevjournal.filters.CustomFilter : Logging Request GET : /greeting
2018-07-04 17:24:42.325 INFO 40519 --- [nio-8080-exec-5] c.j.filters.CustomURLFilter : This Filter is only called when request is mapped for /customer resource
2018-07-04 17:24:42.327 INFO 40519 --- [nio-8080-exec-5] com.javadevjournal.filters.CustomFilter : Logging Response :text/html;charset=UTF-8
5. Servlet @WebFilter Annotation
If you like to use the Servlet 3.0 annotations, we have the option to use the @WebFilter
annotation for the filter in Spring Boot. This is how we can define a filter using @WebFilter
annotation
package com.javadevjournal.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/greeting")
public class GreetingFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filter for greeting project");
filterChain.doFilter(servletRequest,servletResponse);
}
}
If you are using this annotation, you need to use @ServletComponentScan
when the application needs to run in embedded container.
Summary
In this post, we explore how to add a filter in Spring Boot. We covered the different options for creating and registering the custom filter in our Spring Boot application. We can find code snippets GitHub
how do i get acces to the request body? It is not in the servletRequest
Is there any specific requirement for you? Keep in mind that once you read the stream, it will not be available for your controller until you treat it differently.
You might want to fix this
(HttpServletResponse) servletRequest;
in the first chapter. It will compile but fail at runtime.Thanks for the pointer!! It is fixed now