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.