Maven基础概念

如果用过Eclipse和Intellij或者其他的IDE,就会发现由于各个IDE的设置不同,项目的目录结构也不同。如果每个人的可以自行设置项目目录和结构,就让大规模开发变得困难。Maven就是一个标准化的项目构建工具,用不同的IDE新建各自的项目会不同,但所有的IDE都支持创建Maven项目,只要Maven的配置文件一样,创建出来的结构就一样,这就非常方便项目移植和大规模协作开发。

在之前的项目构建中,我们手动下载了jar包,放到指定目录,再添加,有新的需要,再下jar包,再添加。有了Maven之后,把项目需要的依赖都写到Maven的配置文件中,然后启动项目,让项目结构标准化并且自动下载依赖。

Maven的工作原理是,先加载配置文件,然后到本地目录寻找依赖,如果没有,就去下载然后存放到本地目录中。而且下载之后,Maven是自动管理这些包,加入到项目的构建目录中。

Maven项目的标准结构如下:

这些目录的作用是:

Maven目录
目录 解释
src/main/java 相当于src目录,存放源代码
src/main/resources 属性和配置文件
src/main/webapp 这个目录存放Web配置文件,JSP和静态文件。相当于IDEA的Web目录,下边放WEB-INF目录。
src/test 单元测试代码和配置文件
target 编译完成的代码输出目录,好比Intellij的out/artifacts/项目名目录

举个例子,如果要把我们的增删改查项目换成maven结构的目录,控制器CustomerController的路径就是/Sprinweb/src/main/java/cc/conyli/controller/CustomerController.java

pom.xml配置文件

项目的目录下边有一个pom.xml文件,这是Maven的项目配置文件,也是最重要的部分。

这个配置文件的内容包含三部分:

  1. 项目元数据,包含项目名称,版本,输出文件类型比如JAR,WAR等
  2. 项目依赖,项目所需要用到的包
  3. 插件,一些额外的自定义的内容,比如JUnit等

先来看一下项目元数据。

<modelVersion>4.0.0</modelVersion>
<groupId>spring-hibernate-for-beginners</groupId>
<artifactId>spring-web-customer-tracker</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>

这部分的内容实际上就是对自己开发的软件包的定义,如果将来自己的软件包发布,别人就要通过这里的groupIdartifactIdversion来找到软件包,这三个属性简称GAV。后边我们也需要通过GAV去寻找依赖包。

一般groupId的内容常用网站的名称去掉www之后倒着写,这也是很多软件包的名称方式。

ArtfactId是这个项目的名称。

版本是版本号。除了使用1.0这种,经常还习惯使用1.0-SNAPSHOT这种来表示开发中的版本。

来看一下依赖的部分:

<dependencies>
    <!-- Spring -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${springframework.version}</version>
    </dependency>
    <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
</dependencies>

这里可以看到,在dependencies标签内部使用dependency标签标注具体的某一个包。

可以发现,每一个依赖包同样需要GAV三个属性,表示Maven要去找到具体对应的包。这里的版本可以省略,但最好不要省略。

如何获取一个包的Maven配置属性呢?有两个办法:

  1. 到包的官网去搜索具体配置
  2. search.maven.org进行搜索

第一种方法需要到包的网站去寻找GAV属性,比如到http://hibernate.org/,点击Hibernate ORM里边的More,然后选择上边的Latest Stable 5.4,找到Maven Artifact,点击进入,就可以在页面下方看到:

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-agroal</artifactId>
  <version>5.4.1.Final</version>
  <type>pom</type>
</dependency>

将这段代码复制到pom.xml中即可。

第二种方法就直接去搜索,根据搜索结果点击想要的版本,就可以看到对应的GAV。

还有一个网站也是不错的Maven搜索库:http://www.mvnrepository.com/,也经常用于搜索软件包,比如Spring的地址就在https://mvnrepository.com/artifact/org.springframework/spring-context

Maven Archetypes

Maven原型是用来创建新Maven项目的东西,可以把Maven原型认为是创建一个项目的时候自动生成的初始文件和结构。

Maven常用的原型如下:

常用Archetypes
ID 说明
maven-archetype-quickstart 用于生成一个简单的普通Maven项目,适合于创建一个单独的包。
maven-archetype-webapp 创建一个Maven Web项目

更多的原型可以到http://maven.apache.org/archetypes/查看。

在Intellij中选择File–New–Project,在右边的列表中选择Maven,可以看到列出了很多可以用的Archetypes,除了Apache的,还有很多第三方的原型。选中Create from archetype,然后在列表中选择org.apache.maven.archetypes:maven-archetype-quickstart,之后选择Next,会让你填入GAV。之后指定Maven的配置文件和本地库目录,之后是项目名称都能内容,最后点击Finish之后,就可以创建一个Maven项目。然后可以发现,Intellij自动开始下载Maven包和相关依赖。下载完成之后,会提示[INFO] Generating project in Batch mode,然后一堆信息后看到[INFO] Maven execution finished,项目就创建完毕了,可以发现,除了IDE的.idea目录之外,自动生成了src/main/java/cc/conyli/App.javasrc/test/java/cc/conyli/AppTest.java。同时自动创建了pom.xml文件,其中的GAV就是之前填写的内容,自动添加了JUnit包,还自动添加了很多插件。这样就创建好了一个最简单的Maven项目。

再来选择maven-archetype-webapp创建一个Web应用,可以发现除了pom.xml之外,还自动创建了src/main/webapp/index.jspsrc/main/webapp/WEB-INF/web.xml。此时添加好Tomcat服务器然后启动服务器,可以发现自动生成了Target目录,然后项目正常启动了。Intellij没有使用原来的out目录。

Intellij右下角提示Maven配置变动,如果自动检测,则会在pom.xml发生变化的时候去自动下载对应的包。

Maven Repository 仓库设置

Maven仓库在之前设置了一个本地仓库,外边下来的包都会保存到这里。那么Maven是到哪里下载的包呢?Maven实际上是去https://maven.apache.org/的中央仓库进行下载。

https://mvnrepository.com/的右侧可以看到Indexed Repositories,有很多,其中除了Central之外,还有很多库,如何让Maven使用这些库呢。

比如要为新创建的Web应用引入atlassian-mail库,这个库仅在Atlassian仓库内可用,需要在pom.xml内进行设置:

<repositories>
    <repository>
      <id>atlassian</id>
      <name>Atlassian Repository</name>
      <url>https://maven.atlassian.com/content/repositories/atlassian-public/</url>
    </repository>
</repositories>

上边是添加一个仓库,这个标签是直接在project标签下的。然后需要在dependencies添加一个新的dependency标签:

<dependency>
  <groupId>com.atlassian.mail</groupId>
  <artifactId>atlassian-mail</artifactId>
  <version>4.0.4</version>
</dependency>

如果开启了Intellij的自动检测配置文件变化,此时Intellij就会开始下载这个库文件了。在External Libraries就可以发现新下载回来的库文件。

还有一个知识点就是私有仓库,非开源代码不会直接推送的Maven的中央库去,一般都由一个特定的组织管理。

常用的创建一个仓库的工具是由Apache提供的Archiva,类似的工具还有JFrogNexus

这里只是简单提一下私有仓库供了解,在一个公司内部,公司会有相应的Maven配置指导。

将增删改查项目迁移到Maven中来

首先需要确定项目的所有依赖,看了一下有如下依赖:

  1. MySQL-connectorJ-5.1.47
  2. JSTL-1.2.1
  3. Spring 5.0.2RELEASE
  4. Hibernate-core-5.4.1Final
  5. Hibernate-validator-6.0.15Final
  6. C3PO-0.9.5.2
  7. AspectJWeaver-1.8.14

应该是全了,通过Intellij新建一个Maven项目,就叫basecrud,等候项目创建完毕有了基础的路径之后,先将原来项目中的cc.conyli中的所有包复制到新项目的src/main/java目录内,将原项目的web/resources目录内的内容复制到新项目的src/main/目录下,将原项目的WEB-INF目录中除了lib以外的内容都复制到新项目的WEB-INF目录内,删除原来WEB-INF目录下的index.jsp文件。

启动项目发现启动不了,很显然因为还没有配置任何库,所以web.xml启动不了Spring的前端转发器。

然后打开pom.xml一个一个的配置依赖,这里可以将一些配置的版本号抽取出来,然后进行配置:

<properties>
    <springframework.version>5.1.5.RELEASE</springframework.version>
    <hibernate.version>5.4.1.Final</hibernate.version>
    <mysql.connector.version>5.1.47</mysql.connector.version>
    <c3po.version>0.9.5.2</c3po.version>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
</properties>

之后是Spring的配置,由于包之间也有依赖关系,Web开发只需配置Spring webmvc包,core等其他包的依赖会自动导入,然后还有tx和orm用于对接Hibernate持久化:



<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${springframework.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${springframework.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>${springframework.version}</version>
</dependency>

其他包的配置如下:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>${mysql.connector.version}</version>
</dependency>

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>${hibernate.version}</version>
</dependency>

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.15.Final</version>
</dependency>

<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>${c3po.version}</version>
</dependency>

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.14</version>
</dependency>

这里注意要把resources文件放到src/main/webapp/下边,main/resources是一个特殊的目录,是这个项目的一些资源,其中的内容会被放到target/classes目录内。

任何配置都不用修改,直接启动项目,就可以发现我们的项目变成了Maven项目。