Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目, 由Apache, Sun和其他一些公司及个人共同开发而成, 由于有了Sun的参与和支持, 最新的Servlet和JSP规范总是能在Tomcat中得到体现, Tomcat5支持最新的Servlet 2.4和JSP 2.0规范.
因为Tomcat技术先进, 性能稳定, 而且免费, 因而深受Java爱好者的喜爱并得到了部分软件开发商的认可, 成为比较流行的Web应用服务器.
Tomcat是一个HTTP服务器, HTTP服务器有很多种, 在Java领域中, Tomcat是最知名, 最广泛使用的一个, 本质上是基于TCP服务器, 按照HTTP协议的约定来解析请求, 构造响应.
下载与安装:
1️⃣第一步, 浏览器中搜索Tomcat, 找到Tomcat官网 https://tomcat.apache.org/
2️⃣第二步, 根据你的环境, 选择相应版本下载即可, 需要知道的是Tomcat的版本和你使用的Servlet版本是有强相关的, 这里就下载Tomcat8
了, 对应的Servlet
的版本就是3.1
的.
3️⃣第三步, 点进去, 选择zip
文件点击下载即可, 如果你有下载多个版本的需求, 也是可以的, Tomcat是纯绿色的软件, 直接解压就能使用, 下载多个版本之间是互不影响的.
4️⃣第四步, 找个你常用的目录, 解压即可, 点进目录, 你会得到下面一堆文件:
还要注意, Tomcat是基于Java
实现的, 这就要求你的环境中必须要有jdk
, 如果没有Tomcat
是跑不起来的.
使用:
5️⃣第五步, 了解各目录文件的作用
bin
目录中放的是Tomcat相关的批处理文件, .bat
文件表示Windows
批处理文件, .sh
文件表示Linux
的shell脚本文件, 其中包含启动和关闭Tomcat的可执行文件, 也就是说Tomcat也是可以在Linux上运行的, 以startup
命名的文件就是Tomcat启动程序, 以shutdown
命名的文件就是Tomcat关闭程序.
conf
目录中含有Tomcat的配置文件, 配置文件是xml
类型的文件, 比如可以在server.xml
文件可以配置Tomcat的端口号, 不修改的话默认就是8080
了.
logs
目录主要用来储存日志, Tomcat运行的日志都在这里, 如果程序出问题了, 就需要看这里的日志来排产问题.
webapps
目录储存我们部署的Serlvet程序, Servlet部署的程序是war
结尾的压缩包, Tomcat将一个war
包解压后就是一个webapp, 即一个网站, 一个Tomcat可以部署多个Servlet程序, 即多个网站, 所以就是webapps, 里面的每个目录都代表一个独立的网站.
temp, lib, work目录用的不多, 就不作赘述了.
6️⃣第六步, 启动Tomcat, 我们可以在bin
目录下找到startup.bat
文件点击在本地启动Tomcat, 然后直接访问http://127.0.0.1:8080
可访问到Tomcat欢迎页面(Tomcat自带的一个webapp).
启动Tomcat的页面图如下, 出现类似org.apache.catalina.startup.Catalina.start Server startup in 936 ms
的信息就表示启动成功了
可以看到这里控制台有些是乱码的, 这是因为我们的Tomcat是在下Windows下启动的, Windows的默认编码是GBK
, 我们可以可以修改以下配置conf/logging.properties
, 然后关闭Tomcat后重新启动.
当然, 如果要将Tomcat配置到Linux环境下, 这里的配置还是需要改回UTF8
的.
要注意, 当启动一个Tomcat程序后再启动一个Tomcat程序会启动失败, 因为端口号8080
已经被上一个Tomcat程序占用了.
7️⃣第七步, 将项目部署到Tomcat, 所谓部署就是将我们的代码拷贝到webapps
目录下即可, 然后在bin目录找到startup.bat
文件重新启动Tomcat, 最后访问http://127.0.0.1:8080/部署文件的相对wepapps目录的相对路径
进行验证.
比如我的webapps
目录中有一个BlogSystem
文件夹, 里面有一个login.html
页面文件, 我们现在要使用Tomcat访问这个文件, 访问的url就为http://127.0.0.1:8080/BlogSystem/login.html
.
这里访问的路径组成为, ip:端口号, 后面的BlogSystem是我们的webapps下的目录, 我们也称为context path/application path, 再后面的路径是我们的context path下要访问的文件, 这种形式的访问是通过网络可以跨主机访问的, 初学要注意与本地点文件打开访问进行区分.
访问http://127.0.0.1:8080/BlogSystem/login.html
结果如下,
不过我们这里在Tomcat部署的网页, 是在局域网环境下, 只有在同一局域网下的设备才可以访问, 如果是部署在外网IP下, 那么全世界的设备就都可以访问了.
最后就是关闭Tomcat了, 一共有三种关闭方式:
这三种方式中, 第1, 2种是比较粗暴的关闭方式, 这种方式会直接杀死进程; 第3种方式比较优雅, Tomcat还会绑定一个8005管理端口, 是通过管理端口来关闭的, 会多做一些收尾工作; 但实际上, 第1, 2种关闭方式是更方便, 更常用的.
Maven是专门用于管理和构建Java项目的 “工程管理” 工具, 有规范目录结构, 管理依赖, 构建/编译, 打包, 测试等功能, Maven是一个独立的程序, 但不需要我们单独下载安装, IDEA中已经直接集成了.
那么首先来介绍如何使用IDEA来使用Maven来引入的依赖, 以引入Servlet的为例.
1️⃣第一步, 新建项目, 选择Maven.
选中这里的Maven点击Create就可以创建Maven管理的项目了,
main
目录中放业务代码, java
目录中放java代码, resources
目录中放程序的依赖文件, test
目录下放测试代码, pom.xml
文件是Maven项目总的配置文件.
如果是首次使用Maven, 项目创建好了之后, 会在下面读条, 从中央仓库加载一些Maven的依赖, 由于Maven仓库的服务器是在国外的, 下载的速度就可能比较慢; 如果实在太慢尝试就更换下网络, 或者配置一下国内镜像的阿里云服务器再下载.
2️⃣第二步, 引入依赖.
首先要知道坐标的概念, Maven中的坐标是资源的唯一标识, 要使用坐标来引入项目中所需要的依赖, Maven标准由以下几个部分组成:
groupId
: 定义当前Maven项目隶属组织名称(通常是域名的反写)artifactId
: 定义当前Maven项目名称(通常是模块名称, maven_project)version
: 定义当前项目版本号scope
: 设置对应jar包的作用范围这里以引入Servlet的依赖为例进行介绍, 我们要去Maven中央仓库(https://mvnrepository.com/), 搜索Servlet, 找到Servlet的jar包点进去
点击选择3.1
版本, 和tomcat8
对应, 复制图中位置的坐标内容.
把坐标拷贝到项目的pom.xml
文件中, 我们需要, 先创建一个dependencies
标签, 是project
标签的子标签, 可以放多个依赖, 把依赖依次拷贝到这个标签即可.
首次使用, 这里可能会爆红, 说明依赖还没有下载下来.
当这段代码复制到pom.xml
文件中, Maven就会自动下载相应的依赖文件, 没有触发自动下载的话, 可以手动刷新一下触发下载, 当依赖下载完成后, 也就不爆红了.
这样就引入依赖成功了.
Servlet是一种实现动态页面的技术, 要注意区分静态页面和动态页面:
Servlet是Tomcat提供的一组API, 封装了HTTP相关操作, 可以让我们不必关注Socket, HTTP协议格式等细节, 降低了Web开发的门槛, 提高开发效率.
Servlet主要进行的工作:
那么下面就来写一个Servlet程序, 我们使用Servlet来在写一个hello world程序, 然后部署到Tomcat上, 此时通过浏览器去访问, 就会在网页上得到一个有hello world字符串的页面.
1️⃣第一步, 创建Maven项目, 创建步骤在上面介绍过了.
2️⃣第二步, 引入Servlet
依赖, 还是去参考上面写的.
3️⃣第三步, 创建目录结构, 虽然Maven已经帮我们自动创建了一些目录, 但是还不够, 因为此处我们使用Maven开发的是一个Web程序, 还需要一些额外的目录.
给web.xml
写入指定配置, 需要注意的是, 这里的代码可能是爆红的, 但在这里并不代表就是错的, IDEA中只是针对Java代码能够进行比较准确的分析和判定, 针对其他代码, 如果标红, 是否是错的, 都不一定.
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>
这里相关的还要理解的是, Servlet程序中是没有main
方法的, 那么它是怎么跑起来的呢?
这就和我们创建的这个web.xml
有关了, 依靠这个文件, Tomcat就可以识别webapps
目录下哪些项目目录是需要加载到服务器中的.
所以说, 这样的目录结构是必须的, 使用Tomcat就得遵照人家的要求, 当然也不是不可以改其他名称, 是需要额外配置的.
4️⃣第四步, 在Java
目录下编写Servlet代码.
HelloServlet
, 继承HttpServlet
类(由Servlet API提供, 写Servlet代码一般都要继承这个类).doGet
方法, 用来处理HTTP GET请求, 根据请求生成响应, 有HttpServletRequest req
(TCP socket中读出来的字符串,按照HTTP协议解析得到的对象), HttpServletResponse resp
(空对象, 输出型参数, 要由我们去构造)两个参数, Tomcat服务器接收到GET或者POST请求时就会调用这里相应的方法(不需要我们手动调用).WebServlet
注解标识路径, 这个注解的作用是把当前的类和一个HTTP请求的路径关联起来, 不同的路径关联的是不同类, 可以触发不同的代码 (注解是Java 中的特殊的类, Java专门定义了一种 “语法糖” 来实现注解, 作用是针对一个类/方法, 进行额外的解释说明, 赋予额外的含义).import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
// 把当前的类和HTTP请求的路径关联起来
// 根据url中的路径, 通过这个注解, 就可以确定调用服务器中的哪个类的方法
// 路径和servlet是一一对应关系
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 不要调用父类的构造方法
//super.doGet(req, resp);
// 控制台输出hello world
System.out.println("hello world");
// 构造resp对象
// 写入resp中的body中, 最终由tomcat写入网卡, 发送至客户端
resp.getWriter().write("hello world");
}
}
要理解, 一个Servlet程序中, 可以有很多的Servlet类, 每个Servlet类都可以关联到不同的路径(对应到不同的资源), 多个Servlet就可以实现了不同的逻辑和功能, 路径和Servlet类之间是一对一的关系.
上面的代码中要注意, 直接快捷键重写的doGet
方法, 默认调用的是父类的doGet
, 而父类是直接写回一个错误的, 所以一定要注意将默认调用的super.doGet()
删除, 然后再去实现自己的逻辑;
代码中resp.getWriter()
会得到一个Writer
对象, 这里的writer
对象是从属于resp
对象的, 此处的write操作其实是往resp的body
部分进行写入, 等resp对象整个构造好了, tomcat
会统一转成HTTP
相应的格式, 写入socket
.
5️⃣第五步, 打包程序.
Maven默认打的是jar
包, jar包中只含有普通的java程序(.class), 而Tomcat中的webapp需要的war
包, war包是Tomcat部署webapp使用的压缩文件, 可以包含一些前端代码和特定的目录结构, 以方便后续Tomcat识别这些内容, 来加载webapp.
首先需要在pom.xml
文件写入以下内容, 与dependencies
同一级, 目的是为了使打包的压缩格式为war
和指定包名.
<!-- 描述要包类型 -->
<packaging>war</packaging>
<!-- 声明包名 -->
<build>
<finalName>hello_servlet</finalName>
</build>
然后点击IDEA右侧的Maven, 双击Lifecycle下的package, 此时Maven就会帮助我们打包项目, 项目中会出现一个target目录, 打包后的war包就在其中.
这里的打包其实是完成了以下操作:
6️⃣第六步, 将程序部署到Tomcat
将打包好的war
包拷贝到Tomcat中的webapps
目录中即可.
7️⃣第七步, 验证程序运行结果.
启动Tomcat服务器, 在浏览器地址栏中访问http://127.0.0.1:8080/hello_servlet/hello
可以得到一个显示hello world的页面, 同时命令行运行的Tomcat也会输出hello world.
要注意这里的两级路径, 第一级路径是webapps
目录下的war
包文件名, 也叫做Context Path
; 第二级路径是我们代码中在注解标注的路径, 也叫做Servlet Path
; 即/war包名(一级路径)/注解标注的路径(二级路径)
.
这里的war
包名称为hello_servlet
, 注解标注的路径是/hello
; 所以综合起来, 加上前面的协议域名和端口号, URL就是http://127.0.0.1:8080/hello_servlet/hello
.
总结一下, 这里有7步, 依次是, 创建Maven项目, 引入依赖, 创建webapp目录结构, 编写Servlet代码, 打包, 部署, 验证.
Smart Tomcat是IDEA上的一个插件, 上面所介绍的Servlet程序运行步骤其实是可以简化的, 主要是第五步和第六步, 每次修改都需要重新打包和部署, 其实是有点麻烦的, Smart Tomcat就帮助我们解决了这个问题.
Smart Tomcat插件安装和使用步骤如下:
1️⃣第一步, 打开IDEA设置, 找到插件选项, 即Plugins
.
2️⃣第二步, 在Marketplace
搜索Smart Tomcat
, 下载安装即可.
3️⃣第三步, 重启IDEA, 配置Smart Tomcat.
配置Tomcat
看到下图中的提示, Tomcat就启动成功了, 不过这个不能访问Tomcat的欢迎页面.
要注意, 使用Smart Tomcat启动Tomcat和之前介绍的是有本质区别的, Smart Tomcat的工作原理, 不是说把war包拷贝(webapps里是不变的), 使用Smart Tomcat支持启动的时候显示指定一个特定的webapp目录, 相当于是让Tomcat加载单个webapp运行, IDEA直接调用Tomcat, 让Tomcat加载当前项目中的目录, 这里没有打包, 拷贝和解压缩的过程.
这两种部署, 其实是两种Tomcat运行方式, 对于Context Path的定位不同; 如果是直接拷贝war包的方式部署, Context Path就是war包名; 如果是Smart Tomcat方式部署, 这里的Context Path是可以自己配置的.
IDEA专业版还直接集成了Tomcat Server插件, 不过还是没有这个简单好用.
常见错误1: 404
404 表示用户访问的资源不存在, 大概率是 URL 的路径写的不正确.
或者是你的webapp没有正确被部署: web.xml 写错了, 文件名错了, 文件路径错了, 文件位置错了…
常见错误2: 405
405 表示对应的 HTTP 请求方法没有实现, 比如我们在浏览器发了个GET请求, 但是代码里没写doGet, 此时就会出现405.
还有可能就是重写的方法中没有去掉默认调用的父类方法, 如super.doGet
常见错误3:500
往往是Servlet代码中抛出异常导致的, 这个问题最好解决, 因为500的时候页面日志中会明确告诉你异常调用栈, 告诉你是哪一行代码出的异常
比如我们给代码来一个空指针异常.
常见错误4: 出现空白页面
方法中逻辑没有写类似resp.getWriter().write()
这样的代码
常见错误5: 页面无法访问
最常见的原因就是Tomcat没有启动或者崩溃, 我们把Tomcat关了, 就会出现页面无法访问的情况, Tomcat无法启动, 很可能是端口冲突了.