Servlet继承和全局对象的创建和访问

时间:2014-10-13 19:28:17

标签: java servlets inheritance global-variables

我将首先必须为此问题设置框架。我正在创建一个动态servlet环境,该环境使用全局可访问,易变,线程安全的内存数据缓存,该缓存存储并为环境中的每个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方法),这样我最终得到了正在实例化的六个globalCache副本(这是一个严重的内存密集型对象)。

我通过在第一次运行init方法后触发的ServletContext中分配一个标志来修复这个部分,这样它就会跳过所有其他实例,只留下一个globalCache,但是我遇到了Java的问题似乎在任意改变缓存值。

所以,技术问题:为什么Java会重复整个父servlet代码?

设计方面的问题越多:是否有更好的方法可以实现亚毫秒级的延迟,全局(在我的应用程序中) - 可访问的缓存?

我曾考虑使用类似memcached的解决方案,但我仍然希望将RAM缓存用于性能目的。

欢迎任何想法,想法或最佳实践指示。

3 个答案:

答案 0 :(得分:1)

下面的代码可以解决问题,因为它会将您的全局缓存对象放入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()方法。这就是为什么你最终得到了缓存对象的多个实例的原因。

答案 1 :(得分:0)

每个servlet实例都是一个全新的对象,这就是你的初始化代码多次运行的原因。

每个servlet实例都在一个单独的线程中工作。这就是为什么在不了解multithreading原则的情况下,您将获得损坏的数据。

关于你的问题:引入静态缓存,它将在所有这些实例中共享:

protected static final globalCache = new GlobalCache(); 

答案 2 :(得分:0)

当用户执行触发器ajax请求或回发操作时,会收到线程池中的一个线程,并为每个请求servlet调用get或post方法。

web.xml中有一个配置,可以使servlet在加载时处于活动状态。

<load-on-startup>Value</load-on-startup>

servlet具有最小值,在服务器启动时首先进行初始化。

其他明智的:

构造servlet,然后使用init方法初始化。 将处理从客户端到服务方法的任何调用。 servlet停止服务,然后使用destroy方法销毁,然后收集垃圾并最终确定。

在java中,如果一个类被初始化,扩展类也会自动初始化。