守候你守候我
当Servlet容器启动时,它:读取web.xml;在类路径中查找声明的Servlet; 和加载并实例化每个Servlet 只一次。粗略地,像这样: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-pattern。然后servlet容器执行类似于以下的代码: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()。您看,servletcontainer 为每个请求重用相同的servlet实例。换句话说:servlet在每个请求之间共享。这就是为什么以线程安全的方式编写servlet代码非常重要 - 这实际上很简单:只是不将请求或会话范围数据分配为servlet实例变量,而只是作为方法局部变量。例如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. } }