ServletContext
Khi bộ chứa servlet (như Apache Tomcat ) khởi động, nó sẽ triển khai và tải tất cả các ứng dụng web của nó. Khi một ứng dụng web được tải, thùng chứa servlet sẽ tạo ServletContext
một lần và giữ nó trong bộ nhớ của máy chủ. Các ứng dụng web của web.xml
và tất cả bao gồm web-fragment.xml
các file được phân tách, và mỗi <servlet>
, <filter>
và <listener>
tìm thấy (hoặc mỗi lớp chú thích với @WebServlet
, @WebFilter
và @WebListener
tương ứng) được khởi tạo một lần và lưu giữ trong bộ nhớ của máy chủ là tốt. Đối với mỗi bộ lọc khởi tạo, init()
phương thức của nó được gọi với một bộ lọc mới FilterConfig
.
Khi Servlet
có một <servlet><load-on-startup>
hoặc @WebServlet(loadOnStartup)
giá trị lớn hơn 0
, sau đó nó init()
phương pháp cũng được gọi trong quá trình startup với một mới ServletConfig
. Các servlet đó được khởi tạo theo cùng thứ tự được chỉ định bởi giá trị đó ( 1
là 1st, 2
is 2nd, v.v.). Nếu cùng giá trị được quy định trong hơn một servlet, sau đó mỗi người trong số những servlets được nạp theo thứ tự như chúng xuất hiện trong web.xml
, web-fragment.xml
hoặc @WebServlet
classloading. Trong trường hợp không có giá trị "tải khi khởi động", init()
phương thức sẽ được gọi bất cứ khi nào yêu cầu HTTP chạm vào servlet đó lần đầu tiên.
Khi bộ chứa servlet kết thúc với tất cả các bước khởi tạo được mô tả ở trên, thì nó ServletContextListener#contextInitialized()
sẽ được gọi.
Khi tắt servlet container xuống, nó trút tất cả các ứng dụng web, gọi các destroy()
phương pháp của tất cả các servlets nó khởi tạo và các bộ lọc, và tất cả ServletContext
, Servlet
, Filter
và Listener
các trường hợp được cho vào thùng rác. Cuối cùng ServletContextListener#contextDestroyed()
sẽ được viện dẫn.
HttpServletRequest và HttpServletResponse
Bộ chứa servlet được gắn vào một máy chủ web lắng nghe các yêu cầu HTTP trên một số cổng nhất định (cổng 8080 thường được sử dụng trong quá trình phát triển và cổng 80 trong sản xuất). Khi một máy khách (ví dụ: người dùng có trình duyệt web hoặc sử dụng theo chương trìnhURLConnection
) gửi yêu cầu HTTP, thùng chứa servlet sẽ tạo mới HttpServletRequest
và HttpServletResponse
các đối tượng và chuyển chúng qua bất kỳ định nghĩa nào Filter
trong chuỗi và cuối cùng là Servlet
thể hiện.
Trong trường hợp bộ lọc , doFilter()
phương thức được gọi. Khi mã bộ chứa của servlet gọi chain.doFilter(request, response)
, yêu cầu và phản hồi tiếp tục đến bộ lọc tiếp theo hoặc nhấn vào servlet nếu không có bộ lọc còn lại.
Trong trường hợp của servlets , service()
phương thức được gọi. Theo mặc định, phương thức này xác định một trong những doXxx()
phương thức để gọi dựa trên request.getMethod()
. Nếu phương thức xác định vắng mặt trong servlet, thì lỗi HTTP 405 được trả về trong phản hồi.
Đối tượng yêu cầu cung cấp quyền truy cập vào tất cả các thông tin về yêu cầu HTTP, chẳng hạn như URL, tiêu đề, chuỗi truy vấn và phần thân của nó. Ví dụ, đối tượng phản hồi cung cấp khả năng kiểm soát và gửi phản hồi HTTP theo cách bạn muốn, cho phép bạn đặt các tiêu đề và phần thân (thường là với nội dung HTML được tạo từ tệp JSP). Khi phản hồi HTTP được cam kết và kết thúc, cả đối tượng yêu cầu và phản hồi đều được tái chế và cung cấp để sử dụng lại.
Câu hỏi
Khi một khách hàng truy cập ứng dụng web lần đầu tiên và / hoặc HttpSession
lần đầu tiên có được thông qua request.getSession()
, bộ chứa servlet tạo một HttpSession
đối tượng mới , tạo một ID dài và duy nhất (mà bạn có thể nhận được session.getId()
) và lưu trữ nó trong máy chủ ký ức. Container servlet cũng đặt ra một Cookie
trong các Set-Cookie
tiêu đề của HTTP response với JSESSIONID
như tên của nó và ID phiên duy nhất là giá trị của nó.
Theo đặc tả cookie HTTP (hợp đồng bất kỳ trình duyệt web và máy chủ web tốt nào phải tuân thủ), khách hàng (trình duyệt web) được yêu cầu gửi lại cookie này trong các yêu cầu tiếp theo trong Cookie
tiêu đề miễn là cookie hợp lệ ( tức là ID duy nhất phải tham chiếu đến một phiên chưa hết hạn và tên miền và đường dẫn là chính xác). Sử dụng trình giám sát lưu lượng HTTP tích hợp trong trình duyệt của bạn, bạn có thể xác minh rằng cookie hợp lệ (nhấn F12 trong Chrome / Firefox 23+ / IE9 + và kiểm tra tab Net / Network ). Bộ chứa servlet sẽ kiểm tra Cookie
tiêu đề của mọi yêu cầu HTTP đến cho sự hiện diện của cookie với tên JSESSIONID
và sử dụng giá trị của nó (ID phiên) để lấy liên kết HttpSession
từ bộ nhớ của máy chủ.
Việc HttpSession
tồn tại cho đến khi nó ở chế độ chờ (nghĩa là không được sử dụng trong yêu cầu) nhiều hơn giá trị thời gian chờ được chỉ định trong <session-timeout>
, cài đặt trong web.xml
. Giá trị thời gian chờ mặc định là 30 phút. Vì vậy, khi khách hàng không truy cập ứng dụng web lâu hơn thời gian được chỉ định, bộ chứa servlet sẽ bỏ qua phiên. Mọi yêu cầu tiếp theo, ngay cả với cookie được chỉ định, sẽ không có quyền truy cập vào cùng một phiên nữa; container servlet sẽ tạo ra một phiên mới.
Về phía khách hàng, cookie phiên vẫn tồn tại miễn là phiên bản trình duyệt đang chạy. Vì vậy, nếu máy khách đóng phiên bản trình duyệt (tất cả các tab / cửa sổ), thì phiên sẽ được chuyển sang phía máy khách. Trong phiên bản trình duyệt mới, cookie được liên kết với phiên sẽ không tồn tại, do đó, nó sẽ không còn được gửi. Điều này gây ra một cái hoàn toàn mới HttpSession
được tạo ra, với một cookie phiên hoàn toàn mới được sử dụng.
Tóm lại
- Cuộc
ServletContext
sống miễn là ứng dụng web sống. Nó được chia sẻ giữa tất cả các yêu cầu trong tất cả các phiên.
- Thời
HttpSession
gian tồn tại của ứng dụng khách tương tác với ứng dụng web có cùng phiên bản trình duyệt và phiên không hết thời gian ở phía máy chủ. Nó được chia sẻ giữa tất cả các yêu cầu trong cùng một phiên.
- Các
HttpServletRequest
và HttpServletResponse
trực tiếp từ thời điểm đó servlet nhận được một yêu cầu HTTP từ các khách hàng, cho đến khi đáp ứng đầy đủ (trang web) đã đến. Nó không được chia sẻ ở nơi khác.
- Tất cả
Servlet
, Filter
và Listener
trường hợp sống lâu như các ứng dụng web sống. Chúng được chia sẻ giữa tất cả các yêu cầu trong tất cả các phiên.
- Bất kỳ
attribute
được xác định trong ServletContext
, HttpServletRequest
và HttpSession
sẽ sống lâu như các đối tượng trong cuộc sống câu hỏi. Các đối tượng chính nó đại diện cho "phạm vi" trong khuôn khổ quản lý đậu như JSF, CDI, Spring, vv Những khung lưu trữ đậu scoped của họ như là một attribute
phạm vi phù hợp nhất của nó.
An toàn chủ đề
Điều đó nói rằng, mối quan tâm chính của bạn có thể là an toàn chủ đề . Bây giờ bạn nên biết rằng các servlet và bộ lọc được chia sẻ giữa tất cả các yêu cầu. Đó là điều hay về Java, đó là các luồng đa luồng và các luồng khác nhau (đọc: các yêu cầu HTTP) có thể sử dụng cùng một thể hiện. Nó sẽ quá tốn kém để tạo lại, init()
và destroy()
chúng cho mỗi yêu cầu.
Bạn cũng nên nhận ra rằng bạn nên không bao giờ gán bất kỳ dữ liệu yêu cầu hoặc phiên scoped như một ví dụ biến của một servlet hoặc bộ lọc. Nó sẽ được chia sẻ giữa tất cả các yêu cầu khác trong các phiên khác. Đó không phải là chủ đề an toàn! Ví dụ dưới đây minh họa điều này:
public class ExampleServlet extends HttpServlet {
private Object thisIsNOTThreadSafe;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object thisIsThreadSafe;
thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
}
}
Xem thêm: