Quy luật của tự nhiên!

Spring, framework đã được nhắc đến quá nhiều và sử dụng thành thạo bởi rất nhiều anh em ở đây rồi, nên mình muốn có nhứng bài viết đi sâu hơn vào kiến trúc của spring, những bài viết so sánh giữa cái này và cái kia để giúp chúng ta có cái nhìn sâu hơn và đa chiều hơn. Trong bài này mình muốn nói về vòng đời của 1 request trong Spring MVC. Như đã nói ở bài trước thì chúng ta chỉ quan tâm đến MC nên trong hình chúng ta hãy giảm bớt sự chú ý đến những thành phần liên quan đến view nhé

Các thành phần liên quan

Spring web MVC sống nhờ vào các WebServer như Tomcat hay Jetty nên nó cố gắng để tạo ra nhiều các thành phần có khả năng mở rộng và tùy biến để có thể phù hợp với mọi webserver và cũng là để tạo ra sự khác biệt (để cạnh tranh) với chính các webserver mà nó đang sử dụng, các thành phần quan trọng nhất của nó bao gồm:

  1. Filter: Đúng như cái tên của nó, nó sinh ra để cho chúng ta lọc các request gửi đến server, ở đây chúng ta có thể kiểm tra dữ liệu được gửi đến và quyết định cho nó đi tiếp hay là không, ở Filter mình hay sử dụng để cấu hình Cross-Origin Resource Sharing (CORS)
  2. DispatcherServlet: Là đối tượng cài đặt các hàm của HttpServlet (đối tượng chuẩn của JavaEE, các WebServer sẽ gọi đến lớp này tương ứng với các hàm get, post, put, options, head và delete), nó chịu trách nhiệm điều hướng request sẽ đi đến đâu (ví dụ 1 request lấy 1 file css thì sẽ đi vào lớp lấy file css, 1 request để lấy dữ liệu từ DB sẽ phải qua HandlerInterceptor)
  3. HandlerInterceptor: Đây là nơi tất cả các request sẽ chạy qua, chúng ta có thể in ra log ở đây, xác thực token của request ở đây trước khi để request đi vào controller
  4. CustomController: là các controller do chúng ta tự định nghĩa ra, trước khi request đến được Controller của chúng ta, nó đã trải qua 1 bước mapping dữ liệu từ byte[] hoặc string ra đối tượng Request cho chúng ta rồi. Về bản chất bên trong Spring sử dụng command design pattern để điều hướng các request đến với từng lớp Handler (lớp chúng ta không nhìn thấy), và Spring sử dụng bytebuddy để tạo ra các đối tượng wrap lại mỗi method của chúng ta ở controller (khó hiểu nhỉ, mình sẽ có bài nói về bytebuddy sau nhé)
  5. HandlerExceptionResolver: Là nơi tiếp nhận tất cả các Exception xảy ra trong quá trình chúng ta xử lý request, nếu chúng ta không tạo ra các lớp để xử lý exception, nó sẽ được xử lý mặc định bở Spring
  6. CustomExceptionResolver: Là các lớp mà chúng ta annotated với @ControllerAdvice, chúng ta sẽ xử lý các exception và trả về kết quả tương ứng ở đây, đây là một trong những ý tưởng rất hay của Spring, giúp chúng ta tập trung xử lý exception và common được source code

Tương đối mềm dẻo

Vòng đời của 1 request là khá dài, trải qua rất nhiều giai đoạn và các thành phần của spring, ưu điểm là cho phép chúng ta can thiệt sâu vào quá trình xử lý request, và ngăn chặn kịp thời các request xấu, nhưng nhược điểm là khiến chúng ta phải đọc nhiều document để hiểu được và performance có vẻ cũng sẽ bị ảnh hưởng phần nào.

Tham khảo

  1. Add 1 filter
  2. Spring request lifecycle