Maven&SVN
星期四, 12月 26, 2024 | 28分钟阅读
关于Maven&SVN的学习!
Maven
Maven的简介
简介
Maven 是Apache组织中的一个颇为成功的开源项目,Maven主要服务于基于java平台的项目构建,依赖管理和项目信息管理。
项目构建
项目构建包括:编译,运行单元测试,生成文档,打包和部署。
项目构建工具
Ant构建
最早的构建工具,基于IDE, 大概是2000年有的,当时是最流行java构建工具,不过它的XML脚本编写格式让XML文件特别大。对工程构建过程中的过程控制特别好
Maven【JAVA】
项目对象模型,通过其描述信息来管理项目的构建,报告和文档的软件项目管理工具。它填补了Ant缺点,Maven第一次支持了从网络上下载的功能,仍然采用xml作为配置文件格式。Maven专注的是依赖管理,使用Java编写。
Gradle
属于结合以上两个的优点,它继承了Ant的灵活和Maven的生命周期管理,它最后被google作为了Android御用管理工具。它最大的区别是不用XML作为配置文件格式,采用了DSL格式,使得脚本更加简洁。
目前市面上Ant比较老,所以一般是一些比较传统的软件企业公司使用,Maven使用Java编写, 是当下大多数互联网公司会使用的一个构建工具, 中文文档也比较齐全, gradle是用groovy编写,目前比较新型的构建工具一些初创互联网公司会使用,以后会有很大的使用空间。
Maven的四大特性
依赖管理系统
Maven为Java世界引入了一个新的依赖管理系统jar包管理 jar 升级时修改配置文件即可。在Java世界中,可以用groupId、artifactId、version组成的Coordination(坐标)唯一标识一个依赖。
任何基于Maven构建的项目自身也必须定义这三项属性,生成的包可以是Jar包,也可以是war包或者jar包。一个典型的依赖引用如下所示:
<dependency>
<groupId>javax.servlet</groupId> com.baidu
<artifactId>javax.servlet-api</artifactId>
ueditor echarts
<version>3.1.0</version>
</dependency
坐标属性的理解
Maven坐标为各种组件引入了秩序,任何一个组件都必须明确定义自己的坐标。
groupId
定义当前Maven项目隶属的实际项目-公司名称。(jar包所在仓库路径) 由于Maven中模块的概念,因此一个实际项目往往会被划分为很多模块。 比如spring是一个实际项目,其对应的Maven模块会有很多,如spring-core,spring-webmvc等。
artifactId
该元素定义实际项目中的一个Maven模块-项目名, 推荐的做法是使用实际项目名称作为artifactId的前缀。 比如: spring-bean、spring-webmvc等。
version
该元素定义Maven项目当前所处的版本。
多模块构建
在Maven中需要定义一个parent POM作为一组module的聚合POM。在该POM中可以使用 标签来定义一组子模块。parent POM不会有什么实际构建产出。而parent POM中的build配置以及依赖配置都会自动继承给子module。
一致的项目结构
Maven在设计之初的理念就是Conversion over configuration(约定大于配置)。其制定了一套项目目录结构作为标准的Java项目结构,解决不同ide 带来的文件目录不一致问题。
一致的构建模型和插件机制
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.25</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<contextPath>/test</contextPath>
</configuration>
</plugin>
优点:
- 统一架包依赖
- 可以构架多模块项目
- 统一了不同编辑旗下的项目结构
- 一致的构建模型和插件机制
Maven的安装配置和目录结构
Maven的安装配置
检查JDK的版本
打开dos窗口,执行java -version命令
JDK版本1.7及以上版本
下载Maven
下载地址:http://maven.apache.org/download.html
配置环境变量
-
JAVA_HOME:解压后把Maven的根目录配置到系统环境变量中MAVEN_HOME。
1. path:将bin目录配置到path变量中。
注:maven解压后存放的目录不要包含中文和空格
检查Maven是否安装成功
打开dos窗口,执行 mvn -v命令
认识Maven目录结构
Maven项目目录结构
创建一个文件夹作为项目的根目录
在根目录中创建一个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/XMLSchemainstance"
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.xxxx</groupId>
<artifactId>maven01</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>maven00</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-
</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
标签定义解释
根目录下的第一个子元素 ModelVersion指定当前Pom模型的版本。
对于Maven3来说,它只能是4.0.0 。指定了当前Maven模型的版本号,
对于Maven2和Maven3来说,它只能是4.0.0
groupId定义了项目属于哪个组, 这个组往往和项目所在的组织和公司存在关联。
比如: com.xxxx
artifactId 定义了当前Maven项目在组中唯一的ID。
Version X.X.X-里程碑
比如:1.0.0-SNAPSHOT
第一个X 大版本 有重大变革
第二个X 小版本 修复bug,增加功能
第三个X 更新
里程碑版本:
SNAPSHOT (快照,开发版)
alpha(内部测试)
beta(公开测试)
Release | RC( 发布版)
GA(正常版本)
使用name标签声明一个对于用户更为友好的项目名称,虽然不是必须的,但还是推荐为每个Pom声明name,以方便信息交流。
编写main函数
package com.msb.demo;
public class Hello {
public static void main(String[] args) {
System.out.println("Hello Maven");
}
}
cmd下编译并运行
cmd下,进入项目的根目录
-
编译Java文件
mvn compile
-
执行main方法
mvn exec:java -Dexec.mainClass=“com.msb.demo.Hello”
注:第一次下载会比较慢,要修改maven解压之后的conf目录下的settings.xml。
1.1.修改默认仓库位置 打开maven目录 -> conf -> settings.xml 添加仓库位置配置 <localRepository>F:/m2/repository</localRepository> 注:仓库位置改为自己本机的指定目录,"/"不要写反 1.2.更换阿里镜像,加快依赖下载 <mirror> <id>nexus-aliyun</id> <mirrorOf>central</mirrorOf> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/grou ps/public</url> </mirror>
如果编译不成功,可能出现的问题:
- 不是使用管理员权限执行dos命令
- JDK环境配置有问题,重装JDK
- 代码编写时,类里面没设置包名(如果编译时类没加包名,执行 时也不需要加包名)
Maven命令
IDEA等工具给我提供了图形界面化工具,但其底层还是依靠maven命令来驱动的.
Maven的命令格式如下:
mvn [plugin-name]:[goal-name]
命令代表的含义:执行plugin-name插件的goal-name目标
常用命令
命令 | 描述 |
---|---|
mvn –version | 显示版本信息 |
mvn clean | 清理项目生产的临时文件,一般是模块下的target目录 |
mvn compile | 编译源代码,一般编译模块下的src/main/java目录 |
mvn package | 项目打包工具,会在模块下的target目录生成jar或war等文件 |
mvn test | 测试命令,或执行src/test/java/下junit的测试用例. |
mvn install | 将打包的jar/war文件复制到你的本地仓库中,供其他模块使用 |
mvn deploy | 将打包的文件发布到远程参考,提供其他人员进行下载依赖 |
mvn site | 生成项目相关信息的网站 |
mvn eclipse:eclipse | 将项目转化为Eclipse项目 |
mvn dependency:tree | 打印出项目的整个依赖树 |
mvn archetype:generate | 创建Maven的普通java项目 |
mvn tomcat7:run | 在tomcat容器中运行web应用 |
mvn jetty:run | 调用 Jetty 插件的 Run 目标在 JettyServlet 容器中启动 web 应用 |
注意:
运行maven命令的时候,首先需要定位到maven项目的目录,
也就是项目的pom.xml文件所在的目录。否则,必以通过参数来指
定项目的目录。
命令参数
-D 传入属性参数
例如: mvn package -Dmaven.test.skip=true
以-D开头,将maven.test.skip的值设为true ,就是告诉maven打包的时候跳过单元测试。同理,mvn deploy-Dmaven.test.skip=true代表部署项目并跳过单元测试。
-P 使用指定的Profile配置
比如项目开发需要有多个环境,一般为开发,测试,预发,正式4个环境,在pom.xml中的配置如下:
<profiles>
<profile>
<id>dev</id>
<properties>
<env>dev</env>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>qa</id>
<properties>
<env>qa</env>
</properties>
</profile>
<profile>
<id>pre</id>
<properties>
<env>pre</env>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<env>prod</env>
</properties>
</profile>
</profiles>
......
<build>
<filters>
<filter>config/${env}.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
......
</build>
profiles定义了各个环境的变量id,filters中定义了变量配置文件的地址,其中地址中的环境变量就是上面profile中定义的值,resources中是定义哪些目录下的文件会被配置文件中定义的变量替换。
通过maven可以实现按不同环境进行打包部署,例如:mvn package -Pdev -Dmaven.test.skip=true
表示打包本地环境,并跳过单元测试
IDEA编辑器集成Maven环境
设置Maven版本
选择 “File” —> “Other Settings” —> “Settings for New Projects…” —> 搜索 “Maven”
选择下载好的maven版本(目录选到bin目录的上一级目录)
设置settings.xml文件
设置好之后,选择 “Apply” 或者 “OK”
Maven项目的创建
创建Java项目
新建项目
-
选择 “File” —> “New” —> “Project”
-
选择"Maven",设置JDK版本,选择maven项目的模板
-
设置项目的 GroupId 和 ArtifactId
-
检查Maven环境,选择 “Next”
-
检查项目名和工作空间,选择 “Finish”
-
等待项目创建,下载资源,创建完成后目录结构如下
注意:
右下角弹出的提示框,选择**“Enable Auto-Import”**(Maven启动自动导入)
编译项目
-
点击右上角的 “Add Configurations “,打开 “Run/Debug
Configurations” 窗口
-
点击左上角的 “+” 号,选择 “Maven”
-
设置编译项目的命令
-
执行编译命令,两个图标分别代表"普通模式"和"调试模式”
-
编译成功
创建 Web项目
创建项目
-
创建Web项目与创建Java项目步骤基本一致,区别在于选择
Maven模板(web项目选择webapp),如图:
注意:
其他步骤与创建普通的Java项目相同。
-
项目目录结构如下:
启动项目
添加web部署的插件
在 build 标签中添加 plugins 标签
-
Jetty插件
<!-- 设置在plugins标签中 --> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <version>6.1.25</version> <configuration> <!-- 热部署,每10秒扫描一次 --> <scanIntervalSeconds>10</scanIntervalSeconds> <!-- 可指定当前项目的站点名 --> <contextPath>/test</contextPath> <connectors> <connector implementation="org.mortbay.jetty.nio.SelectCh annelConnector"> <port>9090</port> <!-- 设置启动的端口号 --> </connector> </connectors> </configuration> </plugin>
-
Tomcat插件
<!-- 设置在plugins标签中 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-mavenplugin</artifactId> <version>2.1</version> <configuration> <port>8081</port> <!-- 启动端口 默认:8080 --> <path>/test</path> <!-- 项目的站点名,即对外访问路径 --> <uriEncoding>UTF-8</uriEncoding> <!--字符集编码 默认:ISO-8859-1 --> <server>tomcat7</server> <!-- 服务器名称 --> </configuration> </plugin>
启动项目
-
点击右上角的 “Add Configurations “,打开 “Run/Debug Configurations” 窗口
-
点击左上角的 “+” 号,选择 “Maven”
-
Jetty插件配置
也可以输入命令指定端口启动
jetty:run -Djetty.port=9090 # 需要将插件配置中的port标签去掉
点击启动图标,启动服务
启动成功
1. Tomcat插件配置
启动方式如上,启动成功
浏览器访问 http://localhost:8081/test
- Maven依赖仓库:
https://mvnrepository.com/
- Tomcat7插件的命令:
https://tomcat.apache.org/maven-plugin-trunk/tomcat7-maven-plugin/plugin-info.html
Maven仓库的基本概念
当第一次运行Maven命令的时候, 需要Internet链接, 因为它需要从网上下载一些文件。 那么它从哪里下载呢? 它是从Maven默认的远程库下载的。 这个远程仓库有Maven的核心插件和可供下载
的jar文件。
Maven仓库只分为两类: 本地仓库和远程仓库。
当Maven根据坐标寻找构件的时候,它首先会查看本地仓库,如果本地仓库存在,则直接使用; 如果本地没有,Maven就会去远程仓库查找,发现需要的构件之后,下载到本地仓库再使用。 如果本地仓库和远程仓库都没有,Maven就会报错。
远程仓库分为三种: 中央仓库,私服, 其他公共库。
中央仓库是默认配置下,Maven下载jar包的地方。
私服是另一种特殊的远程仓库,为了节省带宽和时间,应该在局域网内架设一个私有的仓库服务器,用其代理所有外部的远程仓库。内部的项目还能部署到私服上供其他项目使用。
一般来说,在Maven项目目录下,没有诸如lib/这样用来存放依赖文件的目录。 当Maven在执行编译或测试时,如果需要使用依赖文件,它总是基于坐标使用本地仓库的依赖文件。
默认情况下, 每个用户在自己的用户目录下都有一个路径名为.m2/repository/的仓库目录。 有时候,因为某些原因(比如c盘空间不足),需要修改本地仓库目录地址。
对于仓库路径的修改,可以通过maven 配置文件conf 目录下settings.xml来指定仓库路径
<!-- 设置到指定目录中,路径的斜杆不要写反 -->
<settings>
<localRepository>D:/m2/repository</localRepository>
</settings>
中央仓库
由于原始的本地仓库是空的,maven必须知道至少一个可用的远程仓库,才能执行maven命令的时候下载到需要的构件。中央仓库就是这样一个默认的远程仓库。maven-model-builder-3.3.9.jar maven自动的 jar 中包含了一个超级POM。定义了默认中央仓库的位置。
中央仓库包含了2000多个开源项目,接收每天1亿次以上的访问。
私服
私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务, 私服代理广域网上的远程仓库,供局域网内的maven用户使用。 当maven需要下载构件时, 它去私服当中找,如果私服没有, 则从外部远程仓库下载,并缓存在私服上, 再为maven提供。
此外,一些无法从外部仓库下载的构件也能从本地上传到私服提供局域网中其他人使用。
配置方式项目pom.xml 配置
<repositories>
<repository>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>public</id>
<name>Public Repositories</name>
<url>http://192.168.0.96:8081/content/groups/public/</url>
</repository>
<repository>
<id>getui-nexus</id>
<url>http://mvn.gt.igexin.com/nexus/content/repositories/releases/</url>
</repository>
</repositories>
其他公共库
常用的阿里云仓库配置
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
Maven环境下构建多模块项目
使用maven 提供的多模块构建的特性完成maven 环境下多个模块的项目的管理与构建。
这里以四个模块为例来搭建项目,以达到通俗易懂的初衷
模块 maven_parent —– 基模块,就是常说的parent (pom)
模块 maven_dao —– 数据库的访问层,例如jdbc操作(jar)
模块 maven_service —– 项目的业务逻辑层 (jar)
模块 maven_controller —– 用来接收请求,响应数据(war)
创建 maven_parent 项目
-
选择 File —> Settings —> Project
-
设置 GroupId 和 ArtifactId
-
设置项目名称及工作空间
创建 maven_dao 模块
-
选择项目maven_parent,右键选择 New ,选择Module
-
选择Maven项目的模板(普通 Java 项目)
-
设置子模块的的 ArtifactId
-
设置Maven的配置
-
设置子模块的名称及存放位置
创建 maven_service 模块
创建 maven_service 模块的步骤与 maven_dao模块一致。
创建maven_controller 模块
创建 maven_service 模块的步骤与 maven_dao模块基本一致,只需要将第一步选择Maven模板设置为web项目即可。(模板类型:maven-archetype-webapp)
模块全部创建完毕后,效果如下:
修改模块的配置
-
设置 JDK 版本
-
单元测试 JUnit版本
-
删除多余的配置
设置模块之间的依赖
maven_dao
-
新建包
-
在包中创建 UserDao类
-
在类中添加方法
package com.msb.dao; public class UserDao { public static void testDao() { System.out.println("UserDao Test..."); } }
maven_service
-
添加maven_dao的依赖
<!-- 加入maven_dao模块的依赖 --> <dependency> <groupId>com.msb</groupId> <artifactId>maven_dao</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
-
在项目中添加UserService类,并添加方法
package com.msb.service; import com.msb.dao.UserDao; public class UserService { public static void testService() { System.out.println("UserService Test..."); // 调用UserDao的方法 UserDao.testDao(); } }
maven_controller
-
添加 maven_service 模块的依赖
<!-- 加入maven_service模块的依赖 --> <dependency> <groupId>com.msb</groupId> <artifactId>maven_service</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
-
添加Servlet的依赖
<!-- Servlet的依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency>
-
新建 Java 类,继承 HttpServlet 类,并重写 service方法
package com.msb.controller; import com.msb.service.UserService; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/user") public class UserServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("UserServlet test..."); //调用maven_service模块的方法 UserService.serviceTest(); } }
-
添加Tomcat插件
<!-- 添加插件 --> <plugins> <!-- tomcat7插件 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.1</version> <configuration> <!-- <port>8080</port> --> <path>/web</path> <uriEncoding>UTF-8</uriEncoding> <server>tomcat7</server> </configuration> </plugin> </plugins>
-
启动项目
-
访问项目
访问地址:http://localhost:8080/web/user
访问结果:
-
如果启动失败,请先将父项目 install
注意:
如果父项目 install 失败,则先将所有子模块 install 成功
后,再 install 父项目。
Maven的打包操作
对于maven 项目,我们可以用过 pom.xml 配置的方式来实现打包时的环境选择,相比较其他形式打包工具,通过maven 只需要通过简单的配置,就可以轻松完成不同环境下项目的整体打包。
比如下面这样一个项目,项目中配置了不同环境下项目所需要的配置文件,这时候需要完成不同环境下的打包操作,此时通过修改pom.xml 如下:
建立对应的目录结构
使用idea创建项目,目录结构可能会缺失,需要通过手动添加对应的目录。
-
添加 Java 源文件夹
选择项目的 main 文件夹,右键选择New,选择Directory
输入文件夹名 “Java”,如图:
选择 java 目录,右键选择 Mark Directory as,选择 Sources
Root。将文件夹标记为源文件夹。
-
添加资源文件夹
步骤如下,创建文件夹,命名为 resources,并标记为Resources Root
-
添加对应的文件夹目录,及添加不同环境下对应的配置文件。(本地环境、测试环境、正式环境)
添加Profile配置
<!-- 打包环境配置 开发环境 测试环境 正式环境 -->
<profiles>
<profile>
<id>dev</id>
<properties>
<env>dev</env>
</properties>
<!-- 未指定环境时,默认打包dev环境 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>test</id>
<properties>
<env>test</env>
</properties>
</profile>
<profile>
<id>product</id>
<properties>
<env>product</env>
</properties>
</profile>
</profiles>
设置资源文件配置
<!-- 对于项目资源文件的配置放在build中 -->
<resources>
<resource>
<directory>src/main/resources/${env}
</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
<include>**/*.tld</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
执行打包操作
打开Run/Debug Configuarations窗口,输入对应的打包命令
此时对应打包命令
- clean compile package -Dmaven.test.skip=true
打包默认环境(开发环境)并且跳过maven 测试操作
- clean compile package -Ptest -Dmaven.test.skip=true
打包测试环境并且跳过maven 测试操作
- clean compile package -Pproduct -Dmaven.test.skip=true
打包生产环境并且跳过maven 测试操作
打包成功
不同的项目打包的文件不一样,一般来说,普通java项目打成jar包,web项目打成war包
Maven依赖的基本概念
依赖的基本配置
根元素project下的dependencies可以包含多个 dependence元素,以声明多个依赖。每个依赖都应该包含以下元素:
-
groupId, artifactId, version : 依赖的基本坐标, 对于任何一个依赖来说,基本坐标是最重要的Maven根据坐标才能找到需要的依赖。
-
Type: 依赖的类型,大部分情况下不需要声明。 默认值为jar
-
compile: 编译依赖范围。
如果没有指定,就会默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。
-
test: 测试依赖范围。
使用此依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此类依赖。典型的例子就是JUnit,它只有在编译测试代码及运行测试的时候才需要。
-
provided: 已提供依赖范围。
使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运行时无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven重复地引入一遍(如:servlet-api)。
-
runtime: 运行时依赖范围。
使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。
-
system: 系统依赖范围。
该依赖与三种classpath的关系,和provided依赖范围完全一致。但是,使用system范围依赖时必须通过systemPath元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用。
-
-
Scope: 依赖范围(compile,test,provided,runtime,system)
-
Optional:标记依赖是否可选
-
Exclusions: 用来排除传递性依赖。
依赖范围
首先需要知道,Maven在编译项目主代码的时候需要使用一套classpath。 比如:编译项目代码的时候需要用到spring-core, 该文件以依赖的方式被引入到classpath中。 其次, Maven在执行测试的时候会使用另外一套classpath。 如:junit。
最后在实际运行项目时,又会使用一套classpath, spring-core需要在该classpath中,而junit不需要。
那么依赖范围就是用来控制依赖与这三种classpath(编译classpath,测试classpath,运行时classpath)的关系, Maven有以下几种依赖范围:
-
Compile 编译依赖范围。 如果没有指定,就会默认使用该依赖范围。 使用此依赖范围的Maven依赖, 对于编译,测试,运行都有效。
-
Test: 测试依赖范围。 只在测试的时候需要。比如junit
-
Provided: 已提供依赖范围。 使用此依赖范围的Maven依赖,对于编译和测试有效, 但在运行时无效。 典型的例子是servlet-API, 编译和测试项目的需要,但在运行项目时,由于容器已经提供, 就不需要Maven重复地引入一遍。
-
Runtime: 运行时依赖范围。 使用此依赖范围的Maven依赖,对于测试和运行有效, 但在编译代码时无效。 典型的例子是:
jdbc驱动程序, 项目主代码的编译只需要jdk提供的jdbc接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体jdbc驱动。
- System: 系统依赖范围。 一般不使用。
传递性依赖
传递依赖机制, 让我们在使用某个jar的时候就不用去考虑它依赖了什么。也不用担心引入多余的依赖。 Maven会解析各个直接依赖的POM,将那些必要的间接依赖,以传递性依赖的形式引入到当前项目中。
注意:传递依赖有可能产生冲突
冲突场景:
A-->B--->C (2.0)
A-->E--->C (1.0)
如果A下同时存在两个不同version的C,冲突!!(选取同时适合
A、B的版本)
<dependencies>
<dependency>
<groupId>A</groupId>
<artifactId>A</artifactId>
<version>xxx</version>
<exclusions>
<exclusion>
<groupId>C</groupId>
<artifactId>C</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>B</groupId>
<artifactId>B</artifactId>
</dependency>
</dependencies>
SVN
简介
SVN全称Subversion,是一个开放源代码的版本控制系统,Subversion 在 2000 年由 CollabNet Inc 开发,现在发展成为Apache 软件基金会的一个项目,同样是一个丰富的开发者和用户社区的一部分。
SVN是一个开放源代码的版本控制系统,管理着随时间改变的数据。这些数据放置在一个中央资料档案库(repository) 中。 这个档案库很像一个普通的文件服务器, 不过它会记住每一次文件的变动。 这样你就可以把档案恢复到旧的版本, 或是浏览文件的变动历史。说得简单一点SVN就是用于多个人共同开发同一个项目,共用资源的目的。
SVN介绍
主要作用
- 目录版本控制
Subversion 实现了一个 “虚拟” 的版本控管文件系统, 能够依时间跟踪整个目录的变动。 目录和文件都能进行版本控制。
- 真实的版本历史
Subversion中,可以增加(add)、删除(delete)、复制(copy)和重命名(rename),无论是文件还是目录。所有的新加的文件都从一个新的、干净的版本开始。
- 自动提交
一个提交动作,不是全部更新到了档案库中,就是完全不更新。这允许开发人员以逻辑区间建立并提交变动,以防止当部分提交成功时出现的问题。
…
基本概念
-
Repository(源代码库):源代码统一存放的地方
-
Checkout(提取):当你手上没有源代码的时候,你需要从repository checkout一份
-
Commit(提交):当你已经修改了代码,你就需要Commit到repository
-
Update (更新):当你已经Checkout了一份源代码, Update后就可以和Repository上的源代码同步
工作流程
开始新一天的工作
-
从服务器下载项目组最新代码。(Checkout)
-
如果已经Checkout并且有人已Commit了代码,你可以更新以获得最新代码。(Update)
-
进入自己的分支,进行工作,每隔一个小时向服务器自己的分支提交一次代码(很多人都有这个习惯。因为有时候自己对代码改来改去,最后又想还原到前一个小时的版本,或者看看前一个小时自己修改了哪些代码,就需要这样做了)(Commit)
-
下班时间快到了,把自己的分支合并到服务器主分支上,一天的工作完成,并反映给服务器。(Commit)
注意:
如果两个程序员同时修改了同一个文件, SVN可以合并这两个程序员的改动,实际上SVN管理源代码是以行为单位的,就是说两个程序员只要不是修改了同一行程序,SVN都会自动合并两种修改。如果是同一行,SVN会提示文件Confict, 冲突,需要手动确认。
生命周期
创建版本库
版本库相当于一个集中的空间,用于存放开发者所有的工作成果。版本库不仅能存放文件,还包括了每次修改的历史,即每个文件的变动历史。
Create 操作是用来创建一个新的版本库。大多数情况下这个操作只会执行一次。当你创建一个新的版本库的时候,你的版本控制系统会让你提供一些信息来标识版本库,例如创建的位置和版本库的名字。
检出
Checkout 操作是用来从版本库创建一个工作副本。工作副本是开发者私人的工作空间,可以进行内容的修改,然后提交到版本库中。
更新
顾名思义,update 操作是用来更新版本库的。这个操作将工作副本与版本库进行同步。由于版本库是由整个团队共用的,当其他人提交了他们的改动之后,你的工作副本就会过期。
让我们假设 Tom 和 Jerry 是一个项目的两个开发者。他们同时从版本库中检出了最新的版本并开始工作。此时,工作副本是与版本库完全同步的。然后,Jerry 很高效的完成了他的工作并提交了更改到版本库中。
此时 Tom 的工作副本就过期了。更新操作将会从版本库中拉取Jerry 的最新改动并将 Tom 的工作副本进行更新。
执行变更
当检出之后,你就可以做很多操作来执行变更。编辑是最常用的操作。你可以编辑已存在的文件来,例如进行文件的添加/删除操作。你可以添加文件/目录。但是这些添加的文件目录不会立刻成为版本库的一部分,而是被添加进待变更列表中,直到执行了 commit 操作后才会成为版本库的一部分。
同样地你可以删除文件/目录。删除操作立刻将文件从工作副本中删除掉,但该文件的实际删除只是被添加到了待变更列表中,直到执行了 commit 操作后才会真正删除。
Rename 操作可以更改文件/目录的名字。“移动"操作用来将文件/目录从一处移动到版本库中的另一处。
复查变化
当你检出工作副本或者更新工作副本后,你的工作副本就跟版本库完全同步了。但是当你对工作副本进行一些修改之后,你的工作副本会比版本库要新。在 commit 操作之前复查下你的修改是一个很好的习惯。
Status 操作列出了工作副本中所进行的变动。正如我们之前提到的,你对工作副本的任何改动都会成为待变更列表的一部分。
Status 操作就是用来查看这个待变更列表。
Status 操作只是提供了一个变动列表,但并不提供变动的详细信息。你可以用 diff 操作来查看这些变动的详细信息。
修复错误
我们来假设你对工作副本做了许多修改,但是现在你不想要这些修改了,这时候 revert 操作将会帮助你。
Revert 操作重置了对工作副本的修改。它可以重置一个或多个文件/目录。当然它也可以重置整个工作副本。在这种情况下,revert操作将会销毁待变更列表并将工作副本恢复到原始状态。
解决冲突
合并的时候可能会发生冲突。Merge 操作会自动处理可以安全合并的东西。其它的会被当做冲突。例如,“hello.c” 文件在一个分支上被修改,在另一个分支上被删除了。这种情况就需要人为处理。Resolve 操作就是用来帮助用户找出冲突并告诉版本库如何处理这些冲突。
提交更改
Commit 操作是用来将更改从工作副本到版本库。这个操作会修改版本库的内容,其它开发者可以通过更新他们的工作副本来查看这些修改。
在提交之前,你必须将文件/目录添加到待变更列表中。列表中记录了将会被提交的改动。当提交的时候,我们通常会提供一个注释来说明为什么会进行这些改动。这个注释也会成为版本库历史记录的一部分。Commit 是一个原子操作,也就是说要么完全提交成功,要么失败回滚。用户不会看到成功提交一半的情况。
安装配置
下载
https://www.visualsvn.com/downloads/ (服务器)
http://tortoisesvn.net/downloads.html (客户端)
最后下载完成的安装包
安装
安装 VisualSVN Server
-
双击安装程序 VisualSVN-Server-4.2.1-x64.msi
-
勾选复选框选择同意,然后选择 Next,选择 Upgrade
-
选择默认配置,选择 Next
-
设置服务器的安装路径、资源的存放目录及端口
-
使用默认配置,选择Next
-
如果出现这个弹窗,选择 Ignore 忽略即可
-
等待安装,安装完成后可勾选复选框,然后选择 Finish
-
出现如下窗口,则表示安装成功
安装 TortoiseSVN
-
双击安装程序 TortoiseSVN-1.13.1.28686-x64-svn-1.13.0.msi
-
选择 Next,然后勾选 command line client tools,选择 Next
-
设置TortoiseSVN的安装路径,勾选 command line client tools
-
进入到TortoiseSVN软件使用协议界面,直接选择 Install 进行安装
-
安装完成之后,直接选择 Finish 即可
-
在任意空白地方,右键,出现如下内容,则表示安装成功
配置
说明:服务器端需要提供IP、端口、帐号、密码供客户端使用。即
有如下配置
设置IP和端口
-
打开服务器,点击 VisualSVN Server,选择 Configure authentication options…
-
设置Server name ,建议使用当前IP
Server name的值可以设置为: 1.127.0.0.1 (只能本地自己访问) 2.电脑用户名(只能本地自己访问) 3.当前IP(能够拼通IP的用户均可访问) Server Port使用默认值即可 查看当前IP: 打开dos窗口(Windows+R键),输入ipconfig,按回车
新建账号密码
-
右键左侧菜单 User,选择 Create User
-
设置用户的账户和密码
新建分组
-
选择 Group 右键,选择 Create Group…
-
设置分组名称,及为分组添加用户
SVN使用
新建版本库
-
选择 Repositories 右键,选择 Create New Repository…
-
选择默认设置,选择下一步,设置仓库名称
-
设置仓库目录 (选择任意一个选项都可)
-
设置仓库的访问权限(这里设置所有svn用户都有读/写权限)
-
仓库创建完成
签入项目到SVN(import)
-
拷贝远程仓库的地址
-
选择任意项目,右键选择 TortoiseSVN,选择 import
-
将上一步拷贝的仓库地址粘贴到地址栏
-
选择永久接受
-
输入用户账号和密码
-
导入成功
-
仓库右键,选择刷新,在服务器中看到的效果
检索项目(check out)
-
复制要下载的项目的远程地址
-
在需要检索项目的目录中,右键选择 SVN Checkout…
-
输入远程地址,设置项目的存放位置
-
检索完成
提交代码(commit)
-
新建文件,右键选择 TortoiseSVN,选择 Add,将文件添加到版本库列表
-
再次点击文件,右键,会出现 SVN Commit…
-
提交成功
更新代码(update)
-
如果当前资源不是最新版本,则可在项目中空白地方右键,选择 SVN Update
-
更新成功
版本冲突问题
版本冲突原因
假设A、B两个用户都在版本号为100的时候,更新了kingtuns.txt这个文件,A用户在修改完成之后提交kingtuns.txt到服务器,这个时候提交成功,这个时候kingtuns.txt文件的版本号已经变成101了。同时B用户在版本号为100的kingtuns.txt文件上作修改,修改完成之后提交到服务器时,由于不是在当前最新的101版本上作的修改,所以导致提交失败。此时用户B去更新文件,如果B用户和A用户修改了文件的同一行代码,就会出现冲突
版本冲突现象
冲突发生时,subversion会在当前工作目录中保存所有的目标文件版本[上次更新版本、当前获取的版本(即别人提交的版本)、自己更新的版本、目标文件]。
假设文件名是kingtuns.txt
对应的文件名分别是:
kingtuns.txt.r101
kingtuns.txt.r102
kingtuns.txt.mine
kingtuns.txt
同时在目标文件中标记来自不同用户的更改。
版本冲突解决
场景
- 现在A、B两个用户都更新项目文件到本地。
用户A
用户B
-
项目中的 hello.txt 文件原始内容为:
-
A用户修改文件,添加内容 “A用户修改内容” ,完成后提交到服务器
-
B用户修改文件,添加内容 “B用户修改内容” ,完成后提交到服务器
-
B用户提交更新至服务器时提示如下
-
B用户将文件提交至服务器时,提示版本过期:首先应该从版本库更新版本,然后去解决冲突,冲突解决后要执行svnresolved(解决),然后在签入到版本库。在冲突解决之后,需要使用svn resolved(解决)来告诉subversion冲突解决,这样才能提交更新。
解决冲突的三种选择
-
放弃自己的更新,使用svn revert(回滚),然后提交。在这种方式下不需要使用svn resolved(解决)
-
放弃自己的更新,使用别人的更新。使用最新获取的版本覆盖目标文件,执行resolved filename并提交(选择文件—右键—解决)。
-
手动解决:冲突发生时,通过和其他用户沟通之后,手动更新目标文件。然后执行resolved filename来解除冲突,最后提交。
解决冲突
-
在B用户当前目录下,右键选择"SVN Update”,执行“update”(更新)操作
-
B用户中的 Hello.txt 文件出现冲突
-
在冲突的文件上(选中文件–右键菜单—TortoiseSVN—Editconflicts(解决冲突))
-
打开编辑冲突的窗口
Theirs窗口为服务器上当前最新版本 Mine窗口为本地修改后的版本 Merged窗口为合并后的文件内容显示
-
如果要使用服务器版本,在Theirs窗口选中差异内容,右键,选择Use this text block(使用这段文本块)。同理如果要使用本地版本,在协商后,在Mine窗口右键,选择Use this text block(使用这段文本块)。
-
修改完成后,选择 “Mark as resolved”(标记为解决),然后选择"Save”(保存文件),关闭窗口即可
-
此时,当前冲突已解决,可再次选择 “SVN Commit"提交文件
注:
也可先不标记为解决,直接保存文件后,在B用户的冲突目录下,选中文件—右键菜单—TortoiseSVN—Resolved(解决)。然后再提交文件。
-
如何降低冲突解决的复杂度
-
当文档编辑完成后,尽快提交,频繁的提交/更新可以降低在冲突发生的概率,以及发生时解决冲突的复杂度。
-
在提交时,写上明确的message,方便以后查找用户更新的原因,毕竟随着时间的推移,对当初更新的原因有可能会遗忘
-
养成良好的使用习惯,使用SVN时每次都是先提交,后更新。每天早上打开后,首先要从版本库获取最新版本。每天下班前必须将已经编辑过的文档都提交到版本库。
Idea集成使用SVN
配置SVN环境
-
File —> Other Settings(全局配置;Settings是局部配置) —>Version Control —> Subversion
-
配置svn
注意:
找不到svn.exe文件,TortoiseSVN的bin目录下面没有svn.exe之所以没有是因为安装TortoiseSVN的时候没有勾选指定安装项,添加command line client tools
-
重启Idea
检索项目
-
选择 VCS —> Checkout from Version Control —> Subversion
-
添加远程仓库中项目的URL
-
点击添加的URL,选择 Checkout
-
选择检索的项目的存放位置
-
选择Destination,根据自己的偏好选择,其他配置默认,单击OK
-
选择 1.8 Format,点击 OK
-
已经check out一个项目,是否要打开,选择 Yes
-
选择 Add
-
此时,项目就可以与远程仓库关联
提交代码
-
选择 VCS —> Commit…
-
选择需要提交的文件,填写提交信息,选择 Commit
-
提交成功后,会在Idea最下面显示提交状态注:项目提交前,最好先更新,然后再提交。
更新代码
-
选择 VCS —> Update Project…
-
默认即可,直接选择 OK
-
更新成功的提示信息
导入项目
-
选择 VCS —> Import into Version Control —> Import into Subversion
-
选择 “+” 添加项目导入的地址(可手动添加一个文件夹,项目中的文件会放置在该文件夹中,文件名自定义)
-
选择要导入的路径,选择 Import
-
选择要导入的项目,点击 OK
-
检查导入的路径,填写导入信息,选择 OK
-
在远程仓库中检查是否导入成功即可。
版本冲突问题
-
如果未更新,就提交资源(有其他用户也提交过资源),则提交失败
-
此时,执行更新操作,将其他人提交过的资源更新到本地,会提示冲突
-
通常选择合并,再选择需要保留的代码,选择好之后选择 Apply
-
提示更新成功
-
再次选择提交,成功解决冲突