maven私服搭建与插件开发

一、maven声明周期

  1. 声明周期的概念与意义

    在项目构建时通常会包含清理、编译、测试、打包、验证、部署、文档生成等步骤,maven统一对其进行了整理,抽象成三个生命周期(lifecycle)及各自对应的阶段(phase)。这么做的意义是:

    • 每个阶段都成为一个扩展点,可以采用不同的方式来实现,提高了扩展性与灵活性。
    • 规范统一了maven的执行路径。

    在执行项目构建阶段时可以采用jar方式构建也可以采用war包方式构建,提高了灵活性。我们可以通过命令mvn ${phase name}直接触发指定阶段的执行

    如:

    • 演示phase的执行

      #执行清理phase

      mvn clean

      #执行编译phase

      mvn compile

      #同时执行清理、编译

      mvn clean compile

一、maven声明周期

  1. 声明周期的概念与意义

    在项目构建时通常会包含清理、编译、测试、打包、验证、部署、文档生成等步骤,maven统一对其进行了整理,抽象成三个生命周期(lifecycle)及各自对应的阶段(phase)。这么做的意义是:

    • 每个阶段都成为一个扩展点,可以采用不同的方式来实现,提高了扩展性与灵活性。
    • 规范统一了maven的执行路径。

    在执行项目构建阶段时可以采用jar方式构建也可以采用war包方式构建,提高了灵活性。我们可以通过命令mvn ${phase name}直接触发指定阶段的执行

    如:

    • 演示phase的执行

      #执行清理phase

      mvn clean

      #执行编译phase

      mvn compile

      #同时执行清理、编译

      mvn clean compile

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tt4c464z-1625121801080)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210621163928827.png)]

  2. maven三大声明周期与其对应的阶段(phase)

    maven 总共包含三大生生命周期

    1. clean Lifecycle 清理生命周期,用于于清理项目
    2. default Lifecycle 默认生命周期,用于编译、打包、测试、部署等
    3. site Lifecycle 站点文档生成,用于构建站点文档
    生命周期(lifecycle)阶段(phase)描述(describe)
    clean Lifecyclepre-clean预清理
    clean清理
    post-clean清理之后
    default Lifecyclevalidate验证
    initialize初始化
    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打包构建
    pre-integration-test
    integration-test
    post-integration-test
    verify验证
    install上传到本地仓库
    deploy上传到远程仓库
    site Lifecyclepre-site准备构建站点
    site构建站点
    post-site构建站点之后
    site-deploy站点部署

    三大生命周期其相互独立执行,也可以合在一起执行。但lifecycle中的phase是有严格执行顺序的,比如必须是先执行完compile才能执行package动作,此外phase还有包含逻辑,即当你执行一个phase是,其前面的phase会自动执行。

    • 演示phase执行

      #执行编译

      mvn compile

      #执行打包就包含了编译的执行

      mvn package

  3. 声明周期与插件的关系

    声明周期的phase组成了项目构建的完成过程,但这些过程具体由谁来实现呢?

    这就是插件,maven的核心部分代码量其实很少,其大部分实现都是由插件来完成的。

    比如:test阶段就是由maven-surefire-plugin 实现。在pom.xml 中我们可以指定插件目标(goal)与phase 绑定,也就是插件在什么阶段执行,当项目构建到达指定phase时就会触发这些插件goal的执行。

    一个插件有时会实现多个phase比如:maven-compiler-plugin插件分别实现了compile 和testCompile。

    总结:

    • 生命周期的阶段可以绑定具体的插件及目标
    • 不同配置下同一个阶段可以对应多个插件和目标
    • phase->plugin->goal
  4. 声明周期与插件的默认绑定

    在我们的项目中并没有配置maven-compiler-plugin插件,但当我们执行compile命令时一样能够执行编译操作,原因是maven默认为指定阶段绑定了插件实现。

    以下两个操作在一定程度上是等价的:

    mvn compile

    #直接执行compile插件目标

    mvn org.apache.maven.plugins:maven-compiler-plugin:3.1:compile

    clean Lifecycle 默认绑定

    pre-clean

    clean

    post-clean

    org.apache.maven.plugins:maven-clean-plugin:2.5:clean

    site Lifecycle 默认绑定

    pre-site

    site

    post-site

    site-deploy

    org.apache.maven.plugins:maven-site-plugin:3.3:site

    org.apache.maven.plugins:maven-site-plugin:3.3:deploy

    Default Lifecycle JAR默认绑定
    注:不同的项目类型 其默认绑定是不同的,这里只指列举了packaging 为jar 的默认绑定
    全部的默认绑定参见:https://maven.apache.org/ref/3.5.4/maven-core/default-bindings.html#

    org.apache.maven.plugins:maven-resources-plugin:2.6:resources

    org.apache.maven.plugins:maven-compiler-plugin:3.1:compile

    org.apache.maven.plugins:maven-resources-plugin:2.6:testResources

    org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile

    org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test

    org.apache.maven.plugins:maven-jar-plugin:2.4:jar

    org.apache.maven.plugins:maven-install-plugin:2.4:install

    org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy

二、maven自定义插件开发

  1. maven插件相关概念
    插件坐标定位:

    插件与普通jar包一样包含组件坐标定位属性即:

    groupId、artifactId、version,当使用该插件时会从本地仓库中搜索,如果没有即从远程仓库下载。

    <!-- 唯一定位到dependency 插件 -->
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.10</version>
    
    插件执行execution:

    execution 配置一组指示插件如何执行的属性:

    id 执行器命名

    phase 什么阶段执行

    goals 执行一组什么目标或功能

    configuration 执行目标所需的配置文件

    • 演示一个插件的配置与使用
      # 将插件依赖拷贝到指定目录
      <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>3.1.1</version>
          <executions>
              <execution>
                  <id>copy-dependencies</id>
                  <phase>package</phase>
                  <goals>
                      <goal>copy-dependencies</goal>
                  </goals>
                  <configuration>              <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
                      <overWriteReleases>false</overWriteReleases>
                      <overWriteSnapshots>true</overWriteSnapshots>
                      <excludeTransitive>true</excludeTransitive>
                  </configuration>
              </execution>
          </executions>
      </plugin>
      
  2. 常用插件的使用

    除了通过配置的方式使用插件外,maven也提供了通过命令直接调用插件目标。

    其命令格式如下:

    mvn groupId:artifactId:version:goal -D{参数名}

    • 演示通过命令执行插件

      #展示pom的依赖关系树

      mvn org.apache.maven.plugins:maven-dependency-plugin:2.10:tree

      #也可以使用简化版的命令,但前提必须是maven官方插件

      mvn dependency:tree

    其他常用插件:

    #查看pom文件的最终配置

    mvn help:effective-pom

    #原型项目生成

    archetype:generate

    #快速创建一个web程序

    mvn archetype:generate -DgroupId=demo -DartifactId=simple-webbapp -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

    #快速创建一个java 项目

    mvn archetype:generate -DgroupId=demo -DartifactId=simple-java -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

  3. 开发一个自定义插件
    实现步骤:
    • 创建maven插件项目
    • 设定packaging为maven-plugin
    • 添加插件依赖
    • 编写插件实现逻辑
    • 打包构建插件

    插件pom配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <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>4.0.0</modelVersion>
        <groupId>bianchengjieji</groupId>
        <version>1.0.SNAPSHOT</version>
        <artifactId>bianchengjieji-maven-plugin</artifactId>
        <packaging>maven-plugin</packaging>
        <dependencies>
            <dependency>
                <groupId>org.apache.maven</groupId>
                <artifactId>maven-plugin-api</artifactId>
                <version>3.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.maven.plugin-tools</groupId>
                <artifactId>maven-plugin-annotations</artifactId>
                <version>3.4</version>
            </dependency>
        </dependencies>
    </project>
    

    插件实现类:

    package com.bianchengjieji.maven; 
    
    import javafx.beans.DefaultProperty;
    import org.apache.maven.plugin.AbstractMojo;
    import org.apache.maven.plugin.MojoExecutionException;
    import org.apache.maven.plugin.MojoFailureException;
    import org.apache.maven.plugins.annotations.LifecyclePhase;
    import org.apache.maven.plugins.annotations.Mojo;
    import org.apache.maven.plugins.annotations.Parameter;
    
    /**
     * @author Tommy
     *         Created by Tommy on 2018/8/8
     **/
    @Mojo(name = "bianchengjieji")
    public class BianchengjiejiPlugin extends AbstractMojo {
        @Parameter
        String sex;
    
        @Parameter
        String describe;
    
        public void execute() throws MojoExecutionException, MojoFailureException {
            getLog().info(String.format("小明 sex=%s describe=%s",sex,describe));
        }
    }
    

三、nexus私服搭建与核心功能

  1. 私服使用场景
    私服使用场景如下:
    • 公司不能连接公网,可以用一个私服务来统一连接
    • 公司内部jar组件的共享
  2. nexus下载安装
    nexus下载地址:

    https://sonatype-download.global.ssl.fastly.net/nexus/oss/nexus-2.14.5-02-bundle.tar.gz

    解压并设置环境变量

    #解压

    shell>tar -zxvf nexus-2.14.5-02-bundle.tar.gz

    #在环境变量当中设置启动用户

    shell> vim /etc/profile

    #添加profile文件。安全起见不建议使用root用户,如果使用其它用户需要加相应权限

    export RUN_AS_USER=root

    #加载配置文件

    shell>source /etc/profile

    配置启动参数

    cd nexus-2.14.9-01/

    cd conf/

    vim nexus.properties

    增加application-port=9999

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d6k8KbgD-1625121801086)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210622155921301.png)]

    #启动

    cd ${nexusBase}/bin/

    ./nexus start

    #停止

    ./nexus stop

    登录nexus 界面

    地址:http://{ip}:9999/nexus/

    用户名:admin

    密码:admin123

  3. nexus仓库介绍

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DgTADewM-1625121801100)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210622160405210.png)]

    点击Repositories

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f36nqkAd-1625121801102)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210622160527712.png)]

    3rd party:第三方仓库

    Apache Snapshots:apache 快照仓库

    Central: maven 中央仓库

    Releases:私有发布版本仓库

    Snapshots:私有 快照版本仓库

  4. 本地远程仓库配置

    在pom.xml中配置远程仓库

    <repositories>
        <repository>
            <id>nexus-public</id>
            <name>my nexus repository</name>
    <url>http://{ip}:9999/nexus/content/groups/public/</url>
        </repository>
    </repositories>
    
    

    或者在settings.xml 文件中配置远程仓库镜像 效果一样,但作用范围广了

    nexus-aliyun

    ​ *

    ​ Nexus aliyun

    http://192.168.0.147:9999/nexus/content/groups/public/

  5. 发布项目至nexus远程仓库

    在pom.xml中配置仓库地址

    <distributionManagement>
        <repository>
            <id>nexus-release</id>
            <name>nexus release</name>
            <url>http://192.168.0.147:9999/nexus/content/repositories/releases/</url>
        </repository>
        <snapshotRepository>
            <id>nexus-snapshot</id>
            <name>nexus snapshot</name>
            <url>http://192.168.0.147:9999/nexus/content/repositories/snapshots/</url>
        </snapshotRepository>
    </distributionManagement>
    

    在setting.xml中设置server

    nexus-snapshot

    deployment

    deployment123

    nexus-release

    deployment

    deployment123

    #执行deploy 命令

    mvn deploy

  6. maven三大声明周期与其对应的阶段(phase)

    maven 总共包含三大生生命周期

    1. clean Lifecycle 清理生命周期,用于于清理项目
    2. default Lifecycle 默认生命周期,用于编译、打包、测试、部署等
    3. site Lifecycle 站点文档生成,用于构建站点文档
    生命周期(lifecycle)阶段(phase)描述(describe)
    clean Lifecyclepre-clean预清理
    clean清理
    post-clean清理之后
    default Lifecyclevalidate验证
    initialize初始化
    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打包构建
    pre-integration-test
    integration-test
    post-integration-test
    verify验证
    install上传到本地仓库
    deploy上传到远程仓库
    site Lifecyclepre-site准备构建站点
    site构建站点
    post-site构建站点之后
    site-deploy站点部署

    三大生命周期其相互独立执行,也可以合在一起执行。但lifecycle中的phase是有严格执行顺序的,比如必须是先执行完compile才能执行package动作,此外phase还有包含逻辑,即当你执行一个phase是,其前面的phase会自动执行。

    • 演示phase执行

      #执行编译

      mvn compile

      #执行打包就包含了编译的执行

      mvn package

  7. 声明周期与插件的关系

    声明周期的phase组成了项目构建的完成过程,但这些过程具体由谁来实现呢?

    这就是插件,maven的核心部分代码量其实很少,其大部分实现都是由插件来完成的。

    比如:test阶段就是由maven-surefire-plugin 实现。在pom.xml 中我们可以指定插件目标(goal)与phase 绑定,也就是插件在什么阶段执行,当项目构建到达指定phase时就会触发这些插件goal的执行。

    一个插件有时会实现多个phase比如:maven-compiler-plugin插件分别实现了compile 和testCompile。

    总结:

    • 生命周期的阶段可以绑定具体的插件及目标
    • 不同配置下同一个阶段可以对应多个插件和目标
    • phase->plugin->goal
  8. 声明周期与插件的默认绑定

    在我们的项目中并没有配置maven-compiler-plugin插件,但当我们执行compile命令时一样能够执行编译操作,原因是maven默认为指定阶段绑定了插件实现。

    以下两个操作在一定程度上是等价的:

    mvn compile

    #直接执行compile插件目标

    mvn org.apache.maven.plugins:maven-compiler-plugin:3.1:compile

    clean Lifecycle 默认绑定

    pre-clean

    clean

    post-clean

    org.apache.maven.plugins:maven-clean-plugin:2.5:clean

    site Lifecycle 默认绑定

    pre-site

    site

    post-site

    site-deploy

    org.apache.maven.plugins:maven-site-plugin:3.3:site

    org.apache.maven.plugins:maven-site-plugin:3.3:deploy

    Default Lifecycle JAR默认绑定
    注:不同的项目类型 其默认绑定是不同的,这里只指列举了packaging 为jar 的默认绑定
    全部的默认绑定参见:https://maven.apache.org/ref/3.5.4/maven-core/default-bindings.html#

    org.apache.maven.plugins:maven-resources-plugin:2.6:resources

    org.apache.maven.plugins:maven-compiler-plugin:3.1:compile

    org.apache.maven.plugins:maven-resources-plugin:2.6:testResources

    org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile

    org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test

    org.apache.maven.plugins:maven-jar-plugin:2.4:jar

    org.apache.maven.plugins:maven-install-plugin:2.4:install

    org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy

二、maven自定义插件开发

  1. maven插件相关概念
    插件坐标定位:

    插件与普通jar包一样包含组件坐标定位属性即:

    groupId、artifactId、version,当使用该插件时会从本地仓库中搜索,如果没有即从远程仓库下载。

    <!-- 唯一定位到dependency 插件 -->
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.10</version>
    
    插件执行execution:

    execution 配置一组指示插件如何执行的属性:

    id 执行器命名

    phase 什么阶段执行

    goals 执行一组什么目标或功能

    configuration 执行目标所需的配置文件

    • 演示一个插件的配置与使用
      # 将插件依赖拷贝到指定目录
      <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>3.1.1</version>
          <executions>
              <execution>
                  <id>copy-dependencies</id>
                  <phase>package</phase>
                  <goals>
                      <goal>copy-dependencies</goal>
                  </goals>
                  <configuration>              <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
                      <overWriteReleases>false</overWriteReleases>
                      <overWriteSnapshots>true</overWriteSnapshots>
                      <excludeTransitive>true</excludeTransitive>
                  </configuration>
              </execution>
          </executions>
      </plugin>
      
  2. 常用插件的使用

    除了通过配置的方式使用插件外,maven也提供了通过命令直接调用插件目标。

    其命令格式如下:

    mvn groupId:artifactId:version:goal -D{参数名}

    • 演示通过命令执行插件

      #展示pom的依赖关系树

      mvn org.apache.maven.plugins:maven-dependency-plugin:2.10:tree

      #也可以使用简化版的命令,但前提必须是maven官方插件

      mvn dependency:tree

    其他常用插件:

    #查看pom文件的最终配置

    mvn help:effective-pom

    #原型项目生成

    archetype:generate

    #快速创建一个web程序

    mvn archetype:generate -DgroupId=demo -DartifactId=simple-webbapp -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

    #快速创建一个java 项目

    mvn archetype:generate -DgroupId=demo -DartifactId=simple-java -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

  3. 开发一个自定义插件
    实现步骤:
    • 创建maven插件项目
    • 设定packaging为maven-plugin
    • 添加插件依赖
    • 编写插件实现逻辑
    • 打包构建插件

    插件pom配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <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>4.0.0</modelVersion>
        <groupId>bianchengjieji</groupId>
        <version>1.0.SNAPSHOT</version>
        <artifactId>bianchengjieji-maven-plugin</artifactId>
        <packaging>maven-plugin</packaging>
        <dependencies>
            <dependency>
                <groupId>org.apache.maven</groupId>
                <artifactId>maven-plugin-api</artifactId>
                <version>3.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.maven.plugin-tools</groupId>
                <artifactId>maven-plugin-annotations</artifactId>
                <version>3.4</version>
            </dependency>
        </dependencies>
    </project>
    

    插件实现类:

    package com.bianchengjieji.maven; 
    
    import javafx.beans.DefaultProperty;
    import org.apache.maven.plugin.AbstractMojo;
    import org.apache.maven.plugin.MojoExecutionException;
    import org.apache.maven.plugin.MojoFailureException;
    import org.apache.maven.plugins.annotations.LifecyclePhase;
    import org.apache.maven.plugins.annotations.Mojo;
    import org.apache.maven.plugins.annotations.Parameter;
    
    /**
     * @author Tommy
     *         Created by Tommy on 2018/8/8
     **/
    @Mojo(name = "bianchengjieji")
    public class BianchengjiejiPlugin extends AbstractMojo {
        @Parameter
        String sex;
    
        @Parameter
        String describe;
    
        public void execute() throws MojoExecutionException, MojoFailureException {
            getLog().info(String.format("小明 sex=%s describe=%s",sex,describe));
        }
    }
    

三、nexus私服搭建与核心功能

  1. 私服使用场景
    私服使用场景如下:
    • 公司不能连接公网,可以用一个私服务来统一连接
    • 公司内部jar组件的共享
  2. nexus下载安装
    nexus下载地址:

    https://sonatype-download.global.ssl.fastly.net/nexus/oss/nexus-2.14.5-02-bundle.tar.gz

    解压并设置环境变量

    #解压

    shell>tar -zxvf nexus-2.14.5-02-bundle.tar.gz

    #在环境变量当中设置启动用户

    shell> vim /etc/profile

    #添加profile文件。安全起见不建议使用root用户,如果使用其它用户需要加相应权限

    export RUN_AS_USER=root

    #加载配置文件

    shell>source /etc/profile

    配置启动参数

    cd nexus-2.14.9-01/

    cd conf/

    vim nexus.properties

    增加application-port=9999

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1HFY8zJz-1625121742756)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210622155921301.png)]

    #启动

    cd ${nexusBase}/bin/

    ./nexus start

    #停止

    ./nexus stop

    登录nexus 界面

    地址:http://{ip}:9999/nexus/

    用户名:admin

    密码:admin123

  3. nexus仓库介绍

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-82QN1FD5-1625121742763)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210622160405210.png)]

    点击Repositories

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1CVOLVtb-1625121742769)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210622160527712.png)]

    3rd party:第三方仓库

    Apache Snapshots:apache 快照仓库

    Central: maven 中央仓库

    Releases:私有发布版本仓库

    Snapshots:私有 快照版本仓库

  4. 本地远程仓库配置

    在pom.xml中配置远程仓库

    <repositories>
        <repository>
            <id>nexus-public</id>
            <name>my nexus repository</name>
    <url>http://{ip}:9999/nexus/content/groups/public/</url>
        </repository>
    </repositories>
    
    

    或者在settings.xml 文件中配置远程仓库镜像 效果一样,但作用范围广了

    nexus-aliyun

    ​ *

    ​ Nexus aliyun

    http://192.168.0.147:9999/nexus/content/groups/public/

  5. 发布项目至nexus远程仓库

    在pom.xml中配置仓库地址

    <distributionManagement>
        <repository>
            <id>nexus-release</id>
            <name>nexus release</name>
            <url>http://192.168.0.147:9999/nexus/content/repositories/releases/</url>
        </repository>
        <snapshotRepository>
            <id>nexus-snapshot</id>
            <name>nexus snapshot</name>
            <url>http://192.168.0.147:9999/nexus/content/repositories/snapshots/</url>
        </snapshotRepository>
    </distributionManagement>
    

    在setting.xml中设置server

    nexus-snapshot

    deployment

    deployment123

    nexus-release

    deployment

    deployment123

    #执行deploy 命令

    mvn deploy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值