开头说两句

小刀博客: https://www.lixiang.red 小刀公众号: 程序员学习大本营

小刀这几天在追斗罗大陆,看到唐门,也突然有一种想组建类似的想法,我们有内门,有外门,有长老等等,让学习变成游戏,有想法的,或者想和小刀聊一聊的,加小刀微信吧: best396975802

学习背景


前面,我们一起学习到了tomcat对web请求的处理 https://www.lixiang.red/articles/2019/08/14/1565794504734.html 通过学习我们可以知道在对web请求进行处理时,以CoyoteAdapter.service为入口,然后经历了各级Container(Engine, Host , Context, wrapper)的pipeline 中 valve 来进行处理,到最后的时候,会经过ApplicationFilterChain到达我们的过滤器链,最后到Servlet, 这个servlet 就是最后处理请求的地方

ApplicationFilterChain


最原始的web应用,其实是web.xml和servlet的组合. 所有和web相关的配置都在web.xml里面,现在用了spring-boot 之后,我们看不到web.xml了,但并不代表他不存在了.web.xml里面的东西都是在的. 在Web整个请求的过程中,我们从过滤器链执行完之后,调用Servlet开始处理逻辑 ApplicationFilterChain的主要字段有四个, filters,pos, n , servlet filters: 当前过滤器链中有的过滤器 pos: 代表当前执行的过滤器的位置 n: 代表这个过滤器链中总共有多少个过滤器 servlet: 当过滤器执行到最后一个的时候,即pos = n 的时候,就调用servlet的实例,执行servlet方法

源码如下:
/**
     * Filters.
     */
    private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];


    /**
     * The int which is used to maintain the current position
     * in the filter chain.
     */
    private int pos = 0;


    /**
     * The int which gives the current number of filters in the chain.
     */
    private int n = 0;


    /**
     * The servlet instance to be executed by this chain.
     */
    private Servlet servlet = null;

可以看到, 在过滤器链执行结束的时候,会调用servlet.service方法

框架的通用封装方法


我们在ApplicationFilterConfig这个类中可以看到,过滤器主要是调用doFilter方法进行处理

但是在doFilter方法中,我们看到,只有一些通用的逻辑,并没有实际的处理,而是把逻辑下放到internalDoFilter里面

在tomcat源码中,对internalDoFilter做了直接实现. 在通用封装中,我们会把internalDoFilter做成一个抽象方法,然后交于子类去实现, 这样可以定义不同的子类去实现不同的逻辑.如我们以前讲的初始化的时候init方法的实现

DefaultServlet


我们在Servlet声明,都是在web.xml之中,所以我们要去web.xml里面去找,这个web应用有哪些servlet,我们找到了DefaultServlet, 其实还有一个jspServlet,这里就不展开了

同样还有配套的servletMapping ,当没有别的servlet处理请求时,就使用这个defaultServlet来处理

我们可以通过类关系图,看到DefaultServlet的继承关系

通过类关系图,他在通用的Servlet的基础之上添加了Http的处理 我们从入口service方法可以看到:

然后在父类方法中可以看到:

然后会调用实现类的doGet方法,我们回到DefaultServlet中,看看doGet方法,可以看到,实际上是对服务器资源的处理

我们细致分析下来,可以划分为以下几段,从请求资源的定位,到获取资源的属性,到获取资源的内容,到最后设置response的输出

tomcat做文件服务器


经过上面对DefaultServlet的分析,我们可以发现,他就是一个资源服务器,所以我们可以直接用tomcat做一个文件服务器,如下图所示,我们在webapps下面新建了一个文件夹

然后启动tomcat,访问我们的资源 提示: content-type

最后说两句


通过这一系列学习,我们学习了tomcat请求从入口,到最后的servlet处理,大家有什么想法,可以分享给小刀:best396975802

本篇应该是tomcat系列最后一篇了, 随着不断的深入,小刀也看到了阅读量从最开始的800多降到了400多,我知道肯定人肯定会越来越少,但是我要坚持做下去! 虽说公众号是一个快消品,通常一篇文章的生命周期也就几天, 公众号可以快消,知识不能快消. 明天开始,我们会进行mybatis系列的深入学习! 和小刀一起加油吧!!!