• Artifact(artifactId):项目(模块)名称,是当前项目在组中的唯一标识。
  • 推荐的做法是使用实际项目名称作为artifact的前缀 , 如appstore项目下的升级模块:appstore-upgrade。这样做的好处是方便寻找实际构件(jar包)默认情况下,Maven默认生成的构件会以artifactId作为开头,如appstore-upgrade-1.0.jar
  • Group+Artifact实际对应Java包的结构,是src/java/main目录中Java的目录结构,如com.xiaomi.mitv.appstore
  • Maven其中一个核心的作用就是管理项目的依赖,引入我们所需的各种jar包等
  • 为了能自动化地解析任何一个Java构件,Maven必须将这些jar包或者其他资源进行唯一标识,这是管理项目的依赖的基础,也就是我们要说的坐标
  • 包括我们自己开发的项目,也是要通过坐标进行唯一标识的,这样才能与其它项目中进行依赖引用
  • 在Maven仓库中存储所有Maven项目共享的构件,每个构件都有一个唯一的坐标,对应在仓库中的唯一存储路径,该路径与坐标的大致关系为:groupId/artifactId/version/artifactId-version.packaging
  • Java Archive(Java归档文件),jar包就是java的类进行编译生成的class文件打包的压缩包,包里面就是一些class文件
  • 在声明了main方法的类,并在jar文件中的META_INF/MANIFEST.MF文件中配置了Main-Class之后,是可以直接用 java -jar xxx.jar 通过内置的tomcat运行的,比较方便,简单
  • Web application Archive,与jar基本相同,但它通常表示这是一个Java的Web应用程序的包,是可以直接运行的web模块
  • Web项目有一个web资源目录,默认位置为src/main/webapp,其中需要包括WEB-INF目录,里面包含class文件、web.xml配置文件及前端页面文件,依赖的jar包在WEB-INF下的lib目录下
  • war包需要发布到一个容器里面,如将war包放在tomcat的webapps目录下,直接启动tomcat即可
  • src/main/java:项目主代码目录,项目的主代码最终会被打包到最终的构件中(jar包)
  • src/main/resources:项目主资源文件目录
  • src/main/test:项目测试代码目录,测试代码不会被打包
  • target:Maven构建的所有输出都在target目录中,项目主代码编译至target/classes,测试代码编译至target/test-classes
  • .idea存放项目的配置信息,包括历史记录,版本控制信息等(不会提交,可以设置隐藏)
  • .gitignore:用git做版本控制时 用这个文件控制那些文件或文件夹 不被提交(不用git的话可删除 没影响)
  • HELP.md:项目的帮助文档(不需要的话可删除 没影响)
  • mvnw(Maven wrapper):linux上处理mevan版本兼容问题的脚本(可删除 没影响)
  • mvnw.cmd:windows 上处理mevan版本兼容问题的脚本(可删除 没影响)
  • .mvn:Maven-wrapper.properties文件中记录你要使用的Maven版本,当用户执行mvnw clean 命令时,发现当前用户的Maven版本和期望的版本不一致,那么就下载期望的版本,然后用期望的版本来执行mvn命令(可删除)
  • appstore.iml:每个导入IDEA的项目都会生成一个项目同名的 .iml文件 用于保存你对这个项目的配置 (删了程序重新导入后还会生成 但由于配置丢失可能会造成程序异常)
  • 2、多模块项目搭建

    2.1、为什么搭建多模块项目?
  • 对项目按功能、业务模块划分,使项目结构更清晰,降低项目耦合性
  • 如电视商店项目,将电视商店的接口服务和升级服务拆分为单独的模块
  • 抽取公共模块,实现一处开发多处引用,提高代码复用率和开发效率,更利于项目后期的维护和升级
  • 如抽取common模块,放置共用的配置类、工具类、常量、枚举等
  • 子模块的pom文件会继承父工程的pom文件,依赖jar包版本统一交由父pom来管理
  • 2.2 、多模块项目建议
  • 一个项目的子模块都应该使用相同的groupId
  • 如果它们一起开发和发布,还应该使用同样的version
  • 一个项目的子模块的artifactId还应该使用一致的前缀,以方便同其他项目区分
  • 子模块的目录名称应当与其artifactId一致,即artifactId=项目名
  • 子模块的包名,如groupId为com.xiaomi.mitv,artifactId为appstore-common,那么此子模块的包名应为 com.xiaomi.mitv.appstore.common
  • 2.3、多模块项目搭建示例:
    2.3.1、新建父模块
  • File-->New-->Project-->Maven
  • Finish
  • 删除src目录
  • 选择Parent,然后填写模块名即可,GroupId、ArtifactId、Version会自动填充
  • Finish,父模块pom.xml中会自动在modules标签内添加新增的子模块
    <parent>
        <artifactId>appstore</artifactId>
        <groupId>com.xiaomi.mitv</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>appstore-common</artifactId>

    parent元素声明了父模块,parent下的子元素artifactId,groupId,version指定了父模块的坐标,这三个元素是必须的

    元素relativePath元素表示父父模块pom的相对路径,默认值为 ../pom.xml,也就是说,Maven默认父pom在上一层目录下

    父模块与子模块的目录结构不一定是父子关系,也可以是平行目录结构。这时,需要修改relativePath元素的值,指定父pom的位置,父模块pom中module元素的值也需要做相应的修改,以指向正确的子模块目录

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.xiaomi.mitv</groupId>
    <artifactId>appstore</artifactId>
    <packaging>pom</packaging>
    <version>1.0</version>
    <modules>
        <module>appstore-common</module>
        <module>appstore-upgrade</module>
    </modules>
    <groupId>com.xiaomi.mitv</groupId> <artifactId>appstore-common</artifactId> <version>1.0</version> </dependency> </dependencies>
    Maven按照父POM中modules标签的顺序读取POM,如果该POM没有依赖模块,那么就构建该模块,否则就先构建其依赖模块,如果该依赖还依赖其他模块,则进一步先构建依赖的依赖。
    模块间的依赖关系会将反应堆构成一个有向非循环图(Directed Acyclic Graph,GAP),各个模块是该图的节点,依赖关系构成了有向边。这个图不允许出现循环,也就是Maven不允许循环依赖,当出现模块A依赖于B,而B又依赖于A的情况时,Maven就会报错
    [INFO] Reactor Build Order:
    [INFO] 
    [INFO] appstore                                                           [pom]
    [INFO] appstore-common                                                    [jar]
    [INFO] appstore-upgrade                                                   [jar]
    2.4.4、自定义模块之间的依赖
    创建多环境配置文件时,需要遵循Spring Boot允许的命名约定来命令,格式为application-{profile}.properties,其中{profile}为对应的环境标识
    在resources目录下分别创建application-dev.properties、application-pre.properties、application-prd.properties,分别对应开发、预览、生产环境的配置文件
    其中application.properties为项目主配置文件,包含项目所需的所有公共配置
    当激活的环境对应的文件中配置项与application.properties中配置项相同时,会覆盖application.properties中的配置项
    3.1.2、多环境的切换
  • application.properties配置文件中增加如下配置项:
  • spring.profiles.active=dev
  • IDEA编译器指定项目启动环境
  • 我们可以在IDEA的Run/debug Configuration 页面配置项目启动环境。
  • <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <executions> <execution> <id>copy-resources</id> <phase>validate</phase> <!--在default生命周期的validate阶段执行copy-resources操作--> <goals> <goal>copy-resources</goal> </goals> <configuration> <!--复制到哪--> <outputDirectory>${basedir}/target/classes</outputDirectory> <!--资源文件属性过滤--> <resources> <resource> <directory>../appstore-config/dev</directory> <filtering>true</filtering> <!--复制哪些文件--> <includes> <include>logback.xml</include> <include>redis.properties</include> </includes> </resource> </resources> </configuration> </execution> </executions> </plugin> </plugins> </build> </profile> <profile> <id>pre</id> <properties> <active.env>pre</active.env> </properties> ...... </profile> </profiles>
    Maven <properties>中配置了 db.username=xiaomi,那么${db.username}只有在POM中才会被解析为具体的值xiaomi,如果是在 src/main/resources内的配置文件中引用了${db.username},构建的时候,它仍然为${db.username},不会被解析为具体的值xiaomi。
    因此, 需要让Maven解析资源文件中的Maven属性
    在pom中配置资源文件的目录,并开启资源属性过滤,如下,即可让maven-resources-plugin插件在将资源文件复制到编译输出目录中时,解析资源文件中的Maven属性
    <directory>${basedir}/src/main/resources</directory> <filtering>true</filtering> <!--只对资源目录下的某些文件开启Maven属性过滤--> <includes> <include>xxx.properties</include> </includes> </resource> </resources> </build>
    SpringBoot 1.3或更高版本,将Maven属性占位符修改为了 @xxx@,要想继续使用${}占位符,需要在POM properties中指定<resource.delimiter>${}</resource.delimiter>