黑马课程
文章目录
- 1. 分模块开发
- 1.1 分模块开发入门案例
- 示例:抽取domain层
- 示例:抽取dao层
- 1.2 依赖管理
- 2. 聚合和继承
- 2.1 聚合
- 概述
- 聚合实现步骤
- 2.2 继承 dependencyManagement
- 3. 属性管理
- 3.1 依赖版本属性管理
- 3.2 配置文件属性管理(了解)
- 3.3 Maven中的属性(了解)
- 3.4 版本说明
- 4. 多环境配置与应用
- 4.1 多环境开发
- 4.2 跳过测试
- 5. 私服
- 5.1 私服安装
- 步骤1:下载和解压nexus
- 步骤2:启动nexus
- 步骤3:访问nexus服务器
- 报错问题
- 步骤4:关闭nexus
- 步骤5: 修改配置
- 5.2 私服中的仓库分类
- 5.3 本地仓库访问私服配置
- 步骤1:私服上配置仓库
- 步骤2:配置本地仓库对私服的访问权限
- 步骤3:配置私服的访问路径
- 5.4 私服资源上传和下载
1. 分模块开发
将原始模块按照功能拆分成若干个子模块,方便模块间的相互调用,接口共享
例如:订单模块和商品模块。订单必然用到商品,如何使商品中的实体类对订单可见?
1.1 分模块开发入门案例
示例:抽取domain层
步骤1:新建一个模块
步骤2:将原Book模块里的domain里面的实体类复制到新的模块maven_pojo里面,并删除Book模块里的domain
步骤3:在Book模块中引入maven_pojo的依赖
<!-- 引入其他模块 -->
<!-- maven_pojo实体类模块 -->
<dependency>
<groupId>org.example</groupId>
<artifactId>maven_pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
步骤4:将maven_pojo模块打包安装到本地仓库中
此后即可正常使用
如何使自己本地仓库里的模块给其他人员使用?——私服
示例:抽取dao层
抽取dao层,步骤类似,maven_dao所需的依赖如下
<dependencies>
<!-- maven_pojo实体类模块 -->
<dependency>
<groupId>org.example</groupId>
<artifactId>maven_pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- spring-webmvc(含有@Respository注解) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
1.2 依赖管理
依赖传递
A引入B,B引入C,那么A也引入了C,这就是依赖的传递性
- 直接依赖:A引入B,B是A的直接依赖
- 间接依赖:A引入B,B引入C,C是A的间接依赖
依赖冲突
项目引入了同一个依赖的不同版本
- 路径最短:A和B同时依赖了X,依赖路径最短的会被使用
- 路径相同时在前者优先:依赖路径相同,在pom中先导入依赖版本被使用
可选依赖
<!-- maven_pojo实体类模块 -->
<dependency>
<groupId>org.example</groupId>
<artifactId>maven_pojo</artifactId>
<version>1.0-SNAPSHOT</version>
<optional>true</optional>
</dependency>
- 设置optional为true:对外隐藏当前所依赖的资源,该依赖只在当前模块中使用
排除依赖
模块A引入模块B,解决依赖冲突时,可选依赖是从模块B入手,排除依赖是从模块A入手
<!-- maven_dao实体类模块 -->
<dependency>
<groupId>org.example</groupId>
<artifactId>maven_dao</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.example</groupId>
<artifactId>maven_pojo</artifactId>
</exclusion>
</exclusions>
</dependency>
springmvc_ssm中,通过在 <exclusion>
在maven_dao中排除掉maven_pojo中的依赖
依赖冲突问题排查
-
IDEA排查(推荐)
-
打印所有依赖的依赖树
mvn dependency:tree # 可以将依赖树输出到文件中 mvn -Dverbose dependency:tree -Doutput=E://depTree.txt
2. 聚合和继承
- 聚合用于快速构建项目,对项目进行管理
- 继承用于快速配置和管理子项目中所使用jar包的版本
- 聚合与继承均属于设计型模块,并无实际的模块内容
2.1 聚合
概述
聚合出现背景
- 前面学习的分模块开发流程
- 创建模块 – install到本地仓库 – 引入模块
- 存在的问题
- 每个创建模块必须 install
- 模块的任意修改都需要重新 install 一次
- 假设对ssm_pojo进行了修改,那么所有引用它的项目都需要重新编译一次,可能出现遗漏的项目未编译
聚合就是为了解决上述问题产生的
聚合的思想:通过一个只有pom.xml的空项目,来管理所有的模块,进行自动 install 和 对项目的重新编译
概述
- 聚合:将多个模块组织成一个整体,同时进行项目构建的过程称为聚合
- 聚合工程:通常是一个不具有业务功能的"空"工程(有且仅有一个pom文件)
- 作用:使用聚合工程可以将多个工程编组,通过对聚合工程进行构建,实现对所包含的模块进行同步构建
- 当工程中某个模块发生更新(变更)时,必须保障工程中与已更新模块关联的模块同步更新,此时可以使用聚合工程来解决批量模块同步构建的问题。
聚合实现步骤
步骤1:创建一个空的maven项目 maven_01_parent
使用01这样的编号更加直观,之前的maven项目也可以改为 maven_02_pojo maven_03_dao
步骤2:在pom.xml中设置打包方式为pom
<packaging>pom</packaging>
- 默认打包方式:jar
- web项目打包方式:war
- 聚合工程打包方式:pom
步骤3: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>org.example</groupId>
<artifactId>maven_01_parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- 设置管理的模块名称 -->
<modules>
<module>../springmvc_ssm</module>
<module>../maven_pojo</module>
<module>../maven_dao</module>
</modules>
</project>
步骤4:使用聚合统一管理项目
对 maven_01_parent 进行 compile,它会将包括自身在内的4个模块一起编译
不管pom.xml添加module的顺序如何,compile都会自动根据依赖关系来决定先后的构建关系
2.2 继承 dependencyManagement
继承是用来解决重复依赖的问题
-
简化配置
-
减少版本冲突
步骤1:在子工程中的pom.xml中配置<parent>
标签
父工程一般为聚合工程,即maven_01_parent,于是在子工程 springmvc_ssm、maven_pojo、maven_dao 中作如下配置
<!-- 配置当前工程继承自parent工程 -->
<parent>
<groupId>org.example</groupId>
<artifactId>maven_01_parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../maven_01_parent/pom.xml</relativePath>
</parent>
步骤2:优化子项目共有依赖导入问题
将子项目共同使用的jar包都抽取出来,维护在父项目的pom.xml中
删除子项目中被抽取的jar包
<dependencies>
<!-- mvc相关 -->
<!-- javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<!-- mybatis相关 -->
<!-- mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- 测试相关 -->
<!-- spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
步骤3:优化子项目依赖版本问题
上述设置会导致子项目多出很多不需要的依赖
例如 maven_domain 模块不需要引入任何依赖,但配置父项目后,就包括了父项目中的全部依赖
可以通过<dependencyManagemen>
来优化管理,以依赖 junit 为例
-
在父工程中删除 junit 依赖,同时添加如下依赖管理
<!-- 定义依赖管理 --> <dependencyManagement> <dependencies> <!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement>
-
在需要用到 junit 的子项目中,引入依赖
<!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency>
注意!子项目中引入依赖时不再需要写 version,从而实现统一依赖版本
3. 属性管理
3.1 依赖版本属性管理
需求:希望将所有版本为5.2.10.RELEASE的依赖改为5.1.9.RELEASE
- 手动修改:每次修改多个,容易遗漏
- 方案:将版本号抽取为一个参数
步骤1:父工程中定义属性
<!-- 定义属性 -->
<properties>
<spring.version>5.2.10.RELEASE</spring.version>
<junit.version>4.12</junit.version>
</properties>
步骤2:修改依赖的version
<!-- spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
3.2 配置文件属性管理(了解)
需求:在之前的springmvc_ssm项目中,有一个jdbc.properties的配置文件,里面定义了driver, url, username, password 这4个属性
现在希望通过maven_01_parent来管理jdbc.properties里面的属性值
步骤1:父工程定义属性
<!-- maven_01_parent中定义属性 -->
<properties>
...
<jdbc.url>jdbc:mysql://localhost:3306/ssm_db?useSSL=false&useServerPrepStmts=true</jdbc.url>
</properties>
步骤2:设置maven过滤文件范围
<!-- maven_01_parent中 -->
<build>
<resources>
<resource>
<!-- Maven在默认情况下是从当前项目的 src\main\resources 下读取文件进行打包
${project.basedir}: 当前项目所在目录,子项目继承了父项目,相当于所有的子项目都添加了资源目录的过滤 -->
<directory>${project.basedir}/src/main/resources</directory>
<!-- 设置能够解析${},默认是false -->
<filtering>true</filtering>
</resource>
</resources>
</build>
说明:
<directory>../springmvc_ssm/src/main/resources</directory> 只管理springmvc_ssm里面的resources
<directory>${project.basedir}/src/main/resources</directory> 管理所有模块的resources
如果希望只管理某几个子项目,可以写多个<resource>标签
步骤3:jdbc.properties文件中引用属性
# 子模块中
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=${jdbc.url}
jdbc.username=root
jdbc.password=123456
刷新maven,可以看到项目结构的变化
步骤4:测试是否生效
install命令将springmvc_ssm打成war包,在本地仓库找到对应的war包
在路径 springmvc_ssm-1.0-SNAPSHOT.war\WEB-INF\classes
中打开生成的jdbc.properties,可以看到 jdbc.url 的值已经被添加
运行项目,正常执行
注意
如果缺乏web.xml文件,打包时可能报错:Error assembling WAR: webxml attribute is required
可以通过将web.xml添加上去解决,也可以通过以下命名忽略web.xml的检查
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
3.3 Maven中的属性(了解)
查看属性:在cmd窗口中输入
mvn help:system #查看所有属性
在程序中使用某个属性,只需要
${java.runtime.name}
3.4 版本说明
在jar包的版本定义中,有两个工程版本用的比较多:
- SNAPSHOT(快照版本)
- 项目开发过程中临时输出的版本,称为快照版本
- 快照版本会随着开发的进展不断更新
- RELEASE(发布版本)
- 项目开发到一定阶段里程碑后,向团队外部发布较为稳定的版本,这种版本所对应的构件文件是稳定的
- 即便进行功能的后续开发,也不会改变当前发布版本内容,这种版本称为发布版本
此外还经常能看到一些发布版本:
- alpha版:内测版,bug多不稳定内部版本不断添加新功能
- beta版:公测版,不稳定(比alpha稳定些),bug相对较多不断添加新功能
- 纯数字版
4. 多环境配置与应用
4.1 多环境开发
在maven_01_parent里面配置多环境
需要删除之前在属性里配置的jdbc.url,然后再加入以下配置
<!-- 配置多环境 -->
<profiles>
<!-- 1. 开发环境 -->
<profile>
<id>env_dep</id>
<properties>
<jdbc.url>jdbc:mysql://127.1.1.1:3306/ssm_db?useSSL=false&useServerPrepStmts=true</jdbc.url>
</properties>
<!-- 设定是否为默认启动的环境 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!-- 2. 生产环境 -->
<profile>
<id>env_pro</id>
<properties>
<jdbc.url>jdbc:mysql://127.2.2.1:3306/ssm_db?useSSL=false&useServerPrepStmts=true</jdbc.url>
</properties>
</profile>
<!-- 3. 测试环境 -->
<profile>
<id>env_test</id>
<properties>
<jdbc.url>jdbc:mysql://127.3.3.1:3306/ssm_db?useSSL=false&useServerPrepStmts=true</jdbc.url>
</properties>
</profile>
</profiles>
上述设定默认的启动环境是开发环境
也可以通过以下命令动态指定环境
mvn install -P env_test
4.2 跳过测试
如果在测试环境使用install,那么所有的test都将依次执行
当部分模块还没有开发完毕,但需要对已经开发完毕的打包时,就无法完成。此时需要跳过测试
应用场景
- 功能更新中并且没有开发完毕
- 快速打包
方法一:IDEA工具实现跳过测试
此时执行install,由于跳过了测试,程序里的 BookServiceTest 不会被执行
- 一次性跳过全部测试
方法二:配置插件实现跳过测试
<build>
<plugins>
<plugin>
<!-- 内部插件,无需提供groupId -->
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<!-- skipTests设置成true 直接跳过所有测试 -->
<skipTests>false</skipTests>
<!-- 排除掉不参与测试的内容,如BookServiceTest -->
<excludes>
<exclude>**/BookServiceTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
方法三:命令行跳过测试
mvn package -D skipTests
注意:cmd要在pom.xml所在目录下进行执行
5. 私服
A,B,C合作开发项目,如果B想要使用A开发的模块,就需要用到私服
- 中央仓库不允许私人上次jar包
- 可以搭建一个类似中央仓库的私服,A将自己开发的模块上传到私服,B只需要联网下载即可使用
私服:公司内部搭建的用于存储Maven资源的服务器
远程仓库/中央仓库:Maven开发团队维护的用于存储Maven资源的服务器
- 私服是一台独立的服务器,用于解决团队内部的资源共享与资源同步问题
- 搭建Maven私服的方式很多,一种常见的方式是通过
Nexus
5.1 私服安装
步骤1:下载和解压nexus
-
官网下载(慢)
下载地址:https://help.sonatype.com/repomanager3/download)
-
百度云盘下载
链接:https://pan.baidu.com/s/1nFgGeDtSL-e0np3BpB7YRQ
提取码:ar7m -
安装
下载后解压即可安装完毕
-
说明
nexus文件夹中的nexus.vmoptions中定义了sonatyoe-work的地址,用到了后者的一些配置,因此这两个文件夹都需要保留
步骤2:启动nexus
在bin目录下打开cmd,执行
nexus.exe /run nexus
即可启动
步骤3:访问nexus服务器
访问 http://localhost:8081
首次使用需要点击 sign up,根据提示到指定位置找到密码,然后登录
登录成功后,根据提示进行设置
报错问题
这里登录之后可能会报一个:java.net.UnknownHostException: sonatype-download.global.ssl.fastly.net
导致结果:能正常使用nexus基础功能,但无法正常关闭
可能的原因:官网进不去导致的
暂时的解决方法:关闭拓展
步骤4:关闭nexus
关闭这里常无法关闭,建议先关闭页面,再关闭nexus
-
方法一:ctrl+c
-
方法二:命令行
在nexus.exe路径下另启一个cmd窗口,输入以下命令
nexus.exe /stop nexus
-
方法三:点 x 强制关闭(不推荐)
步骤5: 修改配置
- 修改基础配置信息
- 安装路径下etc目录中nexus-default.properties文件保存有nexus基础配置信息,例如默认访问端口
- 修改服务器运行配置信息
- 安装路径下bin目录中nexus.vmoptions文件保存有nexus服务器启动对应的配置信息,例如默认占用内存空间
5.2 私服中的仓库分类
私服里有多个仓库,这些仓库分为三大类
-
宿主仓库hosted
保存无法从中央仓库获取的资源
- 自主研发
- 第三方非开源项目,比如Oracle,因为是付费产品,所以中央仓库没有
-
代理仓库proxy
每次去中央仓库下载,速度慢,代理仓库可用于专门存储从远程中央仓库下载的第三方jar包
- 代理远程仓库,通过nexus访问其他公共仓库,例如中央仓库
-
仓库组group
私服里有宿主仓库,有存放SNAPSHOT的代理仓库,有存放RELEASE类型的代理仓库……
为了设置获取资源时在哪个仓库中获取,可以将所有的仓库编成一个组,只需要访问仓库组去获取资源- 将若干个仓库组成一个群组,简化配置
- 仓库组不能保存资源,属于设计型仓库
之前的web项目,实际上用的是阿里云私服
5.3 本地仓库访问私服配置
步骤1:私服上配置仓库
- 需求:创建两个仓库:personal-snapshot 和 personal-release
创建新的仓库
仓库类型选择maven2 (hosted)
,设置仓库名称和存储的jar包类型
创建好personal-snapshot后,同样的方式再创建一个personal-release,只将Version policy改为Release即可
步骤2:配置本地仓库对私服的访问权限
在配置文件setting.xml中配置<servers>
<servers>
<!-- 配置访问私服personal_snapshot的权限 -->
<server>
<id>personal-snapshot</id>
<username>admin</username>
<password>123456</password>
</server>
<!-- 配置访问私服personal_release的权限 -->
<server>
<id>personal-release</id>
<username>admin</username>
<password>123456</password>
</server>
</servers>
- id:私服中仓库的名称
步骤3:配置私服的访问路径
- 在配置访问路径前,需要先将前面新创建的仓库加入到仓库组中,使仓库组能够管理它们
- 进入maven-public仓库组,添加仓库
- 在配置文件setting.xml中配置
<mirrors>
<mirrors>
<!-- 配置私服的访问路径 -->
<mirror>
<id>maven-public</id>
<mirrorOf>*</mirrorOf> <!-- *表示所有jar包都通过私服获取 -->
<url>http://localhost:8081/repository/maven-public/</url>
</mirror>
<!-- 之前使用的是阿里云私服,这里将其注释掉
<mirror>
<id>alimaven</id>
<name>aliyun.maven</name>
<url>https://maven.aliyun.com/repository/public</url>
<mirrorOf>central</mirrorOf>
</mirror>
-->
</mirrors>
5.4 私服资源上传和下载
步骤1:在项目maven-01-parent的pom.xml中配置
<!-- 配置当前工程保存在私服中的具体位置 -->
<distributionManagement>
<repository>
<id>personal-release</id>
<url>http://localhost:8081/repository/personal-release/</url>
</repository>
<snapshotRepository>
<id>personal-snapshot</id>
<url>http://localhost:8081/repository/personal-snapshot/</url>
</snapshotRepository>
</distributionManagement>
要发布的项目都需要配置distributionManagement
标签,要么在自己的pom.xml中配置,要么在其父项目中配置,然后子项目中继承父项目即可
步骤2:deploy 上传到私服
注意,此时已经更改为从私服获取jar,当第一次上传时,由于私服的代理仓库maven-central
为空,必然花费一定时间去下载 maven-01-parent 里面用到的所有jar包到私服中去
步骤3:查看私服中仓库 personal-release 和 personal-snapshot
可以看到personal-snapshot里面已经有上传的项目了,然而personal-release里面依然为空
这是因为maven_01_parent的pom.xml里面设置了当前项目为<version>1.0-SNAPSHOT</version>
<groupId>org.example</groupId>
<artifactId>maven_01_parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
如果将其改为<version>1.0-RELEASE</version>
,即可上传到仓库personal-release里面去
注意:子工程也要修改为RELEASE,否则子项目会被发布到personal-snapshot当中去
步骤4(非必要):配置私服去阿里云中下载依赖
如果私服中没有对应的jar,会去中央仓库下载,如果速度可能太慢,可以配置让私服去阿里云中下载依赖
如果需要修改,可改为:https://maven.aliyun.com/repository/public
下载资源同之前一样,直接在pom.xml里面引入坐标即可