Tomcat 中的默认 Servlet:DefaultServlet 与 JspServlet
在 Tomcat 的 conf/web.xml 配置文件中,定义了两个核心的默认 Servlet:DefaultServlet 和 JspServlet。它们是 Tomcat 处理请求的基础组件,分别负责静态资源和 JSP 页面的处理。理解这两个 Servlet 的作用和配置,有助于更好地掌握 Tomcat 的请求处理流程。
DefaultServlet:静态资源的默认处理器
DefaultServlet 是 Tomcat 的核心默认 Servlet,其 url-pattern 配置为 /,意味着当客户端请求无法匹配任何其他 Servlet 时,将由它来处理。它的主要职责是处理静态资源(如 HTML、CSS、JS、图片等),并提供基础的目录列表功能。
配置详解
conf/web.xml 中对 DefaultServlet 的默认配置如下:
1 | <servlet> |
核心功能
处理静态资源:
当请求的资源是静态文件(如index.html、style.css、image.png等)且未被其他 Servlet 映射匹配时,DefaultServlet会从应用的docBase目录(通常是webapps/应用名)中查找并返回该文件。目录列表功能:
若请求的路径是一个目录(如http://localhost:8080/myapp/files/),且该目录下没有欢迎文件(如index.html),listings参数决定是否返回目录文件列表:listings=true:返回目录中所有文件的列表(类似 FTP 目录浏览)。listings=false(默认):返回 403 禁止访问错误。
缓存优化:
DefaultServlet内置了静态资源缓存机制,通过设置Expires和Cache-Control响应头,减少重复请求,提升性能。可通过初始化参数进一步配置缓存策略,例如:1
2
3
4<init-param>
<param-name>cacheMaxAge</param-name>
<param-value>3600</param-value> <!-- 静态资源缓存时间(秒) -->
</init-param>支持部分请求(断点续传):
支持 HTTP 范围请求(Range头),允许客户端断点续传大文件(如视频、压缩包)。
实际应用场景
- 所有未被自定义 Servlet 映射的静态资源请求,均由DefaultServlet处理。例如:
- 访问
http://localhost:8080/myapp/js/main.js时,若没有 Servlet 映射*.js,则由DefaultServlet返回该 JS 文件。
- 访问
- 可通过覆盖应用自身的
web.xml调整DefaultServlet配置(如开启目录列表、修改缓存时间)。
JspServlet:JSP 页面的专用处理器
JspServlet 负责处理所有 JSP 页面(.jsp 和 .jspx)的请求。JSP 本质上是一种特殊的 Servlet(会被编译为 Java 类),而 JspServlet 则是这个编译和执行过程的管理者。
配置详解
conf/web.xml 中对 JspServlet 的默认配置如下:
1 | <servlet> |
工作原理
JspServlet 处理 JSP 请求的流程如下:
- 接收请求:当客户端请求
.jsp或.jspx资源时(如http://localhost:8080/myapp/index.jsp),请求被JspServlet拦截。 - 检查编译状态:
- 若 JSP 文件是首次被访问,或已被修改(最后修改时间晚于编译后的 class 文件),则触发编译流程。
- 若 JSP 文件未被修改且已编译,则直接使用已生成的 class 文件。
- 编译 JSP:
- 第一步:将 JSP 文件转换为 Java 源文件(Servlet 代码),默认存放于
work/Catalina/localhost/应用名/目录下。 - 第二步:将 Java 源文件编译为 class 字节码文件。
- 第一步:将 JSP 文件转换为 Java 源文件(Servlet 代码),默认存放于
- 执行 Servlet:
构造编译后的 Servlet 实例,调用其_jspService方法处理请求,生成 HTML 响应返回给客户端。
关键初始化参数
JspServlet 提供了多个初始化参数,用于控制 JSP 编译和执行行为:
| 参数名 | 作用说明 | 默认值 |
|---|---|---|
fork |
是否使用独立进程编译 JSP(true 表示使用,避免编译过程影响 Tomcat 主线程)。 |
false |
xpoweredBy |
是否在响应头中添加 X-Powered-By: JSP/2.3 标识。 |
false |
compiler |
指定 JSP 编译器(如 javac)。 |
系统默认 |
classdebuginfo |
是否在编译的 class 文件中包含调试信息。 | true |
trimSpaces |
是否删除 JSP 生成的 HTML 中的多余空格。 | false |
development |
是否启用开发模式(修改 JSP 后自动重新编译)。 | true |
开发模式 vs 生产模式
开发模式(默认):
development=true时,Tomcat 会自动检测 JSP 文件的修改,每次访问都会重新编译(若有更新),便于开发调试。生产模式:
部署到生产环境时,建议将development设为false,并预编译所有 JSP(避免首次访问时的编译延迟):
1 | <init-param> |
两个默认 Servlet 的关系与请求匹配优先级
Tomcat 处理请求时,会按照 Servlet 映射的优先级匹配请求路径,规则如下:
- 精确匹配:优先匹配精确的
url-pattern(如/login)。 - 路径匹配:匹配带有
*的路径模式(如/user/*)。 - 扩展名匹配:匹配
*.xxx形式的模式(如*.jsp由JspServlet处理)。 - 默认匹配:所有未被匹配的请求,由
DefaultServlet(url-pattern="/")处理。
示例:
- 请求
http://localhost:8080/myapp/login.jsp会被JspServlet(*.jsp)匹配。 - 请求
http://localhost:8080/myapp/css/style.css会被DefaultServlet处理(无其他匹配)。 - 请求
http://localhost:8080/myapp/user/123若匹配自定义 Servlet 的/user/*,则由该 Servlet 处理,否则由DefaultServlet处理。
自定义与优化建议
优化静态资源处理:
可通过修改DefaultServlet的缓存参数提升静态资源加载速度:1
2
3
4<init-param>
<param-name>cacheMaxAge</param-name>
<param-value>86400</param-value> <!-- 缓存 24 小时 -->
</init-param>禁用目录列表:
生产环境务必保持listings=false,防止目录结构暴露(安全风险)。JSP 预编译:
生产环境中,使用 Tomcat 提供的jspc工具预编译 JSP,避免运行时编译开销:1
2# 预编译 myapp 应用的所有 JSP
$CATALINA_HOME/bin/jspc -p myapp -d $CATALINA_HOME/webapps/myapp/WEB-INF/classes -v $CATALINA_HOME/webapps/myapp覆盖默认配置:
若需在单个应用中修改配置,可在应用的WEB-INF/web.xml中重新定义DefaultServlet或JspServlet(会覆盖全局配置)。