![translation](https://cdn.durumis.com/common/trans.png)
Đây là bài viết được dịch bởi AI.
Chọn ngôn ngữ
Văn bản được tóm tắt bởi AI durumis
- Filter là một chức năng tiêu chuẩn J2EE cung cấp khả năng xử lý các tác vụ bổ sung cho tất cả các yêu cầu phù hợp với mẫu URL trước và sau khi yêu cầu được chuyển đến Dispatcher Servlet. Filter hoạt động trong container web, trong khi Interceptor là một công nghệ do Spring cung cấp, cho phép bạn tham chiếu hoặc xử lý yêu cầu và phản hồi trước và sau khi Dispatcher Servlet gọi controller. Interceptor hoạt động trong ngữ cảnh Spring.
- Argument Resolver có thể gián tiếp tạo ra các đối tượng mong muốn từ các giá trị đi kèm với yêu cầu khi một yêu cầu nào đó được gửi đến controller.
- Filter và Interceptor khác nhau về việc hoạt động trong container Spring hay container web, xử lý yêu cầu dựa trên Dispatcher Servlet hay controller. Argument Resolver hoạt động sau Interceptor và trả về một đối tượng cụ thể.
Bộ lọc (Filter) là gì?
Bộ lọc là một tính năng tiêu chuẩn của J2EE cho phép bạn xử lý các tác vụ bổ sung cho tất cả các yêu cầu phù hợp với mẫu URL trước hoặc sau khi yêu cầu được chuyển đến Dispatcher Servlet. Nói cách khác, bộ lọc được quản lý bởi bộ chứa web như Tomcat thay vì bộ chứa Spring, do đó nó xử lý yêu cầu trước khi chuyển đến Dispatcher Servlet.
Triển khai bộ lọc (Filter)
Để thêm bộ lọc, bạn cần triển khai giao diện Filter của javax.servlet. Giao diện này có ba phương thức sau:
- Phương thức init
- Đây là phương thức để khởi tạo đối tượng bộ lọc và thêm nó vào dịch vụ. Bộ chứa web sẽ gọi phương thức init một lần để khởi tạo đối tượng bộ lọc, sau đó tất cả các yêu cầu sau này sẽ được xử lý thông qua phương thức doFilter().
- Phương thức doFilter
- Đây là phương thức được gọi bởi bộ chứa web trước khi tất cả các yêu cầu HTTP phù hợp với mẫu URL được chuyển đến Dispatcher Servlet và trước khi Dispatcher Servlet gửi phản hồi HTTP đến máy khách.
Phương thức doFilter() có tham số FilterChain, bạn có thể chuyển yêu cầu đến đối tượng tiếp theo bằng cách sử dụng phương thức doFilter() của FilterChain. Bằng cách đặt các xử lý cần thiết trước và sau chain.doFilter(), bạn có thể tiến hành các xử lý mong muốn.
- Đây là phương thức được gọi bởi bộ chứa web trước khi tất cả các yêu cầu HTTP phù hợp với mẫu URL được chuyển đến Dispatcher Servlet và trước khi Dispatcher Servlet gửi phản hồi HTTP đến máy khách.
- Phương thức destory
- Đây là phương thức để xóa đối tượng bộ lọc khỏi dịch vụ và trả lại các tài nguyên được sử dụng. Phương thức này được gọi bởi bộ chứa web một lần và sau đó sẽ không được xử lý nữa bởi doFilter().
Mã ví dụ - Thông số kỹ thuật Servlet
@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 {
//Xử lý trước
request.setCharacterEncoding("UTF-8");
System.out.println("Trước doFilter()...");
filterChain.doFilter(request, response);
//Xử lý sau
System.out.println("Sau doFilter()...");
}
@Override
public void destroy() { }
Mã ví dụ - @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: Bạn có thể đăng ký Filter làm bean của Spring.
- @Order: Bạn có thể xác định thứ tự nếu có nhiều bộ lọc.
- Khi đăng ký bộ lọc tương ứng với thông số kỹ thuật Servlet làm bean của Spring, bạn có thể sử dụng các bean khác tương ứng với thông số kỹ thuật Spring.
Mã ví dụ - @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;
}
Nếu bạn muốn bộ lọc chỉ hoạt động với một số URI cụ thể, bạn có thể đăng ký bộ lọc làm bean của Spring bằng cách sử dụng FilterRegistrationBean.
Công dụng của bộ lọc (Filter)
Bộ lọc thường chịu trách nhiệm xác thực và xử lý các tham số yêu cầu.
- Công việc chung liên quan đến bảo mật
- Bộ lọc hoạt động trong bộ chứa web, do đó bạn có thể thực hiện kiểm tra bảo mật (chống XSS, chống CSRF v.v.) và chặn các yêu cầu không hợp lệ. Điều này có thể tăng cường bảo mật vì yêu cầu sẽ không được chuyển đến bộ chứa Spring.
- Đăng nhập tất cả các yêu cầu
- Nén hình ảnh/dữ liệu và mã hóa chuỗi
- Bộ lọc đã triển khai các chức năng được sử dụng rộng rãi trong ứng dụng web, chẳng hạn như nén hình ảnh hoặc dữ liệu và mã hóa chuỗi.
- Tùy chỉnh ServletRequest
- HttpServletRequest chỉ có thể đọc nội dung của Body một lần. Do đó, Filter hoặc Interceptor không thể đọc Body. Bạn có thể tạo ServletRequest tùy chỉnh để ghi nhật ký Body.
Interceptor (Bộ chặn)
Interceptor (Bộ chặn) là gì?
Interceptor (Bộ chặn) không giống như Filter (Bộ lọc) là một thông số kỹ thuật J2EE tiêu chuẩn, mà là một công nghệ do Spring cung cấp, cho phép bạn tham chiếu hoặc xử lý yêu cầu và phản hồi trước và sau khi Dispatcher Servlet gọi Controller. Nói cách khác, Interceptor hoạt động trong bối cảnh Spring thay vì hoạt động trong bộ chứa web như Filter.
Dispatcher Servlet yêu cầu ánh xạ trình xử lý để tìm Controller phù hợp và trả về chuỗi thực thi (HandlerExecutionChain). Do đó, chuỗi này sẽ bao gồm một hoặc nhiều Interceptor đã được đăng ký và chúng sẽ được gọi theo thứ tự trước khi Controller được thực thi. Nếu không có Interceptor nào, Controller sẽ được thực thi trực tiếp.
Triển khai Interceptor (Bộ chặn)
Để thêm Interceptor, bạn cần triển khai giao diện org.springframework.web.servlet.HandlerInterceptor. Giao diện này có ba phương thức sau:
- Phương thức preHandle
- Phương thức preHandle được gọi trước khi Controller được gọi. Do đó, nó có thể được sử dụng để xử lý các tác vụ trước khi Controller được gọi hoặc để xử lý và thêm thông tin yêu cầu.
- Tham số handler ở phương thức preHandle là một đối tượng trừu tượng hóa thông tin của phương thức được kết nối với @RequestMapping.
- Loại trả về của phương thức preHandle là boolean. Nếu trả về true, xử lý sẽ tiếp tục đến bước tiếp theo, nếu trả về false, xử lý sẽ bị dừng và các xử lý sau đó (Interceptor tiếp theo hoặc Controller) sẽ không được thực thi.
- Phương thức postHandle
- Phương thức postHandle được gọi sau khi Controller được gọi. Do đó, nó có thể được sử dụng khi có các tác vụ xử lý sau Controller.
- Phương thức afterCompletion
- Phương thức afterCompletion được gọi sau khi tất cả các tác vụ được hoàn thành, bao gồm cả việc tạo kết quả cuối cùng từ tất cả các View.
Mã ví dụ
@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());
}
- Đăng ký Interceptor đã tạo làm bean.
- Đăng ký Interceptor đã tạo trong phương thức addInterceptors() của giao diện WebMvcConfigurer.
- Interceptor sẽ hoạt động theo thứ tự mà chúng được đăng ký trong InterceptorRegistry.
Công dụng của Interceptor (Bộ chặn)
Interceptor thường chịu trách nhiệm xử lý tính nhất quán của thông tin yêu cầu bằng cách sử dụng logic dịch vụ.
- Công việc chung như xác thực/ủy quyền
- Bạn có thể kiểm tra các tác vụ liên quan đến yêu cầu của máy khách, chẳng hạn như xác thực hoặc ủy quyền, trước khi chuyển đến Controller.
- Đăng nhập các cuộc gọi API
- Bạn có thể ghi lại thông tin máy khách thông qua các đối tượng HttpServletRequest và HttpServletResponse được truyền vào.
- Xử lý dữ liệu được chuyển đến Controller
- Bạn có thể xử lý các đối tượng HttpServletRequest và HttpServletResponse được truyền vào và chuyển chúng đến Controller.
- Bắt chước AOP
- Bạn có thể xác định chữ ký của phương thức được thực thi và các thông tin bổ sung khác thông qua HandlerMethod, tham số thứ ba của phương thức preHandle(), để xác định xem có nên thực thi logic hay không.
Filter (Bộ lọc) so với Interceptor (Bộ chặn)
- Filter được thực thi trong bối cảnh web, trong khi Interceptor được thực thi trong bối cảnh Spring, do đó thời điểm thực thi khác nhau.
- Filter có thể xử lý trước và sau Dispatcher Servlet, trong khi Interceptor có thể xử lý trước và sau Controller.
- Filter nên được sử dụng khi cần xử lý toàn cục không liên quan đến Spring, xác thực các tham số đầu vào hoặc khi sử dụng ServletRequest thay vì HttpServletRequest.
- Interceptor nên được sử dụng khi cần xử lý toàn cục liên quan đến yêu cầu của máy khách trong phạm vi Spring hoặc khi cần kết hợp logic dịch vụ.
- Interceptor có thể xử lý ngoại lệ bằng cách sử dụng @ControllerAdvice và @ExceptionHandler, nhưng Filter không thể xử lý ngoại lệ bằng cách sử dụng chúng.
- Filter thường xử lý ngoại lệ xảy ra tại thời điểm đó bằng cách bọc phương thức doFilter() trong khối try~catch.
Argument Resolver
Argument Resolver là gì?
Argument Resolver có thể tạo ra một đối tượng mong muốn từ giá trị được truyền vào trong yêu cầu khi yêu cầu được chuyển đến Controller.
Công dụng của Argument Resolver
Giả sử một yêu cầu được gửi đến với token JWT. Chúng ta cần xác thực xem token đó có hợp lệ hay không và sau đó lấy id được lưu trữ trong token và tạo ra một đối tượng người dùng đăng nhập.
Trong trường hợp này, nếu không sử dụng Argument Resolver, chúng ta sẽ phải triển khai quá trình xác thực token và chuyển đổi nó thành đối tượng người dùng đăng nhập trong mỗi Controller. Điều này sẽ dẫn đến mã trùng lặp trong các Controller cần xác thực người dùng và trách nhiệm của Controller sẽ tăng lên. Argument Resolver có thể giải quyết vấn đề này.
Triển khai Argument Resolver
ArgumentResolver có thể được sử dụng bằng cách triển khai HandlerMethodArgumentResolver. Giao diện này chỉ định hai phương thức sau cần được triển khai.
boolean supportsParameter(MethodParameter parameter);
@Nullable
- Phương thức supportsParameter
- Tạo một chú thích cụ thể và gắn nó vào trước Parameter mà bạn muốn ArgumentResolver thực thi. Phương thức supportsParameter() sẽ kiểm tra xem Parameter của phương thức được gọi có được gắn chú thích mong muốn hay không và trả về true nếu nó chứa chú thích mong muốn.
- Phương thức resolveArgument
- Nếu nhận được true từ supportsParameter, nghĩa là, nếu có một phương thức nào đó có chú thích cụ thể, thì đây là phương thức sẽ ràng buộc thông tin thành dạng mong muốn của parameter và trả về nó.
Triển khai của Controller khi sử dụng Argument Resolver như sau:
@GetMapping("/me")
public ResponseEntity findMemberOfMine(@AuthenticationPrincipal LoginMember loginMember) {
MemberResponse memberResponse = memberService.findMember(loginMember.getId());
return ResponseEntity.ok().body(memberResponse);
Sự khác biệt giữa Argument Resolver và Interceptor (Bộ chặn)
- Argument Resolver hoạt động sau Interceptor và trả về một đối tượng mong muốn từ giá trị được truyền vào trong yêu cầu khi một yêu cầu được chuyển đến Controller.
- Mặt khác, Interceptor chặn yêu cầu trước khi Controller thực sự được thực thi và không thể trả về bất kỳ đối tượng nào. Nó chỉ có loại trả về boolean hoặc void.
Nguồn
- 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
Câu hỏi phỏng vấn dự kiến và câu trả lời
Bộ lọc là gì?
Bộ lọc là một tính năng cho phép bạn xử lý các tác vụ bổ sung cho tất cả các yêu cầu phù hợp với mẫu URL trước hoặc sau khi yêu cầu được chuyển đến Dispatcher Servlet. Nó hoạt động trong bộ chứa Servlet.
Khi nào nên sử dụng bộ lọc?
Bộ lọc có thể được sử dụng để xử lý các tác vụ toàn cục không liên quan đến Spring. Hoặc nó được sử dụng khi xác thực các tham số yêu cầu.
Các tác vụ tiêu biểu được xử lý bởi bộ lọc bao gồm các tác vụ chung liên quan đến bảo mật, đăng nhập tất cả các yêu cầu, nén hình ảnh/dữ liệu và mã hóa chuỗi, tùy chỉnh ServletRequest.
Interceptor (Bộ chặn) là gì?
Interceptor là một tính năng cho phép bạn tham chiếu hoặc xử lý yêu cầu và phản hồi trước và sau khi Dispatcher Servlet gọi Controller. Nó hoạt động trong bộ chứa Spring.
Khi nào nên sử dụng Interceptor?
Interceptor có thể được sử dụng để xử lý các tác vụ toàn cục liên quan đến yêu cầu của máy khách. Hoặc nó được sử dụng khi cần gọi logic dịch vụ trong quá trình xác thực.
Các tác vụ tiêu biểu được xử lý bởi Interceptor bao gồm các tác vụ chung như xác thực/ủy quyền, đăng nhập các cuộc gọi API, xử lý dữ liệu được chuyển đến Controller.
Sự khác biệt giữa bộ lọc và Interceptor là gì?
Bộ lọc được thực thi trong bộ chứa Servlet, trong khi Interceptor được thực thi trong bộ chứa Spring.
Bộ lọc có thể xử lý trước và sau Dispatcher Servlet, trong khi Interceptor có thể xử lý trước và sau Controller.
Do đó, bộ lọc nên được sử dụng khi cần xử lý toàn cục không liên quan đến Spring, trong khi Interceptor nên được sử dụng khi cần xử lý toàn cục liên quan đến yêu cầu của máy khách trong phạm vi Spring.
Argument Resolver là gì?
Argument Resolver có thể tạo ra một đối tượng mong muốn từ giá trị được truyền vào trong yêu cầu khi yêu cầu được chuyển đến Controller.
Khi nào nên sử dụng Argument Resolver?
Bạn có thể sử dụng nó khi một yêu cầu được gửi đến với token JWT, xác thực xem token đó có hợp lệ hay không và sau đó lấy id được lưu trữ trong token và tạo ra một đối tượng LoginMember.
Sự khác biệt giữa Interceptor và Argument Resolver là gì?
Argument Resolver trả về một đối tượng mong muốn từ giá trị được truyền vào trong yêu cầu khi một yêu cầu được chuyển đến Controller. Mặt khác, Interceptor không thể trả về bất kỳ đối tượng nào và được thực thi trước Argument Resolver.