【maven】maven聚合工程如何打包 解决maven pom.xml各种报错问题 规范pom文件

导入别人项目或者自己搭建项目时,每次必不可少都会遇到maven报错问题 (当然有可能是别人的项目pom写的不规范 自信点可能不是你的问题 但我们需要学会解决)。 这些问题 百度都不知道怎么查,最近着手自己搭建了一个springcloud聚合工程的demo 应该算是比较有代表性了,当然 springboot也可差不多 主要是理解maven的使用, 终于把这些给理解了个大概。文章有点长 原创不易

项目结构介绍: MySpringCloud为父模块,本文以红框内的模块举例, file为业务模块 调用了user-api工具模块,user-api引入了framework工具模块,两个工具模块被common模块管理
在这里插入图片描述

本文从多个层面分析maven综合报错问题:

  1. 首先一个比较低级的错误 一般有了开发经验不会犯 但是入门者可能会踩坑 要确保maven配置里面的maven仓库地址是可用的,典型错误:早期maven中央仓库是http传输的,后来改成了https, 网上可能还存在很多错误的mirrors配置 换句话说 仓库地址都是错误的 所以会导致所有依赖下载失败,此外 不同的仓库地址 某些依赖的groupId有可能会不同

在这里插入图片描述

  1. 确保了地址是可用的 groupId 和 artifactId都是无误:

    maven遇到的主要错误 应该属以下几个

    .A  Cannot resolve xxxx 错误 
    .B  Could not find artifact 错误
    .C  must be "pom" but is "jar"错误
    .D  程序包XXX 不存在
    .E Unable to find main class
    

解决方式:

  1. 低级错误1:找到本地maven仓库路径 查找 .lastUpdated 结尾的文件 全部删除 ,出现这种文件的情况可能由于网络不好,下载错误 并且它会阻止下次下载;
  2. 低级错误2:如果网络正常 且每次下载都是这个文件,那么很可能就是依赖版本号不正确,远程仓库根本没有这个包,所以一直都是 lastUpdated 。
    在这里插入图片描述
  3. 正文开始 用一个父子多模块maven项目 pom.xml文件实际举例 重点都在注释上面,顺便写了个英文版注释,因为xml比较容易乱码,项目几经周转很可能注释就乱了,这些注释就不复制出来了 研究这玩意 我累了。

父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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <!-- 子项目继承父项目pom文件时 父项目需要packing指定为pom
    daclare the packing:pom when child extends this moudule-->
    <packaging>pom</packaging>
    <groupId>com.demo</groupId>
    <artifactId>MySpringCloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>MySpringCloud</name>
    <description>Demo project for Spring Boot</description>

    <!-- 配置版本 version config 用于依赖管理版本号el表达式取值 
    act on dependencyManagement-dependencies-dependency-version by ${xxx.version}-->
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

        <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        <spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>

        <nacos.version>1.3.0</nacos.version>
        <sentinel.version>1.8.2</sentinel.version>
        <openfeign.version>2.2.5.RELEASE</openfeign.version>
        <netflix-hystrix.version>2.2.5.RELEASE</netflix-hystrix.version>

        <fastjson.version>1.2.76</fastjson.version>
        <servlet.version>4.0.1</servlet.version>
    </properties>

    <!-- author by qkj-->
    <!-- 声明依赖及其版本 但不引入, 子模块进行引入 (但子模块无需声明版本 否则会使用声明的版本号)-->
    <!-- note: dependencyManagement only declare the dependency Id and version but not import,
    child moudule should import again without declare the version when need dependency  -->

    <!-- 注意:dependencyManagement与dependencies区别 如果在父模块使用dependencies,子模块都继承,不管用不用得上-->
    <!-- note: difference with dependencies:child moudule extends dependencies unconditional   -->
    <dependencyManagement>

        <dependencies>
           <!-- diff:cloud-dependencies and cloud-starter?
            dependencies only declare the version and download jar with starter -->
            <!-- cloud-dependencies and cloud-starter 的区别 一般带 dependencies 的 artifactId 都是声明版本
            点进去看就能发现 里面是声明的dependencyManagement, 而starter则是我们要下载具体的xxx-starter.jar包-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <!-- 需要加上type 否则在阿里云可能下载不了
                declare type:pom  or maybe download fall in alibaba maven
                type pom: 已打包为pom工程-->
                <!-- 同理 如果我们写了一个聚合工程 且把聚合工程当成基础包供其它项目使用 
                其它项目把parent指定为基础包,并在依赖引入 声明type为pom即可 -->
                <type>pom</type>
            </dependency>

            <!-- alibaba与cloud整合 -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <!-- scope:import can only declare in dependencyManagement; resolve the problem of single extends -->
                <!--<scope>import</scope> 只会在dependencyManagement中出现-->
                <!-- 解决单继承问题 换句话说 加上import 可以使用spring-cloud-alibaba-dependencies面的dependencyManagement -->
                <!-- such as spring-cloud-alibaba-dependencies already include spring-cloud-starter-alibaba-nacos-discovery
                  child module can declare spring-cloud-starter-alibaba-nacos-discovery without version-->
                <scope>import</scope>
            </dependency>



            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
                <version>${lombok.version}</version>
            </dependency>

            <!--fastjson 过低版本会有漏洞(建议关注新版) low version such as 1.2.71 before with remote bug-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>

            <!-- nacos注册中心客户端 内置ribbon-->
            <dependency>
                <groupId>com.alibaba.nacos</groupId>
                <artifactId>nacos-client</artifactId>
                <version>${nacos.version}</version>
            </dependency>


            <!-- sentinel-->
            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-core</artifactId>
                <version>${sentinel.version}</version>
            </dependency>

            <!-- sentinel控制台-->
            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-transport-simple-http</artifactId>
                <version>${sentinel.version}</version>
            </dependency>

            <!--feign 依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
                <version>${openfeign.version}</version>
            </dependency>

            <!-- feign集成hystrix豪猪降级-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
                <version>${netflix-hystrix.version}</version>
            </dependency>

            <!-- servlet -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>${servlet.version}</version>
            </dependency>
            
           <!-- skywalking工具类:自定义链路追踪等-->
            <dependency>
                <groupId>org.apache.skywalking</groupId>
                <artifactId>apm-toolkit-trace</artifactId>
                <!-- 与sw版本对应 -->
                <version>${skywalking.version}</version>
            </dependency>

            <!-- skywalking和logback整合-->
            <dependency>
                <groupId>org.apache.skywalking</groupId>
                <artifactId>apm-toolkit-logback-1.x</artifactId>
                <version>${skywalking.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>

    <!-- 可以理解为声明子类(子模块) -->
    <modules>
        <module>common</module>
        <module>user</module>
        <module>file</module>
    </modules>

	 <!--注意 子模块有工具类(没有main方法的模块)
	  不能在父模块这里声明maven插件 子模块继承 会导致打包报错:找不到main方法(unalbe to find main class)  -->
<!--    <build>-->
<!--        <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>-->
<!--                <version>2.3.4.RELEASE</version>-->
<!--            </plugin>-->
<!--        </plugins>-->
<!--    </build>-->

</project>


子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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.demo</groupId>
        <artifactId>MySpringCloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <!-- 因为file是我们的业务模块 通俗点说是一个小项目 到时候要打包java -jar运行的 所以打包方式为jar(可以不写 默认为jar) 而不是pom-->
    <packaging>jar</packaging>
    <groupId>com.qkj</groupId>
    <artifactId>file</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>file</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <!-- 父模块该依赖为pom 子模块该依赖也尽量定义为pom
            父模块该依赖未使用<scope>import</scope>:当前模块如果还有子模块必须声明为pom 没有则随意 -->
            <!-- 但是父模块该依赖使用了import 可以理解为继承了该依赖内置的dependencyManagement 必须使用pom 且声明版本号-->
            <!-- must declare type:pom when child module exist or parent module dependency declare scope:import;
            version should be declared if parent module dependency declare scope:import,else type could be default or other-->
            <!-- so shoule better declare the type: pom -->
            <version>${spring-cloud.version}</version>
            <type>pom</type>
        </dependency>

        <!-- alibaba与cloud整合 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>${spring-cloud-alibaba.version}</version>
            <type>pom</type>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--fastjson 注意过低版本会有漏洞 low version such as 1.2.71 before with remote bug-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>

        <!-- nacos注册中心客户端 内置ribbon-->
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </dependency>

        <!-- sentinel-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-core</artifactId>
        </dependency>

        <!-- sentinel控制台-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-transport-simple-http</artifactId>
        </dependency>

        <!--feign 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- 豪猪熔断-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>


        <!--Nacos Discovery-->
        <!-- 在spring-cloud-alibaba-dependencies里面声明了版本 又因为设置了scope:import 所以在我们自己写的父模块pom文件中 不能显式看到-->
        <!-- declare in spring-cloud-alibaba-dependencies-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!--实现配置的动态变更-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <!-- skywalking工具类:自定义链路追踪等-->
        <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-trace</artifactId>
        </dependency>

        <!-- skywalking和logback整合 print traceId in our logs-->
        <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-logback-1.x</artifactId>
        </dependency>
        <dependency>
            <groupId>com.qkj</groupId>
            <artifactId>user-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <!-- scope :默认provided 没有传递性 ,compile具有传递性 换句话说就是会把jar包打进来,而runtime表示不作用在编译时 如JDBC驱动-->
            <!-- compile can pass on but provided(default) can't , runtime means not compile-->
            <scope>compile</scope>
        </dependency>


    </dependencies>

    <build>
        <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>
                <version>2.3.4.RELEASE</version>
            </plugin>
        </plugins>
    </build>

</project>




工具类父pom :common.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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.demo</groupId>
        <artifactId>MySpringCloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <packaging>pom</packaging>

    <groupId>com.qkj</groupId>
    <artifactId>common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>common</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <modules>
        <module>file-api</module>
        <module>user-api</module>
        <module>framework</module>
    </modules>


    <!-- 注意工具类pom中 不能有maven打包插件 同理 不能写在最外层的父级模块中 否则子模块会继承-->
</project>

工具类子pom : user-api.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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.qkj</groupId>
        <artifactId>common</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <packaging>jar</packaging>
    <artifactId>user-api</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>user-api</name>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--feign 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>


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

        <dependency>
            <groupId>com.qkj</groupId>
            <artifactId>framework</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <!-- scope :默认provided 没有传递性 ,compile具有传递性 换句话说就是会把jar包打进来,而runtime表示不作用在编译时 如JDBC驱动-->
            <!-- compile can pass on but provided(default) can't , runtime means not compile-->
            <scope>compile</scope>

        </dependency>

        <!-- 注意工具类pom中 不能有maven打包插件 同理 不能写在最外层的父级模块中 否则子模块会继承-->
    </dependencies>



</project>

工具类子pom: framework.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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.qkj</groupId>
        <artifactId>common</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <packaging>jar</packaging>
    <artifactId>framework</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>framework</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--feign 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

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

        <!-- servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
        </dependency>

    </dependencies>


</project>

什么时候可以不写version?

父pom dependencyManagement 里面声明了version, 而子pom继承了 父pom(parent 节点声明继承关系) ,子pom依赖不声明版本,则使用父pom依赖版本,这在多子模块项目中方便管理。 而整个pom不存在parent时,version是一定要写的,如果不写则会报错

type: 默认为jar 因为我们的是聚合工程,所以父模块要声明为pom,否则会报must be “pom” but is "jar"错误

总结:

  1. maven仓库地址有误或下载缓慢 网络不好 (推荐使用阿里仓库)
  2. 版本号错误 或缺少版本号
  3. 多模块项目中未正确声明父模块groupId artifactId
  4. pom工程中 未正确声明type
  5. 父模块中声明了maven打包插件 而子模块含有工具类模块

猜你喜欢

转载自blog.csdn.net/qq_36268103/article/details/119386201
今日推荐