【Maven】Maven 基础教程(三):build、profile

Maven 基础教程》系列,包含以下 3 篇文章:

  • Maven 基础教程(一):基础介绍、开发环境配置
  • Maven 基础教程(二):Maven 的使用
  • Maven 基础教程(三):build、profile

😊 如果您觉得这篇文章有用 ✔️ 的话,请给博主一个一键三连 🚀🚀🚀 吧 (点赞 🧡、关注 💛、收藏 💚)!!!您的支持 💖💖💖 将激励 🔥 博主输出更多优质内容!!!

Maven 基础教程(三):build、profile

  • 4.build 标签
    • 4.1 build 标签的组成
      • 4.1.1 定义约定的目录结构
      • 4.1.2 备用插件管理
      • 4.1.3 生命周期插件
    • 4.2 典型应用:指定 JDK 版本
    • 4.3 典型应用:SpringBoot 定制化打包
  • 5. 依赖配置补充
    • 5.1 import
    • 5.2 system
    • 5.3 runtime
  • 6.profile
    • 6.1 profile 概述
    • 6.2 profile 配置
      • 6.2.1 外部视角:配置文件
      • 6.2.2 内部实现:具体标签
    • 6.3 激活 profile
    • 6.4 Maven profile 多环境管理

4.build 标签

在实际使用 Maven 的过程中,我们会发现 build 标签有时候有,有时候没,这是怎么回事呢?其实通过有效 POM 我们能够看到,build 标签的相关配置其实一直都在,只是在我们需要定制构建过程的时候才会通过配置 build 标签覆盖默认值或补充配置。这一点我们可以通过打印有效 POM 来看到。

打印有效 pom
mvn help:effective-pom

当默认配置无法满足需求的定制构建的时候,就需要使用 build 标签。

4.1 build 标签的组成

build 标签的子标签大致包含三个主体部分:

  • 1️⃣ 定义约定的目录结构
  • 2️⃣ 备用插件管理
  • 3️⃣ 生命周期插件

4.1.1 定义约定的目录结构

<sourceDirectory>D:\product\maven-demo-parent\demo-module\src\main\java</sourceDirectory>
<scriptSourceDirectory>D:\product\maven-demo-parent\demo-module\src\main\scripts</scriptSourceDirectory>
<testSourceDirectory>D:\product\maven-demo-parent\demo-module\src\test\java</testSourceDirectory>
<outputDirectory>D:\product\maven-demo-parent\demo-module\target\classes</outputDirectory>
<testOutputDirectory>D:\product\maven-demo-parent\demo-module\target\test-classes</testOutputDirectory>
<resources>
    <resource>
        <directory>D:\product\maven-demo-parent\demo-module\src\main\resources</directory>
    </resource>
</resources>
<testResources>
    <testResource>
        <directory>D:\product\maven-demo-parent\demo-module\src\test\resources</directory>
    </testResource>
</testResources>
<directory>D:\product\maven-demo-parent\demo-module\target</directory>
<finalName>demo-module-1.0-SNAPSHOT</finalName>

各个目录的作用如下:

目录名作用
sourceDirectory主体源程序存放目录
scriptSourceDirectory脚本源程序存放目录
testSourceDirectory测试源程序存放目录
outputDirectory主体源程序编译结果输出目录
testOutputDirectory测试源程序编译结果输出目录
resources主体资源文件存放目录
testResources测试资源文件存放目录
directory构建结果输出目录

4.1.2 备用插件管理

pluginManagement 标签存放着几个极少用到的插件:

  • maven-antrun-plugin
  • maven-assembly-plugin
  • maven-dependency-plugin
  • maven-release-plugin

通过 pluginManagement 标签管理起来的插件就像 dependencyManagement 一样,子工程使用时可以省略版本号,起到在父工程中统一管理版本的效果。

4.1.3 生命周期插件

plugins 标签存放的是默认生命周期中实际会用到的插件,这些插件想必大家都不陌生,所以抛开插件本身不谈,plugin 标签的结构如下:

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <executions>
        <execution>
            <id>default-compile</id>
            <phase>compile</phase>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>
        <execution>
            <id>default-testCompile</id>
            <phase>test-compile</phase>
            <goals>
                <goal>testCompile</goal>
            </goals>
        </execution>
    </executions>
</plugin>

坐标部分

  • artifactIdversion 标签定义了插件的坐标,作为 Maven 的自带插件这里省略了 groupId

执行部分

  • executions 标签内可以配置多个 execution 标签,execution 标签内:
    • id:指定唯一标识
    • phase:关联的生命周期阶段
    • goals / goal:关联指定生命周期的目标。goals 标签中可以配置多个 goal 标签,表示一个生命周期环节可以对应当前插件的多个目标。

4.2 典型应用:指定 JDK 版本

前面我们在 settings.xml 中配置了 JDK 版本,那么将来把 Maven 工程部署都服务器上,脱离了 settings.xml 配置,如何保证程序正常运行呢?思路就是我们直接把 JDK 版本信息告诉负责编译操作的 maven-compiler-plugin 插件,让它在构建过程中,按照我们指定的信息工作。如下:

<!-- build 标签:意思是告诉 Maven,你的构建行为,我要开始定制了!-->
<build>
    <!-- plugins 标签:Maven 你给我听好了,你给我构建的时候要用到这些插件!-->
    <plugins>
        <!-- plugin 标签:这是我要指定的一个具体的插件 -->
        <plugin>
            <!-- 插件的坐标。此处引用的 maven-compiler-plugin 插件不是第三方的,是一个 Maven 自带的插件。-->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>

            <!-- configuration 标签:配置 maven-compiler-plugin 插件 -->
            <configuration>
                <!-- 具体配置信息会因为插件不同、需求不同而有所差异 -->
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
    </plugins>
</build>
  • settings.xml 中配置:仅在本地生效,如果脱离当前 settings.xml 能够覆盖的范围,则无法生效。
  • 在当前 Maven 工程 pom.xml 中配置:无论在哪个环境执行编译等构建操作都有效。

4.3 典型应用:SpringBoot 定制化打包

很显然 spring-boot-maven-plugin 并不是 Maven 自带的插件,而是 SpringBoot 提供的,用来改变 Maven 默认的构建行为。具体来说是改变打包的行为。默认情况下 Maven 调用 maven-jar-plugin 插件的 jar 目标,生成普通的 jar 包。

普通 jar 包没法使用 java -jar xxx.jar 这样的命令来启动、运行,但是 SpringBoot 的设计理念就是每一个 微服务 导出为一个 jar 包,这个 jar 包可以使用 java -jar xxx.jar 这样的命令直接启动运行。

这样一来,打包的方式肯定要进行调整。所以 SpringBoot 提供了 spring-boot-maven-plugin 这个插件来定制打包行为。

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <version>2.5.5</version>
    </plugin>
  </plugins>
</build>

5. 依赖配置补充

管理依赖最基本的办法是继承父工程,但是和 Java 类一样,Maven 也是单继承的。如果不同体系的依赖信息封装在不同 POM 中了,没办法继承多个父工程怎么办?这时就可以使用 import 依赖范围。

5.1 import

典型案例当然是在项目中引入 SpringBoot、SpringCloud 依赖:

<dependencyManagement>
    <dependencies>
        <!-- SpringCloud 微服务 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <!-- SpringCloud Alibaba 微服务 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>${spring-cloud-alibaba.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

import 依赖范围使用要求:

  • 打包类型必须是 pom
  • 必须放在 dependencyManagement

官网说明如下:

This scope is only supported on a dependency of type pom in the section. It indicates the dependency is to be replaced with the effective list of dependencies in the specified POM’s section. Since they are replaced, dependencies with a scope of import do not actually participate in limiting the transitivity of a dependency.

5.2 system

以 Windows 系统环境下开发为例,假设现在 D:\product\maven-demo-parent\demo-module\target\demo-module-1.0-SNAPSHOT.jar 想要引入到我们的项目中,此时我们就可以将依赖配置为 system 范围:

<dependency>
    <groupId>net.javatv.maven</groupId>
    <artifactId>demo-module</artifactId>
    <version>1.0-SNAPSHOT</version>
    <systemPath>D:\product\maven-demo-parent\demo-module\target\demo-module-1.0-SNAPSHOT.jar</systemPath>
    <scope>system</scope>
</dependency>

但是很明显:这样引入依赖完全不具有可移植性,所以不要使用。

5.3 runtime

专门用于编译时不需要,但是运行时需要的 jar 包。比如:编译时我们根据接口调用方法,但是实际运行时需要的是接口的实现类。典型案例是:

<!--热部署 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

6.profile

6.1 profile 概述

这里我们可以对接 profile 这个单词中 侧面 这个含义:项目的每一个运行环境,相当于是项目整体的一个侧面。

在这里插入图片描述
通常情况下,我们项目至少有三种运行环境:

  • 开发环境:供不同开发工程师开发的各个模块之间互相调用、访问;内部使用。
  • 测试环境:供测试工程师对项目的各个模块进行功能测试;内部使用。
  • 生产环境:供最终用户访问,所以这是正式的运行环境,对外提供服务。

在这里插入图片描述
我们这里的 环境 仍然只是一个笼统的说法,实际工作中一整套运行环境会包含很多种不同服务器:

  • MySQL
  • Redis
  • ElasticSearch
  • RabbitMQ
  • FastDFS
  • Nginx
  • Tomcat
  • ……

就拿其中的 MySQL 来说,不同环境下的访问参数肯定完全不同,可是代码只有一套。如果在 jdbc.properties 里面来回改,那就太麻烦了,而且很容易遗漏或写错,增加调试的难度和工作量。所以最好的办法就是把适用于各种不同环境的配置信息分别准备好,部署哪个环境就激活哪个配置。

在 Maven 中,使用 profile 机制来管理不同环境下的配置信息。但是解决同类问题的类似机制在其他框架中也有,而且从模块划分的角度来说,持久化层的信息放在构建工具中配置也违反了 高内聚,低耦合 的原则。

实际上,即使我们在 pom.xml 中不配置 profile 标签,也已经用到 profile了。为什么呢?因为根标签 project 下所有标签相当于都是在设定默认的 profile。这样一来我们也就很容易理解下面这句话:project 标签下除了 modelVersion 和坐标标签之外,其它标签都可以配置到 profile 中。

6.2 profile 配置

6.2.1 外部视角:配置文件

从外部视角来看,profile 可以在下面两种配置文件中配置:

  • settings.xml:全局生效。其中我们最熟悉的就是配置 JDK 1.8。
  • pom.xml:当前 POM 生效。

6.2.2 内部实现:具体标签

从内部视角来看,配置 profile 有如下语法要求:

1️⃣ profiles / profile 标签

  • 由于 profile 天然代表众多可选配置中的一个,所以由复数形式的 profiles 标签统一管理。
  • 由于 profile 标签覆盖了 pom.xml 中的默认配置,所以 profiles 标签通常是 pom.xml 中的最后一个标签。

2️⃣ id 标签

每个 profile 都必须有一个 id 标签,指定该 profile 的唯一标识。这个 id 标签的值会在命令行调用 profile 时被用到。这个命令格式是:

-D<profile id>

3️⃣ 其它允许出现的标签

一个 profile 可以覆盖项目的 最终名称项目依赖插件配置 等各个方面以影响构建行为。

  • build
  • defaultGoal
  • finalName
  • resources
  • testResources
  • plugins
  • reporting
  • modules
  • dependencies
  • dependencyManagement
  • repositories
  • pluginRepositories
  • properties

6.3 激活 profile

1️⃣ 默认配置默认被激活

前面提到了,POM 中没有在 profile 标签里的就是默认的 profile,当然默认被激活。

2️⃣ 基于环境信息激活

环境信息包含:JDK 版本操作系统参数文件属性 等各个方面。一个 profile 一旦被激活,那么它定义的所有配置都会覆盖原来 POM 中对应层次的元素。可参考下面的标签结构:

<profile>
  <id>dev</id>
    <activation>
        <!-- 配置是否默认激活 -->
      <activeByDefault>false</activeByDefault>
        <jdk>1.5</jdk>
        <os>
          <name>Windows XP</name>
            <family>Windows</family>
            <arch>x86</arch>
            <version>5.1.2600</version>
        </os>
        <property>
          <name>mavenVersion</name>
            <value>2.0.5</value>
        </property>
        <file>
          <exists>file2.properties</exists>
            <missing>file1.properties</missing>
        </file>
    </activation>
</profile>

这里有个问题是:多个激活条件之间是什么关系呢?

  • Maven 3.2.2 之前:遇到第一个满足的条件即可激活,或的关系。
  • Maven 3.2.2 开始:各条件均需满足,且的关系。

下面我们来看一个具体例子。假设有如下 profile 配置,在 JDK 版本为 1.6 时被激活:

<profiles>
  <profile>
      <id>JDK1.6</id>
        <activation>
            <!-- 指定激活条件为:JDK 1.6 -->
          <jdk>1.6</jdk>
        </activation>
        ……
    </profile>
</profiles>

这里需要指出的是:Maven 会自动检测当前环境安装的 JDK 版本,只要 JDK 版本是以 1.6 开头都算符合条件。下面几个例子都符合:

  • 1.6.0_03
  • 1.6.0_02
  • ……

6.4 Maven profile 多环境管理

在开发过程中,我们的软件会面对不同的运行环境,比如开发环境、测试环境、生产环境,而我们的软件在不同的环境中,有的配置可能会不一样,比如数据源配置、日志文件配置、以及一些软件运行过程中的基本配置,那每次我们将软件部署到不同的环境时,都需要修改相应的配置文件,这样来回修改,很容易出错,而且浪费劳动力。

因此我们可以利用 Maven 的 profile 来进行定义多个 profile,然后每个 profile 对应不同的激活条件和配置信息,从而达到不同环境使用不同配置信息的效果。

<build>
    <!-- profile对资源的操作 -->
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <!-- 先排除所有环境相关的配置文件 -->
            <excludes>
                <exclude>application*.yml</exclude>
            </excludes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <!-- 是否替换 @xx@ 表示的maven properties属性值 -->
            <!--通过开启 filtering,maven 会将文件中的 @xx@ 替换 profile 中定义的 xx 变量/属性-->
            <filtering>true</filtering>
            <includes>
                <include>application.yml</include>
                <include>application-${profileActive}.yml</include>
            </includes>
        </resource>
    </resources>
</build>

<!--多环境文件配置-->
<profiles>
    <!--开发环境-->
    <profile>
        <id>dev</id>
        <activation>
            <!--默认激活-->
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <profileActive>dev</profileActive>
        </properties>
    </profile>
    <!--测试环境-->
    <profile>
        <id>test</id>
        <properties>
            <profileActive>test</profileActive>
        </properties>
    </profile>
    <!--正式环境-->
    <profile>
        <id>prod</id>
        <properties>
            <profileActive>prod</profileActive>
        </properties>
    </profile>
</profiles>

idea 中可以看到,因此,当你需要打包哪一个环境的就勾选即可:

在这里插入图片描述
同时,SpringBoot 天然支持多环境配置,一般来说,application.yml 存放公共的配置,application-dev.ymlapplication-test.ymlapplication.prod.yml 分别存放三个环境的配置。如下:
在这里插入图片描述
application.yml 中配置 spring.profiles.active=prod(或者 devtest)指定使用的配置文件,如下:

在这里插入图片描述
注:profileActive,就是上面我们自定义的标签。

然后当我们勾选哪一个环境,打包的配置文件就是那一个环境:

在这里插入图片描述
同时我们再在 resource 标签下看到 includesexcludes 标签。它们的作用是:

  • includes:指定执行 resource 阶段时要包含到目标位置的资源。
  • excludes:指定执行 resource 阶段时要排除的资源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/421735.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue+SpringBoot打造个人保险管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 登录注册模块2.2 保险档案模块2.3 保险订单模块2.4 保险理赔模块 三、系统展示四、核心代码4.1 查询保险产品4.2 新增保险预定4.3 订单支付4.4 新增理赔单4.5 查询保险理赔 五、免责说明 一、摘要 1.1 项目介绍 基于J…

计算以e为底1+x的自然对数 即ln(1+x) math.log1p(x)

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 计算以e为底 1x的自然对数 即ln(1x) math.log1p(x) [太阳]选择题 请问执行以下程序的运行结果是&#xff1a; import math print("【执行】math.log1p(0)") print (math.log1p(0)) …

服务端向客户端推送数据的实现方案

在日常的开发中&#xff0c;我们经常能碰见服务端需要主动推送给客户端数据的业务场景&#xff0c;比如数据大屏的实时数据&#xff0c;比如消息中心的未读消息&#xff0c;比如聊天功能等等。 本文主要介绍SSE的使用场景和如何使用SSE。 服务端向客户端推送数据的实现方案有哪…

Vue路由模式

聚沙成塔每天进步一点点 本文内容 ⭐ 专栏简介路由模式1. Hash 模式2. History 模式选择路由模式的考虑因素 ⭐ 写在最后 ⭐ 专栏简介 Vue学习之旅的奇妙世界 欢迎大家来到 Vue 技能树参考资料专栏&#xff01;创建这个专栏的初衷是为了帮助大家更好地应对 Vue.js 技能树的学习…

Node.js中的数据加密和安全传输

在当今日益数字化的世界中&#xff0c;数据安全一直是一个备受关注的话题。Node.js作为一种流行的后端开发技术&#xff0c;其在数据加密和安全传输方面的应用也备受关注。本篇博客将深入探讨Node.js中的数据加密和安全传输相关内容&#xff0c;并为读者提供一些示例代码&#…

vue实现水印功能

目录 一、应用场景 二、实现原理 三、详细开发 1.水印的实现方式 2.防止用户通过控制台修改样式去除水印效果&#xff08;可跳过&#xff0c;有弊端&#xff09; 3.水印的使用 &#xff08;1&#xff09;单页面/全局使用 &#xff08;2&#xff09;全局使用个别页面去掉…

【投稿优惠|快速见刊】2024年图像,机器学习和人工智能国际会议(ICIMLAI 2024)

【投稿优惠|快速见刊】2024年图像&#xff0c;机器学习和人工智能国际会议&#xff08;ICIMLAI 2024&#xff09; 重要信息 会议官网&#xff1a;http://www.icimlai.com会议地址&#xff1a;深圳召开日期&#xff1a;2024.03.30截稿日期&#xff1a;2024.03.20 &#xff08;先…

音视频开发之旅(72)- AI数字人-照片说话之SadTalker

目录 1.效果展示 2.SadTalker原理学习 3.SadTalker代码流程分析 4.性能优化 5.参考资料 AI数字人目前做的最好的无疑是heygen&#xff0c;但是费用也是很贵&#xff0c;也有一些其他的商业应用&#xff0c;比如&#xff1a;微软小冰、腾讯智影、万兴播爆和硅基智能等。 而…

如何确保JDK版本与操作系统架构匹配?

1. 序言 最近的工作中&#xff0c;需要升级JDK版本到17.0.7&#xff0c;以解决一个JDK bug&#xff1a;JDK-8299626该bug的core dump关键字如下&#xff1a;SIGSEGV in PhaseIdealLoop::build_loop_late_post_work公司JDK团队提供的、包含JDK的基础镜像&#xff0c;有aarch64和…

基于C#开发OPC DA客户端——搭建KEPServerEX服务

简介 OPC DA (OLE for Process Control Data Access) 是一种工业自动化领域中的通信协议标准&#xff0c;它定义了应用程序如何访问由OPC服务器提供的过程控制数据。OPC DA标准允许软件应用程序&#xff08;客户端&#xff09;从OPC服务器读取实时数据或向服务器写入数据&…

elment-ui table表格排序后 清除排序箭头/恢复默认排序 的高亮样式

问题描述&#xff1a; 1.默认排序是按照名称升序排列&#xff08;图一&#xff09; 2.在选择了筛选项以及其他排序方式之后&#xff0c;箭头高亮是这样的&#xff08;图二&#xff09; 3.当我点击清空按钮后&#xff0c;类型清空了&#xff0c;并且传给后端的排序方式是名称/升…

数据库管理-第157期 Oracle Vector DB AI-08(20240301)

数据库管理157期 2024-03-01 数据库管理-第157期 Oracle Vector DB & AI-08&#xff08;20240301&#xff09;1 创建示例向量2 查找最近向量3 基于向量簇组的最近向量查询总结 数据库管理-第157期 Oracle Vector DB & AI-08&#xff08;20240301&#xff09; 作者&…

蓝桥杯-单片机组基础5——外部中断与LED的控制(附小蜜蜂课程代码)

蓝桥杯单片机组备赛指南请查看这篇文章&#xff1a;戳此跳转蓝桥杯备赛指南文章 本文章针对蓝桥杯-单片机组比赛开发板所写&#xff0c;代码可直接在比赛开发板上使用。 型号&#xff1a;国信天长4T开发板&#xff08;绿板&#xff09;&#xff0c;芯片&#xff1a;IAP15F2K6…

二叉搜索树在线OJ题讲解

二叉树创建字符串 我们首先进行题目的解读&#xff1a; 大概意思就是用&#xff08;&#xff09;把每个节点的值给括起来&#xff0c;然后再经过一系列的省略的来得到最后的结果 大家仔细观察题目给出的列子就可以发现&#xff0c;其实这个题目可以大致分为三种情况&#xff1…

git安装与使用4.3

一、git的安装 1、下载git包 下载git包url&#xff1a;https://git-scm.com/download/win 下载包分为&#xff1a;64位和32位 2、点击安装包 2、选择安装路径 3、 点击下一步 4、点击next 5、点击next 6、点击next 7、 8、 9、 10、 11、 12、在桌面空白处&#xff0c;右键…

服务器上部署WEb服务方法

部署Web服务在服务器上是一个比较复杂的过程。这不仅仅涉及到配置环境、选择软件和设置端口&#xff0c;更有众多其它因素需要考虑。以下是在服务器上部署WEb服务的步骤&#xff1a; 1. 选择服务器&#xff1a;根据项目规模和预期访问量&#xff0c;选择合适的服务器类型和配置…

2024.02.29作业

1. TCP模型 server #include "test.h"#define SER_IP "192.168.191.128" #define SER_PORT 9999int main(int argc, char const *argv[]) {int sfd -1;sfd socket(AF_INET, SOCK_STREAM, 0);if (-1 sfd){perror("socket error");return -1;…

Tomcat部署Web服务器及基础功能配置

前言 Tomcat作为一款网站服务器&#xff0c;目前市面上Java程序使用的比较多&#xff0c;作为运维工人&#xff0c;有必要了解一款如何去运行Java环境的网站服务。 目录 一、Java相关介绍 1. Java历史 2. Java跨平台服务 3. Java实现动态网页功能 3.1 servelt 3.2 jsp …

【排序算法】基数排序

一&#xff1a;基本概念 1.1 基数排序(桶排序)介绍 基数排序&#xff08;radix sort&#xff09;属于“分配式排序”&#xff08;distribution sort&#xff09;&#xff0c;又称“桶子法”&#xff08;bucket sort&#xff09;或bin sort&#xff0c;顾名思义&#xff0c;它是…

2024最新ChatGPT网站源码AI绘画系统:SparkAI系统(Ai智能问答系统和Midjourney绘画系统)

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持GPT…