![translation](https://cdn.durumis.com/common/trans.png)
This is an AI translated post.
[Spring] What are Filter, Interceptor, and Argument Resolver?
- Writing language: Korean
- •
-
Base country: All countries
- •
- Information Technology
Select Language
Summarized by durumis AI
- Filter is a J2EE standard specification feature that provides the ability to handle additional tasks for all requests that match a URL pattern before/after a request is delivered to the Dispatcher Servlet. It operates in the web container, while Interceptor is a technology provided by Spring that allows you to refer to or process requests and responses before and after the Dispatcher Servlet calls the controller, operating in the Spring context.
- Argument Resolver can indirectly create the desired object from the value that comes in with a request when a request enters a controller.
- Filter and Interceptor differ in whether they operate in the Spring container or web container, whether they handle requests based on the Dispatcher Servlet or the controller, and Argument Resolver operates after the Interceptor and returns a specific object.
What is a Filter?
Filters are a J2EE standard specification feature that allows you to perform additional tasks on all requests that match a url pattern before and after the request is forwarded to the Dispatcher Servlet. In other words, it is managed by the web container like Tomcat, not by the Spring container, so it processes the request before it goes to the Dispatcher Servlet.
Filter Implementation
To add a filter, you need to implement the Filter interface of javax.servlet, which has the following three methods.
- init method
- It is a method for initializing the filter object and adding it to the service. When the web container calls the init method once to initialize the filter object, subsequent requests are processed through the doFilter() method.
- doFilter method
- It is a method that is executed by the web container before all HTTP requests that match the url-pattern are forwarded to the Dispatcher Servlet, and before the Dispatcher Servlet sends an HTTP response to the client.
The doFilter() parameter contains FilterChain, which forwards the request to the next target through the FilterChain's doFilter(). By inserting the processing we need before/after chain.doFilter(), we can perform the desired processing.
- It is a method that is executed by the web container before all HTTP requests that match the url-pattern are forwarded to the Dispatcher Servlet, and before the Dispatcher Servlet sends an HTTP response to the client.
- destory method
- It is a method for removing the filter object from the service and returning the resources it uses. This is called once by the web container, after which it is no longer processed by doFilter().
Example Code - Servlet Specification
@WebFilter("/*")
public class dolphagoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
//Pre-processing here
request.setCharacterEncoding("UTF-8");
System.out.println("Before doFilter()....");
filterChain.doFilter(request, response);
//Post-processing here
System.out.println("After doFilter()....");
}
@Override
public void destroy() { }
Example Code - @Component
@Order(1)
@Component
public class CustomFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException { }
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
}
@Override
public void destroy() { }
- @Component: You can register the Filter as a Spring bean.
- @Order: You can set the order when there are multiple filters.
- If you register a filter that corresponds to the Servlet specification as a Spring bean like this, you can use other beans that correspond to the Spring specification.
Example Code - @Configuration
@Configuration
public class CustomRegistrationBean {
@Bean
public FilterRegistrationBean customFilterBean() {
FilterRegistrationBean registration = new FilterRegistrationBean<>();
registration.setFilter(new CustomFilter());
registration.setOrder(1);
registration.addUrlPatterns("/api/*");
return registration;
}
If you want the filter to only work on a specific URI, you can register the filter as a Spring bean using FilterRegistrationBean.
Filter Usage
It is mainly responsible for validating and processing the request parameters themselves.
- Common tasks related to security
- Because the filter operates in the web container, it can perform security checks (XSS, CSRF protection, etc.) to block invalid requests. Since the request cannot be forwarded to the Spring container and is blocked, security can be further enhanced.
- Logging for all requests
- Image/data compression and string encoding
- The filter implemented functions that are used globally in web applications, such as image or data compression and string encoding.
- ServletRequest customization
- HttpServletRequest can read the contents of the Body only once. Therefore, the Body cannot be read in the Filter or Interceptor. You can create a custom ServletRequest to log the Body.
Interceptor
What is an Interceptor?
Unlike filters, which are a J2EE standard specification, Interceptors are a technology provided by Spring that allows you to reference or process requests and responses before and after the Dispatcher Servlet calls the controller. In other words, unlike filters that operate in the web container, interceptors operate in the Spring context.
The Dispatcher Servlet requests a handler mapping to find the appropriate controller, which in turn returns an execution chain (HandlerExecutionChain). So, if there are one or more interceptors registered in this execution chain, the interceptors are executed sequentially before the controller is executed. If there are no interceptors, the controller is executed immediately.
Interceptor Implementation
To add an interceptor, you need to implement the org.springframework.web.servlet.HandlerInterceptor interface, which has the following three methods.
- preHandle method
- The preHandle method is executed before the controller is called. Therefore, it can be used for pre-processing tasks that need to be processed before the controller or for processing or adding request information.
- The handler parameter, the third parameter of the preHandle method, is an object that abstracts the information of the method with @RequestMapping attached to it.
- The return type of the preHandle method is boolean. If the return value is true, the process proceeds to the next step. However, if it is false, the operation is stopped and the subsequent operations (the next interceptor or the controller) are not performed.
- postHandle method
- The postHandle method is executed after the controller is called. Therefore, it can be used when there are post- processing tasks to be processed after the controller.
- afterCompletion method
- The afterCompletion method, as its name suggests, is executed after all operations are completed, including the task of generating the final result from all views.
Example Code
@Component
public class CustomInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CustomInterceptor());
registry.addInterceptor(new LoggingInterceptor());
}
- Register the created interceptor as a bean.
- Register the created interceptor in the addInterceptors() method of the WebMvcConfigurer interface.
- Interceptors work in the order in which they are registered in InterceptorRegistry.
Interceptor Usage
It is mainly responsible for processing request information integrity using service logic.
- Common tasks such as authentication and authorization
- For example, you can check authentication or authorization and other client request-related tasks before they are passed to the controller.
- Logging for API calls
- You can record the client's information through the received HttpServletRequest and HttpServletResponse objects.
- Data processing to be passed to Controller
- You can process the received HttpServletRequest and HttpServletResponse objects and pass them to the controller.
- AOP imitation
- You can find additional information such as the signature of the method to be executed using the HandlerMethod, the third parameter of the preHandle() method, to determine whether to execute the logic.
Filter vs Interceptor
- Filters are executed in the web context, while interceptors are executed in the Spring context, so the execution time is different.
- Filters can handle the before and after of the Dispatcher Servlet, while interceptors can handle the before and after of the controller.
- Filters are good for tasks that need to be processed globally, regardless of Spring, or for validating the input parameters themselves, or for using ServletRequest instead of HttpServletRequest.
- Interceptors are good to use when you need to handle client requests globally that are in the Spring unit, or when you need to mix service logic.
- Interceptors can handle exceptions using @ControllerAdvice and @ExceptionHandler, but filters cannot handle exceptions using them.
- Filters usually wrap the doFilter() method around a try~catch block to handle exceptions that occur at that point immediately.
Argument Resolver
What is an Argument Resolver?
Argument Resolver can indirectly help create the desired object from the values received in the request when a request enters the controller.
Argument Resolver Usage
For example, let's assume that a request comes in with a JWT token. We need to verify that this token is a valid token, and then extract the id stored in the token and create a login user object.
In this case, if we don't use Argument Resolver, we have to implement the process of verifying the token and converting it into a login user object in every controller. Then, duplicate code will be generated in the controllers that require user verification, and the responsibilities of the controller will increase. Argument Resolver can solve this problem.
Argument Resolver Implementation
ArgumentResolver can be used by implementing HandlerMethodArgumentResolver. And this interface specifies that you should implement the following two methods.
boolean supportsParameter(MethodParameter parameter);
@Nullable
- supportsParameter method
- Create a specific annotation and attach it to the front of the Parameter for which you want the ArgumentResolver to be executed. The supportsParameter() method checks if the requested method's argument has the desired annotation attached to it. If it contains the desired annotation, it returns true.
- resolveArgument method
- If you get true from supportsParameter, that is, if there is a method with a specific annotation attached to it, it is a method that binds the parameter in the desired form and returns information.
The implementation of the controller when using Argument Resolver like this is as follows.
@GetMapping("/me")
public ResponseEntity findMemberOfMine(@AuthenticationPrincipal LoginMember loginMember) {
MemberResponse memberResponse = memberService.findMember(loginMember.getId());
return ResponseEntity.ok().body(memberResponse);
Argument Resolver and Interceptor Differences
- ArgumentResolver operates after the interceptor and returns the desired object from the values received in the request when a request enters the controller.
- On the other hand, the interceptor intercepts the request before the actual controller is executed, and it cannot return a specific object. Only boolean or void return types exist.
Source
- https://mangkyu.tistory.com/173
- https://junhyunny.github.io/spring-boot/filter-interceptor-and-aop/
- https://supawer0728.github.io/2018/04/04/spring-filter-interceptor/
- https://tecoble.techcourse.co.kr/post/2021-05-24-spring-interceptor/
- https://baeldung-cn.com/spring-mvc-handlerinterceptor-vs-filter
- https://www.baeldung.com/spring-boot-add-filter
Expected Interview Questions and Answers
What is a filter?
A filter is a feature that allows you to perform additional tasks on all requests that match a url pattern before and after the request is forwarded to the Dispatcher Servlet. It operates at the Servlet container level.
When should I use a filter?
Filters can be used to handle tasks that need to be processed globally, regardless of Spring. They can also be used for validation, especially when it comes to request parameters themselves.
Common uses include handling common security tasks, logging all requests, image/data compression and string encoding, and customizing ServletRequest.
What is an interceptor?
An interceptor provides a feature that allows you to reference or process requests and responses before and after the Dispatcher Servlet calls the controller. It operates at the Spring container level.
When should I use an interceptor?
Interceptors can be used to handle tasks that need to be processed globally related to client requests, and they are commonly used when calling service logic for validation.
Common uses include handling common authentication/authorization tasks, logging API calls, and processing data to be passed to the Controller.
What is the difference between a filter and an interceptor?
Filters are executed at the Servlet container level, while interceptors are executed at the Spring container level.
Filters can handle the before and after of the Dispatcher Servlet, while interceptors can handle the before and after of the controller.
Therefore, it is better to use filters for tasks that need to be processed globally, regardless of Spring, while it is better to use interceptors for tasks that need to be processed globally related to client requests.
What is an Argument Resolver?
An Argument Resolver indirectly helps to create the desired object from the values received in the request when a request enters the controller.
When should I use an Argument Resolver?
It can be used when a request comes in with a JWT token, to verify that the token is valid, extract the id stored in the token, and create a LoginMember object.
What is the difference between an interceptor and an Argument Resolver?
An Argument Resolver returns the desired object from the values received in the request when a request enters the controller. On the other hand, an interceptor cannot return an object like this, and the Argument Resolver is executed after the interceptor is executed.