1 How to package a Springboot project into a war package
1.1 Environment preparation
The overall idea of packaging into a war is to check the web container dependencies and add the maven-war-plugin plug-in. Next, I will use the Tomcat container to give you a demonstration. It is effective in personal testing.
Let me explain the environment in the explanation to avoid causing unnecessary trouble to everyone because of environmental problems:
-
(1) Operating system: Win10
-
(2)IDE:IntelliJ IDEA 2021.3.2
-
(3) JDK version: 1.8
-
(4) Spring Boot version: 2.7.6
-
(5) Tomcat version: apache-tomcat-9.0.40
1.2 Create a SpringBoot project
1.3 Modify pom.xml file
1.3.1 Add war packaging method
In the project's pom.xml file, set the project packaging mode to war,
<packaging>war</packaging>
As shown below:
1.3.2 Exclude SpringBoot’s built-in tomcat
We now need to package the project into a war package, so there is no need to embed the web container when packaging, and it needs to be excluded. To exclude the embedded web container, you only need to modify the spring-boot-starter-web dependency of the pom.xml file and add the following exclusions attribute:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
1.3.3 Add tomcat container dependency
The tomcat container dependency has been excluded above. Why should the tomcat container be introduced here?
Because packaging into a war package allows the project to run in an external tomcat container, but we still need to use the tomcat container when developing and debugging. It is introduced here mainly to facilitate our development and debugging, so we need to set the scope to provided, as follows :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!-- 防止部分同学部分同学不明白参数的意义, 这里加些说明
1.test范围是指测试范围有效,在编译和打包时都不会使用这个依赖
2.compile范围是指编译范围内有效,在编译和打包时都会将依赖存储进去
3.provided依赖,在编译和测试过程中有效,最后生成的war包时不会加入 例如:
servlet-api,因为servlet-api在tomcat服务器已经存在了,如果再打包会冲突
4.runtime在运行时候依赖,在编译时候不依赖
5.system表示此依赖来自于外部jar, 而不是maven仓库
如果引入依赖未指定,默认依赖范围是compile
-->
<scope>provided</scope>
</dependency>
1.3.4 Add war packaging plug-in
Add a new label pair in the -label pair in the label pair and introduce the maven-war-plugin plugin:
<build>
<finalName>seckill-redis</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<!--
failOnMissingWebXml设置为false,意思是让系统忽略缺少WEB-INF的错误
-->
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
1.3.5 Set the final packaging project name
Set the final packaged project name under build. It’s okay if you don’t set it. The default display is the project name plus the version number.
<build>
<finalName>seckill-redis</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<!--
failOnMissingWebXml设置为false,意思是让系统忽略缺少WEB-INF的错误
-->
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
1.4 Modify the startup class of the project
The main modifications include:
-
(1) The startup class inherits SpringBootServletInitializer
-
(2) Rewrite the configure method
package com.kkarma;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class SeckillRedisApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SeckillRedisApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SeckillRedisApplication.class, args);
}
}
1.5 Use maven for packaging
-
(1) mvn clean
-
(2)mvn package
-
(3) Obtain the war package after packaging is completed
1.6 Use tomcat to deploy projects
-
(1) Place the war package in the webapps directory of tomcat.
-
(2) Start tomcat: bin/startup.bat
-
(3) localhost+tomcat port number+project name+interface for access.
The running port of the springboot project I set here is 8080, so my access address here is:
POST
http://localhost:8080/seckill-redis/seckill/ready
OK, the interface in the project It can be accessed normally and the project is packaged and deployed successfully.
2 The SpringBoot project introduces external Jar and packages it into a war package
The external jar was introduced successfully. If you use the external jar method to modify the project code in your own project, you need to repackage and deploy it.
Here we still use the same example as in How the SpringBoot project introduces external jars and packages the external jars into the project release jar package , introduce the guava-31.1-jre.jar package to implement a simple interface for demonstration
2.1 Introduce guava into the project
external jar packages, I use guava-31.1-jre.jar as a demonstration
Download address: https:// repo1.maven.org/maven2/com/google/guava/guava/31.1-jre/guava-31.1-jre.jar
Create a folder libs in the project root path and put guava-31.1-jre.jar under libs.
2.2 Modify pom.xml file
2.2.1 Introducing dependencies
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
<!--
scope=system表示此依赖是来自外部jar,而不是maven仓库
注意:
只有当scope设置为system时,systemPath属性才会生效
systemPath是一个物理文件路径,来指定依赖的外部jar在物理磁盘的位置
${project.basedir}代表项目根目录
-->
<scope>system</scope>
<systemPath>${project.basedir}/libs/guava-31.1-jre.jar</systemPath>
</dependency>
2.2.2 Modify packaging configuration
<build>
<finalName>seckill-redis</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<!--
failOnMissingWebXml设置为false,意思是让系统忽略缺少WEB-INF的错误
-->
<failOnMissingWebXml>false</failOnMissingWebXml>
<!--
外部jar包打包到当前项目需要增加以下属性配置
-->
<webResources>
<webResource>
<directory>${pom.basedir}/libs/</directory>
<targetPath>WEB-INF/lib/</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</webResource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
2.3 Create a test interface and use the classes in guava
package com.kkarma.controller;
import com.google.common.collect.Lists;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/app")
public class AppController {
@GetMapping("")
public Map<String, Object> index() {
Map<String, Object> map = new HashMap<>();
List<String> list = Lists.newArrayList("zhangsan", "lisi", "wangwu");
map.put("code", 200);
map.put("msg", "操作成功");
map.put("data", list);
return map;
}
}
2.4 Repackaging and deploying tests
After repackaging, we found that the external jar package we introduced was successfully packaged under the lib directory under the WEB-INF directory of the project
Re-deploy the war package to the webapp directory of tomcat
Restart the tomcat container before testing
Access interface test:
GET
http://localhost:8080/seckill-redis/app
OK, the interfaces in the project can be accessed normally. After introducing the external jar package, the project packaging and deployment are still successful.
3 How to run SpringBoot project in an external tomcat container
3.1 Configure tomcat container
- Click Edit Configurations
- Click the "+" sign, scroll down to find Tomcat Server and select Local
- Modify tomcat name and configure local tomcat
- Configure project package
- Customize the Application context (can be left unchanged)
Click apply and OK to complete the basic configuration. You can see the configured Tomcat in the Idea configuration.
3.2 Start Tomcat test
Note that you cannot right-click to start the class ExampleApplication and execute startup. Here we need to select our tomcat Server to start
The project is successfully deployed to tomcat and started
Access the interface that introduces the external jar package for testing and verification
OK, the project is packaged into a war package, and running access is still normal.
3.3 Frequently asked questions and solutions
3. Jars imported from outside cannot be accessed
solution
Create the directory src/main/webapp/WEB-INF/lib/ and place the external jar in this directory.
Of course, other places with references also need to modify the path accordingly, modify the path of maven-war-plugin:
<build>
<finalName>seckill-redis</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<!--
failOnMissingWebXml设置为false,意思是让系统忽略缺少WEB-INF的错误
-->
<failOnMissingWebXml>false</failOnMissingWebXml>
<!--
外部jar包打包到当前项目需要增加以下属性配置
-->
<webResources>
<webResource>
<directory>${pom.basedir}/src/main/webapp/WEB-INF/lib/</directory>
<targetPath>WEB-INF/lib/</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</webResource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
Normally, after modifying the configuration like this, it can be used normally. If it still doesn't work, then add another maven-compiler-plugin plug-in:
<!-- 设置javac编译器的版本和编码字符 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>utf8</encoding><!-- 编译器编码 -->
<compilerArguments>
<extdirs>${project.basedir}/src/main/webapp/WEB-INF/lib</extdirs>
</compilerArguments>
</configuration>
</plugin>
If this still doesn't work, haha, go to Baidu by yourself, because I haven't encountered the problem you encountered~