Tomcat 怎么处理静态资源?GZIP 压缩是怎么回事、有什么用?
简化版
静态资源(HTML、CSS、JS、图片、字体等不变的文件)和 GZIP 压缩,是 Web 性能优化的两个基础话题。① 静态资源处理——Tomcat 有一个内置的 DefaultServlet 负责处理静态资源(读文件、返回、支持缓存头如 Last-Modified/ETag、支持 range 断点续传);但生产环境通常不让 Tomcat 处理静态资源,而是交给 Nginx/CDN——因为 Nginx 处理静态文件更高效、还能做缓存和 CDN 加速,让 Tomcat 专注处理动态请求。② GZIP 压缩——把响应体(文本类如 HTML/CSS/JS/JSON)用 GZIP 算法压缩后再传,能大幅减小传输体积(文本压缩率常达 70%~90%),加快传输、省带宽;工作方式:客户端请求头带 Accept-Encoding: gzip(表示我支持 gzip),服务端压缩响应、加 Content-Encoding: gzip 头,客户端解压。Tomcat 配置 GZIP:Connector 上配 compression="on" + 压缩的类型/最小大小。注意:GZIP 只压缩文本(HTML/CSS/JS/JSON),不压缩已经压缩过的(图片 JPG/PNG、视频、zip)(再压没意义、反而浪费 CPU);且压缩有 CPU 开销(用带宽换 CPU)。核心:静态资源用 DefaultServlet(生产常交给 Nginx/CDN),GZIP 压缩文本响应减小体积(客户端 Accept-Encoding 协商、只压文本、CPU 换带宽)。
详细版
GZIP 压缩的协商流程:
客户端 → 请求头:Accept-Encoding: gzip, deflate, br ← 我支持这些压缩
服务端 → 判断:响应是文本、支持 gzip、大小够大 → 压缩
服务端 → 响应头:Content-Encoding: gzip ← 我用了 gzip
→ 响应体:<gzip 压缩后的数据>
客户端 → 解压(看到 Content-Encoding: gzip 就解压)
<!-- Tomcat 配置 GZIP(server.xml Connector)-->
<Connector port="8080"
compression="on" // 开启压缩
compressionMinSize="2048" // 大于 2KB 才压(小的压了没意义)
noCompressionUserAgents="gozilla" // 某些 UA 不压
compressibleMimeType="text/html,text/css,application/javascript,application/json" />
<!-- 只压这些文本类型 -->
# Spring Boot 配置 GZIP(application.properties)
server.compression.enabled=true
server.compression.mime-types=text/html,text/css,application/javascript,application/json
server.compression.min-response-size=2048
⚠️ GZIP 压缩的关键原则是「只压该压的、压该压的场景」——用 CPU 开销换带宽/传输速度,用错了反而更糟。只压文本类(HTML、CSS、JS、JSON、XML 等)——文本有大量重复字符,压缩率高(常压到原来的 10%~30%);绝对不要压已经压缩过的二进制(JPG/PNG/GIF 图片、MP4 视频、zip/gz 文件)——它们已经是压缩格式,再用 GZIP 压不但几乎没效果、还白白消耗 CPU(甚至可能变大)。设置最小压缩大小(如 2KB)——太小的响应压缩的收益还不够压缩本身的开销(协商、压缩、加头)。权衡:GZIP 是「用 CPU 换带宽」——压缩要消耗服务端 CPU、解压要消耗客户端 CPU,但换来的是传输体积大幅减小、传输更快、省带宽;对文本响应通常划算(带宽是瓶颈、CPU 富余)。现代还有更好的压缩算法 Brotli(br)——压缩率比 GZIP 更高,很多 CDN/Nginx 支持。生产中静态资源+压缩通常在 Nginx/CDN 层做(更高效),Tomcat 只处理动态请求。
完整版教学
一、Tomcat 处理静态资源
先理解 Tomcat 怎么处理静态资源:
静态资源:不变的文件——HTML、CSS、JS、图片、字体、视频等
(相对"动态请求":需要程序处理、生成响应的)
Tomcat 处理静态资源——DefaultServlet:
Tomcat 有一个内置的 DefaultServlet(在 web.xml 里映射到 /)
→ 负责处理静态资源请求(读文件、返回)
功能:
① 读取静态文件、返回
② 支持缓存头:Last-Modified、ETag
→ 浏览器缓存,没变返回 304 Not Modified(省流量)
③ 支持 Range 请求(断点续传、视频拖动)
④ 目录列表(可配置)
缓存机制(静态资源优化):
Last-Modified:文件最后修改时间
→ 浏览器带 If-Modified-Since,没变返回 304
ETag:文件的标识(如内容 hash)
→ 浏览器带 If-None-Match,没变返回 304
Cache-Control/Expires:缓存时长
→ 浏览器直接用缓存,不请求服务端
生产的做法(不让 Tomcat 处理静态资源):
★ 通常交给 Nginx / CDN 处理静态资源
原因:
① Nginx 处理静态文件更高效(专门优化的)
② CDN 就近分发(用户从最近的节点拿,快)
③ 让 Tomcat 专注动态请求(别占 Tomcat 的线程/资源)
→ 静态资源 Nginx/CDN、动态请求 Tomcat
所以 Tomcat 用 DefaultServlet 处理静态资源,但生产常交给 Nginx/CDN
Tomcat 处理静态资源——内置 DefaultServlet(映射到 /,处理静态资源请求),功能:读文件返回、支持缓存头(Last-Modified/ETag,没变返回 304 省流量)、支持 Range 请求(断点续传/视频拖动)、目录列表。缓存机制:Last-Modified(+If-Modified-Since)、ETag(+If-None-Match)、Cache-Control(缓存时长)。生产做法:通常交给 Nginx/CDN(Nginx 处理静态文件更高效、CDN 就近分发快、让 Tomcat 专注动态请求)。理解「Tomcat 用 DefaultServlet 处理静态资源(读文件+缓存头 Last-Modified/ETag 返回 304+Range 断点续传);生产常交给 Nginx/CDN(更高效+就近分发+Tomcat 专注动态)」,就掌握了 Tomcat 处理静态资源。
二、GZIP 压缩是什么
理解 GZIP 压缩:
GZIP 压缩:
把响应体用 GZIP 算法压缩后再传输
→ 减小传输体积、加快传输、省带宽
为什么压缩有用:
文本类响应(HTML、CSS、JS、JSON)有大量重复内容
→ 压缩率高(常压到原来的 10%~30%)
例:100KB 的 JS 文件,GZIP 后可能只有 20~30KB
→ 传输更快、省带宽
压缩率(文本):
HTML/CSS/JS/JSON:压缩率高(70%~90% 减小)
→ 因为文本有很多重复字符、空格、关键字
工作原理(协商):
① 客户端请求头:Accept-Encoding: gzip
→ 告诉服务端"我支持 gzip 解压"
② 服务端判断:响应是文本、支持 gzip、够大 → 压缩响应
③ 服务端响应头:Content-Encoding: gzip
→ 告诉客户端"响应用了 gzip"
④ 客户端解压:看到 Content-Encoding: gzip → 解压
→ 协商:客户端说支持、服务端压缩并声明、客户端解压
代价(用 CPU 换带宽):
① 服务端压缩要 CPU
② 客户端解压要 CPU
→ 换来传输体积减小、传输更快、省带宽
→ 通常划算(带宽是瓶颈、CPU 富余)
所以 GZIP = 压缩文本响应减小体积(协商、Content-Encoding、CPU 换带宽)
GZIP 压缩——把响应体用 GZIP 算法压缩后传输(减小体积、加快传输、省带宽)。为什么有用:文本类响应有大量重复内容、压缩率高(常压到原来 10%~30%)(100KB JS 可能压到 20~30KB)。工作原理(协商):① 客户端请求头 Accept-Encoding: gzip(我支持解压)→ ② 服务端判断是文本/支持/够大就压缩 → ③ 响应头 Content-Encoding: gzip(我用了 gzip)→ ④ 客户端解压。代价(用 CPU 换带宽):压缩/解压要 CPU、换传输体积减小(通常划算,带宽瓶颈、CPU 富余)。理解「GZIP 压缩文本响应减小体积;文本压缩率高(10%~30%);协商:客户端 Accept-Encoding: gzip→服务端压缩+Content-Encoding: gzip→客户端解压;代价 CPU 换带宽通常划算」,就掌握了 GZIP 压缩。
三、只压该压的
GZIP 有个关键原则——「只压该压的」:
只压文本类(该压的):
HTML、CSS、JS、JSON、XML、SVG、纯文本
→ 有大量重复、压缩率高(该压)
绝对不压已压缩的(不该压的):
① 图片:JPG、PNG、GIF、WebP(已经是压缩格式)
② 视频:MP4、WebM(已压缩)
③ 压缩包:zip、gz、rar
④ 其他二进制压缩格式
→ 它们已经压过了,再 GZIP:
- 几乎没效果(压不动)
- 白白消耗 CPU(压缩开销)
- 甚至可能变大(压缩头开销)
→ 绝对不要压!
设置最小压缩大小:
太小的响应不压(如小于 1~2KB)
→ 小响应压缩的收益 < 压缩本身的开销(协商、压缩、加头)
compressionMinSize=2048(2KB)
配置压缩的类型(白名单):
compressibleMimeType="text/html,text/css,application/javascript,
application/json,..."
→ 只压这些类型(文本类)
→ 图片视频等不在列表(不压)
所以只压文本、大于阈值的,别压已压缩的和太小的
GZIP 的关键原则「只压该压的」:只压文本类(HTML/CSS/JS/JSON/XML/SVG,有大量重复、压缩率高);绝对不压已压缩的(图片 JPG/PNG、视频 MP4、压缩包 zip——已压过、再 GZIP 几乎没效果+白耗 CPU+可能变大)。设置最小压缩大小(太小的不压,小响应收益<压缩开销,compressionMinSize=2048)。配置压缩类型白名单(compressibleMimeType 只压文本类)。理解「只压该压的:压文本类(HTML/CSS/JS/JSON 压缩率高)、绝对不压已压缩的(图片/视频/压缩包,再压没效果+白耗 CPU+可能变大)、设最小压缩大小(太小不压)、配压缩类型白名单」,就掌握了这个关键原则。
四、Tomcat 配置 GZIP
理解 Tomcat 怎么配 GZIP:
Tomcat 配 GZIP(server.xml Connector):
<Connector port="8080"
compression="on" // 开启(on/off/force)
compressionMinSize="2048" // 最小压缩大小(字节)
compressibleMimeType="text/html,text/css,application/javascript,
application/json,application/xml" // 压的类型
noCompressionUserAgents="..." /> // 某些 UA 不压
关键参数:
compression:
on:满足条件才压(推荐)
force:强制压(不判断,一般不用)
off:不压
compressionMinSize:最小压缩大小(小的不压)
compressibleMimeType:压缩的 MIME 类型(文本类白名单)
Spring Boot 配置(内嵌 Tomcat):
server.compression.enabled=true
server.compression.mime-types=text/html,text/css,application/javascript,
application/json
server.compression.min-response-size=2048
生产的做法(GZIP 在哪做):
① Tomcat 直接压(配 Connector)
② 在 Nginx/CDN 压(gzip on; gzip_types ...)
→ 常见:Nginx 处理静态资源 + 压缩、Tomcat 处理动态
→ 或 CDN 压缩缓存
→ 生产常在 Nginx/网关层做压缩(更高效、集中管理)
所以 Tomcat 配 GZIP:compression=on + minSize + compressibleMimeType
生产常在 Nginx/CDN 做
Tomcat 配 GZIP(server.xml Connector):compression="on"(开启)、compressionMinSize(最小压缩大小)、compressibleMimeType(压的文本类型白名单)。关键参数:compression(on 满足条件才压/force 强制/off 不压)、compressionMinSize、compressibleMimeType。Spring Boot:server.compression.enabled+mime-types+min-response-size。生产做法:Tomcat 直接压或在 Nginx/CDN 压(常见 Nginx 处理静态资源+压缩、Tomcat 处理动态)。理解「Tomcat 配 GZIP:compression=on+compressionMinSize+compressibleMimeType(文本类白名单);Spring Boot server.compression.*;生产常在 Nginx/CDN 做压缩(更高效)」,就掌握了 Tomcat 配 GZIP。
五、其他压缩与优化
理解其他压缩算法和优化:
其他压缩算法:
① GZIP:最通用、支持最广
② Brotli(br):Google 出的,压缩率比 GZIP 更高(10%~20% 更小)
→ 很多 CDN/Nginx 支持,现代浏览器支持
→ Accept-Encoding: br
③ deflate:较老,用得少
静态资源的其他优化(配合压缩):
① 缓存(Cache-Control、ETag)——浏览器缓存,不重复请求
② CDN——就近分发、边缘缓存
③ 合并/压缩资源(构建时 minify JS/CSS)——减小文件本身
④ 图片优化(WebP、懒加载、响应式图片)
⑤ HTTP/2(多路复用、头压缩)
压缩 vs minify(区分):
minify(构建时):去掉 JS/CSS 的空格、注释、缩短变量名
→ 减小文件本身(源文件层面)
GZIP(传输时):传输时压缩
→ 减小传输体积(传输层面)
→ 两者配合:minify 后的文件再 GZIP(都用)
现代前端优化的完整链路:
minify(构建)→ 静态资源放 CDN → CDN 压缩(GZIP/Brotli)+ 缓存
→ 用户从 CDN 就近拿压缩后的文件(快)
所以除 GZIP 还有 Brotli(压缩率更高)、配合缓存/CDN/minify/HTTP2 优化
其他压缩和优化:其他压缩算法(GZIP 最通用、Brotli/br 压缩率更高 CDN 支持、deflate 较老);静态资源其他优化(缓存 Cache-Control/ETag、CDN 就近分发、minify 减小文件本身、图片优化 WebP、HTTP/2)。压缩 vs minify:minify(构建时去空格注释减小文件本身)、GZIP(传输时压缩减小传输体积)——两者配合。现代前端优化链路:minify→CDN→CDN 压缩+缓存。理解「其他压缩:GZIP 通用/Brotli 压缩率更高/deflate 老;优化:缓存/CDN/minify/图片/HTTP2;压缩(传输)vs minify(构建减小文件本身)配合;现代链路 minify→CDN 压缩+缓存」,就掌握了其他压缩与优化。
六、实践与总结
总结静态资源和 GZIP 的实践:
静态资源实践:
① 生产静态资源交给 Nginx/CDN(Tomcat 专注动态)
② 用缓存头(Cache-Control、ETag、Last-Modified)
③ CDN 就近分发
GZIP 实践:
① 开启 GZIP 压缩文本响应(HTML/CSS/JS/JSON)
② 只压文本、别压已压缩的(图片/视频/压缩包)
③ 设最小压缩大小(如 2KB)
④ 生产常在 Nginx/CDN 层做压缩
⑤ 考虑 Brotli(压缩率更高)
配置位置的选择:
Tomcat 直接配(compression):简单、内嵌场景
Nginx/CDN 配:生产常见(更高效、集中管理、配合缓存)
→ 有 Nginx/CDN 就在那层做(压缩 + 缓存 + 静态资源)
核心总结:
静态资源:Tomcat 用 DefaultServlet(缓存头/Range),生产交给 Nginx/CDN
GZIP:压缩文本响应减小体积(客户端 Accept-Encoding 协商、Content-Encoding)
只压文本(HTML/CSS/JS/JSON)、别压已压缩的(图片/视频)、设最小大小
用 CPU 换带宽,生产常在 Nginx/CDN 做,Brotli 压缩率更高
静态资源实践:生产交给 Nginx/CDN、用缓存头、CDN 就近分发。GZIP 实践:开启压缩文本响应、只压文本别压已压缩的、设最小压缩大小、生产常在 Nginx/CDN 做、考虑 Brotli。配置位置:Tomcat 直接配(简单/内嵌)或 Nginx/CDN 配(生产常见、更高效、配合缓存)——有 Nginx/CDN 就在那层做(压缩+缓存+静态资源)。理解「静态资源:生产交给 Nginx/CDN+缓存头;GZIP:压文本+别压已压缩+设最小大小+Nginx/CDN 层做+Brotli;有 Nginx/CDN 就在那层做压缩缓存静态资源」,就掌握了实践与总结。
记忆钩子:「①静态资源:Tomcat 内置 DefaultServlet 处理(读文件+缓存头 Last-Modified/ETag 返回 304 省流量+Range 断点续传),★生产通常交给 Nginx/CDN(更高效+就近分发+Tomcat 专注动态)②GZIP 压缩:把文本响应压缩后传减小体积(文本压缩率 70%~90%);协商:客户端请求头 Accept-Encoding: gzip(我支持)→服务端压缩+响应头 Content-Encoding: gzip(我用了)→客户端解压;★只压该压的:压文本类(HTML/CSS/JS/JSON),绝对不压已压缩的(图片 JPG/PNG/视频 MP4/zip,再压没效果+白耗 CPU+可能变大),设最小压缩大小(太小不压);代价 CPU 换带宽(通常划算);Tomcat 配 compression=on+compressibleMimeType,生产常在 Nginx/CDN 做;Brotli(br)压缩率更高;minify(构建减小文件本身)vs GZIP(传输压缩)配合」。
七、常见误区与追问
- 误区:所有响应都应该 GZIP 压缩。 只压文本类(HTML、CSS、JS、JSON 等,压缩率高);绝对不要压已经压缩过的二进制(图片 JPG/PNG、视频 MP4、zip 文件)——它们已经是压缩格式,再 GZIP 几乎没效果、还白白消耗 CPU、甚至可能变大;要配置压缩类型白名单只压文本。
- 误区:GZIP 压缩没有代价、越多越好。 有代价——GZIP 是「用 CPU 换带宽」:服务端压缩要消耗 CPU、客户端解压也要 CPU;对文本响应通常划算(带宽是瓶颈、压缩率高),但太小的响应压缩收益不够压缩开销(要设最小压缩大小如 2KB),已压缩的二进制压了白耗 CPU(别压)。
- 误区:生产环境应该让 Tomcat 处理静态资源。 通常不——生产环境一般把静态资源交给 Nginx/CDN 处理:Nginx 处理静态文件更高效、CDN 能就近分发和边缘缓存,让 Tomcat 专注处理动态请求(别占 Tomcat 的线程和资源);Tomcat 的 DefaultServlet 能处理静态资源,但不是生产的最优选择。
- 误区:GZIP 压缩和 minify(代码压缩)是一回事。 不同——minify 是构建时去掉 JS/CSS 的空格、注释、缩短变量名,减小文件本身(源文件层面);GZIP 是传输时用压缩算法压缩响应体,减小传输体积(传输层面);两者配合使用(minify 后的文件再 GZIP 传输),一个减小文件、一个减小传输。
- 追问:GZIP 压缩是怎么工作的? 通过内容协商:① 客户端在请求头带 Accept-Encoding: gzip,告诉服务端「我支持 gzip 解压」;② 服务端判断响应是否适合压缩(是文本类、支持 gzip、大小超过阈值),如果适合就用 GZIP 算法压缩响应体;③ 服务端在响应头加 Content-Encoding: gzip,告诉客户端「响应用了 gzip」;④ 客户端看到 Content-Encoding: gzip 就解压响应体;这样传输的是压缩后的小体积数据、加快传输、省带宽,代价是服务端压缩和客户端解压的 CPU 开销。
- 追问:为什么图片、视频不用 GZIP 压缩? 因为图片(JPG、PNG、GIF、WebP)、视频(MP4、WebM)、压缩包(zip、gz)本身已经是压缩格式了——它们内部已经用了专门的压缩算法(JPEG 压缩、H.264 等),数据已经很紧凑、几乎没有可压缩的冗余;再用 GZIP 压缩,几乎压不动(没效果)、还白白消耗服务端和客户端的 CPU、甚至可能因为 GZIP 的头部开销而变大;所以 GZIP 只压文本类(有大量重复内容、压缩率高),配置压缩类型白名单排除已压缩的二进制。
- 追问:静态资源和动态请求生产上怎么分工? 生产上通常:静态资源(HTML、CSS、JS、图片、字体)交给 Nginx/CDN 处理——Nginx 处理静态文件高效、支持缓存和压缩,CDN 就近分发、边缘缓存,用户从最近的节点拿;动态请求(需要程序处理、生成响应的 API、页面)转发给后端 Tomcat 处理;这样静态资源不占 Tomcat 的线程和资源、Tomcat 专注动态请求;架构是「用户 → CDN(静态)/ Nginx(反向代理)→ Tomcat(动态)」。
八、加强记忆
静态资源处理和 GZIP 压缩是 Web 性能优化的基础。① 静态资源(HTML、CSS、JS、图片等不变的文件)——Tomcat 内置 DefaultServlet 处理(读文件、缓存头 Last-Modified/ETag 没变返回 304 省流量、Range 断点续传);但生产通常交给 Nginx/CDN(Nginx 处理静态文件更高效、CDN 就近分发和边缘缓存、让 Tomcat 专注动态请求)。② GZIP 压缩——把响应体用 GZIP 算法压缩后传输,大幅减小体积(文本压缩率 70%~90%);协商流程:客户端请求头 Accept-Encoding: gzip(我支持)→ 服务端压缩 + 响应头 Content-Encoding: gzip(我用了)→ 客户端解压。关键原则「只压该压的」:只压文本类(HTML/CSS/JS/JSON,压缩率高),绝对不压已压缩的(图片 JPG/PNG、视频 MP4、zip——再压没效果 + 白耗 CPU + 可能变大),设最小压缩大小(太小的不压)。GZIP 是「用 CPU 换带宽」(通常划算)。Tomcat 配 compression="on" + compressibleMimeType(Spring Boot 用 server.compression.*);生产常在 Nginx/CDN 层做压缩(更高效);Brotli(br)压缩率比 GZIP 更高。minify(构建时减小文件本身)和 GZIP(传输时压缩)配合。一句话「静态资源:Tomcat DefaultServlet(缓存头/Range),生产交给 Nginx/CDN;GZIP 压缩文本响应减小体积(Accept-Encoding 协商、Content-Encoding);只压文本(HTML/CSS/JS/JSON)、别压已压缩的(图片/视频)、设最小大小;CPU 换带宽,生产在 Nginx/CDN 做,Brotli 压缩率更高」。