Maven_HTTP_Tomcat详解
Maven + HTTP + Tomcat 详解
本章位置:第二阶段 Java 核心框架
前置知识:JavaSE、Servlet、JSP、MyBatis、Web CRUD
下一篇:MyBatis 进阶
学习目标:理解 Maven 的项目构建、HTTP 的请求响应模型、Tomcat 的部署运行机制,并掌握端口、Context Path、状态码、乱码、WAR 部署和 IDEA 配置。
一、为什么把 Maven、HTTP、Tomcat 放在一起学
Java Web 项目真正运行起来,可以看成:
Java 源码
↓
Maven 编译和打包
↓
WAR / exploded artifact
↓
Tomcat 部署
↓
浏览器发送 HTTP 请求
↓
Tomcat 找到 Servlet
↓
Servlet 处理请求
↓
HTTP 响应
↓
浏览器
三者分工:
Maven
负责项目构建和依赖管理
HTTP
负责客户端和服务器通信
Tomcat
负责接收 HTTP 并运行 Servlet
二、Maven 是什么
Maven 是 Java 常用的:
项目管理与构建工具
主要负责:
依赖管理
项目目录规范
编译
测试
打包
安装
发布
三、为什么需要 Maven
如果没有 Maven,使用 MyBatis、MySQL 驱动、JUnit、JSTL 等库时可能需要:
手工下载 jar
复制到 lib
配置 classpath
自己解决版本冲突
换电脑或者换项目后很容易出现:
jar 缺失
版本冲突
依赖路径错误
Maven 可以通过 pom.xml 自动管理。
四、Maven 项目坐标
一个 Maven 项目通常由:
groupId
artifactId
version
标识。
例如:
<groupId>com.example</groupId>
<artifactId>student-web</artifactId>
<version>1.0-SNAPSHOT</version>
其中:
groupId
组织、公司或项目组
artifactId
项目或模块名称
version
项目版本
五、SNAPSHOT
例如:
1.0-SNAPSHOT
表示:
当前是开发中的快照版本
正式发布时常见:
1.0.0
2.1.3
六、Maven 标准目录结构
project
│
├─ pom.xml
│
└─ src
├─ main
│ ├─ java
│ └─ resources
│
└─ test
├─ java
└─ resources
传统 Web 项目还常有:
src/main/webapp
七、src/main/java
存放:
正式 Java 源代码
八、src/main/resources
存放:
properties
xml
Mapper XML
日志配置
编译后通常复制到:
target/classes
九、src/test/java
存放:
测试代码
十、pom.xml
pom.xml 是:
Project Object Model
它是 Maven 项目的核心配置。
常见内容:
项目坐标
依赖
插件
JDK 版本
编码
打包方式
模块
十一、基础 pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
十二、设置 JDK 17
推荐:
<properties>
<maven.compiler.release>
17
</maven.compiler.release>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
</properties>
如果编译出现:
不支持发行版本 5
往往需要检查:
Maven 编译版本
IDEA Project SDK
Maven Runner JDK
十三、dependency
依赖写在:
<dependencies>
内部。
例如:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.19</version>
</dependency>
十四、Maven scope
常见:
compile
provided
runtime
test
十五、compile
默认范围。
表示:
编译需要
运行也需要
例如:
MyBatis
十六、provided
表示:
编译需要
运行环境已经提供
典型:
Servlet API
因为 Tomcat 已经自带 Servlet API。
十七、test
只用于:
测试阶段
典型:
JUnit
十八、runtime
主要表示:
运行时需要
编译时不一定直接使用。
十九、本地 Maven 仓库
Windows 常见路径:
C:\Users\用户名\.m2\repository
Maven 下载的 jar 会保存在这里。
二十、远程仓库
如果本地仓库没有依赖:
Maven 会从远程仓库下载
常见:
Maven Central
公司私服
国内镜像
二十一、依赖下载失败
常见原因:
网络问题
版本不存在
settings.xml 错误
镜像配置错误
本地缓存损坏
IDEA 中可以尝试:
Reload All Maven Projects
二十二、Maven 生命周期
最常见命令:
clean
compile
test
package
install
二十三、mvn clean
mvn clean
删除:
target
清理旧构建结果。
二十四、mvn compile
mvn compile
编译:
src/main/java
生成:
target/classes
二十五、mvn test
mvn test
编译并执行:
测试代码
二十六、mvn package
mvn package
进行:
编译
测试
打包
Web 项目通常得到:
xxx.war
二十七、mvn install
mvn install
除了 package,还会:
把当前项目安装到本地 Maven 仓库
供其他项目依赖。
二十八、target 目录
构建后常见:
target/classes
target/test-classes
target/xxx.war
二十九、WAR 是什么
WAR:
Web Application Archive
传统 Servlet/JSP 项目通常:
<packaging>war</packaging>
然后交给:
Tomcat
部署。
三十、JAR 和 WAR
简单区分:
JAR
普通 Java 库或程序
WAR
传统 Java Web 应用
三十一、查看 Maven 依赖树
mvn dependency:tree
用于排查:
传递依赖
版本冲突
重复依赖
三十二、什么是传递依赖
例如:
项目 A
依赖 B
B
依赖 C
那么 A 可能自动获得:
C
这叫:
传递依赖
三十三、依赖冲突
如果:
A 依赖 X 1.0
B 依赖 X 2.0
最终 Maven 需要选择一个版本。
冲突可能导致:
ClassNotFoundException
NoSuchMethodError
运行结果异常
三十四、HTTP 是什么
HTTP:
HyperText Transfer Protocol
中文:
超文本传输协议
它规定:
客户端和服务器如何通信
三十五、HTTP 核心模型
客户端
发送 Request
服务器
返回 Response
浏览器访问:
http://localhost:8080/demo/hello
本质就是:
浏览器发送 HTTP 请求
Tomcat 返回 HTTP 响应
三十六、HTTP 请求组成
通常包括:
请求行
请求头
空行
请求体
三十七、请求行
例如:
GET /demo/student/list?pageNum=1 HTTP/1.1
其中:
GET
请求方法
/demo/student/list?pageNum=1
请求目标
HTTP/1.1
协议版本
三十八、HTTP 方法
常见:
GET
POST
PUT
PATCH
DELETE
HEAD
OPTIONS
三十九、GET
主要用于:
查询资源
例如:
列表
详情
搜索
分页
四十、POST
主要用于:
提交数据
创建资源
执行业务动作
例如:
新增
登录
表单提交
四十一、PUT / PATCH / DELETE
RESTful 中常见:
PUT
整体更新
PATCH
部分更新
DELETE
删除资源
四十二、请求头 Header
常见:
Host
User-Agent
Accept
Content-Type
Cookie
Authorization
四十三、Host
例如:
Host: localhost:8080
表示目标:
主机 + 端口
四十四、User-Agent
表示:
客户端信息
例如:
Chrome
Edge
手机浏览器
四十五、Accept
告诉服务器:
客户端希望接收什么类型
例如:
text/html
application/json
四十六、Content-Type
表示:
请求体或响应体的数据格式
常见:
application/x-www-form-urlencoded
multipart/form-data
application/json
text/html
四十七、普通表单
常见:
application/x-www-form-urlencoded
Servlet 可以:
request.getParameter(
"username"
);
获取。
四十八、文件上传
常见:
multipart/form-data
四十九、JSON
前后端分离常见:
application/json
例如:
{
"name": "张三",
"age": 20
}
五十、Query String
例如:
/student/list?pageNum=2&keyword=java
其中:
pageNum=2
keyword=java
属于:
Query String Parameters
五十一、HTTP 响应组成
通常:
状态行
响应头
空行
响应体
五十二、状态行
例如:
HTTP/1.1 200 OK
五十三、常见状态码
200
成功
201
创建成功
204
成功,无响应体
302
临时重定向
304
缓存未修改
400
请求错误
401
未认证
403
无权限
404
资源不存在
405
请求方法不允许
500
服务器内部错误
502
网关错误
503
服务不可用
五十四、404
Java Web 中最常见原因:
项目没部署
Context Path 错
Servlet Mapping 错
URL 错
资源不存在
五十五、405
例如:
客户端发 POST
Servlet 却只实现:
doGet()
可能返回:
405 Method Not Allowed
五十六、500
表示服务器内部异常。
例如:
NullPointerException
SQL 异常
MyBatis 异常
Servlet 初始化失败
JSP JasperException
遇到 500:
优先看 Tomcat 控制台堆栈
五十七、HTTP 为什么叫无状态
每个 HTTP 请求本身:
相对独立
服务器不会仅凭一次请求天然知道:
你上一次是谁
你是否已经登录
所以通常通过:
Cookie
Session
Token
保持状态。
五十八、Cookie
服务器可以通过响应让浏览器保存 Cookie。
之后浏览器发送请求时:
自动带上 Cookie
五十九、Session 和 JSESSIONID
Tomcat 常使用:
JSESSIONID
作为 Session 标识。
流程:
服务器创建 Session
↓
返回 JSESSIONID Cookie
↓
浏览器保存
↓
下次请求带回
↓
Tomcat 找到对应 Session
六十、请求编码
旧式 Servlet 表单 POST:
request.setCharacterEncoding(
"UTF-8"
);
必须在:
第一次 getParameter 之前
六十一、响应编码
response.setContentType(
"text/html;charset=UTF-8"
);
要尽量在:
getWriter 之前
设置。
六十二、Tomcat 是什么
Tomcat 是:
Web 服务器
Servlet 容器
主要负责:
监听端口
接收 HTTP
解析请求
管理 Servlet
创建 request/response
调用 Servlet
返回 HTTP 响应
六十三、Tomcat 不是数据库
Tomcat
运行 Java Web
MySQL
保存业务数据
六十四、Tomcat 不是 JDK
JDK
Java 开发和运行环境
Tomcat
Servlet/JSP 容器
Tomcat 自己也需要:
Java 环境
才能运行。
六十五、CATALINA_HOME
表示:
Tomcat 安装目录
例如:
D:\apache-tomcat-8.5.65
六十六、CATALINA_BASE
表示:
当前 Tomcat 实例运行目录
IDEA 配置 Tomcat 后:
CATALINA_BASE
经常是 IDEA 自动生成的目录
这和 CATALINA_HOME 不同是正常的。
六十七、Tomcat 常见目录
bin
conf
lib
logs
temp
webapps
work
六十八、bin
包含:
startup.bat
shutdown.bat
catalina.bat
等脚本。
六十九、conf
包含:
server.xml
web.xml
context.xml
logging.properties
七十、lib
包含:
Tomcat 自己需要的 jar
Servlet API
七十一、logs
保存:
运行日志
七十二、webapps
独立 Tomcat 常用:
部署 WAR
七十三、work
JSP 被 Tomcat 翻译和编译后:
相关 Java / class
通常会出现在 work 目录。
七十四、server.xml
Tomcat 核心配置之一。
常见 Connector:
<Connector
port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"
/>
七十五、port
port="8080"
表示:
Tomcat HTTP 监听 8080
浏览器:
http://localhost:8080
七十六、8080 被占用
如果出现:
Address already in use
说明:
8080 已有其他进程使用
Windows:
netstat -ano | findstr :8080
找到 PID。
七十七、查看 PID 对应进程
tasklist | findstr 进程号
确认是什么程序后,再决定是否关闭。
七十八、结束进程
taskkill /PID 进程号 /F
不要:
不确认进程就直接结束
七十九、修改 Tomcat 端口
可以改:
<Connector
port="8081"
protocol="HTTP/1.1"
/>
之后访问:
http://localhost:8081
八十、URIEncoding
正确拼写:
URIEncoding="UTF-8"
不要写成:
URIEconding
否则 Tomcat 会提示:
找不到匹配属性
八十一、Context Path
假设项目上下文:
/demo
Servlet:
@WebServlet(
"/hello"
)
完整 URL:
http://localhost:8080/demo/hello
八十二、完整 URL 三部分
8080
端口
/demo
Context Path
/hello
Servlet Mapping
这三个经常被初学者混淆。
八十三、Tomcat 如何找到 Servlet
请求 /demo/hello
↓
找到 /demo Web 应用
↓
找到 /hello 映射
↓
找到 HelloServlet
↓
调用 service()
↓
分发 doGet / doPost
八十四、Tomcat 为什么叫 Servlet 容器
它负责:
创建 Servlet
管理生命周期
分发请求
管理 request/response
管理 Session
销毁 Servlet
八十五、Tomcat 8.5 和 Tomcat 10
这是必须注意的版本区别。
Tomcat 8.5 常见:
javax.servlet
Tomcat 10+:
jakarta.servlet
不要混用。
八十六、Servlet API 为什么用 provided
Tomcat 8.5 Maven 项目:
<dependency>
<groupId>
javax.servlet
</groupId>
<artifactId>
javax.servlet-api
</artifactId>
<version>
4.0.1
</version>
<scope>
provided
</scope>
</dependency>
因为运行时:
Tomcat 已经提供 Servlet API
八十七、IDEA 配置 Tomcat
一般:
Run
→ Edit Configurations
→ Tomcat Server
→ Local
然后设置:
Application Server
Deployment
八十八、Deployment
需要添加:
Artifact
例如:
student-web:war exploded
八十九、war exploded
表示:
以解压后的目录结构部署
开发阶段:
更新更方便
九十、Tomcat 启动成功不等于项目部署成功
Tomcat 可能:
正常监听 8080
但项目:
没有 Deployment
访问仍然:
404
九十一、Tomcat 控制台重点看什么
Tomcat version
CATALINA_HOME
CATALINA_BASE
端口
Deployment
Server startup
异常堆栈
九十二、404 排查顺序
1. Tomcat 是否启动
2. 端口是否正确
3. 项目是否部署
4. Context Path 是否正确
5. Servlet Mapping 是否正确
6. URL 是否正确
7. JSP 是否位于 WEB-INF
九十三、405 排查
请求 Method
form method
Servlet doGet/doPost
三者要对应。
九十四、500 排查
重点:
Tomcat 控制台
Caused by
Root Cause
不要只看浏览器的“500”。
九十五、JasperException
JSP 报:
JasperException
常见:
JSP 编译错误
JSP Java 脚本错误
标签库错误
运行时异常
重点看:
具体 JSP 行号
九十六、HTTP 与 Servlet 对应关系
HTTP:
GET
POST
HttpServlet:
doGet()
doPost()
Tomcat:
读取 HTTP Method
↓
调用 service()
↓
service 分发到 doGet/doPost
九十七、redirect 的 HTTP 本质
response.sendRedirect(
"/login"
);
通常:
服务器返回 302
+
Location 响应头
浏览器:
重新发送一次请求
所以:
地址栏改变
request 也变了
九十八、forward 的本质
request
.getRequestDispatcher(
"/WEB-INF/views/a.jsp"
)
.forward(
request,
response
);
是:
服务器内部转发
浏览器通常不知道。
所以:
地址栏不变
还是同一个 request
九十九、Maven 和 Tomcat 如何连接
Maven:
compile
↓
package
↓
WAR
Tomcat:
部署 WAR
↓
运行 Web Application
一百、IDEA 实际帮你做了什么
IDEA 配 Tomcat 后,大量步骤被自动完成:
编译
↓
生成 Artifact
↓
准备 war exploded
↓
启动 Tomcat
↓
部署 Web 项目
一百零一、为什么修改代码后没生效
可能:
编译失败
Artifact 没更新
Tomcat 没重新部署
浏览器缓存
修改的不是当前运行项目
一百零二、mvn clean 的意义
旧构建文件有问题时:
mvn clean
然后:
mvn package
重新构建。
一百零三、Maven 测试代码问题
如果 pom 中已经删除 JUnit:
src/test/java
中却还存在:
import org.junit.jupiter.api.Test;
执行 Maven 测试编译时仍然会报错。
所以:
依赖和代码必须匹配
一百零四、不要只删 dependency
如果测试代码仍然需要 JUnit:
就不能只把依赖删除
要么:
恢复依赖
要么:
删除/修改测试代码
一百零五、浏览器 F12 Network
必须掌握:
F12
→ Network
重点查看:
Request URL
Request Method
Status Code
Query String
Form Data
Request Payload
Request Headers
Response Headers
Response
一百零六、Java Web 排错三件套
浏览器 Network
看 HTTP
Tomcat 控制台
看服务端异常
MyBatis 日志
看 SQL
一百零七、完整排错路线
浏览器
↓
URL
↓
Method
↓
Status Code
↓
Tomcat
↓
Deployment
↓
Servlet
↓
Request 参数
↓
Service
↓
Mapper
↓
SQL
↓
Response / JSP
不要:
一报错就所有代码一起改
一百零八、练习 1:Maven 生命周期
依次执行:
mvn clean
mvn compile
mvn package
观察:
target
目录变化。
一百零九、练习 2:依赖树
mvn dependency:tree
找出:
MyBatis
MySQL Driver
JSTL
一百一十、练习 3:GET 请求
创建:
/hello
浏览器访问。
F12 查看:
GET
200
一百一十一、练习 4:POST 请求
创建:
login.html
提交:
POST /login
在 Network 查看:
Form Data
一百一十二、练习 5:404
故意访问错误地址:
/demo/abc-not-exist
观察:
404
然后按排错顺序定位。
一百一十三、练习 6:405
Servlet 只写:
doGet()
使用 POST 请求。
观察:
405
一百一十四、练习 7:500
Servlet 中临时:
throw new RuntimeException(
"测试异常"
);
观察:
浏览器 500
Tomcat 控制台异常
一百一十五、练习 8:redirect
response.sendRedirect(
request.getContextPath()
+ "/hello"
);
Network 观察:
302
↓
第二次 GET
一百一十六、练习 9:Context Path
假设:
端口 8080
Context Path /demo
Servlet /hello
手工写出完整:
http://localhost:8080/demo/hello
一百一十七、练习 10:端口冲突
PowerShell:
netstat -ano | findstr :8080
找到 PID 后:
tasklist | findstr PID
确认占用程序。
一百一十八、练习 11:乱码
分别测试:
GET 中文参数
POST 中文表单
响应中文
理解:
URIEncoding
request.setCharacterEncoding
response.setContentType
分别解决什么。
一百一十九、必须掌握 Maven
pom.xml
groupId
artifactId
version
dependency
scope
repository
clean
compile
test
package
install
dependency:tree
WAR
一百二十、必须掌握 HTTP
Request
Response
Method
URL
Header
Body
Query String
Content-Type
Cookie
Session
Status Code
一百二十一、必须掌握 Tomcat
Servlet Container
CATALINA_HOME
CATALINA_BASE
server.xml
Connector
port
Context Path
Deployment
Artifact
war
war exploded
一百二十二、必须回答的问题
学完以后应该能够回答:
1. Maven 是什么?
2. pom.xml 有什么作用?
3. groupId、artifactId、version 是什么?
4. compile、provided、test 有什么区别?
5. mvn clean、compile、package、install 分别做什么?
6. WAR 是什么?
7. HTTP 是什么?
8. Request 和 Response 分别由什么组成?
9. GET 和 POST 有什么区别?
10. Content-Type 是什么?
11. Cookie 和 Session 是什么关系?
12. 为什么 HTTP 是无状态协议?
13. 200、302、404、405、500 分别是什么?
14. Tomcat 是什么?
15. Tomcat 为什么叫 Servlet 容器?
16. CATALINA_HOME 和 CATALINA_BASE 有什么区别?
17. Context Path 是什么?
18. 8080 被占用怎么查?
19. Tomcat 8.5 和 Tomcat 10 的 servlet 包有什么区别?
20. 为什么 Servlet API 使用 provided?
21. war 和 war exploded 有什么区别?
22. redirect 为什么地址栏变化?
23. forward 为什么地址栏不变?
24. 项目启动后 404 应该怎么排查?
25. Java Web 出错应该按照什么顺序排查?
一百二十三、知识结构
Java Web
│
├─ Maven
│ ├─ POM
│ ├─ Dependency
│ ├─ Scope
│ ├─ Repository
│ ├─ Lifecycle
│ └─ WAR
│
├─ HTTP
│ ├─ Request
│ ├─ Response
│ ├─ Method
│ ├─ Header
│ ├─ Body
│ ├─ Cookie
│ └─ Status
│
└─ Tomcat
├─ Connector
├─ Port
├─ Context
├─ Deployment
├─ Servlet Container
├─ CATALINA_HOME
└─ CATALINA_BASE
一百二十四、三者完整关系
Java 源码
↓
Maven
↓
compile
↓
package
↓
WAR
↓
Tomcat
↓
部署 Web App
↓
浏览器
↓
HTTP Request
↓
Tomcat Connector
↓
Servlet
↓
HTTP Response
↓
浏览器
这是本章最重要的一张图。
一百二十五、本章总结
Maven 解决:
项目怎么构建
依赖怎么管理
项目怎么打包
HTTP 解决:
浏览器和服务器如何通信
Tomcat 解决:
谁接收 HTTP
谁运行 Servlet
谁管理 Web 应用
Maven 必须掌握:
pom.xml
dependency
scope
clean
compile
package
WAR
HTTP 必须掌握:
Method
URL
Header
Body
Content-Type
Cookie
Status Code
Tomcat 必须掌握:
port
Context Path
Deployment
CATALINA_HOME
CATALINA_BASE
server.xml
Connector
排错顺序:
浏览器
↓
HTTP
↓
Tomcat
↓
Servlet
↓
Service
↓
Mapper
↓
数据库
按照课程表,下一篇进入:
MyBatis 进阶
重点会继续学习:
动态 SQL
复杂 resultMap
一对一
一对多
缓存
批处理
插件
执行流程