我必须首先为这个问题建立框架。我正在创建一个动态 Servlet 环境,该环境使用全局可访问、 volatile 、线程安全的内存中数据缓存,为环境中的每个 Servlet 存储并提供对其自身的访问。
类似这样的事情:
public class CoreServlet extends HttpServlet {
protected globalCache;
public void init(ServletConfig config){
globalCache = new InMemoryCache();
}
doGet...
doPost...
}
然后,许多其他 servlet 会扩展该 servlet,这些 servlet 在 globalCache 上执行辅助任务(更改值等)。
public class subServletA extends CoreServlet {
doGet...
doPost...
}
和
public class subServletB extends CoreServlet {
doGet...
doPost...
}
等等...
通过实验,我发现这样做会导致每次扩展 CoreServlet 时重新执行整个 CoreServlet 代码(包括所有全局变量实例化和 init 方法),最终实例化了 6 个 globalCache 副本(这是一个严重内存密集型对象)。
我通过在第一次运行 init 方法后触发的 ServletContext 中分配一个标志来修复此部分,这样它将跳过所有其他实例化,只留下一个 globalCache,但我遇到了 Java 似乎任意更改缓存值的问题。
那么,技术问题是:为什么 Java 会重复整个父 servlet 代码?
更多设计方面的问题:是否有更好的方法来实现亚毫秒级延迟、全局(在我的应用程序内)可访问的缓存?
我曾考虑过使用类似 memcached 的解决方案,但出于性能目的,我仍然希望将缓存保留在 RAM 中。
欢迎任何想法、创意或最佳实践建议。
最佳答案
下面的代码应该可以解决这个问题,因为它将把您的全局缓存对象放入 Web 应用程序的 ServletContext
中,从而与所有 servlet 共享它。
public class CoreServlet extends HttpServlet {
protected globalCache;
@Override
public void init(ServletConfig config){
synchronized(CoreServlet.class) {
globalCache = (InMemoryCache) config.getServletContext().getAttribute("core.cache");
if (globalCache == null) {
globalCache = new InMemoryCache();
config.getServletContext().setAttribute("core.cache", globalCache);
}
}
}
}
如果扩展CoreServlet
,Servlet 容器将调用init()
方法。这就是为什么您最终会得到多个缓存对象实例的原因。
关于java - Servlet 继承以及全局对象创建和访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26347467/