Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
836 views
in Technique[技术] by (71.8m points)

initialization - Using special auto start servlet to initialize on startup and share application data

I need to get some configuration and connect to external resources/objects/systems somewhere and store it in application scope.

I can see two ways to setup my application:

  • Overriding the init() in the existing servlets and required code there and keeping all constructed objects inside that same servlet.
  • Having some kind of an initialisation servlet and using its init() to do the work. Then storing created objects in ServletContext to share it with my other servlets.

Which out of above is better approach? Is there any better way to share objects between servlets? Calling them directly from one another or so...?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

None of both is the better approach. Servlets are intended to listen on HTTP events (HTTP requests), not on deployment events (startup/shutdown).


CDI/JSF/EJB unavailable? Use 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.
    }

}

If you're not on Servlet 3.0 yet and can't upgrade, and thus can't use @WebListener annotation, then you need to manually register it in /WEB-INF/web.xml like below:

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

To store and obtain objects in the application scope (so that all servlets can access them), use ServletContext#setAttribute() and #getAttribute().

Here's an example which lets the listener store itself in the application scope:

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

and then obtain it in a servlet:

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

It's also available in JSP EL by ${config}. So you could make it a simple bean as well.


CDI available? Use @Observes on 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.
    }
}

This is available in a servlet via @Inject. Make it if necessary also @Named so it's available via #{config} in EL as well.

Noted should be that this is new since CDI 1.1. If you're still on CDI 1.0 and can't upgrade, then pick another approach.


JSF available? Use @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.
    }
}

This is available via #{config} in EL as well.


EJB available? Consider @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.
    }
}

This is available in a servlet via @EJB. I'm saying "consider", because you should not abuse an EJB for the sake of a startup hook. Moreover, a @Singleton is by default read/write locked and primarily intented for transactional stuff such as scheduling background jobs.

See also:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...