Comparison of several ways to automatically execute programs after Web container startup

Source: Internet
Author: User
Tags message queue

1. Background 1.1. Background introduction

In Web projects we sometimes encounter this need, after the launch of the Web project needs to open the thread to do some important work, such as: to initialize some data in the database, open the thread, initialize the message queue, in this demand, how to execute after the Web container startup is the focus of this article.

1.2. Test Project Setup

First we create a new Web project to simulate this requirement, and here we choose to build a MAVEN project

Add the following properties items to the project's Pom file

<properties>
<!--web-->
<servlet.version>3.1.0</servlet.version>
<!--spring-->
<spring-framework.version>4.3.8.RELEASE</spring-framework.version>
<!--logging-->
<logback.version>1.1.7</logback.version>
<slf4j.version>1.7.5</slf4j.version>
</properties>

Add the following dependencies

<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>

Wait until the MAVEN build is complete and we can start building a Web project for testing

Regular projects are basically built with the spring framework, and here we are no exception, where we use 0 configuration files to build a Web project

For SPRING0 configuration file construction project can find a lot of information on the Internet, here to simple build one, without detailed explanation

1. First set up the package structure under the Project SRC directory as follows

2. Create the following two files in the Config directory to configure this project

public class Webinitializer implements webapplicationinitializer{

Logger logger= loggerfactory.GetLogger(Webinitializer.class);


public void Onstartup (ServletContext servletcontext) throwsservletexception {
Annotationconfigwebapplicationcontext CTX = Newannotationconfigwebapplicationcontext ();
Ctx.register (Myconfig.class);
Logger.debug ("Boot sequence: Start");
Ctx.setservletcontext (ServletContext);
Ctx.refresh ();
Servletregistration.dynamicservlet = Servletcontext.addservlet ("Dispatcher", New Dispatcherservlet (CTX));
Servlet.addmapping ("/");
Servlet.setloadonstartup (1);
Servlet.setasyncsupported (TRUE);

}
}

@Configuration
@EnableWebMvc
@ComponentScan ("com.hei123")
public class Myconfig extends Webmvcconfigureradapter {


}

By this point, the test project has been completed, followed by several common solutions

2. Several solutions

2.1. Javaweb-based Servletcontextlistener

1, the new class Simpleservletlistener implementation Servletcontextlistener interface under the Listener package

public class Simpleservletlistener implements Servletcontextlistener {
Logger logger= loggerfactory. GetLogger (Simpleconsumer.class);

public void contextinitialized (Servletcontextevent sce) {
Logger.debug ("Boot Sequence: Listener ServletContext listeners hear ServletContext initialization");
/**
*
Write the code that needs to be executed here
*/
}

Publicvoid contextdestroyed (SERVLETCONTEXTEVENTSCE) {

}
}

2. Add the following code to the Onstartup tail of the Webinitializer class

Servletcontext.addlistener (Simpleservletlistener.class);

2.2. Javaweb-based filter
    1. To implement the filter interface under the filter package, create a new Simplefilter class

public class Simplefilter implements Filter {
Logger logger= loggerfactory. GetLogger (Simpleconsumer.class);

public void init (Filterconfig filterconfig) throwsservletexception {
Logger.debug ("Boot Sequence: Filter initialization configured in the Web Initialization Configuration");

Write the code that needs to be executed here
}

Publicvoid DoFilter (Servletrequestservletrequest, Servletresponseservletresponse, Filterchainfilterchain) throws IOException, Servletexception {

}
Publicvoid Destroy () {

}
}

    1. Add the following code to the tail of Onstartup in the Webinitializer class

Servletcontext.addfilter ("Simplefilter", Simplefilter.class);

2.3. Javaweb-based Servlet
    1. New Simpleservlet inherit HttpServlet under Servlet package

public class Simpleservlet extends HttpServlet {

Logger logger= loggerfactory. GetLogger (Webinitializer.class);


@Override
Publicvoid init () throws Servletexception {
Logger.debug ("Boot Sequence: servlet initialization configured in Web initialization Configuration");
Write the code that needs to be executed here
Super.init ();
}
}

    1. Add the following code to the tail of Onstartup in the Webinitializer class

Servletregistration.dynamic simpleservlet =servletcontext.addservlet ("Simpleservlet", New SimpleServlet ());
Simpleservlet.setloadonstartup (2);

This is set to 2 because you need to start SPRINGMVC's Dispatcherservlet first

2.4. Spring-based Applicationlistener
    1. The new Simpleapplicationlistener class implements the Applicationlistener<contextrefreshedevent> interface under the listener package to listen for events that the spring container started to complete

@Component
public class Simpleapplicationlistenerimplements applicationlistener<contextrefreshedevent>{
Logger logger= loggerfactory. GetLogger (Simpleconsumer.class);

public void Onapplicationevent (Contextrefreshedevent contextrefreshedevent) {

Logger.debug ("Boot Sequence: Method call to listen for the spring container context initialization"); Write the code that needs to be executed here
}
}

2.5. Spring-based PostProcessor2.5.1 Beanfactorypostprocessor

The new Simplebeanfactorypostprocessor class implements the Beanfactorypostprocessor interface under the Postprocessor package

@Component
public class Simplebeanfactorypostprocessorimplements beanfactorypostprocessor{

Logger logger= loggerfactory. GetLogger (Webinitializer.class);

public void Postprocessbeanfactory (configurablelistablebeanfactoryconfigurablelistablebeanfactory) throws beansexception {
Logger.debug ("Bootsequence:bootfactory processor execution");

Write the code that needs to be executed here
}
}

2.5.2 Beanpostprocessor

The new Simplebeanpostprocessor class implements the Beanpostprocessor interface under the Postprocessor package

@Component
public class Simplebeanpostprocessor implements Beanpostprocessor {
Note: The methods in this interface are executed once for each bean initialization
Loggerlogger = Loggerfactory. GetLogger (Webinitializer.class);

Public Objectpostprocessbeforeinitialization (Objecto, String s) throwsbeansexception {
Returno;
}

Publicobject postprocessafterinitialization (Object o, String s) throws Beansexception {
if (o instanceof simpleconsumer) {
Logger.debug ("Execution after initialization of Bootsequence:simpleconsumer");

Write the code that needs to be executed here
}else{
Logger.debug ("Other Bean: Executes after initialization");
}
Returno;
}
}

2.6. Spring-based Initializingbean
    1. The new Simpleconsumer class implements the Initializingbean interface under the Initializingbean package

@Component
public class Simpleconsumer implements Initializingbean {
Logger logger= loggerfactory. GetLogger (Simpleconsumer.class);

public void Afterpropertiesset () throws exception{
Logger.debug ("Boot sequence:simpleconsumer Bean Dependency Injection complete");
Write the code that needs to be executed here
}
}

3. Comparison between Solutions

3.1. Execution order

I have added all of the above solutions in my test project from the log to see the execution order of several scenarios

Boot order

Scheme name

Explain

1

Servletcontextlistener based on the Javaweb

Listening Webcontext initialization

2

Filter based on the Javaweb

Webcontext initializes the defined filter before loading the defined servlet, and the spring container here is initialized with the defined Dispatcherservlet.

3

Spring-based Beanfactorypostprocessor

4

Spring-based Initializingbean

Executes after the Simpleconsumer property injection is complete

5

Spring-based Beanpostprocessor

Executes after Simplerconsumer initialization is complete

6

Spring-based Applicationcontextlistener

Executes after the spring container initializes all the beans

7

Javaweb-based Servlet

In the configuration we set the order of execution to 2, and this servlet will not initialize until the Dispatcherservlet initialization is complete, so it will fall to the last

3.2. Horizontal contrast

 

Servlet

Contextlistener

Filter

Beanfactory

Postprocessor

Initializing

Bean

Bean

postprocessor

Application

Contextlistener

servlet

Auto execute

Yes

Strong>√

references a variable or method of another class

x

x

* unsure

* unsure

Whether the spring container has attribute injection

x

x

X

All properties of the current bean have been injected and other properties referenced in its properties have been injected

All properties of the current bean have been injected and other properties referenced in its properties have been injected

Web Container fully started

X

X

X

X

X

X

X

* refers to a bean that is not initialized to be referenced if another bean has been initialized to complete

3.3. Details 3.3.1 The difference between Beanfactorypostprocessor and beanpostprocessor

Beanfactorypostprocessor and beanpostprocessor do not look like the name long, in fact, the contents of the gap is very large,

    1. Beanfactorypostprocessor is a post processor that is called after the spring container has acquired all the bean initialization lists and created the Beanfactory, and all the beans are not initialized at this time
    2. Beanpostprocessor is the Postprocessafterinitialization method that will be called at each initialization of a bean, at which point it may have initialized some beans
The difference between afterpropertiesset in 3.3.2 Initializing and the Init-method of XML configuration and Beanpostprocessor

If we were to configure a bean in spring through an XML configuration file, which could be configured with a Init-method method for initialization, what is the difference between the three?

Execution order

In fact, this project can add Init-method to verify the order of execution, here is no longer to add, directly explained, in fact, only from the name can be seen in the execution sequence should be

Afterpropertiessetàinitmethodàbeanpostprocessor

This bean is basically created when the property is set to complete, that is, Afterpropertiesset,

After the bean is created, you can perform some initialization operations on the bean, that is, the Init-method

After initialization is complete, call the Bean's back processor to do some other things

This can be viewed in the source code, here is not a long explanation

3.3.3 the start order of web containers

1. When the Web container starts, all Webcontextlistener will receive a notification that the Web container is started and can execute the listening method in it.

2. Next, the Web container will initialize all filter filters First

3. The Web container then initializes all servlets according to the order in which the servlet is initialized, in this case the Dispacherservlet boot order is 1 MAX,

The spring container is initialized in 4.DispacherServlet

5. Initialize the other servlet

6.web Container Start complete

3.3.4 How to choose
    1. If we need to execute the program when the Web container is just initialized, we need to implement the SERVLETCONTEXTLISTENRE scheme.
    2. If we need all the content in the spring container to be loaded, we will implement the Applicationcontextlistener scheme.

In short, we need to according to their actual situation to choose the corresponding scheme to achieve the best results

4. Summary

This article mainly introduces several kinds of solutions for automatic code execution after web container startup, and gives some general analysis of these solutions, some of which are explained in detail, and the detailed explanations need to be better understood by observing the source material, and the shortcomings, please correct me.

Any questions please contact [email protected]

Comparison of several ways to automatically execute programs after Web container startup

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.