Final Target to this solutions
SCM:              Git/SVN/GitHub
Static Anlyst:       Sonar
Build:              Jenkins/Maven
Unit Test:       Junit
Deployment:       Jenkins/KVM(How to Rollback)
Accept Test:       Cucumber


Scenario1
------------------------
Step1:
jekins+maven+svn/gitHub+junit ->Windows

Step2:
Implementation based on rhel

Step3:
plugins

Step4:
Implementation based on ubuntu

以下参考均为网络文章,出处如下,蓝色字体为亲历亲为
http://blog.csdn.net/onlyqi

==========================================================

Jekins
----------------------------------------------------------------------------------------------------
Jenkins是一个CI工具。它可以持续编译,运行你的代码;运行UT或集成测试;将运行结果发送至邮件,或展示成报告。。。

这样做的最终目的是:

让项目保持健康的状态。如果任何checkin break了build,每个人都会在最短的时间内通知到,然后问题被fix。接下来的开发将建立在一个健康正确的基础上,而不是任由问题累积,最后失控。

最后,你的项目随时可以被deliver给用户,因为,你的项目每一天都在健康,茁壮的生长。这就是CI的意义所在。


Jenkin和cruisecontrol

Jenkins和cruisecontrol都是CI工具,二者在CI中发挥的作用完全一致。

而Jenkins作为新一代的CI工具,渐渐开始取代cruisecontrol。二者都是java程序,但:

1,Jenkins提供更为友好的用户界面,而cruisecontrol在界面方面糟糕的几乎等于没有。

2,Jenkins内置的功能提供了极大的便利,不论是新建一个build,还是日常使用,你需要做的大部分时候仅仅是在用户界面上点击而已。

在cruisecontrol新建build是通过创建config.xml来完成的。它仅仅提供非常有限的功能,很多时候你会发现,需要自己完成很多工作。

3,Jenkins作为一个欣欣向荣的开源项目,有大批的plugin。当你发现需要一个Jenkins本身并不提供的功能是,搜索一下plugin,总会有收获。非常多的流行工具如JBehave,cobertura都提供jenkins插件。

而针对cruisecontrol的plugin却很少。

4,Jenkins友好的用户界面让学习成本很少,你可以在最短的时间内开始你的工作。


事实上,Jenkins是我见过的最好的开源项目之一,它简洁实用的用户界面设计,完善的文档,丰富的插件。当你开始使用它,你就会爱上它。

当你需要一个build工具时,Jenkins几乎是当下的不二选择。


Jenkins和Hudson

Jenkins起源于Hudson。Hudson在商业软件的路上继续前行,而Jenkins则作为开源软件,从hudson分支出来。

因此现在的jenkins和hudson非常类似,但是随着二者各自的发展,已经有了一些不同。


要想更多的了解Jenkins,当然最好是访问它的官方网站。也可以参考我的下一篇文章:

Jenkins(二)   http://blog.csdn.net/onlyqi/article/details/7076915

至少和官网比起来,它是中文的~


官网:https://wiki.jenkins-ci.org/display/JENKINS/Meet+Jenkins

我的这篇文章仅仅是简单的根据上文,介绍Jenkins提供了哪些功能。具体大家还是要自己学习啦~


官网首页就提供了windows版本的Jenkins安装包。我们可以下载一个用于学习。安装后自动打开http://localhost:8080,你就能看见Jenkins的界面了。

其他也需要安装的是:

1,Jenkins是java程序,因此需要安装JDK。

2,同时运行job需要提供repository,也就是存放Jenkins定期poll源代码的地方。我们可以去github免费注册一个。

3,如果想在Jenkins中使用ant,maven等,则还需要单独安装。但不是必须的。


启动Jenkins

Jenkins天生支持unix-like system。

  • 直接运行

好吧,Jenkins是一个java程序,所以要运行它,只需要:

$ java -jar jenkins.war

我们也可以使用nohup命令,让Jenkins在后台运行。

之后打开URL http://myServer:8080 就可以方便的操作Jenkins了

官网给了一个sh的例子,用于启动Jenkins。可以参考一下。

  • 在Servlet container中运行

Alternatively, if you have a servlet container that supports Servlet 2.4/JSP 2.0, such as Glassfish v2, Tomcat 5 (or any later versions), then you can run them as services, and deployjenkins.war as you would any other war file.

For example,
you could simply place the jenkins.war file in Tomcat’s webapps directory.  此时使用的URL默认就变成:

http://localhost:8080/jenkins


同时Jenkins提供一些默认不会启动的特殊的功能,参考下面的link来enable它们。

https://wiki.jenkins-ci.org/display/JENKINS/Features+controlled+by+system+properties


Jenkins的目录结构

和CruiseControler一样,Jenkins需要一个目录来存储相关文件:JENKINS_HOME。默认为 ~/.jenkins。即为user的home目录下的一个隐藏目录。我们也可以更改JENKINS_HOME,指向我们希望的地方。

(注意因为是隐藏目录,所以需要使用ls -al 才能看到)

JENKINS_HOME
 +- config.xml     (jenkins root configuration)
 +- *.xml          (other site-wide configuration files)
 +- userContent    (files in this directory will be served under your http://server/userContent/)
 +- fingerprints   (stores fingerprint records)
 +- plugins        (stores plugins)
 +- jobs
     +- [JOBNAME]      (sub directory for each job)
         +- config.xml     (job configuration file)
         +- workspace      (working directory for the version control system)
         +- latest         (symbolic link to the last successful build)
         +- builds
             +- [BUILD_ID]     (for each build)
                 +- build.xml      (build result summary)
                 +- log            (log file)
                 +- changelog.xml  (change log)

如果有权限管理,则在HOME目录下还会有users目录。

从目录结构来看,和CruiseController非常相似。其中config.xml是Jenkins重要的配置文件。我们都知道Jenkins用于monitor多个build,而jobs这个目录无疑就是存储每个build相关信息的地方。

总的来说,Jenkins目录结构非常直白,简洁。


备份和恢复

备份和恢复非常简单,就是简单的copy Jenkins的目录就好了:

All the settings, build logs, artifact archives are stored under the JENKINS_HOME directory. Simply archive this directory to make a back up. Similarly, restoring the data is just replacing the contents of the JENKINS_HOME directory from a back up.


移动/拷贝/重命名 job

由于每个jobs都有自己单独的目录,我们可以很容易的:

    1,move a job from one installation of Jenkins to another by simply copying the corresponding job directory.
   ,2,make a copy of an existing job by making a clone of a job directory by a different name.
    3,rename an existing job by renaming a directory.

修改后执行下面的命令刷新:

http://[jenkins-server]/[command]

在这里[command]可以是:exit 退出,restart 重启, reload 重载。


创建一个Project

因为Jenkins可以用于运行各种CI,测试,批处理任务等等,所以在Jenkins中将这些任务统称为“free-style software project”.

Jenkins也提供了其他类型的jobs,例如:

1,如果项目是Maven,Jenkins还提供了一种仅用于Maven Project的job。但其实free-style software projec仍然可以用于创建Maven项目,只不过这种更适合Maven项目,结合的更好而已。

2,也可以创建一个"Monitor an external job“用于监控外部进程。

3,或者一个Matrix project,也就是multi-configuration project。

我不确定是否仅有这4种job,也许使用插件可以创建更多类型的job,大家自己看资料吧。


下面是如何创建一个最常见的“free-style software project"的过程:

Go to Jenkins top page, select "New Job", then choose "Build a free-style software project". This job type consists of the following elements:

  • optional SCM, such as CVS or Subversion where your source code resides. 指定源代码在哪。

Note: In software engineering, software configuration management (SCM) is the task of tracking and controlling changes in the software.

  • optional triggers to control when Jenkins will perform builds. 指定Jenkins何时触发一次build。
  • some sort of build script that performs the build (ant, maven, shell script, batch file, etc.) where the real work happens 触发build时,使用的脚本文件,例如ant。在这个脚本文件中,我们可以从svn下载最新代码,删除上次build的临时文件,创建必要目录,编译源 代码,运行,打包等一系列工作。
  • optional steps to collect information out of the build, such as archiving the artifacts and/or recording javadoc and test results. 收集log信息。
  • optional steps to notify other people/systems with the build result, such as sending e-mails, IMs, updating issue tracker, etc. 通知相关人员build的结果。

例如我们使用的build script就是ant,在Jenkins中运行ant。在脚本文件中,可以直接使用Jenkins提供的一些变量。

同时,每个job可以有多个step。例如:将运行程序定义为step1,运行单元测试定义为step2,生成coverage报告定义为step3。

同时还可以定义post-build action。例如:生成javadoc,或清理程序运行的临时文件目录等。


自动运行Build

触发一个build有三种方式:

  • Builds in Jenkins can be triggered periodically (on a schedule, specified in configuration) 这里定义schedule的语法是unix常见的cron语法。
  • Or when source changes in the project have been detected

可以设置Jenkins定时检查SVN是否发生了变化,也可以手动检查:http://YOURHOST /jenkins/job/PROJECTNAME/pollong。也可以设置Jenkins为post-commit,这个方式尤其适用于那些检查是 否代码改变会花费很长时间的情况。

  • Or they can be automatically triggered by requesting the URL:

http://YOURHOST/jenkins/job/PROJECTNAME/build


Distributed builds

Jenkins supports the "master/slave" mode, where the workload of building projects are delegated to multiple "slave" nodes, allowing single Jenkins installation to host a large number of projects, or provide different environments needed for builds/tests.

在现实中需要使用distributed builds情况很多,例如:一个web application的build,需要分别验证firefox和IE的行为,那么就需要到windows机器上运行IE。

或因为性能问题,将build分布到多个slave节点去。


到Jenkins的管理界面,就可以方便的添加节点。配置节点时,需要提供节点所在的机器,登陆用户名密码,使用的目录等。

但是slave并不需要再安装Jenkins。jenkins会自动启用slave agent,将build需要tools考到远程机器上。

需要注意的是:the build results and artifacts will always end up on the master server. 因此不需要跑到各个节点去查看build产生的文件,log等。

其实在slave节点,会创建一个本地的workspace,并在运行时使用这个workspace。因为毕竟build运行在slave节点上,所以这个节点肯定要有运行build需要的所有因素。

总之添加节点并远程运行build真是太方便了~


添加节点后,在master Jenkins home目录下会出现关于该节点的配置文件。

Jenkins将自动决定在哪个节点上运行build,根据下列策略:

Some slaves are faster, while others are slow. Some slaves are closer (network wise) to a master, others are far away. So doing a good build distribution is a challenge. Currently, Jenkins employs the following strategy:

  1. If a project is configured to stick to one computer, that's always honored.
  2. Jenkins tries to build a project on the same computer that it was previously built.
  3. Jenkins tries to move long builds to slaves, because the amount of network interaction between a master and a slave tends to be logarithmic to the duration of a build (IOW, even if project A takes twice as long to build as project B, it won't require double network transfer.) So this strategy reduces the network overhead.

Jenkins通过运行slave agents来完成分布式build。最常见的情况是:slave agent运行在各个slave 节点。master通过SSH远程启动/停止slave agent,进而控制各个节点的行为。

一共有下列4种方式启动slave agent:

•The master starts the slave agents via ssh
• Starting the slave agent manually using Java Web Start
• Installing the slave agent as a Window service
• Starting the slave agent directly from the command line on the slave machine from the command line

需要注意的是这4种方式适用于不同的情况,例如slave节点在防火墙后,导致master无法通过SSH启停slave agent。此时只能用后三种方式,但是往往有一些弊端,比如master无法自动停止/重启 slave agent.

一旦添加node成功,你就可以在job中指定这个job在哪个node运行:

Restrict where this project can be run (如果不指定则由Jenkins自行决定,即可以在slave节点运行,也可以在master节点运行,甚至在一次build中就可以自行来回切换)。


配置Jenkins,让它收集更多的log

https://wiki.jenkins-ci.org/display/JENKINS/Logging

我想这对于初学Jenkins的人,用来判断问题所在太有用了。


在流行持续集成的今天,我们在各个环境:alpha,beta和production 都部署了唯一的Jenkins服务器。

Jenkins服务器统一负责该环境内所有组件的持续集成。也就是说,一个Jenkins服务器会有很多个build。所以有时会用到上面提到的”Monitor an external job“。

但不是Distributed Builds。


同时由于Jenkins会进入每个环境,包括production,因此会使用auto deployment的方式,自动完成Jenkins在各个环境的部署。


用户管理

毫无疑问Jenkins中需要有用户管理的功能,因为除开发人员外,有多种角色的人需要查看build的结果。

在Jenkins中的系统管理中,可以设置“任何用户可以做任何事” 或 “登录用户可以做任何事”。

因此前一个选项意味着,任何浏览JenkinsURL的用户都可以修改Jenkins。或只有登录用户才能做修改。

所以我把Jenkins中的用户划分为两类:可登录用户和不可登录用户。

1,只要是修改过repository,即对build产生过影响的用户,都会被Jenkins记录在本地的database中。这类用户我们可以在Jenkins界面->查看用户中浏览。

但这类用户不是正式的Jenkins用户,也不能登录Jenkins。这类用户的权限由上面说的系统管理中的配置决定。通常只有查看build的权限,没有修改权限。

2,只有在Jenkins中明确注册的用户,才能够登录Jenkins,并且有权限控制。同时注册过的用户,在 JENKINS_HOME目录下的users目录下,都有一个单独的目录来存储相关信息。我不太清楚是否能够通过copy/paste将用户部署到其他地 方去,回头测试一下。


既然要满足各种人对jenkins使用的各种需求,因此权限管理远没有这么简单。具体大家还得自己去看啊~


Jenkins Script Console

Jenkins提供了一个script console Groovy script which allows to run arbitrary scripts on the Jenkins server or on slave nodes. This feature can be accessed from the "manage Jenkins" link。

也可以通过URL直接访问:http://myserver:8080/hudson/script

可惜只能用Groovy 反证我不懂。

在使用Jenkins的过程中,当然也会遇到一些问题。在这里我把我遇到的,比较奇怪的问题列出来,供大家参考。


环境变量

我在一个slave node上运行job时发现,被启动的程序显示找不到环境变量。

原来,当Jenkins在slave上启动一次build时,不会应用当前用户的profile。因此我们得自己解决这个问题。

解决方式有很多:

1,在创建slave node时,可以指定要传递的环境变量。这种方法不好的地方就是,相当于hard code,当实际的环境变量改变时,也需要手工修改slave node的配置。

2,想办法自己应用:运行shell前运行:. /usr/usr_account/.profile (注意第一个点后面有空格),这个是最好的方法,因为所有的环境变量都会生效,而不是仅仅某一个。

或者在调用的ant中,或ksh script中指定某个具体的环境变量。


进程被kill

需求是这样的:在Jenkins中一个job运行完毕时,可以配置它触发下一个job运行。这种情况很常见,例如一个 job中启动一个程序并运行了UT,当运行完毕时,我们可能会希望一个集成测试的job被触发。这里隐含的意思就是,我们希望程序能一直运行,直到所有的 测试结束,最后再显式的停止这个程序。

然而在实施的过程中,我遇到了一个大问题:在第一个job运行结束后,程序就被杀掉了。第二个job没有运行测试的时间。

来看看这个人遇到的类似的问题:

I am trying to run a shell script to stop/start the JBoss instance, but when the Hudson job completes, the JBoss instance shutdowns.  Does anybody have any recommendations on how we can spawn an instance of JBoss from a Hudson job without using the daemonize script?


由于现实中事情的复杂性(在Jenkins中调用了ant,ant调用了ksh,ksh最终启动了程序),我绕了很大一圈才怀疑到Jenkins上。在这之前,我尝试在ant中使用,在调用ksh时使用nohup,但是问题依旧。

而问题的根本在于是Jenkins使用processTreeKiller杀掉了所有子进程,而且这是Jenkins的 默认行为。其实回头来看这个问题,就发现Jenkins的做法非常合理。当一次build异常结束,或被人终止时,必然需要结束所有这次build启动的 子进程。下面的link提供了更多细节,以及解决方法。

https://wiki.jenkins-ci.org/display/JENKINS/ProcessTreeKiller


Jenkins home目录下的tools目录没有被同步到slave node

在Jenkins的home目录下,有两个自动生成的目录: tools and usercontent。

当我在使用slave node时,我注意到在每个slave node的上,Jenkins自动建了一个tools目录。因此我想当然的以为,tools目录是用来存放用户自己需要的第三方工具的。

例如,我在project中需要使用ant 1.8.2。而tools中则存放了ant 1.8.2,同时在建立slave node时,Jenkins自动将ant1.8.2拷贝到了slave node的tools下。

然而在之后的使用中,我发现在master node的tools中放置其他的第三方工具后,slave node的tools中并没有增加。因此slave node上的project并不能使用对应的第三方工具。

事实真相是,我应该使用usercontent目录,而不是直接使用tools目录。

当用户需要某个第三方工具时,正确的做法是将安装包放到usercontent目录。然后在Jenkins system management中要求安装这个工具。

userContent目录的说明:

You can use this directory to place your own custom content onto your Jenkins server. You can access files in this directory at http://myserver/hudson/userContent (if you are running
Jenkins on an application server) or http://myserver/userContent (if you are running in standalone mode).

之后Jenkins会自动将该工具安装到tools目录下,同时也会同步到slave node的tools下。像我这样直接扔在master node的tools下,是不会自动同步的。


还有一种解决方案:

Jenkins 并没有机制自动将master node上的tools目录下的内容同步到slave node上。这意味着如果在slave node上运行project需要某些特殊工具(或jar包),只能事先在slave node所在的box上安装好(或准备好)。

但是在某些极端条件下,slave node并没有准备好这些工具。

例如,我们使用Jenkins来自动deployment最新的release到production,而安装release意味着很多附加功能,例如环境检查,安装程序,自动启停程序,启动cluster等复杂操作。

我们使用Ant script来完成这些操作。但Ant在production环境没有安装。

因此我希望将ant相关的jar放到master jenkins根目录的tools目录,然后将tools同步到slave node的tools目录下,之后在slave node上运行Ant就可以使用这些jar包了。

但是目前我们只能通过使用一个工具rsync来将tools下的内容同步到slave node:

On master, I have a little shell script that uses rsync to synchronize master's/var/jenkins to slaves (except/var/jenkins/workspace) I use this to replicate tools on all slaves.


如何取得slave node上的jenkins home
我在脚本里,或Ant中使用环境变量JENKINS_HOME的时候发现一个问题: 尽管限制了job在slave node上运行,但是这个变量的值还是master node的 JENKINS_HOME。而不是在slave node的配置中配置的“Remote FS root”
一个解决方案是,在创建slave node时,在配置页面下方的node properties中添加一个环境变量:SLAVE_HOME=上面配置的“Remote FS root”目录。这样就可以在slave node上使用这个变量了。
 
You can also specify environment variables. These will be passed into your build jobs, and can be a good way to allow your build jobs to behave differently depending on where they are being executed.
比如在ant中,加入:
来获取所有的环境变量。
之后用就可以了。

这里顺便提一下,有一个plugin可以显示每次build时,jenkins自动生成的环境变量。在shell, ant中都可以方便的使用这些变量。



在所有的projects中传递参数
一个需求:有3个projects,run.program, run.ut, run.integration.test
它们使用在一个project完成后自动trigger另外一个的方式,形成了一个chain。同时第一个project是parameterized- project,即build时需要提供输入参数。其中一个输入参数是,boolean ifRunUT,是否运行UT。
现在,如果在第一个project中选择不运行UT,则skip后面的那个project,之后继续运行第三个project,也就是集成测试。

解决方法是安装这个plugin:https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Trigger+Plugin
同时将后面的run.ut改为parameterized-project,同时有唯一的一个输入参数ifRunUT。
上面的plugin可以将第一个project的输入参数传递到它触发的下一个project。这样当后面的run.ut发现ifRunUT=false时,就自动返回successful,之后该project继续触发之后的run.integration.test。
听上去有点无聊,但是试想一下,如果有两个关于ut的project:run.ut.1 run.ut.2。上面的方法就可以一次配置,skip掉两个projects,而不需要配置多次。
更重要的是,这种做法使得整个chain的配置都集中在一个地方,而不是分散在各个project中。每次build都需要去多个projects配置参数是很让人崩溃的。

------------------------------------------------------


jenkins邮件配置

分类: 系统配置  2013-03-22 14:50  4621人阅读  评论(1)  收藏  举报
jenkins自带的邮件管理太弱了,为了能按自定义的方式发送邮件,需要安装一个插件:  Jenkins Email Extension Plugin

1.配置邮件:通过“系统管理”-“系统设置”,进行系统设置界面,上面的内容在“使用Jenkins配置自动化构建”中已经讲过,直接移动到设置页面的最下面,“邮件通知”部分,设置上“stmp服务器“和”用户默认邮件后缀“,如图:

如果成功安装了 Jenkins Email Extension Plugin,在邮件通知的上面还有
到这里,系统级的邮件设置已经完成了。
2. 创建一个测试的自动构建项目,如svnTest
其他部分不说了,只说邮件部分,点”Add posts-build action“,选择”Editable Email Notification“,出现下面的界面:

这些内容都可以根据你的需要进行修改。
3. 完成之后,点”立即构建“看看是不是成功,如果成功了,就大功告成了。如果不成功,那就慢慢的调了^_^。
有一个地方要注意:如果配置的邮件服务器是stmp.126.com,好像就只能发送邮件到126邮箱,这个我配置的是这样,不知道是不是全部是这样。

--------------------------------------------

[原创] Jenkins 邮件配置 (使用 Jenkins Email Extension Plugin)

本文主要对 jenkins 的邮件通知进行介绍,

  • jenkins 内置的邮件功能
  • 使用插件扩展的邮件功能

1. 先介绍下 基本的Jenkins 邮件服务器 配置

   1)system config 页面 (以公用的163邮件服务器为例):

 

   

可以勾选 “通过发送测试邮件配置”  测试此配置能否连通, 如果收到以下邮件,恭喜

   

This is test email #1 sent from Jenkins

 

   2)下面接着对构建的job 添加邮件发送的步骤,

 这样每次build后都会发送邮件给这个接收者, 到这里你会发现,只能发给 固定的对象,且格式单一(txt)

 

 ====好了,现在进入主题====

 

2.  使用插件 “Email Extersion Plugin”进行扩展

 它可根据构建的结果,发送构建报告,给当前的committer (用git做代码管理)

   1) 该插件支持jenkins 1.5以上的版本,至少我的 1.486是不支持的啦。所以果断升级吧。。

    插件的安装此处略 ,若您可选插件的页卡的列表是空的,先去高级页面检查更新下。

   2)插件用于job配置页面,添加构建后步骤“Editable Email Notification”

 

   上面的配置 给出了 该工程的默认接收列表,当然抄送的话 直接 可以这么写 cc:xxxx@163.com

   对于内容,你也许注意到了 这里调用了个 ‘html.jelly’ 的模板,这是插件内置的,直接用即可。(支持git每次变更的记录,mvn 及junit 等编译的结果报告)

   当然也可以自己写 jelly文件, 确保放置 jenkins/home/email-template下 以供jenkins调用。  

 

    3)至此你也许会问 这不还是用的固定的接收列表嘛 (⊙_⊙) ,别着急 看到右下角的高级选项没, 继续配置,

 

    

 

     我设置了 build成功和失败都发给 默认的接收者和当前提交代码的家伙,而send to requester 是指手动触发构建时当前登陆jenkins的用户。

 

ps:

         1. 如果有人 git commit时候没有进行global的name和email设置,将不会发送到正确的邮箱(jenkins将按各自的机器名作为域名地址发送到错误的邮箱)

 

         2. 当然还可在jenkins 管理用户中 个别设置 邮箱。不过对于团队较多的话,你就苦了。 所以还是有必要请大家提交前进行实名设置。

http://www.cnblogs.com/GGHHLL/p/jenkins.html

------------------------------------------------


http://blog.csdn.net/yanmingming1989/article/details/8557716

Linux 环境下搭建 Jenkins(Hudson)平台

分类: CI  2013-01-30 21:38

安装jenkins:
安装 jenkins 有两种方式:
安装方式一: 
[java]  view plain copy
  1. sudo java -jar jenkins.war –httpPort=18080 –ajp13Port=18009  
但 是很多时候我们是使用SSH方式到目标机器上的,放我们关闭SSH连接时,这个命令也会被中断,jenkins服务会被终止,我们不可能一直保持这SSH 连接,怎么办?可以把这行命令写成 shell 脚本,然后使用 nohup sh jenkins.sh &
命令启动这个脚本,这样jenkins就能正常提供服务了。
安装方式二:安装 RPM包
为了能够使用jenkins库,首先需要导入jenkins库的 key:
[java]  view plain copy
  1. sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo sudo rpm –import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key  
安装软件(以jenkins-x.x.x.rpm为例):yum install jenkins-x.x.x.rpm
     删除软件:yum remove jenkins-x.x.x.rpm或者yum erase jenkins-x.x.x.rpm
     升级软件:yum upgrade jenkins或者yum update jenkins
     查询信息:yum info jenkins
开启服务(关闭,重启):  
[java]  view plain copy
  1. sudo service jenkins start|stop|restart  
检查jenkins是否安装完成: localhost:8080 (默认是8080 端口,如果采用安装方式一,那么就需要指定的端口)
运行job时遇到的问题:
  mvn:command not found
遇到的问题: 不能使用MVN命令;
排查过程:
①Jenkins 默认创建进程,启动任务的用户名是 jenkins,使用root权限查看passwd,可以看到这个用户默认情况下 ssh 为false,也就是说这个用户默认情况下是不能使用ssh进行登录的,除非修改 passwd中相应字段为 bash,然后sourse;
jenkins:x:500:500:mengqc:/home/jenkins:/bin/fasle
passwd文件的格式:   注册名:口令:用户标识号:组标识号:用户名:用户主目录:命令解释程序
②默认情况下 Jenkins 的安装目录是 /var/lib/jenkins/ ,项目根目录是 /var/lib/jenkins/jobs/workspace

从目录上看,就知道这个是需要 root 权限才能执行一些命令,但是我们通过界面 执行一些命令使用的是admin用户,纵使我们在 根目录下 能适应mvn命令,但是问题也不能解决。

还有一个简单的测试Maven 是否加入到了环境变量中的方法,在执行mvn命令时,填写maven安装的绝对路径,如果能够执行,说明不是权限的问题,而是环境变量的问题。


解决方案一:
①安装 ssh slave 插件;
②启动slave 服务;
③jenkins-系统管理-节点管理:重新设置 slave机器的 Remote FS root 为 /home/admin/xxx
(主要是添加了workspace的目录) $ITEM_ROOTDIR
④把master的节点数设为0,这样默认情况下就会使用 slave节点。
问题:
如果修改 工作目录(Remote FS root),可能会遇到:
[java]  view plain copy
  1. “main”java.lang.NoclassDefFoundError:hudson/maven/agent/Main  
原因:我们修改了slave的工作目录,但是slave服务没有重启导致;
解决方法:使用我们的脚本 对slave进行 重启操作。
解决方案二:
在 /home/admin/目录下新建一个工作目录,然后将 /var/lib/jenkins目录设置成一个跳转链接 ,链接到admin目录下 [sudo ln -s /home/admin/xxx/   /var/lib/jenkins] ,然后将/var/lib/jenkins 目录下的文件 mv 到/home/admin/xxx/ 目录下。
mvn和一些基本的命令是可以运行了,但是运行shell脚本时还是没有权限,因为 新建的这个跳转连接user=root ,group=root,并且对这个链接 使用chown/chgrp 都是没有效果的,执行一些操作命令是还是没有权限;

解决方案三:修改默认 jenkins 用户为 admin
①安装jenkins 
Java代码   (我们一般使用的是admin权限)
[java]  view plain copy
  1. sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo    
  2. sudo rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key    
  3. sudo yum install jenkins    
  4. rpm -ql jenkins    


②. 配置jenkins 
Java代码  
// edit JENKINS_PORT, JENKINS_USER  
sudo vi /etc/sysconfig/jenkins   (把 JENKINS_USER 设置为 admin)
③. 修改jenkins权限(如果修改JENKINS_USER情况下) 
Java代码  
[java]  view plain copy
  1. ####  
  2. sudo chown -R admin /usr/lib/jenkins    
  3. sudo chgrp -R admin /usr/lib/jenkins   
  4. ####  
  5. sudo chown -R admin /var/log/jenkins   
  6. sudo chgrp -R admin /var/log/jenkins    
  7. sudo chown -R admin /var/lib/jenkins    
  8. sudo chgrp -R admin /var/lib/jenkins    
  9. sudo chown -R admin /var/cache/jenkins   
  10. sudo chgrp -R admin /var/cache/jenkins (这个如果不改,会出现404)  

④. 启动jenkins 
Java代码  
sudo /sbin/service jenkins start 
或者   sudo service jenkins start

 -------------------------------------------------------------

http://www.51testing.com/html/87/300987-815659.html
Linux安装Jenkins手册

一、前期准备工作

因为我是在Windows系统上连接Linux服务器以及需要把在Windows系统下载的安装包上传到Linux系统,所以需要用到两个工具---puttyFileZilla

Putty是一个免费的、Windows 32平台下的telnetrloginssh客户端,但是功能丝毫不逊色于商业的telnet类工具。 用它来远程管理Linux十分好用。

FileZilla是一种快速、可信赖的FTP客户端以及服务器端开放源代码程式,具有多种特色、直觉的接口。

这两款工具都是免安装的,使用非常方便。

 

二、卸载和安装LINUX上的JDK

2.1卸载linux上自带的jdk

root用户登陆到系统,打开一个终端输入
# rpm -qa|grep gcj
显示内容其中包含下面两行信息
# java-1.4.2-gcj-compat-1.4.2.0-27jpp
# java-1.4.2-gcj-compat-devel-l.4.2.0-27jpp
卸载
# rpm -e java-1.4.2-gcj-compat-devel-l.4.2.0-27jpp
# rpm -e java-1.4.2-gcj-compat-l.4.2.0-27jpp

卸载其他自己安装的JDK就直接用rpm -e
  
卸载rpm版的jdk

   #rpm -qa|grep jdk

  显示:jdk-1.6.0_10-fcs
  
卸载:#rpm -e  --nodeps  jdk-1.6.0_10-fcs

 

2.2安装JDK

http://www.oracle.com/technetwork/java/javase/downloads/jdk-6u32-downloads-1594644.html1.6.0举例,下载一个Linux PlatformJDK,建议下载RPM格式的(我下载的是 Linux x86 (32-bit)的名称为jdk-6u32-linux-i586-rpm.binjdk

 

2.2   把刚才第一步下载的bin文件上传到Linux服务器上,在shell下执行命令:

注:我的jdk安装包放在home目录下

[root@testdep home]# chmod 755 jdk-6u32-linux-i586-rpm.bin
[root@testdep home]# ./ jdk-6u32-linux-i586-rpm.bin

 

 这时会有一段Sun的协议如下

准备中… ######################################## [100%]

 1:jdk ######################################## [100%]

Unpacking JAR files...

       rt.jar...

       jsse.jar...

       charsets.jar...

       tools.jar...

       localedata.jar...

       plugin.jar...

       javaws.jar...

       deploy.jar...

 

Java(TM) SE Development Kit 6 successfully installed.

 

Product Registration is FREE and includes many benefits:

* Notification of new versions, patches, and updates

* Special offers on Oracle products, services and training

* Access to early releases and documentation

 

Product and system data will be collected. If your configuration

supports a browser, the JDK Product Registration form. will

be presented. If you do not register, none of this information

will be saved. You may also register your JDK later by

opening the register.html file (located in the JDK installation

directory) in a browser.

 

For more information on what data Registration collects and

how it is managed and used, see:

http://java.sun.com/javase/registration/JDKRegistrationPrivacy.html

 

Press Enter to continue.....

 

 

Done.

2.3安装jdk主程序包

程序会自动生成一个jdk-6u32-linux-i586.rpm文件,这是主程序包,下面来安装;

[root@testdep home]#rpm –ivh jdk-6u32-linux-i586.rpm

 

2.4设置环境变量

     通常都喜欢用export命令直接在shell下设置

[root@ testdep home]# export JAVA_HOME=/usr/java/jdk1.6.0_32
[root@ testdep home]# export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
[root@ testdep home]# export PATH=$PATH:$JAVA_HOME/bin
当然这样设置环境变量是可以生效的,但是只对当前shell生效。如果从另外一个shell登陆,将不能使用刚才设置的变量。所以最好的方法还是修改.bashrc文件。
我用下面这个
cd ~     .bashrc
是在根目录下
[root@testdep ~]#vi .bashrc
export JAVA_HOME=/usr/java/
jdk1.6.0_32(这里的jdk的版本号可以通过cd /usr/java查看)
export JAVA_HOME
export PATH=$PATH:$JAVA_HOME/bin
export PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export CLASSPATH

 

注:保存成功后需要通过. .bashrc使此脚本生效。

 

当然也可以通过更改/etc/profile来实现,不过不推荐这么做,因为这样的设置将对所有用户的shell都生效,对系统安全会产生影响。下面来验证一下变量设置是否生效(在验证前先logout一下,再重新登陆);
[root@testdep home]# echo $JAVA_HOME
/usr/java/jdk1.6.0_32/
[root@testdep home]# echo $CLASSPATH
/usr/java/jdk1.6.0_32/lib/dt.jar:/usr/java/jdk1.6.0_32/lib/tools.jar
[root@testdep home]# echo $PATH
/usr/java/jdk1.6.0_32/bin/:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
[root@testdep home]# JAVA-version
JAVA version "jdk1.6.0_32"
JAVA(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_06-b03)
JAVA HotSpot(TM) Client VM (build 1.4.2_06-b03, mixed mode)

 

2.5测试环境变量是否安装成功

环境设置OK,看看JDK是否能正常工作,我们来写一个测试文件test.java

[root@LinuxServer rpm]#vi test.java
class test
{
       public static void main(String[] args)
       {
              System.out.println("Hello World!");
       }
}


保存退出,下面来编译、执行;

[root@testdep home]# javac test.java
[root@testdep home]# java test
Hello World!

OK,工作正常。

 

2.6  如果要使某个用户具有运行java命令的权限,只要修改其bash初始化文件即可。
比如要给用户longware以运行java命令的权限,
[root@LinuxServer root]# vi /home/longware/.bashrc
export JAVA_HOME=/usr/java/jdk1.6.0_32
export JAVA_HOME
export PATH=$PATH:$JAVA_HOME/bin
export PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export CLASSPATH


2.7   
至此,LinuxJDK的安装完毕。


三、在Linux下配置Tomcat服务器

  Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由ApacheSun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的ServletJsp规范总能在Tomcat中得到体现。

  Tomcat是稳固的独立的Web服务器与Servlet Container,不过,其Web服务器的功能则不如许多更健全的Web服务器完整,如Apache Web服务器(举例来说,Tomcat没有大量的选择性模块)。不过,Tomcat是自由的开源软件,而且有许多高手致力于其发展。

3.1安装jdk

在安装Tomcat之前需要安装j2sdk(Java 2 Software Development Kit),也就是JDK

请参考第一部分卸载和安装LINUX上的JDK

 

3.2下载tomcat

http://tomcat.apache.org/download-60.cgi 下载tomcat6.0,

[转载]Jenkins <wbr>Solutions我来了   请选择上图红色所示的tomcat版本。

 

3.3解压tomcat安装包

解压缩刚才的tomcat安装包(apache-tomcat-6.0.35.tar.gz)

注:我把tomcat安装包暂时通过FileZilla上传到了home目录下。

[root@testdep home]#tar –zxvf apache-tomcat-6.0.35.tar.gz

 

3.4为压缩包指定目录

把解压缩的文件放在一个新建的目录下

[root@testdep home]#cp -R apache-tomcat-6.0.35 /usr/local/tomcat ;

//拷贝apache-tomcat-6.0.35/usr/local/下并重命名为tomcat

 

3.5设置tomcat的路径

[root@testdep home]cd ~

[root@testdep home]vi .bashrc

//在第一步卸载和安装Linux JDK设置jdk的路径后面加上tomcat的路径

//vi编辑器的使用方法请大家百度一下

 export TOMCAT_HOME=/usr/local/tomcat

 

注:修改过.bashrc文件后需要通过一下命令使.bashrc生效。

[root@testdep home]. .bashrc

安装完后,重新启动tomcat以使JAVA_HOMETOMCAT_HOME的设置生效.

 

3.6启动tomcat
运行命令:

[root@testdep home]#/usr/local/tomcat/bin/startup.sh;

//正常情况下可以见到如下的信息:

 Using CATALINA_BASE: /usr/local/tomcat

  Using CATALINA_HOME: /usr/local/tomcat

  Using CATALINA_TEMDIR: /usr/local/tomcat/temp

Using JAVA_HOME: /usr/java/jdk1.6.0_35

3.7关闭tomcat

运行命令:

[root@testdep home]#/usr/local/tomcat/bin/shutdown.sh;

 

四、在Tomcat里边配置Jenkins

4.1  http://mirrors.jenkins-ci.org/war/1.466/下载Jenkinswar包。

4.2  通过FileZilla把刚下载的Jenkins包从本机PC上传到Linux服务器的webapps目录下。

[root@testdep home]cd /usr/local/tomcat/webapps

[转载]Jenkins <wbr>Solutions我来了

可看出刚刚上传的jenkins war包。

 

4.3 Jenkins安装完成,可以通过本地PC连接上Linux上的Tomcat服务器。

    在本地PC的浏览器窗口输入: http://192.168.3.182:8080/jenkins/

 

4.4      至此Jenkins的配置安装完成。

五、Jankins的相关配置

5.1      首次进入Jenkins的主页面会出现如下截图所示的错误提示:

[转载]Jenkins <wbr>Solutions我来了

意思是tomcat容器没有使用UTF-8编码,所以不能使用中文作名称,可以在tomcat行配置。

[root@testdep home]# cd /usr/local/tomcat/conf

[root@testdep home]#vi server.xml

……

 

connectionTimeout="20000"

redirectPort="8443"URIEncoding="UTF-8"/>

……

注:增加了utf-8的编码格式URIEncoding="UTF-8"

 

5.2情况下,JENKINS_HOME会在当前用的家目下建立,名称.jenkins

linux下:~/.jenkins

----------------------------------------------

持续集成Jenkins API常见用法

您的评价:          收藏该经验    
jenkins(持续集成开源工具)提供了丰富的api接口,基本上所有的操作都可以使用curl来从后台调度,包括:创建项目,禁用项目,启用项目,获取项目描述,获取配置文件,普通触发,scm触发,带参数触发,带补丁触发。

【背景】:部门在搞持续集成,使用jenkins作为核心调度,要再其基础上进行二次封装,所以需要研究下jenkins的api。笔者主要负责搭建平台,在研究用法也花费了些时间,本文主要做个简要的记录,希望能为各位朋友节省时间。

【环境】:(默认读者已经具备了基本的持续集成经验和jenkins用法

1. Jenkins1.455 

2. 系统Suse

3. Tomcat 6.0.37

4. Java 1.6.0_26

5. patch-parameter 

【API介绍】

 Jenkins提供了html、json、python API,实质都是以http get/post方式调用的。查看http://www.xxx.xxx/jenkins/api/ 即可得到相应的说明,如图:

持续集成Jenkins API常见用法 

【API实践】

1.创建

curl -X POST http://www.xxx.xxx/jenkins/createItem?name=JavaStd  --user peterguo:peterguo --data-binary "@javastd.config.xml" -H "Content-Type: text/xml"

2.禁用 

curl -X POST http://www.xxx.xxx/jenkins/job/JavaStd/disable  --user peterguo:peterguo

3.启用 

curl -X POST http://www.xxx.xxx/jenkins/job/JavaStd/enable --user peterguo:peterguo

4.删除 

curl -X POST http://www.xxx.xxx/jenkins/job/JavaStd/doDelete --user peterguo:peterguo

5.获取项目描述 

curl -X GET http://www.xxx.xxx/jenkins/job/JavaStd/description --user peterguo:peterguo

6.获取配置文件 

curl -X GET http://www.xxx.xxx/jenkins/job/JavaStd/config.xml --user peterguo:peterguo

7.触发SCM检查 

curl -X GET http://www.xxx.xxx/jenkins/job/JavaStd/polling --user peterguo:peterguo

8.普通触发 

curl -X GET http://www.xxx.xxx/jenkins/job/JavaStd/build --user peterguo:peterguo

9.带参数触发

curl -X GET "http://www.xxx.xxx/jenkins/job/helloworld-freestyle/buildWithParameters?bAllTest=&Choices=2&strParam=abc" --user peterguo:peterguo

10.带参数和补丁触发  

curl -X POST "http://www.xxx.xxx/jenkins/job/helloworld-freestyle/buildWithParameters?bAllTest=&Choices=2&strParam=abc" --user peterguo:peterguo -F "action=upload" -F "patch.diff=@OtherTest.java.patch"

注:带补丁触发需要先安装补丁插件,并设置项目的补丁参数

持续集成Jenkins API常见用法

【Python调用】

 提供python使用pycurl调用的例子片段,实际和curl调用一样,优点是易整合。

import pycurl url "http://10.129.145.112:8081/jenkins/job/helloworld-freestyle/config.xml" crl pycurl.Curl() crl.setopt(pycurl.VERBOSE,1) crl.setopt(pycurl.FOLLOWLOCATION, 1) crl.setopt(pycurl.MAXREDIRS, 5) crl.setopt(pycurl.USERPWD, "peterguo:peterguo")  crl.setopt(pycurl.CONNECTTIMEOUT, 60) crl.setopt(pycurl.TIMEOUT, 300) crl.setopt(pycurl.HTTPPROXYTUNNEL,1) crl.fp StringIO.StringIO() crl.setopt(pycurl.URL, url) crl.setopt(crl.WRITEFUNCTION, crl.fp.write) crl.perform() ret crl.fp.getvalue()

 

来自:http://my.oschina.net/sanpeterguo/blog/197931



----------------------------------------

config.xml of Jenkins


Jenkins 有两类config.xml:

在Jenkins home之下的config.xml是Jenkins server的配置文件。

另外在每个job或project自己的目录下,还有一个config.xml。它包含了是这个job的配置信息。


The Jenkins home directory contains all the details of your Jenkins server configuration, details that you configure in the Manage Jenkins screen.


A user appearing in this list cannot necessarily log on to Jenkins.

SCM user

(People who make changes to code in a source code repository that Jenkins is monitoring)

It is a good idea for developers to use their SCM username here: in
this case, Jenkins will be able to work out what users contributed to the SCM changes
that triggered a particular build.



Post-build Actions 对应了 config.xml中的

builder 就对应build

Source Code Management 

 Trigger


portfolio controller builder-maven , publishers:ant merge.results

portfolio package:builder-ant  target:portfolio.packaging。 publishers没有。


每个job下面都有一个workspace,里面有hudson_migration需要的所有ant脚本。

同时 workspace/trunk下 对于一个项目有两个文件:

portfolio

portfolio_pom.xml


https://sami.cdt.int.thomsonreuters.com/svn/searchandnavigation_searchandnavigation/Development/CP1.5/trunk/SourceCode/Controller/portfolio


Indeed, Continuous Delivery can be viewed as Continuous Deployment
with the final step (deployment into production) being a manual one dictated by
the business rather than the development team.

Maven
----------------------------------------------------------------------------------------------------

当我们在IDE中开发时,经常需要使用maven。现在流行的java的IDE有eclipse,intellij等等。对于maven而言,我们可以将IDE分为两类:

1,Eclipse等和maven结合的不够紧密的IDE。

Eclipse和Maven结合的并不算好,如果在eclipse中想使用maven,需要安装插件:m2e

安装该插件之后,你才能在eclipse中看到关于maven的菜单,并且可以创建maven项目,执行maven goal等。


为了在命令行中使用maven,我们往往会在本地再单独安装一个maven。这样就会有一个问题:eclipse中运行maven goal时,即可以选择使用embedded maven,也可以选择单独安装的maven。如下:


为了在命令行中使用maven的效果和在eclipse中执行maven goal的效果一致,建议在eclipse中选择单独安装的maven而不是内嵌的maven。


2,Intellij,Netbeans等较为紧密的IDE。

在intellij这类IDE中,不需要单独安装maven插件了。我们还是需要自己安装maven,同时也可以配置所使用的maven(默认是按环境变量M2_HOME):


  • 在导入一个maven项目时,往往需要下载很多本地repository中没有的dependency。如果出现连不上互联网的repository时,我们可以:

1,打开maven settings.xml,配置代理。或让maven去指定的repository下载。注意maven有默认的settings.xml在maven home的conf目录下。

user settings.xml默认是没有的,但是可以创建且其将覆盖默认的settings.xml

2,修改完后,在命令行运行mnv package重新开始下载。我在intellij中遇到过maven无法下载所有的dependency,但在命令行中执行则可以的情况。可能和IDE和maven的集成有关系。

在IDE中安装了maven插件之后,就可以直接运行maven package来打包了。

如果没有在IDE中安装插件而是单独安装了maven程序,则可以在命令行中直接执行mvn package来打包。

二者没有本质区别,本文以在IDE中直接为例。


要将项目打包,有两种选择:生成一个jar包;或一个包含jar包,配置文件,脚本文件等等的一个zip文件(assembly)。

如果没有在pom中显示的指定,则会使用默认的插件(通过查看effective pom可以看到)并按默认方式打包。


我们常用maven-jar-plugin来生成jar包。如果希望生成assembly,则除了maven-jar-plugin外,再使用插件maven-assembly-plugin来生成zip包。

[html]  view plain copy
  1. <</span>plugin>  
  2.                 <</span>artifactId>maven-jar-plugin</</span>artifactId>  
  3.                 <</span>version>2.3.1</</span>version>  
  4.                 <</span>executions>  
  5.                     <</span>execution>  
  6.                         <</span>id>default-jar</</span>id>  
  7.                         <</span>phase>package</</span>phase>  
  8.                         <</span>goals>  
  9.                             <</span>goal>jar</</span>goal>  
  10.                         </</span>goals>  
  11.                         <</span>configuration>  
  12.                             <</span>archive>  
  13.                                 <</span>manifest>  
  14.                                     <</span>addClasspath>true</</span>addClasspath>  
  15.                                     <</span>mainClass>com.thomsonreuters.PALFullExtractor.ExtractorMain</</span>mainClass>  
  16.                                 </</span>manifest>  
  17.                             </</span>archive>  
  18.                         </</span>configuration>  
  19.                     </</span>execution>  
  20.                 </</span>executions>  
  21.             </</span>plugin>  
在上例中,指定mainClass将在manifest文件中加入mainclass,这样jar就可以直接运行了。
[html]  view plain copy
  1. <</span>plugin>  
  2.                 <</span>artifactId>maven-assembly-plugin</</span>artifactId>  
  3.                 <</span>version>2.2</</span>version>  
  4.                 <</span>executions>  
  5.                     <</span>execution>  
  6.                         <</span>id>make-assembly</</span>id>  
  7.                         <</span>phase>package</</span>phase>  
  8.                         <</span>goals>  
  9.                             <</span>goal>single</</span>goal>  
  10.                         </</span>goals>  
  11.                         <</span>configuration>  
  12.                             <</span>archive>  
  13.                                 <</span>manifest>  
  14.                                     <</span>mainClass>com.thomsonreuters.PALFullExtractor.ExtractorMain</</span>mainClass>  
  15.                                 </</span>manifest>  
  16.                             </</span>archive>  
  17.                             <</span>descriptorRefs>  
  18.                                 <</span>descriptorRef>jar-with-dependencies</</span>descriptorRef>  
  19.                             </</span>descriptorRefs>  
  20.                             <</span>descriptors>  
  21.                                 <</span>descriptor>D:projectnamesrcmainassembly/assembly.xml</</span>descriptor>  
  22.                             </</span>descriptors>  
  23.                         </</span>configuration>  
  24.                     </</span>execution>  
  25.                 </</span>executions>  
  26.             </</span>plugin>  

注意其中2点:

1,descriptorRef -- jar-with-dependencies 就是将程序依赖的所有第三方类库都打入jar包,这样就不需要在运行时指定class-path了。

2,descriptor -- 指定assembly文件所在的位置。我们还需要创建一个assembly.xml来详细说明package的目录结构和内容。

assembly.xml文件的示例:

[html]  view plain copy
  1. <</span>assembly>  
  2.     <</span>id>package</</span>id>  
  3.     <</span>formats>  
  4.         <</span>format>zip</</span>format>  
  5.     </</span>formats>  
  6.     <</span>includeBaseDirectory>false</</span>includeBaseDirectory>  
  7.     <</span>fileSets>  
  8.         <</span>fileSet>  
  9.             <</span>directory>src/main/resources/config</</span>directory>  
  10.             <</span>outputDirectory>config</</span>outputDirectory>   
  11.   
  12.             <</span>includes>  
  13.                 <</span>include>*.xsd</</span>include>  
  14.                 <</span>include>*.dtd</</span>include>  
  15.                 <</span>include>*.xml</</span>include>  
  16.                 <</span>include>*.properties</</span>include>  
  17.                 <</span>include>*.key</</span>include>  
  18.             </</span>includes>  
  19.             <</span>lineEnding>lf</</span>lineEnding>  
  20.         </</span>fileSet>  
  21.         <</span>fileSet>  
  22.             <</span>directory>src/main/resources/script</</span>directory>  
  23.             <</span>outputDirectory></</span>outputDirectory>  
  24.   
  25.   
  26.   
  27.             <</span>includes>   
  28.                 <</span>include>*.ksh</</span>include>   
  29.                 <</span>include>*.cmd</</span>include>   
  30.             </</span>includes>   
  31.             <</span>lineEnding>lf</</span>lineEnding>   
  32.         </</span>fileSet>   
  33.     </</span>fileSets>  
  34.     <</span>dependencySets>   
  35.         <</span>dependencySet>  
  36.             <</span>outputDirectory>lib</</span>outputDirectory>  
  37.         </</span>dependencySet>   
  38.     </</span>dependencySets>  
  39. </</span>assembly>  

这样打好的package名叫例如:project-1_0.zip中解压后就会得到脚本文件以及另外两个目录config(包含配置文件),和lib目录(包含所有依赖的第三方类库和projectName.jar)

我们还可以在assembly按需要构建更复杂的package结构。

从maven-jar-plugin和maven-assembly-plugin的pom文件可以看到它们都指定了:package

这会导致运行mvn package命令时运行这两个插件。

直接搜索这两个插件的名字可以找到maven官网中队插件更详细的介绍。

Maven中的几个重要概念(三):POM

http://maven.apache.org/guides/introduction/introduction-to-the-pom.html

本文基本上是翻译+一点点理解。


  • 什么是POM

POM(Project Object Model) 是Maven的基础。它是一个XML文件,包含了Maven用来build项目所需要的项目配置的信息。

(译者:在使用ant进行build时,我们需要通过script告诉ant每一步要做什么,同时提供每一步需要的信息。

例如,首先要编译,编译的源代码在哪里,目标代码放哪里等等。

在Maven中我们不需要告诉Maven应该做些什么,仅需要在pom中提供一些必要的信息即可。对于那些在pom中没有提到的信息,Maven就会使用默认值。

例如Maven默认源代码在src/main/java中。因此Maven在最大程度上简化了项目build的过程。)

它包含了可用于大部分项目的默认值。例如,build directory默认使用定义;source directory,默认使用了src/main/java;test source directory默认使用了src/main/test等等。

在Maven1中(Maven的早期版本)POM的名字是project.xml,而在Maven 2中改为pom.xml。

(译者:通常认为Maven从1到2发生了根本性的改变,因此尽管可能你使用的Maven是3.x的版本,仍然会发现很多以m2命名的目录。)

同时,以前在maven.xml中包含的goal,plugin等信息现在也被放到了pom.xml中。当执行一个task或goal时,Maven搜索当前目录下的pom文件,从其中取出需要的配置信息并执行goal。

(译者:plugin和goal的概念非常重要,请参考我的另外一篇介绍Maven中的lifecycle的文章。)

另外一些需要在POM中配置的信息是project dependencies,也就是那些需要被执行的plugin或goal,build profile等等。其他项目相关信息,包括项目版本,项目描述,开发人员列表,邮件列表等等也可以在POM中。

  • Super POM
Super POM是Maven的默认POM。所有的POM都继承了super POM。也就是说,所有的POM中的信息都来自于Super POM,但在子POM中的配置信息会覆盖Super POM中的重复项。

(译者:文中分别写出了Maven2.0.x和2.1.x的super POM的具体内容。这里请参考原文)


  • 最简单的pom.xml

一个最简单的POM文件需要包括的内容如下:

(译者:也就是说,如果想建立一个简单的Maven项目,提供一个如此简单的POM就够了。Maven会自动完成剩下的事情)

  • project root
  • modelVersion - should be set to 4.0.0
  • groupId - the id of the project's group.
  • artifactId - the id of the artifact (project)
  • version - the version of the artifact under the specified group
具体的例子:


  4.0.0
  com.mycompany.app
  my-app
  1

一个POM必须配置项目的groupId, artifactId, 和version。这三个值构成了项目的fully qualified artifact name。那就是::。对于上面的例子,fully qualified artifact name就是“com.mycompany.app:my-app:1”

同时,正如在第一节提到的,如果一些配置信息没有被提供,Maven将会使用默认值。这些默认值之一是packaging type。如果POM中没有配置它,将会使用默认值jar。

此外,如同你在最简单的POM中看到的,这个POM并没有配置所使用的repositories

(译者:repository是Maven中的另外一个重要概念,不清楚的同学请参考我的另外一篇关于Maven中repository的文章。)

如果你使用这个POM来build你的项目,它将从Super POM继承repository的配置。因此,当Maven发现需要下载POM中的dependency时,它会到Super POM中配置的默认repository,http://repo1.maven.org/maven2去下载。


  • Project Inheritance 项目继承

(译者:project inheritance 和下面要提到的project aggregation 是理解项目间POM父子关系的关键,必须理解。)

另外一些可包含在POM中的信息是:

  • dependencies
  • developers and contributors
  • plugin lists (including reports)
  • plugin executions with matching ids
  • plugin configuration
  • resources

其实Super POM就是项目继承的的一个例子。然而你同样可以通过在POM中加入,来引入其他的父POM。

示例一:

在前面的例子中我们已经引入了“com.mycompany.app:my-app:1”这个项目,现在我们再引入另一个项目“com.mycompany.app:my-module:1”并以此为例,讲述如何让my-app成为my-module的父项目。


  4.0.0
  com.mycompany.app
  my-module
  1

同时让它们的目录结构如下:

.
 |-- my-module
   `-- pom.xml
 `-- pom.xml

my-module/pom.xml 指的是my-module这个项目的POM,而pom.xml指my-app的POM。

现在,我们把my-module的POM修改成下面:


 
    com.mycompany.app
    my-app
    1
 

  4.0.0
  com.mycompany.app
  my-module
  1

注意现在我们加了一个配置,parent。这个配置允许我们设置哪个项目(artifact)是当前项目的父项目。我们 需要设置父POM的fully qualified artifact name。配置好之后,my-module的POM就可以从my-app的POM中继承一些配置信息了。

另外,如果我们希望my-module的groupId和/或version与父项目保持一致,我们甚至可以删除my-module的POM中的groupId和/或version。


示例二:


然而上例是有局限性的。只有当父项目已经安装到local repository中,或者必须是特殊的文件结构(父项目的pom.xml在子项目的pom.xml的父一级目录里)时,上例才工作。

(译者:我工作的就是类似的父子项目。子项目依赖于父项目。每次修改了父项目的代码后,必须运行:

mvn install //将父项目编译并加入到repository中

之后才能顺利的运行子项目。)

如果父项目没有安装到local repository中,同时目录结构如下(父子项目在平行的目录结构中)就会有问题:

.
 |-- my-module
   `-- pom.xml
 `-- parent
     `-- pom.xml

为了解决这个目录结构(也可以是其他目录结构)导致的问题,我们必须在parent section中使用。


 
    com.mycompany.app
    my-app
    1
    .../parent/pom.xml
 
  4.0.0
  my-module

如同的字面意思(相对路径),它是module的pom.xml到父pom.xml的相对路径。


  • Project Aggregation 项目集成

project aggregation 和project inheritance类似。但与project inheritance在my-module中设置父POM不同的是,project aggregation是在父POM中设置my-module。

通过这种方式,父项目在知道它的子模块。同时,如果在父项目上执行Maven命令,父项目和所有的子模块都会执行该命令。

(译者:这就是为什么在Maven的POM中既有父子关系,又有子父关系。)

要使用project aggregation, 必须:

1, 将父POM的改为“pom”。

2, 在父POM中设置子模块的路径。


示例三:

再次使用之前的pom示例和目录结构,如下:

com.mycompany.app:my-app:1's POM


  4.0.0
  com.mycompany.app
  my-app
  1


com.mycompany.app:my-module:1's POM


  4.0.0
  com.mycompany.app
  my-module
  1


目录结构:

.
 |-- my-module
   `-- pom.xml
 `-- pom.xml

如果我们想把my-module加到my-app中,可以简单的讲my-app的pom.xml改为如下:


  4.0.0
  com.mycompany.app
  my-app
  1
  pom

 
    my-module
 

在这个修改过的pom中,加入了和。前者的值被设置为“pom”,后者设置为 my-module

的值是从com.mycompany.app:my-app:1的pom到com.mycompany.app:my-module:1的pom的相对路径(在例子中使用module的artifactId,即my-module作为目录名,所以设置的不是module名,而是目录的名字)。

现在,对于my-app运行的任何一个Maven命令(或者说phase或goal),同时也会在my-module上运行。


示例四:

但是如果我们将目录改为:

.
 |-- my-module
   `-- pom.xml
 `-- parent
     `-- pom.xml

父pom应该怎么设置呢?


  4.0.0
  com.mycompany.app
  my-app
  1
  pom

 
    ../my-module
 

答案是,使用和实例三同样的方法,将路径加到中。

  • Project Inheritance和Project aggregation的使用

如果你有好几个Maven项目,同时它们有着类似的配置信息,你可以重构你的这些项目,通过将这些相同的配置抽取出来,放到一个父项目中去。

这样,你需要做的所有事情就是让你的Maven项目继承父项目,然后这些共同的配置就会生效了。

同时,如果你有一组项目,它们需要在一起build和process,你可以创建一个父项目,同时将这些子项目配置成父项目的modules。通过这种方式,你只需要build父项目而子项目就都会build了。

(译者:例如我工作的项目,多个项目,比如项目A,B,C共享同样的核心代码。采取的方式就是将核心代码抽取出来做成一个父项目称为core,将)这些项目配置为父项目的modules。

可以通过build core项目,就build了所有的modules。

但有时也需要变通一下:当运行比如A项目的daily build时,我们并不需要build所有的项目。这时的做法就是,对于core项目,实际有4个pom文件:

pom.xml, A_pom.xml, B_pom.xml, C_pom.xml。当运行A的daily build时,实际在build环境中使用的是A_pom.xml。同时该pom文件中,core的子模块只有A一个。

另外需要注意的一点是:如何build的问题

例如我前面提到的我工作的项目,如果修改了core中的代码,并想重新build项目A时,有三种方法。

1,在core项目上运行mvn build。这样core, A, B, C4个项目都会被build。

2,如果只想build项目A,就用A_pom.xml覆盖core的pom文件,然后运行mvn build。则会build项目core和A。

3,或者,对core项目运行mvn install(该命令会编译,build并将build出来的jar包安装到repository中去), 之后再在A项目运行mvn build)

但是,当然了,你也可以同时使用项目集成和项目继承。意思是,你可以在子项目的pom中配置parent,同时在父项目中配置modules。你只需要明确下面3个规则:

1, 在每一个子项目pom中都要配置parent。

2,将父项目pom的packaging改为“pom”。

3,在父pom中配置子modules。

(译者:到此项目间的关系已经讲完了,让我们来总结一下:

当我们拿到了几个相关项目时,一定要先搞清楚这些项目间的父子关系。我们不仅要考察每一个项目的pom文件,弄清楚他们之间的集成和继承关系,也需要留意项目的目录结构,以防止有些设置并没有生效。

只有弄清楚了项目的关系,我们才能正确的使用Maven的功能)


(译者:原文中还有一个示例五,是关于将上面3点都融合在一起的pom文件,我觉得没有必要再累述了。)

(另外需要说明的一点,如果打开本地的repository,你会发现每个artifact(通常是jar包)也有自己的pom文件。其实原因很简单:Maven也要管理这些artifact。比如类库A,同时也依赖于类库B,C。

因此repository中的artifact也需要pom文件来说明它们之间的关系)


  • 项目的插入值和变量

Maven鼓励的一种做法是,不要自我重复。然而,有时候还是需要在几个不同的地方使用相同值。为了保证仅在唯一的地方定义值,Maven允许你在pom中使用你自己定义的变量。

例如,为了在pom几个不同的地方使用相同的值,project.version,你可以这样做:

${project.version}

同时,在pom文件中定义:


  ...
 
    <<span style="color:#000000">version
>1.0.4<<tt>/version>
 
  ...

需要注意的是,这些变量是在继承机制生效后赋值的。这意味着,如果一个父项目pom包含变量,这些变量会被子项目继承并可以在子项目中直接使用。


这里有三种可使用的变量:

Project Model Variables

所有在pom中的独立的element都可以作为一个变量。例如${project.groupId},${project.version},${project.build.sourceDirectory} 等等。参考POM reference来得到所有的properties。

所有这些变量使用时都应加上前缀"project."。你也可能看到一些以“pom.”为前缀的情况,但是已经不赞成这么做了。

Special Variables
basedir The directory that the current project resides in.
project.baseUri The directory that the current project resides in, represented as an URI.Since Maven 2.1.0
maven.build.timestamp The timestamp that denotes the start of the build. Since Maven 2.1.0-M1

对于build timestamp的格式问题,可以通过指定,如下:


  ...
 
    yyyyMMdd-HHmm
 
  ...

日期格式需要遵守的规则可以参考 SimpleDateFormat(java的)的API文档。如果没有设置这个值,则使用上例中的默认值。


最后一种就是前面提到的,不累述。

 

原文到此结束,但我还想加一点关于POM中的dependency的内容。

dependency描述了当前项目对其他项目的依赖关系。如下例,表示当前项目依赖于log4j artifact(并非父子关系)。

   
       
       log4j
       log4j
       1.2.14
       

   

同样我们使用的很多第三方工具,如JUnit等等,都需要使用dependency加入到项目的POM中(当然也可以使用项目继承的方法,从父项目继承)。

在eclipse中使用Maven插件时,可以使用图形化界面添加dependency。过程是:

1,点击添加dependency。

2,输入名字,如JUnit。此时Maven插件会到使用的remote repository中搜索相应的类库。

3,搜索到以后,点击希望添加的artifact,确定。此时POM文件已经被修改了,加入了新增的dependency。

4,点击保存。这时Maven就会开始从remote repository下载artifact。

 

如果没有按照Maven插件,另外一种方法就是直接修改pom.xml,加入dependency部分。保存后Maven即开始下载artifact。

不过这里有一个问题,直接修改pom.xml时,往往不知道要添加的类库的完整名称, 即::,进而也不知道该怎么填 写等内容。

这里有一个方法,下面的网站是browse repository的:

https://repository.sonatype.org/index.html#nexus-search;quick~junit

使用方法类似:搜索后,找到想要的类库,然后就能看到对应的 的内容。直接将该段xml复制到自己的pom.xml中就可以了。


完毕~~~

关于POM,可以参考http://maven.apache.org/pom.html 得到更详细的解释。


看完了Maven中的几个重要概念一,二和三,相信对Maven已经有比较全面的了解了。

这个时候开始看Maven的完全参考手册就会非常轻松了。

----------------------------

首先是Maven的官网guide,包含了相当多的内容。有时间的时候应该全部浏览一遍。

http://maven.apache.org/guides/index.html

 

参考原文:

http://maven.apache.org/guides/introduction/introduction-to-repositories.html


在Maven出现之前,如果我们希望在自己的程序中使用第三方类库,需要怎么做呢?

首先,得到这个类库的jar包。可以从官网上下载,也可以从别的地方copy过来。

然后把这个包import到IDE中的JRE System Library中,就可以开始使用了。

不算复杂,但使用Maven更简单。你只需要告诉Maven,我需要用某个类库,就OK了。

Maven将自动去获取你需要的这个类库,从哪?repository。

A repository in Maven is used to hold build artifacts and dependencies of varying types.

repository只有两种:local and remote。所以当你告诉Maven要使用某类库时(即当一个项目声明要使用一个dependency),Maven做的事情就是:

从它在网络上的远程repository 找到这个类库,下载到你本地的repository(默认在c盘 ....m2repository)中。

如果Maven发现你本地的repository已经有这个类库,那就什么都不做。

因此,remote repository包含了相当丰富的流行的类库/框架/工具。如果你需要使用某个很偏门儿的类库,那么,通常还是只能用老方法,自己去下载先。

下载后可以在命令行中运行mvn install,将类库安装到自己本地的repository中去。


远程repository有两种,一种是由公共组织提供的:

a third party to provide their artifacts for downloading (for example, repo1.maven.org anduk.maven.org house Maven's central repository).

我们通常都会使用这些repository。这些repository有两个问题:

1,网络问题。例如你所在的环境没有网络。或者公司对互联网访问有限制,导致你无法访问到。

2,由于Maven已经相当流行,有时这些repository服务器会因为负载过高而出现问题。

默认情况下,会去默认的repository 下载artifact。

http://repo1.maven.org/maven2/ (从前提供了browse的功能,但是现在被禁止了)

如果不想使用这个默认的repository,可以在settings.xml中使用mirrors来指定别的。但是在POM中可以指定使用的repository所以这个设置可能被覆盖。

(关于settings.xml,可以参考 http://maven.apache.org/settings.html#Servers。个人认为要必要把这个也好好看看。)

另一种可以是公司自己搭建的,用于公司内部人员共享的repository。这样通常就不会有网络和负载的问题了。


文章最后讲述了如何搭建internal repository。有兴趣的同学自行参考。

需要说明的一点是:

Such an internal repository can be downloaded from using HTTP or the file system (using afile://URL), and uploaded to using SCP, FTP, or a file copy.

Note that as far as Maven is concerned, there is nothing special about this repository: it is anotherremote repository that contains artifacts to download to a user's local cache, and is a publish destination for artifact releases.

因此repository没有什么特别,它可以是任何一个文件系统,上传和下载可以使用多种协议。

但需要使用repository manager来搭建一个repository server。

http://maven.apache.org/repository-management.html

讲述了3种repository manager工具,及其作用。

 

最后再提一下关于settings.xml。有两种settings.xml:

  • The Maven install: $M2_HOME/conf/settings.xml
  • A user's install: ${user.home}/.m2/settings.xml


第一个settings.xml,也称为global settings。第二种,也称为user settings。这里有一点及其重要的!不论是global settings还是user settings,settings.xml都不会被自动创建。

例如,你现在想把local repository放到一个你自己指定的地方,而不是默认的地方,就可以创建一个user settings,同时在其中指定你需要的位置。

创建方法很简单,到官网上copy一个例子,并修改相应的内容就可以了。user settings中的配置优先级更高。

原文:http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html


当我们在使用Maven做一些工作,如打包,编译,运行测试等等任务时,我们已经使用到了Maven中的几个重要概念:

lifecycle, phase and goal。

例如,如果我们使用ant打包,我们需要清晰的在脚本中告诉ant:

源代码在哪,打包的目标文件类型如jar,目标文件夹在哪。首先要编译,然后运行测试,最后打包。

而Maven为了在最大程度上简化我们的工作,因而定义了lifecycle, phase and goal。我们仅仅需要简单的运行:

mvn package(package是一个phase), 包就自动打好了。

而实际上,mvn package这个命令会运行以下6个步骤(左边这列是步骤名,同时也是phase的名字,右边是对应的goal):

process-resources resources:resources
compile compiler:compile
process-test-resources resources:testResources
test-compile compiler:testCompile
test surefire:test
package jar:jar

因此使用Maven打包时,用到的信息和步骤一点都不比用ant少,只不过使用到的信息,定义在了POM文件中(本文并不涉及);而步骤定义在了lifecycle, phase and goal中。

也就是说,Maven定义了一系列的best practice。

在这里,对与打包这个任务,我们仅需要使用Maven中已经定义好的这些best practice,就能简单的完成日常工作了。

下面我们首先介绍这些best practice,也就是定义好的lifecycle, phase, goal。

之后介绍如果我们不想使用best practice,比如,我们想在打包时,在上面的test-complie(这个步骤仅编译测试代码,但不会运行测试用例)之后,运行测试。同时,还希 望能使用一个第三方工具检查测试用例的代码覆盖率,并形成一个报表。也就是说,我们希望在打包结束时,同时得到一个测试代码覆盖率的报告,应该怎么做。

现在开始~

  • There are three built-in build lifecycles: default, clean and site.

有三种内置的build lifecycle:The default lifecycle handles your project deployment, the clean lifecyclehandles project cleaning, while thesite lifecycle handles the creation of your project's site documentation.

  • Each of these build lifecycles is defined by a different list of build phases, wherein a build phase represents a stage in the lifecycle.

For example, the default lifecycle has the following build phases (这里并不包含所有的phase,只是举例):

1,validate - validate the project is correct and all necessary information is available

2,compile - compile the source code of the project

3,test - test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployed

4,package - take the compiled code and package it in its distributable format, such as a JAR.

5,integration-test - process and deploy the package if necessary into an environment where integration tests can be run

6,verify - run any checks to verify the package is valid and meets quality criteria

7,install - install the package into the local repository, for use as a dependency in other projects locally

8,deploy - done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects.

执行一个phase将会执行这个lifecycle前面的所有phase。


下面这个例子执行了clean lifecycle和default lifecycle到install为止的所有phase。

mvn clean install

  •  A Build Phase is made up of goals

However, even though a build phase is responsible for a specific step in the build lifecycle, the manner in which it carries out those responsibilities may vary.

And this is done by declaring the goals bound to those build phases.

A goal represents a specific task (finer than a build phase) which contributes to the building and managing of a project. 

也就是说,执行phase实际执行的是goal。如果一个phase没有绑定goal,那这个phase就不会被执行。

一些phase默认已经绑定了一些goal。对于default lifecycle来说, 这些被绑定的goal并不完全相同,而是和packaging value相关。所谓的packaging value就是

jar//这个很好理解,对于不同的包类型,打包的过程不尽相同,因此需要执行的goal也不同。

一个goal是独立的,它可以被绑定到多个phase中去,也可以一个phase都没有。如果一个goal没有被绑定到任何一个lifecycle,它仍然可以直接被调用,而不是被lifecycle调用。

因此可以这样理解phase与goal的关系:

phase其实就是goal的容器。实际被执行的都是goal。phase被执行时,实际执行的都是被绑定到该phase的goal。

goal与goal之间是独立的。因此单独执行一个goal不会导致其他goal被执行。

下面的例子

mvn clean dependency:copy-dependencies package

clean是phase。

dependency:copy-dependencies是plugin-in dependency 的goal copy-dependencies。

package也是一个phase。

maven会顺序执行这3个对象中包含的所有goal。


Plugin

另外一种将goal绑定到phase的方法就是在project中使用plugin。即在POM中配置。

Plugins are artifacts that provide goals to Maven. Furthermore, a plugin may have one or more goals wherein each goal represents a capability of that plugin.

这里我们先思考一个问题,goal的本质是什么?

例如我们上面提到的需要,希望在打包时得到一个测试代码覆盖率的报告。

实现的方法就是:

1,将计算代码覆盖率的工具,例如cobertura,安装到Maven的repository中。此时cobertura就是一个plugin。

最简单的方法就是将cobertura加到项目的dependency中就行了。Maven会自动去网上的公共repository中下载项目依赖的的dependency到本地的repository中。

2,修改POM文件(可参考下面的pom的例子),将这个plugin,连同要执行的goal,加到package这个phase中去。

由于现在Maven已经非常流行,所以这些工具的官网上都会提供在Maven中使用该工具时,应使用什么命令。

参考cobertura网站,我们可以知道对于这个工具,对应的命令是:

mvn cobertura:cobertura (即phase和goal的名字都是cobertura)

3,此时再运行mvn package,就会运行cobertura这个plugin的goal,也就是cobertura。

之后我们就会在默认的位置找到生成的报表。

因此,goal其实是由存在于Maven的repository中的plugin提供的一个个小的功能程序。

它是Maven的lifecycle以及phase的基本组成元素。同时,我们也可以通过将各种各样的goal加入到Maven的phase中,从而根据自己的实际需求,灵活实现各种定制功能。


下面是一个更general的例子,该POM中展示了,如何将display-maven-plugin中的goal time绑定到process-test-resources这个phase中。
 
   com.mycompany.example
   display-maven-plugin
   1.0
  
    
       process-test-resources
      
         time
      
    
  
 
...

通过前面的例子我们明白,完全可以自行开发一个java程序,作为goal绑定到phase中后执行。

但Maven对嵌入到它之中的plugin有一些标准,在开发程序时需要遵循。


下面链接中列出了主要的Maven plugin。

http://maven.apache.org/plugins/index.html

同时关于plugin还可以参考下面链接中的plugin文档,得到更详细的解释。

http://maven.apache.org/guides/index.html

-----------------------------------

基本上运行maven有两种形式:

1,Maven phase name

比如:Maven Build--Build是一个phase。

 

2,Maven plug-in:goal

比如:Maven assembly:assembly 指运行assembly plug-in 中的assemly goal。

 

在运行Maven项目时经常可以看到大量的类似信息:

 

[INFO] >>> maven-assembly-plugin:2.2:assembly (default-cli) @ project name >>>

//这里的插件全称是maven-assembly-plugin 2.2是版本号? assembly 是goal

//嗯,回头还得再扫一眼maven。(default-cli) @ project name 不知道是啥。

  
[WARNING] The POM for opensymphony:quartz-all:jar:1.6.3 is missing, no dependency information available
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ name---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 12 resources --后面紧跟这个插件的运行结果。
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ name---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ name---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ name ---
[INFO] Nothing to compile - all classes are up to date

 

 安装了maven之后,在run as中会出现很多快捷方式,如:

maven install  --将代码安装到本地repository。

maven test

maven build 等等

这些相当于运行phase的快捷方式。如果需要修改phase,在每个phase中指定不同的goal,就可以右键点击:

project->run as ->maven build。。。

Maven

此时,在goal中写入希望运行的phase名字,如install。其他的选择则是用来修改它的一些行为,如skip tests就可以了。 

maven相当于一个独立的项目。对pom。xml进行了修改,都需要重新build这个项目。




Junit
----------------------------------------------------------------------------------------------------


Git/GitHub
----------------------------------------------------------------------------------------------------


SVN
----------------------------------------------------------------------------------------------------


java打包
------------------------------------------------------------------

jar包

http://docs.oracle.com/javase/tutorial/deployment/jar/basicsindex.html


The Java™ Archive (JAR) file format enables you to bundle multiple files into a single archive file. Typically a JAR file contains the class files and auxiliary resources associated with applets and applications.

jar使用的是zip压缩技术,我们也可以选择不压缩。

  • 基本命令

基本的打jar包的命令很简单:

jar cf test.jar input-file(s)

cf的意思是打一个jar文件。其他参数请自己查询。

test.jar是指定的jar文件的名字。

input-file(s)是 指定哪些文件应该被包括到jar中去。通常是代码编译后产生的class文件。另外如果代码中引用了其他类库,也就是jar包。我们可以一并和源代码打到 一个jar包里,这样运行时,一个jar包就够了。如果选择仅将源代码打进jar包,则在程序运行时,还必须将需要的类库放到合适的地方并加入 classpath中。

  • manifest 文件

执行完上面的命令后,就生成了一个jar包。如果我们解压这个jar包,可以看到这样一个文件:

META-INF/MANIFEST.MF,内容是:

Manifest-Version: 1.0
Created-By: 1.7.0 (Oracle Corporation)

这是自动生成的manifest文件。

此时如果运行:

java -jar test.jar

将会返回:

Failed to load Main-Class manifest attribute from test.jar

程序无法运行,因为java不知道程序的入口在哪。

  • Main-Class header in manifest file

通过在manifest file中指定Main-Class属性,就可以告诉程序入口了。有两种方法:

1,手工修改mafifest file。

We first create a text file named Manifest.txt with the following contents:

Main-Class: MyPackage.MyClass

然后运行:

jar cfm MyJar.jar Manifest.txt MyPackage/*.class

m的意思是使用一个已有的manifest文件。此时java -jar MyJar.jar就可以工作了。

2,使用参数e

jar cfe app.jar MyApp MyApp.class

参数e将manifest文件中的Main-class设置为:MyApp 。这样就不用手工修改文件了。


另外说一下引用第三方类库的问题。前面说了,可以将java代码依赖的第三方类库一并打包进一个jar文件,也可以只将java代码放进jar文件,在程序运行时再另外指定classpath。

对于第二种方式,manifest文件中,还有一个属性,class-path。使用这个属性,我们就可以直接指定classpath了,而不是在每次运行的时候麻烦的单独指定。

注意,这种方式有以下限制:

The Class-Path header points to classes or JAR files on the local network, not JAR files within the JAR file or classes accessible over internet protocols. To load classes in JAR files within a JAR file into the class path, you must write custom code to load those classes. For example, if MyJar.jar contains another JAR file calledMyUtils.jar, you cannot use theClass-Path header inMyJar.jar's manifest to load classes inMyUtils.jar into the class path.


例如,MyApp.jar在运行时需要一个MyUils.jar。首先造一个manifest文件,加入以下内容:

class-path: directory-name/MyUils.jar

和前面一样,运行jar cfm,使用已有的manifest文件生成jar文件,该jar文件仅包含MyApp的class文件:

jar cfm MyJar.jar Manifest.txt MyPackage/*.class

然后MyApp.jar就可以直接运行,而不必指定classpath了:

java -jar MyApp.jar


我们还可以在manifest文件中指定package的版本:

http://docs.oracle.com/javase/tutorial/deployment/jar/packageman.html

 

对于第一种方式,即在运行时指定classpath:

java -cp ${CLASSPATH} main-class

需要注意的是 ${CLASSPATH}  不能使用类似/folder/* 这样来指定将一个目录下的所有jar包都加到class-path中,注意下面的话:

For a .jar or .zip file that contains .class files, the class path ends with the name of the .zip or .jar file

 

因此只能是这样的:

CLASSPATH="$codeHome/lib/commons-collections-3.2.1.jar:$codeHome/lib/commons-io-2.0.jar:$codeHome/lib/saxon-xpath-8.7.jar"

但如果要运行的程序的是.class文件而不是jar包时,classpath可以直接指定成目录:

CLASSPATH=.;D:JAVALIB;C:DOCJavaT

java解释器会去目录search class文件
CLASSPATH contains one or more directories that are used as roots in a search for .class files. Starting at that root, the interpreter will take the package name and replace each dot with a slash to generate a path name off of the CLASSPATH root (so package foo.bar.baz becomes foobarbaz or foo/bar/baz or possibly something else, depending on your operating system). This is then concatenated to the various entries in the CLASSPATH.

There’s a variation when using JAR files, however. You must put the actual name of the JAR file in the classpath, not just the path where it’s located. So for a JAR named grape.jar your classpath would include:
CLASSPATH=.;D:JAVALIB;C:flavorsgrape.jar

最后,由于现在maven在
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐