Servlet基本原理与常见API方法的应用

1.Tomcat如何调用Servlet

1.1Servlet原理

Servlet是属于上层建筑,它处在应用层,它的下层有传输层,网络层,数据链路层,硬件,属于“经济基础”,毕竟下层经济基础决定上层建筑。前面说过,Servlet是一组操作HTTP的API,Tomcat可作为HTTP服务器来处理请求,这个处理请求的关键就是调用Servlet来操作HTTP给客户端做出响应。

我们所写的Servlet代码没有main方法,那他是如何运行的呢?其实是Tomcat在调用Servlet,Tomcat其实就是一个应用程序,是运行在用户态上的一个普通的Java进程。

 

当浏览器发送请求给服务器的时候,Tomcat作为HTTP Server会调用Serlvet API,然后执行我们所写的Servlet程序来处理请求。

 处理请求的过程中牵涉的不仅仅只有HTTP,还有其他层的协议,但是我们并没有感知到其他层协议的细节,只关注了应用层HTTP协议的细节,这就是协议分层好处,程序员在实现处理请求时,不必去关心应用层下面的细节。

 

1.2Tomcat的执行逻辑

为了方便描述Tomcat的执行逻辑,我们使用伪代码的形式来分析:

初始化与收尾工作,又细分为以下几部分:

1)从指定的目录中找到Servlet类,并加载。

2根据加载的结果,给这些类型创建实例。

3)创建好实例后,调用Servlet对象中的 init 方法。

4)创建TCP socket对象,监听8080端口,等待客户端来连接。

5)如果请求处理完毕,也就是处理请求的循环退出了,那Tomcat也结束了,调用 destroy 方法结束进程,但是这个环节不一定可靠,正常退出的情况下,需要在管理端口(8005)去调用 destroy ,将Tomcat关闭,但很多时候都是直接杀死进程来达到关闭的目的,此时根本来不及调用 dsetroy 方法。

class Tomcat {     // 用来存储所有的 Servlet 对象    private List<Servlet> instanceList = new ArrayList<>();    public void start() {         // 根据约定,读取 WEB-INF/web.xml 配置文件;        // 并解析被 @WebServlet 注解修饰的类        // 假定这个数组里就包含了我们解析到的所有被 @WebServlet 注解修饰的类.         Class<Servlet>[] allServletClasses = ...;        // 这里要做的的是实例化出所有的 Servlet 对象出来;        for (Class<Servlet> cls : allServletClasses) {             // 这里是利用 java 中的反射特性做的            // 实际上还得涉及一个类的加载问题,因为我们的类字节码文件,是按照约定的            // 方式(全部在 WEB-INF/classes 文件夹下)存放的,所以 tomcat 内部是            // 实现了一个自定义的类加载器(ClassLoader)用来负责这部分工作。            Servlet ins = cls.newInstance();            instanceList.add(ins);        }        // 调用每个 Servlet 对象的 init() 方法,这个方法在对象的生命中只会被调用这一次;        for (Servlet ins : instanceList) {             ins.init();        }        // 利用我们之前学过的知识,启动一个 HTTP 服务器        // 并用线程池的方式分别处理每一个 Request        ServerSocket serverSocket = new ServerSocket(8080);        // 实际上 tomcat 不是用的固定线程池,这里只是为了说明情况        ExecuteService pool = Executors.newFixedThreadPool(100);        while (true) {             Socket socket = ServerSocket.accept();            // 每个请求都是用一个线程独立支持,这里体现了我们 Servlet 是运行在多线程环境下的            pool.execute(new Runnable() {                 doHttpRequest(socket);//处理请求            });        }        // 调用每个 Servlet 对象的 destroy() 方法,这个方法在对象的生命中只会被调用这一次;        for (Servlet ins : instanceList) {             ins.destroy();        }    }    public static void main(String[] args) {         new Tomcat().start();    }}

Tomcat处理请求工作:

1)读取socket中的数据,并按照HTTP协议的格式来进行解析,获取请求。

2)判断请求是需要静态内容还是动态内容,如果是静态内容,可以在根路径上找到目的文件,返回请求

3)如果是动态文件,则需要通过URL上的一级路径与二级路径来确定通过哪一个Servlet类来进行处理,没有的话就会返回404

4)找到对应Servlet对象,调用对象里面的 service 方法,根据请求的方法来调用对应的 do... 方法

class Tomcat {     void doHttpRequest(Socket socket) {         // 参照我们之前学习的 HTTP 服务器类似的原理,进行 HTTP 协议的请求解析,和响应构建        HttpServletRequest req = HttpServletRequest.parse(socket);        HttpServletRequest resp = HttpServletRequest.build(socket);                // 判断 URL 对应的文件是否可以直接在我们的根路径上找到对应的文件,如果找到,就是静态        // 直接使用我们学习过的 IO 进行内容输出        if (file.exists()) {             // 返回静态内容            return;       }                // 走到这里的逻辑都是动态内容了                // 根据我们在配置中说的,按照 URL -> servlet-name -> Servlet 对象的链条        // 最终找到要处理本次请求的 Servlet 对象        Servlet ins = findInstance(req.getURL());                // 调用 Servlet 对象的 service 方法        // 这里就会最终调用到我们自己写的 HttpServlet 的子类里的方法了        try {        ins.service(req, resp);        } catch (Exception e) {             // 返回 500 页面,表示服务器内部错误       }   }}

service方法执行逻辑:

class Servlet {     public void service(HttpServletRequest req, HttpServletResponse resp) {         String method = req.getMethod();        if (method.equals("GET")) {             doGet(req, resp);       } else if (method.equals("POST")) {             doPost(req, resp);       } else if (method.equals("PUT")) {             doPut(req, resp);       } else if (method.equals("DELETE")) {             doDelete(req, resp);       }        ......   }}

在整个流程中,有三个关键的方法:

init

2.Servlet中关键的几个API

2.1常用方法列举

HttpServlet关键方法:

方法名称

调用时机

init</

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值