springboot 打包与启动01. maven引入及打包方式

709 阅读2分钟

在使用maven构建springboot项目时,springboot相关jar包可以使用parent方式引入(即在pom.xmlparent节点引入springbootGAV:org.springframework.boot:spring-boot-starter-parent:2.1.1.RELEASE),也可以使用非parent方式引入(即在pom的dependencyManagement节点引入springbootGAV:org.springframework.boot:spring-boot-dependencies:2.1.1.RELEASE)。同时,在打包时,我们可以打成jar包,也可以打成war包,本文旨在梳理各引入、打包方式的异同。

1. parent方式引入,打成jar包

parent方式,即在pom文件中,将springboot的依赖当成项目的parent引入,pom文件示例如下:

<?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>

    <!-- 引入springboot的parent -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
    </parent>

    <groupId>com.gitee.funcy</groupId>
    <artifactId>springboot-parent-jar</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    <name>springboot parent jar打包方式</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
    </properties>

    <dependencies>
        <!-- springboot 的基础依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- springboot 的web 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- maven编译插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <!-- springboot编译插件 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <!-- 其他内容不用指定,因为 spring-boot-starter-parent 已经指定了-->
            </plugin>
        </plugins>
    </build>

</project>

添加一个controller:

package com.gitee.funcy.mavenparent.jar.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * {这里添加描述}
 *
 * @author funcy
 * @date 2019-12-13 10:43 下午
 */
@RestController
public class IndexController {

    @RequestMapping("/")
    public String helloWorld() {
        return "hello world";
    }

}

再引入启动类:

package com.gitee.funcy.mavenparent.jar;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * {这里添加描述}
 *
 * @author funcy
 * @date 2019-12-13 10:36 下午
 */
@SpringBootApplication
public class Main {

    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }

}

运行Main方法,请求http://localhost:8080/,结果如下:

 $ curl http://localhost:8080/
hello world

可以看到,项目运行成功。

接着,尝试使用jar包启动:

# 打包
 mvn clean install -Dmaven.test.skip=true
 # 启动jar包
 java -jar target/springboot-parent-jar-1.0.0.jar

可以看到,项目启动成功,请求请求http://localhost:8080/,也能显示正确结果。

2. 非parent方式引入,打成jar包

在实际项目中,项目的parent依赖可能给了其他项目,此时parent引用就无法进行了,这时我们需要非parent引入。非parent引入的pom如下:

<?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.gitee.funcy</groupId>
    <artifactId>springboot-jar</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    <name>springboot非parent jar打包方式</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-boot.version>2.1.1.RELEASE</spring-boot.version>
        <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <!-- Import dependency management from Spring Boot -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <!-- 与parent引入相比,需要指定goals,否则会打包失败-->
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

再添加一个ControllerIndexController.java与启动类Main.java,这两个文件与上述示例相同,这里就不作展示了。

运行Main方法,请求http://localhost:8080/,结果如下:

 $ curl http://localhost:8080/
hello world

可以看到,项目运行成功。

接着,尝试使用jar包启动:

# 打包
 mvn clean install -Dmaven.test.skip=true
 # 启动jar包
 java -jar target/springboot-jar-1.0.0.jar

可以看到,项目启动成功,请求请求http://localhost:8080/,也能显示正确结果。

3. parent方式引入,打成war包

以上两种方式都是打成jar,为了兼容传统的servlet应用,springboot也支持打包war包,parent引入打包war包的pom文件如下:

<?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>

    <!-- 引入springboot的parent -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
    </parent>

    <groupId>com.gitee.funcy</groupId>
    <artifactId>springboot-parent-war</artifactId>
    <version>1.0.0</version>
    <!-- 指定打包方式为war包 -->
    <packaging>war</packaging>
    <name>springboot parent war打包方式</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <!-- 保持与 spring-boot-dependencies 版本一致 -->
                <version>3.2.2</version>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

再添加一个ControllerIndexController.java与启动类Main.java,这两个文件与上述示例相同,这里就不作展示了。

除此之外,war包方式还需要添加一个类,用以实现SpringBootServletInitializer,该类与启动类Main.java位于同一个包下,主要是用来引导tomcat等servlet容器加载servlet,内容如下:

/**
 * {这里添加描述}
 *
 * @author funcy
 * @date 2019-12-20 1:22 下午
 */
public class StartApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        // 注意这里要指向原先用main方法执行的Application启动类
        return builder.sources(Main.class);
    }
}

运行Main方法,请求http://localhost:8080/,结果如下:

 $ curl http://localhost:8080/
hello world

可以看到,项目运行成功。

接着,尝试使用jar包启动:

# 打包
 mvn clean install -Dmaven.test.skip=true
 # 启动jar包
 java -jar target/springboot-parent-war-1.0.0.jar

可以看到,项目启动成功,请求请求http://localhost:8080/,也能显示正确结果。

4. 非parent方式引入,打成war包

同样地,打成war包时,也可使用非parent引入方式:

<?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.gitee.funcy</groupId>
    <artifactId>springboot-war</artifactId>
    <version>1.0.0</version>
    <!-- 指定打包方式为war包 -->
    <packaging>war</packaging>
    <name>springboot非parent war打包方式</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-boot.version>2.1.1.RELEASE</spring-boot.version>
        <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <!-- Import dependency management from Spring Boot -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 测试war包中 WEB-INF/lib-provided/ 目录内容-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <!-- 打成war包时,需要添加该插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <!-- 保持与 spring-boot-dependencies 版本一致 -->
                <version>3.2.2</version>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

再添加一个ControllerIndexController.javaStartApplication.java与启动类Main.java,这三个文件与上述示例相同,这里就不作展示了。

运行Main方法,请求http://localhost:8080/,结果如下:

 $ curl http://localhost:8080/
hello world

可以看到,项目运行成功。

接着,尝试使用jar包启动:

# 打包
 mvn clean install -Dmaven.test.skip=true
 # 启动jar包
 java -jar target/springboot-war-1.0.0.jar

可以看到,项目启动成功,请求请求http://localhost:8080/,也能显示正确结果。

5. 总结

springboot 引入及打包方式组合下来有如下四种:

打包/引入parent方式非parent方式
jarparent-jar方式非parent-jar方式
warparent-war方式非parent-war方式