
Spring Boot 默认不支持 JSP,当访问 JSP 路径时浏览器直接下载文件,本质是响应头 Content-Type 未正确设为 text/html,导致服务端未解析 JSP。根本原因包括:缺少 tomcat-embed-jasper 依赖、打包方式错误、路径配置偏差、JSP 存放位置不符规范,以及 Spring Boot 3.x 对 JSP 的兼容性限制。
spring boot 默认不支持 jsp,当访问 jsp 路径时浏览器直接下载文件,本质是响应头 `content-type` 未正确设为 `text/html`,导致服务端未解析 jsp。根本原因包括:缺少 `tomcat-embed-jasper` 依赖、打包方式错误、路径配置偏差、jsp 存放位置不符规范,以及 spring boot 3.x 对 jsp 的兼容性限制。
在 Spring Boot 项目中,JSP 页面被浏览器自动下载(而非渲染)是一个典型且高频的问题。其表象是:输入 http://localhost:9091/home 后,浏览器弹出 home.jsp 下载提示,打开下载文件可见原始 JSP 源码(含 和 EL 表达式未执行),说明服务器未触发 JSP 编译与 Servlet 转换流程——这并非前端问题,而是服务端视图解析链断裂所致。
? 核心原因与逐项修复方案
✅ 1. 必须添加并正确配置 tomcat-embed-jasper(关键依赖)
Spring Boot 内置 Tomcat 是精简版,默认移除了 JSP 支持模块。仅靠 spring-boot-starter-web 无法解析 .jsp 文件。需显式引入编译器依赖:
<!-- pom.xml 中替换原有依赖 --> <dependency><groupid>org.apache.tomcat.embed</groupid><artifactid>tomcat-embed-jasper</artifactid><!-- ⚠️ 重点:务必移除 scope="provided" --><!-- Spring Boot 3.x 推荐不指定 version,由 parent 自动对齐嵌入式 Tomcat 版本 --></dependency>
? 为什么 scope="provided" 会导致失败?
provided 表示该依赖仅在编译和测试期有效,运行时不会打入最终包。而 JSP 解析发生在运行期(JspServlet 初始化阶段),若依赖缺失,则容器跳过 JSP 处理流程,直接以静态资源方式返回 .jsp 文件(HTTP 响应头为 Content-Type: application/octet-stream),浏览器即触发下载。
✅ 2. 打包方式必须为 WAR(强制要求)
Spring Boot 官方明确:JSP 仅支持 WAR 部署模式(Spring Boot 官方文档 §3.6.1)。JAR 包无法提供 ServletContext 所需的 WEB-INF 资源结构及 JSP 编译上下文。
修改 pom.xml:
<packaging>war</packaging>
同时,主类需继承 SpringBootServletInitializer 并重写 configure() 方法,以支持外部/内置 Tomcat 启动:
@SpringBootApplication
public class SpringBootFirstApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SpringBootFirstApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SpringBootFirstApplication.class, args);
}
}
✅ 3. JSP 文件路径必须严格遵循标准 Web 结构
Spring Boot 的 InternalResourceViewResolver 依赖传统 Servlet 规范路径。JSP 不可放在 src/main/resources 或 static/templates 目录下。
✅ 正确路径(唯一有效位置):
src/main/webapp/WEB-INF/jsp/home.jsp
⚠️ 注意:
- webapp 目录需在 IDEA 中标记为 Web Resource Root(右键 → Add Framework Support → Web → 设置 webapp 为 Web Resources Directory);
- WEB-INF 是受保护目录,禁止直接通过 URL 访问,必须经 Controller 转发(如 return "home");
- 若你当前 application.properties 中配置了 spring.mvc.view.prefix=/views/,则需同步调整 JSP 存放路径为 src/main/webapp/WEB-INF/views/home.jsp,并确保前缀匹配。
✅ 4. 检查 application.properties 配置细节(易忽略的空格陷阱)
你当前配置:
spring.mvc.view.prefix=/views/ spring.mvc.view.suffix=.jsp
✅ 正确,但请手动检查 .jsp 后是否有多余空格或不可见字符(常见于复制粘贴)。一个隐藏空格会导致 ViewResolver 无法匹配后缀,降级为静态资源处理——直接返回原始文件。
建议改用 application.yml 避免此类问题:
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
server:
port: 9091
✅ 5. Spring Boot 版本兼容性警告(重要!)
你使用的是 Spring Boot 3.1.0(基于 Jakarta EE 9+)。而 tomcat-embed-jasper 在 Spring Boot 3.x 中已不再官方推荐用于生产环境,且存在以下限制:
- 依赖 javax.servlet.* 包(如 javax.servlet.jsp.JspFactory)在 Jakarta EE 9+ 中已迁移至 jakarta.servlet.*,旧版 Jasper 无法兼容;
- Spring Boot 3.x 默认启用 spring-boot-starter-tomcat 的 Jakarta 版本,与传统 JSP API 冲突;
- 官方文档明确指出:“JSPs are not supported with embedded containers in Spring Boot 3.x”。
? 务实建议:
- ✅ 短期开发调试:降级至 Spring Boot 2.7.18(最后一个支持 JSP 的稳定版本),并配合 Tomcat 9.x;
- ✅ 长期生产方案:彻底弃用 JSP,迁移到现代模板引擎(Thymeleaf、Freemarker)或前后端分离架构(Vue/React + REST API);
- ❌ 不建议在 Spring Boot 3.x 中强行启用 JSP,即使临时成功也面临维护性差、安全更新滞后等风险。
? 验证步骤(按顺序执行)
- 修改 pom.xml:
war + 移除 tomcat-embed-jasper 的 scope; - 创建目录 src/main/webapp/WEB-INF/jsp/,将 home.jsp 放入其中;
- 更新 application.properties 前缀为 /WEB-INF/jsp/;
- 主类继承 SpringBootServletInitializer;
- 清理 Maven:mvn clean → 重启应用;
- 访问 http://localhost:9091/home —— 应正常渲染 HTML,而非下载。
? 总结
JSP 在 Spring Boot 中属于“向后兼容特性”,其工作依赖于严格的 WAR 结构、特定依赖组合与历史版 Servlet API。自动下载的本质是服务端未识别 .jsp 为可执行视图资源。解决的关键在于:依赖注入(非 provided)、WAR 打包、标准路径、无空格配置、版本兼容。对于新项目,请优先选择 Thymeleaf 等现代化方案;若必须使用 JSP,请锁定 Spring Boot 2.7.x 生态,并严格遵循上述规范。










