(小白必看)Servlet、GenericServlet与HttpServlet的关系以及它们的运行过程

servlet是什么

servlet是一个接口,servlet的实现类就可以被前端访问,继而处理一些前端请求

servlet的方法

servlet一共有5个方法:
1、init:初始化方法
2、getServletConfig:获取servletConfig对象的
3、service:提供服务的方法
4、getServletInfo:获取servlet的一些信息、版本、作者等等…
5、destroy:销毁方法

servlet的实现类必须要重写这5个方法

public interface Servlet {
     

    public void init(ServletConfig config) throws ServletException;
    
    public ServletConfig getServletConfig();
    
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
	
    public String getServletInfo();
    
    public void destroy();
}

servlet的生命周期

1、init:初始化方法 ------只执行一次

2、service:提供服务的方法--------提供服务(可以执行多次)
*每一次访问servlet时,service方法都会被调用一次

3、destroy:销毁方法-------服务器正常关闭被销毁(执行一次)

servlet的使用

1、创建一个servlet的实现类Demo01Servlet

public class Demo01Servlet implements Servlet {
     
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
     

    }

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
     
    	//处理前端请求的逻辑代码
        System.out.println("servlet来咯");
    }

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

    @Override
    public void destroy() {
     

    }
}

2、配置servlet

2.1、在web.xml中配置
	注意:servlet-class  标签中定义的是类的全限定类名(包名+类名),
	如Demo01Servlet的全限定类名为cn.itCate.web.servlet.Demo01Servlet
	 <servlet>
        <servlet-name>demo1</servlet-name>
        <servlet-class>cn.itCate.web.servlet.Demo01Servlet</servlet-class>

    </servlet>
    <servlet-mapping>
        <servlet-name>demo1</servlet-name>
        <url-pattern>/demo1</url-pattern>
    </servlet-mapping>
2.2、注解配置
	servlet3.0支持注解配置,注解配置比在web.xml文件这种配置方便多了只需在类上加入一个注解
	即可
@WebServlet("/demo01")//添加一个注解,就可以不用在web.xml中进行配置了
public class Demo01Servlet implements Servlet {
     
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
     

    }

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
     
        //处理前端请求的逻辑代码
        System.out.println("servlet来咯");
    }

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

    @Override
    public void destroy() {
     

    }
}

servlet的运行过程

(小白必看)Servlet、GenericServlet与HttpServlet的关系以及它们的运行过程_第1张图片

当一个请求来请求Demo01Servlet时,服务器主要做以下两件事情:

一、通过访问路径中 /demo01找到全限定类名cn.itCate.web.servlet.Demo01Servlet
具体步骤:
1、通过访问路径/demo01找到 servlet-mapping中的 url-pattern
2、servlet-mapping中的servlet-name 找到servlet标签中的servlet-name
3、找到servlet-class的全限定类名cn.itCate.web.servlet.Demo01Servlet

二、通过反射创建Demo01Servlet对象,并且执行service方法
具体步骤:
1、通过全限定类名找到对应的Demo01Servlet字节码文件(也就是Demo01Servlet.class文件)
2、JVM将Demo01Servlet字节码文件加载到内存中,并创建一个对应的class类对象
3、通过操作class类对象创建一个Demo01Servlet对象
4、通过Demo01Servlet对象执行service方法

GenericServlet

每次写一个servlet的实现类都必须重写这5个方法,实在是太麻烦了,因此GenericServlet抽象类继承了Servlet,并且实现了其他4个方法,只剩一个抽象方法service

public abstract class GenericServlet implements Servlet, ServletConfig, java.io.Serializable
{
     
   
    public void destroy() {
     
    }
    
    public ServletConfig getServletConfig() {
     
	return config;
    }
 
    public String getServletInfo() {
     
	return "";
    }


    public void init(ServletConfig config) throws ServletException {
     
	this.config = config;
	this.init();
    }

    public void init() throws ServletException {
     

    }
    
	//service方法仍然是抽象方法,因此子类需要重写此方法
    public abstract void service(ServletRequest req, ServletResponse res)
	throws ServletException, IOException;
    
}

GenericServlet的使用

创建一个GenericServlet的子类demo02Servlet

@WebServlet("/demo2")//使用注解配置
public class demo02Servlet extends GenericServlet {
     

	//只需重写service方法
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
     
    	//处理前端请求的逻辑代码
        System.out.println("genderricservlet来了");
    }
}

这里配置使用了注解配置,当然也可以在web.xml文件中配置,看个人喜好

 <servlet>
        <servlet-name>demo2</servlet-name>
        <servlet-class>cn.itCate.web.servlet.Demo02Servlet</servlet-class>

    </servlet>
    <servlet-mapping>
        <servlet-name>demo2</servlet-name>
        <url-pattern>/demo2</url-pattern>
    </servlet-mapping>

GenericServlet的运行过程

GenericServlet的运行过程和Servlet的运行过程一样,当有请求来请求Demo02Servlet时服务器会:
通过反射创建Demo02Servlet对象,并且执行service方法

HttpServlet

继承了GenericServlet的抽象类(开发常用),HttpServlet是专门用来处理http请求的一个抽象类,下面来看一些它的主要方法

public abstract class HttpServlet extends GenericServlet {
     
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_get_not_supported");
        if (protocol.endsWith("1.1")) {
     
            resp.sendError(405, msg);
        } else {
     
            resp.sendError(400, msg);
        }

    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_post_not_supported");
        if (protocol.endsWith("1.1")) {
     
            resp.sendError(405, msg);
        } else {
     
            resp.sendError(400, msg);
        }

    }

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
     
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
     
                this.doGet(req, resp);
            } else {
     
                long ifModifiedSince;
                try {
     
                    ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException var9) {
     
                    ifModifiedSince = -1L;
                }

                if (ifModifiedSince < lastModified / 1000L * 1000L) {
     
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
     
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
     
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
     
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
     
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
     
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
     
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
     
            this.doTrace(req, resp);
        } else {
     
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{
     method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }

    }

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
     
        HttpServletRequest request;
        HttpServletResponse response;
        try {
     
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)res;
        } catch (ClassCastException var6) {
     
            throw new ServletException(lStrings.getString("http.non_http"));
        }

        this.service(request, response);
    }
}

HttpServlet四个主要方法:
1、service(ServletRequest req, ServletResponse res) , 此方法是重写父类GenericServletservice方法
2、service(HttpServletRequest req, HttpServletResponse resp),此方法是重载上一个方法,这两个方法的参数不同
3、doPost(HttpServletRequest req, HttpServletResponse resp),处理post请求
4、doGet(HttpServletRequest req, HttpServletResponse resp),处理get请求

1、service(ServletRequest req, ServletResponse res)方法
首先,先来查看service(ServletRequest req, ServletResponse res)方法

 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
     
        HttpServletRequest request;
        HttpServletResponse response;
        try {
     
            request = (HttpServletRequest)req;//ServletRequest --> HttpServletRequest 
            response = (HttpServletResponse)res;//ServletResponse --> HttpServletResponse
        } catch (ClassCastException var6) {
     
            throw new ServletException(lStrings.getString("http.non_http"));
        }

        this.service(request, response);//跳转到service(HttpServletRequest req, HttpServletResponse resp)方法
    }

此方法主要是将参数ServletRequest req 和 ServletResponse res强制转换成 HttpServletRequest request 和 HttpServletResponse response,之后就跳转到service(HttpServletRequest req, HttpServletResponse resp)方法。

注意:HttpServletRequest继承自ServletRequest,HttpServletResponse继承自ServletResponse,它们都是接口。HttpServletRequest相比较于ServletRequest多了一些关于http协议的方法,强制转换的原因也是为了使用这些http协议的方法

2、service(HttpServletRequest req, HttpServletResponse resp)

 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        String method = req.getMethod();//获取请求的方式
        long lastModified;
        if (method.equals("GET")) {
      //如果请求方式为get,则跳转到doGet方法
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
     
                this.doGet(req, resp);
            } else {
     
                long ifModifiedSince;
                try {
     
                    ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException var9) {
     
                    ifModifiedSince = -1L;
                }

                if (ifModifiedSince < lastModified / 1000L * 1000L) {
     
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
     
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
     
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
     
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
     
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
     
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
     
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
     
            this.doTrace(req, resp);
        } else {
     
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{
     method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }

    }

此方法主要是获取请求的方式,并执行对应的方法。
String method = req.getMethod();
getMethod()就是HttpServletRequest独有的方法,此方法是获取请求的方式。
若请求方式为GET,则执行doGet(req, resp)方法:
this.doGet(req, resp);
若请求方式为POST,则执行doPost(req, resp)方法:
this.doPost(req, resp);

HttpServlet的使用

HttpServlet实现了service(ServletRequest req, ServletResponse res)方法,因此HttpServlet的子类就不必再去重写service方法了,只需要重写doget和dopost方法,在方法内编写对应的代码即可。
创建一个HttpServlet的实现类demo03servlet方法,使用注解进行配置

@WebServlet(value = "/demo3")//注解配置
public class demo03servlet extends HttpServlet {
     

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
    	
        //处理get请求逻辑代码
        System.out.println("doget..");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //处理post请求逻辑代码
        System.out.println("dopost...");
    }
}

HttpServlet的运行过程

1、当有一个请求来请求demo03servlet时我们都知道服务器会通过反射创建一个demo03servlet对象

2、创建的demo03servlet对象会调用service(ServletRequest req, ServletResponse res)方法,也就是demo03servlet对象.service(ServletRequest req, ServletResponse res)

3、demo03servlet类中并没有service(ServletRequest req, ServletResponse res)方法,于是就会去调用父类也就是HttpServlet中的service(ServletRequest req, ServletResponse res)方法

4、service(ServletRequest req, ServletResponse res)方法主要是将参数ServletRequest req 和 ServletResponse res强制转换成 HttpServletRequest request 和 HttpServletResponse response , 转换完成后,执行service(HttpServletRequest req, HttpServletResponse resp)方法

5、在service(HttpServletRequest req, HttpServletResponse resp)方法中,先是获取了请求方式:String method = req.getMethod();
若请求方式为GET,则执行doGet(req, resp)方法:
this.doGet(req, resp);
若请求方式为POST,则执行doPost(req, resp)方法:
this.doPost(req, resp);
注意这里的 this 关键字指的是demo03servlet对象,因为是它调用了service方法。因此在执行 this.doGet(req, resp) 或者 this.doPost(req, resp) 时,执行的是我们在demo03servlet类中定义 doGet 和 doPost 方法,当 this 调用demo03servlet类中没有定义的方法时,才会去父类中寻找。

(小白必看)Servlet、GenericServlet与HttpServlet的关系以及它们的运行过程_第2张图片

你可能感兴趣的:(java,servlet,tomcat,http)