servlet与tomcat

1、servlet与servlet容器

 (1)servlet本质

   前方高能,请注意、注意、注意。。。重要的事情说三遍,servlet本质就是一个Java接口 ,目的在于定义一套处理网络请求的规范,如下所示:

package javax.servlet;

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

public interface Servlet {
    void init(ServletConfig arg0) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

  所有实现servlet接口的类,都要实现接口中的五个方法,其中最主要的是两个生命周期方法 init()和destroy()、处理请求的service(),即:

  • 初始化的作用;
  • 销毁后的作用;
  • 收到请求后需要做什么。

 init() 和 destroy()方法只执行一次, 即servlet的生命周期---创建和销毁,而service()方法每次有新请求到达时都会调用,即处理处理实际业务。

(2)servlet容器

  全称server applet,意为服务程序。主要作用是给上级容器(Tomcat)提供doGet()和doPost()等方法。其生命周期实例化、初始化、调用、销毁受控于Tomcat容器。

 (3)request/response

  request:浏览器发起http请求,请求到达tomcat,经tomcat封装成了request对象(将请求头、请求地址、请求参数等进行了封装);

  response:浏览器发起http请求到达tomcat容器时,产生一个空的response对象,http请求数据经过servlet处理,将处理后结果封装成response对象,经过tomcat处理后,组装成HTTP响应返回给浏览器。

 (4)web容器

  可以部署多个WEB应用程序的环境。Tomcat容器属于web容器的一种,web容器还包括weblogic容器、JBoss容器等;而Tcomcat、webLogic等包含servlet容器。

  

  注:三层架构实质是对servlet的拆分,目的在于解耦合。

2、tomcat

(1)tomcat程序入口main()

  main方法是启动一个java程序的入口,任何程序都会有自己的main方法,tomcat是一个WEB容器,也不例外:

//TODO 以下为伪代码,目的在于说明tomcat执行原理
public static void main(String args[]) {
       //TODO 初始化运行环境,载入需要的jar包,读取conf/server.xml,生成相应的运行对象:
        if (daemon == null) {
            Bootstrap bootstrap = new Bootstrap();
            try {
                bootstrap.init();//初始化守护进程
            } catch (Throwable t) {
                return;
            }
            daemon = bootstrap;
        } 
   //TODO 装载,开始运行。
        try {
            String command = "start";
            if (command.equals("startd")) {
                daemon.load(args);
                daemon.start();//启动Tomcat
            } else if (command.equals("stopd")) {
                args[args.length - 1] = "stop";
                daemon.stop();//停止Tomcat守护进程
            } 
        } catch (Throwable t) {
        }
    }

(2)tomcat创建的resques和response

 

(3)tomcat对servlet接口的实现

   逻辑层级关系:

    abstract class GenericServlet implements Servlet, ServletConfig,Serializable

    abstract class HttpServlet extends GenericServlet

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);
        }
    }
    
    //TODO doHead doPut doDelete

    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 errMsg;
        if (method.equals("GET")) {
            errMsg = this.getLastModified(req);
            if (errMsg == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException arg8) {
                    ifModifiedSince = -1L;
                }

                if (ifModifiedSince < errMsg / 1000L * 1000L) {
                    this.maybeSetLastModified(resp, errMsg);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        }  else if (method.equals("POST")) {
            this.doPost(req, resp);
        } else {
            String errMsg1 = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[] { method };
            errMsg1 = MessageFormat.format(errMsg1, errArgs);
            resp.sendError(501, errMsg1);
        }
    }

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

        this.service(request, response);
    }
}
(4)web容器的部署

  部署的过程其实就是解析 xml 实例化对象,并触发和处理容器及组件对应生命周期事件的过程。在 Tomcat 中,一个 Context 实例就代表一个 Web 应用程序,所以部署的第一步就是创建一个 StandardContext 对象。在创建时 HostConfig 首先会查找 Context 描述符,它可能在两个位置:

  • $CATALINA_BASE/conf/<engine>/<host>/[webappname].xml
  • $CATALINA_BASE/webapps/webappname/META_INF/context.xml

  如果两个位置都不存在此文件,则使用 conf/context.xml 默认配置。

  Context 实例化后会触发 init 和 start 生命周期事件:

  • init - 会创建用于解析 context.xml 和 web.xml 的工具 Digester 的实例,并解析context.xml
  • start - 则会根据 web.xml 部署描述符实例化 Servlet、Filter、Listener 等 Web 组件

  感谢阅读,参考了不少大佬资料,如需转载,请注明出处 https://www.cnblogs.com/huyangshu-fs/p/13173474.html

原文地址:https://www.cnblogs.com/huyangshu-fs/p/13173474.html