小编典典
事实:在webapp的生存期内只有一个servlet实例。它是在webapp启动时创建的,在webapp关闭时销毁的。另请参见此答案以进行粗略的解释。
因此,它已在所有请求(线程)之间共享。如果将请求或会话范围的数据分配为实例static变量(或更糟的是,作为)变量,则它绝对不是线程安全的,因为它随后在应用程序范围内的所有用户(会话)的所有请求(线程)之间共享。您只需要将它们分配为方法局部变量即可保持线程安全。所以:
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.
}
}
在开发考虑线程安全性的servlet时,基本上这就是您需要考虑的所有内容。
然后是HttpSession可以在同一用户的多个请求之间共享的session()属性,但是在现实世界中,您实际上不必担心同步会话访问。通常,您只在其中放置特定于用户的数据,例如已登录的用户,特定于用户的首选项,购物篮等。您只需要确保不将纯请求范围的数据放入会话范围即可。它会反映在同一会话内的多个浏览器窗口/选项卡中。
然后有application(ServletContext)属性,这些属性在整个应用程序范围内的所有用户之间共享,但是通常您只在其中放置常量和其他静态数据,例如webapp配置,DAO工厂,下拉列表内容等。所有这些都可以通过和完成ServletContextListener,也请参见基本示例的答案。您只需要确保不将纯请求范围或会话范围的数据放入应用程序范围即可。
2020-10-18