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

2022-08-31 11:55:43

Servlet 类是否有多个实例?当我听到“每个servlet实例”时,任何人都可以详细说明这一点吗?


答案 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 的关联 .然后,Servlet 容器执行类似于以下内容的代码:url-pattern

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() 轮到它来决定哪个 、 等。基于 HttpServletRequest#getMethod() 调用doGet()doPost()

你看,servletcontainer 为每个请求重用相同的 servlet 实例。换句话说:servlet 在每个请求之间共享。这就是为什么以 threadsafe 方式编写 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.
    } 
}

答案 2

不,只有一个 servlet 实例被重用用于来自多个客户端的多个请求。这就引出了两条重要的规则:

  • 不要在 servlet 中使用实例变量,但应用程序范围的值除外,这些值通常是从上下文参数中获取的。
  • 不要在 servlet 中生成方法synchronized

(servlet filters 和 jsps 也是如此)


推荐