Explain Codes LogoExplain Codes Logo

How can I add a filter class in Spring Boot?

java
filter-registration
spring-boot
filter-chain
Alex KataevbyAlex Kataev·Nov 16, 2024
TLDR

To insert a filter in Spring Boot, rapidly put a filter class into action by creating a class that implements the Filter interface and tagging it with @Component. Here's a quick illustration:

import javax.servlet.*; import org.springframework.stereotype.Component; @Component public class SimpleFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // Our knight against incoming dragons... chain.doFilter(request, response); } }

This folds your custom filter smoothly into your application's request workflows, keeping away all the nasty dragons (request issues).

Delving into filter configurations

Play chess with your filter setup using FilterRegistrationBean

If you need to play chess with your filters, setting initialization parameters or ordering moves, use FilterRegistrationBean. This registration bean is the king to your chess game, of course defined within a @Configuration class.

@Configuration public class FilterConfig { @Bean public FilterRegistrationBean<SimpleFilter> filterRegistrationBean() { FilterRegistrationBean<SimpleFilter> registrationBean = new FilterRegistrationBean<>(); SimpleFilter simpleFilter = new SimpleFilter(); registrationBean.setFilter(simpleFilter); // Here's our King registrationBean.addUrlPatterns("/api/*"); // Modus operandi registrationBean.setOrder(1); // The opening move return registrationBean; } }

addUrlPatterns is the modus operandi, stating the endpoints to which the filter applies, where setOrder is your first opening move determining the filter's order of execution. Let the game begin!

The saga of @WebFilter and @Component

In your game of filters, you might also want to embrace @WebFilter, the native knight of Servlet 3.0 specification. To choose this warrior, ensure the inclusion of @ServletComponentScan in your headquarters (@SpringBootApplication-annotated class).

@WebFilter(urlPatterns = "/api/*") // He strikes at specific endpoints public class ApiFilter implements Filter { // Your valiant warrior... }

However, let the bugle sound and beware of duplicates! Avoid having the same warrior fight twice – once by @WebFilter and once by @Component. Duplication on the battlefield can have unexpected results.

Filters at your command using @Profile

There might be situations where you want certain warriors to strike only upon orders based on the mode of the battlefield, the Spring profiles. This is where @Profile plays the generals:

@Component @Profile("production") // Only on production battlefield, march forth! public class ProductionLoggingFilter implements Filter { // Your strategist for the production battlefield }

With the above setup, your strategist, the ProductionLoggingFilter, only marches to the production battlefield.

Tactics for robust filters with Spring Boot

Join the knights of the filter chain with doFilter

Knights only battle once, so if you have more than one, ensure that you allow the next knight's turn in line:

@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // Pre-fight code chain.doFilter(request, response); // Allows the next knight to spring into action // Celebratory code }

Auto-wiring for your filter knights

When creating filters using FilterRegistrationBean, oftentimes you require assistance from other entities in your castle. This is your backstage support team:

public class AutowiredFilter implements Filter { private final SomeDependency someDependency; // The stablemaster public AutowiredFilter(SomeDependency someDependency) { this.someDependency = someDependency; // Thanks for the steed! } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { // Get the steeds ready for battle! } } @Configuration public class FilterConfig { @Autowired private AutowireCapableBeanFactory beanFactory; // The blacksmith's foundry @Bean public FilterRegistrationBean<AutowiredFilter> autowiredFilterRegistration() { AutowiredFilter autowiredFilter = new AutowiredFilter(beanFactory.getBean(SomeDependency.class)); // The pouring of the sword beanFactory.autowireBean(autowiredFilter); // The sharpening of the sword FilterRegistrationBean<AutowiredFilter> registrationBean = new FilterRegistrationBean<>(autowiredFilter); // The newly-forged sword registrationBean.setOrder(1); // First knight // Other configurations return registrationBean; } }

All this backstage activity ensures a seamless and successful deployment of your knights.

Rules of engagement

Double the trouble

Be cautious when combining @Bean and @Component:

// This class should NOT be annotated with @Component, avoid double trouble. public class ApiSecurityFilter implements Filter { // Oh, double rainbow...I mean filter...is it? } @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<ApiSecurityFilter> apiSecurityFilter() { FilterRegistrationBean<ApiSecurityFilter> bean = new FilterRegistrationBean<>(); bean.setFilter(new ApiSecurityFilter()); bean.addUrlPatterns("/secure/*"); return bean;// Thankfully, only single rainbow here... } }

The mystery of URL patterns

To gain fine-grained command over the battlefield, use addUrlPatterns(). It's like giving orders, only to selected knights.

registrationBean.addUrlPatterns("/api/private/*", "/api/public/*"); // You, you, and you! Forward!

Just remember, your orders are only followed by the specific knights you have called upon.

The Chronicle of @Component vs. @WebFilter

When choosing knights, select wisely between @WebFilter and @Component. Opt for @WebFilter when you are assigning specific battles - it's like choosing a knight most suited for the skirmish.