假设我有两个servlet,A和B。在 Servlet A 中,我创建了一个 HashMap 并存储在 init() 中的 Servlet 上下文中,如下所示:
ServletContext context = getServletContext();
context.setAttribute("otable", someObject);
现在在 Servlet B 的 init() 中,我正在初始化对 servlet 上下文对象的本地引用(我指定首先创建 servlet 上下文对象的 servlet 首先通过 web.xml 启动):
// get and set reference to object cache
oc = (ObjectCache)getServletContext().getAttribute("otable");
然后我插入,大小变为 1。 当再次调用 Servlet A 并检查 servlet 上下文 HashMap 时,大小仍为 0。
存储对 servlet 上下文对象的本地引用是一个坏主意吗?我也尝试直接从servlet上下文中获取对象,但得到了相同的结果。 我在这里错过了什么?
创建共享对象的 servlet 首先在我的 web 中启动.xml如下所示:
<servlet>
<servlet-name>ServletA</servlet-name>
<servlet-class>package.ServletA</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
在 ServletContext 中存储跨 servlet 又名应用程序范围对象的想法是完全可行的。我重新测试了你的方法,它完全有效。你一定错过了代码中忘记发布的东西。
我可以使其按如下方式工作:
ServletA (snip):
public void init() throws ServletException {
Map<String, String> map = new ConcurrentHashMap<>();
getServletContext().setAttribute("map", map);
System.out.println("Servlet A Mapsize: " + map.size());
map.put("foo", "bar");
System.out.println("Servlet A Mapsize: " + map.size());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, String> map = (Map<String, String>) getServletContext().getAttribute("map");
System.out.println("Servlet A Mapsize: " + map.size());
}
ServletB (snip):
public void init() throws ServletException {
Map<String, String> map = (Map<String, String>) getServletContext().getAttribute("map");
System.out.println("Servlet B Mapsize: " + map.size());
map.put("foo", "bar");
System.out.println("Servlet B Mapsize: " + map.size());
}
网络.xml(截图):
<servlet>
<servlet-name>ServletA</servlet-name>
<servlet-class>mypackage.ServletA</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet>
<servlet-name>ServletB</servlet-name>
<servlet-class>mypackage.ServletB</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletA</servlet-name>
<url-pattern>/a</url-pattern>
</servlet-mapping>
启动应用程序将提供以下输出:
Servlet A 映射大小: 0
Servlet A 映射大小:1
Servlet B 映射大小: 1
Servlet B 映射大小: 1
如您所见,地图已正确填充。
现在你可以调用servletA来检查一切是否正常。
在浏览器中打开(我的设置):
http://localhost:8080/servtest/a
将产生以下输出
Servlet A 映射大小:1
顺便说一句,有了CDI,你可以编写你的applicationScoped缓存生产者,以获得更易于维护的代码。