JSP: Lọc yêu cầu và phản hồi trong Servlet
Giải phóng thời gian, khai phóng năng lực
Một bộ lọc là một đối tượng mà có thể chuyển đổi các tiêu đề và nội dung (hoặc cả hai) của một yêu cầu hoặc phản ứng. Bộ lọc khác với các thành phần web trong bộ lọc đó thường không tự tạo ra phản hồi. Thay vào đó, một bộ lọc cung cấp chức năng có thể được "gắn" vào bất kỳ loại tài nguyên web. Do đó, một bộ lọc không nên có bất kỳ phụ thuộc vào một tài nguyên web mà nó đang hoạt động như một bộ lọc; Theo cách này nó có thể được cấu tạo với nhiều loại tài nguyên web.
Các tác vụ chính mà bộ lọc có thể thực hiện như sau:
- Truy vấn yêu cầu và hành động phù hợp.
- Chặn cặp yêu cầu và đáp ứng từ xa hơn.
- Chỉnh sửa tiêu đề yêu cầu và dữ liệu. Bạn thực hiện việc này bằng cách cung cấp một phiên bản tùy chỉnh yêu cầu.
- Sửa đổi tiêu đề và dữ liệu. Bạn thực hiện việc này bằng cách cung cấp phiên bản trả lời tùy chỉnh.
- Tương tác với các nguồn lực bên ngoài.
Các ứng dụng của bộ lọc bao gồm xác thực, ghi nhật ký, chuyển đổi hình ảnh, nén dữ liệu, mã hóa, các luồng tokenizing, chuyển đổi XML, v.v.
Bạn có thể định cấu hình một tài nguyên web để được lọc bởi một chuỗi gồm các bộ lọc zero, một hoặc nhiều hơn theo thứ tự cụ thể. Chuỗi này được chỉ định khi ứng dụng web có chứa thành phần được triển khai và được khởi tạo khi một kho chứa web tải thành phần.
Tóm lại, các nhiệm vụ liên quan đến sử dụng bộ lọc là
- Lập trình bộ lọc
- Lập trình yêu cầu và phản hồi tùy chỉnh
- Chỉ định chuỗi lọc cho mỗi tài nguyên web
Bộ lọc lập trình
API lọc được xác định bởi các giao diện Filter , FilterChain , và FilterConfig trong gói javax.servlet . Bạn xác định một bộ lọc bằng cách thực hiện giao diện Bộ lọc .
Phương pháp quan trọng nhất trong giao diện này là doFilter , được truyền qua yêu cầu, đáp ứng, và các đối tượng chuỗi lọc. Phương pháp này có thể thực hiện các hành động sau:
- Kiểm tra tiêu đề yêu cầu.
- Tùy chỉnh đối tượng yêu cầu nếu bộ lọc mong muốn sửa đổi tiêu đề yêu cầu hoặc dữ liệu.
- Tùy chỉnh đối tượng phản hồi nếu bộ lọc muốn thay đổi tiêu đề hoặc dữ liệu.
- Gọi cho thực thể tiếp theo trong chuỗi lọc. Nếu bộ lọc hiện tại là bộ lọc cuối cùng trong chuỗi kết thúc với thành phần web đích hoặc tài nguyên tĩnh, thực thể tiếp theo là tài nguyên ở cuối chuỗi; Nếu không, nó là bộ lọc kế tiếp được cấu hình trong WAR. Bộ lọc sẽ gọi đối tượng tiếp theo bằng cách gọi phương thức doFiltertrên đối tượng chuỗi (chuyển qua yêu cầu và đáp ứng được gọi bằng hoặc các phiên bản gói có thể đã được tạo ra). Ngoài ra, nó có thể chọn để chặn yêu cầu bằng cách không thực hiện cuộc gọi để gọi các thực thể tiếp theo. Trong trường hợp thứ hai, bộ lọc có trách nhiệm điền câu trả lời.
- Kiểm tra tiêu đề phản ứng sau khi nó đã triệu gọi bộ lọc tiếp theo trong chuỗi.
- Vứt một ngoại lệ để chỉ ra lỗi trong quá trình xử lý.
Ngoài bộ lọc doFilter , bạn phải thực hiện phương pháp init và hủy . Các init phương pháp được gọi bằng container khi bộ lọc được khởi tạo. Nếu bạn muốn truyền các tham số khởi tạo cho bộ lọc, bạn sẽ lấy chúng từ đối tượng FilterConfig đã truyền cho init.
Ứng dụng sách của Duke sử dụng các bộ lọc HitCounterFilter và OrderFilter, được đặt tại Tut-install/javaeetutorial5/example/web/bookstore1/src/java/com/sun/bookstore1/filters/, để tăng và đăng nhập giá trị của quầy khi nhập và tiếp nhận servlet được truy cập.
Trong phương thức doFilter, cả hai bộ lọc lấy bối cảnh servlet từ đối tượng cấu hình bộ lọc để họ có thể truy cập vào các quầy lưu trữ dưới dạng các thuộc tính ngữ cảnh. Sau khi các bộ lọc đã hoàn thành quá trình xử lý cụ thể ứng dụng, chúng sẽ gọi hàm doFilter trên đối tượng chuỗi bộ lọc truyền vào phương thức doFilter gốc . Mã elided được thảo luận trong phần tiếp theo.
public finally class HitCounterFilter thực hiện Bộ lọc { private filter FilterConfigConfig = null; Public void init (FilterConfig filterConfig) Ném ServletException { This.filterConfig = filterConfig; } Public void destroy () { This.filterConfig = null; } Public void doFilter (yêu cầu ServletRequest, Đáp ứng ServletResponse, String FilterChain) Ném IOException, ServletException { If (filterConfig == null) trở về; StringWriter sw = new StringWriter (); PrintWriter writer = mới PrintWriter (sw); Counter counter = (Số lượt truy cập) filterConfig. GetServletContext (). GetAttribute ("hitCounter"); Writer.println (); Writer.println ("==============="); Writer.println ("Số lần truy cập là:" + Counter.incCounter ()); Writer.println ("==============="); / / Đăng nhập chuỗi kết quả Writer.flush (); System.out.println (sw.getBuffer () toString ()); ... Chain.doFilter (yêu cầu, wrapper); ... } }
Lập trình Các yêu cầu và phản hồi tùy chỉnh
Có nhiều cách để bộ lọc sửa đổi yêu cầu hoặc phản hồi. Ví dụ: bộ lọc có thể thêm thuộc tính vào yêu cầu hoặc có thể chèn dữ liệu vào câu trả lời. Trong ví dụ của Hiệu sách của Công tước, HitCounterFilter chèn giá trị của bộ đếm vào câu trả lời.
Một bộ lọc sửa đổi một phản hồi thường phải bắt đáp ứng trước khi nó được trả lại cho khách hàng. Để thực hiện việc này, bạn chuyển một luồng đăng nhập vào servlet tạo ra câu trả lời. Luồng đăng nhập ngăn không cho servlet đóng luồng phản hồi ban đầu khi hoàn tất và cho phép bộ lọc sửa đổi phản hồi của servlet.
Để vượt qua luồng đăng nhập này vào servlet, bộ lọc tạo ra một lớp phủ phản hồi để ghi đè phương thức getWriter hoặc getOutputStream để trả lại luồng đăng nhập. Bao bọc được truyền vào phương pháp doFilter của chuỗi lọc. Các phương pháp Wrapper mặc định gọi qua yêu cầu gói hoặc đối tượng trả lời. Phương pháp tiếp cận này dựa theo mô hình Wrapper hoặc Decorator nổi tiếng được mô tả trong các mẫu thiết kế, các phần tử của phần mềm hướng đối tượng có thể tái sử dụngđược Erich Gamma et al. (Addison-Wesley, 1995). Các phần sau mô tả cách bộ lọc truy cập đã mô tả trước đây và các loại bộ lọc khác sử dụng trình bao bọc.
Để ghi đè các phương thức yêu cầu, bạn sẽ gói yêu cầu này trong một đối tượng mở rộng ServletRequestWrapper hoặc HttpServletRequestWrapper . Để ghi đè các phương pháp phản hồi, bạn hãy gói câu trả lời trong một đối tượng mở rộng ServletResponseWrapper hoặc HttpServletResponseWrapper .
HitCounterFilter kết thúc tốt đẹp câu trả lời tại Tut-install/javaeetutorial5/example/web/bookstore1/src/java/com/sun/bookstore1/filter/ CharResponseWrapper . Câu trả lời bọc được truyền cho đối tượng tiếp theo trong chuỗi lọc, đó là BookStoreServlet . Sau đó, BookStoreServlet viết phản ứng của nó vào luồng do CharResponseWrapper tạo . Khi chain.doFilter trả, HitCounterFilter lấy phản ứng của servlet từ PrintWriter và viết nó vào một bộ đệm. Bộ lọc chèn giá trị của bộ đếm vào bộ đệm, đặt lại tiêu đề chiều dài nội dung của phản hồi, và sau đó ghi nội dung của bộ đệm vào luồng phản ứng.
InWriter ra = response.getWriter (); CharResponseWrapper wrapper = new CharResponseWrapper ( (HttpServletResponse) phản hồi); Chain.doFilter (yêu cầu, wrapper); CharArrayWriter caw = new CharArrayWriter (); Caw.write (wrapper.toString () chuỗi con (0, Wrapper.toString (). IndexOf ("</ body>") - 1)); Caw.write ("<p> \ n <center>" + Messages.getString ("Visitor") + "<font color = 'red'>" + Counter.getCounter () + "</ font> </ center>"); Caw.write ("\ n </ body> </ html>"); Response.setContentLength (caw.toString (). GetBytes (). Chiều dài); Out.write (caw.toString ()); Out.close (); Public class CharResponseWrapper mở rộng HttpServletResponseWrapper { Sản lượng CharArrayWriter riêng; Chuỗi công khai toString () { Return output.toString (); } Công khai CharResponseWrapper (phản hồi HttpServletResponse) { Siêu (phản ứng); Đầu ra = new CharArrayWriter (); } Công cộng printWriter getWriter () { Quay trở lại PrintWriter mới (đầu ra); } }
Hình dưới đây cho thấy trang nhập cho Hiệu sách của Duke với bộ đếm lượt truy cập.
Nhà sách của Duke với Hit Counter
Chỉ định ánh xạ bộ lọc
Vùng chứa web sử dụng ánh xạ bộ lọc để quyết định cách áp dụng bộ lọc cho tài nguyên web. Lập bản đồ bộ lọc phù hợp với một bộ lọc cho một thành phần web theo tên, hoặc các tài nguyên web theo mẫu URL. Các bộ lọc được gọi theo thứ tự trong đó ánh xạ bộ lọc xuất hiện trong danh sách ánh xạ bộ lọc của một WAR. Bạn chỉ định một danh sách bản đồ bộ lọc cho một WAR trong descriptor triển khai của nó, hoặc với NetBeans IDE hoặc bằng cách mã hóa danh sách bằng tay với XML.
Để khai báo bộ lọc và ánh xạ nó vào một tài nguyên web bằng cách sử dụng NetBeans IDE, hãy thực hiện theo các bước sau:
- Mở rộng nút dự án của ứng dụng trong khung Project.
- Mở rộng các trang Web và các nút WEB-INF dưới nút dự án.
- Nhấp đúp vào web.xml .
- Nhấp vào Bộ lọc ở đầu cửa sổ trình soạn thảo.
- Mở rộng nút Servlet Filters trong khung soạn thảo.
- Nhấp vào Thêm phần tử bộ lọc để ánh xạ bộ lọc đến tài nguyên web theo tên hoặc theo mẫu URL.
- Trong hộp thoại Thêm bộ lọc bổ sung, nhập tên của bộ lọc vào trường Tên Bộ lọc.
- Nhấp vào Duyệt để xác định vị trí lớp servlet áp dụng bộ lọc. Bạn có thể bao gồm các ký tự đại diện để bạn có thể áp dụng bộ lọc cho nhiều hơn một servlet.
- Nhấp OK.
Để hạn chế cách lọc được áp dụng cho các yêu cầu, hãy thực hiện theo các bước sau:
- Mở rộng nút Bản đồ lọc (Filter Mappings) trong tab Bộ lọc (Filters) của cửa sổ trình soạn thảo.
- Chọn bộ lọc từ danh sách bộ lọc.
- Nhấp vào Thêm.
- Trong hộp thoại Thêm bản đồ lọc, hãy chọn một trong các loại trình điều khiển sau đây:
- YÊU CẦU : Chỉ khi yêu cầu đến trực tiếp từ khách hàng
- FORWARD : Chỉ khi yêu cầu đã được chuyển tiếp tới một thành phần (xem Chuyển quyền điều khiển sang Một thành phần Web khác )
- BAO GỒM : Chỉ khi yêu cầu đang được xử lý bởi một thành phần đã được bao gồm (xem Bao gồm các Nguồn khác trong Phản hồi )
- L ERI : Chỉ khi yêu cầu đang được xử lý với cơ chế trang lỗi (xem Xử lý lỗi Servlet )
Bạn có thể hướng bộ lọc được áp dụng cho bất kỳ sự kết hợp nào của các tình huống trước bằng cách chọn nhiều loại trình điều khiển. Nếu không có loại nào được chỉ định, tùy chọn mặc định là YÊU CẦU .
Bạn có thể khai báo, lập bản đồ và hạn chế bộ lọc bằng cách chỉnh sửa XML trong bộ mô tả triển khai ứng dụng web bằng cách làm theo các bước sau:
- Trong cửa sổ trình biên tập web.xml trong NetBeans IDE, nhấp vào XML ở đầu cửa sổ trình soạn thảo.
- Khai báo bộ lọc bằng cách thêm phần tử bộ lọc ngay sau phần tử tên hiển thị . Phần tử lọc tạo ra một tên cho bộ lọc và tuyên bố lớp thực thi của bộ lọc và các tham số khởi tạo.
- Lắp bộ lọc tới tài nguyên web theo tên hoặc bằng mẫu URL sử dụng phần tử lọc-ánh xạ :
- Bao gồm phần tử bộ lọc tên xác định tên của bộ lọc như được xác định bởi phần tử bộ lọc .
- Bao gồm một phần tử tên servlet chỉ định servlet mà bộ lọc sẽ áp dụng. Phần tử tên servlet có thể bao gồm các ký tự đại diện để bạn có thể áp dụng bộ lọc cho nhiều hơn một servlet.
- Hạn chế cách bộ lọc sẽ được áp dụng cho các yêu cầu bằng cách chỉ định một trong các tùy chọn điều khoản liệt kê (được mô tả trong bước 4 của tập hợp các bước trước) với phần tử trình điều khiển và thêm yếu tố điều phối vào phần tử lọc bản đồ .
Bạn có thể hướng bộ lọc được áp dụng cho bất kỳ kết hợp nào của các tình huống trước bằng cách bao gồm nhiều yếu tố điều phối . Nếu không có phần tử được xác định, tùy chọn mặc định là YÊU CẦU .
Nếu bạn muốn đăng nhập mọi yêu cầu cho một ứng dụng web, bạn ánh xạ bộ lọc truy cập đến mẫu URL / * . Bảng 4-6 tóm tắt định nghĩa bộ lọc và bản đồ lập bản đồ cho ứng dụng của Công ty Duke's Bookstore. Các bộ lọc được khớp bởi tên servlet và mỗi chuỗi lọc chứa chỉ một bộ lọc.
Bộ lọc |
Lớp học |
Servlet |
---|---|---|
HitCounterFilter |
Filter.HitCounterFilter |
BookStoreServlet |
Trình tự Lệnh |
Filter.OrderFilter |
ReceiptServlet |
Bảng 4-6 Nhà sách của Duke Danh sách định nghĩa và lập bản đồ
Bạn có thể bản đồ bộ lọc cho một hoặc nhiều tài nguyên web và bạn có thể bản đồ nhiều hơn một bộ lọc để một nguồn tài nguyên web. Điều này được minh họa trong Hình 4-4 , nơi bộ lọc F1 được ánh xạ tới các servlet S1, S2, và S3, bộ lọc F2 được ánh xạ tới servlet S2, và bộ lọc F3 được ánh xạ tới các servlet S1 và S2.
Ánh xạ từ bộ lọc đến servlet
Nhớ lại rằng một chuỗi lọc là một trong các đối tượng truyền vào phương pháp doFilter của bộ lọc. Chuỗi này được hình thành gián tiếp bằng các phép ánh xạ. Thứ tự của các bộ lọc trong chuỗi tương tự như thứ tự trong đó ánh xạ bộ lọc xuất hiện trong bộ mô tả triển khai ứng dụng web.
Khi bộ lọc được ánh xạ tới servlet S1, vùng chứa web sẽ gọi phương thức doFilter của F1. Các doFilter phương pháp của mỗi bộ lọc trong chuỗi lọc S1 được gọi bởi bộ lọc trước trong chuỗi bằng phương tiện của chain.doFilter phương pháp. Bởi vì chuỗi lọc của S1 chứa các bộ lọc F1 và F3, lệnh gọi F1 đến chuỗi.doFilter gọi phương thức doFilter của bộ lọc F3. Khi phương thức doFilter của F3 hoàn thành, điều khiển trả về phương thức doFilter của F1.
Giải phóng thời gian, khai phóng năng lực