The Servlet is briefly

A Servlet is a Java class that usually plays the role of Controler in the MVC pattern of Web applications. Its job is to receive a request from a customer and send back a response. After receiving the request, the model is invoked to process the request data and set the processed data as the request properties. And send it to the JSP of the control page. Let’s take a look at how the Servlet works with a complete HTTP request.

The arrival of an HTTP request

The container controls the entire life of the Servlet, and when a user clicks on a link such as: http://localhost:8080/testWeb/action.do, the request to the server and container, Tomcat see user request is testWeb this Web application, So go to the testWeb directory and look for web.xml (commonly known as the deployment description file, or DD), and look for the servlet-mapping element in DD. The matching url-pattern is mapped to the real servlet-class according to the servlet-name of the url-pattern, and the container calls the corresponding servlet class based on this.

<servlet>
	<servlet-name>ActionServletName</servlet-name>
	<servlet-class>com.gyf.web.ActionServlet</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>ActionServletName</servlet-name>
	<url-pattern>/action.do</url-pattern>
</servlet-mapping>Copy the code

The life cycle of a Servlet

Through the above process, the container finds the Servlet to call, and if the Servlet class has not been loaded, the container calls the lifecycle of the Servlet from scratch:

  1. First load the target class (actionservlet.class), then call the Servlet’s default no-argument constructor (note that we don’t need to override the Servlet’s constructor).
  1. The init() method is then called, which is only called once in the lifetime of the Servlet if you have other initialization code (such as getting a database connection).
  2. The Service() method is then called. If the container finds that the Servlet class has been loaded, it skips the previous two steps and goes directly to this step. Each time an HTTP request arrives, the Service method of the target Servlet is called. The Service method starts a new thread each time it is called, depending on the type of HTTP request, whether to continue calling doGet() or doPost(). The Service method can be called multiple times during the lifetime of the Servlet.
  3. Finally, the Servlet class is killed with a call to the destroy() method, where garbage collection cleans up resources.
Servlet life cycle

Note that there is only one instance of each particular Servlet class on each JVM, so there is no such thing as every instance of a Servlet.

Inheritance structure and methods of servlets

ServletConfig and ServletContext

We might do this when the Servlet outputs some fixed information

PrintWriter out=response.getWriter();
out.println("59833576*@qq.com");Copy the code

If we want to change the email address, we have to change the source code, stop the Web application, recompile it, and start the Web application again. Very tedious. In a real production environment, if you can leave the source code untouched, you can use ServletConfig and ServletContext to solve this problem.

ServletConfig

Write this in the deployment description file:

<servlet>
	<servlet-name>ActionServletName</servlet-name>
	<servlet-class>com.gyf.web.ActionServlet</servlet-class>
  	<init-param>
  		<param-name>adminEmail</param-name>
      	<param-value>59833576*@qq.com</param-value>
    </init-param>
</servlet>
<servlet-mapping>
	<servlet-name>ActionServletName</servlet-name>
	<url-pattern>/action.do</url-pattern>
</servlet-mapping>Copy the code

You can see that init-param is within the servlet tag, which means that it is only used within the servlet class, not globally.

In servlets we use this:

out.println(getServletConfig().getInitParameter("adminEmail"));Copy the code

Note that this method cannot be called in the constructor, and the Servlet gets the ServletConfig object only after init().

####ServletContext

The ServletContext is globally valid, as can be seen from where it is deployed:

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version = "2.4" > < servlet > <servlet-name>Test</servlet-name> <servlet-class>com.gyf.web.GetJarServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Test</servlet-name> <url-pattern>/servlet-api.jar</url-pattern> </servlet-mapping> <context-param> <param-name>adminEmail</param-name> <param-value>59833576*@qq.com</param-value> </context-param> </web-app>Copy the code

Context-param is under the web-app tag, so it is valid for all servlets, in Servlet code:

out.println(getServletContext().getInitParamter("adminEmail"));Copy the code

Be aware of the difference between ServletContext and ServletConfig.

## Listener

What if we want to do something right away when the application is deployed? That’s when we need a listener. There are many types of listeners, each of which is used for different purposes. For example, ServletContextListener is required when an application is deployed.

ServletContextListener

package com.gyf; import javax.servlet.*; public class MyServletContextListener implements ServletContextListener { public void contextInitialized(ServletContextEvent event) { ServletContext sc=event.getServletContext(); String dogBreed=sc.getInitParameter("breed"); Dog d=new Dog(dogBreed); sc.setAttribute("dog",d); Public void contextDestroyed(ServletContextEvent Event) {// Close database}}Copy the code

To do this, simply extend the ServletContextListener interface, place the.class file in the classes folder, and write the name of the listener class in the deployment description file:

<listener>
        <listener-class>
            com.gyf.MyServletContextListener
        </listener-class>
    </listener>Copy the code

There are also many listener classes available


Context initialization parameter thread safety

Now there is a question, since ServletContext is globally visible, how can it be guaranteed to be thread-safe? Some students might want to add synchronized to the doPost() or doGet() methods, but if you think about it, this only ensures that each Servlet has one thread running, whereas a Web application can have many servlets. That still doesn’t make it thread-safe. The correct way to do this is:

synchronized (getServletContext())
{
    getServletContext().setAttribute("foo",22);
    getServletContext().setAttribute("bar",42);
}Copy the code

Each time you use ServletContext, you need to acquire its lock for this method to work