前言
不知道你是否以前经常遇到把一个project的相关依赖配置好,想启动看看效果,但却遇到一个ClassNotFoundException的失败?
不知道你是不是有不知道把src文件一test文件放哪的选择困难,或者不知道resources文件放哪的纠结?
Maven,就是它。有了它,java项目管理不再是问题。
安装
前期准备:安装JDK环境。
Ubuntu jdk7:sudo apt-get install openjdk-7-jdk -y
Windows请到Oracle JDK下载安装,现在应该都会自动配置环境变量,如果没配置成功,请自行搜索配置。
安装完成后,在命令行运行:java -version
如果显示了java的版本信息,表示安装成功。
安装Maven
在ubuntu下面直接执行:sudo apt-get install maven -y
就能直接安装并配置好相关的环境变量。
windows下需要到Maven下载页面下载maven开发包,比如解压到D:/maven下,设置环境变量:M2_HOME = D:/maven
运行mvn -v
如果看到版本信息,说明安装配置成功。
maven仓库默认在用户目录下的.m2目录下,linux可以用
cd ~/.m2
快速切换到该目录下,windows用户请到Users\user.m2目录下查看。
maven项目查找依赖的时候首先会在本地仓库查找,如果找不到,就会到远程仓库查找并同步到本地,下一次再用的时候就能快速定位到本地仓库的资源。
创建Maven项目
快速创建一个webappmvn archetype:generate -DinteractiveMode=false -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=org.codelogger -DartifactId=web-demo -Dversion=1.0.0-SNAPSHOT
也可以通过交互式创建mvn archetype:generate
当然,你也可以用IDE来创建Maven项目,Eclipse如下:
File > New > Other > Maven Project, 如果按原型创建,就按Next,如果要自定义创建,就勾上Create a simple project。
自定义创建里面可以比较详细的定义项目属性,尤其是parennt project非常有用,我自己就创建了一个Codelogger Parent Pom, 里面定义了常用的工具集(Codelogger Utils,Guava,Common-lang Utils),及常用的项目版本整合(Spring,Hibernate,etc),及测试环境。
关于pom.xml
下面是一个pom.xml的示例,有点长,可以略过这里直接住下看:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codelogger</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>web-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>Codelogger Web Project Demo</name>
<description>Codelogger webapp demo, build with Spring MVC, Spring JPA and Hibernate</description>
<url>https://github.com/defei/codelogger-core</url>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<developers>
<developer>
<name>Deng Defei</name>
<email>dengdefei@gmail.com</email>
</developer>
</developers>
<scm>
<connection>scm:git:git@github.com:defei/web-demo.git</connection>
<developerConnection>scm:git:git@github.com:defei/web-demo.git</developerConnection>
<url>git@github.com:defei/codelogger-core.git</url>
</scm>
<properties>
<web.version>1.0.0</web.version>
<maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>
<java.version>1.7</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.codelogger</groupId>
<artifactId>web</artifactId>
<version>${web.version}</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
</dependencies>
<profiles>
<profile>
<id>dev-mysql</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profileName>dev-mysql</profileName>
<logPath>~/Desktop</logPath>
</properties>
</profile>
<profile>
<id>production</id>
<properties>
<profileName>production</profileName>
<logFile>/var/www/codelogger.org/web-demo/logs</logFile>
</properties>
</profile>
</profiles>
<build>
<resources>
<resource>
<directory>docs/commons</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>docs/profiles/${profileName}</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Maven项目的唯一性
pom里面的下面三个属性非常重要:
- 项目 groupId(组织名:隶属于哪个公司或组织,如org.codelogger
- 项目 artifactId(构件名):该组织下,项目的唯一标识符
- 项目 version(版本号):原则做到语义化版本最好
【groupId】,【artifactId】,【version】可以精确定位到一项目的指定版本,所以具有唯一性,你在Maven中央库中就能通过这三个属性找到对应的项目,这样才能准确的管理好项目依赖。
小提示:version可以指定为
RELEASED
,这样项目就会去找最新的released的版本,好处是可以用到新特性,缺点是可能造成项目不稳定。
Maven的继承关系
pom是可以继承的,所以我们可以在Parent Pom里面做依赖管理等操作,然后在子项目里面,只需要定义需要哪些依赖,然后依赖版本就会自动从父级继承下来。
比如上面展示的:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
没有指定version,但一样能用,就是因为我们在Parent Pom的<dependencyManagement>
里面已经定义过版本信息了。
其它的,比如properties, plugins, profile, dependency, resources等,都是可继承的。
项目说明信息
- name:项目的名称
- description:项目的具体描述
- url:项目页面Web地址
- licenses:版权信息
- developers:开发者
- scm:软件配置管理,如git,cvs信息
properties
<properties>
<web.version>1.0.0</web.version>
<java.version>1.7</java.version>
</properties>
properties定义了一系列的property,使用的时候,用${property.key}
就能输出里面的值。
除了定义公共的<properties>
外,我们还可以在<profiles>
里面的<profile>
里定义私有的properties,如下:
<profiles>
<profile>
<id>dev-mysql</id>
<properties>
<profileName>dev-mysql</profileName>
<logPath>~/Desktop</logPath>
</properties>
</profile>
</profiles>
profile里面的properties权限比公共的大,也就是说如果名称都是一样的,会复写掉公共properties里面的数据,这样我们就可以做到非常灵活的定制了。
dependencies
dependencies定义了该项目的依赖关系,如果你需要引入一个依赖,只需要在dependencies里面定义一个dependency,并指定正确的groupId,artifactId以及version,就能自动载入这个依赖,如下:
<dependencies>
<dependency>
<groupId>org.codelogger</groupId>
<artifactId>web</artifactId>
<version>${web.version}</version>
</dependency>
</dependencies>
同properties一样,我们也可以在profile里面自定义dependencies,权重关系也是以profile的重,并且是profile隔离的。
profiles
profiles我们可以理解为pipeline,项目在运行的时候,只能选择一个profile,所以我们可以根据不同的profile做出不同的响应,比如dev这个profile,我们的数据库可以采用dbunit数据库,production的可以采用mysql数据库。
profile和<build>
的<resources>
一起使用的话,就可以做到根据不同的profile,载入不同的配置文件。
maven切换profile的命令是maven -P profileId
build
build定义了maven在管理项目的时候的配置,下面主要介绍resources和plugins,示例如下:
<build>
<resources>
<resource>
<directory>docs/commons</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>docs/profiles/${profileName}</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
resources定义了该项目的classPath,我们可以添加多个resource目录,并且当把filtering设置为true的时候,该目录下所有的文件,都会被扫描,如果有${property.key}
,并且在properties里面有匹配的数据,则${property.key}
会被替换为其对应的值,这样就能在pom.xml里对对项目乃至对profile做特定配置了。
plugins定义了build的时候会用到哪些插件,比如上面,我们用到的maven-compiler-plugin,在项目用mvn compile
的时候,就会按我们指定的java版本编译。
Maven命令
maven的命令有两种响应方式:
- mvn <插件>:<目标> [参数]
- mvn <行为>
第二种方式是我们使用最频繁的,例如:
mvn clean
:清空输出目录(即 target 目录)mvn compile
:编译源代码mvn package
:打包为构件(如jar、war包)mvn install
:将构件包安装到本地仓库mvn deploy
:将构件包部署到远程仓库
可以多个命令组合使用,如mvn clean install
执行 Maven 命令必须在 Maven 项目的根目录执行,也就是当前目录下一定存在一个名为 pom.xml 的文件。
后记
接触maven也有三年时间了,一直想详细的整理下资料,但由于懒惰与时间关系,直到现在才写出来,真的感到汗颜。
以上也只是对maven的一个大致介绍,更详尽的内容,请参考Maven官方文档。
感谢Maven,感谢Jason van Zyl。

