发表于: 2018-03-09 18:29:35

3 664


今天学习的内容总结

接着昨天的写的,还是一样的。

三、编写测试代码

在之前我们已经知道了,测试代码和主代码不在一起,这样的好处是是项目的结构更加清晰。
在编写测用例之前,所以我们需要继续创建文件夹:src/test/java
而实际上,要进行单元测试,需要依赖一个JUnit的构件,所以我们要为Hello World添加一个JUnit依赖。在POM中添加如下?

        <dependencies>
                <dependency>
                        <groupId>junit</groupId>
                        <artifactId>junit</artifactId>
                        <version>4.7</version>
                        <scope>test</scope>
                </dependency>
        </dependencies>

由上面可以知道,所有需要的依赖,都放在了dependencies元素的下面,同时依赖里相关的配置都需要在放在dependency元素里面。
我们也都知道,通过groupId和artifactId可以找到这个构件,但是这个貌似有一点不同,因为他的groupId只有一个Junit!!在本地的仓库里面也没有找到!好吧,其实是有一个中央仓库。

【知识点】仓库

何为Maven仓库?

  1. 仓库中存在构建项目的组件和各种各样的依赖。
  2. 构件完成后生成的构件也可以安装或部署到仓库中,用install命令。

仓库严格的分为两种类型,一种是本地一种是远程。
本地仓库
本地仓库指的是从远程仓库下载的安装在你自己本地的仓库

本地仓库的位置是可以改变的,修改maven安装目录下的conf文件夹下的setting.xml文件,即可

【注】有的人建议把这个文件复制一份放在本地的仓库中,这样的好处,就是只有当前用户,是这个配置,此电脑的其他用户,在使用的试试,本地仓库就是他们自己设置的地址,或者是默认的。

将本地项目的构件安装到maven仓库中,如何去做呢?
项目根目录中,运行mvn clean install

[INFO] Scanning for projects...[INFO] [INFO] ------------------------------------------------------------------------[INFO] Building Maven Hello World Project 1.0-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ hello-world ---[INFO] Deleting /home/dreamer/workspace/hello-world/target[INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-world ---[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent![INFO] skip non existing resourceDirectory /home/dreamer/workspace/hello-world/src/main/resources[INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello-world ---[INFO] Changes detected - recompiling the module![WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent![INFO] Compiling 1 source file to /home/dreamer/workspace/hello-world/target/classes[INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello-world ---[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent![INFO] skip non existing resourceDirectory /home/dreamer/workspace/hello-world/src/test/resources[INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hello-world ---[INFO] Nothing to compile - all classes are up to date[INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello-world ---[INFO] No tests to run.[INFO] [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello-world ---[INFO] Building jar: /home/dreamer/workspace/hello-world/target/hello-world-1.0-SNAPSHOT.jar[INFO] [INFO] --- maven-install-plugin:2.4:install (default-install) @ hello-world ---[INFO] Installing /home/dreamer/workspace/hello-world/target/hello-world-1.0-SNAPSHOT.jar to /home/dreamer/document/maven_local/com/mycom/app/hello-world/1.0-SNAPSHOT/hello-world-1.0-SNAPSHOT.jar[INFO] Installing /home/dreamer/workspace/hello-world/pom.xml to /home/dreamer/document/maven_local/com/mycom/app/hello-world/1.0-SNAPSHOT/hello-world-1.0-SNAPSHOT.pom[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 1.620 s[INFO] Finished at: 2018-03-09T15:52:32+08:00[INFO] Final Memory: 16M/203M[INFO] ------------------------------------------------------------------------

在本地仓库中,真的找到了!

不妨我们更加深入探讨一下,为什么它的输出目录就是本地仓库下的com/mycom/app 为什么它的名字是这种格式和jar呢?
从源码出发,看一下他到此经历了什么。

        private static final char PATH_SEPARATOR = '/';  
      
        private static final char GROUP_SEPARATOR = '.';  
      
        private static final char ARTIFACT_SEPARATOR = '-';  
      
        public String pathOf( Artifact artifact )  
        {  
            ArtifactHandler artifactHandler = artifact.getArtifactHandler();  
      
            StringBuilder path = new StringBuilder( 128 );  
      
            path.append( formatAsDirectory( artifact.getGroupId() ) ).append( PATH_SEPARATOR );  
            path.append( artifact.getArtifactId() ).append( PATH_SEPARATOR );  
            path.append( artifact.getBaseVersion() ).append( PATH_SEPARATOR );  
            path.append( artifact.getArtifactId() ).append( ARTIFACT_SEPARATOR ).append( artifact.getVersion() );  
      
            if ( artifact.hasClassifier() )  
            {  
                path.append( ARTIFACT_SEPARATOR ).append( artifact.getClassifier() );  
            }  
      
            if ( artifactHandler.getExtension() != null && artifactHandler.getExtension().length() > 0 )  
            {  
                path.append( GROUP_SEPARATOR ).append( artifactHandler.getExtension() );  
            }  
      
            return path.toString();  
    }  
      
        private String formatAsDirectory( String directory )  
        {  
            return directory.replace( GROUP_SEPARATOR, PATH_SEPARATOR );  
        }  

我们从上面的源码可以看出,一个构件是怎么输出到准确的位置的。

  1. 首先,先将构件的groupId中的.替换成/,同时在后面加了一个/,这时的path=“com/mycom/app/"
  2. 然后得到构件的ArtifactId和BaseVersion,将其添加到了,path的后面。此时path="com/mycom/app/hello-world/1.0-SNAPSHOT/
  3. 再获取一遍artifactId和version,按如下格式拼接artifactId-version-然后再添加到中去,此时的path="com/mycom/app/hello-world/1.0-SNAPSHOT/hello-world-1.0-SNAPSHOT
  4. 检查构件否有classifier,如果有,就继续用-连接。
  5. 检查构件的extension,若extension存在,则加上句点分隔符和extension。可以看到extension是从artifactHandler而给artifact获取,artifactHandler是由项目的packaging决定,也就是packaging决定了构件的扩展名。

【疑】经过以上的源码分析,由于第2步中,获取的是baseVersion。(baseVersion是专门为快照版本准备的,version为1.0-SNAPSHOT的构件,其baseVersion就是1.0),所以应该是目录的结构应该是1.0才对?为何文件夹是1.0-SNAPSHOT?

中央仓库
最原始的本地仓库是空的,Maven至少需要一个可用的远程仓库,远程仓库指的是除本地仓库以外的任何其他的仓库,可以通过file://http://等协议访问。

远程仓库的配置信息,其实在我们安装maven的时候就存在了,不信把M2_HOME/lib/maven-model-builder-3..jar解压,访问org/apache/maven/model/pom-4.0.0.xml就可以看到:

 <repositories>
    <repository>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>

仔细的分析一下,maven的中央仓库地址发现更改了,(但是之前的http://repo1.maven.org/maven2 也能用),布局是默认的,也就是之前的源码分析,下面的<snapshots> <enabled>元素则是设置成了false,这个意思就是,不会从该仓库下载快照版本的构件。

远程仓库的配置
了解了很多了,但是我们只有一个默认的中央仓库还是不够的,还需要一个远程仓库,这个远程仓库该如何配置呢?肯定还是在项目的pom.xml中设置!继续在pom.xml中添加代码如下:

        <repositories>
                <repository>
                        <id>jboss</id>
                        <name>JBoss Repository</name>
                        <url>http://repository.jboss.com/maven2</url>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>false</enabled>
                        </snapshots>
                        <layout>default</layout>
                </repository>
        </repositories>

这些素估计你都能看懂吧,其中,releases的enabled值是true,表示开启JBoss仓库的发布版本下载支持。。

<snapshots><release>元素除了enabled,他们还包括另外两个子元素updatePolicy和checksumPolicy

<snapshots>
    <enabled>true</enabled>
    <updatePolicy>daily</updatePolicy>
    <checksumPolicy>ignore</checksumPolicy></snapshots>

<updatePolicy>表示的是Maven从远程仓库检查更新的频率,默认值是daily,其他值为never always(每构建都会检查更新) interval:X(每个X分钟检查一次更新。(x为任意证整数)

<checksumPolicy>用来配置Maven检查检验和文件的策略。当构件被部署到Maven仓库的时候,会同时部署对应的校验和文件。如果校验失败,值为warn时,会打印出警告信息,fail时会让构建失败,ignore使得它忽视这个错误。

部署到远程仓库
在一个公司中,大家肯定要共用一些依赖,这些依赖和构建在别的仓库上市不存在的,于是创建了私服,这时出现了一个问题,如何将开发中生成的构件部署到仓库中呢?

还是需要修改项目的pom.xml文件,这时我们应该添加的元素是<distributionManagement>具体代码如下:

<distributionManagement>
    <repository>
        <id>proj-releases</id>
        <name>Proj Release Repository</name>
        <url>http://192.168.1.1000/content/repositories/proj-releases</url>
    </repository>
    <snapshotRepository>
        <id>proj-snapshots</id>
        <name>Proj Snapshot Repository</name>
        <url>http://192.168.1.100/content/repositories/proj-snapshots</url>
    </snapshotRepository>
    </distributionManagement>

由上面可以见到,包含两个版本,一个是发布版本的构件的仓库,一个是快照版本的仓库。
通过mvn clean deploy来进行部署.

测试代码

呼,终于所有的都弄完了,现在开始写代码吧。在src/test/java下创建文件HelloWorldTest.java代码如下:

package com.mycom.app.helloworld;import static org.junit.Assert.assertEquals;import org.junit.Test;public class HelloWorldTest{
        @ Test        public void testSayHello(){
                HelloWorld helloWorld = new HelloWorld();                String result  = helloWorld.sayHello();
                assertEquals("Hello World",result);

        }

}

【疑】在这里的package 和导入的两个包在哪里呢?为何没有找到?
自我答疑,我们导入了junit,这个包在本地仓库的junit/junit/4.7的jar包中,我觉得这就是maven的好处吧,他把仓库的地方和项目的地方结合在了一起,这样直接导入org.junit.Test 通过pom就可以找到了!真的很神奇!

【疑】在package中,本来是导的hello-world,但是出错,不允许,该怎么办?

关于里面的Junit的内容可以先不理,只看代码理解就可以了。
运行mvn clean test进行测试。
成功了!

[INFO] Scanning for projects...[INFO] [INFO] ------------------------------------------------------------------------[INFO] Building Maven Hello World Project 1.0-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ hello-world ---[INFO] Deleting /home/dreamer/workspace/hello-world/target[INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-world ---[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent![INFO] skip non existing resourceDirectory /home/dreamer/workspace/hello-world/src/main/resources[INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello-world ---[INFO] Changes detected - recompiling the module![WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent![INFO] Compiling 1 source file to /home/dreamer/workspace/hello-world/target/classes[INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello-world ---[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent![INFO] skip non existing resourceDirectory /home/dreamer/workspace/hello-world/src/test/resources[INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hello-world ---[INFO] Changes detected - recompiling the module![WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent![INFO] Compiling 1 source file to /home/dreamer/workspace/hello-world/target/test-classes[INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello-world ---[INFO] Surefire report directory: /home/dreamer/workspace/hello-world/target/surefire-reports-------------------------------------------------------
 T E S T S-------------------------------------------------------Running com.mycom.app.helloworld.HelloWorldTestTests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.076 secResults :Tests run: 1, Failures: 0, Errors: 0, Skipped: 0[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 2.054 s[INFO] Finished at: 2018-03-09T17:52:45+08:00[INFO] Final Memory: 16M/199M[INFO] ------------------------------------------------------------------------

需要注意的是,他先下载了junit-4.7.pom和junit-4.7.jar,上图没有显示是因为我执行了几次,已经下载过了。

四、打包

终于到了这一时刻,将项目编译、测试之后,下一个重要的命令就是打包(package)此项目中没有制定打包类型,前面所说的就是用默认类型jar包。
使用命令mvn clean package
输出如下:

[INFO] Scanning for projects...[INFO] [INFO] ------------------------------------------------------------------------[INFO] Building Maven Hello World Project 1.0-SNAPSHOT[INFO] ------------------------------------------------------------------------[INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ hello-world ---[INFO] Deleting /home/dreamer/workspace/hello-world/target[INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-world ---[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent![INFO] skip non existing resourceDirectory /home/dreamer/workspace/hello-world/src/main/resources[INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello-world ---[INFO] Changes detected - recompiling the module![WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent![INFO] Compiling 1 source file to /home/dreamer/workspace/hello-world/target/classes[INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello-world ---[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent![INFO] skip non existing resourceDirectory /home/dreamer/workspace/hello-world/src/test/resources[INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hello-world ---[INFO] Changes detected - recompiling the module![WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent![INFO] Compiling 1 source file to /home/dreamer/workspace/hello-world/target/test-classes[INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello-world ---[INFO] Surefire report directory: /home/dreamer/workspace/hello-world/target/surefire-reports-------------------------------------------------------
 T E S T S-------------------------------------------------------Running com.mycom.app.helloworld.HelloWorldTestTests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.055 secResults :Tests run: 1, Failures: 0, Errors: 0, Skipped: 0[INFO] [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello-world ---[INFO] Building jar: /home/dreamer/workspace/hello-world/target/hello-world-1.0-SNAPSHOT.jar[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 2.098 s[INFO] Finished at: 2018-03-09T18:05:29+08:00[INFO] Final Memory: 17M/202M[INFO] ------------------------------------------------------------------------

现在,我仅仅将项目主代码打包成了hello-world-1.0-SNAPSHOT.jar`,并输出到了/target/文件夹中,如何让其他项目也能用此包呢?
有两种方法,第一种将此jar包放在其他项目的classpath中,(在刚开始设置了classpath有一项就是本目录下,所以将它放在其他项目的目录下就好了)
第二种则是使用mvn clean install就可以直接使用了!
其实使用install命令就会执行前面的所有命令。

运行

默认打包生成的jar文件是不能直接运行的,因为带有main方法的累心不会添加到manifect中(打开jar文件中的META-INF/MANIFEST.MF文件,无法看到Main-Class一行)为了生成可执行的jar文件,需要借助maven-shade-plugin

这个是插件!


明天

1. 开始学习插件,插件的配置等

2. Archetype学一下?

3. 熟悉IDEA,

一定要完成这几个,今天学的慢的原因,是我写文章写到一半不小心退了,没有自动保存,又重新写的。。。


问题

1. 在编写代码的时候,为什么在完全不同的两个文件夹下面,都可以直接导入,并成功运行?

自我答疑:我们导入了junit,这个包在本地仓库的junit/junit/4.7的jar包中,我觉得这就是maven的好处吧,他把仓库的地方和项目的地方结合在了一起,这样直接导入org.junit.Test 通过pom就可以找到了!真的很神奇!


这或许就是maven吧。。。。强大。。pom。。。强大。。。这pom竟如此恐怖如斯?



收货

收货多多




返回列表 返回列表
评论

    分享到