zoukankan      html  css  js  c++  java
  • Web基础之Maven

    Web基础之Maven

    Maven是一个优秀的项目管理工具,可以很轻松的管理项目。

    POM和LifeCycle

    POM:Project Object Model。也就是项目模型,简单来说就是对项目进行建模,既然是建模,那就会有一些属性来定义这个项目。而配置文件pom.xml就是以xml形式描述这个建模,所以里面会有一些项目特定的属性,比如:groupId、artifactId、version……

    那么Lifecycle又是什么呢?翻译过来就是生命周期,在项目构建过程中有着不同的阶段(phase),总共有多少个阶段呢?

    一个标准的Lifecycle有着以下几个阶段:

    validate: 用于验证项目的有效性和其项目所需要的内容是否具备
    initialize:初始化操作,比如创建一些构建所需要的目录等。
    generate-sources:用于生成一些源代码,这些源代码在compile phase中需要使用到
    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:打包
    pre-integration-test:集成测试前置操作   
    integration-test:集成测试
    post-integration-test:集成测试后置操作
    install:将打包产物安装到本地maven仓库
    deploy:将打包产物安装到远程仓库
    

    在执行任意一个阶段时,之前的每个阶段都会执行。

    注意,以上的每个阶段只是一个约定,并没有说每个阶段具体干什么。这有点类似接口,约定了一个项目需要有这些过程,但是每个过程具体干什么需要由我们自己去指定。这里再引入一个概念MOJO。什么是MOJO,官方解释是可执行的goal(目标),下面是stackoverflow上的高票答案:

    What is a Mojo? A mojo is a Maven plain Old Java Object. Each mojo is an executable goal in Maven, and a plugin is a distribution of one or more related mojos.

    In short, a mojo is a maven goal, to extend functionality not already found in maven.

    翻译一下就是MOJO就是一个可执行对象(goal,目标),这个对象可以获得已经在maven里面定义过的功能。而我们需要做的就是把这个可执行对象和具体的阶段绑定起来。

    在哪里绑定呢?在pom.xml里面的<build>属性里,因此一个plugins如下:

    <!--使用的插件列表 。 -->
    <plugins>
        <plugin>
            <groupId></groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.5.5</version>
    
            <!--在构建生命周期中执行一组目标的配置。每个目标可能有不同的配置。 -->
            <executions>
                <execution>
    
                    <!--执行目标的标识符,用于标识构建过程中的目标,或者匹配继承过程中需要合并的执行目标 -->
                    <id>assembly</id>
    
                    <!--绑定了目标的构建生命周期阶段,如果省略,目标会被绑定到源数据里配置的默认阶段 -->
                    <phase>package</phase>
    
                    <!--配置的执行目标 -->
                    <goals>
                        <goal>single</goal>
                    </goals>
    
                    <!--配置是否被传播到子POM -->
                    <inherited>false</inherited>
    
                </execution>
            </executions>
    
            <!--作为DOM对象的配置,配置项因插件而异 -->
            <configuration>
                <finalName>${finalName}</finalName>
                <appendAssemblyId>false</appendAssemblyId>
                <descriptor>assembly.xml</descriptor>
            </configuration>
    
            <!--是否从该插件下载Maven扩展(例如打包和类型处理器), -->
            <!--由于性能原因,只有在真需要下载时,该元素才被设置成true。 -->
            <extensions>false</extensions>
    
            <!--项目引入插件所需要的额外依赖 -->
            <dependencies>
                <dependency>...</dependency>
            </dependencies>
    
            <!--任何配置是否被传播到子项目 -->
            <inherited>true</inherited>
    
        </plugin>
    </plugins>
    

    上例就将single这个goal绑定到了package这个phase。

    这样虽然指定了要做什么,但是并没有在哪做、用什么做。这里需要说一下Maven的理念就是convention over configuration(约定优于配置)。这一点和ant有非常大的区别,例如使用ant来进行编译时,我们需要指定源文件的位置,输出文件的位置,javac的位置,classpath... ...在maven中这些都是不需要,若没有手动配置,maven默认从<项目根目录>/src/main/java这个目录去查找Java源文件,编译后的class文件会保存在<项目根目录>/target/classes目录。在maven中,所有的PO都有一个根对象,就是Super POM。Super POM中定义了所有的默认的配置项。Super POM对应的pom.xml文件可以在maven安装目录下lib/maven-model-builder-3.0.3.jar:org/apache/maven/model/pom-4.0.0.xml中找到。

    参考Maven内部原理解析


    简单使用

    仓库

    Maven将所有的jar包都集中在一个叫做“仓库”的地方,一个Maven项目需要使用到某个jar包时会在其项目中指向这个jar包,具体表现就是pom.xml中添加了坐标。

    仓库分为本地、私服、远程仓库。就像瓶子里没有盐了就去柜子里找,柜子里也没有的话那就只能去超市买了,瓶子、柜子、超市分别对应本地仓库、私服、远程公共仓库。

    生命周期

    maven拥有三套相互独立的生命周期,分别是cleandefaultsite。clean 生命周期的目的是清理项目 ,default 生命周期的作用是构建项目 ,site 生命周期的目的是构建项目站点 。每个生命周期都有各自的阶段,上面罗列出的是default的各个阶段。下面是几个比较重要的阶段:

    clean生命周期

    clean生命周期的目的是清理项目,它包含三个阶段:

    1. pre-clean 执行一些清理前需要完成的工作;
    2. clean 清理上一次构建生成的文件;
    3. post-clean 执行一些清理后需要完成的工作;

    default生命周期

    ​default生命周期定义了真正构建项目需要执行的所有步骤,它是所有生命周期中最核心的部分。其中的重要阶段如下:

    1. compile :编译项目的源码,一般来说编译的是src/main/java目录下的java文件至项目输出的主classpath目录中;
    2. test :使用单元测试框架运行测试,测试代码不会被打包或部署;
    3. package :接收编译好的代码,打包成可以发布的格式,如jar和war;
    4. install: 将包安装到本地仓库,共其他maven项目使用;
    5. deploy :将最终的包复制到远程仓库,供其他开发人员或maven项目使用;

    site生命周期

    ​site生命周期的目的是建立和发布项目站点,maven能够基于pom文件所包含的项目信息,自动生成一个友好站点,方便团队交流和发布项目信息。该生命周期中最重要的阶段如下:

    1. site :生成项目站点文档;

    maven可以使用命令行直接调用命令。
    Maven 命令:

    mvn clean:调用clean生命周期的clean阶段,清理上一次构建项目生成的文件;
    mvn compile :编译src/main/java中的java代码;
    mvn test :编译并运行了test中内容 ;
    mvn package:将项目打包成可发布的文件,如jar或者war包; 
    mvn install :发布项目到本地仓库 ;
    

    pom.xml介绍

    <!-- xml文档声明 -->
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 
        xmlns即xml name space, 本xml命名空间(命名空间出现是为了防止xml出现冲突)
        xmlns:xsi, 约定了前缀为xsi对应的唯一字符串,即Schema约束(xsd)命名空间(业界默认)
        xsi:schemaLocation, 这一行其实是 xsi:schemaLocation = "键" “值” 的形式,即 xsi 命名空间下 schemaLocation 元素的值为一个由空格分开的键值对。
        不过这些定义不是太重要
     -->
     <!-- project pom文件的根节点 -->
    <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>: 声明项目描述符遵循哪一个POM模型版本。模型本身的版本很少改变,虽然如此,但它仍然是必不可少的,目前POM模型版本是4.0.0 -->
        <modelVersion>4.0.0</modelVersion>
    
        <!-- <groupId> :maven项目组织id标识符,一般是公司域名倒过来写 -->
        <groupId>com.bilibili.maven</groupId>
    
        <!-- <artifactId>:项目的标识符,即项目名 -->
        <artifactId>maven-web2</artifactId>
    
        <!-- <version>:项目的版本号 -->
        <version>1.0-SNAPSHOT</version>
    
        <!-- <packaging>:maven项目的打包方式一般配置jar或者war -->
      	<packaging>war</packaging>
    </project>
    

    xml头部声明参考这篇博客

    对于jar、war:

    Jar文件(扩展名为. Jar,Java Application Archive)包含Java类的普通库、资源(resources)、辅助文件(auxiliary files)等
    War文件(扩展名为.War,Web Application Archive)包含全部Web应用程序。在这种情形下,一个Web应用程序被定义为单独的一组文件、类和资源,用户可以对jar文件进行封装,并把它作为小型服务程序(servlet)来访问。
    Ear文件(扩展名为.Ear,Enterprise Application Archive)包含全部企业应用程序。在这种情形下,一个企业应用程序被定义为多个jar文件、资源、类和Web应用程序的集合。
    每一种文件(.jar, .war, .ear)只能由应用服务器(application servers)、小型服务程序容器(servlet containers)、EJB容器(EJB containers)等进行处理。

    参考

    依赖管理

    Maven的一个核心功能就是管理项目依赖。在<dependencies>标签中可以添加如下三个参数就能确定一个依赖的具体信息

    <dependency>
        <!-- 项目组 -->
        <groupId>mysql</groupId>
        <!-- 项目名 -->
        <artifactId>mysql-connector-java</artifactId>
        <!-- 版本号 -->
        <version>5.1.47</version>
    </dependency>
    

    在idea的pom.xml文件中用快捷键alt + insert可以快速添加本地依赖。
    本地没有的话可以在这个网站搜索

    依赖配置

    添加依赖之后还需要对依赖进行配置,比如确定 依赖范围依赖版本维护等。

    Maven中有以下5种典型的依赖范围:

    • compile :编译依赖范围。如果没有指定,默认就是这种依赖范围。使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。
    • test :测试依赖范围。使用此依赖范围的Maven依赖,只对测试classpath有效。在编译主代码和运行项目期间都不需要使用此依赖。典型的例子就是Junit,它只在编译和运行测试代码时有效。
    • provided :已提供依赖范围。使用此依赖范围的maven依赖在编译和测试classpath有效,但运行时无效。典型的例子就是servlet-api。编译和测试的时候需要使用servlet-api中的方法,但是使用tomcat运行项目的时候不需要,因为tomcat在运行期间会提供这个依赖。
    • runtime: 运行时依赖范围。使用次依赖范围的maven依赖对于测试和运行classpath有效,但在编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要提供JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。
    • system :系统依赖范围。该依赖与三种classpath的关系和provided依赖范围完全一致。但是,使用system范围的依赖时必须通过systemPath元素显式地指定依赖文件的路径。由于此依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用。systemPath元素可以引用环境变量。

    system 类型的依赖有个典型的例子就是oracle的驱动包,从中央仓库无法下载,需要先下载到本地,再通过本地路径引入。

    <dependency>
      <groupId>oracle</groupId>
      <artifactId>ojdbc</artifactId>
      <version>1.0</version>
      <scope>system</scope>
      <!-- 必须指定systemPath -->
      <systemPath>D:/software/maven/apache-maven-3.5.2/repository/ojdbc6.jar</systemPath>
    </dependency>
    

    依赖范围与classpath的关系如下:

    依赖 对于编译classpath有效 对于测试classpath有效 对于运行时classpath有效 例子
    compile Y Y Y spring-core
    test - Y - Junit
    provided Y Y - servlet-api
    runtime - Y Y JDBC驱动
    system Y Y - 本地的,maven仓库之外的类库

    指定依赖的方式很简单,只需在<dependency>标签中使用<scope>设置即可。

    示例
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>4.3.9.RELEASE</version>
      <!--compile是默认的依赖范围,可以不用写出来-->
      <scope>compile</scope>
    </dependency>
    
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.0.8</version>
      <scope>runtime</scope>
    </dependency>
    
    <dependency>
      <groupId>oracle</groupId>
      <artifactId>ojdbc</artifactId>
      <version>1.0</version>
      <scope>system</scope>
      <systemPath>D:/software/maven/apache-maven-3.5.2/repository/ojdbc6.jar</systemPath>
    </dependency>
    

    如果pom.xml文件中的依赖太多不便于统一管理,因此可以将版本号抽象出来同一管理:

    示例
    <properties>
      <spring.version>4.2.4.RELEASE</spring.version>
      <struts.version>2.3.8</struts.version>
    
      <!-- IDEA中输入junit.version自动补全为下面的方式 -->
      <junit class="version">4.11</junit>
    </properties>
    
    <dependencies>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.apache.struts</groupId>
        <artifactId>struts2-spring-plugin</artifactId>
        <version>${struts.version}</version>
      </dependency>
    </dependencies>
    

    插件

    如上面所说,Maven核心并没有什么功能,它的本质就是一个插件框架,所有的功能都是由插件来完成。同时官方提供了一些默认的插件,如果需要配置自己的插件,也可使引入坐标来实现。

    官方的插件列表
    
    http://maven.apache.org/plugins/index.html
    http://mojo.codehaus.org/plugins.html
    

    一个编译插件的例子:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.2</version>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
            <encoding>UTF-8</encoding>
        </configuration>
    </plugin>
    

    清理文件
    由于网络原因仓库中可能存在以lastUpdated结尾的文件导致jar包导入失败,用everything搜一下删除就好了。
    更新依赖
    有时候配置了仓库后找不到jar包,此时需要在idea中更新仓库依赖:setting -> build -> buildTools -> maven -> repositories -> update


    具体pom.xml的细节可以百度(。・ω・。)


    这里放一个设置maven使用jdk 1.8的设置:

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
  • 相关阅读:
    Abp vNext 模块化系统简单介绍
    CLR via C# 笔记 -- 计算限制的异步操作(27)
    CLR via C# 笔记 -- 线程基础(26)
    Redis 入门
    .NET Core 中生成验证码
    CLR via C# 笔记 -- 异常和状态管理(20)
    CLR via C# 笔记 -- 托管堆和垃圾回收(21)
    CLR via C# 笔记 -- 字符、字符串、文本处理(14)
    广州公司黑名单
    总博客教程全导航
  • 原文地址:https://www.cnblogs.com/lixin-link/p/11251128.html
Copyright © 2011-2022 走看看