更新时间:2023-10-05 17:21:46
当Servlet容器启动时,它:
When the Servlet container starts, it:
web.xml
; web.xml
;粗略地,像这样:
String urlPattern = parseWebXmlAndRetrieveServletUrlPattern();
String servletClass = parseWebXmlAndRetrieveServletClass();
HttpServlet servlet = (HttpServlet) Class.forName(servletClass).newInstance();
servlet.init();
servlets.put(urlPattern, servlet); // Similar to a map interface.
这些Servlet存储在内存中,并在每次请求URL与Servlet关联的 URL模式。然后,servlet容器执行类似于以下的代码:
Those Servlets are stored in memory and reused every time the request URL matches the Servlet's associated url-pattern
. The servlet container then executes code similar to:
for (Entry<String, HttpServlet> entry : servlets.entrySet()) {
String urlPattern = entry.getKey();
HttpServlet servlet = entry.getValue();
if (request.getRequestURL().matches(urlPattern)) {
servlet.service(request, response);
break;
}
}
GenericServlet #service()
轮到决定 doGet()
, doPost()等...基于 HttpServletRequest#getMethod()
。
The GenericServlet#service()
on its turn decides which of the doGet()
, doPost()
, etc.. to invoke based on HttpServletRequest#getMethod()
.
您可以看到,servletcontainer为每个请求重用相同的servlet实例。换句话说:servlet在每个请求之间共享。这就是为什么以线程安全的方式编写servlet代码非常重要 - 这实际上很简单:只需要不将请求或会话范围数据分配为servlet实例变量,而只是作为方法局部变量。例如
You see, the servletcontainer reuses the same servlet instance for every request. In other words: the servlets are shared among every request. That's why it's extremely important to write servlet code the threadsafe manner --which is actually simple: just do not assign request or session scoped data as servlet instance variables, but just as method local variables. E.g.
public class MyServlet 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.
}
}