my-webapp/
├── index.jsp # 靜態/動態頁面入口
├── css/, js/, images/ # 靜態資源目錄 (任意命名)
├── WEB-INF/ # 核心受保護目錄,**客戶端無法直接訪問**
│ ├── web.xml # 部署描述符 (Servlet 3.0+ 可選,註解替代)
│ ├── classes/ # 編譯後類文件與資源文件 (屬性文件、XML 配置等)
│ │ ├── com/
│ │ │ └── example/
│ │ │ ├── controller/
│ │ │ ├── service/
│ │ │ └── dao/
│ │ ├── log4j2.xml
│ │ └── db.properties
│ ├── lib/ # 第三方 JAR 包 (JDBC 驅動、框架庫、工具庫)
│ │ ├── spring-core-5.3.x.jar
│ │ ├── mysql-connector-java-8.x.jar
│ │ └── ...
│ └── *.tld # 標簽庫描述符 (可選)
└── META-INF/ # 構建工具生成 (MANIFEST.MF 等)
WEB-INF/web.xml —— 部署描述符@WebServlet, @WebFilter, @WebListener, @MultipartConfig),**web.xml 成為可選**。但仍建議保留用於:容器級配置 (如 <session-timeout>)、第三方庫無註解組件、環境差異化配置。web.xml → 註解掃描 → ServletContainerInitializer (Spring SpringServletContainerInitializer 啟動根上下文)。WEB-INF/classes/ —— 應用類與資源com.example.service.UserService.class 必須位於 classes/com/example/service/,**不能平鋪**。log4j2.xml、application.properties、mybatis-config.xml 等置於對應包路徑或 classes/ 根目錄,ClassLoader.getResourceAsStream() 統一訪問。target/classes、Gradle build/classes/java/main 打包時複製至此。WEB-INF/lib/ —— 依賴 JAR 庫.jar 並加入 WebApp ClassPath。maven-shade-plugin 重定位或 dependencyManagement 統一版本。**杜絕手動放 JAR**,統一由構建工具管理。| 類別 | 典型 JAR |
|---|---|
| Web 框架 | spring-webmvc, spring-boot-starter-web |
| ORM/數據庫 | mybatis, hibernate-core, mysql-connector-j, hikariCP |
| JSON/序列化 | jackson-databind, fastjson2, gson |
| 日志 | logback-classic, log4j2-api, slf4j-api |
| 工具庫 | guava, apache-commons-lang3, hutool |
| 模板引擎 | thymeleaf, freemarker |
<!-- Maven WAR 打包 -->
<packaging>war</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml> <!-- Servlet 3.0+ 可選 -->
</configuration>
</plugin>
</plugins>
</build>
執行 mvn package 自動產出 target/my-webapp.war,內部結構完全符合上述規範。
| 維度 | 傳統 WAR (部署到外部 Tomcat) | Spring Boot JAR (內嵌容器) |
|---|---|---|
| 打包格式 | WAR | 可執行 JAR (Fat JAR) |
| 啟動方式 | catalina.sh start 部署 WAR | java -jar app.jar |
| 靜態資源 | Web 根目錄 | classpath:/static/, /public/, /resources/, /META-INF/resources/ |
| 配置文件 | WEB-INF/classes/ | classpath:/application.yml (JAR 根目錄 BOOT-INF/classes/) |
| 依賴 JAR | WEB-INF/lib/ | JAR 內 BOOT-INF/lib/ |
| 類文件 | WEB-INF/classes/ | JAR 內 BOOT-INF/classes/ |
兼容性:Spring Boot 同時支持 spring-boot-maven-plugin 生成 **可部署 WAR** (繼承 SpringBootServletInitializer),滿足傳統應用服務器部署需求。
/WEB-INF/* 請求,**敏感配置 (DB 密碼、API Key) 僅放此處**。WEB-INF/views/ 或 WEB-INF/jsp/,配合 InternalResourceViewResolver 前綴/後綴解析。css/js/images 走 Nginx/CDN,**不經 Servlet 容器**,提升性能、降低應用服務器壓力。標準目錄結構是 **Servlet 規範與構建工具的契約**:
WEB-INF/web.xml (可選) 定義部署元數據。WEB-INF/classes/ 承載應用代碼與資源,**優先級最高**。WEB-INF/lib/ 承載所有第三方依賴,**由構建工具自動管理版本**。理解這三者的**類加載隔離、優先級、資源查找機制**,能快速排查:ClassNotFoundException、NoSuchMethodError (JAR 衝突)、配置文件讀取失效、熱部署不生效等經典問題。現代 Spring Boot 雖以 Fat JAR 重新定義結構,但**核心邏輯不變**:類與資源的物理位置決定了類加載器的可見性與優先級。