Tomcat 简介
Tomcat 服务器是一个免费的开放源代码的 Web 应用服务器。应用十分广泛,毕竟免费好用。
Tomcat 官网
Tomcat 与 servlet、jsp、jdk 的版本支持
Tomcat 目录结构:
目录 | 说明 |
---|---|
bin | 命令中心(启动、关闭等命令) |
conf | 配置中心(核心配置 server.xml) |
lib | Tomcat 的库文件。Tomcat 运行时需要的 jar 包所在的目录。 |
logs | 存放日志文件。 |
temp | 存储临时产生的文件,即缓存。 |
webapps | 存放项目的文件,web 应用放置到此目录下浏览器可以直接访问。 |
work | 存放编译以后的 class 文件。 |
下载 tomcat 压缩包后,解压并启动 tomcat
便可以看见如下画面,即启动成功。
部署应用,将 web 项目打包成 war 包,放在 webapps 目录下启动 tomcat 即可。
Tomcat 执行流程
Tomcat 是 Http 服务器 + Servlet 容器。
对我们屏蔽了应用层和网络层的协议(即不用我们去处理 TCP 连接,以及对 HTTP 报文的解析),给我们提供了标准的 Request 和 Response 对象。
我们只需要从 request 中获取请求参数,然后调用业务逻辑,最后构建 Response 对象返回即可。
至于 TCP 连接 和 HTTP 协议的数据处理和响应,Tomcat 会帮我们完成。
实现了 HTTP 服务器与业务类的解耦。
详细架构就不仔细介绍了,放几篇文章:
Tomcat 架构原理解析到架构设计借鉴
四张图带你了解Tomcat系统架构
Tomcat 的体系结构(超详细)
介绍执行流程之前,先介绍几个概念(上面的文章中也有):
- Server:服务器,启动一个 tomcat 就是启动了一个服务器,一个 Server 可以有多个 Service ,一个 Service 可以有多个 Connector 和 Engine
- Service:服务,一个 server 可以包含多个 service 一个 service 维护多个 Connector 和一个 Engine
- Engine:叫引擎,也有资料叫 Container ,一个服务可以开一个引擎,就是一个公司可以有很多个门,不同身份的人从不同的门进,但是具体干活的就一个部门。引擎负责处理请求,不需要考虑请求链接,协议等。
- Context:一个 Context 管理一个应用,其实就是我们写的程序。
- Wrapper:每个都封装着一个 Servlet(当然只局限于普通的 Http 请求)。
下面是 Tomcat 的执行流程:
比如用户发送一个请求: http://localhost:8080/test/index.jsp
- 我们的请求被发送到本机端口8080,被在那里侦听的 Coyote HTTP/1.1 Connector 获得。
- Connector 把该请求交给它所在的 Service 的 Engine 来处理,并等待来自 Engine 的回应 。
- Engine 获得请求 localhost:8080/test/index.jsp ,匹配它所拥有的所有虚拟主机 Host ,我们的虚拟主机在 server.xml 中默认配置的就是 localhost。
- Engine 匹配到 name=localhost 的 Host(即使匹配不到也把请求交给该 Host 处理,因为该 Host 被定义为该 Engine 的默认主机)。
- localhost Host 获得请求 /test/index.jsp ,匹配它所拥有的所有 Context。
- Host 匹配到路径为 /test 的 Context(如果匹配不到就把该请求交给路径名为””的Context去处理)。
- path=”/test” 的 Context 获得请求 /index.jsp,在它的 mapping table 中寻找对应的 servlet 。
- Context 匹配到 URL PATTERN 为 *.jsp 的 servlet,对应于 JspServlet 类。
- 构造 HttpServletRequest 对象和 HttpServletResponse 对象,作为参数调用 JspServlet 的 doGet 或 doPost 方法 。
- Context 把执行完了之后的 HttpServletResponse 对象返回给 Host 。
- Host 把 HttpServletResponse 对象返回给 Engine 。
- Engine 把 HttpServletResponse 对象返回给 Connector 。
- Connector 把 HttpServletResponse 对象返回给客户 browser 。
所以我们在使用 tomcat 时,不需要理会中间过程(HTTP怎么解析,TCP怎么连接)。
只需要写好 servlet 和 对应的映射关系即可。
Servlet 简介
Servlet(Server Applet) 是基于 Jakarta 技术的 Web 组件,由容器管理,可生成动态内容。
与其他基于 Jakarta 技术的组件一样,servlet 是独立于平台的 Java 类,它们被编译为与平台无关的字节码,这些字节码可以动态加载到支持 Jakarta 技术的 Web 服务器中并由其运行。
容器,有时也称为 servlet 引擎,是提供 servlet 功能的 Web 服务器扩展。
Servlet 通过 servlet 容器实现的请求/响应范式与 Web 客户端交互。
Servlet 容器是 Web 服务器或应用程序服务器的一部分,它提供发送请求和响应的网络服务、解码基于 MIME 的请求以及格式化基于 MIME 的响应。Servlet 容器还通过其生命周期包含和管理 Servlet。
Servlet 容器可以内置到主机 Web 服务器中,也可以通过该服务器的本机扩展 API 作为附加组件安装到 Web 服务器。Servlet 容器也可以内置于或可能安装在支持 Web 的应用程序服务器中。
所有 Servlet 容器都必须支持 HTTP 作为请求和响应的协议,但可以支持其他基于请求/响应的协议,例如 HTTPS(基于 SSL 的 HTTP)。容器必须实现的 HTTP 规范的必需版本是 HTTP/1.1 和 HTTP/2。
Java SE 8 是必须用来构建 Servlet 容器的底层 Java 平台的最低版本。
更多可以参考菜鸟教程-servlet教程
Servlet 生命周期
Servlet 生命周期可被定义为从创建直到毁灭的整个过程。
以下是 Servlet 遵循的过程:
- Servlet 初始化后调用 init () 方法。
- Servlet 调用 service() 方法来处理客户端的请求。
- Servlet 销毁前调用 destroy() 方法。
最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
首次访问 servlet 时,init() 方法会被执行,并且会执行 service() 方法
再次访问时,只会执行 service() 方法
关闭 web 容器时,会执行 destroy() 方法
Servlet 使用
创建 servlet 有三种方式:
- 实现 javax.servlet.Servlet 接口。
- 继承 javax.servlet.GenericServlet 类。
- 继承 javax.servlet.http.HttpServlet 类。
一般使用第三种方式进行 servlet 的创建。
创建完成后,需要在 web.xml 中完成 servlet 的配置(映射关系之类的)才可以使用。
例如:
servlet:
1 | public class ServletTest extends HttpServlet { |
别忘了在 web.xml 中添加映射:
1 | <web-app> |
servlet 中详细的方法用法可以参考菜鸟教程,有比较详细的文档。
关于 web.xml 中 servlet 的匹配规则也不详细列举了。
关于 JSP
JSP 全称 Java Server Pages,是一种动态网页开发技术。它使用 JSP 标签在 HTML 网页中插入 Java 代码。标签通常以 <% 开头以 %> 结束。
JSP 是一种 Java servlet,主要用于实现 Java web 应用程序的用户界面部分。网页开发者们通过结合 HTML 代码、XHTML 代码、XML 元素以及嵌入 JSP 操作和命令来编写 JSP。
由于 jsp 以及被淘汰了,所以就放个教程的链接。后面的内容也只是做简单介绍,不做具体使用。
菜鸟教程-jsp教程
首先,来讲下 jsp 出现的原因:
因为 tomcat 的出现,我们只需要写 servlet 就可以完成 web 请求。
但是 servlet 主要功能在于交互式地浏览和生成数据,生成动态 Web 内容。
而动态响应的内容是写在 servlet(java代码)中的,即我们需要在 Java 中使用字符串拼接 html 页面。
这显然是很麻烦,并且低效,阅读性差的工作。
所以 jsp 就诞生了,既能写 java 代码,又能写 html。
JSP 的实现原理:
JSP 的本质其实还是 servlet。
因为浏览器向服务器发送请求,无论访问什么资源,其实都是在访问 servlet。
服务器在执行 jsp 的时候,首先把 jsp 编译成一个 Java(servlet) 文件,然后将 Java 文件编译为 class 文件,加载到容器中。
最后和其他的 servlet 一样,创建实例,初始化,调用 service() 方法,将 html 返回给客户端。
JSP 的缺点(不好用的地方):
- 动态资源与静态资源耦合在一起,无法做到前后端分离。并且服务端压力也大,一旦服务器出现问题,整个网站前后端一起寄。
- 前端做好网页后,需要后端改成 jsp 页面。沟通成本巨大、出错的概率也大、修改起来也麻烦(需要双方的协同开发)、效率因此也低。
- JSP 必须要在支持 Java 的容器(tomcat)中运行,而无法使用 nginx 等。nginx 的性能很高。
- 第一次请求 jsp ,需要经过编译。速度较慢。
所以后面才会发展出视图解析器以及 Thymeleaf 模板引擎 等技术来解决前端资源根据需求动态生成的问题。
再往后就是前后端更加彻底的分离,vue+springboot 这种,可以将静态资源完全交由前端处理,后端仅实现数据接口的模式。
END
说白了就是解耦,专业的人干专业的事。