在 Spring Boot 开发中,我们通常使用嵌入式 Servlet 容器(如 Tomcat),它能将应用打包成可执行 JAR,简化部署流程。但在某些场景下(如需要支持 JSP、复杂的容器定制或企业级部署规范),我们需要使用外置 Servlet 容器。本文将详细介绍如何配置 Spring Boot 使用外置 Tomcat,并解释其工作原理。
一、嵌入式与外置 Servlet 容器对比
特性 | 嵌入式 Servlet 容器(JAR 包) | 外置 Servlet 容器(WAR 包) |
---|---|---|
打包方式 | 可执行 JAR | WAR 包 |
容器位置 | 内置在应用中 | 独立安装在服务器上 |
JSP 支持 | 默认不支持(需额外配置) | 原生支持 |
定制灵活性 | 有限(需通过配置类) | 高(可直接修改容器配置) |
部署方式 | 直接运行 JAR 文件 | 部署到外置容器(如 Tomcat) |
适用场景 | 快速开发、微服务、简单部署 | 企业级应用、需要 JSP、复杂配置 |
二、使用外置 Servlet 容器的步骤
1. 创建 WAR 项目
首先,需要创建一个 WAR 类型的 Maven 项目。在 IDEA 中,可通过以下方式配置:
- 新建项目时选择 "Spring Initializr"
- 打包方式选择 "War"
- 勾选 "Spring Web" 依赖
项目结构如下(重点关注与 JSP 相关的目录):
wservlet/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/qcby/wservlet/
│ │ │ ├── controller/ // 控制器
│ │ │ ├── WservletApplication.java // 主程序类
│ │ │ └── ServletInitializer.java // 外置容器启动器
│ │ ├── resources/
│ │ │ └── application.properties // 配置文件
│ │ └── webapp/ // Web资源目录(外置容器必需)
│ │ ├── WEB-INF/
│ │ │ └── jsp/ // JSP页面目录
│ │ └── WEB-INF/web.xml // Web配置(可选)
│ └── pom.xml // 依赖配置
2. 配置依赖(pom.xml)
核心是将嵌入式 Tomcat 设置为provided
(仅编译时生效,不打包到 WAR 中),并指定打包方式为war
:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" ...><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.9.RELEASE</version></parent><groupId>com.qcby</groupId><artifactId>wservlet</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging> <!-- 打包为WAR --><dependencies><!-- Web核心依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 嵌入式Tomcat设为provided(不打包) --><dependency><groupId>orgId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope> <!-- 关键配置 --></dependency></dependencies><build><plugins><!-- 编译版本配置 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><!-- Spring Boot打包插件 --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
关键说明:provided
scope 确保嵌入式 Tomcat 不会被打包到 WAR 中,避免与外置容器冲突。
配置项目的目录结构
3. 编写 ServletInitializer 类
外置容器启动时,不会执行 Spring Boot 主类的main
方法,而是通过SpringBootServletInitializer
子类初始化应用。因此需要创建该类:
package com.qcby.wservlet;import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;// 继承SpringBootServletInitializer,用于外置容器启动
public class ServletInitializer extends SpringBootServletInitializer {@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application) {// 传入Spring Boot主程序类,关联应用上下文return application.sources(WservletApplication.class);}
}
作用:相当于传统 Web 项目的web.xml
,负责在容器启动时加载 Spring Boot 应用。
4. 配置主程序类
主程序类与普通 Spring Boot 应用一致,但需确保@SpringBootApplication
注解正确:
package com.qcby.wservlet;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class WservletApplication {// 主方法(嵌入式容器启动入口,外置容器时不执行)public static void main(String[] args) {SpringApplication.run(WservletApplication.class, args);}
}
5. 配置 JSP 视图(可选)
外置容器天然支持 JSP,需在application.properties
中配置视图解析器:
# 应用名称
spring.application.name=wservlet# JSP视图配置
spring.mvc.view.prefix=/WEB-INF/jsp/ # JSP文件存放路径
spring.mvc.view.suffix=.jsp # 视图后缀
创建 JSP 页面(src/main/webapp/WEB-INF/jsp/suc.jsp
):
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Success</title>
</head>
<body><h1>Hello, 外置Tomcat!</h1>
</body>
</html>
6. 创建控制器
编写一个简单的控制器,映射请求到 JSP 视图:
package com.qcby.wservlet.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
@RequestMapping("/suc")
public class SucController {// 映射路径:/suc/index@RequestMapping("/index")public String index() {System.out.println("访问suc页面");return "suc"; // 对应WEB-INF/jsp/suc.jsp}
}
7. 部署到外置 Tomcat
-
下载并安装 Tomcat:从官网下载 Tomcat(建议 8.5 + 版本),解压到本地目录。
-
打包 WAR 文件:
- 在 IDEA 中执行
mvn clean package
,生成 WAR 包(位于target/wservlet-0.0.1-SNAPSHOT.war
)。 - 可将 WAR 包重命名为简化名称(如
wservlet.war
)。
- 在 IDEA 中执行
-
部署到 Tomcat:
- 将 WAR 包复制到 Tomcat 的
webapps
目录下。 - 启动 Tomcat(执行
bin/startup.bat
或bin/startup.sh
)。 - Tomcat 会自动解压 WAR 包并部署应用。
- 将 WAR 包复制到 Tomcat 的
-
访问应用:
- 地址格式:
http://localhost:8080/[WAR包名称]/[请求路径]
- 示例:
http://localhost:8080/wservlet/suc/index
,将显示 JSP 页面内容。
- 地址格式:
三、工作原理:JAR 与 WAR 启动差异
-
JAR 包启动(嵌入式容器):
- 执行
main
方法,通过SpringApplication.run()
启动 IOC 容器。 - 自动创建嵌入式 Servlet 容器(如 Tomcat),并将应用部署到该容器。
- 执行
-
WAR 包启动(外置容器):
- 外置容器(如 Tomcat)启动时,会扫描
webapps
目录下的 WAR 包。 - 执行
ServletInitializer
的configure
方法,初始化 Spring 应用上下文。 - 由外置容器接管请求处理,不再依赖嵌入式容器。
- 外置容器(如 Tomcat)启动时,会扫描
核心区别:外置容器的生命周期由容器本身管理,Spring Boot 应用作为 Web 应用被部署,而非作为独立进程运行。
四、常见问题与解决方案
-
JSP 页面 404 错误:
- 检查
spring.mvc.view.prefix
是否正确(需对应webapp/WEB-INF/jsp/
)。 - 确保
webapp
目录在src/main
下(IDEA 默认资源目录)。
- 检查
-
依赖冲突:
- 避免引入与外置容器版本冲突的依赖(如不同版本的 Tomcat API)。
- 确保
spring-boot-starter-tomcat
的 scope 为provided
。
-
访问路径问题:
- 外置容器部署时,应用上下文路径为 WAR 包名称(可在 Tomcat 的
server.xml
中自定义)。
- 外置容器部署时,应用上下文路径为 WAR 包名称(可在 Tomcat 的