为何要有 Servlet ,什么是 Servlet 容器,什么是 Web 容器?

本文已收录至 https://github.com/yessimida/yes ,这里有个人全部文章分类汇总,欢迎 star!java

如下代码相信你们都很熟悉,大学时学 Java Web 都写过这样的代码。git

从第一次接触 Servlet 到以后的很长一段时间内,我都没理解 Servlet 是个什么玩意?github

为何要有 Servlet ?web

为何要有 Servlet 容器?面试

啥又是 Web 容器、HTTP 服务器?算法

今儿我们就来盘盘,而且从中来看看架构和框架的设计套路。浏览器

看完以后可能对接口、抽象会有进一步的认识。服务器

来,上车!微信

正文

首先浏览器发起 HTTP 请求,像早期的时候只会请求一些静态资源,这时候须要一个服务器来处理 HTTP 请求,而且将相应的静态资源返回。架构

这个服务器叫 HTTP 服务器。

简单点说就是解析请求,而后得知须要服务器上面哪一个文件夹下哪一个名字的静态文件,找到返回便可。

而随着互联网的发展,交互愈加得重要,单纯的静态文件知足不了需求。

业务变得复杂,须要咱们编写代码来处理诸多业务。

须要根据 HTTP 请求调用不一样的业务逻辑来响应,可是咱们的业务代码不能跟 HTTP 服务器耦合起来。

总不能在 HTTP 服务器的具体实现里面来作判断到底须要调用哪一个业务类吧?

这就把非业务和业务强相关了。

因此须要作一层抽象,将 HTTP 的解析和具体的业务隔离。

本质上的需求就是根据 HTTP 请求找到对应的业务实现类而后执行逻辑再返回。

业务千千万,因此须要规定一个接口,因此业务类都实现这个接口这样才好对接。

这就是接口的含义,就像 USB。

这个接口就是 Servlet,固然这是最狭义的解释。

Servlet 实际上是 Server Applet,全称 Java Servlet,指的是用Java 编写的服务端程序。

其实指代的是实现 Servlet 接口的那些业务类。

这就是 Servlet 的由来。

而 Servlet 容器其实就是管理和加载这些 Servlet 类的,拿到 HTTP 请求以后找到对应的 Servlet 类这就是 Servlet 容器要作的事情。

看到这是否是以为还能再抽一层?由于这好像也和具体的业务实现不要紧?

是的,还能抽一层。

不必把 Servlet 容器作的事情和具体的业务耦合起来,业务反正照着 Servlet 接口实现就行,这样 Servlet 容器就能够加载它和管理它。

把请求和哪一个 Servlet 对应关系也抽象出来,就是 web.xml 了,我们在配置里面告诉 Servlet 容器对应关系便可。

我图中的业务实现其实对应的就是咱们日常的 war 包,这就是业务和 Servlet 容器的解耦。

想必你也听过 Servlet 规范,其实 Servlet 接口和 Servlet 容器这一整套包括目录命名啊啥的合起来就叫 Servlet 规范。

全部相关的中间件按照 Servlet 规范实现,咱们也按 Servlet 规范来实现业务代码,这样咱们就能在不一样场景选择不一样的 Web 中间件。

反正规范的目的就是为了对接方便,减小对接成本。

至此 HTTP 服务器、Servlet 、Servlet 容器想必都清晰了。

而 Web 容器其实就是 HTTP 服务器 + Servlet 容器,由于单单 Servlet 容器没有解析 HTTP 请求、通讯等相关功能。

因此把 Tomcat、Jetty 等实现包含了 HTTP 服务器和 Servlet 容器的功能,称之为 Web 容器。

从咱们的分析一层一层的剥离,一层一层的抽象,相信你对 Web 有了更进一步的认识,我再画个 Tomcat 的分析图,应该就很清晰了。

从上面的一步步分析能够看出:其实架构的设计就是一系列相关的抽象。

先是抽象出 HTTP 服务,用来通讯和解析协议。

再由于业务的复杂,为了避免和 HTTP 服务耦合又抽象了一层 Servlet。

由 Servlet 加载和管理 Servlet ,来控制请求转发到指定的 Servlet 实现类。

而后咱们安心的开发业务便可。

由于抽象因此灵活易扩展,好比如今是 HTTP1.1 服务,能够换成 HTTP 2。

如今用 Tomcat 来做为 Servlet 容器,也能够换成 Jetty。

如今用原生的实现 Servlet 来作业务,也能够换成 SpringMVC。

随意变动,由于都抽象出来了,就很好替换,只要遵循约定的接口实现便可。

框架设计的一个套路

看完了架构设计的套路,再说说框架套路。

接口和抽象类。

全部中间件设计必用的套路,固然咱们本身的代码也会这样用。

定义一个接口来约定一些动做,能作啥作啥。

而后再定义一个抽象类来实现这个接口,用来实现一些通用的逻辑,作到代码的复用。

而后再搞一些经常使用的实现类继承抽象类,方便开发者的使用。

剩下的就留给开发者自行扩展便可。

而后抽象类都会使用模板方法,也就是定义执行的流程,具体实现逻辑由子类自行实现。

这就是必用的套路。

接口约束、抽象类代码复用、实现经常使用实现类方便使用、剩下的自行扩展。

拿 Servlet 举例,首先定义 Servlet 接口。

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

而后搞了个通用抽象类 GenericServlet,不过这个抽象类逻辑比较简单。

public abstract class GenericServlet implements Servlet, ServletConfig,
        java.io.Serializable {
  ................省略一些.............
   @Override
    public ServletConfig getServletConfig() {
        return config;
    }
    @Override
    public ServletContext getServletContext() {
        return getServletConfig().getServletContext();
    }
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }
................省略一些.....................
}

而后搞了个经常使用的 HttpServlet 继承了 GenericServlet。

public abstract class HttpServlet extends GenericServlet {

    private static final long serialVersionUID = 1L;

    private static final String METHOD_DELETE = "DELETE";
    private static final String METHOD_HEAD = "HEAD";
    private static final String METHOD_GET = "GET";
  ....................
}

套路就是这么个套路,以后面试官问你接口和抽象类的问题,相信你也能答出来了。

最后

套路你们应该都 GET 到了。

想必你们都听过“计算机科学中的每一个问题均可以用一间接层解决”。

是的,基本上全部问题抽象一层都能解决。

若是一层不够,那就两层。

欢迎加我好友进行深刻地交流,备注「进群」,拉你进交流&内推群。

平日的面试题遇到难处,或者看某个知识点翻遍全网的资料仍是感受很模糊、不透彻,能够私聊我,给我留言。

遇到合适的我会整理写出一篇文章,我不会的去请教别人也给整出来。

那种工做遇到很细节的场景的仍是别了,这种问你上司比较合适:)

欢迎关注个人公众号【yes的练级攻略】,更多硬核文章等你来读。

巨人的肩膀

《深刻拆解Tomcat & Jetty》 李号双


微信搜索【yes的练级攻略】,关注 yes,回复【123】一份20W字的算法刷题笔记等你来领,从一点点到亿点点,咱们下篇见。
我的文章汇总:https://github.com/yessimida/yes 欢迎 star !

相关文章
相关标签/搜索