maven一篇文章就够了(上)

一:maven的发展历程

在maven发展之前,传统的jar包管理我们一般会用ant+lvy来管理jar包,它有显而易见的两个缺点,

缺点一:需要我们来手动的来打jar包(build as),然后把打过得包放到我们规定的目录下(虽然可以进行特殊的处理引用本地的应用,不需要打包,但是前提条件就是你的有这个应用的源码)。

缺点二:每一个应用都需要有相同的配置,重复的工作不停的在做,这样的话相当月重复造轮子,这也不太符合编程语言的原则。

基于这两点:我们从农业社会开始向工业社会转型,开始步入maven的时代。

二,maven介绍

2.1,convention over configuration(约定优于配置原则)

在介绍maven之前我们先记住一个原则:约定优于配置的原则(比如我们建立的多个应用之间的目录结构是一致的),下面的配置是在主pom文件中的,在下面的maven目录结构中会讲到的。(超级pom文件)

比如上面的地方,我们建立的多个应用之间我们的目录结构都是一致的,这样我们会在主(父)pom文件中可以进行统一的设置。(后面我们还会多次提到这个原则)

2.2,maven的下载安装配置(略)

2.3,maven的目录结构解析

maven是java代码写的。

下面通过两张图来解析一下,更加直接一点。

在这里附上超级pom.xml的配置

<?xml version="1.0" encoding="UTF-8"?>

<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->

<!-- START SNIPPET: superpom -->
<project>
  <modelVersion>4.0.0</modelVersion>

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

  <pluginRepositories>
    <pluginRepository>
      <id>central</id>
      <name>Central Repository</name>
      <url>http://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <releases>
        <updatePolicy>never</updatePolicy>
      </releases>
    </pluginRepository>
  </pluginRepositories>

  <build>
    <directory>${project.basedir}/target</directory>
    <outputDirectory>${project.build.directory}/classes</outputDirectory>
    <finalName>${project.artifactId}-${project.version}</finalName>
    <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
    <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
    <scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory>
    <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
    <resources>
      <resource>
        <directory>${project.basedir}/src/main/resources</directory>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>${project.basedir}/src/test/resources</directory>
      </testResource>
    </testResources>
    <pluginManagement>
      <!-- NOTE: These plugins will be removed from future versions of the super POM -->
      <!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) -->
      <plugins>
        <plugin>
          <artifactId>maven-antrun-plugin</artifactId>
          <version>1.3</version>
        </plugin>
        <plugin>
          <artifactId>maven-assembly-plugin</artifactId>
          <version>2.2-beta-5</version>
        </plugin>
        <plugin>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>2.8</version>
        </plugin>
        <plugin>
          <artifactId>maven-release-plugin</artifactId>
          <version>2.3.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

  <reporting>
    <outputDirectory>${project.build.directory}/site</outputDirectory>
  </reporting>

  <profiles>
    <!-- NOTE: The release profile will be removed from future versions of the super POM -->
    <profile>
      <id>release-profile</id>

      <activation>
        <property>
          <name>performRelease</name>
          <value>true</value>
        </property>
      </activation>

      <build>
        <plugins>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-source-plugin</artifactId>
            <executions>
              <execution>
                <id>attach-sources</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-javadoc-plugin</artifactId>
            <executions>
              <execution>
                <id>attach-javadocs</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <inherited>true</inherited>
            <artifactId>maven-deploy-plugin</artifactId>
            <configuration>
              <updateReleaseInfo>true</updateReleaseInfo>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>

</project>
<!-- END SNIPPET: superpom -->

2.4,maven的settings.xml配置文件解读

mirrors本人常用的地址

<mirror>
              <id>alimaven</id>
              <name>aliyun maven</name>
              <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
              <mirrorOf>central</mirrorOf>
            </mirror>
            <mirror>
                  <id>ui</id>
                  <mirrorOf>central</mirrorOf>
                  <name>Human Readable Name for this Mirror.</name>
                  <url>http://uk.maven.org/maven2/</url>
            </mirror>
            <mirror>
            <id>osc</id>
            <mirrorOf>central</mirrorOf>
            <url>http://maven.oschina.net/content/groups/public/</url>
        </mirror>
        <mirror>
            <id>osc_thirdparty</id>
            <mirrorOf>thirdparty</mirrorOf>
            <url>http://maven.oschina.net/content/repositories/thirdparty/</url>
        </mirror>

2.5,pom.xml文件讲解

<modelVersion>4.0.0</modelVersion>

maven的版本号:就是我们在上面说的maven-model-builder-3.2.1里面的超级pom文件中定义的。

<groupId>com.qingruihappy</groupId>

一般都是公司域名前面加上com

<artifactId>qingruihappy_duoxiancheng</artifactId>

就是应用的名称

<packaging>war</packaging>

包的类型jar,war,pom(主要就是多个应用之间的父级,聚合)

<version>0.0.1-SNAPSHOT</version>

版本号

<properties>标签,父pom中的一些参数。类似于常量一样,统一版本号,不用写在后面的每一个配置中,同时它本身也可以是变量的,例如下面带红色圈起来的。

下面我们来着重讲一下dependencyManagement这个配置

1. 只能出现在父pom

2. 统一版本号

3. 声明 (子POM里用到再引)

既然已经dependencies为什么还要有dependencyManagement呢?

考虑这个问题之前,我们先考虑一个问题在父pom文件中dependencyManagement定义的jar包依赖,在子目录中能应用到吗?

答案是不能呢,那为什么还要在父目录中的dependencyManagement定义dependencies依赖jar包呢?

我们来看一下子目录中的pom文件

是不是有点理解了,主要就是虽然我们用dependencyManagement定义了依赖,子目录不会自动的引用父目录中的引用,需要我们在子目录中在写一遍,但是我们写的方式完全不一样了,我们不需要写版本号,版本的控制还是在父目录中,避免出现版本号不一致的情况。

还有一点就是,假如我们不用这个标签的话,子类统一引用父类的pom文件,这样就会把我们子pom文件用不到的jar包也给依赖进来,这一点有点类似于声明式事物。(例如我们经常用到的httpclient用到的比较多最好在父类中统一版本号)。

dependencyManagement综上所述,一句话来概括就是,它的作用就是,版本号在父pom,用不用子pom决定。

dependencies下的scope属性

每个依赖项的Scope选项进行该jar包的相关操作设置,默认为compile,根据需要调整设置:

1、compile设置编译范围内有效,在编译和打包时都会将依赖项加载进去,默认设置。

2、test设置测试范围内有效,只在测试时使用,编译和打包时都不会加载该项,这个就是为什么我们有时候test目录下报错,但是不会影响本地tomact的启动,因为它是不会编译的。

最常用的就是complie和test

3、provided设置编译和测试的范围内有效,打包时不会加载该项。

对于第三方jar包,传递依赖到war包的,但发布时并不需要的。

如:我们项目中使用了webwork-2.2.3.jar。可以我们在打包后发现在war下的lib中多了spring-web-1.2.jar,可是我们项目并不需要这个jar。

第一种办法:借用provided

虽然provided的本意是指jdk或者容器提供的,只是编译中使用,但不会打到war中,但我们也可借用。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>1.2</version>
    <scope>provided</scope>
</dependency>

第二种办法: 使用exclusions; (效果与第一种相同)

<dependency>
    <groupId>opensymphony</groupId>
    <artifactId>webwork</artifactId>
    <version>2.2.3</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </exclusion>
    </exclusions>
</dependency>

4、runtime设置在运行时加载该依赖项,但是编译时不依赖。

这种场景很少用的。

exclusions标签

主要解决jar包冲突的,

比如httpclient

我们可能在多个jar包中用到它了,但是引起jar包冲突了,我们就需要把在父类中定义统一的版本号,同时在子pom中排出掉就行了。

它的书写规范就是把 <groupId> 和 <artifactId>作为唯一的表示排出掉就行了,例如下面的案例

还有好多配置上面是最主要的。用到在说

<name>qingruihappy_duoxiancheng Maven Webapp</name>

<url>http://maven.apache.org</url>

2.6, 依赖传递

第一列表示直接依赖的scope,第一行表示间接依赖的scope

compile test provided runtime

compile compile - - runtime

test test - - test

provided provided - provided provided

runtime runtime - - runtime

知道有上面的存在就行了,一般很少用到的。

2.7,依赖仲裁:

我们来看上面的案例:

当web即依赖1.1-common 有依赖 1.0common的时候它最终选择哪个呢?

最短路径原则:选择1.0-common

假如出现上面的情况:路劲长短都是一样的,那么会依赖谁呢?

加载先后的顺序:

这个时候就会根据我们pom.xml文件写的顺序,谁写在前面就依赖谁。

2.8,maven的声明周期

们在用maven构建java项目时,最常用的打包命令有mvn clean ,mvn package、mvn install、deploy,这四个命令都可完成打jar包或war(当然也可以是其它形式的包)的功能。

但是这并不是maven的生命周期,只是生命周期的一部分,下面这张图就是maven的整个生命周期。

这个上面就是maven的全部的声明周期,但是我们现在只说一下标注黄色的主要的命名,它的声明周期一般是从左往右,从上到下的。

执行后面的命令的时候都会把前面的命令执行一遍。

其实在这个目录下我们可以看到maven 声明周期的插件

我们借鉴网上https://blog.csdn.net/zhaojianting/article/details/80321488这篇网站来写一下。

我们先来看一张图

可以看到整个执行过程包含了:1.clean 2.resources 3.compile 4.testResources 5.testCompile 6.test 7.jar 8.install;接下来详细说下各个插件的具体的作用;

2.8.1:clean插件maven-clean-plugin:2.5

clean插件是一个独立的阶段,功能是删除当前项目的target目录;这个自己也可以测试下,执行之后就是把target目录删除了而已;

2.8.2:resources插件maven-resources-plugin:2.6

resources插件的功能是把src/main/resources目录的文件拷贝到target/classes目录下;如果不存在src/main/resources目录,则不会做任何处理,测试期间,可以创建一个resources目录,里面添加个1.txt文件,然后执行resources插件,结果如图所示
resource插件的功能就是把项目需要的配置文件拷贝到指定的目当,默认是拷贝src\main\resources目录下的件到classes目录下,当然可以自己来配置源目录和输出目录。resources插件一般不单独执行,complie插件执行时会先调用resources插件。

2.8.3:compile插件maven-compiler-plugin

compile插件执行时,会先执行resources插件,主要的作用就是把src/main/java代码编译成字节码生成class文件,输出到targe/classes目录下;执行效果如图

2.8.4:.单元测试使用的插件testResource,testCompile

类似于resources和compile,只不过这两个类主要用于对单元测试的资源文件和代码进行编译;生成的文件位于target/test-classes下面;

有时候可以使用mvn -Dmaven.test.skip=true 跳过该步骤

2.8.5:package  maven-jar-plugin

这个插件是把class文件,resources文件打包成一个jar包,依赖包是不在里面包含的;常用的打包的插件有maven-jar-plugin、maven-assembly-plugin、maven-shade-plugin三种;生成的jar包位于target目录下;

2.8.6:install    maven-install-plugin

install是把构建好的artifact部署到本地仓库中;这样本地的其他项目依赖于本项目的jar时可以直接从本地仓库去获取,而不用到远端的私服上去下载;

2.8.7:.deploy

deploy是将本地的jar部署到远端的仓库;需要在maven的setting.xml中配置私服的用户名和密码;还需要再pom.xml做配置;

<distributionManagement>
   <repository>
     <id>releases</id>
     <name>Internal Releases</name>
     <url>http://localhost:8081/nexus/content/repositories/thirdparty</url>
   </repository>
   <snapshotRepository>
     <id>releases</id>
     <name>Internal Releases</name>
     <url>http://localhost:8081/nexus/content/repositories/thirdparty</url>
   </snapshotRepository>
 </distributionManagement> 

2.8.8:总结(重要的命名)

mvn clean package依次执行了clean、resources、compile、testResources、testCompile、test、jar(打包)等7个阶段。
mvn clean install依次执行了clean、resources、compile、testResources、testCompile、test、jar(打包)、install等8个阶段。
mvn clean deploy依次执行了clean、resources、compile、testResources、testCompile、test、jar(打包)、install、deploy等9个阶段。

由上面的分析可知主要区别如下,

package命令完成了项目编译、单元测试、打包功能,但没有把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库和远程maven私服仓库
install命令完成了项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库,但没有布署到远程maven私服仓库
deploy命令完成了项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库和远程maven私服仓库

  

原文地址:https://www.cnblogs.com/qingruihappy/p/10398649.html

时间: 2024-07-29 16:40:50

maven一篇文章就够了(上)的相关文章

Android:学习AIDL,这一篇文章就够了(上)

前言 在决定用这个标题之前甚是忐忑,主要是担心自己对AIDL的理解不够深入,到时候大家看了之后说--你这是什么玩意儿,就这么点东西就敢说够了?简直是坐井观天不知所谓--那样就很尴尬了.不过又转念一想,我辈年轻人自当有一种一往无前的锐气,标题大气一点岂不更好?并且大家都是文明人,总归更多的是理解与补充而不是侮辱与谩骂?所以最终还是厚颜用了这么一个不怎么有耻的标题. 好了,接下来进入正题,谈谈我对AIDL的理解和认识. 正文 1,概述 AIDL是一个缩写,全称是Android Interface D

(转) TensorFlow深度学习,一篇文章就够了

TensorFlow深度学习,一篇文章就够了 2016/09/22 · IT技术 · TensorFlow, 深度学习 分享到:6 原文出处: 我爱计算机 (@tobe迪豪 ) 作者: 陈迪豪,就职小米科技,深度学习工程师,TensorFlow代码提交者. TensorFlow深度学习框架 Google不仅是大数据和云计算的领导者,在机器学习和深度学习上也有很好的实践和积累,在2015年年底开源了内部使用的深度学习框架TensorFlow. 与Caffe.Theano.Torch.MXNet等框

面试题-关于Java线程池一篇文章就够了

在Java面试中,线程池相关知识,虽不能说是必问提,但出现的频次也是非常高的.同时又鉴于公众号"程序新视界"的读者后台留言让写一篇关于Java线程池的文章,于是就有本篇内容,本篇将基于Java线程池的原理.实现以及相关源码进行讲解等. 什么是线程池 线程池是一种多线程处理形式,处理过程中将任务提交到线程池,任务的执行交由线程池来管理. 为了充分利用CPU多核资源,应用都会采用多线程并行/并发计算,最大限度的利用多核提升应用程序性能. 试想一下,如果每个请求都执行一遍创建线程.执行任务.

关于HTTPS一篇文章就够了

欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/54754921 本文出自:[余志强的博客] HTTP是明文请求的,它的域名.路径和参数都被中间人看得一清二楚.Google鼓励所有的网站都要使用Https,AppStore也要求新的app也要是https协议,随着各大巨头对网络安全的重视,对用户隐私的重视,是时候系统的研究下Https了. 以前在开发App的时候,在App里面内嵌H5界面,我们这个H5是http协议的

扩展方法从简单应用到深入解析,读这一篇文章就够了

前言(扯淡-_-) 大家好,今天和大家聊聊扩展的事,我将带着大家从简单应用开始深入理解扩展方法的原理,并对扩展方法的使用给出合理的建议. 在实际应用中,当我们在使用某类时发现类中缺少我们想要的方法,最简单直接的就是修改类的源代码来添加我们想要的方法.但事实往往不如人意,总会因为各种因素不可以直接修改源码:拿不到源码.不允许修改,这时候通过继承并扩展的方式来复用是再好不过了,但是如果连最后的继承的权利都剥夺的话(密封类不允许继承)?...这时候就需要用到[扩展方法]了. 扩展方法简介 我们先来看看

学习 ES6,一篇文章就够了

ES6 简介 ECMAScript 6 简称 ES6,是 JavaScript 语言的下一代标准,已经在2015年6月正式发布了.它的目标是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言. ECMAScript 和 JavaScript 的关系:前者是后者的语法规格,后者是前者的一种实现 Babel:将ES6代码转为ES5代码 http://babeljs.io/ image 新特性 let.const let 定义的变量不会被变量提升,const 定义的常量

如何进行云主机迁移?看这一篇文章就够了!

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云计算产品团队发表于云+社区专栏 主机迁移概述 在云计算时代,不管是从IDC上云还是多云直接的迁移,都已经是常见的事宜.而在上云/迁移的方案中,也是有多种的方式能够将主机迁移到腾讯云中. 然而,不同的方式会有不同的利弊. 目前,腾讯云可以提供导入镜像和服务迁移(冷迁移)的工具,而这两种方式均涉及到镜像制作.故本文将分享镜像制作的操作步骤,仅供参考. 1.在制作镜像之前需要了解符合导入腾讯云的镜像文件要求,详情可参考导入镜像概述

彻底理解Netty,这一篇文章就够了

Netty到底是什么 从HTTP说起 有了Netty,你可以实现自己的HTTP服务器,FTP服务器,UDP服务器,RPC服务器,WebSocket服务器,Redis的Proxy服务器,MySQL的Proxy服务器等等. 我们回顾一下传统的HTTP服务器的原理 1.创建一个ServerSocket,监听并绑定一个端口 2.一系列客户端来请求这个端口 3.服务器使用Accept,获得一个来自客户端的Socket连接对象 4.启动一个新线程处理连接 4.1.读Socket,得到字节流 4.2.解码协议

Activity、View、Window的理解一篇文章就够了

作者:细卷子 博客:http://www.jianshu.com/u/511ccb5a2012 要了解这三者之间的关系,我们带着问题通过分析源码一步一步来揭开它们的神秘面纱! 文章有点长,首先要理解Activity.View.Window,我提出了一些问题,这篇文章可以解答如下问题: 1.为什么要设计Activity.View.Window? 2.Activity工作过程是什么样的?(理解Activity) 3.Window是什么?它的职能是什么? 4.View跟Window有什么联系? 5.A