JAVA WEB中,Servlet与Servlet容器有何本质不同?
- 内容介绍
- 文章标签
- 相关推荐
本文共计3170个文字,预计阅读时间需要13分钟。
Servlet 是一种运行在服务器端的 Java 程序,用于处理网络请求。Servlet 容器负责管理 Servlet 的生命周期,包括初始化、处理请求和销毁。Servlet 容器通常指的是服务器软件,如 Apache Tomcat,它为 Servlet 提供运行环境。
Servlet
很多同学可能跟我一样始终没有搞清楚到底什么是 Servlet,什么是 Servlet 容器。网上看了很多帖子,或许人家说的很清楚,但是自己的那个弯弯就是拐不过来。
想了很久说一下自己的理解。
Java web 开发中为啥要有 Servlet 呢?是否可以不要。
web开发的本质就一句话:客户端和服务器交换数据。于是你使用 Java 的 Socket 套接字进行编程,去处理客户端来的 tcp 请求,经过编解码处理读取请求体,获取请求行,然后找到请求行对应的处理逻辑步入服务器的处理中,处理完毕把对应的结果返回给当前的 Socket 链接,响应完毕,关闭 Socket。
以上过程,你有没有发现其实是两个部分:
建立连接,传输数据,关闭连接,你肯定知道这些步骤不是你所开发的web服务去处理的,而是tomcat容器帮你做了这些事情。
拿到请求行之后去找对应的 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 服务端的规范,最重要的三个步骤是:
- init():初始化请求的时候要做什么;
- service():拿到请求的时候要做什么;
- destory():处理完请求销毁的时候要做什么。
所有实现 Servlet 的实现方都是在这个规范的基础上进行开发。那么 Servlet 中的数据是从哪里来的呢?答案就是 Servlet 容器。容器才是真正与客户端打交道的那一方。Servlet容器只有一个,而 Servlet 可以有多个。常见的Servlet容器Tomcat,它监听了客户端的请求端口,根据请求行信息确定将请求交给哪个Servlet 处理,找到处理的Servlet之后,调用该Servlet的 service() 方法,处理完毕将对应的处理结果包装成ServletResponse 对象返回给客户端。
Servlet 容器
上面说过,Servlet 只是一个处理请求的应用程序,光有Servlet是无法运行起来的,需要有一个 main 方法去调用你的这段 Servlet 程序才行。所以这里出现了Servlet 容器的概念。Servlet容器的主要作用是:
- 建立连接;
- 调用Servlet处理请求;
- 响应请求给客户端;
- 释放连接;
这上面的四步,如果是你来设计的话是否可以用一个模板方法搞定,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 相关的书籍,封面上有动物,所以他想以动物命名。后来这位老哥想到了猫🐈。他认为这只动物代表着某种可以自己生存的东西,当2003年 O'Reilly 发行带有雪豹的 Tomcat 书籍时,他希望看到动物封面的愿望终于实现了。
3. Connector 组件是监听组件,它有四个作用:
- 开启监听套接字,监听外界请求,并和客户端建立 TCP 连接;
- 使用 protocolHandler 解析请求中的协议和端口等信息,如 http 协议、AJP 协议;
- 根据解析到的信息,使用 processer 将分析后的请求转发给绑定的 Engine;
- 接收响应数据并返回给客户端。
上面的 server.xml 配置我们能看到有两个 Connector。
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"/>
这个 Connector 表示通过 8080 端口使用 HTTP/1.1版本的协议来访问 Tomcat。
我们知道 80 端口是为 HTTP(HyperText Transport Protocol) 即 超文本传输协议 开放的,主要用于万维网传输信息的协议。而我们一般在 Tomcat 中监听的是一个非 80 端口。那为啥不直接在 Tomcat 中写上 80 端口,即所有 HTTP 请求都可以收到。这是因为在生产环境中,一般不会直接暴露原始服务给外网,一方面是安全性,另一方面是 负载均衡处理 和 静态资源处理。所以会在原始服务上加一层代理,代理来监听 80 端口,再将服务暴露端口的请求转发给对应服务。
第二个 Connector:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
这个 Connector 监听 8009 端口的 AJP 协议连接。AJP 协议负责和其他的 HTTP 服务器(如 Apache )建立连接;在把 Tomcat 与其他 HTTP 服务器集成时,就需要用到这个连接器。之所以使用 Tomcat 和其他服务器集成,是因为 Tomcat 可以用作 Servlet/JSP 容器,但是对静态资源的处理速度较慢,不如 Apache 和 IIS 等 HTTP 服务器。因此常常将 Tomcat 与 Apache 等集成,前者作 Servlet 容器,后者处理静态资源,而 AJP 协议便负责 Tomcat 和 Apache 的连接。
Container 表示一类组件,在配置文件(server.xml)中没有体现出来。它包含4个容器类组件:Engine容器、Host容器、Context容器 和 wrapper容器。
Engine 容器用于从 Connector 组件处接收已建立的 TCP 连接,还用于接收客户端发送的 HTTP 请求并分析请求,然后按照分析的结果将相关参数传递给匹配出的虚拟主机。Engine 还用于指定默认的虚拟主机。
Host 容器定义虚拟主机,对应了服务器中一个网络名实体(如”www.baidu.com”,或IP地址”23.0.32.1”)。为了使用户可以通过域名连接 Tomcat 服务器,这个域名应该在域名服务器已经注册过。
比如上例中的配置:
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
name=localhost 表示当前对应的请求是本机,这是因为已经配置了Nginx代理的原因,如果没有配置代理,那么这里就必须是真实的IP 或者域名。注意后面的 appBase,appBase表示当前 web资源所在的目录。
Context 容器主要是根据 path 和 docBase 获取一些信息,将结果交给其内的 wrapper 组件进行处理(它提供wrapper运行的环境,所以它叫上下文context)。一般来说,都采用默认的标准 wrapper 类,因此在 Context 容器中几乎不会出现 wrapper 组件。
wrapper 容器对应 Servlet 的处理过程。它开启 Servlet 的生命周期,根据 Context 给出的信息以及解析 web.xml 中的映射关系,负责装载相关的类,初始化 servlet 对象 init()、执行 servlet 代码 service() 以及服务结束时 servlet 对象的销毁 destory()。
根据上面描述的 tomcat 组件体系结构,处理请求的大致过程其实很容易推导出来:
Client(request)-->Connector-->Engine-->Host-->Context-->Wrapper(response data)-->Connector(response header)-->Client
可以看到宏观上 Tomcat 设计的真是非常精妙,层叠式的容器设计呈现出一种美感。Connector 和 Container 两大组件涵盖主要功能,这种复合组件化的设计思想我们是否可以应用在业务系统中呢。右面有空继续分析 Tomcat 中各个模块的设计。
以上就是JAVA WEB中Servlet和Servlet容器的区别的详细内容,更多关于JAVA WEB Servlet和Servlet容器的资料请关注易盾网络其它相关文章!
本文共计3170个文字,预计阅读时间需要13分钟。
Servlet 是一种运行在服务器端的 Java 程序,用于处理网络请求。Servlet 容器负责管理 Servlet 的生命周期,包括初始化、处理请求和销毁。Servlet 容器通常指的是服务器软件,如 Apache Tomcat,它为 Servlet 提供运行环境。
Servlet
很多同学可能跟我一样始终没有搞清楚到底什么是 Servlet,什么是 Servlet 容器。网上看了很多帖子,或许人家说的很清楚,但是自己的那个弯弯就是拐不过来。
想了很久说一下自己的理解。
Java web 开发中为啥要有 Servlet 呢?是否可以不要。
web开发的本质就一句话:客户端和服务器交换数据。于是你使用 Java 的 Socket 套接字进行编程,去处理客户端来的 tcp 请求,经过编解码处理读取请求体,获取请求行,然后找到请求行对应的处理逻辑步入服务器的处理中,处理完毕把对应的结果返回给当前的 Socket 链接,响应完毕,关闭 Socket。
以上过程,你有没有发现其实是两个部分:
建立连接,传输数据,关闭连接,你肯定知道这些步骤不是你所开发的web服务去处理的,而是tomcat容器帮你做了这些事情。
拿到请求行之后去找对应的 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 服务端的规范,最重要的三个步骤是:
- init():初始化请求的时候要做什么;
- service():拿到请求的时候要做什么;
- destory():处理完请求销毁的时候要做什么。
所有实现 Servlet 的实现方都是在这个规范的基础上进行开发。那么 Servlet 中的数据是从哪里来的呢?答案就是 Servlet 容器。容器才是真正与客户端打交道的那一方。Servlet容器只有一个,而 Servlet 可以有多个。常见的Servlet容器Tomcat,它监听了客户端的请求端口,根据请求行信息确定将请求交给哪个Servlet 处理,找到处理的Servlet之后,调用该Servlet的 service() 方法,处理完毕将对应的处理结果包装成ServletResponse 对象返回给客户端。
Servlet 容器
上面说过,Servlet 只是一个处理请求的应用程序,光有Servlet是无法运行起来的,需要有一个 main 方法去调用你的这段 Servlet 程序才行。所以这里出现了Servlet 容器的概念。Servlet容器的主要作用是:
- 建立连接;
- 调用Servlet处理请求;
- 响应请求给客户端;
- 释放连接;
这上面的四步,如果是你来设计的话是否可以用一个模板方法搞定,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 相关的书籍,封面上有动物,所以他想以动物命名。后来这位老哥想到了猫🐈。他认为这只动物代表着某种可以自己生存的东西,当2003年 O'Reilly 发行带有雪豹的 Tomcat 书籍时,他希望看到动物封面的愿望终于实现了。
3. Connector 组件是监听组件,它有四个作用:
- 开启监听套接字,监听外界请求,并和客户端建立 TCP 连接;
- 使用 protocolHandler 解析请求中的协议和端口等信息,如 http 协议、AJP 协议;
- 根据解析到的信息,使用 processer 将分析后的请求转发给绑定的 Engine;
- 接收响应数据并返回给客户端。
上面的 server.xml 配置我们能看到有两个 Connector。
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"/>
这个 Connector 表示通过 8080 端口使用 HTTP/1.1版本的协议来访问 Tomcat。
我们知道 80 端口是为 HTTP(HyperText Transport Protocol) 即 超文本传输协议 开放的,主要用于万维网传输信息的协议。而我们一般在 Tomcat 中监听的是一个非 80 端口。那为啥不直接在 Tomcat 中写上 80 端口,即所有 HTTP 请求都可以收到。这是因为在生产环境中,一般不会直接暴露原始服务给外网,一方面是安全性,另一方面是 负载均衡处理 和 静态资源处理。所以会在原始服务上加一层代理,代理来监听 80 端口,再将服务暴露端口的请求转发给对应服务。
第二个 Connector:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
这个 Connector 监听 8009 端口的 AJP 协议连接。AJP 协议负责和其他的 HTTP 服务器(如 Apache )建立连接;在把 Tomcat 与其他 HTTP 服务器集成时,就需要用到这个连接器。之所以使用 Tomcat 和其他服务器集成,是因为 Tomcat 可以用作 Servlet/JSP 容器,但是对静态资源的处理速度较慢,不如 Apache 和 IIS 等 HTTP 服务器。因此常常将 Tomcat 与 Apache 等集成,前者作 Servlet 容器,后者处理静态资源,而 AJP 协议便负责 Tomcat 和 Apache 的连接。
Container 表示一类组件,在配置文件(server.xml)中没有体现出来。它包含4个容器类组件:Engine容器、Host容器、Context容器 和 wrapper容器。
Engine 容器用于从 Connector 组件处接收已建立的 TCP 连接,还用于接收客户端发送的 HTTP 请求并分析请求,然后按照分析的结果将相关参数传递给匹配出的虚拟主机。Engine 还用于指定默认的虚拟主机。
Host 容器定义虚拟主机,对应了服务器中一个网络名实体(如”www.baidu.com”,或IP地址”23.0.32.1”)。为了使用户可以通过域名连接 Tomcat 服务器,这个域名应该在域名服务器已经注册过。
比如上例中的配置:
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
name=localhost 表示当前对应的请求是本机,这是因为已经配置了Nginx代理的原因,如果没有配置代理,那么这里就必须是真实的IP 或者域名。注意后面的 appBase,appBase表示当前 web资源所在的目录。
Context 容器主要是根据 path 和 docBase 获取一些信息,将结果交给其内的 wrapper 组件进行处理(它提供wrapper运行的环境,所以它叫上下文context)。一般来说,都采用默认的标准 wrapper 类,因此在 Context 容器中几乎不会出现 wrapper 组件。
wrapper 容器对应 Servlet 的处理过程。它开启 Servlet 的生命周期,根据 Context 给出的信息以及解析 web.xml 中的映射关系,负责装载相关的类,初始化 servlet 对象 init()、执行 servlet 代码 service() 以及服务结束时 servlet 对象的销毁 destory()。
根据上面描述的 tomcat 组件体系结构,处理请求的大致过程其实很容易推导出来:
Client(request)-->Connector-->Engine-->Host-->Context-->Wrapper(response data)-->Connector(response header)-->Client
可以看到宏观上 Tomcat 设计的真是非常精妙,层叠式的容器设计呈现出一种美感。Connector 和 Container 两大组件涵盖主要功能,这种复合组件化的设计思想我们是否可以应用在业务系统中呢。右面有空继续分析 Tomcat 中各个模块的设计。
以上就是JAVA WEB中Servlet和Servlet容器的区别的详细内容,更多关于JAVA WEB Servlet和Servlet容器的资料请关注易盾网络其它相关文章!

