韩非囚秦
——独善其身者,难成大事也。

导航

 

  Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

  servlet是单例多线程的。也就是说,在堆内存中只有一份servlet对象。对于每一次http请求,servlet容器会自动调用servlet对象的service()方法去开辟线程,在这个线程中根据已有的url-class关系对这个request进行处理。

  servlet需要跑在web服务器上。这里使用apache-tomcat-9.0.12。

  servlet流程图:

一、Servlet接口类

  1.Servlet接口类及其方法

  public interface Servlet

  Defines methods that all servlets must implement.

  A servlet is a small Java program that runs within a Web server. Servlets receive and respond to requests from Web clients, usually across HTTP, the HyperText Transfer Protocol.

  To implement this interface, you can write a generic servlet that extends javax.servlet.GenericServlet or an HTTP servlet that extends javax.servlet.http.HttpServlet.

This interface defines methods to initialize a servlet, to service requests, and to remove a servlet from the server. These are known as life-cycle methods and are called in the following sequence:

    1.The servlet is constructed, then initialized with the init method.

    2.Any calls from clients to the service method are handled.

    3.The servlet is taken out of service, then destroyed with the destroy method, then garbage collected and finalized.

  In addition to the life-cycle methods, this interface provides the getServletConfig method, which the servlet can use to get any startup information, and the getServletInfo method, which allows the servlet to return basic information about itself, such as author, version, and copyright.

Method Summary
 void destroy()
          Called by the servlet container to indicate to a servlet that the servlet is being taken out of service.
 ServletConfig getServletConfig()
          Returns a ServletConfig object, which contains initialization and startup parameters for this servlet.
 String getServletInfo()
          Returns information about the servlet, such as author, version, and copyright.
 void init(ServletConfig config)
          Called by the servlet container to indicate to a servlet that the servlet is being placed into service.
 void service(ServletRequest req, ServletResponse res)
          Called by the servlet container to allow the servlet to respond to a request.

  Servlet特性:

    1.Servlet是单例多线程的,一个Servlet实例就是一次请求;
    2.一个Servlet实例只会执行一次无参构造方法和init方法,并且是在第一次访问时执行;
    3.一个Servlet实例只会执行一次destroy方法,并且在应用停止时销毁;
    4.一个Servlet实例可以执行多个service,每当有用户请求发生,就会执行一次service方法;
    5.Servlet是单例(单例模式)多线程的,所以为了线程安全,不为其设置成员变量,以避免线程间篡改成员变量;
    6.默认情况下,Servlet在web容器启动时是不会被实例化的;

  2.Servlet生命周期测试

package com.servlets;

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * servlet的生命周期
 * @author apple
 * @see http://tool.oschina.net/apidocs/apidoc?api=javaEE5
 * @see javax.servlet.Servlet
 * @see javax.servlet.ServletConfig
 */
public class ServletLifeCircleDemo implements Servlet {

    public ServletLifeCircleDemo() {
        System.out.println(" 1.执行构造方法......");
    }

    @Override
    public void init(ServletConfig init) throws ServletException {
        System.out.println(" 2.初始化......");
    }

    @Override
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        System.out.println(" 3.接受并处理请求......");

        // 两个方法
        ServletConfig servletConfig = this.getServletConfig();
        System.out.println(servletConfig); // 读取配置信息

        String servletInfo = this.getServletInfo();
        System.out.println(servletInfo);
    }

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

    @Override
    public void destroy() {
        System.out.println(" 销毁:  destroy");
    }

}
Servlet接口方法测试
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <servlet>
    <servlet-name>Servlet-Life-Circle</servlet-name>
    <servlet-class>com.servlets.ServletLifeCircleDemo</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Servlet-Life-Circle</servlet-name>
    <url-pattern>/servletLifeCircle</url-pattern>
  </servlet-mapping>
</web-app>
web.xml

  启动并访问http://localhost:8080/servletLifeCircle。后台依次打印上述信息。也就是说,整个流程是constructor实例化servlet --> 执行init函数 --> 执行service方法。在整个服务关闭或停止时,会最后执行destroy方法。这里getServletConfig()和getServletInfo()返回null是因为重写了接口设定返回值为null。

  service是自动调用的,对外提供的请求和相应处理的方法。

 1.执行构造方法......
 2.初始化......
 3.接受并处理请求......
null
null
服务器打印结果

二、ServletConfig接口类

  1.ServletConfig接口类及其方法

  public interface ServletConfig

  A servlet configuration object used by a servlet container to pass information to a servlet during initialization.

Method Summary
 String getInitParameter(String name)
          Returns a String containing the value of the named initialization parameter, or null if the parameter does not exist.
 Enumeration getInitParameterNames()
          Returns the names of the servlet's initialization parameters as an Enumeration of String objects, or an empty Enumeration if the servlet has no initialization parameters.
 ServletContext getServletContext()
          Returns a reference to the ServletContext in which the caller is executing.
 String getServletName()
          Returns the name of this servlet instance.

  servlet容器会在实例化Servlet对象后,立刻调用init()方法,前面可以看到Servlet.init()传入的参数就是ServletConfig对象。ServletConfig负责读取web.xml内容,并交给init进行初始化配置。

  this.config.getInitParameter和this.config.getInitParameterNames是获取单个url请求的配置信息。它返回的是String或者Enumeration。

  this.config.getServletContext()是获取全局的配置信息。它返回的是一个ServletContext对象,该对象有一堆方法。

  2.ServletConfig演示

package com.servlets;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.*;

/**
 * @see http://tool.oschina.net/apidocs/apidoc?api=javaEE5, ServletConfig
 * ServletConfig提供了四个方法,它主要用于读取配置信息
 * 一个Servlet对应一个ServletConfig
 */
public class ServletConfigDemo implements Servlet {

    private ServletConfig config;
    @Override
    public void init(ServletConfig config) throws ServletException {
        // servlet容器将ServletConfig传递了进来,为了使用config,在初始化的时候把它赋给成员变量
        this.config = config;
        System.out.println("config = " + this.config);
    }

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

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        // 在service中测试config的方法,总共就四个
        // 1.测试getServletName()
        String servletName = config.getServletName();
        System.out.println("servlet name = " + servletName);

        // 2.测试getServletContext()
        ServletContext servletContext = config.getServletContext();
        System.out.println("servlet context = " + servletContext);

        // 3.测试getInitParameterNames()方法
        Enumeration<String> names = config.getInitParameterNames();// 获取所有的配置的name
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            String value = config.getInitParameter(name); // 4.测试getInitParameter()方法
            System.out.println("init-param: name=" + name + ", " + "value=" + value);
        }
    }

    @Override
    public String getServletInfo() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

}
ServletConfig测试
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <servlet>
    <servlet-name>Servlet-Config</servlet-name>
    <servlet-class>com.servlets.ServletConfigDemo</servlet-class>
    <init-param>
      <param-name>name</param-name>
      <param-value>Jan</param-value>
    </init-param>
    <init-param>
      <param-name>age</param-name>
      <param-value>20</param-value>
    </init-param>
    <init-param>
      <param-name>gender</param-name>
      <param-value>female</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>Servlet-Config</servlet-name>
    <url-pattern>/servletConfig</url-pattern>
  </servlet-mapping>
</web-app>
web.xml

  servletConfig的配置在web.xml中是由<init-param>标签实现的,<init-param>标签需要写在<servlet>标签中。因此,我们可以给每一个url视图都写上请求前的配置。但是url请求彼此之间是访问不到各自的servletConfig的。

  启动服务并访问http://localhost:8080/servletConfig,可以看到如下信息。

servlet name = Servlet-Config
servlet context = org.apache.catalina.core.ApplicationContextFacade@202520aa
init-param: name=gender, value=female
init-param: name=name, value=Jan
init-param: name=age, value=20
服务器打印结果

三、ServletContext

  既然有了每个url请求的servletConfig配置。就有所有servlet的全局配置,其里面放置的键值对都能够被所有url请求共享,这个接口就是ServletContext。

  前面可以看到,ServletConfig对象是由servlet容器自动传递给init函数的。ServletConfig包含的三个方法:getInitParameter()和getInitParameters()、getServletContext()。前两个是单个的url请求配置,由web.xml中的<servlet>标签下的<init-param>标签设置。后一个是全局的属性配置,由web.xml中的<context-param>标签直接配置。

  1.ServletContext接口类及其方法

  public interface ServletContext

  Defines a set of methods that a servlet uses to communicate with its servlet container, for example, to get the MIME type of a file, dispatch requests, or write to a log file.

  There is one context per "web application" per Java Virtual Machine. (A "web application" is a collection of servlets and content installed under a specific subset of the server's URL namespace such as /catalog and possibly installed via a .war file.)

  In the case of a web application marked "distributed" in its deployment descriptor, there will be one context instance for each virtual machine. In this situation, the context cannot be used as a location to share global information (because the information won't be truly global). Use an external resource like a database instead.

  The ServletContext object is contained within the ServletConfig object, which the Web server provides the servlet when the servlet is initialized

Method Summary
 Object getAttribute(String name)
          Returns the servlet container attribute with the given name, or null if there is no attribute by that name.
 Enumeration getAttributeNames()
          Returns an Enumeration containing the attribute names available within this servlet context.
 ServletContext getContext(String uripath)
          Returns a ServletContext object that corresponds to a specified URL on the server.
 String getContextPath()
          Returns the context path of the web application.
 String getInitParameter(String name)
          Returns a String containing the value of the named context-wide initialization parameter, or null if the parameter does not exist.
 Enumeration getInitParameterNames()
          Returns the names of the context's initialization parameters as an Enumeration of String objects, or an empty Enumeration if the context has no initialization parameters.
 int getMajorVersion()
          Returns the major version of the Java Servlet API that this servlet container supports.
 String getMimeType(String file)
          Returns the MIME type of the specified file, or null if the MIME type is not known.
 int getMinorVersion()
          Returns the minor version of the Servlet API that this servlet container supports.
 RequestDispatcher getNamedDispatcher(String name)
          Returns a RequestDispatcher object that acts as a wrapper for the named servlet.
 String getRealPath(String path)
          Returns a String containing the real path for a given virtual path.
 RequestDispatcher getRequestDispatcher(String path)
          Returns a RequestDispatcher object that acts as a wrapper for the resource located at the given path.
 URL getResource(String path)
          Returns a URL to the resource that is mapped to a specified path.
 InputStream getResourceAsStream(String path)
          Returns the resource located at the named path as an InputStream object.
 Set getResourcePaths(String path)
          Returns a directory-like listing of all the paths to resources within the web application whose longest sub-path matches the supplied path argument.
 String getServerInfo()
          Returns the name and version of the servlet container on which the servlet is running.
 Servlet getServlet(String name)
          Deprecated. As of Java Servlet API 2.1, with no direct replacement.

This method was originally defined to retrieve a servlet from a ServletContext. In this version, this method always returns null and remains only to preserve binary compatibility. This method will be permanently removed in a future version of the Java Servlet API.

In lieu of this method, servlets can share information using the ServletContext class and can perform shared business logic by invoking methods on common non-servlet classes.

 String getServletContextName()
          Returns the name of this web application corresponding to this ServletContext as specified in the deployment descriptor for this web application by the display-name element.
 Enumeration getServletNames()
          Deprecated. As of Java Servlet API 2.1, with no replacement.

This method was originally defined to return an Enumeration of all the servlet names known to this context. In this version, this method always returns an empty Enumeration and remains only to preserve binary compatibility. This method will be permanently removed in a future version of the Java Servlet API.

 Enumeration getServlets()
          Deprecated. As of Java Servlet API 2.0, with no replacement.

This method was originally defined to return an Enumeration of all the servlets known to this servlet context. In this version, this method always returns an empty enumeration and remains only to preserve binary compatibility. This method will be permanently removed in a future version of the Java Servlet API.

 void log(Exception exception, String msg)
          Deprecated. As of Java Servlet API 2.1, use log(String message, Throwable throwable) instead.

This method was originally defined to write an exception's stack trace and an explanatory error message to the servlet log file.

 void log(String msg)
          Writes the specified message to a servlet log file, usually an event log.
 void log(String message, Throwable throwable)
          Writes an explanatory message and a stack trace for a given Throwable exception to the servlet log file.
 void removeAttribute(String name)
          Removes the attribute with the given name from the servlet context.
 void setAttribute(String name, Object object)
          Binds an object to a given attribute name in this servlet context.

   一个web应用对应一个ServletContext对象,所有的servlet(这里指url)共享这个对象。

  ServletContext对象既是全局的,包含了一些信息,又提供一个域属性空间,供我们用来设置一些参数和值。即setAttribute、getAttribute、removeAttribute。

  2.ServletContext演示

package com.servlets;


import javax.servlet.*;
import java.io.IOException;

/**
 * @see http://tool.oschina.net/apidocs/apidoc?api=javaEE5, ServletContext
 * 一个应用对应一个servletContext,servletContext的别名又叫做application context
 * 所有的servlet共享一个servletContext
 * servletContext内的属性是全局性的,称为域属性空间
 */
public class ServletContextDemo2 implements Servlet {

    private ServletConfig config;

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        this.config = servletConfig;

    }

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        ServletContext context = config.getServletContext();

        // 3.测试servletContext的域属性设置信息
        String mobile = (String) context.getAttribute("mobile");
        System.out.println("Context params: " + "mobile=" + mobile);
        String email = (String) context.getAttribute("email");
        System.out.println("Context params: " + "email=" + email);

        // 4.重置或删除域属性的值
        context.setAttribute("mobile", "7654321");
        context.removeAttribute("email");

        // 5.测试getContextPath()方法
        String contextPath = context.getContextPath();// 应用的名称,也就是servlet-app,这里不知道为什么没有显示
        System.out.println("contextPath=" + contextPath);
        String realPath = context.getRealPath("/images");
        System.out.println("realPath=" + realPath);

    }

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

    @Override
    public void destroy() {

    }
}
ServletContextDemo2
package com.servlets;


import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;

/**
 * @see http://tool.oschina.net/apidocs/apidoc?api=javaEE5, ServletContext
 * 一个应用对应一个servletContext,servletContext的别名又叫做application context
 * 所有的servlet共享一个servletContext
 * servletContext内的属性是全局性的,是由web.xml中的context-param配置的
 * 此外它有一个全局的域属性,称为域属性空间,在域属性里可以设置属性值
 */
public class ServletContextDemo1 implements Servlet {

    private ServletConfig config;

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        this.config = servletConfig;

    }

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        // 测试context的方法
        ServletContext context = config.getServletContext();

        // 1.测试context-param的配置信息ServletContext
        Enumeration<String> names = context.getInitParameterNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            String value = context.getInitParameter(name);
            System.out.println(name + " = " + value);
        }

        // 2.设置域属性,先访问servletContext,设置了这个属性;再访问servletConfig,发现已经有了这个属性
        context.setAttribute("email", "xxx@qq.com");
        context.setAttribute("mobile", "13041234123");

    }

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

    @Override
    public void destroy() {

    }
}
ServletContextDemo1
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">

  <context-param>
    <param-name>author</param-name>
    <param-value>Zhang</param-value>
  </context-param>
  <context-param>
    <param-name>date</param-name>
    <param-value>2018-09-30</param-value>
  </context-param>
  <servlet>
    <servlet-name>Servlet-Context-1</servlet-name>
    <servlet-class>com.servlets.ServletContextDemo1</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Servlet-Context-1</servlet-name>
    <url-pattern>/servletContext1</url-pattern>
  </servlet-mapping>
  <servlet>
    <servlet-name>Servlet-Context-2</servlet-name>
    <servlet-class>com.servlets.ServletContextDemo2</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Servlet-Context-2</servlet-name>
    <url-pattern>/servletContext2</url-pattern>
  </servlet-mapping>

</web-app
web.xml

  启动服务,访问路径即结果如下:

// 第一次访问http://localhost:8080/servletContext2
Context params: mobile=null
Context params: email=null
contextPath=
realPath=/Users/apple/eclipse-workspace/servlet-partOne/out/artifacts/servletLifeCircle_war_exploded/images

// 访问http://localhost:8080/servletContext1
date = 2018-09-30
author = Zhang

// 第二次访问http://localhost:8080/servletContext2
Context params: mobile=13041234123
Context params: email=xxx@qq.com
contextPath=
realPath=/Users/apple/eclipse-workspace/servlet-partOne/out/artifacts/servletLifeCircle_war_exploded/images
服务器访问及打印结果

  这里Context Path=空是因为IDEA中的Deployment对话框下的Application context设置成了 "/",输入"/servlet-parthOne"会有相对路径。

四、将Servlet写成HttpServlet

  1.通过抽象类将service和Servlet进行解耦

  如果直接每次继承Servlet类然后在service写业务逻辑太危险了。init()、getServletConfig()都需要自己去写。

  此时可以写一个抽象类继承Servlet,在该抽象类中实现其余四个方法,只将service定义为抽象方法。子类直接继承这个抽象,并且只需重写service方法就好了。

import javax.servlet.*;
import java.io.IOException;

/**
 * "适配器设计模式": 在子类和接口类添加一层抽象类。抽象类实现接口类定义的部分方法,从而子类不必实现所有的接口类方法。
 */
public abstract class GenericServlet implements Servlet {
    // 同样把config存到成员变量里,子类通过getServletConfig方法来获取config
    private ServletConfig config;
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        this.config = servletConfig;
    }
    @Override
    public ServletConfig getServletConfig() {
        return config;
    }

    // 把service写为抽象方法,并把该实现类定义为抽象类。在此抽象类中实现其它的接口方法,而不实现service这个抽象方法。
    @Override
    public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException;


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

    @Override
    public void destroy() {

    }
}
GenericServlet

  子类继承GenericServlet。

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class SubServletDemo extends GenericServlet {
    // 子类只需要实现service就行了
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        System.out.println("执行servletDemo");

        ServletConfig config = this.getServletConfig(); // 获取config
        // System.out.println(config);
        System.out.println(
                "name=" + config.getInitParameter("name") +
                ", age=" + config.getInitParameter("age")
        );

    }
}
SubServletDemo

 

  2.重写servletConfig方法

  在上例中,config.getInitParameter()等价于this.getServletConfig().getInitParameter(),由于GenericService没有实现这个方法,所以又需要访问init中传入的config的方法。为了保持各个service的独立性,应该让GenericService中继承servletConfig并重写其中的四个方法。

import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;


public abstract class GenericServlet implements Servlet, ServletConfig {
    // 同样把config存到成员变量里,子类通过getServletConfig方法来获取config
    private ServletConfig config;
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        this.config = servletConfig;
        init();// 启动子类的init初始化设置
    }

    // "模板方法设计模式"
    // 让子类用这个init
    public void init(){}

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

    // 把service写为抽象方法,并把该实现类定义为抽象类。在此抽象类中实现其它的接口方法,而不实现service这个抽象方法。
    @Override
    public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException;


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

    @Override
    public void destroy() {

    }

    // 直接继承重写ServletConfig的四个方法
    @Override
    public String getServletName() {
        return config.getServletName();
    }

    @Override
    public ServletContext getServletContext() {
        return config.getServletContext();
    }

    @Override
    public String getInitParameter(String s) {
        return config.getInitParameter(s);
    }

    @Override
    public Enumeration<String> getInitParameterNames() {
        return config.getInitParameterNames();
    }
}
GenericServlet

  同时,为了不破坏init(ServletConfig config)函数,再重载一个init()给子类用即可。这样能保证在serlvet实例化时,同样使子类(service处理类)也能够自由的初始化。

  3.GET请求和POST请求解耦

  前面SubServletDemo继承了自己写的抽象父类GenericServlet(继承了Servlet和ServletConfig),并且实现了父类service方法。如果需要根据GET请求和POST请求分开处理,需要改写成这样:

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoginServlet extends GenericServlet{
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("login HttpServletBase ......");

        // 获取请求方式
        HttpServletRequest request = (HttpServletRequest) servletRequest; // 强转
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String method = request.getMethod();
        System.out.println("method=" +  method);

        // 定义get和post方法,用来调用不同的处理方式
        if("GET".equals(request)){
            doGet(request, response);
        }else if("POST".equals(response)){
            doPost(request, response);

        }

    }

    private void doPost(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("POST 提交......");
    }

    private void doGet(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("GET 提交");
    }

}
SubServletDemo

 

  显然这种写法有些陋。我们进行如下改写,并将SubServletDemo重命名为HttpServlet。

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/*
   "模板设计模式":以后只用doPost或者doGet来处理get请求或者post请求
 */
public class HttpServlet extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("login HttpServletBase ......");

        // 获取请求方式
        HttpServletRequest request = (HttpServletRequest) servletRequest; // 强转
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        service(request, response);

    }

    public void service(HttpServletRequest request, HttpServletResponse response){
        String method = request.getMethod();
        System.out.println("method=" + method);

        if ("GET".equals(request)) {
            doGet(request, response);
        } else if ("POST".equals(response)) {
            doPost(request, response);
        }
    }

    //
    public void doPost(HttpServletRequest request, HttpServletResponse response) {

    }
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
    }
}
HttpServlet

  最后写一个只有GET请求和POST请求的处理类,让它继承HttpServlet:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginServlet extends HttpServlet{

    public void doPost(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("POST 提交......");
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("GET 提交");
    }

}
SubServletDemo

五、GenericServlet和HttpServlet

  上一节手动写了一遍GenericServlet.class和HttpServlet.class。实际上,在serlvet中导入javax.servlet.http.HttpServlet直接使用即可:

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


/*
    直接使用javax.HttpServletBase.http.HttpServletBase
 */
public class LoginServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("GET 提交......");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("POST 提交......");
    }
}
SubServletDemo

  1.GenericServlet类

  public abstract class GenericServletextends Objectimplements Servlet, ServletConfig, Serializable

  Defines a generic, protocol-independent servlet. To write an HTTP servlet for use on the Web, extend HttpServlet instead.

  GenericServlet implements the Servlet and ServletConfig interfaces. GenericServlet may be directly extended by a servlet, although it's more common to extend a protocol-specific subclass such as HttpServlet.

  GenericServlet makes writing servlets easier. It provides simple versions of the lifecycle methods init and destroy and of the methods in the ServletConfig interface. GenericServlet also implements the log method, declared in the ServletContext interface.

  To write a generic servlet, you need only override the abstract service method.

Method Summary
 void destroy()
          Called by the servlet container to indicate to a servlet that the servlet is being taken out of service.
 String getInitParameter(String name)
          Returns a String containing the value of the named initialization parameter, or null if the parameter does not exist.
 Enumeration getInitParameterNames()
          Returns the names of the servlet's initialization parameters as an Enumeration of String objects, or an empty Enumeration if the servlet has no initialization parameters.
 ServletConfig getServletConfig()
          Returns this servlet's ServletConfig object.
 ServletContext getServletContext()
          Returns a reference to the ServletContext in which this servlet is running.
 String getServletInfo()
          Returns information about the servlet, such as author, version, and copyright.
 String getServletName()
          Returns the name of this servlet instance.
 void init()
          A convenience method which can be overridden so that there's no need to call super.init(config).
 void init(ServletConfig config)
          Called by the servlet container to indicate to a servlet that the servlet is being placed into service.
 void log(String msg)
          Writes the specified message to a servlet log file, prepended by the servlet's name.
 void log(String message, Throwable t)
          Writes an explanatory message and a stack trace for a given Throwable exception to the servlet log file, prepended by the servlet's name.
abstract  void service(ServletRequest req, ServletResponse res)
          Called by the servlet container to allow the servlet to respond to a request.

   与第四节写的GenericServlet几乎一致。

  2.HttpServlet类

  public abstract class HttpServlet extends GenericServlet implements Serializable

  Provides an abstract class to be subclassed to create an HTTP servlet suitable for a Web site. A subclass of HttpServlet must override at least one method, usually one of these:

  • doGet, if the servlet supports HTTP GET requests

  • doPost, for HTTP POST requests

  • doPut, for HTTP PUT requests

  • doDelete, for HTTP DELETE requests

  • init and destroy, to manage resources that are held for the life of the servlet

  • getServletInfo, which the servlet uses to provide information about itself

  There's almost no reason to override the service method. service handles standard HTTP requests by dispatching them to the handler methods for each HTTP request type (the doXXX methods listed above).

  Likewise, there's almost no reason to override the doOptions and doTrace methods.

  Servlets typically run on multithreaded servers, so be aware that a servlet must handle concurrent requests and be careful to synchronize access to shared resources. Shared resources include in-memory data such as instance or class variables and external objects such as files, database connections, and network connections. See the Java Tutorial on Multithreaded Programming for more information on handling multiple threads in a Java program.

Method Summary
protected  void doDelete(HttpServletRequest req, HttpServletResponse resp)
          Called by the server (via the service method) to allow a servlet to handle a DELETE request.
protected  void doGet(HttpServletRequest req, HttpServletResponse resp)
          Called by the server (via the service method) to allow a servlet to handle a GET request.
protected  void doHead(HttpServletRequest req, HttpServletResponse resp)
          Receives an HTTP HEAD request from the protected service method and handles the request.
protected  void doOptions(HttpServletRequest req, HttpServletResponse resp)
          Called by the server (via the service method) to allow a servlet to handle a OPTIONS request.
protected  void doPost(HttpServletRequest req, HttpServletResponse resp)
          Called by the server (via the service method) to allow a servlet to handle a POST request.
protected  void doPut(HttpServletRequest req, HttpServletResponse resp)
          Called by the server (via the service method) to allow a servlet to handle a PUT request.
protected  void doTrace(HttpServletRequest req, HttpServletResponse resp)
          Called by the server (via the service method) to allow a servlet to handle a TRACE request.
protected  long getLastModified(HttpServletRequest req)
          Returns the time the HttpServletRequest object was last modified, in milliseconds since midnight January 1, 1970 GMT.
protected  void service(HttpServletRequest req, HttpServletResponse resp)
          Receives standard HTTP requests from the public service method and dispatches them to the doXXX methods defined in this class.
 void service(ServletRequest req, ServletResponse res)
          Dispatches client requests to the protected service method.

   上节只实现了doGet和doPost,但是逻辑都是相同的。

 

posted on 2018-10-12 17:39  一只火眼金睛的男猴  阅读(2147)  评论(0编辑  收藏  举报