Spring Boot 第三篇:理解 spring-boot-starter-parent

简介: 基于 maven 的 Spring Boot 项目,我们通常会指定 spring-boot-starter-parent 作为当前项目 pom 的 parent,大多数人都知道这可以用于依赖管理,以便引入依赖时可以省略版本号,这篇我们聊点不一样的。

基于 maven 的 Spring Boot 项目,我们通常会指定 spring-boot-starter-parent 作为当前项目 pom 的 parent,大多数人都知道这可以用于依赖管理,以便引入依赖时可以省略版本号,这篇我们聊点不一样的。


maven 中的继承


spring-boot-starter-parent 作为 maven pom 中的 parent,我们需要先了解下 maven pom 中的 parent 有什么作用。


我们经常在多个项目中引入相同的依赖,如 Spring MVC 相关依赖。


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


对于相同的部分,作为程序员的我们下意识的会将其提取到公共的部分,maven 提供了类似 Java 的继承机制,只要将依赖加入到 parent,继承 parent 的项目会自动引入 parent 中的依赖。

定义如下的 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.zzuhkp</groupId>
    <artifactId>project-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.2.7.RELEASE</version>
        </dependency>
    </dependencies>
</project>


这里定义了一个名为 project-parent 的 maven 项目,并引入了 spring-boot-starter-web,再创建一个子项目。


<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.zzuhkp</groupId>
        <artifactId>project-parent</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <groupId>com.zzuhkp</groupId>
    <artifactId>spring-boot-child1</artifactId>
    <version>1.0-SNAPSHOT</version>
</project>


子项目 spring-boot-child1 项目中仅引入了上面我们定义的 parent,以相同的方式定义一个子项目 spring-boot-child2,借助 idea 内置 maven 支持功能,查看各项目的依赖情况。


image.png


可以看到,两个子项目都成功引入了 parent 中引入的依赖。不过可能不是所有的子项目都想要依赖 parent 中的依赖,maven 还支持在 parent 中定义依赖,子项目可以有选择性的引入 parent 的依赖。修改 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.zzuhkp</groupId>
    <artifactId>project-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>2.2.7.RELEASE</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>


和原始版本相比,这里唯一的变化是将 dependencies 元素移到了 dependencyManagement 元素内部。修改 spring-boot-child1 项目如下。

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.zzuhkp</groupId>
        <artifactId>project-parent</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <groupId>com.zzuhkp</groupId>
    <artifactId>spring-boot-child1</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>


与原始版本不同的是这里添加了 spring-boot-starter-web 依赖,由于 parent dependencyManagement 已经定义了依赖的 version,因此子项目直接进行了继承从而可以省略。再借助 idea 看下依赖。


image.png


这时 parent 和 spring-boot-child2 中的依赖都已经不见了,只有我们显式在 spring-boot-child1 中定义的依赖还在。


上面只是介绍了 maven dependencies 依赖与 dependencyManagement 依赖版本的继承,还有很多其他可以继承的元素,就不具体介绍了,我们重点关注的可以继承的元素如下。


groupId:项目组ID,项目坐标元素之一。

version:项目版本号,项目坐标元素之一。

properties:maven 属性信息,可以在其他标签中引入。

dependencies:项目依赖描述。

dependencyManagement:项目依赖管理描述。

build:构建相关配置,如源码目录、输出目录、插件等。

spring-boot-starter-parent

spring-boot-starter-parent 只用来作为其他 maven 项目的 parent,因此它除了 pom 文件并没有什么有效的内容,要理解 spring-boot-starter-parent,还得看它的 pom 文件定义。由于 pom 文件内容过长,下面我们分别进行介绍它主要引入的功能。


1. 依赖版本管理

spring-boot-starter-parent 自身并没有定义 dependencyManagement,依赖管理依托于它的 parent spring-boot-dependencies,见下图。


581.png


spring-boot-dependencies 内部定义了很多依赖,这样我们就不用关心依赖的版本了。



依赖管理是我们用的最多的功能,示例代码如下。


<?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>
    <parent>
        <version>2.2.7.RELEASE</version>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
    </parent>
    <groupId>com.zzuhkp</groupId>
    <artifactId>project-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>


2. 属性配置


spring-boot-starter-parent 添加了一些默认的配置,如指定了使用的 JDK 版本号为 1.8,编译时使用 UTF-8 编码方式。

591.png



3. 资源过滤


spring-boot-starter-parent 指定了编译资源文件时将 **/application*.properties、**/application*.yml 和 **/application*.yaml 中的 maven 占位符替换为具体的属性值。具体如下。


59.png


如果没有引入 spring-boot-starter-parent,需要在 application.properties 文件中使用 maven 占位符时切记要手动配置 resource。


4. 插件配置


spring-boot-starter-parent 内置了不少插件配置,我们重点关注 maven-compiler-plugin 和 spring-boot-maven-plugin。


对于 maven-compiler-plugin,spring-boot-starter-parent 主要配置了 parameters 参数,以便将方法参数名写入 class 文件。


60.png


对于 spring-boot-maven-plugin 插件,spring-boot-starter-parent 为其配置了 repackage 目标。


61.png


spring-boot-maven-plugin 插件 repackage 目标默认绑定 maven 声明周期中的 package 阶段,这样当打包后这个插件就会进一步将所有依赖的 jar 包以及当前项目的代码打包到一个 jar 包中,从而支持 jar -jar 启动 Spring Boot 项目。


spring-boot-starter-parent 指定 spring-boot-maven-plugin 插件目标后,当我们的项目指定了 parent 为 spring-boot-starter-parent 后,就可以省略插件目标配置了。


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.7.RELEASE</version>
    </parent>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


spring-boot-dependencies


spring-boot-dependencies 是 spring-boot-starter-parent 的好兄弟,由于 maven 只支持单继承,如果项目本身已经指定了其他 parent,则只能用 spring-boot-dependencies 进行依赖管理。


    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.7.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


加入上面的代码就可以注解引入 spring-boot-dependencies 中定义的依赖不用指定版本号了。


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


依赖版本升级


spring-boot-starter-parent 和 spring-boot-dependencies 都进行了依赖管理,如果依赖中存在漏洞我们就需要紧急进行修复,它们之间的升级方式有所不同。


对于 spring-boot-starter-parent 而言,我们可以直接在 properties 中指定依赖的版本。以前段时间暴露出来的 log4j 2 漏洞为例,为了升级 log4j 2 版本号,我们可以在自己的项目中进行如下配置。


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.7.RELEASE</version>
    </parent>
    <properties>
        <log4j2.version>2.17.2</log4j2.version>
    </properties>


指定 log4j2.version 属性是因为在 spring-boot-dependenciesloj4j 2 的坐标使用了这个属性值作为版本号,如下。


image.png

对于 spring-boot-dependencies,如果要进行依赖升级,配置属性是不行的,需要在 spring-boot-dependencies 前面加上要升级的依赖的坐标,示例如下。


    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-to-slf4j</artifactId>
                <version>2.17.2</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.7.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


如果要升级的依赖不是 spring-boot-starter-parentspring-boot-dependencies 管理的依赖,还可以直接把它加到 dependencies 标签下,这样依据最短路径原则,我们直接配置的依赖会覆盖间接引入的依赖,示例如下。


    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.17.2</version>
        </dependency>
    </dependencies>


总结

本文从 maven 中的继承开始讲起,然后介绍 spring-boot-starter-parent 与替代它的 spring-boot-dependencies,最后还介绍了 Spring Boot 项目的依赖版本升级。


在介绍 spring-boot-starter-parent 的时候我们提到了一个插件 spring-boot-maven-plugin 可以将项目打成可执行的 jar 包,这个插件除了打包,还具有在开发环境运行 Spring Boot 的项目的功能,下篇会重点介绍这个插件如何运行 Spring Boot 项目的。


目录
相关文章
|
13天前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
25 2
|
1月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
56 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
1月前
|
NoSQL Java Redis
redis的基本命令,并用netty操作redis(不使用springboot或者spring框架)就单纯的用netty搞。
这篇文章介绍了Redis的基本命令,并展示了如何使用Netty框架直接与Redis服务器进行通信,包括设置Netty客户端、编写处理程序以及初始化Channel的完整示例代码。
51 1
redis的基本命令,并用netty操作redis(不使用springboot或者spring框架)就单纯的用netty搞。
|
1月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
68 2
|
1月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
109 1
|
1月前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
28 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
1月前
|
Java API Spring
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中过滤器的基础知识和实战项目应用的教程。
27 0
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
|
1月前
|
Java 测试技术 Spring
springboot学习三:Spring Boot 配置文件语法、静态工具类读取配置文件、静态工具类读取配置文件
这篇文章介绍了Spring Boot中配置文件的语法、如何读取配置文件以及如何通过静态工具类读取配置文件。
61 0
springboot学习三:Spring Boot 配置文件语法、静态工具类读取配置文件、静态工具类读取配置文件
|
1月前
|
SQL Java 数据库
Springboot+spring-boot-starter-data-jdbc实现数据库的操作
本文介绍了如何使用Spring Boot的spring-boot-starter-data-jdbc依赖来操作数据库,包括添加依赖、配置数据库信息和编写基于JdbcTemplate的数据访问代码。
85 2
|
1月前
|
XML Java 应用服务中间件
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
182 2
下一篇
无影云桌面