前言:
团队在开发过程中用的是maven项目,由于对maven的一些打包流程以及相关参数配置不是太了解,因此应大家的需求做一下maven的讲解,为了不误导大家,看了很多相关资料,自己也实验了一下,就把自己觉得对大家有用的东西列出来,做了一些简单的介绍,起到抛砖引玉的作用,希望能对大家能有帮助。
一、什么是maven
Maven是一个Java语言编写的开源项目管理工具,是Apache软件基金会的顶级项目。主要用于项目构建,依赖管理,项目信息管理。
二、Maven诞生的背景
Maven这个单词来自于意第绪语(犹太语),意为知识的积累,最初在Jakata Turbine项目中用来简化构建过程。当时有一些项目(有各自Ant build文件),仅有细微的差别,而JAR文件都由CVS来维护。于是希望有一种标准化的方式构建项目,一个清晰的方式定义项目的组成,一个容易的方式发布项目的信息,以及一种简单的方式在多个项目中共享JARs。
三、Maven特点
1. maven不仅是构建工具,它还是依赖管理工具和项目管理工具,提供了中央仓库,能够帮我们自动下载构件。
2.为了解决的依赖的增多,版本不一致,版本冲突,依赖臃肿等问题,它通过一个坐标系统来精确地定位每一个构件(artifact)。
3.还能帮助我们分散在各个角落的项目信息,包括项目描述,开发者列表,版本控制系统,许可证,缺陷管理系统地址。
4.maven还为全世界的java开发者提供了一个免费的中央仓库,在其中几乎可以找到任何的流行开源软件。通过衍生工具(Nexus),我们还能对其进行快速搜索
5.maven对于目录结构有要求,约定优于配置,用户在项目间切换就省去了学习成本。
6.跨平台,是声明式的,没有依赖管理。
四、Maven私服的搭建
一、为什么搭建Maven私服
有些公司都不提供外网给项目组人员,因此就不能使用maven访问远程的仓库地址,所以很有必要在局域网里找一台有外网权限的机器,搭建nexus私服,然后开发人员连到这台私服上,这样的话就可以通过这台搭建了nexus私服的电脑访问maven的远程仓库。
二、Maven仓库
Maven库:
http://repo2.maven.org/maven2/
Maven依赖查询:
maven的仓库只有两大类:1.本地仓库 2.远程仓库,在远程仓库中又分成了3种:2.1 中央仓库 2.2 私服 2.3 其它公共库;如图:
1.本地仓库
Maven在本地存储构件的地方。
2. 远程仓库
2.1 中央仓库
中央仓库是默认的远程仓库,maven在安装的时候,自带的就是中央仓库的配置。
2.2 私服
Maven私服的 个特性:
1.节省自己的外网带宽:减少重复请求造成的外网带宽消耗
2.加速Maven构件:如果项目配置了很多外部远程仓库的时候,构建速度就会大大降低
3.部署第三方构件:有些构件无法从外部仓库获得的时候,我们可以把这些构件部署到内部仓库(私服)中,供内部maven项目使用
4.提高稳定性,增强控制:Internet不稳定的时候,maven构建也会变的不稳定,一些私服软件还提供了其他的功能
5.降低中央仓库的负荷:maven中央仓库被请求的数量是巨大的,配置私服也可以大大降低中央仓库的压力
当前主流的maven私服:
1.Apache的Archiva
2.JFrog的Artifactory
3.Sonatype的Nexus
三、搭建Maven私服
详细介绍地址:http://www.cnblogs.com/quanyongan/archive/2013/04/24/3037589.html
http://blog.csdn.net/clj198606061111/article/details/52200928
在安装安装nexus如果出现这种情况:
以管理员身份运行cmd.exe即可。
五、Maven安装
安装教程:http://jingyan.baidu.com/article/4f7d5712a1306c1a21192746.html
六、settings.xml配置
详细介绍地址:http://blog.csdn.net/u014527058/article/details/50906343
1 <?xml version="1.0" encoding="UTF-8"?> 2 <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> 5 6 7 <proxies> 8 9 </proxies> 10 11 12 <servers> 13 14 <!--用来实现热部署 --> 15 <server> 16 <id>tomcat7x</id> 17 <username>admin</username> 18 <password>admin</password> 19 </server> 20 <!--用来发布项目到nexus的相对应的发布目录下 ,这里的id要和eclipse中配置的一样--> 21 <server> 22 <id>user-release</id> 23 <username>deployment</username> 24 <password>deployment123</password> 25 </server> 26 <!--用来发布项目到nexus的相对应的快照目录下 ,这里的id要和eclipse中配置的一样--> 27 <server> 28 <id>user-snapshots</id> 29 <username>deployment</username> 30 <password>deployment123</password> 31 </server> 32 </servers> 33 34 <mirrors> 35 36 <mirror> 37 <id>public</id> 38 <mirrorOf>*</mirrorOf> 39 <name>Human Readable Name for this Mirror.</name> 40 <!--<url>http://repo.maven.apache.org/maven2/</url>--> 41 <url>http://maven私服ip地址:8081/nexus/content/groups/public/</url> 42 </mirror> 43 44 </mirrors> 45 46 47 <profiles> 48 49 <profile> 50 <id>nexus</id> 51 <repositories> 52 <repository> 53 <id>central</id> 54 <url>http://central</url> 55 <releases><enabled>true</enabled></releases> 56 <snapshots><enabled>true</enabled><updatePolicy>always</updatePolicy></snapshots> 57 </repository> 58 </repositories> 59 <pluginRepositories> 60 <pluginRepository> 61 <id>central</id> 62 <url>http://central</url> 63 <releases><enabled>true</enabled></releases> 64 <snapshots><enabled>true</enabled></snapshots> 65 </pluginRepository> 66 </pluginRepositories> 67 </profile> 68 69 <profile> 70 <id>jdk-1.7</id> 71 <activation> 72 <activeByDefault>true</activeByDefault> 73 <jdk>1.7</jdk> 74 </activation> 75 <properties> 76 <maven.compiler.source>1.7</maven.compiler.source> 77 <maven.compiler.target>1.7</maven.compiler.target> 78 <maven.compiler.compilerVersion>1.7</maven.compiler.compilerVersion> 79 </properties> 80 </profile> 81 82 </profiles> 83 84 <activeProfiles> 85 <activeProfile>nexus</activeProfile> 86 </activeProfiles> 87 </settings>
七、Maven工程的创建
省略,这些在网上一搜一大堆,这里就不再啰嗦了。
知识驿站(具体了解地址:http://blog.csdn.net/cnhk1225/article/details/51189467):
maven中的仓库分为两种,snapshot快照仓库和release发布仓库。snapshot快照仓库用于保存开发过程中的不稳定版本,release正式仓库则是用来保存稳定的发行版本。定义一个组件/模块为快照版本,只需要在pom文件中在该模块的版本号后加上-SNAPSHOT即可(注意这里必须是大写)
八、pom.xml的配置
一、插件配置详解地址:
http://www.cnblogs.com/dennyzhangdd/p/5831112.html
1 <?xml version="1.0"?> 2 <project 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" 4 xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 5 <modelVersion>4.0.0</modelVersion> 6 <parent> 7 <groupId>组织名</groupId> 8 <artifactId>父工程名</artifactId> 9 <version>版本号</version> 10 </parent> 11 <artifactId>子工程名</artifactId> 12 <packaging>war</packaging> 13 <dependencies> 14 15 </dependencies> 16 <profiles> 17 <!-- 开发/测试环境,默认激活 --> 18 <profile> 19 <id>dev</id> 20 <properties> 21 <env>dev</env> 22 <tomcat.host>远程tomcat的地址</tomcat.host> 23 <tomcat.port>${tomcatPort}</tomcat.port> 24 <tomcat.username>admin</tomcat.username> 25 <tomcat.password>admin</tomcat.password> 26 </properties> 27 <activation> 28 <activeByDefault>true</activeByDefault><!--默认启用的是dev环境配置--> 29 </activation> 30 </profile> 31 <!-- 生产环境 --> 32 <profile> 33 <id>prod</id> 34 <properties> 35 <env>prod</env> 36 <tomcat.host>远程服务器ip地址</tomcat.host> 37 <tomcat.port>${tomcatPort}</tomcat.port> 38 <tomcat.username>admin</tomcat.username> 39 <tomcat.password>admin</tomcat.password> 40 </properties> 41 </profile> 42 <profile> 43 <id>qa</id> 44 <properties> 45 <env>qa</env> 46 <tomcat.host>远程服务器ip地址</tomcat.host> 47 <tomcat.port>${tomcatPort}</tomcat.port> 48 <tomcat.username>admin</tomcat.username> 49 <tomcat.password>admin</tomcat.password> 50 </properties> 51 </profile> 52 </profiles> 53 54 <build> 55 <finalName>ucf-personal</finalName> 56 <plugins> 57 <!-- 用来支持maven自带的命令 --> 58 <plugin> 59 <groupId>org.apache.maven.plugins</groupId> 60 <artifactId>maven-compiler-plugin</artifactId> 61 <version>3.1</version> 62 <configuration> 63 <source>1.7</source> 64 <target>1.7</target> 65 </configuration> 66 </plugin> 67 <!-- 用cargo插件来实现项目自动远程热部署 --> 68 <plugin> 69 <groupId>org.codehaus.cargo</groupId> 70 <artifactId>cargo-maven2-plugin</artifactId> 71 <version>1.4.9</version> 72 <configuration> 73 <container> 74 <containerId>tomcat7x</containerId> 75 <type>remote</type> 76 </container> 77 <configuration> 78 <type>runtime</type> 79 <properties> 80 <cargo.remote.uri>http://${tomcat.host}:${tomcat.port}/manager/text</cargo.remote.uri> 81 <cargo.remote.username>${tomcat.username}</cargo.remote.username> 82 <cargo.remote.password>${tomcat.password}</cargo.remote.password> 83 </properties> 84 </configuration> 85 </configuration> 86 </plugin> 87 </plugins> 88 <!-- 根据构建环境的改变(生产或测试)来获得相应的值 --> 89 <filters> <!-- 指定使用的 filter --> 90 <filter>src/main/resources/filter/${env}.properties</filter> 91 </filters> 92 <resources> 93 <resource> <!-- 配置需要被替换的资源文件路径, db.properties 应该在 src/main/resource 目录下 --> 94 <directory>src/main/resources</directory> 95 <filtering>true</filtering> <!-- 是否使用过滤器 --> 96 </resource> 97 </resources> 98 </build> 99 <properties> 100 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 101 </properties> 102 <distributionManagement> 103 <repository> 104 <id>releases</id> 105 <name>releases</name> 106 <url>http://远程服务器ip地址:8081/nexus/content/repositories/releases/</url> 107 </repository> 108 <snapshotRepository> 109 <id>snapshots</id> 110 <name>snapshots</name> 111 <url>http://远程服务器ip地址:8081/nexus/content/repositories/snapshots/</url> 112 </snapshotRepository> 113 </distributionManagement> 114 </project>
web.xml动态给变量赋值
1.在<profile>
的<properties>
标签中添加与web.xml中相对应的${cas.serverLoginUrl
}的key作为标签,
在里面赋值,如:<cas.serverLoginUrl>http://10.1.1.1</cas.serverLoginUrl>
1 <profiles> 2 <profile> 3 <id>development</id> 4 <activation> 5 <activeByDefault>true</activeByDefault> 6 </activation> 7 <properties> 8 <profiles.active>dev</profiles.active> 9 <mybatis.log>ERROR</mybatis.log> 10 <log.path>/opt/dev/</log.path> 11 <cas.serverLoginUrl>http://10.1.1.1</cas.serverLoginUrl> 12 <cas.serverName>http://10.1.1.1</cas.serverName> 13 <cas.serverUrlPrefix>http://10.1.1.1</cas.serverUrlPrefix> 14 </properties> 15 </profile> 16 </profiles>
2.在工程的pom.xml中,新增过滤web资源配置
1 <plugin> 2 <groupId>org.apache.maven.plugins</groupId> 3 <artifactId>maven-war-plugin</artifactId> 4 <version>2.1.1</version> 5 <configuration> 6 <webResources> 7 <resource> 8 <directory>src/main/webapp</directory> 9 <filtering>true</filtering> 10 </resource> 11 </webResources> 12 </configuration> 13 </plugin>
3.在web.xml中用占位符替换
1 <filter> 2 <filter-name>CASFilter</filter-name> 3 <filter-class>com.ezubo.global.om.web.filter.LoginFilter</filter-class> 4 <init-param> 5 <param-name>casServerLoginUrl</param-name> 6 <param-value>${cas.serverLoginUrl}</param-value> 7 </init-param> 8 <init-param> 9 <param-name>serverName</param-name> 10 <param-value>${cas.serverName}</param-value> 11 </init-param> 12 <init-param> 13 <param-name>noFilterUrl</param-name> 14 <param-value>*.js</param-value> 15 </init-param> 16 </filter>
二、Jetty插件运行Maven Web工程
详细介绍地址:https://my.oschina.net/cokolin/blog/409164
1 <?xml version="1.0"?>
2 <plugin>
3 <groupId>org.mortbay.jetty</groupId>
4 <artifactId>jetty-maven-plugin</artifactId>
5 <version>8.1.16.v20140903</version>
6 <configuration>
7 <scanIntervalSeconds>5</scanIntervalSeconds>
8 <webApp>
9 <contextPath>/ucf-company</contextPath>
10 </webApp>
11 <connectors>
12 <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
13 <port>9080</port>
14 </connector>
15 <connector implementation="org.eclipse.jetty.server.ssl.SslSelectChannelConnector">
16 <port>9443</port>
17 <password>changeit</password>
18 </connector>
19 <!-- 这两个connector的配置要改为: -->
20 <connector implementation="org.eclipse.jetty.server.bio.SocketConnector">
21 <port>8080</port>
22 </connector>
23 <connector implementation="org.eclipse.jetty.server.ssl.SslSocketConnector">
24 <port>8443</port>
25 <password>changeit</password>
26 </connector>
27 </connectors>
28 </configuration>
29 </plugin>
三、Maven混淆代码
Maven的proguard插件只能混淆jar包。如果要混淆Web项目则将Web混淆的工程jar的classes替换打的war包的classes文件夹即可。
1 <build> 2 <plugins> 3 <plugin> 4 <groupId>com.github.wvengen</groupId> 5 <artifactId>proguard-maven-plugin</artifactId> 6 <version>2.0.7</version> 7 <executions> 8 <execution> 9 <phase>package</phase> 10 <goals> 11 <goal>proguard</goal> 12 </goals> 13 </execution> 14 </executions> 15 <configuration> 16 <attach>true</attach> 17 <attachArtifactClassifier>pg</attachArtifactClassifier> 18 <!-- attach 的作用是在 install 与 deploy 时将生成的 pg 文件也安装与部署 --> 19 <options> <!-- 详细配置方式参考 ProGuard 官方文档 --> 20 <!--<option>-dontobfuscate</option>--> 21 <option>-ignorewarnings</option> <!--忽略所有告警--> 22 <option>-dontshrink</option> <!--不做 shrink --> 23 <option>-dontoptimize</option> <!--不做 optimize --> 24 <option>-dontskipnonpubliclibraryclasses</option> 25 <option>-dontskipnonpubliclibraryclassmembers</option> 26 27 <option>-repackageclasses com.ucfgroup.framework.web.app.pg</option> 28 <!--平行包结构(重构包层次),所有混淆的类放在 pg 包下--> 29 30 <!-- 以下为 Keep,哪些内容保持不变,因为有一些内容混淆后(a,b,c)导致反射或按类名字符串相关的操作失效 --> 31 32 <option>-keep class **.package-info</option> 33 <!--保持包注解类--> 34 35 <option>-keepattributes Signature</option> 36 <!--JAXB NEED,具体原因不明,不加会导致 JAXB 出异常,如果不使用 JAXB 根据需要修改--> 37 <!-- Jaxb requires generics to be available to perform xml parsing and without this option ProGuard was not retaining that information after obfuscation. That was causing the exception above. --> 38 39 <option>-keepattributes SourceFile,LineNumberTable,*Annotation*</option> 40 <!--保持源码名与行号(异常时有明确的栈信息),注解(默认会过滤掉所有注解,会影响框架的注解)--> 41 42 <option>-keep class SSRuntimeEasyJava.** { *;}</option> 43 <!--保持 Bean 类,(由于很多框架会对 Bean 中的内容做反射处理,请根据自己的业务调整) --> 44 45 </options> 46 <outjar>${project.build.finalName}-pg</outjar> 47 <libs> 48 <lib>${java.home}/lib/rt.jar</lib> 49 </libs> 50 51 </configuration> 52 </plugin> 53 </plugins> 54 </build>
研究过程出现的问题:
如果没有<injar></injar>会报如下错误信息:
1 [ERROR] Failed to execute goal com.github.wvengen:proguard-maven-plugin:2.0.7:proguard (default) on project ucf-company: Obfuscation failed (result=1) -> [Help 1]
2 [ERROR]
3 [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
4 [ERROR] Re-run Maven using the -X switch to enable full debug logging.
5 [ERROR]
6 [ERROR] For more information about the errors and possible solutions, please read the following articles:
7 [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
具体实现参照地址:
http://www.cnblogs.com/yanduanduan/p/5340060.html
http://blog.csdn.net/wltj920/article/details/48970869
四、Maven打包时动态替换properties资源文件中的配置值:
1 <profiles>
2 <!-- 开发/测试环境,默认激活 -->
3 <profile>
4 <id>dev</id>
5 <properties>
6 <env>dev</env>
7 </properties>
8 <activation>
9 <activeByDefault>true</activeByDefault>
10 <!--默认启用的是dev环境配置-->
11 </activation>
12 </profile>
13 <!-- 生产环境 -->
14 <profile>
15 <id>prod</id>
16 <properties>
17 <env>prod</env>
18 </properties>
19 </profile>
20 <!-- qa环境 -->
21 <profile>
22 <id>qa</id>
23 <properties>
24 <env>qa</env>
25 </properties>
26 </profile>
27 </profiles>
28 <build>
29 <filters>
30 <!-- 指定使用的 filter -->
31 <filter>src/main/resources/filter/${env}.properties</filter>
32 </filters>
33 <resources>
34 <resource>
35 <!-- 配置需要被替换的资源文件路径, db.properties 应该在 src/main/resource 目录下 -->
36 <directory>src/main/resources</directory>
37 <filtering>true</filtering>
38 <!-- 是否使用过滤器 -->
39 </resource>
40 </resources>
41 </build>
九、Maven配置多模块项目
用项目层次的划分替代包层次的划分能给我们带来如下好处:
- 方便重用,如果你有一个新的swing项目需要用到app-dao和app-service,添加对它们的依赖即可,你不再需要去依赖一个WAR。而有些模块,如app-util,完全可以渐渐进化成公司的一份基础工具类库,供所有项目使用。这是模块化最重要的一个目的。
- 由于你现在划分了模块,每个模块的配置都在各自的pom.xml里,不用再到一个混乱的纷繁复杂的总的POM中寻找自己的配置。
- 如果你只是在app-dao上工作,你不再需要build整个项目,只要在app-dao目录运行mvn命令进行build即可,这样可以节省时间,尤其是当项目越来越复杂,build越来越耗时后。
- 某些模块,如app-util被所有人依赖,但你不想给所有人修改,现在你完全可以从这个项目结构出来,做成另外一个项目,svn只给特定的人访问,但仍提供jar给别人使用。
- 多模块的Maven项目结构支持一些Maven的更有趣的特性(如DepencencyManagement),这留作以后讨论。
一个简单的Maven模块结构是这样的:
---- app-parent
|-- pom.xml (pom)
|
|-- app-util
| |-- pom.xml (jar)
|
|-- app-dao
| |-- pom.xml (jar)
|
|-- app-service
| |-- pom.xml (jar)
|
|-- app-web
|-- pom.xml (war)
创建Maven多模块项目参照地址:http://www.cnblogs.com/huboking/p/4351921.html
十、Maven常用命令
mvn help:system 自动在本用户下创建 ~/.m2/repository
mvn clean compile 清理编译
mvn clean test 清理测试
mvn clean package 清理打包
mvn clean install 清理将打包好的jar存入 本地仓库 注意是本地仓库
mvn archetype:generate 使用Archetype生成项目骨架
mvn clean deploy 根据pom中的配置信息将项目发布到远程仓库中
十一、Maven常见错误排查
一.Maven工程出现红差解决方法:
进行maven clean、update,然后进行工程clean、tomcat clean,如果还没有去掉则说明是工程代码有问题,不属于工程环境的问题。
二.Maven工程出现感叹号解决方法:
产生原因:
因为一些maven管理的jar没能正确下载。
先查看buildpath,找问题的jar包,之后再一个个解决
对这些有问题的jar,是因为当前的maven仓库无法找到,所以可以通过如下方法添加能找到相应jar的maven仓库:
1.在google中直接搜索相应jar,比如:jmxri-1.2.1.jar
2.在搜索结果中找到有这个jar的maven仓库,并加入到setting.xml中。
3.重新对项目进行 右键 - maven - update dependencies。
十二、cargo远程部署项目到tomcat
tomcat-users.xml,至少要添加manager,manager-gui,manager-script,manager-jmx,manager-status,添加权限
<tomcat-users> <role rolename="tomcat"/> <role rolename="role1"/> <role rolename="manager"/> <role rolename="admin"/> <role rolename="manager-gui"/> <role rolename="manager-script"/> <role rolename="manager-jmx"/> <role rolename="manager-status"/> <!--admin角色没有的要注意添上--> <user username="tomcat" password="tomcat" roles="tomcat"/> <user username="admin" password="admin" roles="admin,manager,tomcat,manager-gui,manager-script,manager-jmx,manager-status"/> <!--你用哪个用户做管理员,则需要分配相应的角色,我给admin用户分配了admin和manager连个角色--> </tomcat-users>
注意:当解压的项目已存在时,会部署不成功,需要在context.xml中再Context标签中加入antiResourceLocking="true" 就可以了。
新版无需修改maven的settings.xml文件,网上很多误导别人的
mvn cargo:redeploy
<!-- 远程部署 ,tomcat必须启动-->
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.4.9</version>
<configuration>
<container>
<containerId>tomcat7x</containerId>
<type>remote</type>
</container>
<configuration>
<type>runtime</type>
<properties>
<cargo.remote.uri>http://${tomcat.host}:${tomcat.port}/manager/text</cargo.remote.uri>
<cargo.remote.username>${tomcat.username}</cargo.remote.username>
<cargo.remote.password>${tomcat.password}</cargo.remote.password>
</properties>
</configuration>
</configuration>
</plugin>
遇到的错误:
cargo-maven2-plugin:1.4.9:redeploy failed: Failed to undeploy
原因:
是antiResourceLocking属性引起的,参考如下:http://stackoverflow.com/questions/14873219/cannot-undeploy-a-web-app-completely-in-tomcat-7
修改context.xml文件<Context antiResourceLocking="true">
十三、Maven打包时通过命令向pom.xml中传多参数
如上图所说即可实现maven打包时传多个参数的需求