1 Introduction
Although the official recommendation of the SpringBoot project is to use the jar package to publish, it can also be published as a war package and published to external web containers (such as Jetty, tomcat, etc.). Next we discuss how to package a Spring Boot project into a war package.
More reference: "Two Ways War and Jar to Release SpringBoot Project to Server" .
2. Build a Spring Boot project
2.1 Create Spring Boot Directory
Refer to "Maven's Agreement" to manually create a project directory. Of course, you can definitely use the IDE to create.
# 存放pom.xml和所有的子目录
~/Desktop$ mkdir FlowerShop
# 项目的java源代码
~/Desktop/FlowerShop$ mkdir -p src/main/java
# 创建包com.flower和com.flower.controller
~/Desktop/FlowerShop$ mkdir -p src/main/java/com/flower/controller
# 目录结构
~/Desktop/FlowerShop$ tree -L 6
.
└── src
└── main
└── java
└── com
└── flower
└── controller
This directory is enough for what we will demonstrate.
2.2 Initialize pom.xml
Create pom.xml
~/Desktop/FlowerShop$ touch pom.xml
content in pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.flower</groupId>
<artifactId>FlowerShop</artifactId>
<version>1.0-SNAPSHOT</version>
<!--指定打包类型:pom,war,jar-->
<packaging>war</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<!--指定打包的名称:FlowerShopDemo.war或FlowerShopDemo.jar-->
<finalName>FlowerShopDemo</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.3 Create a startup class
Create MainApplicationStarter.java startup class
~/Desktop/FlowerShop$ touch src/main/java/com/flower/MainApplicationStarter.java
~/Desktop/FlowerShop$ vim src/main/java/com/flower/MainApplicationStarter.java
Contents in MainApplicationStarter.java
package com.flower;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication
public class MainApplicationStarter{
public static void main(String[] args) {
SpringApplication.run(MainApplicationStarter.class, args);
}
}
2.4 Create Controller
Create HomeController.java
~/Desktop/FlowerShop$ touch src/main/java/com/flower/controller/HomeController.java
~/Desktop/FlowerShop$ vim src/main/java/com/flower/controller/HomeController.java
Content in HomeController.java
package com.flower.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController{
@GetMapping("/home")
public String getHomePage() {
return "I Love you to come to my Flower Shop!";
}
}
2.5 Run the test
~/Desktop/FlowerShop$ mvn spring-boot:run
The SpringBoot project was created successfully! Before adjusting the project, the war package is deployed to Jetty9, and an error will be reported when starting:
~/Documents/jetty-distribution-9.4.27.v20200227/bin$ ./jetty.sh start
...
2020-04-15 11:00:30.101:WARN:oejw.WebAppContext:main: Failed startup of context o.e.j.w.WebAppContext@a859c5{FlowerShopDemo,/FlowerShopDemo,file:///tmp/jetty-0_0_0_0-8888-FlowerShopDemo_war-_FlowerShopDemo-any-8018217352624732370.dir/webapp/,UNAVAILABLE}{/home/kyun/Documents/jetty-distribution-9.4.27.v20200227/webapps/FlowerShopDemo.war}
java.util.ServiceConfigurationError: org.apache.juli.logging.Log: Provider org.eclipse.jetty.apache.jsp.JuliLog not a subtype
at java.util.ServiceLoader.fail(ServiceLoader.java:239)
at java.util.ServiceLoader.access$300(ServiceLoader.java:185)
at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:376)
at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
at org.apache.juli.logging.LogFactory.<init>(LogFactory.java:91)
at org.apache.juli.logging.LogFactory.<clinit>(LogFactory.java:66)
at org.apache.tomcat.websocket.WsWebSocketContainer.<init>(WsWebSocketContainer.java:92)
...
3. Adjust SpringBoot project to prepare for war package
3.1 Modify pom.xml
org.apache.juli.logging.Log: Provider org.eclipse.jetty.apache.jsp.JuliLog not a subtype
: The JuliLog provided by the Jetty container is not a subclass of org.apache.juli.logging.Log, which is caused by the loading mechanism of Jetty (the problem is not directly deployed to tomcat) The pom.xml is modified as follows:
- Spring-boot-starter-web dependency excludes tomcat
- Introduce spring-boot-starter-jetty dependencies
- Comment out the spring-boot-maven-plugin plugin
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.flower</groupId>
<artifactId>FlowerShop</artifactId>
<version>1.0-SNAPSHOT</version>
<!--指定打包类型pom, war, jar-->
<packaging>war</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 移除嵌入式tomcat插件 -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入Jetty依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
<build>
<!--指定打包的名称:FlowerShopDemo.war或FlowerShopDemo.jar-->
<finalName>FlowerShopDemo</finalName>
<plugins>
<!--<plugin>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-maven-plugin</artifactId>-->
<!--</plugin>-->
</plugins>
</build>
</project>
3.2 Modify the startup class
Because we want to start the project with an external web container, the startup class must inherit SpringBootServletInitializer and override the configure method. If you use the embedded web container, you do not need to inherit SpringBootServletInitializer.
package com.flower;
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 MainApplicationStarter extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(MainApplicationStarter.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
// 注意这里要指向原先用main方法执行的Application启动类
return builder.sources(MainApplicationStarter.class);
}
}
4. Package war to Jetty9
Pack
~/Desktop/FlowerShop$ mvn clean package
Copy the FlowerShop / target / xxx.war package to Jetty's webapps directory, restart Jetty, enter in the browser:
success!
note:
The officially recommended deployment method of the SpringBoot project is the jar package operation mode, ie nohup java -jar xxx.jar &
.
If you want to use jar package deployment, then you need to restore, but do not need to restore all, just add back to the
spring-boot-maven-plugin plugin:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
Welcome attention