Использование специального автозапуска сервлета для инициализации при запуске и обмена данными приложения - PullRequest
31 голосов
/ 12 августа 2010

Мне нужно получить некоторую конфигурацию и подключиться к внешним ресурсам / объектам / системам где-нибудь и сохранить ее в области приложения.

Я вижу два способа настройки моего приложения:

  • Переопределение init() в существующих сервлетах и ​​требуемый там код и сохранение всех построенных объектов в этом же сервлете.
  • Наличие какого-либо сервлета инициализации и использование его init() для выполнения работы.Затем сохраните созданные объекты в ServletContext, чтобы поделиться им с моими другими сервлетами.

Какой из вышеперечисленных является лучшим подходом?Есть ли лучший способ для обмена объектами между сервлетами?Звонить им напрямую друг от друга или около того ...?

1 Ответ

72 голосов
/ 12 августа 2010

Ни то, ни другое не является лучшим подходом. Сервлеты предназначены для прослушивания событий HTTP (HTTP-запросов), а не событий развертывания (запуск / выключение).


CDI / JSF / EJB недоступен? Используйте ServletContextListener

@WebListener
public class Config implements ServletContextListener {

    public void contextInitialized(ServletContextEvent event) {
        // Do stuff during webapp's startup.
    }

    public void contextDestroyed(ServletContextEvent event) {
        // Do stuff during webapp's shutdown.
    }

}

Если вы еще не используете Servlet 3.0 и не можете выполнить обновление и, следовательно, не можете использовать аннотацию @WebListener, вам необходимо вручную зарегистрировать ее в /WEB-INF/web.xml, как показано ниже:

<listener>
    <listener-class>com.example.Config</listener-class>
</listener>

Чтобы хранить и получать объекты в области приложения (чтобы все сервлеты могли к ним обращаться), используйте ServletContext#setAttribute() и #getAttribute().

Вот пример, который позволяет слушателю сохранять себя в области приложения:

    public void contextInitialized(ServletContextEvent event) {
        event.getServletContext().setAttribute("config", this);
        // ...
    }

и затем получить его в сервлете:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        Config config = (Config) getServletContext().getAttribute("config");
        // ...
    }

Он также доступен в JSP EL по ${config}. Таким образом, вы могли бы также сделать его простым бобом.


CDI доступен? Используйте @Observes на ApplicationScoped.class

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class Config {

    public void init(@Observes @Initialized(ApplicationScoped.class) ServletContext context) {
        // Do stuff during webapp's startup.
    }

    public void destroy(@Observes @Destroyed(ApplicationScoped.class) ServletContext context) {
        // Do stuff during webapp's shutdown.
    }
}

Это доступно в сервлете через @Inject. Сделайте также, если необходимо, @Named, чтобы оно было доступно через #{config} в EL.

Следует отметить, что это новое, начиная с CDI 1.1. Если вы все еще используете CDI 1.0 и не можете выполнить обновление, выберите другой подход.


JSF доступен? Используйте @ManagedBean(eager=true)

import javax.faces.bean.ManagedBean
import javax.faces.bean.ApplicationScoped;

@ManagedBean(eager=true)
@ApplicationScoped
public class Config {

    @PostConstruct
    public void init() {
        // Do stuff during webapp's startup.
    }

    @PreDestroy
    public void destroy() {
        // Do stuff during webapp's shutdown.
    }
}

Доступно также через #{config} в EL.


EJB доступен? Рассмотрим @Startup@Singleton

@Startup
@Singleton
public class Config {

    @PostConstruct
    public void init() {
        // Do stuff during webapp's startup.
    }

    @PreDestroy
    public void destroy() {
        // Do stuff during webapp's shutdown.
    }
}

Это доступно в сервлете через @EJB. Я говорю «рассмотреть», потому что вы не должны злоупотреблять EJB ради запуска запуска. Более того, @Singleton по умолчанию заблокирован для чтения / записи и предназначен в основном для транзакционных операций, таких как планирование фоновых заданий.

Смотри также:

...