tangguo

servlet的每个实例与servlet中的servlet的每个线程之间的区别?

java

servlet类有多个实例吗?当我听到“每个servlet实例”时,有人可以详细说明吗?


阅读 322

收藏
2020-10-19

共1个答案

小编典典

Servlet容器启动时,它:

  1. web.xml;
  2. 在类路径中找到已声明的Servlet;和
  3. 加载和实例化每个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()

您会看到,servlet容器为每个请求重用了相同的servlet实例。换句话说:servlet在每个request之间共享。这就是为什么它是要编写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.
    } 
}
2020-10-19