GenericServlet, ServletConfig and ServletContext

2023.10.19

What are the disadvantages of writing a Servlet class to directly implement the Servlet interface?

  • We only need the service method, other methods do not need to be used in most cases, and the code is very bloated.

Solution: Write a GenericServlet class. This class is an abstract class with an abstract method service.

  • GenericServlet implements the Servlet interface.

  • GenericServlet is an adapter.

  • All Servlet classes written in the future inherit GenericServlet and just rewrite the service method.

Does the GenericServlet class need to be modified? How to transform it? Is it more conducive to writing subclass programs?

Since the service function may use the ServletConfig object in the init function, it is necessary to define a ServletConfig member variable to receive the ServletConfig object in init, and then return the config object in getServletConfig, so that the subservice can obtain the config object.

At this time there is another question: What if the programmer rewrites the init method? Then all previous assignment operations to member variables in the init method will be overwritten. The solution is: first modify the init method with final, then define a member method init, which is specifically for subclasses to rewrite, and then call the init in the final modified init method: this.init();

The modified GenericServlet class code is as follows:

package com.servlet;

import jakarta.servlet.*;

import java.io.IOException;

/**
 * Write a standard universal Servlet and name it: GenericServlet
 * In the future, all Servlet classes should not directly implement the Servlet interface.
 * All future Servlet classes must inherit the GenericServlet class.
 * GenericServlet is an adapter.
 */
public abstract class GenericServlet implements Servlet {
    privateServletConfig config;

    @Override
    public final void init(ServletConfig Config) throws ServletException {
        this.config = Config;
        this.init();
    }
    //This init method is for subclasses to override
    public void init(){

    }

    @Override
    public ServletConfig getServletConfig() {
        return config;
    }

    /**
     * Abstract method, this method is the most commonly used. Therefore, subclasses are required to implement the service method.
     */
    public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException;


    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

ServletConfig

  • What is ServletConfig?

    • The configuration information object of the Servlet object.

    • The ServletConfig object encapsulates the configuration information in the tag. (Configuration information of servlet in web.xml file)

  • A Servlet corresponds to a ServletConfig object.

  • The Servlet object is created by the Tomcat server, and the ServletConfig object is also created by the Tomcat server. And by default, they are created when the user sends the first request.

  • When the Tomcat server calls the init method of the Servlet object, it needs to pass a parameter of the ServletConfig object to the init method.

  • The implementation class of the ServletConfig interface is implemented by the Tomcat server.

  • What are the commonly used methods in the ServletConfig interface?

public String getInitParameter(String name); // Get the value through the name of the initialization parameter
public Enumeration<String> getInitParameterNames(); // Get the names of all initialization parameters
public ServletContext getServletContext(); // Get the ServletContext object
public String getServletName(); // Get the name of Servlet

The above methods can be called using this in the Servlet class. Because GenericServlet implements the ServletConfig interface.

ServletContext

  • A Servlet object corresponds to a ServletConfig.

  • As long as they are in the same webapp, as long as they are in the same application, all Servlet objects share the same ServletContext object.

  • The ServletContext object is created during the server startup phase and is destroyed when the server is shut down. This is the life cycle of the ServletContext object. ServletContext objects are application-level objects.

  • There is a webapps in the Tomcat server. Multiple webapps can be stored under this webapps. Assume there are 100 webapps, then there are 100 ServletContext objects. However, a webapp must have only one ServletContext object.

  • ServletContext is called the Servlet context object. (The surrounding environment object of the Servlet object.)

  • A ServletContext object usually corresponds to a web.xml file.

  • ServletContext is an interface, and the Tomcat server implements the ServletContext interface.

    • The creation of the ServletContext object is also completed by the Tomcat server. Created when starting the webapp.

What are the commonly used methods in the ServletContext interface?

public String getInitParameter(String name); // Get the value through the name of the initialization parameter
public Enumeration<String> getInitParameterNames(); // Get the names of all initialization parameters
<!--The above two methods are methods of the ServletContext object. What information does this method obtain? It is the following configuration information -->
<context-param>
    <param-name>pageSize</param-name>
    <param-value>10</param-value>
</context-param>
<context-param>
    <param-name>startIndex</param-name>
    <param-value>0</param-value>
</context-param>
<!--Note: The above configuration information belongs to application-level configuration information. Generally, the configuration information shared in a project will be placed in the above tags. -->
<!--If your configuration information only wants to be used as a reference for a certain servlet, then you can configure it in the servlet tag and use the ServletConfig object to obtain it. -->
// Get the root path of the application (very important), because there are some places in the java source code that may require the root path of the application. This method can dynamically obtain the root path of the application.
// In the java source code, do not write down the root path of the application, because you never know what the name of the application will be when it is finally deployed.
public String getContextPath();
//String contextPath = application.getContextPath();
// Get the absolute path of the file (real path)
public String getRealPath(String path);
// Logging can also be recorded through the ServletContext object.
public void log(String message);
public void log(String message, Throwable t);
//Where are these log information recorded?
// localhost.2021-11-05.log

//What log files are there in the logs directory of the Tomcat server?
//catalina.2021-11-05.log console information of the server-side java program running.
//localhost.2021-11-05.log The log information recorded by the log method of the ServletContext object is stored in this file.
//localhost_access_log.2021-11-05.txt access log

The ServletContext object has another name: application domain (there are other domains later, such as request domain and session domain)

If all users share a piece of data, the data is rarely modified, and the amount of data is small, the data can be placed in the ServletContext application domain.

Why is data shared among all users? It doesn’t make sense if it’s not shared. Because there is only one ServletContext object. It only makes sense to put the shared data in it.

Why should the data size be small? Because if the amount of data is relatively large, it will occupy too much heap memory, and the life cycle of this object is relatively long. This object will only be destroyed when the server is shut down. Large data volumes can affect server performance. Data that takes up less memory can be considered.

Why are these shared data rarely modified, or almost never modified? If the data shared by all users involves modification operations, there will inevitably be security issues caused by thread concurrency. Therefore, the data placed in the ServletContext object is generally read-only.

The amount of data is small, shared by all users, and not modified. Putting such data in the application domain of ServletContext will greatly improve efficiency. Because the application domain is equivalent to a cache, the data placed in the cache does not need to be obtained from the database again the next time it is used, which greatly improves execution efficiency.

//Save (how to store data in the ServletContext application domain)
public void setAttribute(String name, Object value); // map.put(k, v)
// Get (how to get data from the ServletContext application domain)
public Object getAttribute(String name); // Object v = map.get(k)
// Delete (how to delete data in the ServletContext application domain)
public void removeAttribute(String name); // map.remove(k)

ps: When we write the Servlet class in the future, we will actually not directly inherit the GenericServlet class because we are a B/S structured system. This system is based on the HTTP Hypertext Transfer Protocol. In the Servlet specification, it is provided There is a class called HttpServlet, which is a Servlet class specially prepared for the HTTP protocol. The Servlet class we write must inherit HttpServlet. (HttpServlet is dedicated to the HTTP protocol.) It is more convenient to use HttpServlet to handle the HTTP protocol. Its inheritance structure:

jakarta.servlet.Servlet (interface) [Grandpa]
jakarta.servlet.GenericServlet implements Servlet (abstract class) [Son]
jakarta.servlet.http.HttpServlet extends GenericServlet (abstract class) [Sun Tzu]

The Servlet we write in the future will inherit the HttpServlet class. 

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Java Skill TreeHomepageOverview 137861 people are learning the system