Maven

Maven课程目标

  • 了解maven的基本简介

  • 掌握maven的下载、安装流程

  • 理解maven的基本概念(重点)

  • 动手完成第一个maven项目(重点)

  • 理解依赖管理(重点)

  • 理解生命周期与插件

一、Maven基础

1.1 maven简介

1.1.1传统项目管理状态分析

    前面我们通过 Web 阶段项目,要能够将项目运行起来,就必须将该项目所依赖的一些 jar 包添加到 工程中,否则项目就不能运行。试想如果具有相同架构的项目有十个,那么我们就需要将这一份 jar 包复制到十个不同的工程中。我们一起来看一个 CRM项目的工程大小。 使用传统 Web 项目构建的 CRM 项目如下:

此外还有一些其他的问题,比如jar包繁多,容易导致jar包版本不统一,引起jar包冲突的问题。

 1.1.2 什么是Maven

     Maven 的正确发音是[ˈmevən]。Maven 在美国是一个口语化的词语,代表专家、内行的意思。 一个对 Maven 比较正式的定义是这么说的:Maven 是一个项目管理工具,它包含了一个项目对象模型 (POM:Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标 (goal)的逻辑。

1.1.3 Maven的作用

  1. 我们需要引用各种 jar 包,尤其是比较大的工程,引用的 jar 包往往有几十个乃至上百个, 每用到一种 jar 包,都需要手动引入工程目录,而且经常遇到各种让人抓狂的 jar 包冲突,版本冲突。

  2. 世界上没有不存在 bug 的代码,计算机喜欢 bug 就和人们总是喜欢美女帅哥一样。为了追求美为了减少 bug,因此写完了代码,我们还要写一些单元测试,然后一个个的运行来检验代码质量。

  3. 再优雅的代码也是要出来卖的。我们后面还需要把代码与各种配置文件、资源整合到一起,定型打包,如果是 web 项目,还需要将之发布到服务器,供人蹂躏。试想,如果现在有一种工具,可以把你从上面的繁琐工作中解放出来,能帮你构建工程,管理 jar 包,编译代码,还能帮你自动运行单元测试,打包,生成报表,甚至能帮你部署项目,生成 Web 站点,你会心动吗? Maven 就可以解决上面所提到的这些问题

4.统一开发结构,提供标准了、统一的项目结构

1.2 Maven的下载和安装

官网:http://maven.apache.org/icon-default.png?t=N7T8http://maven.apache.org/

下载地址:http://maven.apache.org/download.cgiicon-default.png?t=N7T8http://maven.apache.org/download.cgi

为了使用 Maven 管理工具,我们首先要到官网去下载它的安装软件。通过百度搜索“Maven“如下:

进入官网,点击 Download 链接,就可以直接进入到 Maven 软件的下载页面  

 

点击Download,进入选择对应的下载版本:

注意:不同的MAVEN版本,跟IDEA之间也存在适配问题,所以大家在选择maven版本的时候,应该根据自己IDEA的版本选择对应的适配版本,适配版本如下:

  • IDEA 2022 兼容maven 3.8.1及之前的所用版本

  • IDEA 2021 兼容maven 3.8.1及之前的所用版本

  • IDEA 2020 兼容Maven 3.6.3及之前所有版本

  • IDEA 2018 兼容Maven3.6.1及之前所有版本

1.2.2 Maven的安装

 Maven下载后,将 Maven 解压到一个没有中文没有空格的路径下,比如 D:\software\maven 下面。 解压后目录结构如下:

在这里简单介绍一下各个文件的作用:

bin:存放了 maven 的命令,比如我们前面用到的 mvn tomcat:run

boot:存放了一些 maven 本身的引导程序,如类加载器等

conf:存放了 maven 的一些配置文件,如 setting.xml 文件

lib:存放了 maven 本身运行所需的一些 jar 包 至此我们的 maven 软件就可以使用了,前提是你的电脑上之前已经安装并配置好了 JDK。

1.2.2.1 maven及JDK的配置

我们所使用工具软件的统一,JDK 使用 JDK8版本。

  • JDK1.8版本安装之后,JDK配置JAVA_HOME  

  • 配置 MAVEN_HOME ,变量值就是你的 maven 安装 的路径(bin 目录之前一级目录)

  • 在环境变量的path目录里面还需要配置:

  • Maven 软件版本测试

通过 mvn -v命令检查 maven 是否安装成功,看到 maven 的版本为 3.5.2 及 java 版本为 1.8 即为安装 成功。 找开 cmd 命令,输入 mvn –v命令,如下图:

我们发现 maven 的版本,及 jdk 的版本符合要求,这样我们的 maven 软件安装就成功了。  

1.2.3 maven的基本概念

1.2.3.1 仓库

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

下图描述了maven仓库的类型:

  • 本地仓库 :用来存储从远程仓库或中央仓库下载的插件和 jar 包,项目使用一些插件或 jar 包,manen项目优先从本地仓库查找 默认本地仓库位置在 ,​{user.dir}表示 windows 用户目录。

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

注意:默认本地仓库在系统磁盘中,比较浪费系统盘空间,所以我们可以修改本地仓库的默认存放位置。这里我们准备了一个本地仓库,解压之后,放入任意盘符下面即可(不能包含中文路径)。解压之后的本地仓库名字(maven_repository)目录如下:  

在 MAVE_HOME/conf/settings.xml 文件中配置本地仓库位置(maven 的安装目录下):

打开 settings.xml文件,配置如下:  

 1.2.3.2 坐标

maven中的坐标用于描述仓库中资源的位置。https://mvnrepository.comicon-default.png?t=N7T8https://mvnrepository.com

  • Maven坐标的主要构成

    • groupId 定义当前maven项目隶属组织名称(通常是域名反写,例如org.mybatis)

    • artifactId 定义当前maven项目名称(通常是模块名称)

    • version 定义当前项目版本号

    • packaging 定义该项目的打包方式

  • Maven坐标的作用

​ 使用唯一标识,用来定位资源。通过该标识可以将资源的识别与下载交给机器完成。

1.2.3.3 镜像仓库  

在中央仓库直接下载通常会比较慢,所以我们在setting.xml文件中配置国内镜像仓库,来解决中央仓库资源下载慢的问题!

  •  在settings.xml配置文件中,配置阿里云镜像仓库
<mirror>
    <!-- mirror -->
    <id>nexus-aliyun</id>
    <!-- -->
    <mirrorOf>central</mirrorOf>
    <!-- -->
    <name>Nexus aliyun</name>
    <!-- URL -->
    <url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

1.3 构建第一个maven项目(手动制作)  

 1.3.1 maven项目的目录结构及常用命令

1.3.1.1 maven的项目结构

src/main/java —— 存放项目的.java 文件

src/main/resources —— 存放项目资源文件,如 spring, hibernate 配置文件

src/test/java —— 存放所有单元测试.java 文件,如 JUnit 测试类

src/test/resources —— 测试资源文件 target —— 项目输出位置,编译后的 class 文件会输出到此目录

pom.xml——maven 项目核心配置文件 注意:如果是普通的 java 项目,那么就没有 webapp 目录。

1.3.1.2 maven的常用命令
  • mvn compile

compile 是 maven 工程的编译命令,作用是将 src/main/java 下的文件编译为 class 文件输出到 target 目录下。

  • mvn clean

clean 是 maven 工程的清理命令,执行 clean 会删除 target 目录及内容。

  • mvn test

test 是 maven 工程的清理命令,将测试代码和正式代码全部编译

  • mvn package

package 是 maven 工程的打包命令,同时编译正式代码和测试代码。对于 java 工程执行 package 打成 jar 包,对于 web 工程打成 war 包。

  • mvn install

install 是 maven 工程的安装命令,执行 install 将 maven 打成 jar 包或 war 包发布到本地仓库。 从运行结果中,可以看出: 当后面的命令执行时,前面的操作过程也都会自动执行。

1.3.2 手动创建maven工程  

1.3.2.1 创建目录结构

1.3.2.2 编写源程序

  •  主程序

  • 测试代码

1.3.2.3 编写POM文件

在src的同级目录下面,编写pom.xml文件。

1.3.2.4 运行maven工程  

在pom.xml的同级目录下面,执行cmd命令

  • 编译 mvn compile

  • 清空 mvn clean

注意: 执行mvn clean之后,之前mvn compile编译的文件也会消失

  • 测试 mvn test :

 生成的测试报告如下:

  • 打包 mvn package  

  • 安装 mvn install

打开本地仓库

一般常用下面这种方式构建Maven项目 

1.3.3 使用idea构建maven工程

1.3.3.1 在maven中创建一个工程(不使用骨架)
  • 创建一个空工程  

  • 选择下一步,设置工程名称和工程目录

  • 设置sdk版本

  • 设置maven环境

右键settings,选择maven选项。

设置maven客户端的、settings文件以及本地仓库的路径。

具体设置如下:

  •  创建modules

  • 选择maven

  • 点击next,设置组织名称和工程名称

  • 设置模块名称

  • 点击完成,并且完善工程目录

  • 设置编译环境

File –> project Structureàmodules

Settings-->javaCompiler

 

  • 填充代码(和手动创建的代码一样,这里省略)

当然我们还可以设置这些命令的快捷方式

具体设置如下:

设置完成之后的效果如下:

其他命令类似这样的设置。

1.3.3.2 使用maven骨架创建java普通工程  
  • 选择骨架

  • 创建完成

完善resources目录

1.3.3.3.使用maven骨架创建web工程  
  • 使用web工程的骨架创建 

  • 创建完成之后的工程目录结构如下:  

工程目录并不完整,我们需要补齐工程目录。

  • 配置tomcat插件来启动tomcat

在远程仓库搜索tomcat—maven-plugin, 选择2.1版本,点击进入

<build>
    <!--定义插件的集合-->
    <plugins>
        <!--具体的插件-->
        <plugin>
            <!--插件组织id-->
            <groupId>org.apache.tomcat.maven</groupId>
            <!-- 插件名称 -->
            <artifactId>tomcat7-maven-plugin</artifactId>
            <!--插件版本-->
            <version>2.1</version>
            <configuration>
                <!--配置tomcat端口号-->
                <port>8088</port>
                <!--配置虚拟路径-->
                <path>/</path>
            </configuration>
        </plugin>
    </plugins>
</build>
  • 刷新之后,就可以看见tomcat7插件了  

如何启动?  

也可以配置快捷启动方式:  

启动之后。控制台效果如下:  

这时启动成功了!!!

1.4依赖管理   

1.4.1 依赖配置与依赖传递  

依赖指的是当前项目运行所需要的jar,一个项目可以有很多个依赖。

格式:

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.10</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
</dependencies>

依赖传递

依赖具有传递性:

直接依赖:在当前项目中,通过依赖配置建立的依赖关系。

间接依赖:被依赖的资源,如果还依赖其他资源,那么当前项目间接依赖其他资源。

1.4.2 解决依赖冲突的问题

依赖冲突是指项目依赖的某一个jar包,有多个不同的版本,因而造成类包版本冲突。

如下所示:

<dependencies>
	<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.7.RELEASE</version>
    </dependency>
     <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
 </dependencies>

通过查看依赖,我们发现spring-aop和spring-context都依赖了一个叫spring-core的依赖。此时spring-core的版本有两个。这样就产生了依赖冲突

解决依赖冲突:

1、使用第一声明优先的原则

谁先定义的就用谁的传递依赖,即在pom.xml文件自上而下,先声明的jar坐标,就先引用该jar的传递依赖。因此我们如果要使用5.2.0版本的spring-core包,我们可以改成如下声明:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.7.RELEASE</version>
</dependency>

2、路径近优先原则—直接依赖高于间接依赖

即直接依赖级别高于传递依赖。因此我们可以在最先的pom.xml添加如下内容

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
</dependencies>

3、排除依赖原则

在不影响项目运行的情况下,如果依赖冲突,可以把被冲突的依赖排除掉,注意排除的依赖不需要添加依赖的版本号。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.7.RELEASE</version>
    <exclusions>
        <exclusion>
            <artifactId>spring-core</artifactId>
            <groupId>org.springframework</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>

4、版本锁定

使用dependencyManagement 进行版本锁定,dependencyManagement可以统一管理项目的版本号,确保应用的各个项目的依赖和版本一致。

如果我们项目中只想使用spring core 5.2.0的包,pom.xml可以改为如下

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
</dependencies>

1.4.3 依赖范围

1、什么是依赖范围?

依赖的jar包在默认情况下可以在任何范围内使用,可以通过scope标签来控制其作用范围。

作用范围:

主程序范围有效(main文件夹)

测试程序范围有效(test文件夹)

是否参与打包(package指令范围之内)

举例:在demo3的pom.xml里面引入一个依赖  

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.3</version>
</dependency>

此时在main文件夹和test文件夹里面的java程序里面都可以用到SqlNode这个类(mybatis提供的一个类)。但是如果把mybatis的作用域换成test。如下:  

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.3</version>
    <scope>test</scope>
</dependency>

在main目录的程序里面:

public class Demo1 {
    public void sayHello(){
        SqlNode node = new TextSqlNode("");//报错
    }
}

但是在test目录的程序里面:  

@Test
public void test(){
    SqlNode node = new TextSqlNode("");
}

1.5 生命周期与插件  

1、生命周期

Maven对项目周期的构建分为3套

clean: 清理工作阶段

default:核心工作阶段。比如编译、测试、打包、部署等

site: 产生报告,发布站点等

  • clean生命周期

    • pre-clean 执行一些需要在clean之前完成的工作

    • clean 移除所有上一次构建生成的文件

    • post-clean 执行一些需要在clean之后立刻完成的工作

  • default生命周期

  • site生命周期

    • pre-site 执行一些需要在生成站点文档之前完成的工作

    • site 生成项目的站点文档

    • post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备

    • site-deploy 将生成的站点文档部署到特定的服务器

2、插件

插件与生命周期内的阶段绑定,在执行到对应生命周期时,执行对应的插件功能。

默认maven在各个生命周期阶段上绑定有预设功能

通过插件可以自定义其他功能

这个插件就是 在生成测试代码的时候,给主程序源代码打包、同时给测试源代码打包。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-source-plugin</artifactId>
    <version>2.2.1</version>
    <executions>
        <execution>
            <goals>
                <goal>jar</goal>
                <goal>test-jar</goal>
            </goals>
            <phase>generate-test-resources</phase>
        </execution>
    </executions>
</plugin>

 



 

二、Maven高级

  • 分模块开发与设计(重点)

  • 聚合(重点)

  • 继承(重点)

  • 属性(重点)

  • 版本管理

  • 资源配置

  • 多环境开发配置

  • 私服(重点)

2.1 maven分模块开发与设计

2.1.1 创建父工程  

 

使用maven创建一个父工程。在POM里面导入相关依赖  

<dependencies>
    <!-- servlet依赖的jar包start -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!-- servlet依赖的jar包start -->
    <!-- jsp依赖jar包start -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.1</version>
        <scope>provided</scope>
    </dependency>
    <!-- jsp依赖jar包end -->
    <!--jstl标签依赖的jar包start -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
        <!--<scope>provided</scope>-->
    </dependency>
    <!-- JSTL实现包 -->
    <dependency>
        <groupId>org.apache.taglibs</groupId>
        <artifactId>taglibs-standard-impl</artifactId>
        <version>1.2.5</version>
    </dependency>
    <!--jstl标签依赖的jar包end -->
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.1.2</version>
    </dependency>
    <!--beanUtils的依赖-->
    <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils</artifactId>
        <version>1.8.3</version>
    </dependency>
    <!--dbutils组件 封装了原生的jdbc-->
    <dependency>
        <groupId>commons-dbutils</groupId>
        <artifactId>commons-dbutils</artifactId>
        <version>1.6</version>
    </dependency>
    <!--logging-->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.1.1</version>
    </dependency>
    <!--mysql驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.18</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.1</version>
            <configuration>
                <port>8088</port>
                <path>/</path>
            </configuration>
        </plugin>
    </plugins>
</build>

2.1.2 maven-pojo拆分  

public class User {
    private Integer id;
    private String name;
    private String gender;
    private Integer age;
    private String address;
    private String email;
    private String qq;
    private String username;
    private String password;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getQq() {
        return qq;
    }

    public void setQq(String qq) {
        this.qq = qq;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                ", email='" + email + '\'' +
                ", qq='" + qq + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

创建后的目录结构:


2.1.3 maven-utils模块拆分  

在父工程上,右键,新建模块(使用maven构建,不使用骨架创建)。然后创建工具类和配置文件:

/**
 * 连接数据库的工具类
 */
public class DataSourceConfig {

    //根据c3p0-config.xml初始化一个数据源,我们可以从数据源里面获取连接对象(此时已经自动加载了c3p0-config.xml配置文件)
    static ComboPooledDataSource dataSource = new ComboPooledDataSource();

    /**
     * 获取数据源的方法
     * @return
     */
    public static DataSource getDataSource() {
        return dataSource;
    }
    /**
     * 获取连接对象
     * @return
     * @throws Exception
     */
    public static Connection getConnection() throws Exception{
        return dataSource.getConnection();
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://192.168.10.137:3306/user</property>
        <property name="user">root</property>
        <property name="password">Admin123!</property>
        <!--
            初始化的连接数量 在连接池里面初始化10个连接对象
        -->
        <property name="initialPoolSize">10</property>
        <!--
           最大空闲时间
           某一个连接对象空闲时长最多是30s,超过了30s,该连接对象会被自动回收
        -->
        <property name="maxIdleTime">30</property>
        <!--
            最大连接数量
            在连接池里面存在最多的连接数量
        -->
        <property name="maxPoolSize">100</property>
        <!--
           最小连接数量
        -->
        <property name="minPoolSize">10</property>
    </default-config>
</c3p0-config>

创建后的目录结构如下:

2.1.4 maven-dao模块拆分

在父工程上,右键,新建模块(使用maven构建,不使用骨架创建)。然后创建接口以及实现类。

  • pom文件

由于这个模块需要用到实体类,操作数据库也需要用到工具类。所以dao模块需要依赖pojo和utils模块

<dependencies>
    <dependency>
        <groupId>com.xq.pojo</groupId>
        <artifactId>maven-pojo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>com.xq.utils</groupId>
        <artifactId>maven-utils</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>
  • 代码部分 
public interface UserDao {
    //查询所有用户信息
    public List<User> findAll();
}
public class UserDaoImpl implements UserDao {
    //DbUtils组件里面的一个核心类 主要是用来进行各种增删改查
    QueryRunner runner = new QueryRunner(DataSourceConfig.getDataSource());
    /**
     * 查询所有用户信息
     * @return
     */
    public List<User> findAll() {
        String sql = "select * from user";
        try {
            /**
             * 参数1 要执行的sql语句
             * 参数2  我们从数据库服务器里面查询出来的是一条条sql语句,我们在java后台肯定不能接收一条条sql语句
             *        怎么办? 把这一条条sql语句封装到List集合里面
             *        怎么封装? 使用一个DbUtils给我们提供的处理器来实现   BeanListHandler
             *             User.class 就是告诉BeanListHandler将一条条sql语句转换成List集合的时候,封装什么类型的数据
             *             放在list集合里面
             */
            List<User> list = runner.query(sql, new BeanListHandler<User>(User.class));
            return list;
        } catch (SQLException e) {
            throw new RuntimeException();
        }
    }
}

最后目录结构如下:

2.1.5 maven-service模块拆分

在父工程上,右键,新建模块(使用maven构建,不使用骨架创建)。然后创建业务接口以及实现类。

  • pom文件

由于service模块需要调用dao模块里面的数据。所以service模块依赖dao模块。

<dependencies>
    <dependency>
        <groupId>com.xq.dao</groupId>
        <artifactId>maven-dao</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>
  •  代码部分

public interface UserService {
    //查询所有用户信息
    public List<User> findUser();
}
public class UserServiceImpl implements UserService {

    UserDao userDao = new UserDaoImpl();

    //查询所有用户信息
    public List<User> findUser() {
        return userDao.findAll();
    }
}

 

2.1.6 maven-servlet模块拆分

在父工程上,右键,新建模块(使用maven构建,使用骨架创建)。然后创建servlet

  • pom文件

由于servlet模块需要调用service模块里面的数据,需要在servlet模块里面引入service依赖。

<dependencies>
    <dependency>
        <groupId>com.xq.service</groupId>
        <artifactId>maven-service</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
</dependencies>
  • 代码部分  
@WebServlet("/showUserList")
public class UserServlet extends HttpServlet {

    UserService userService = new UserServiceImpl();

    /**
     * 查询用户的所有信息
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        List<User> list = userService.findUser();
        //将list存入到request作用域
        request.setAttribute("list",list);
        //转发到list.jsp页面
        request.getRequestDispatcher("/list.jsp").forward(request,response);
    }
}

 前台jsp页面参照素材。

2.2 聚合与继承

2.2.1 聚合 

我们思考一个问题

 上面的各个模块是分开独立开发的,彼此互相独立,互补影响。假设如果现在maven-dao模块更新升级了,那么其他模块是如何感知dao模块发生了变化的?

解决方案:

会不会有一个工程,专门对这些模块进行管理。对这些模块进行统一的编译,测试,打包等操作。一旦一个模块发生了变化,会同时对其他模块也进行编译、测试、打包。

此时就需要用到聚合的思想。

聚合的作用:用于快速构建maven工程,一次性管理多个模块。

  • 创建一个maven工程,定义打包方式为pom  
 <packaging>pom</packaging>
  • 定义当前模块管理的其他模块的名称
<modules>
    <!--具体模块的名称-->
    <module>maven-pojo</module>
    <module>maven-dao</module>
    <module>maven-service</module>
    <module>maven-servlet</module>
    <module>maven-utils</module>
</modules>

​​​​​​​

  • 在子模块里面引入父工程
<parent>
    <artifactId>maven-user</artifactId>
    <groupId>com.xq</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>

在本案例中,我们的maven-user就是一个父工程,专门用来管理其他的子模块。

此时我们测试一下。

在父工程上,使用compile命令:

此时所有的模块都会进行编译。

问题:编译的顺序是怎么样的?

参与聚合操作的模块最终执行顺序与模块的依赖关系有关系。跟配置顺序没有关系。

  • 各个模块的打包方式

父工程打pom

Web工程打war包

其他工程 打jar包(如果没有任何打包配置,默认就是打jar包)

2.2.2 继承

通过继承可以实现在父工程中的配置,让子模块沿用思考。类似于java中的继承关系。

实现:

在子模块中,使用parent标签引入父工程,这样子工程和父工程就有了继承关系了

<parent>
    <artifactId>maven-user</artifactId>
    <groupId>com.xq</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>

测试观察效果:

在maven-dao的pom文件里面没有配置任何依赖资源。

但是maven-dao却是继承了maven-user父工程的所有依赖资源

其他子模块一样,都继承了父工程的资源。

思考:这样的做法有没有问题?

答案:有,并不是子模块都需要所有父工程的资源。以maven-dao为例,这个子模块并不需要tomcat插件,也不需要servlet jsp相关的依赖。如果全部资源都继承下来会导致子模块特别大,将来打包,部署效率比较低。

解决方案:

使用<dependencyManagement>标签帮我们管理依赖

具体操作如下:

  • 在父工程的Pom文件里面定义

<dependencyManagement>
    <dependencies>
        <!--管理自己的依赖-->
        <dependency>
            <groupId>com.xq.service</groupId>
            <artifactId>maven-service</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.xq.dao</groupId>
            <artifactId>maven-dao</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.xq.pojo</groupId>
            <artifactId>maven-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.xq.utils</groupId>
            <artifactId>maven-utils</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.xq.servlet</groupId>
            <artifactId>maven-servlet</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!-- servlet依赖的jar包start -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
           <!-- <scope>provided</scope>-->
        </dependency>
        <!-- servlet依赖的jar包start -->
        <!-- jsp依赖jar包start -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
           <!-- <scope>provided</scope>-->
        </dependency>
        <!-- jsp依赖jar包end -->
        <!--jstl标签依赖的jar包start -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
            <!--<scope>provided</scope>-->
        </dependency>
        <!-- JSTL实现包 -->
        <dependency>
            <groupId>org.apache.taglibs</groupId>
            <artifactId>taglibs-standard-impl</artifactId>
            <version>1.2.5</version>
        </dependency>
        <!--jstl标签依赖的jar包end -->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <!--beanUtils的依赖-->
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.8.3</version>
        </dependency>
        <!--dbutils组件 封装了原生的jdbc-->
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.6</version>
        </dependency>
        <!--logging-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.18</version>
        </dependency>
    </dependencies>
</dependencyManagement>
  • 在子模块中按照自己的需求,引入对应的依赖,此时不需要加依赖的版本号了,因为在父工程里面已经给我们定义好了。  

以maven-utils为例

<dependencies>
    <!--dbutils组件 封装了原生的jdbc-->
    <dependency>
        <groupId>commons-dbutils</groupId>
        <artifactId>commons-dbutils</artifactId>
    </dependency>
    <!--logging-->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
    </dependency>
    <!--mysql驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <!--c3p0-->
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
    </dependency>
</dependencies>

此外插件也可以用类似的方法进行管理。在父工程的POM里面:

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <port>8088</port>
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

 在maven-servlet里面 我们引入tomcat插件,此时不用定义插件的版本号了。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <!--  <version>2.1</version>--><!--
                <configuration>
                    <port>8088</port>
                    <path>/</path>
                </configuration>-->
        </plugin>
    </plugins>
</build>

配置之后效果如下,插件依然可以正常引入

总结:

聚合和继承的关系

  • 作用:

    • 聚合用于快速构建项目

    • 继承用于快速配置

  • 相同点:

    • 聚合与继承的pom.xml文件打包方式均为pom。可以将两种关系定义在同一个pom文件中。

    • 聚合和继承均属于设计系模块,并无实际的模块内容

  • 不同点

    • 聚合是在当前模块中配置关系,聚合可以感知到参与聚合的模块都有哪些

    • 继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己

2.3 属性与版本管理&多资源配置

2.3.1 属性

在定义依赖的版本的时候,我们可以使用属性来描述,方便维护管理。

定义格式:

调用格式:

 改造我们的父工程:

<properties>
    <javax.servlet-api>3.1.0</javax.servlet-api>
    <javax.servlet.jsp-api>2.3.1</javax.servlet.jsp-api>
    <jstl>1.2</jstl>
    <taglibs-standard-impl>1.2.5</taglibs-standard-impl>
    <c3p0>0.9.1.2</c3p0>
    <commons-beanutils>1.8.3</commons-beanutils>
    <commons-dbutils>1.6</commons-dbutils>
    <commons-logging>1.1.1</commons-logging>
    <mysql>5.1.18</mysql>
</properties>

在pom.xml我们如下定义:

2.3.2 版本管理

我们的模块开发完成之后,并不是一成不变的。后续肯定会进行更新升级,那么这样会形成多个版本,那么如何来区分这些版本呢?

 

测试:

我们在maven-pojo上面自定义版本

然后打包

观察本地仓库

工程版本号约定:  

2.3.3 在配置文件引入pom属性

我们可以在任意配置文件中加载POM 属性

格式: ${usr.name}

在maven-dao中定义属性:

在maven-dao的user.properties中加载这些属性值  

在maven-dao的pom中定义如下配置

<build>
    <resources>
        <resource>
            <directory>${project.basedir}/src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

到本地仓库,查看打包的jar包,解压并查看

2.4 多环境配置

在实际开发中,生产环境的配置和开发环境的配置是不一样的。比如生产环境使用的数据库和开发环境的数据库就不一样。那么在项目由开发环境切换到生产环境的时候,配置应该如何更改?

 

实例:

在maven-dao中我们定义不同的数据库连接信息

<profiles>
    <!--生产环境的数据库信息-->
    <profile>
    <!--环境名称,自定义-->
        <id>pro-env</id>
        <properties>
            <jdbc.url>jdbc:mysql://127.1.1.1:3306/ssm_db</jdbc.url>
        </properties>
    </profile>
    <!--开发环境的数据库信息-->
    <profile>
        <id>dev-env</id>
        <properties>
            <jdbc.url>jdbc:mysql://127.1.1.1:3308/ssm_db</jdbc.url>
        </properties>
    </profile>
</profiles>

 在properties文件中指定:

jdbc.url=${jdbc.url}

那么如何根据指定的开发环境进行运行呢?

格式: 指令 –P 环境名称  

运行打包之后,我们在本地仓库看看配置信息

2.5 私服 

我们的项目都是协同开发的,并不是一个人开发所有的模块。如果每个人开发不同的模块,当我们需要别人的模块时,怎么获取?用硬盘拷贝吗?很显然不可取。

应该怎么办?

可不可以把大家开发的模块都放在一个公共的服务器上,大家需要别人的模块时,只需要从这个公共的服务器去获取就可以。

2.5.1 搭建私服

我们已经给大家准备好了安装包

  •  解压之后的目录结构

  • 启动命令

  • 启动服务 nexus.exe /run nexus

  • 在bin目录打开cmd 输入启动命令: nexus.exe /run nexus

  • 访问服务器,默认端口8081 http://localhost:8081

  • 修改基础配置信息

    • 在etc目录下面的nexus-default.properties文件中保存nexus的基础配置信息。比如默认访问端口

  • 修改服务器运行配置信息

    • 在bin目录中的nexus.vmoptions文件保存有nexus服务器运行的配置信息。比如内存分配的信息等

2.5.2 私服资源获取  

仓库的分类:

2.5.2.1 登录私服

点击 sign in

 

按照指定的密码登录之后

我们需要设置新的密码:

设置密码之后,sign out,重新登录  

 

2.5.2.2 创建仓库  

点击创建仓库:

选择maven2(hosted),点击进入仓库

点击创建,创建之后

将创建的仓库加入到仓库组里面来(添加到maven-public这个组)

点击maven-public这个组,进入到添加页面

添加之后的效果,点击save保存

2.5.2.3 向仓库上传资源  

点击上传组件:

最后点击upload按钮  

2.5.2.4 IDEA环境中资源上传与下载

​​​​​​​ 

  • 配置maven客户端的settings配置文件  
<!--配置访问krisswen-release的仓库名称、用户名、密码-->
<server>
    <id>krisswen-release</id>
    <username>admin</username>
    <password>admin</password>
</server>
<!--配置访问krisswen-snapshots的仓库名称、用户名、密码-->
<server>
    <id>krisswen-snapshots</id>
    <username>admin</username>
    <password>admin</password>
</server>
  •  配置私服的地址
<mirror>
    <id>nexus-krisswen</id>
    <mirrorOf>*</mirrorOf>
    <url>http://localhost:8081/repository/maven-public/</url>
</mirror>
  • 配置当前项目访问私服上传资源保存的位置

在父工程里面的POM文件配置

<distributionManagement>
    <repository>
        <id>krisswen-release</id>
        <url>http://localhost:8081/repository/krisswen-release/</url>
    </repository>
    <snapshotRepository>
        <id>krisswen-snapshots</id>
        <url>http://localhost:8081/repository/krisswen-snapshots/</url>
    </snapshotRepository>
</distributionManagement>
  • 发布资源到私服的命令 mvn deploy  

查看控制台效果:

最后在私服上面查看是否上传成功:

2.5.3 nexus代理阿里云仓库  

为了提高资源的下载速度,我们也可以在nexus官方仓库中添加国内阿里云maven仓库。具体操作如下:

  • 第一步:点击repositories

  • 点击 create repository,选中maven(proxy)  

  • 设置阿里云

阿里云仓库url:http://maven.aliyun.com/nexus/content/groups/publicicon-default.png?t=N7T8http://maven.aliyun.com/nexus/content/groups/public

 

  • 将创建的仓库添加到仓库组maven-public

  • 把阿里云代理仓库设置为第一位

移动之后的效果:  

  • 设置maven的setting.xml文件  
<!-- 使用nexus  配置镜像 -->
<mirror>
    <id>nexus-central</id>
    <mirrorOf>*</mirrorOf>
    <name>Nexus Central</name>
    <url>http://localhost:8081/nexus/repository/maven-public/</url>
</mirror>

或者在项目的pom.xml里面指定仓库路径:

<repositories>
    <repository>
        <id>nexus-central</id>
        <name>nexus-central</name>
        <url>http://localhost:8081/repository/maven-public/</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>

以上就是关于Maven的全部内容了,希望对读者有帮助!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Austine Reaves

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值