Spring Boot allows to add multiple filters to an application so that you can do multiple filter operations in the request and response before sending it to the controller class. The multiple filters can be set to run in sequence or in parallel. The annotation @Order specifies the order in which the multiple filters are executed. When you use the url pattern to configure filters, you can execute multiple filters at once.
Filters in Spring Boot are created by either implementing Filter or extending HTTPFilter. The annotation @WebFilter is used to define a filter in the spring boot application. Add the annotation @ServletComponentScan to the spring boot main class, which will scan all servlet-related classes in the spring boot application context.
You can use the url pattern to limit request control based on the request url.If you add multiple filters in a sequence, they will all run one at a time. The order in which the configured filters are run is important. The annotation @Order specifies the order in which the multiple filters are executed.
The request url pattern is another way to configure multiple filters. The doFilter method in the filter will be run if the request url matches the request url pattern provided in the filter. Based on the request url pattern configured in the filters, the multiple filters might perform different filter operations.
Multiple filters run in sequence
The example below will show how to create multiple filters that run in sequence. There are two filters created and order of execution will be configured using @Order annotation. When the request url is invoked, the request is called the filters one after another before delivering to the controller class. The response will also returned back in the same order at which the multiple filters are called.
There are two filter classes that have been created. The @WebFilter annotation is provided to the filter classes. The filter class’s execution sequence is controlled by the annotation @Order. @Order(1) is used to configure the first filter class. @Order(2) is used to configure the second filter class.
MyFilter1.java
package com.yawintutor;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import org.springframework.core.annotation.Order;
@WebFilter
@Order(1)
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterchain)
throws IOException, ServletException {
System.out.println("START doFilter1");
filterchain.doFilter(request, response);
System.out.println("END doFilter1");
}
}
MyFilter2.java
package com.yawintutor;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import org.springframework.core.annotation.Order;
@WebFilter
@Order(2)
public class MyFilter2 implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterchain)
throws IOException, ServletException {
System.out.println("START doFilter2");
filterchain.doFilter(request, response);
System.out.println("END doFilter2");
}
}
TestController.java
package com.yawintutor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String testFilter() {
System.out.println("Executing testFilter Method");
return "TEST OK";
}
}
The annotation @ServletComponentScan is used to scan all of the spring boot application’s servlet-related classes. In the spring boot main class, add the annotation @ServletComponentScan.
SpringBootFilterApplication.java
package com.yawintutor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan
public class SpringBootFilterApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootFilterApplication.class, args);
}
}
Output
START doFilter1
START doFilter2
Executing testFilter Method
END doFilter2
END doFilter1
Multiple filters run in parallel
Based on the request url pattern, Spring Boot allows you to create multiple filters that execute in parallel. The request url pattern groups requests and allows certain filters to be run. If the request url fits the filter’s configured url pattern, the request will be performed before being sent to the controller class.
The filter will not be run if the request url pattern does not match the request url. If the request url matches two or more filters that use the url pattern, all of the filters for the request url will be called. The annotation @Order should be used to order the filters for the request url in this situation.
MyFilter1.java
package com.yawintutor;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
@WebFilter("/test")
public class MyFilter1 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterchain)
throws IOException, ServletException {
System.out.println("START doFilter1");
filterchain.doFilter(request, response);
System.out.println("END doFilter1");
}
}
MyFilter2.java
package com.yawintutor;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
@WebFilter("hello")
public class MyFilter2 implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterchain)
throws IOException, ServletException {
System.out.println("START doFilter2");
filterchain.doFilter(request, response);
System.out.println("END doFilter2");
}
}
TestController.java
package com.yawintutor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String testFilter() {
System.out.println("Executing testFilter Method");
return "TEST OK";
}
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String testHelloFilter() {
System.out.println("Executing testHelloFilter Method");
return "Hello OK";
}
}
SpringBootFilterApplication.java
package com.yawintutor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan
public class SpringBootFilterApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootFilterApplication.class, args);
}
}
Output1
The following output will be displayed when using the link http://localhost:8080/test.
START doFilter1
Executing testFilter Method
END doFilter1
Output2
The following output will be displayed when using the link http://localhost:8080/hello.
START doFilter2
Executing testHelloFilter Method
END doFilter2