穿越至目录:
对于概念的一些理解
Maven的作用
管理模块之间的依赖:根据业务需求,系统会划分很多模块,这些模块彼此之间存在着依赖关系。比如系统管理模块依赖着文件上传模块,来实现用户头像上传的功能。maven通过配置模块之间的pom依赖
生命周期管理:在web应用中,我们常要进行编译、打包、测试这些环节。在maven的世界里,将这些过程定义为生命周期。maven将这些复杂的过程进行了封装,使用者只需要简单的用鼠标点几下就可以完成项目的构建工作
强大的插件:举一个很常用的插件tomcat7-maven-plugin,在老老年间,我们发布应用的方式是,将web应用打包成war->手动拷贝到tomcat的webapp目录下->启动tomcat。现在有了Maven以上过程我们只需要点击一下鼠标即可完成。是不是很方便?
仓库式管理:曾经为了找一个jar包费劲周折,曾经因为jar包冲突、版本产生莫名其妙的问题困扰我们好久。Maven提供的公用仓库http://mvnrepository.com/,只要输入jar包的坐标即可查找到想要的资源,将模块的坐标加入到自己的pom中就可以快乐的使用了,真的觉得很方便。同时由于依赖的概念,与其相关的jar包也会引入到项目环境中,并且不会产生版本的问题
Nexus作用
节省流量:Nexus作为私有库部署在局域网内部,比如10个人协同开发,开发人员A需要一个log4j的jar来实现系统日志功能,A将log4j的坐标添加到自己模块的pom文件中,maven会向公共仓库发送请求,下载log4j的jar包。下载的过程中,Nexus也偷偷的保存了一份log4j在私有的仓库。那么以后再有开发人员需要log4j的时候,请求是直接发送到Nexus上请求资源的。就不需要访问外网了,否则每个人都需要访问公共Maven库下载资源。这样节省了流量,同时内网的网速一般也比公网快。也提高了工作效率
协同开发:多人协同开发,A开发系统管理、B开发考勤模块。考勤模块依赖了系统管理的员工接口,那么B需要手动拷贝A打包的jar到自己的工程中。当A改动了系统管理的接口,B完全不知情,等出现问题了还需要联调,很麻烦!有了Nexus A就可以将系统管理打包发布到Nexus的私有仓库中,B添加系统管理的坐标即可完成依赖,以后A再有改动,只要发布到Nexus上就可以了。减少了沟通成本
场景描述
项目的模块结构
大概是这个样子
commonModal:提供公共的基础服务,比如文件上传、邮件发送、权限管理等等
businessModal:业务模块,是系统真正要实现的业务。依赖于commonModal,比如订单管理、财务统计、会员管理等
application:可发布的web应用,由各个businessModal组成,最终满足项目的整体需求
第三方模块:包括各类框架,spring、mybatis、日志等。整个应用都是依赖它们完成开发的
如何使用Maven管理以上的结构呢?
首先要弄清楚Maven的两个重要的概念,依赖和继承。举例说明:
场景:
1、有A、B、C三个模块是用Maven进行管理的,它们之间的关系:C依赖B、B依赖A
2、有D、E、F三个模块是用Maven进行管理的。它们之间的关系:F继承自E,也就是F的parent是E。E依赖D
结果:
依赖:对于场景1,由于依赖的传递性,C模块中,除了能使用B的接口外,同时也能使用A的接口。但是在C模块中,无法继承到B模块的一些POM配置(比如<properties>定义的版本信息,<build>中定义构建信息等)
继承:对于场景2,F是能够继承到E的Pom的配置的,比如对E对D的依赖,在F中是能够使用D中定义的接口的。还有其他的Pom配置,比如<properties>、<build>、<distributionManagement>
回到主题,对于上述的模块结构,如果使用maven管理应该考虑的问题有哪些呢?
1、随着项目的进展,模块的数量不断增长。maven对于模块的管理包含着版本的概念,只有正确的管理版本,才不至于在工作中造成版本的混乱。
是否应该有一个地方统一对版本进行管理?
2、对于所有的模块,是都需要发布到nexus上进行管理的,那么是否代表着,没一个模块都要配置<distributionManagement>来对发布过程进行管理呢?如果nexus服务器ip换了怎么办?每个模块去修改?
应该有一个地方统一管理整个项目的发布配置
3、对于依赖的管理,通过模块结构图可以想象,模块之间的依赖是很复杂的,比如很多模块都依赖于log4j,是否每个模块都要使用<dependency>一次Log4j
实战
基于以上的问题,将Maven的管理结构定义如下,有maven模块之间的关系和类之间的关系非常接近,因此使用类图表示
图解:
上图中绿色部分为Maven管理模块,打包类型为pom。
root:抽象层级最高的模块,应该配置公用级别最高的配置。也就是所有模块都需要用到的发布到nexus上的配置。那么其他所有层级的模块就可以共享这一配置,比如commonModal就可以通过路径5-4-3-1继承到<distributionManagement>配置。这样问题2就得到了解决
version、modalVersion、businessVersion:为版本定义模块,分别定义了第三方模块、commonModal、businessModal的版本信息。这样就解决了问题1
j2ee、modalGather:分别持有对第三方模块、commonModal的依赖。application、businessModal、commonModal都可以通过继承路径,获取到上层的资源。也就不必要在所有的模块中都重复的进行引用操作
具体配置
root模块的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>com.wt.common</groupId> <artifactId>root</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <name>root</name> <developers> <developer> <name>lichking</name> <email>lichking2017@aliyun.com</email> </developer> </developers> <properties> <project.build.sourceEncoding>1.8</project.build.sourceEncoding> <version.j2ee>1.0-SNAPSHOT</version.j2ee> </properties> <!--构建设置--> <build> <outputDirectory>${basedir}/target/${project.build.finalName}/WEB-INF/classes</outputDirectory> <plugins> <!--设置编译的jdk版本还有编码格式--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <encoding>UTF-8</encoding> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <!--设置资源文件读取编码格式--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> <configuration> <encoding>${project.build.sourceEncoding}</encoding> </configuration> </plugin> <!--源码打包--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>2.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>jar-no-fork</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <!--配置发布信息--> <distributionManagement> <repository> <id>releases</id> <url>http://192.168.0.110:8081/repository/maven-releases/</url> </repository> <snapshotRepository> <id>snapshots</id> <url>http://192.168.0.110:8081/repository/maven-snapshots/</url> </snapshotRepository> </distributionManagement> </project>
version模块的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"> <parent> <artifactId>root</artifactId> <groupId>com.wt.common</groupId> <version>1.0-SNAPSHOT</version> <relativePath>../root/pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.wt.common</groupId> <artifactId>version</artifactId> <packaging>pom</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <version.spring>5.0.2.RELEASE</version.spring> <version.com.google.code.gson>2.8.2</version.com.google.code.gson> <version.commons-lang3>3.7</version.commons-lang3> <version.druid>1.1.9</version.druid> <version.mybatis>3.4.6</version.mybatis> <version.mybatis-spring>1.3.2</version.mybatis-spring> <version.mybatis-generator>1.0SNAPSHOT</version.mybatis-generator> <version.core>1.0-SNAPSHOT</version.core> <version.mysql.driver>6.0.6</version.mysql.driver> <version.gson>2.8.2</version.gson> <version.junit>4.12</version.junit> <version.testng>6.14.3</version.testng> <slf4j.version>1.7.25</slf4j.version> <log4j.version>2.8.2</log4j.version> </properties> </project>
j2ee模块的配置:
<?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>version</artifactId> <groupId>com.wt.common</groupId> <version>1.0-SNAPSHOT</version> <relativePath>../version/pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.wt.common</groupId> <artifactId>j2ee</artifactId> <packaging>pom</packaging> <name>j2ee</name> <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> <scope>compile</scope> </dependency> <!--通过传递依赖,已经将spring-core、context、aop、beans模块加入到了依赖树中--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${version.spring}</version> </dependency> <!-- spring事物模块 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${version.spring}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${version.spring}</version> </dependency> <!--apache工具包--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${version.commons-lang3}</version> </dependency> <!--前后端通过json通信--> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>${version.com.google.code.gson}</version> </dependency> <!--数据库连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${version.druid}</version> </dependency> <!--mysql数据库连接驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${version.mysql.driver}</version> </dependency> <!-- controller向客户端返回数据的时候,表述形式为JSON时,需要的依赖(google的gson工具) --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>${version.gson}</version> </dependency> <!--mybatis依赖begin--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${version.mybatis}</version> </dependency> <!--mybatis与spring整合--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${version.mybatis-spring}</version> </dependency> <!--<!–mybatis 代码生成器–>--> <!--<dependency>--> <!--<groupId>org.mybatis.generator</groupId>--> <!--<artifactId>mybatis-generator-core</artifactId>--> <!--<version>${version.mybatis-generator}</version>--> <!--</dependency>--> <!--框架依赖--> <dependency> <groupId>com.wt.common</groupId> <artifactId>core</artifactId> <version>${version.core}</version> </dependency> <!--日志处理--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j.version}</version> </dependency> <!--用于与sfl4j保持桥接--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-web</artifactId> <version>${log4j.version}</version> <scope>runtime</scope> </dependency> <!--测试框架--> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>${version.testng}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${version.junit}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${version.spring}</version> <scope>test</scope> </dependency> </dependencies> <!--<build>--> <!--<plugins>--> <!--<plugin>--> <!--<groupId>org.mybatis.generator</groupId>--> <!--<artifactId>mybatis-generator-maven-plugin</artifactId>--> <!--<version>${version.mybatis-generator}</version>--> <!--</plugin>--> <!--</plugins>--> <!--</build>--> </project>
moduleVersion模块的配置
<?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>j2ee</artifactId> <groupId>com.wt.common</groupId> <version>1.0-SNAPSHOT</version> <relativePath>../j2ee/pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.wt.common</groupId> <artifactId>moduleVersion</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <properties> <version.security>1.0-SNAPSHOT</version.security> <version.upload>1.0-SNAPSHOT</version.upload> <version.core>1.0-SNAPSHOT</version.core> </properties> </project>
modalGather模块的配置
<?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>moduleVersion</artifactId> <groupId>com.wt.common</groupId> <version>1.0-SNAPSHOT</version> <relativePath>../moduleVersion/pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.wt.common</groupId> <artifactId>modalGather</artifactId> <packaging>pom</packaging> <dependencies> <dependency> <groupId>com.wt.common</groupId> <artifactId>security</artifactId> <version>${version.security}</version> </dependency> <dependency> <groupId>com.wt.common</groupId> <artifactId>upload</artifactId> <version>${version.upload}</version> </dependency> <dependency> <groupId>com.wt.common</groupId> <artifactId>core</artifactId> <version>${version.core}</version> </dependency> </dependencies> </project>
以上就是个人的一些见解
其他
关于Maven与nexus的结合使用,搞清楚几点就可以:
1、在项目中配置模块的发布路径,如上文提到的root的配置
其中的<repository>和<snapshotRepository>是固定写法,分别对应snapshot版本和release版本
<id>是要注意的,一定要与你本地的setting中的<server>中的id对应上,Maven才能通过id对应的用户名和密码连接到nexus
2、<url>中的内容是哪来的?
它对应着nexus仓库中的配置,见下图nexus中的红箭头,点击一下就可以拷贝对应的地址了
<distributionManagement> <repository> <id>releases</id> <url>http://192.168.0.110:8081/repository/maven-releases/</url> </repository> <snapshotRepository> <id>snapshots</id> <url>http://192.168.0.110:8081/repository/maven-snapshots/</url> </snapshotRepository> </distributionManagement>
以下是本机settings.xml配置
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <servers> <server> <id>nexus</id> <username>admin</username> <password>admin123</password> </server> <server> <id>snapshots</id> <username>admin</username> <password>admin123</password> </server> <server> <id>tomcat8</id> <username>admin</username> <password>admin</password> </server> </servers> <mirrors> <!-- 本地nexus私服 <mirror> <id>nexus</id> <mirrorOf>*</mirrorOf> <url>http://192.168.0.240:8081/nexus/content/groups/public/</url> </mirror> --> <!-- 阿里云仓库 <mirror> <id>alimaven</id> <mirrorOf>*</mirrorOf> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> </mirror> --> <mirror> <id>nexus</id> <mirrorOf>*</mirrorOf> <url>http://192.168.0.110:8081/repository/maven-public/</url> </mirror> </mirrors> <profiles> <profile> <id>nexus</id> <repositories> <repository> <id>nexus</id> <name>Nexus</name> <!-- <url>http://192.168.0.240:8081/nexus/content/groups/public/</url> --> <url>http://192.168.0.110:8081/repository/maven-public/</url> <releases><enabled>true</enabled><updatePolicy>always</updatePolicy></releases> <snapshots><enabled>true</enabled><updatePolicy>always</updatePolicy></snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>nexus</id> <name>Nexus</name> <!-- <url>http://192.168.0.240:8081/nexus/content/groups/public/</url> --> <url>http://192.168.0.110:8081/repository/maven-public/</url> <releases><enabled>true</enabled><updatePolicy>always</updatePolicy></releases> <snapshots><enabled>true</enabled><updatePolicy>always</updatePolicy></snapshots> </pluginRepository> </pluginRepositories> </profile> </profiles> <activeProfiles> <activeProfile>nexus</activeProfile> </activeProfiles> </settings>
另外Nexus3相对2改进还是很多的,界面也很炫酷,可以尝试一下