Как получить и установить глобальный объект в контексте сервлета Java

Интересно, может ли кто-либо советовать: у Меня есть сценарий, где запланированное задание, выполняемое Кварцем, будет обновлять arraylist объектов каждый час.

Но мне нужен этот arraylist объектов быть видимым ко всем сессиям, созданным Tomcat. Таким образом, то, что я думаю, - то, что я пишу этот объект где-нибудь каждый час от Кварцевого задания, которое работает так, чтобы каждая сессия могла получить доступ к нему.

Кто-либо может сказать, как лучше всего это может быть достигнуто? Я задавался вопросом об объекте, записанном в контекст сервлета от Кварцевого задания? Альтернатива имеет каждую сессию, заполняют arraylist объектов от таблицы базы данных.

Спасибо

Г-н Morgan.

20
задан Bozho 10 July 2010 в 13:32
поделиться

3 ответа

Да, я бы хранил список в ServletContext как атрибут, привязанный к приложению. Извлечение данных из базы данных вместо этого, вероятно, менее эффективно, поскольку вы обновляете список только каждый час. Создание ServletContextListener может потребоваться для того, чтобы передать задаче Quartz ссылку на объект ServletContext. Объект ServletContext можно получить только из классов, связанных с JavaEE, таких как сервлеты и слушатели.

EDIT: В ServletContextListener, когда вы создаете задание, вы можете передать список в задание, добавив его в JobDataMap.

public class MyServletContextListener implements ServletContextListener{
  public void contextInitialized(ServletContextEvent event){
    ArrayList list = new ArrayList();

    //add to ServletContext
    event.getServletContext().setAttribute("list", list);

    JobDataMap map = new JobDataMap();
    map.put("list", list);
    JobDetail job = new JobDetail(..., MyJob.class);
    job.setJobDataMap(map);
    //execute job
  }

  public void contextDestroyed(ServletContextEvent event){}
}

//Quartz job
public class MyJob implements Job{
  public void execute(JobExecutionContext context){
    ArrayList list = (ArrayList)context.getMergedJobDataMap().get("list");
    //...
  }
}
14
ответ дан 30 November 2019 в 01:23
поделиться

Что ж, если вы используете статические поля, они будут видны всем классам, загруженным одним и тем же загрузчиком классов. Я думаю, что по крайней мере сервлеты одного приложения должны пройти квалификацию. Однако это, по общему признанию, грязно.

Объект, который определен и гарантированно является (более) глобальным, - это ServletContext . Он используется всеми сервлетами, составляющими часть одного приложения, то есть загружается из одного и того же web.xml . Существуют вызовы put и get для ServletContext, которые позволяют рассматривать его по существу как карту.

Кроме того, вам нужно будет найти классы, общие для всех веб-приложений, внутри одного сервера Tomcat. Tomcat много работает с загрузчиками, и я думаю, что у разных веб-приложений будут разные загрузчики. Вы можете обойти это, написав собственный класс и поместив его в каталог Tomcat common или shared . Если я правильно понимаю это описание , эти классы будут доступны ОДИН РАЗ для всех веб-приложений.

Наконец, помимо одного сервера Tomcat, вам понадобится некоторый механизм на основе TCP / IP для связи между JVM. Но насколько я понял ваш вопрос, в этом не должно быть необходимости.

0
ответ дан 30 November 2019 в 01:23
поделиться

Вы можете попробовать кэширование, например, EhCache для хранения значений и обновления их каждый час. Это поможет справиться с проблемами параллелизма. Сам объект кэша можно хранить в ServletContext

Хороший способ писать в ServletContext из задания Quartz - зарегистрировать слушателей в задании, которые будут получать уведомления об изменении значения. Например:

public class JobListener {
    public void updateValue(Object newValue);
}

public class ServletContextCacheJobListener implements JobListener {
     private ServletContext ctx;
     public ServletContextJobListener(ServletContext ctx) {
         this.ctx = ctx;
     }

     public void updateValue(Object newValue) {
          Cache cache = (Cache) ctx.getAttribute("cache");
          cache.update("yourKey", newValue);
     }
}

Ваше задание будет иметь List, и когда вы планируете задание, вы инстанцируете конкретный слушатель и добавляете его к заданию.

1
ответ дан 30 November 2019 в 01:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: