Fork me on GitHub

Maven

本节内容:

  • Maven的简介
  • Maven的安装配置
  • 入门程序
  • 项目构建
  • 依赖管理

 

一、Maven的简介

1. 什么是maven

是apache下的一个开源项目,是纯java开发,并且只是用来管理java项目的。它是要给项目管理工具,使用maven对java项目进行构建、依赖管理。

 

2. 什么是项目构建

项目构建是一个项目从编写源代码到编译、测试、运行、打包、部署、运行的过程。

(1)传统项目的构建过程

  1. 在Eclipse等IDE中创建一个java web工程
  2. 在工程中编写源代码及配置文件等
  3. 对源代码进行编译,java文件编译成class文件
  4. 执行Junit单元测试
  5. 将工程打成war包部署至tomcat或其他中间件中运行

 

(2)maven项目构建过程

maven将项目构建的过程进行标准化,每个阶段使用一个命令完成,下图展示了构建过程中的一些阶段:

上图中部分阶段对应命令如下:

  • 清理阶段对应maven的命令是clean,清理已经输出的class文件
  • 编译阶段对应maven的命令是compile,将java代码编译成class文件
  • 打包阶段对应maven的命令是package,java工程可以打成jar包,web工程可以打成war包

运行一个maven工程(web工程)需要一个命令:tomcat:run

比如,有个基于maven管理的java项目:maven-helloworld,里面存放的都是java源代码。一条命令就可以跑起来了(即使你的电脑没有安装IDE工具,没有安装tomcat。maven可以去仓库里下载编译插件、tomcat插件):

 

3. maven的好处

  • 一个命令完成构建、运行,方便便捷
  • 一键构建,见上面的示例
  • 应用于大型项目,可以提高效率
    • 举个例子,比如京东商城,分为用户管理、订单管理、支付管理等等。对于我们看到的是同一个项目,但是在他们开发的时候是分成不同的项目来做的。一个开发人员只会属于一个项目,别的都接触不到,毕竟大公司,分工细。
    • 项目和项目之间是没有关系的,但是订单管理和支付管理需要用到用户的信息,如何产生关联呢?把用户管理这个项目打成一个jar包,扔到订单管理这个项目里。
    • 假如这几个项目放在同一个项目里,那么部署用户管理,订单管理和支付管理也是需要编译的,做用户管理的人只关注用户管理,还要编译订单管理和支付管理,浪费时间。如果以jar包的形式存在,就不需要浪费时间了,jar里面都是class文件。
    • 这就是maven里的分模块开发。
    • 补充:互联网项目和传统项目的分模块开发是不一样的。互联网项目按业务分模块开发;传统项目按层分:entity、dao、service、web
  • maven项目体积小

对于上面的“maven项目体积小”,来做个对比:

普通的传统项目:

Maven项目:

maven项目为什么这么小?因为没有jar包。 需要jar吗?肯定需要。jar包没有存在于maven项目里面,jar包存在于哪?

比如,下面是本地的一个maven仓库。这个找的过程,是maven中的配置文件中写好了,不是我们自己找的。

当然,随着这个本地仓库越来越大,找起来也是需要一定的时间。maven仓库也有索引的概念,索引的目的就是提高查询速度。这样项目在本地仓库找jar包会非常快捷。

为什么要本地maven仓库?

  本地可能有多个项目,比如项目一和项目二都用的ssh框架,那么它们用的jar就都是一样的。如果不用maven仓库,这些jar包得存在于两个项目里。有个本地仓库,就不需要在每个项目里拷贝一大堆jar包了。

 

4. 依赖管理

(1)什么是依赖管理

什么是依赖?一个java项目可能要使用一些第三方的jar包才可以运行,那么我们说这个java项目依赖了这些第三方的jar包。

比如一个crm系统,它的架构是SSH框架,该crm项目依赖SSH框架,具体它依赖的是Hibernate、Spring、Struts2。

什么是依赖管理?就是对项目所有依赖的jar进行规范化管理。

 

(2)传统项目的依赖管理

传统的项目工程要管理所依赖的jar包完全靠人工进行,程序员从网上下载jar包添加到项目工程中,如下图,程序员手工将Hibernate、Struts2、Spring的jar添加到工程的 WEB-INF/lib 目录下。

手工拷贝jar包添加到工程中的问题有:

  • 没有对jar包的版本统一管理,容易导致版本冲突
  • 从网上找jar包非常不方便,有些jar找不到
  • jar包添加到工程中导致工程过大

 

(3)maven项目的依赖管理

maven项目管理依赖的jar不需要手动向工程里添加jar包,只需要在 pom.xml(maven工程的配置文件)添加jar包的坐标,自动从maven仓库中下载jar包、运行,如下图:

使用maven依赖管理添加jar的好处:

  • 通过pom.xml文件对jar包的版本进行统一管理,可避免版本冲突
  • maven团队维护了一个非常全的maven仓库,里面包括了的当前使用的jar包,maven工程可以自动从maven仓库下载jar包,非常方便

 

二、Maven的安装配置

1. 下载安装

(1)下载

下载地址:http://maven.apache.org/download.cgi

 

(2)解压

解压后目录如下:

  • bin目录:mvn.bat/mvn.sh(以run方式运行项目)、mvDebug.bat/mvnDebug.sh(以debug方式运行项目)
  • boot目录:maven运行需要类加载器
  • conf目录:settings.xml是整个maven工具核心配置文件
  • lib目录:maven运行依赖的jar包

 

2. maven环境变量配置

需要安装配置JDK7+。

以windows为例:

在系统变量添加环境变量的名称:MAVEN_HOME。变量值:就是maven软件解压的目录,比如F:\class32\apache-maven-3.3.9

将 %MAVEN_HOME%/bin 加入到环境变量Path

 

验证maven是否配置成功:

打开dos窗口 输入: mvn –v

 

3. maven仓库介绍及配置

maven的工作需要从仓库下载一些jar包,如下图所示,本地项目A和项目B等都会通过maven软件从远程仓库(可以理解为互联网上的仓库)下载jar包并存于本地仓库,本地仓库就是本地文件夹。当第二次需要此jar包时则不再需要从远程仓库下载,因为本地仓库已经存在了,可以将本地仓库理解为缓存,有了本地仓库就不用每次从远程仓库下载了。

  • 本地仓库:用来存储从远程仓库或中央仓库下载的插件和jar包,项目使用一些插件或jar包,优先从本地仓库查找。--自己维护
    • 默认本地仓库位置在${user.dir}/.m2/repository,下载的jar包都会放在这个目录。${user.dir}表示windows用户目录。
    • 配置本地仓库只需要修改 ${MAVEN_HOME}/conf/settings.xml 文件就可以,如下图

 

  • 远程仓库(私服):如果需要的插件或者jar包本地仓库没有,默认去远程仓库下载。远程仓库可以在互联网内,也可以在局域网内。 --公司维护
  • 中央仓库:在maven软件中内置了一个远程仓库地址 http://repo1.maven.org/maven2,它是中央仓库,服务于整个互联网,它由Maven团队维护,里面存储了非常全的jar包,它包含了世界上大部分流行的开源项目构件,大概两个亿个jar包。

 

三种仓库的关系如下:

 

三、入门程序

(1)入门程序(以Mac上IDEA为例演示)

安装maven,配置好maven环境变量,配置 ${MAVEN_HOME}/conf/settings.xml 中的本地仓库位置。

打开IntellJ IDEA,先配置好JDK和Maven。点击File—>New—>Project,左侧菜单选择“Maven”。

填写GroupID和ArtifactID。

  • GroupID是项目组织唯一的标识符,实际对应JAVA的包的结构,是main目录里java的目录结构。
  • ArtifactID就是项目的唯一的标识符,实际对应项目的名称,就是项目根目录的名称。
  • 一般GroupID就是填com.leafive.test这样子。

  groupid和artifactId被统称为“坐标”是为了保证项目唯一性而提出的,如果你要把你项目弄到maven本地仓库去,你想要找到你的项目就必须根据这两个id去查找。
  groupId一般分为多个段,这里我只说两段,第一段为域,第二段为公司名称。域又分为org、com、cn等等许多,其中org为非营利组织,com为商业组织。举个apache公司的tomcat项目例子:这个项目的groupId是org.apache,它的域是org(因为tomcat是非营利项目),公司名称是apache,artigactId是tomcat。

选择本地安装的maven软件,本地仓库等信息。

输入项目名称。

 

这就创建了一个基于Maven的web项目了。

创建Java程序目录。点击工具栏的“project structure”。

 

把java目录设置为Sources。选中java文件夹,点击上面的Make as:Sources,该文件夹就会变成蓝色,用以保存java代码,按OK。

编写java代码。新建一个包

package com.wisedu.demo;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by jkzhao on 11/30/17.
 */

public class ServletTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        req.getRequestDispatcher("/jsp/test.jsp").forward(req, resp);
    }

}
ServletTest.java
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

    <display-name>Archetype Created Web Application</display-name>

    <!-- 配置servlet -->
    <servlet>
        <servlet-name>servletTest</servlet-name>
        <servlet-class>com.wisedu.demo.ServletTest</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletTest</servlet-name>
        <url-pattern>/test</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>

</web-app>
web.xml
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>第一个maven工程</title>
</head>
<body>
第一个maven工程,运行了一个servlet
</body>
</html>
test.jsp

Mac上打开终端,进去这个项目目录下:

访问:http://localhost:8080/mvnDemo/test 

 

(2)Maven项目工程目录约定

 

(3)Maven常用命令

  • compile:compile是maven工程的编译命令,作用是将 src/main/java 下的文件编译为class文件输出到 target 目录下。windows上打开cmd(linux或Mac上打开xshell终端),输入命令:mvn compile。命令执行完,在 src 同级目录,可以看到 target 文件夹,里面都是编译好的class文件。
  • test:test是maven工程的测试命令,会执行 src/test/java 下的单元测试类。windows上打开cmd(linux或Mac上打开xshell终端),输入命令:mvn test 
  • clean:clean是maven工程的清理命令,执行clean会删除 target 目录的内容。
  • package:package是maven工程的打包命令,对于java工程执行 package 命令会打成jar包,对于web工程打成war包。
  • install:install是maven工程的安装命令,执行install将maven打成jar包或war包发布到本地仓库。

 

(4)生命周期(了解)

 三套生命周期:maven对项目构建过程分为三套相互独立的生命周期,注意这里说的是“三套”,而且“相互独立”,这三套生命周期分别是:

  1. Clean Lifecycle:在进行真正的构建之前进行一些清理工作;
  2. Default Lifecycle:构建的核心部分,编译、测试、打包、部署等等。
  3. Site Lifecycle:生成项目报告,站点,发布站点。

 

生命周期的阶段

每个生命周期都有很多阶段,每个阶段对应一个执行命令。

  • 如下是clean生命周期的阶段:
    • pre-clean:执行一些需要在clean之前完成的工作
    • clean:移除所有上一次构建生成的文件
    • post-clean:执行一些需要在clean之后立刻完成的工作
  • 如下是default生命周期的阶段:
    • validate
    • generate-sources
    • process-sources
    • generate-resources
    • process-resources 复制并处理资源文件,至目标目录,准备打包
    • compile 编译项目的源代码
    • process-classes
    • generate-test-sources
    • process-test-sources
    • generate-test-resources
    • process-test-resources 复制并处理资源文件,至目标测试目录
    • test-compile 编译测试源代码
    • process-test-classes
    • test 使用合适的单元测试框架进行测试。这些测试代码不会被打包或部署
    • prepare-package
    • package 接受编译好的代码,打包成可发布的格式,如JAR
    • pre-integration-test
    • integration-test
    • post-integration-test
    • verify
    • install 将包安装至本地仓库,以让其它项目依赖
    • deploy 将最终的包复制到远程的仓库,以让其它开发人员与项目共享
  • 如下是site生命周期的阶段
    • pre-site:执行一些需要在生成站点文档之前完成的工作
    • site:生成项目的站点文档
    • post-site:执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
    • site-deploy:将生成的站点文档部署在特定的服务器上。

 

命令与生命周期的阶段:

每个maven命令对应生命周期的某个阶段,例如:mvn clean 命令对应clean生命周期的clean阶段,mvn test 命令对应default生命周期的test阶段。

执行命令会将该命令在的生命周期当中之前的阶段自动执行,比如:执行mvn clean 命令会自动执行 pre-clean 和 clean 两个阶段,执行mvn test命令会自动执行 validate、compile、test等阶段。

【注意】:执行某个生命周期的某个阶段不会影响其它的生命周期。

如果要同时执行多个生命周期的阶段可在命令行输入多个命令,中间以空格隔开,例如:mvn clean package,该命令执行clean生命周期的clean阶段和default生命周期的package阶段。

 

(5)maven的概念模型

 Maven包含了一个项目对象模型(Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。

下图是maven的概念模型图:

  • 项目对象模型(Project Object Model) 
    • 一个maven工程都有一个pom.xml文件,通过pom.xml文件定义项目的坐标、项目依赖、项目信息、插件目标等。
  • 依赖管理系统(Dependency Management System) 
    • 通过maven的依赖管理对项目所依赖jar包进行统一管理。
    • 比如:项目依赖junit 4.9,通过pom.xml中定义junit 4.9的依赖即使用junit 4.9,如下图所示是定义junit 4.9的依赖定义:

 

  • 一个项目生命周期(Project Lifecycle)
    • 使用maven完成项目的构建,项目构建包括:清理、编译、测试、部署等过程,maven将这些过程规范为一个生命周期,如下所示是生命周期的各个阶段
    • maven通过执行一些简单的命令即可实现上边生命周期的各个过程。

 

  • 一组标准集合
    • maven将整个项目管理过程定义一组标准,比如:通过maven构建工程有标准的目录结构,有标准的生命周期阶段、依赖管理有标准的坐标定义等。

 

  • 插件(plugin)目标(goal)
    • maven管理项目生命周期过程都是基于插件完成的。

 

四、项目构建

1. m2e插件安装配置

使用命令行的方式使用maven工作效率不高,可以在eclipse开发工具中集成maven软件,eclipse是一个开发工具,maven是一个项目管理工具,maven有一套项目构建的规范,在eclipse中集成maven插件,最终通过eclipse创建maven工程。

我使用的eclipse自带maven插件,不用单独安装。点击File—>New—>Other,可以看到maven项目的创建项,表示maven插件已存在,如下图:

 

2. 指定maven安装目录

一些高版本的eclipse已经内置了maven的安装,下图是我使用的eclipse版本中已经内置了的 maven3.3.9 版本, 项目为了统一不会使用eclipse内置的maven版本,这里我们用的是maven 3.3.9

 

3. User Setting 配置

修改默认的本地仓库地址。

【注意】:如果修改了 setting.xml 文件需要点击上图中的“Update Settings”按钮对本地仓库重建索引,点击“Reindex”。

 

4. eclipse浏览仓库

maven配置完成后,需要测试在eclipse中是否可以浏览maven的本地仓库,如果可以正常浏览maven本地仓库则说明eclipse集成maven已经完成。

点击eclipse菜单栏的 windows—> Show View—>Other,输入maven:

找到 Local repository 本地仓库选项,点击 Rebuild index 重建索引。

重建索引完成后,点击前面的“+”图标,可查看本地仓库的内容,如下图:

 

5. 定义maven坐标

每个maven工程都需要定义本工程的坐标,坐标是maven对jar包的身份定义,比如

  <!-- 项目名称:定义为组织名+项目名,类似包名 -->
  <groupId>com.wisedu</groupId>
  <!-- 模块名称 -->
  <artifactId>mvnDemo</artifactId>
  <!-- 当前项目版本号,snapshot为快照版本即非正式版本,release为正式发布版本 -->
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>
  <!-- 打包类型,jar:执行package命令会打成jar包; war:打成war包; pom:用户maven工程的继承,通常父工程设置为pom -->
pom.xml

 

6. 构建maven项目(以eclipse演示)

(1)File—>New—>Other,输入maven,选择“Maven Project”

了解下骨架界面:当我们不跳过骨架点击“next”会进入骨架选择界面,如果eclipse中配置本地仓库正确则显示出骨架

【注意】:使用骨架的问题是创建maven工程目录不完整,所以不推荐使用。

 

(2)定义坐标

 

(3)处理红色叉号

手动在webapp文件夹下创建一个WEB-INF文件夹,在里面放一个web.xml文件。但是项目还是红的。这是因为需要设置编译版本。

 

(4)设置编译版本

查看上边工程的“Libraries”,显示的是JDK1.5,这里我使用JDK1.7,需要设置编译版本为1.7,这里需要使用maven插件来设置。

在pom.xml中添加如下代码:

 <build>
    <finalName>mvnDemo</finalName>
      <!-- 配置了很多插件 -->
      <plugins>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.5.1</version>
              <configuration>
                  <source>1.7</source>
                  <target>1.7</target>
                  <encoding>UTF-8</encoding>
              </configuration>
          </plugin>

      </plugins>
  </build>

选中项目“helloworld”,鼠标右键选择“Maven”—>"Update project"。然后点开“Libraries”,可以看到变为1.7了。

 

(5)编写Servlet

在 src/main/java 下创建package和Servlet

package com.wisedu.hello;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class ServletTest
 */
public class ServletTest extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * Default constructor. 
     */
    public ServletTest() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.getWriter().append("Served at: ").append(request.getContextPath());
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}
ServletTest.java

但是你会发现里面报红很多,因为没有jar包。

还有web.xml也报错了,因为你创建Servlet的时候,它去修改了web.xml文件。

 

(6)添加jar包

添加jar包的方式不再是之前那样创建一个lib文件夹,把需要的jar包放进去。

在pom.xml中添加如下代码

      <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
        
    </dependencies>

点击保存,然后你就会发现jar包已添加到项目中:

 

(7)启动项目

右击项目—>Run As—>Maven build…

浏览器访问:http://localhost:8080/helloworld/ServletTest

 

五、依赖管理

就是jar包的管理。

1. 添加依赖

在pom.xml中添加<dependency>标签,如下:

<dependency>
    <groupId></groupId>
    <artifactId></artifactId>
    <version></version>
    <scope></scope>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.9</version>
    <scope>test</scope>
</dependency>
依赖示例

 

2. 查找坐标

添加依赖需要指定依赖jar包的坐标,但是很多情况我们是不知道jar包的坐标,可以通过如下方式查询:

(1)方式一:从互联网搜索

  • http://search.maven.org/
  • http://mvnrepository.com/

网站搜索示例:以http://mvnrepository.com/为例:

 

(2)方式二:使用maven插件的索引功能

如果在本地仓库有我们要的jar包,可以在pom.xml中直接添加依赖。

在Eclipse中,选中项目,右键选择“Maven”—>“Add Dependency”。

点击OK后,就可以看到pom.xml中加入了相应的代码。

 

3. 依赖范围

A依赖B,需要在A的pom.xml中添加B的坐标,添加坐标时需要指定依赖范围,依赖范围包括:

  • compile:编译范围,指A在编译时依赖B,此范围为默认依赖范围。编译范围的依赖会用在编译、测试、运行,由于运行时需要所以编译范围内的依赖会被打包。
  • provided:provided依赖只有在当JDK或者一个容器已经提供该依赖之后才使用,provided依赖在编译和测试时需要,在运行时不需要,所以打包时不需要。比如:servlet api被tomcat容器提供。
  • runtime:runtime依赖在运行和测试系统的时候需要,但在编译的时候不需要,比如jdbc驱动包。由于运行时需要所以runtime范围的依赖会被打包
  • test:test范围依赖 在编译和运行时都不需要(因为测试的代码都在 src/test/java/ 下面的代码,编译时编译的是 src/main/java/ 下的源代码),它们只有在测试编译和测试运行阶段可用,比如junit。由于运行时不需要,所以test范围依赖不会被打包。
  • system:system范围依赖 与provided类似,但是你必须显式的提供一个对于本地系统中JAR文件的路径,需要指定systemPath磁盘路径,system依赖不推荐使用。

依赖范围由强到弱的顺序是:compile>provided>runtime>test

 

4. maven添加插件

这也是可以通过修改插件来修改的:(上面的是默认的tomcat插件,不会出现在pom.xml中,但是修改别的tomcat插件,该插件的配置需要存在于pom.xml中)

在Eclipse中,选中项目,右键选择“Maven”—>“Add Plugin”。

点击OK后,查看pom.xml,多了该插件的配置代码。

如果需要修改端口,需要添加如下的配置:

 

posted @ 2018-04-27 11:35  暴走小骚年  阅读(744)  评论(0编辑  收藏  举报