在servlets中,每个servlet实例与每个servlet线程之间的区别是什么?

26 浏览
0 Comments

在servlets中,每个servlet实例与每个servlet线程之间的区别是什么?

这个问题已经有答案了:

Servlets是如何工作的? 实例化,会话,共享变量和多线程

Servlet类有多个实例吗?我听说\"每个Servlet实例\"

有人能详细解释一下吗?

admin 更改状态以发布 2023年5月21日
0
0 Comments

不,servlet只有一个实例,用于多个客户端的多个请求。这导致两个重要的规则:

  • 在servlet中不要使用实例变量,除非是应用程序范围内的值,通常是从上下文参数获取的。
  • 不要在servlet中使用同步方法

(servlet过滤器和JSP也是一样)

0
0 Comments

当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 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在每个请求中是共享的。这就是为什么编写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.
    } 
}

0