Usando o Special Auto Start Servlet para inicializar na inicialização e compartilhar dados do aplicativo
-
28-09-2019 - |
Pergunta
Preciso obter alguma configuração e conectar -se a recursos/objetos/sistemas externos em algum lugar e armazená -lo no escopo do aplicativo.
Eu posso ver duas maneiras de configurar meu aplicativo:
- Substituindo o
init()
Nos servlets existentes e o código necessário lá e mantendo todos os objetos construídos dentro desse mesmo servlet. - Ter algum tipo de servlet de inicialização e usar seu
init()
Para fazer o trabalho. Em seguida, armazenando objetos criados emServletContext
compartilhar com meus outros servlets.
Qual fora de cima é uma abordagem melhor? Existe alguma maneira melhor de compartilhar objetos entre servlets? Chamando -os diretamente um do outro ou mais ...?
Solução
Nenhuma de ambos é a melhor abordagem. Os servlets destinam -se a ouvir os eventos HTTP (solicitações HTTP), não em eventos de implantação (inicialização/desligamento).
CDI/JSF/EJB indisponível? Usar 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.
}
}
Se você ainda não está no Servlet 3.0 e não pode atualizar e, portanto, não pode usar @WebListener
anotação, então você precisa registrá -lo manualmente em /WEB-INF/web.xml
como abaixo:
<listener>
<listener-class>com.example.Config</listener-class>
</listener>
Para armazenar e obter objetos no escopo do aplicativo (para que todos os servlets possam acessá -los), use ServletContext#setAttribute()
e #getAttribute()
.
Aqui está um exemplo que permite que o ouvinte se mantenha no escopo do aplicativo:
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("config", this);
// ...
}
e depois obtê -lo em um servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
Config config = (Config) getServletContext().getAttribute("config");
// ...
}
Também está disponível no JSP el por ${config}
. Então você também pode torná -lo um feijão simples.
CDI disponível? Usar @Observes
sobre 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.
}
}
Isso está disponível em um servlet via @Inject
. Faça isso se necessário também @Named
Então está disponível via #{config}
em El também.
Observado deve ser que isso seja novo desde o CDI 1.1. Se você ainda está no CDI 1.0 e não pode atualizar, escolha outra abordagem.
JSF disponível? Usar @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.
}
}
Isso está disponível via #{config}
em El também.
EJB disponível? Considerar @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.
}
}
Isso está disponível em um servlet via @EJB
. Estou dizendo "Considere", porque você não deve abusar de um EJB em prol de um gancho de startup. Além disso, a @Singleton
é por padrão ler/gravar bloqueado e pretendido principalmente para coisas transacionais, como agendar trabalhos em segundo plano.