zoukankan      html  css  js  c++  java
  • 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:class32apache-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,多了该插件的配置代码。

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

  • 相关阅读:
    /etc/init.d/functions: No such file or directory报错问题
    在Linux上安装Python3.7.1
    python 使用openpyxl实现读写xlsx文件
    Git 撤销本地修改
    element的el-table表格自定义表头,slot="header"内,数据不更新的问题
    记录下本地修改文件名称大小写问题线上说找不到文件
    解决国内访问github慢的问题笔记
    vue项目中使用echarts实现疫情地图
    uni-app项目搭建
    uniapp引入uni-ui组件报错TypeError: this.getOptions is not a function
  • 原文地址:https://www.cnblogs.com/zhaojiankai/p/7918509.html
Copyright © 2011-2022 走看看