Servlet

很多同学可能跟我一样始终没有搞清楚到底什么是 Servlet,什么是 Servlet 容器。网上看了很多帖子,或许人家说的很清楚,但是自己的那个弯弯就是拐不过来。

想了很久说一下自己的理解。

Java web 开发中为啥要有 Servlet 呢?是否可以不要。

web开发的本质就一句话:客户端和服务器交换数据。于是你使用 Java 的 Socket 套接字进行编程,去处理客户端来的 tcp 请求,经过编解码处理读取请求体,获取请求行,然后找到请求行对应的处理逻辑步入服务器的处理中,处理完毕把对应的结果返回给当前的 Socket 链接,响应完毕,关闭 Socket。

以上过程,你有没有发现其实是两个部分:

  1. 建立连接,传输数据,关闭连接,你肯定知道这些步骤不是你所开发的web服务去处理的,而是tomcat容器帮你做了这些事情。

  2. 拿到请求行之后去找对应的 url 路由,这一部分是谁做的呢?在如今 SpringBoot 横行的时代,去配置化已经成为趋势,编程越来越简单导致的后果就是越来越难以理解事物最开始的样子。还记得 SpringMVC工程中的 web.xml文件吗?是否还记得在web.xml中有这么一段配置呢:

<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring/SpringMVC-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

Spring 的核心就是一个 Servlet,它拦截了所有的请求,将请求交给 DispatcherServlet 去处理。

我们再来问一遍,Servlet 到底是什么,它就是一段处理 web 请求的逻辑,并不是很高深的东西。

再来看 Java 中的 Servlet,它只是一个接口:


package javax.servlet; import java.io.IOException; 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 接口规定请求从容器到达 web 服务端的规范,最重要的三个步骤是:

  1. init():初始化请求的时候要做什么;
  2. service():拿到请求的时候要做什么;
  3. destory():处理完请求销毁的时候要做什么。

所有实现 Servlet 的实现方都是在这个规范的基础上进行开发。那么 Servlet 中的数据是从哪里来的呢?答案就是 Servlet 容器。容器才是真正与客户端打交道的那一方。Servlet容器只有一个,而 Servlet 可以有多个。常见的Servlet容器Tomcat,它监听了客户端的请求端口,根据请求行信息确定将请求交给哪个Servlet 处理,找到处理的Servlet之后,调用该Servlet的 service() 方法,处理完毕将对应的处理结果包装成ServletResponse 对象返回给客户端。

Servlet 容器

上面说过,Servlet 只是一个处理请求的应用程序,光有Servlet是无法运行起来的,需要有一个 main 方法去调用你的这段 Servlet 程序才行。所以这里出现了Servlet 容器的概念。Servlet容器的主要作用是:

  1. 建立连接;
  2. 调用Servlet处理请求;
  3. 响应请求给客户端;
  4. 释放连接;

这上面的四步,如果是你来设计的话是否可以用一个模板方法搞定,1,3,4都是固定的步骤,不会因为请求不同而有很大的变化。2却会因为对应的请求不同需要业务逻辑自己去实现不同的处理。所以这里抽象出来了 Servlet,Servlet想怎么玩就怎么玩,这是你自己的事情。容器帮你做的是你不想做的脏活累活。

另外,既然叫做容器肯定是能装多个Servlet,并且可以管理Servlet的声明周期。这些功能应该是容器必备的。

上面提到了 web.xml 中的 DispatcherServlet,它是 Spring 中定义的一个 Servlet,实现了 Servlet 接口,本质也是一个 Servlet。只是它是 HttpServlet 的继承者,主要处理 http 请求。所以 Spring 程序本质是就是一个 Servlet。SpringMVC 帮你做了本该你去实现的逻辑,你看不到并不代表它不是。

好啦,以上通俗的语言解释了什么是 Servlet,什么是 Servlet 容器,以及 Servlet 和 Servlet 容器之间的关系。

Tomcat

Tomcat是啥呢?本质上是一个 Servlet 容器,实现了对 Java Servlet 规范的支持。同时 Tomcat 也提供了处理HTTP请求的能力,所以也可以作为一个Web服务器。了解到Tomcat有 Web服务器和 Servlet容器的功能,那么 Tomcat总体是如何设计的呢?我们来看一张简图:

Java web 应用如果部署到 Tomcat 中,一个Tomcat就表示一个服务。一个 Server 服务器可以包含多个 Service 服务,Tomcat 默认的 Service 服务是 Catalina,而一个 Service 服务可以包含多个连接器,因为 Tomcat 支持多种网络协议,包括 HTTP/1.1、HTTP/2、AJP 等等,一个 Service 服务还会包括一个容器,容器外部会有一层 Engine 引擎所包裹,负责与处理连接器的请求与响应,连接器与容器之间通过 ServletRequest 和 ServletResponse 对象进行交流。

Tomcat容器的设计提现在一个核心文件中:server.xml。这个文件充分展示了Tomcat的高度抽象设计:

<Server port="8005" shutdown="SHUTDOWN">
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"/>
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"> </Host>
</Engine>
</Service>
</Server>

其中:

  1. Server 组件是管理 tomcat 实例的组件,可以监听一个端口,从此端口上可以远程向该实例发送 shutdown 关闭命令。

  2. Service 组件是一个逻辑组件,用于绑定 connector 和 container,有了 service 表示可以向外提供服务,就像是一般的 daemon 类服务的 service。可以认为一个 service 就启动一个JVM,更严格地说,一个 engine 组件才对应一个 JVM (定义负载均衡时,jvmRoute 就定义在 Engine 组件上用来标识这个 JVM ),只不过 connector 也工作在 JVM 中。

    小故事

    是否关注到 Service name = Catalina,实际上 Tomcat 的前身就是 Catalina,这是一个岛的名字,而

    Catalina 只是一个 Servlet 容器,为Servlet和 JavaServer Pages(JSP)实现了Sun Microsystems的规范。

    Tomcat 的作者 詹姆斯·邓肯·戴维森,Sun Microsystems 的软件架构师在后来 Sun Microsystems 向 Apache Software Foundation 捐赠该项目中发挥了重要作用。当时他认为许多开源项目都有与 O'Reilly 相关的书籍,封面上有动物,所以他想以动物命名。后来这位老哥想到了猫

    Servlet 和 Servlet容器的更多相关文章

    1. Java Servlet与Web容器之间的关系

      自从计算机软件开发进入网络时代,就开始涉及到通讯问题.在客户/服务器(也叫C/S应用)时期,每个软件都有自己的客户端和服务器端软件.并且客户端和服务器端之间的通讯协议差别也很大.后来随着互联网的发展, ...

    2. servlet和web容器之间的关系

      Java是一种动态加载和运行的语言.也就是说当应用程序持有一个类的地址(CLASSPATH)和名称(包名和类名)的情况下,可以在程序运行期 间任何时候加载这个类,并创建和使用该类的对象.Servlet ...

    3. 【Java】servlet和servlet 容器

      servlet不是线程安全的,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,所以你的项目中如果只有一个servlet,那么web容器就只会创建一个实例 ...

    4. 对于Servlet、Servlet容器以及一个Servlet容器-Tomcat

      Servlet.Servlet容器等内容讲解 转载自http://blog.csdn.net/iAm333 对于Servlet.Servlet容器以及一个Servlet容器-Tomcat这些概念讲解的 ...

    5. JavaWeb开发之详解Servlet及Servlet容器

      自JavaEE诞生伊始,Servlet容器和Servlet技术,就构成了JavaEE应用的核心,配合其它组件,它们完善了Java企业级开发的全套解决方案.小到一个静态博客网站,大到分布式的集群应用,都 ...

    6. Servlet、Servlet容器等内容讲解

      转载自http://blog.csdn.net/iAm333 对于Servlet.Servlet容器以及一个Servlet容器-Tomcat这些概念讲解的挺清晰的,转载下 之前在开源中国看到一篇文章& ...

    7. JAVA网络编程基本功之Servlet与Servlet容器

      Servlet与Servlet容器关系 Servlet 比较这两个的区别, 就得先搞清楚Servlet 的含义, Servlet (/ˈsərvlit/ ) 翻译成中文就是小型应用程序或者小服务程序, ...

    8. Servlet和Servlet容器

      Java Servlet(Java服务器小程序)是一个基于Java技术的Web组件,运行在服务器端,它由Servlet容器所管理,用于生成动态的内容, Servlet是平台独立的Java类,编写一个S ...

    9. [Servlet] 初识Servlet

      什么是Servlet? 定义 Servlet的全称是 Server Applet,顾名思义,就是用 Java 编写的服务器端程序. Servlet 是一个 Java Web开发标准,狭义的Servle ...

    随机推荐

    1. 深度学习中正则化技术概述(附Python代码)

      欢迎大家关注我们的网站和系列教程:http://www.tensorflownews.com/,学习更多的机器学习.深度学习的知识! 磐石 介绍 数据科学研究者们最常遇见的问题之一就是怎样避免过拟合. ...

    2. POJ 1797 最短路变形所有路径最小边的最大值

      题意:卡车从路上经过,给出顶点 n , 边数 m,然后是a点到b点的权值w(a到b路段的承重),求卡车最重的重量是多少可以从上面经过. 思路:求所有路径中的最小的边的最大值.可以用迪杰斯特拉算法,只需 ...

    3. 【翻译】.NET 5 Preview2发布

      在4月2日,发布了.NET 5.0 Preview2,这次发布对一些功能和性能做了相关的改进,同时后面也会实施5.0版本更多的功能,其中一些功能目前也dotnet/designs在.NET 5 Pre ...

    4. 好记性-烂笔头:JDK8流操作

      1):对象 List<User> 转 Map<String,Object> 案例如下: public class User { private Integer id; priv ...

    5. POJ旅行商问题——解题报告

      旅行商问题 总时间限制: 1000ms 内存限制: 65536kB 描述 某国家有n(1<=n<=10)座城市,给定任意两座城市间距离(不超过1000的非负整数).一个旅行商人希望访问每座 ...

    6. CSS盒子模型(boeder)+浮动(float)+定位(position)

      盒子的上下层:margin--background-color--background-image--padding--content--border(最外层) 计算一个盒子宽 =  内容的宽(wid ...

    7. vue中的生命周期事件和钩子函数

      vue实例有一个完整的生命周期,也就是从开始创建.初始化数据.编译模板.挂载Dom.渲染->更新->渲染.卸载等一系列过程,我们称这是vue的生命周期.通俗的将就是vue实例从创建到销毁的 ...

    8. CodeForces 506B/505D Mr. Kitayuta's Technology

      Portal:http://codeforces.com/problemset/problem/506/B http://codeforces.com/problemset/problem/505/D ...

    9. O - 推箱子 HDU - 1254(bfs_box + bfs_man)

      O - 推箱子 HDU - 1254 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能 ...

    10. PTA数据结构与算法题目集(中文) 7-31

      PTA数据结构与算法题目集(中文)  7-31 7-31 笛卡尔树 (25 分)   笛卡尔树是一种特殊的二叉树,其结点包含两个关键字K1和K2.首先笛卡尔树是关于K1的二叉搜索树,即结点左子树的所有 ...