《Maven实战》笔记 4.2 – maven命令与lifecycle&plugin的关系

mvn test   执行lifecycle "default"的phase "test". 由于phase "test"被绑定到surefire plugin的test goal, 因此surefire的test goal会被执行; 同时, phase "test"之前的所有的phase也会被执行。 mvn eclipse:eclipse   执行 eclipse plugin中的eclipse goal. "eclipse" plugin是哪个plugin? 如果没有特殊配置,Maven会去 http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-metadata.xml等默认metadata中寻找prefix=eclipse的配置

《Maven实战》笔记 4.1 – lifecycle和plugin的概念

a.Maven定义了标准的lifecycle,如 编译 -> 测试 -> 打包,每个步骤称作一个"phase"。phase有先后关系,执行一个phase前必须先执行前面所有的phase b.phase有名无实,只是一个虚的接口,本身并不做任何事情 c.plugin则做一些真正的事情,比如真正的编译、打包等。一个插件可以有多个功能点,每个功能点称作一个"goal" d.把phase 和 goal关联起来,就可以基于lifecycle进行构建了

《Maven 实战》笔记3.3 – internal repository与mirror

    internal repository是指在局域网内部搭建的repository,它跟central repository, jboss repository等的区别仅仅在于其URL是一个内部网址     mirror则相当于一个代理,它会拦截去指定的远程repository下载构件的请求,然后从自己这里找出构件回送给客户端。配置mirror的目的一般是出于网速考虑。     可以看出, internal repository和mirror是两码事。前者本身是一个repository,可以和其它repository一起提供服务,比如它可以用来提供公司内部的maven构件;而后者本身并不是repository,它只是远程repository的网络加速器。     不过,很多internal repository搭建工具往往也提供mirror服务,比如Nexus就可以让同一个URL,既用作internal repository,又使它成为所有repository的mirror

《Maven 实战》笔记3.2 – 让Repository区别对待snapshot版本和release版本

可以让Repository区别对待snapshot版本和release版本。也就是说,你可以只从jboss repository中下载release版本,并只从google repository中下载snapshot版本。      另外,考虑到本地Repository相当于远程Repository的缓存,应该设置一下缓存的更新频率,提供snapshot的repository更要设置(当然,也可以不显式设置,默认值是daily)         <repository> <!– … –> <releases> <!– 本repository不提供release版本下载 –> <enabled>false</enabled> </releases> <snapshots> <!– 本repository提供snapshot版本下载 –> <enabled>true</enabled> <!– 缓存每超过五分钟就要更新–> <updatePolicy>5</updatePolicy> </snapshots> <!– … –>   

《Maven 实战》笔记3.1 – Repository的概念及其在项目中的使用

1. Repository用来存放maven项目的构件,如pom, *.jar, *-source.jar等,它的布局像一个文件系统,有路径(目录)和文件 2. 使用Maven时,你会跟两类Repository打交道。    a. 存放在你本机那些的构件即组成“ 本地Repository”    b. 不在你本机的、存在服务器上的叫“ 远程Repository"。    当Maven需要构件时,首先会在本地Repository里找,找不到才去远程Repository中找。 3. Repository是相对于项目而言的,所以 你可以在项目级别配置远程的Repository,而且可以配多个。    一个Repository是一个 id + url + 其它信息的组合。id你可以随便取,url则是远程Repository的确切地址。 <project> <repositories> <repository> <id>jboss</id> <name>jboss</name> <url>https://repository.jboss.org/nexus/content/repositories/</url> … </repository> <repository> <id>google</id> <name>google</name> <url>http://google-maven-repository.googlecode.com/svn/repository/</url> … </repository> </repositories> … </project> 对此你可能有多种疑问: 问:项目里配了两个repository,那下载构件时,Maven去哪个repository呢? 答案:测试表明,Maven会先去定义在最前面的repository即"jboss"里去找; 如果找不到,再去"google"找 问:如果jboss和google里都找不到呢? 答:就去Maven默认的central repository里去找,它的id是"central", url是http://repo1.maven.org/maven2. 这个配置写死在maven的某个jar里面 问:如果我把上面的jboss repository换成"central"会怎么样? <project> …

《Maven 实战》笔记3.1 – Repository的概念及其在项目中的使用 Read More »

不建议把可以做在webapp里面的基础架构做到webapp外面

有很多基础服务,本来可以做在webapp里面的,但有人却选择把它做在webapp外面。 比如jboss提供的log4j服务,就是一个很讨厌的东西,很容易跟你应用里面的log4j冲突。 还有些服务,比如连接池服务,被强行做成了jndi,由容器来打理,这也很讨厌。 在我看来,把可以放里面的东西丢到外面有这样几个缺点:     1. 本可以由程序员完全控制的基础设施,现在要由运维人员来分担了。jndi就是一个例子。   2. 本可以由scm工具控制的东西,现在要经常手动来管理,这在版本管理方面往往产生问题。比如那些由jca写的、丢在jboss下面的东西,没办法用maven+svn直接管理了   3. 内外冗余造成的冲突问题。如果你的应用里使用了log4j,就可能跟jboss自带的log4j产生版本冲突和class loading冲突   4. 开发环境和其它环境的不一致问题。比如你开发用Tomcat,Tomcat不提供JNDI,所以你开发时不使用jndi那一套; 但正式环境用的又是jboss + jndi。结果就是你的代码或配置要支持两种东西,开发时不搞jndi,发布时要搞jndi

《Maven实战》笔记 2.4 - Optional依赖

Optional依赖:   假设App依赖了A, A“可选”地依赖了B,那App在打包时,会不会纳入B?   答案:不会。如果你的App里需要用到A中跟B相关的功能,那就需要把B用作App的直接依赖。  可选依赖不是什么好东西,它搞得你把传递依赖升级为直接依赖,很容易令人困惑,你的同事会问:为什么App要直接依赖B?   如果A对B有可选依赖,则应该把A拆成两个项目,其中A1依赖B,A2不依赖B,App再按需选择  

《Maven实战》笔记 2.5 - 依赖的调解

Maven的依赖调解机制     1.如果存在App->A->B-0.9, 又存在App->C->D->B-1.0,那App在打包时会不会把B-0.9和B-1.0都纳入进来?如果不会,倒底选择哪个B?    答案:只会纳入一个,即B-0.9,因为它离App较近(中间只隔了一个A,B-1.0和App之间则隔了D,C两个)   2.App到B存在两条依赖路径,怎么识别这种情况?    答案: mvn dependency:tree -Dverbose,它会显示哪些项目由于这种情况而被“omitted for conflict”   3.B-0.9被选中,会不会导致依赖B-1.0的D在运行时出错?    答案:会的。如果D依赖了B-1.0中有而B-0.9里没有的东西,就会在运行时出错   4.那该怎么办?    答案:      办法1. 在App的pom里,屏蔽掉A对B的依赖 <dependency> <groupId>kent.learn</groupId> <artifactId>maven-a</artifactId> <exclusions> <exclusion> <groupId>kent.learn</groupId> <artifactId>maven-b</artifactId> </exclusion> </exclusions> </dependency>      办法2. 让App直接依赖B-1.0,让其他的对B的传递依赖都失效

《Maven实战》笔记 2.6 – Used undeclared 和 Unused declared

你的项目会直接依赖一些项目,也可能会传递依赖一些项目;有的直接依赖,可能你本应该降格为传递依赖;有的传递依赖,你可能应该用作直接依赖;还有些直接依赖,可能你已经用不上应该去掉了。 mvn dependency:analyze就是用来帮你发现上述情况的一条命令。它会对两种情况作出警告:   1. Used undeclared dependencies。 你的App的代码直接调用了B里的API,但当前B是通过App->A->B的关系被纳入到Classpath的。这种情况下,你应该将B升级为直接依赖。否则的话,如果A不再依赖B了,你依赖B的那些代码就会有编译错误,而且可能是很难找到原因的编译错误。   2. Unused declared dependencies。你的App的代码没用直接调用B里的API,但却把B声明为App的直接依赖。 这种情况下,你要谨慎     a.App可能确实不需要直接依赖B,不过,可能会这样:App->A,A调用了B里的API,但A的pom里没有声明B。如果A的作者不负责任,这种情况就会出现,而且在大型组织里经常会遇到。这种情况下,你就要仍然把B留下来作为依赖,否则运行时A就会说找不到B而报错。     b.App的java代码里不需要直接依赖B,但是经过xml配置文件或者以反射方式调用了B里的API,这种情况下你也要保留B作为直接依赖。     c.App依赖了A,A依赖了B,这时你可以去除对B的直接依赖     d.App没有调用B里的代码,App的其他所有直接依赖和传递依赖的pom里都没有依赖B,也没有调用B里的API,这时也应该去除对B的直接依赖。 要判断App打包后是否需要B出现在classpath里,可以使用JarJar工具。它可以分析App打包后、包里所有的jar文件之间的java调用关系。

《Maven实战》笔记 2.3 - 传递依赖:Maven的核心竞争力之一

如果你的项目要引入Spring,而你又不用Maven,你怎么把Spring本身所需的jar文件找出来?   1.办法一:先只纳入spring.jar,然后创建你的应用,根据编译和运行时的错误,结合Spring的文档,把Spring所需的第三方jar一个一个下载,再纳入进来 — 不用说,会费劲死   2.办法二:把spring-with-dependencies.zip包里的spring.jar和第三方库一次性纳入进来,这样是省事很多,但你纳入的第三方库存在两个问题:     a.有些则可能和你已经存在的第三方库重复(如apache-commons系列),但版本不一样。这时你就得手动解决这种重复问题,即选择留下哪个,去掉哪个     b.有些库可能并不需要纳入进来,因为spring只是某块功能会用到它们,而这块功能你的应用根本用不上。这些不需要的库放在你的应用里,很容易跟未来引入的其他第三方库重复(比如引入Hibernate时也要引入apache-commons系列),到时又会产生跟#a一样的问题。 Maven可以自动化地解决这些问题。   1. 你只需要宣称依赖Spring   2. Spring所需要的类库会被Maven自动下载下来,不需要你手动下   3. 如果这时存在第三方库的重复问题,Maven会自动为你做好依赖的调解