maven是专门用于管理和构建Java项目的工具,它的主要功能有:
提供了一套标准化的项目结构
提供了一套标准化的构建流程
提供了一套依赖管理机制(从此导jar包和管理jar包变得非常方便)
本地仓库:本地计算机上的一个目录
中央仓库:由maven团队维护的全球唯一的仓库由于在国外访问速度很慢,而且有一些jar包不是免费开源的,有版权纠纷的不会出现在上边
远程仓库:一般由公司搭建的私有仓库(私服)搭建起来的时候一般会同步所有中央仓库的jar包,这样访问速度会很快。而且自己还可以导入一些其他的jar包(包括有版权的)
当项目中使用坐标引入对应jar包之后,首先会查找本地仓库中是否有对应的jar包,如果有则在项目中直接引用,如果没有则到中央仓库中下载对应的jar包到本地仓库。
如果搭建了远程仓库,则jar包的查找顺序变为:本地仓库->远程仓库->中央仓库。
maven的配置上网找。
maven常用命令:
//编译整个项目的java文件,在src下方生成一个target目录存放编译好的文件
mvn compile
//将compile创建的target目录删除
mvn clean
//会自动运行test包下的代码
mvn test
//将Java项目打包,打包的jar包存放在target目录里(没有该目录就先编译生成)
mvn package
//将Java项目打包,打包的jar包放在本地仓库的目录下
mvn install
坐标的作用:
坐标组成:
使用pom写依赖导入jar包,这些jar包的作用范围是可以限制的。在pom里面使用标签就可以写入作用范围。
将原本的模块分成几个子模块,各个模块之间可以独立维护。这也是微服务的思想。将原本的一个服务分为几个服务,每个服务用一个模块(module)进行开发。
可以预见的是,一个模块不能使用另一个模块的实体、工具类等。那么怎么才能进行使用呢?
作为一个maven项目,pom文件中一定有这个模块的坐标。所以,想要在一个模块中使用另一个模块中的内容,可以在模块的pom文件中导入被引用模块的坐标。
但是直接引入是会报错的。因为:本地仓库里是没有这个模块的!所以,首先要把将要引入的模块打包进本地仓库。
一个模块要引用另一个模块:**在被引入的模块中使用maven的install指令自动打包入本地仓库。**不过在idea之中,右上角点点点就ok了。
如果模块A中导入了依赖:模块B。而模块B中导入了mybaits等其他依赖,那么mybatis等等依赖在模块A中也能使用。mybatis等依赖就叫做模块A的间接依赖。模块B就叫做模块A的直接依赖。
依赖传递会出现依赖冲突。假如模块A有一个间接依赖mybatis3.0,又有一个间接依赖mybatis2.0。那么会使用哪个依赖呢?
idea右边的maven工具栏中有一个查看依赖关系的按钮,可以生成思维导图快速查看依赖关系。
可选依赖就是隐藏自己jar包的依赖。(我不想让别人用我的依赖,如此一来,被隐藏的依赖无法成为间接依赖,可以解决依赖冲突问题)。只需要添加
即可配置可选依赖。配置可选依赖后,此依赖不再具有传递性。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
排除依赖就是排除要导入的jar包的某个依赖。(我不想用别人的某个依赖)
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<!--在这里写不想要lombok中哪个依赖(^-^)-->
<groupId></groupId>
<artifactId></artifactId>
</exclusion>
</exclusions>
</dependency>
如果一个依赖中的代码被改变了,那么但凡引用到这个依赖的jar包都要进行更新,由此引出了聚合的概念。
聚合其实就是同时打包。试想一个场景:有两个模块iss_schedule和iss_ucenter,iss_schedule引用了iss_ucenter的坐标。当iss_ucenter更改了某些东西,从版本1变成了版本2,此时iss_schedule如果没有重新打包,它用的还是版本1的iss_ucenter,这会造成错误。
所以就想要实现一个功能:一个模块重新构建了,引用该模块的其他模块必须一起跟着构建。这就是聚合。
为了实现聚合,可以创建一个聚合模块,该模块不具有业务功能,仅有pom文件。把想要聚合的所有模块放入聚合模块之中,并且把这些模块写入聚合模块的pom文件之中(不是依赖引入,而是在
标签内写入要聚合的模块)。同时,聚合模块的打包方式必须是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.iss</groupId>
<artifactId>intelligent_schedule_system</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 聚合模块 -->
<modules>
<module>common</module>
<module>service</module>
</modules>
<!-- 打包方式是pom,表示聚合模块 -->
<packaging>pom</packaging>
聚合的构建顺序:首先构建最底层的模块,再顺着依赖关系一层一层往上构建。
又出现了一个问题:多个模块中如果引入了大量相同的依赖,不仅增加了代码量,而且管理起来很麻烦(要改动某一个依赖的版本需要把所有相同依赖的版本都更新一遍),于是就有了继承的思想。
把多个模块中相同的依赖都抽取出来,然后创建一个父模块,把这些依赖放入父模块之中。Java中,继承是在子类中实现的,maven中也是一样,在子模块中使用
声明它有一个父模块。
<?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">
<!--这样一来,这个模块就可以使用intelligent_schedule_system这个父模块中的依赖了-->
<parent>
<artifactId>intelligent_schedule_system</artifactId>
<groupId>com.iss</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
继承虽好,但是有一个小问题。如果模块1是模块2、模块3、模块4的父模块,模块2、模块3共用一些依赖,提到父模块之中去;模块3、模块4共用一些依赖,也提到父模块之中去。如此一来,由于继承,模块2会有模块4的依赖,不是很好。
可以在父模块中使用
代替
即可解决这个问题。注意,父模块在dependency
中的所有依赖会全部传递到所有子模块中去,而dependencyManagement
中的依赖,如果子模块不引入坐标(不需要写版本),是不会传递到子模块中去的。
以下代码中,没有版本号的依赖就是存在于父模块service之中的dependencyManagement
中的依赖。
<?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">
<parent>
<artifactId>service</artifactId>
<groupId>com.iss</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>schedule_service</artifactId>
<dependencies>
<!--springboot web的起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--邮件发送-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.4</version>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
</dependencies>
</project>
通常,会选择父模块作为聚合模块。聚合和继承其实都是为了更好地管理依赖。
属性可以实现对依赖的统一管理。比方说spring那么多个依赖,每次导入都要导入同样的版本。如果要更新版本,一个一个去改很麻烦。可以通过设置属性对同类依赖的版本进行统一管理。(属性其实就有点儿变量的味道)。
直接在pom文件中写属性
,然后要到对应的依赖那里的版本用${什么.version}替换版本。
这样一来,直接对属性进行管理,就可以实现对所有jar包的版本进行管理了。
我在后面其实也有用到属性。
<?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.iss</groupId>
<artifactId>intelligent_schedule_system</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>common</module>
<module>service</module>
</modules>
<packaging>pom</packaging>
<!--父依赖是springboot的起步依赖-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.9.RELEASE</version>
<relativePath/>
</parent>
<properties>
<mybatis-plus.version>3.0.5</mybatis-plus.version>
<velocity.version>2.0</velocity.version>
<swagger.version>2.7.0</swagger.version>
<spring-cloud.version>Hoxton.SR10</spring-cloud.version>
<mysql.version>8.0.18</mysql.version>
<junit.version>4.12</junit.version>
<alibaba-dependencies.version>2.2.5.RELEASE</alibaba-dependencies.version>
<fastjson.version>1.2.28</fastjson.version>
<jwt.version>0.7.0</jwt.version>
<slf4j.version>1.7.30</slf4j.version>
<joda-time.version>2.3</joda-time.version>
<aliyun-sdk-oss.version>3.15.1</aliyun-sdk-oss.version>
<poi.version>5.2.2</poi.version>
</properties>
<dependencyManagement>
<dependencies>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- velocity 模板引擎, Mybatis Plus 代码生成器需要 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>${velocity.version}</version>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<!--swagger ui界面-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--Spring Cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--阿里巴巴cloud依赖库-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${alibaba-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--阿里巴巴的fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- JWT令牌,登录时需要用到 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<!--日志-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!--阿里云的oss存储-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${aliyun-sdk-oss.version}</version>
</dependency>
<!--joda-time日期格式转换-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${joda-time.version}</version>
</dependency>
<!--用来操作03年xls格式的excel-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<!--07年的 .xlsx-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
利用pom文件的
对配置文件进行管理。其实直接在配置文件中写也是非常方便的,而且还清楚明了。
这一部分内容感觉有点儿多此一举,用到再学。
maven提供配置多种环境的设定,帮助开发者在使用过程中快速切换环境。
<profiles>
<profile>
<!--开发环境-->
<id>env_dev</id>
<activation>
<!--默认启动该环境-->
<activeByDefault>true</activeByDefault>
</activation>
<properties></properties>
<dependencies></dependencies>
<dependencyManagement></dependencyManagement>
</profile>
<profile>
<!--生产环境-->
<id>env_prod</id>
<properties></properties>
<dependencies></dependencies>
<dependencyManagement></dependencyManagement>
</profile>
<profile>
<id>测试环境</id>
<properties></properties>
<dependencies></dependencies>
<dependencyManagement></dependencyManagement>
</profile>
</profiles>
之后,使用mvn -install -P env_dev
就可以将开发环境打包。通过最后的参数可以很方便地控制要打包哪一个环境。