Использование специального сервлета автоматического запуска для инициализации при запуске и обмена данными приложения

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

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

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

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

32
задан BalusC 7 October 2015 в 09:09
поделиться

1 ответ

Ни один из них не является лучшим подходом. Сервлеты предназначены для прослушивания событий 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.
    }

}

, если вы не используете сервлет 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} . Так что вы также можете сделать его простым bean-компонентом.


CDI доступен? Используйте @Observe в 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 по умолчанию заблокирован для чтения / записи и в первую очередь предназначен для транзакционных операций, таких как планирование фоновых заданий.

См. Также:

74
ответ дан 27 November 2019 в 20:17
поделиться
Другие вопросы по тегам:

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