Maven技术求助:将Spring Boot War项目web-inf/classes下的类打包为Jar并存入web-inf/lib的方法
Hey there! I've run into this exact scenario before when working with Spring Boot WAR projects, so let's break down how to solve this—with both a quick single-module fix and a more maintainable multi-module approach.
Option 1: Single-Module Configuration (Using Maven Plugins)
If you want to keep your project as a single module, you can use maven-jar-plugin to generate your project's JAR, then configure maven-war-plugin to include this JAR in WEB-INF/lib while excluding the default classes directory.
Step 1: Configure maven-jar-plugin to generate your JAR
Add this to your <build><plugins> section in pom.xml—this will create a JAR of your compiled classes during the package phase:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <id>package-project-jar</id> <phase>package</phase> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin>
Step 2: Configure maven-war-plugin to use the JAR and exclude classes
Next, update the maven-war-plugin (or add it if it's not there) to:
- Exclude the auto-generated
WEB-INF/classesdirectory from the WAR - Copy the JAR you just built into
WEB-INF/lib
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.2</version> <configuration> <!-- Prevent the default classes directory from being packaged --> <warSourceExcludes>WEB-INF/classes/**</warSourceExcludes> <!-- Add our generated JAR to WEB-INF/lib --> <webResources> <resource> <directory>${project.build.directory}</directory> <includes> <include>${project.build.finalName}.jar</include> </includes> <targetPath>WEB-INF/lib</targetPath> </resource> </webResources> <!-- Disable web.xml check if you're using Spring Boot without a traditional web.xml --> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin>
Run mvn clean package and you'll see your WAR now contains your project JAR in WEB-INF/lib, with no classes directory inside.
Option 2: Multi-Module Project (Recommended Best Practice)
While the single-module fix works, splitting your project into modules is a cleaner, more maintainable approach that aligns with Maven's design. Here's how to set it up:
- Parent Module: Acts as the root, managing dependencies and modules.
- Core Module: A JAR module containing all your business logic, entities, services, etc.
- Web Module: A WAR module that depends on the core JAR, containing only web-related code (controllers, Spring Boot starter class, web config).
Parent Module pom.xml
<groupId>com.example</groupId> <artifactId>MavenWeb-parent</artifactId> <version>0.0.1</version> <packaging>pom</packaging> <modules> <module>MavenWeb-core</module> <module>MavenWeb-web</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.15</version> <!-- Use your Spring Boot version --> <relativePath/> </parent>
Core Module pom.xml
<parent> <groupId>com.example</groupId> <artifactId>MavenWeb-parent</artifactId> <version>0.0.1</version> </parent> <artifactId>MavenWeb-core</artifactId> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- Add other dependencies your business logic needs --> </dependencies>
Web Module pom.xml
<parent> <groupId>com.example</groupId> <artifactId>MavenWeb-parent</artifactId> <version>0.0.1</version> </parent> <artifactId>MavenWeb-web</artifactId> <packaging>war</packaging> <dependencies> <!-- Depend on your core module --> <dependency> <groupId>com.example</groupId> <artifactId>MavenWeb-core</artifactId> <version>0.0.1</version> </dependency> <!-- Web-specific dependencies --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- For external Tomcat deployment (optional) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.2</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </build>
When you run mvn clean package from the parent module, the core JAR will be built first, then the web WAR will automatically include this JAR in WEB-INF/lib. The web module's classes directory will only contain its own web-specific code (like the Spring Boot starter class), which is typically minimal.
Key Notes
- The multi-module approach is better for long-term maintenance, especially as your project grows.
- For the single-module setup, ensure the
maven-jar-pluginruns beforemaven-war-plugin—since both are bound to thepackagephase, Maven will execute them in the order they appear in yourpom.xml.
Let me know if you hit any snags while setting this up—I’m happy to help troubleshoot!
内容的提问来源于stack exchange,提问作者Yang Kai

