maven的使用和爬过的坑

maven的使用和爬过的坑

maven的介绍及使用

一. 为何要使用maven?

公司之前的项目类型是传统的hadoop项目
发到全国各地的现场去运行
但是遇到的问题是:

1. 版本管理混乱
开发人员直接从svn下载代码发送给现场
版本多的时候,出现问题难以定位,为问题的排查和解决增加了很大的难度

2. 对于部分地市,jar包过大

部分地市的特殊性,会需要一些独特的jar包,
为了保证程序正常运行,需要把相关jar包打进去, 导致jar包达到100-200M, 严重影响使用和效率

3. 项目过于复杂, 层次结构不够清晰,显得很臃肿,
不利于新同事理解业务

4.  容易出现jar包冲突或者是缺少相应的依赖jar包

随着需要的jar包越来越多, 每次引入jar包也需要小心翼翼, 说不准什么时候就会造成jar包冲突, 

而且也很容易造成某个jar包依赖的jar包没有引入而导致整个项目跑不起来

基于以上, 我们引入了maven

1. 在集群的某个节点上面搭建了
maven3.5 + nexus3(私仓)
这样 对测试通过的版本才会进行编译
开发人员去私仓上面下载最新的版本发布给现场,保证了版本的稳定性

2. 在pom.xml里面添加相应依赖
并使用如下标签来排除不需要的配置:
一个例子 : 
 <excludes>
    <exclude>META-INF/*.SF</exclude>
    <exclude>META-INF/*.DSA</exclude>
    <exclude>META-INF/*.RSA</exclude>
</excludes>

经过优化,原来200M才能跑起来的jar包后面4M就可以正常运行!

3.利用Maven将核心项目拆分成5个模块
层次结构非常清晰,一目了然!

4. jar包冲突的问题 :
在冲突的地方像第二条一样排除掉冲突的地方即可!

缺少依赖jar包的问题:
maven在导包的时候会自动把依赖的jar包导进来,完全不需要担心!

二. maven的使用

1. maven环境变量的配置
     a. 下载解压maven
    maven官网下载链接 : https://maven.apache.org/download.cgi
    b. 设置环境变量
    打开我的电脑(此电脑) -->右键选择-->属性-->高级系统设置-->环境变量
    
    新建变量 : MAVEN_HOME
    变量名为 : E:\softWare\bigData\maven3.5.4\apache-maven-3.5.4 // 这里是maven解压后的路径
    
    修改变量 : PATH
    win10 直接在原来的基础上添加
    %MAVEN_HOME%\bin即可
    
    c. 检验环境变量是否安装成功: 
    cmd命令输入 : echo %MAVEN_HOME%

这里写图片描述
继续输入 : mvn -version
这里写图片描述
出现上述提示证明安装成功!!

2.maven项目的打包
首先需要介绍一下 : maven项目的依赖

传统项目的依赖 : 项目右键 --> Build Path --> Configure Build Path
即可添加,编辑,和删除项目依赖

这里写图片描述
maven项目 通过pom.xml里面的配置来进行管理
比如说:

	  <dependencies>
        <dependency>
            <groupId>pers.xmr.bigdata</groupId>
            <artifactId>bigdata-common</artifactId>
            <version>${bigdata-common-version}</version>
        </dependency>
        <dependency>
            <groupId>pers.xmr.bigdata</groupId>
            <artifactId>bigdata-hadoop-tools</artifactId>
            <version>${bigdata-hadoop-tools-version}</version>
        </dependency>

      </dependencies>

对于没有任何依赖的项目,右键
1.run as --> Maven clean
这里写图片描述
2.run as–>Maven install
这里写图片描述
3.去到该项目的target目录下拿jar包就可以了
jar包里面的第一个就是我们所需要的!

对于有依赖的项目:

第一次打包的时候: 需要先从依赖的项目开始,依次执行
maven clean --> maven install 命令
然后去target目录下拿jar包
之后, 如果依赖的项目没有变动的话,直接对该项目执行
maven clean–>maven install 命令即可!

3.引入jar包的时候排除掉jar包冲突

这个在介绍maven有点的时候已经介绍到, 这里举一个实例来详细说明:

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>${hadoop-version}</version>
            <exclusions>  
           <!--  hadoop,spark程序运行的时候会导致jar包冲突  -->
       		 	 <exclusion>  
            		<groupId>javax.servlet</groupId>  
            		<artifactId>*</artifactId>  
        		</exclusion>
        		<!-- 已经有一个类来解析xml,再引入这个包会导致冲突 -->
       		 	<exclusion>
       		 		<groupId>xerces</groupId>
       		 		<artifactId>xercesImpl</artifactId>
       		 	</exclusion>
       		 	<!-- 已经有一个类来解析xml,再引入这个包会导致冲突 -->
       		 	<exclusion>
       		 		<groupId>xalan</groupId>
       		 		<artifactId>xalan</artifactId>
       		 	</exclusion>
            </exclusions>  
        </dependency>

上面的这个实例就是在引入jar包的时候,去除掉会导致jar包冲突的实例
就是在 dependency里面加入exclusion标签,在里面配置好每一个不需要引入的包即可!

3. 打包的时候引入相应的包,或者是排除掉不需要的配置

引入相应的包 :
将需要的部分导入进jar包里,保证程序正常运行

	<-- 以下的这个实例是我在原有的项目增加redis的使用添加的,需要将redis相关的类打到jar包里,保证程序正常执行!-->
	<artifactSet>
		<includes>
			<include>cn.mastercom*</include>
			<include>org.apache.commoms.pool2*</include>
			<include>redis*</include>
		</includes>
	</artifactSet>

排除掉不需要的配置
我们的主要目的就是使打出来的jar包尽可能小,节约jar包传输的时间

	<!-- 排除不需要的配置 -->
	<excludes>
	       	<exclude>org/**/*.xml</exclude>
	       	<exclude>org/**/*.properties</exclude>
	       	<exclude>remote/**</exclude>
	       	<exclude>local/**</exclude>
                <exclude>META-INF/*.SF</exclude>
               <exclude>META-INF/*.DSA</exclude>
               <exclude>META-INF/*.RSA</exclude>
      </excludes>
4. 如何使用我们自定义的xml文件而不是默认的pom.xml文件?
在打包的时候,maven默认会按照pom.xml里的配置来引入依赖,
但是有的地市比较特殊,需要为其配置单独的xml文件才能保证程序正常运行,那么如何使打包的时候按照我们配置的文件来打包呢?

1. 首先要保证该项目依赖的项目已经执行 maven install成功
2. 通过 cmd 命令进入到该项目的文件夹下面
3. 执行命令 mvn clean

这里写图片描述

4.执行命令:  mvn -f=pom.guangxi.xml package
其中pom.guangxi.xml为我们想要其编译的xml文件名
5.打jar包的时候指定主类
	 <transformers>
	         <transformer
	                  implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
	              <mainClass>pers.xmr.bigdata.mapr.Main</mainClass>
	          </transformer>
	      </transformers>

这样,该jar包就会以我们设置的pers.xmr.bigdata.mapr.Main为主类,
而不需要我们在运行的时候自己指定!

6. 自动排除掉不需要的类及我爬的坑

有一个minimizeJar标签, 将该标签设置为true的时候会自动排除掉不需要的类,很好用,
但是一定要慎用!!! 一定要慎用!!!

                   <minimizeJar>true</minimizeJar>

  这里分享一个坑了我很久的问题 : 
 
 在hadoop框架里使用redis的时候,本地测试已经没有问题,但是打成jar包放到集群上的时候报了如下问题:
 
  18/07/17 09:12:51 INFO mapreduce.Job: Task Id : attempt_1528676607738_0866_r_000000_2, Status : FAILED
 Error: java.lang.IllegalArgumentException: Unable to create EvictionPolicy instance of type org.apache.commons.pool2.impl.DefaultEvictionPolicy
 	at org.apache.commons.pool2.impl.BaseGenericObjectPool.setEvictionPolicyClassName(BaseGenericObjectPool.java:615)
 	at org.apache.commons.pool2.impl.GenericObjectPool.setConfig(GenericObjectPool.java:321)
 	at org.apache.commons.pool2.impl.GenericObjectPool.<init>(GenericObjectPool.java:117)
 	at redis.clients.util.Pool.initPool(Pool.java:44)
 	at redis.clients.util.Pool.<init>(Pool.java:23)
 	at redis.clients.jedis.JedisPool.<init>(JedisPool.java:185)
 	at redis.clients.jedis.JedisClusterInfoCache.setupNodeIfNotExist(JedisClusterInfoCache.java:158)
 	at redis.clients.jedis.JedisClusterInfoCache.discoverClusterNodesAndSlots(JedisClusterInfoCache.java:74)
 	at redis.clients.jedis.JedisClusterConnectionHandler.initializeSlotsCache(JedisClusterConnectionHandler.java:39)
 	at redis.clients.jedis.JedisClusterConnectionHandler.<init>(JedisClusterConnectionHandler.java:17)
 	at redis.clients.jedis.JedisSlotBasedConnectionHandler.<init>(JedisSlotBasedConnectionHandler.java:24)
 	at redis.clients.jedis.BinaryJedisCluster.<init>(BinaryJedisCluster.java:54)
 	at redis.clients.jedis.JedisCluster.<init>(JedisCluster.java:93)
 	at cn.mastercom.bigdata.util.redis.JedisClusterFactory.getJedisCluster(JedisClusterFactory.java:68)
 	at cn.mastercom.bigdata.mapr.mro.loc.MroLableFileReducers$MroDataFileReducers.setup(MroLableFileReducers.java:61)
 	at org.apache.hadoop.mapreduce.Reducer.run(Reducer.java:168)
 	at org.apache.hadoop.mapred.ReduceTask.runNewReducer(ReduceTask.java:627)
 	at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:389)
 	at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:164)
 	at java.security.AccessController.doPrivileged(Native Method)
 	at javax.security.auth.Subject.doAs(Subject.java:415)
 	at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1657)
 	at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:158)
 Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.DefaultEvictionPolicy
 	at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
 	at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
 	at java.security.AccessController.doPrivileged(Native Method)
 	at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
 	at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
 	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
 	at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
 	at java.lang.Class.forName0(Native Method)
 	at java.lang.Class.forName(Class.java:191)
 	at org.apache.commons.pool2.impl.BaseGenericObjectPool.setEvictionPolicyClassName(BaseGenericObjectPool.java:606)
 	... 22 more

一看是ClassNotFoundException这种简单的报错,首先怀疑的肯定是没有导入jar包 :
于是去pom.xml里面去查看相应的配置 :
确实是没有直接引入commons-pool2 2.2这个jar包
只有这个 :

   <dependency>
          <groupId>redis.clients</groupId>
           <artifactId>jedis</artifactId>
           <version>2.9.0</version>
           <type>jar</type>
           <scope>compile</scope>
  </dependency>

于是我画蛇添足的加上了这个配置:

	 <!--   
   		<dependency>
    		<groupId>org.apache.commons</groupId>
    		<artifactId>commons-pool2</artifactId>
    		<version>2.2</version>
		</dependency> 
	  -->

打成jar包丢上去跑仍然报同样的问题,于是我去掉了这个配置
发现,在Maven Dependencies 是有相对应的jar包的:
这里写图片描述
maven会在导入jar包的时候自动导入相互依赖的jar包! 而jedis-2.9.0.jar是依赖于commons-pool2-2.4.2.jar的 所以会一并导入

那会不会是打包的时候没有把相应的jar包打进去呢?
但是我的pom.xml文件是有这样的配置的:

	<artifactSet>
		<includes>
			 <include>cn.mastercom*</include>
		     <include>org.apache.commons.pool2*</include>
			 <include>redis*</include>
		</includes>
	</artifactSet>

这证明了确实是把相关的jar包打进来的, 我就很疑惑了??
难道是集群抽风了?? 实际上,计算机永远都是比人可靠的
我打开了那个jar文件,发现了org.apache.commons.pool2.impl
这个包在jar包里面确实是存在的,而且这个包下面有一大堆的**.class文件
却唯独缺少了 DefaultEvictionPolicy类
.class**文件,证明确实是没有这个类的

那会不会是这个jar包本身就没有这个类呢?
当然是不可能的
这里写图片描述

排除了上述问题之后,把问题定位到了这个配置上面

	<minimizeJar>true</minimizeJar>

尝试着把这个配置改成false,打成jar包丢到集群上跑,成功了!!!
这里写图片描述

也就是说,这个配置把我们需要的类给过滤掉了!
官网中对这个标签的解释如下 : (官网原话:)
附上这一部分的官网链接, 有兴趣的可以点进去看一下:

	As of version 1.6, minimizeJar will respect classes that were specifically marked for inclusion in a filter. 
	Note that specifying an include filter for classes in an artifact implicitly excludes all non-specified classes in that artifact.

7.如何设置开发和编译的版本?

为什么需要有这个需求呢?
我们本地的开发人员普遍使用的是JDK1.8,但是有的现场集群环境JDK是1.7
所以编译需要设置为1.7,否则,程序执行的时候就会报错!
普通的项目

右键–>properties–>JavaCompiler–>被圈起来的地方设置为1.7即可
这里写图片描述

maven是这样配置的

	<build>
	        <plugins>
	            <plugin>
	                <groupId>org.apache.maven.plugins</groupId>
	                <artifactId>maven-compiler-plugin</artifactId>
	                <version>3.2</version>
	                <configuration>
	                    <source>1.7</source> <!-- 源代码使用的开发版本 -->
	                    <target>1.7</target> <!-- 需要生成的目标class文件的编译版本 -->
	
	                    <!-- 这下面的是可选项 -->
	                    <!-- <meminitial>128m</meminitial>-->
	                    <!--<maxmem>512m</maxmem>-->
	                    <!--<fork>true</fork>--> <!-- fork is enable,用于明确表示不同于默认的JDK去编译 -->
	                    <!-- <compilerVersion>1.3</compilerVersion>-->
	
	                    <!-- 这个选项用来传递编译器自身不包含但是却支持的参数选项 -->
	                    <!--<compilerArgument>-verbose -bootclasspath ${java.home}\lib\rt.jar</compilerArgument>-->
	
	                </configuration>
	            </plugin>
	        </plugins>
	    </build>

上面介绍到的只是冰山一角,maven还有很多有趣的特性值得去开发和应用,
而且对于一个深受传统项目毒害的人来说,用了maven,真的是回不去了!

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值