GenericServlet principle: Servlet; ServletConfig

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

    • service method is the most commonly used method, and other methods do not need to be used in most cases. In this way, other methods appear redundant and the code is ugly.
    • Solution: write a "middleman" to enable the middleman to implement the Servlet interface, and the Servlet class we write will inherit the "middleman"

Servlet

  • Version one
    • Create an abstract class GenericServlet to implement the Servlet interface, and set the methods required by the subclass as abstract methods.
    • The subclass inherits the GenericServletTest abstract class and implements the corresponding abstract method.
    • It should be noted that the init method (non Abstract) of the parent class will also be executed
  • Version 1 problem: the subclass inherits GenericServletTest and implements its abstract method, and the init method of the parent class will also be implemented. The init method in the parent GenericServlet class is executed.
    The subclass object is created by tomcat, and the init method is also called by Tomcat. Of course, the parameters of ServletConfig type that need to be passed in the init method are also created by Tomcat. It should be considered that the ServletConfig object must be used in the service method
  • Solution to ensure that ServletConfig can be used in other methods, set ServletConfig as a member variable
  • Version 2
    • Set member variable servletConfig
    • Considering that the variable is created by Tomcat, and the servletConfig of the member variable is null at first, how to assign a value?
      -Version 2 problem: the above method can solve the problem of obtaining servletConfig by other methods. However, if a subclass wants to override the init method, the init method of the parent class may be destroyed, resulting in the failure to obtain servletConfig and the member variable is still empty.
  • Solution: the init method of the parent class is modified by final, that is, the init method of the parent class cannot be rewritten, which eliminates the problem that rewriting the init method leads to empty member variables
  • After the problem is solved: what if the subclass really needs to override the init method?
  • Solution: write a parameterless init class, make the subclass rewrite the parameterless init class, and overload the method
  • Version 3
  • "Middleman code"
package adapter;
import jakarta.servlet.*;
import java.io.IOException;

/**    Understand the principle of GenericServlet
 *  Set "middleman" -- GenericServletTest
 *      After the loginServlet class in the servlet package inherits the servlet class, we need to implement all methods of the servlet, but when we use it, we find that not all methods are required
 *Implementation, then some methods in the loginServlet class appear redundant.
 *      At this point, we create an abstract class GenericServlet to implement the Servlet interface, and set the method to be written as an abstract method
 *      Inherit the loginServlet class from the GenericServletTest abstract class and implement the corresponding abstract method.
 */
public abstract class GenericServletTest implements Servlet {
    private ServletConfig servletConfig;
    /**
     *      The subclass loginServlet inherits GenericServletTest and implements its abstract method. The init method of the parent class will also be implemented. The init method in the parent GenericServlet class is executed.
     *      loginServlet The object of is created by tomcat, and the init method is also called by Tomcat. Of course, the parameters of ServletConfig type that need to be passed in the init method are also Tomcat
     *Created.
     *      It should be considered that the ServletConfig object must be used in the service method. To ensure that ServletConfig can be used in other methods, set ServletConfig as a member variable
     * @param servletConfig
     * @throws ServletException
     */
    @Override
    public final void init(ServletConfig servletConfig) throws ServletException {
        //The servletConfig parameter created by Tomcat is passed in and assigned to the member variable servletConfig through the equal sign.
        this.servletConfig =servletConfig;
        /**
         *After we have determined the "middleman", some subclasses need to override the init method
         *  When a subclass overrides the init method, the init method of the parent class may be broken
         *     Because the init method in the parent class can obtain the servletConfig parameter from the parameters created by Tomcat and further assign it to the member variable
         *     If it is destroyed, the variable of member variable servletConfig type may be empty, so it cannot be used in other methods.
         *     Solution: the init method of the parent class does not allow the child class to override. To avoid errors, add the final keyword on the init method of the parent class
         *  However, when subclasses do need to override init methods, you can write another init method -- method overloading
         */
        this.init();
    }

    /**
     * This method is overridden by subclasses
     */
    public void init(){

    }

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

    /**
     * Abstract method
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse)
            throws ServletException, IOException ;



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

    @Override
    public void destroy() {

    }
}

  • Subclass code
package adapter;

import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;

import java.io.IOException;

public class loginServlet extends GenericServletTest{

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("");
        //Use the servletConfig object in the loginServlet subclass
        ServletConfig config = this.getServletConfig();
    }
}

  • GenericServlet source code: public abstract class GenericServlet implements Servlet, ServletConfig, Serializable
  • So far, it is clear why GenericServlet implements Servlet

ServletConfig

  • As mentioned above, we need to consider that the ServletConfig object must be used in the service method. What is ServletConfig?
  • jakarta.servlet.ServletConfig. ServletConfig is a member of the Servlet specification.
  • ServletConfig is an interface
    • The Tomcat server implements the ServletConfig interface, and a servlet object has a corresponding ServletConfig object. Different servlets have different ServletConfig objects
    • The ServletConfig object is created by the Tomcat server
  • Use of ServletConfig
    • The ServletConfig object is the configuration information object of the servlet object
    • Information contained in ServletConfig object: configuration information of tags in web.xml file
    • Tomcat automatically wraps the configuration information of the web.xml file into the ServletConfig object.
      • This explains: ServletConfig method. getServletName();
  • Thinking: since the tag configuration information in the web.xml file can be packaged into the ServletConfig object, can we plug something else into it and get it through ServletConfig.

  • The answer is yes. By combining the four methods of ServletConfig, one of which is getInitParameterNames(), you can know what is plugged - initialization parameters

  • java.util.Enumeration<java.lang.String> getInitParameterNames()
    java.lang.String getInitParameter(java.lang.String name)
    The above two methods can obtain initialization parameters

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">
    <servlet>
        <servlet-name>config</servlet-name>
        <servlet-class>javaWeb.servlet.configTest.ConfigTestServlet</servlet-class>
        <!--to configure Servlet Object initialization information-->
        <init-param>
            <param-name>driver</param-name>
            <param-value>com.mysql.cj.jdbc.Driver</param-value>
        </init-param>
        <init-param>
            <param-name>url</param-name>
            <param-value>jdbc:mysql://localhost:3306/yiyu</param-value>
        </init-param>
        <init-param>
            <param-name>user</param-name>
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>123123</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>config</servlet-name>
        <url-pattern>/test</url-pattern>
    </servlet-mapping>
</web-app>
public class ConfigTestServlet extends GenericServlet {
    @Override
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        //Get ServletConfig object
        ServletConfig config = this.getServletConfig();
        //Output object
        PrintWriter out=response.getWriter();
        out.print("ServletConfig Object——"+config);

        out.print("<br>"+"<servlet-name>"+config.getServletName()+"<servlet-name>");
        // Obtain < init param > < / init param > initialization parameters through the ServletConfig object method
        Enumeration<String> initParameterNames= config.getInitParameterNames();
        while(initParameterNames.hasMoreElements()){
            String name = initParameterNames.nextElement();
            //config.getInitParameter("") gets vlaue by name
            String diver = config.getInitParameter(name);
            out.print("<br>"+name+"="+diver);
        }
    }
}
  • GenericServlet source code: public abstract class GenericServlet implements Servlet, ServletConfig, Serializable
  • So far, you can know what ServletConfig is and that GenericServlet inherits ServletConfig, because the Servlet class we write needs to inherit GenericServlet, that is, the method of ServletConfig can be called directly by this.

Tags: Java Tomcat server

Posted on Sun, 05 Dec 2021 02:12:20 -0500 by waylon999