【数据层解决方案】NOSQL:Redis,MongoDB,ES
目录结构
- SpringBoot整合Redis
- 一、认识Redis
- 1. 启动服务器
- 2. 启动客户端
- 3. Windows基本操作
- 4. hash结构
- 二、SpringBoot整合Redis
- 1. 导入springboot整合redis的starter坐标
- 2. 进行基础配置
- 3. RedisTemplate测试
- 4. StringRedisTemplate(常用)
- 5. redis客户端选择
- SpringBoot整合MongoDB
- 一、认识MongoDB
- 1. 启动服务器
- 2. 启动客户端
- 3. 基本操作
- 二、SpringBoot整合MongoDB
- 1. 先导入对应技术的整合starter坐标
- 2. 配置必要信息
- 3. 使用提供的API操作即可
- SpringBoot整合ES
- 一、ES介绍
- 二、安装Elasticsearch
- 三、安装Kibana
- 四、介绍ES中的一些概念
- 集群
- 节点
- 索引---数据库
- 文档---数据库中表中一条记录
- 分片
- 副本
- 五、操作ES
- 六、Spring Boot整合ES
SpringBoot整合Redis
一、认识Redis
Redis是一款采用key-value数据存储格式的内存级NoSQL数据库,重点关注数据存储格式,是key-value格式
,也就是键值对的存储形式
。与MySQL数据库不同,MySQL数据库有表、有字段、有记录,Redis没有这些东西,就是一个名称对应一个值,并且数据以存储在内存中使用为主。什么叫以存储在内存中为主?其实Redis有它的数据持久化方案,分别是RDB和AOF,但是Redis自身并不是为了数据持久化而生的,主要是在内存中保存数据,加速数据访问的
,所以说是一款内存级数据库。
Redis是一个开源的(BSD许可),内存中的数据结构存储,用作数据库,缓存和消息代理。它支持数据结构,如字符串、散列、列表、集合、使用范围查询的排序集合、位图、超loglog、使用半径查询的地理空间索引和流。Redis有内置的复制,Lua脚本,LRU驱逐,事务和不同级别的磁盘持久性,并提供高可用性通过Redis哨兵和自动分区与Redis集群
redis的特点
速度快
写速度能达到:80000次/S,读速度100000次/秒,基于内存的。使用C语言编写。支持的数据结构丰富
string字符串,hash(key-value),set(集合),zset(有序集合),list(列表)支持的开发语言丰富
支持主从复制(集群)
redis集群的基础就是主从复制,10G/s.支持数据的持久化
memecached基于内存的nosql(not only sql)数据库,不能够持久化。redis支持数据的持久化(AOF,到期时间,RDB)
Linux安装:
步骤一:安装最新的redis,需要安装Remi的软件源,官网地址:http://rpms.famillecollet.com
yum install -y http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
如果安装失败,安装一下epel源
yum -y install epel-release
步骤二:安装redis(默认安装最新版本)
yum --enablerepo=remi install -y redis
步骤三:查看redis版本号
redis-cli --version
步骤四:修改 /etc/redis.conf 文件
# 允许访问的地址,默认是127.0.0.1,会导致只能在本地访问。修改为0.0.0.0则可以在任意IP访问,生产环境不要设置为0.0.0.0
bind 0.0.0.0
# 守护进程,修改为yes后即可后台运行
daemonize yes
# 密码,设置后访问Redis必须输入密码
requirepass 123321
redis常见的其他配置
# 监听的端口
port 6379
# 工作目录,默认是当前目录,也就是运行redis-server时的命令,日志、持久化等文件会保存在这个目录
dir .
# 数据库数量,设置为1,代表只使用1个库,默认有16个库,编号0~15
databases 1
# 设置redis能够使用的最大内存
maxmemory 512mb
# 日志文件,默认为空,不记录日志,可以指定日志文件名
logfile "redis.log"
上诉配置的日志文件在工作目录中,文件名为redis.log
步骤五:启动服务
- 查看状态
systemctl status redis.service - 启动服务
systemctl start redis.service - 关闭服务
systemctl stop redis.service
windows版安装包下载地址:
https://github.com/tporadowski/redis/releases
下载的安装包有两种形式,一种是一键安装的msi文件,还有一种是解压缩就能使用的zip文件,哪种形式都行,这里就不介绍安装过程了,本课程采用的是msi一键安装的msi文件进行安装的。
啥是msi?
- 其实就是一个文件安装包,不仅安装软件,还帮你把安装软件时需要的功能关联在一起,打包操作。比如如安装序列、创建和设置安装路径、设置系统依赖项、默认设定安装选项和控制安装过程的属性。说简单点就是一站式服务,安装过程一条龙操作一气呵成,就是为小白用户提供的软件安装程序。
装完毕后会得到如下文件,其中有两个文件对应两个命令,是启动Redis的核心命令,需要再CMD命令行模式执行。
1. 启动服务器
redis-server.exe redis.windows.conf
初学者无需调整服务器对外服务端口,默认6379。
2. 启动客户端
redis-cli.exe
注意:
如果启动redis服务器失败,可以先启动客户端,然后执行shutdown操作后退出,此时redis服务器就可以正常执行了。
3. Windows基本操作
服务器启动后,使用客户端就可以连接服务器,类似于启动完MySQL数据库,然后启动SQL命令行操作数据库。
放置一个字符串数据到redis中,先为数据定义一个名称,比如name,age等,然后使用命令set设置数据到redis服务器中即可
set name itheima
set age 12
从redis中取出已经放入的数据,根据名称取,就可以得到对应数据。如果没有对应数据就会得到(nil)
get name
get age
nil相当于null,意思为空
4. hash结构
以上使用的数据存储是一个名称对应一个值,如果要维护的数据过多,可以使用别的数据存储结构。例如hash,它是一种一个名称下可以存储多个数据的存储模型,并且每个数据也可以有自己的二级存储名称。向hash结构中存储数据格式如下:
hset a a1 aa1 #对外key名称是a,在名称为a的存储模型中,a1这个key中保存了数据aa1
hset a a2 aa2
获取hash结构中的数据命令如下
hget a a1 #得到aa1
hget a a2 #得到aa2
二、SpringBoot整合Redis
经过若干种技术的整合后基本上可以总结出一套固定思维
第一,需要先导入对应技术的坐标,而整合之后,这些坐标都有了一些变化第二,任何技术通常都会有一些相关的设置信息,整合之后,这些信息如何写,写在哪是一个问题
第三,没有整合之前操作如果是模式A的话,整合之后如果没有给开发者带来一些便捷操作,那整合将毫无意义,所以整合后操作肯定要简化一些,那对应的操作方式自然也有所不同
下面就开始springboot整合redis,操作步骤如下:
1. 导入springboot整合redis的starter坐标
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
如果在新建项目时勾选的话,有两个关于redis的勾,目前选第一个
Spring Data Redis(Access+Driver)
就行
2. 进行基础配置
默认就是localhost 6379 ,如果符合的话可以不写
spring:redis:host: localhostport: 6379
3. RedisTemplate测试
使用springboot整合redis的专用客户端接口操作,此处使用的是RedisTemplate
@SpringBootTest
class SpringbootRedisApplicationTests {@Autowiredprivate RedisTemplate redisTemplate;@Testvoid set() {ValueOperations ops = redisTemplate.opsForValue();ops.set("age",18);}@Testvoid get() {ValueOperations ops = redisTemplate.opsForValue();System.out.println(ops.get("age"));}@Testvoid hset() {HashOperations ops = redisTemplate.opsForHash();ops.put("info","b","bb");}@Testvoid hget() {HashOperations ops = redisTemplate.opsForHash();Object val = ops.get("info", "b");System.out.println(val);}
}
在操作redis时,需要先确认操作何种数据,根据数据种类得到操作接口。例如使用opsForValue()获取string类型的数据操作接口,使用opsForHash()获取hash类型的数据操作接口,剩下的就是调用对应api操作了。各种类型的数据操作接口如下:
总结
- springboot整合redis步骤
- 导入springboot整合redis的starter坐标
- 进行基础配置
- 使用springboot整合redis的专用客户端接口RedisTemplate操作
4. StringRedisTemplate(常用)
由于redis内部不提供java对象的存储格式,因此当操作的数据以对象的形式存在时,会进行转码,转换成字符串格式后进行操作。为了方便开发者使用基于字符串为数据的操作
,springboot整合redis时提供了专用的API接口StringRedisTemplate,你可以理解为这是RedisTemplate的一种指定数据泛型的操作API。
@SpringBootTest
public class StringRedisTemplateTest {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testvoid get(){ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();String name = ops.get("name");System.out.println(name);}
}
- 使用StringRedisTemplate可以拿到我们在
黑窗口
中设置的值。(等效)- 修改原先的值,是相同的key重新set一遍
5. redis客户端选择
springboot整合redis技术提供了多种客户端兼容模式,默认提供的是lettucs客户端技术,也可以根据需要切换成指定客户端技术,例如jedis客户端技术,切换成jedis客户端技术操作步骤如下:
- 导入jedis坐标
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId>
</dependency>
jedis坐标受springboot管理,无需提供版本号
- 配置客户端技术类型,设置为jedis
spring:redis:host: localhostport: 6379client-type: jedis
- 根据需要设置对应的配置
spring:redis:host: localhostport: 6379client-type: jedislettuce:pool:max-active: 16jedis:pool:max-active: 16
lettcus与jedis区别
- jedis连接Redis服务器是直连模式,当多线程模式下使用jedis会存在线程安全问题,解决方案可以通过配置连接池使每个连接专用,这样整体性能就大受影响
- lettcus基于Netty框架进行与Redis服务器连接,底层设计中采用StatefulRedisConnection。 StatefulRedisConnection自身是线程安全的,可以保障并发访问安全问题,所以一个连接可以被多线程复用。当然lettcus也支持多连接实例一起工作
总结
- springboot整合redis提供了StringRedisTemplate对象,以字符串的数据格式操作redis
- 如果需要切换redis客户端实现技术,可以通过配置的形式进行
SpringBoot整合MongoDB
一、认识MongoDB
使用Redis技术可以有效的提高数据访问速度,但是由于Redis的数据格式单一性,无法操作结构化数据,当操作对象型的数据时,Redis就显得捉襟见肘。在保障访问速度的情况下,如果想操作结构化数据,看来Redis无法满足要求了,此时需要使用全新的数据存储结束来解决此问题
MongoDB是一个开源、高性能、无模式的文档型数据库,它是NoSQL数据库产品中的一种,是最像关系型数据库的非关系型数据库。
其中对于我们最陌生的词是无模式的。什么叫无模式呢?简单说就是作为一款数据库,没有固定的数据存储结构,第一条数据可能有A、B、C一共3个字段,第二条数据可能有D、E、F也是3个字段,第三条数据可能是A、C、E3个字段,也就是说数据的结构不固定,这就是无模式。有人会说这有什么用啊?灵活,随时变更,不受约束。基于上述特点,MongoDB的应用面也会产生一些变化。以下列出了一些可以使用MongoDB作为数据存储的场景,但是并不是必须使用MongoDB的场景:
- 淘宝用户数据
- 存储位置:数据库
- 特征:永久性存储,修改频度极低
- 游戏装备数据、游戏道具数据
- 存储位置:数据库、Mongodb
- 特征:永久性存储与临时存储相结合、修改频度较高
- 直播数据、打赏数据、粉丝数据
- 存储位置:数据库、Mongodb
- 特征:永久性存储与临时存储相结合,修改频度极高
- 物联网数据
- 存储位置:Mongodb
- 特征:临时存储,修改频度飞速
windows版安装包下载地址:https://www.mongodb.com/try/download
1. 启动服务器
mongod --dbpath=..\data\db
启动服务器时需要指定数据存储位置,通过参数–dbpath进行设置,可以根据需要自行设置数据存储路径。默认服务端口27017。
2. 启动客户端
mongo --host=127.0.0.1 --port=27017
3. 基本操作
MongoDB虽然是一款数据库,但是它的操作并不是使用SQL语句进行的,因此操作方式各位小伙伴可能比较陌生,好在有一些类似于Navicat的数据库客户端软件,能够便捷的操作MongoDB,先安装一个客户端,再来操作MongoDB。
同类型的软件较多,本次安装的软件时Robo3t,Robot3t是一款绿色软件,无需安装,解压缩即可。解压缩完毕后进入安装目录双击robot3t.exe即可使用。
连接成功后在命令输入区域输入命令即可操作MongoDB。
创建数据库:在左侧菜单中使用右键创建,输入数据库名称即可
创建集合:在Collections上使用右键创建,输入集合名称即可,集合等同于数据库中的表的作用
新增文档:(文档是一种类似json格式的数据,初学者可以先把数据理解为就是json数据)
db.集合名称.insert/save/insertOne(文档)
删除文档:
db.集合名称.remove(条件)
修改文档:
db.集合名称.update(条件,{操作种类:{文档}})
查询文档:
基础查询
查询全部: db.集合.find();
查第一条: db.集合.findOne()
查询指定数量文档: db.集合.find().limit(10) //查10条文档
跳过指定数量文档: db.集合.find().skip(20) //跳过20条文档
统计: db.集合.count()
排序: db.集合.sort({age:1}) //按age升序排序
投影: db.集合名称.find(条件,{name:1,age:1}) //仅保留name与age域条件查询
基本格式: db.集合.find({条件})
模糊查询: db.集合.find({域名:/正则表达式/}) //等同SQL中的like,比like强大,可以执行正则所有规则
条件比较运算: db.集合.find({域名:{$gt:值}}) //等同SQL中的数值比较操作,例如:name>18
包含查询: db.集合.find({域名:{$in:[值1,值2]}}) //等同于SQL中的in
条件连接查询: db.集合.find({$and:[{条件1},{条件2}]}) //等同于SQL中的and、or
二、SpringBoot整合MongoDB
1. 先导入对应技术的整合starter坐标
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
2. 配置必要信息
spring:data:mongodb:uri: mongodb://localhost/itheima
3. 使用提供的API操作即可
@SpringBootTest
class Springboot17MongodbApplicationTests {@Autowiredprivate MongoTemplate mongoTemplate;@Testvoid contextLoads() {Book book = new Book();book.setId(2);book.setName("springboot2");book.setType("springboot2");book.setDescription("springboot2");mongoTemplate.save(book);}@Testvoid find(){List<Book> all = mongoTemplate.findAll(Book.class);System.out.println(all);}
}
springboot整合MongoDB步骤
- 导入springboot整合MongoDB的starter坐标
- 进行基础配置
- 使用springboot整合MongoDB的专用客户端接口MongoTemplate操作
SpringBoot整合ES
一、ES介绍
Redis可以使用内存加载数据并实现数据快速访问,MongoDB可以在内存中存储类似对象的数据并实现数据的快速访问,在企业级开发中对于速度的追求是永无止境的。ES也是一款NoSQL解决方案,只不过他的作用不是为了直接加速数据的读写,而是加速数据的查询的。
ES(Elasticsearch)是一个分布式全文搜索引擎,重点是全文搜索。
那什么是全文搜索呢?比如用户要买一本书,以Java为关键字进行搜索,不管是书名中还是书的介绍中,甚至是书的作者名字,只要包含java就作为查询结果返回给用户查看,上述过程就使用了全文搜索技术。搜索的条件不再是仅用于对某一个字段进行比对,而是在一条数据中使用搜索条件去比对更多的字段,只要能匹配上就列入查询结果,这就是全文搜索的目的。而ES技术就是一种可以实现上述效果的技术。
要实现全文搜索的效果,不可能使用数据库中like操作去进行比对,这种效率太低了。ES设计了一种全新的思想,来实现全文搜索。具体操作过程如下:
将被查询的字段的数据全部文本信息进行查分,分成若干个词
- 例如“中华人民共和国”就会被拆分成三个词,分别是“中华”、“人民”、“共和国”,此过程有专业术语叫做分词。分词的策略不同,分出的效果不一样,不同的分词策略称为分词器。
将分词得到的结果存储起来,对应每条数据的id
例如id为1的数据中名称这一项的值是“中华人民共和国”,那么分词结束后,就会出现“中华”对应id为1,“人民”对应id为1,“共和国”对应id为1
例如id为2的数据中名称这一项的值是“人民代表大会“,那么分词结束后,就会出现“人民”对应id为2,“代表”对应id为2,“大会”对应id为2
此时就会出现如下对应结果,按照上述形式可以对所有文档进行分词。需要注意分词的过程不是仅对一个字段进行,而是对每一个参与查询的字段都执行,最终结果汇总到一个表格中
分词结果关键字 | 对应id |
---|---|
中华 | 1 |
人民 | 1,2 |
共和国 | 1 |
代表 | 2 |
大会 | 2 |
- 当进行查询时,如果输入“人民”作为查询条件,可以通过上述表格数据进行比对,得到id值1,2,然后根据id值就可以得到查询的结果数据了。
上述过程中分词结果关键字内容每一个都不相同,作用有点类似于数据库中的索引,是用来加速数据查询的。但是数据库中的索引是对某一个字段进行添加索引,而这里的分词结果关键字不是一个完整的字段值,只是一个字段中的其中的一部分内容。并且索引使用时是根据索引内容查找整条数据,全文搜索中的分词结果关键字查询后得到的并不是整条的数据,而是数据的id,要想获得具体数据还要再次查询,因此这里为这种分词结果关键字起了一个全新的名称,叫做倒排索引。
使用ES其实准备工作还是挺多的,必须先建立文档的倒排索引,然后才能继续使用。
二、安装Elasticsearch
windows版安装包下载地址:https://www.elastic.co/cn/downloads/elasticsearch
将压缩包下载后,解压
- bin目录:包含所有的可执行命令
- config目录:包含ES服务器使用的配置文件
- jdk目录:此目录中包含了一个完整的jdk工具包,版本17,当ES升级时,使用最新版本的jdk确保不会出现版本支持性不足的问题
- lib目录:包含ES运行的依赖jar文件
- logs目录:包含ES运行后产生的所有日志文件
- modules目录:包含ES软件中所有的功能模块,也是一个一个的jar包。和jar目录不同,jar目录是ES运行期间依赖的jar包,modules是ES软件自己的功能jar包
- plugins目录:包含ES软件安装的插件,默认为空
启动ES(双击即可)
浏览器访问
9200:表示公开对外的端口号
9300:表示集群成员之间的端口号
三、安装Kibana
1、kibana是es数据的前端展现,数据分析时,可以方便地看到数据。作为开发人员,可以方便访问es。
https://www.elastic.co/cn/downloads/
历史版本下载:https://www.elastic.co/cn/downloads/past-releases/
2、下载,解压kibana。
3、启动Kibana:bin\kibana.bat
浏览器访问 http://localhost:5601
默认端口为:5601
可能会出现的问题:
运行Kibana.bat,启动失败,报错大概意思是已经存在一个启动的Kibana了,但明明是第一次启动
报错:
[warning][savedobjects-service] Unable to connect to Elasticsearch.
Error: [resource_already_exists_exception] index [.kibana_task_manager_1/_2s2vHazSRqCl7dPlZ_oQQ] already exists, with { index_uuid="_2s2vHazSRqCl7dPlZ_oQQ" & index=".kibana_task_manager_1" }
在cmd中运行如下命令:
curl -X DELETE http://localhost:9200/.kibana*
四、介绍ES中的一些概念
集群
集群这一概念已经遍及天下了,在Elasticsearch中也不例外,可以将多台Elasticsearch节点组成集群使用,可以在任意一台节点上进行搜索。
节点
节点是一台Elasticsearch服务器,可以存储、查询、创建索引,也可以与其它节点一共组成一个集群。
索引—数据库
索引是具有某种相似特性的文档集合,熟悉mysql的应该不会对于这个名词陌生,Elasticsearch使用的是倒排索引。
文档—数据库中表中一条记录
一个文档是一个可以被索引的基础信息单元。
分片
单个索引包含数据太大的话,将会降低索引速度。为此,Elasticsearch提供了将索引细分成多个片段的能力,就是分片。
副本
副本是ElasticSearch索引分片的备份,主要应对与节点故障时保存数据的可用性。副本与它的原始分片不会在同一个节点上,以此来保存单节点故障时的高可用。
注意: ES6.0以后Type这个概念模糊了,7.0以后不在使用Type. 默认索引的type都是_doc。
五、操作ES
ES中提供了大量的接口—这些接口要想访问必须按照restful风格来访问。
POST 添加操作 DELETE 删除操作 PUT 修改操作 GET 查询操作
可以在地址栏以地址的形式传递参数 /user/1
详细操作:
【Elasticsearch】Elasticsearch命令行操作
六、Spring Boot整合ES
链接:
xxx…
【数据层解决方案】NOSQL:Redis,MongoDB,ES相关推荐
- 一步一步教你使用AgileEAS.NET基础类库进行应用开发-基础篇-基于接口驱动的数据层...
系列回顾 在前面的文章中,我用了大量的篇幅对UDA及ORM的使用进行了讲解和演示,我们已经知道并熟悉的使用UDA和ORM构建简单的应用,AgileEAS.NET在应用的纵向结构上建议使用分层结构,提出 ...
- 前端 重构时需要注意的事项_前端数据层落地实践
源宝导读:天际移动平台经过重构改版,近期正式发布了1.0版本,我们在低代码开发方面做了进一步增强.本文主要围绕前端Model.前端业务逻辑(领域模型).数据层与视图层解耦(包装器模式)3个方面,给大家 ...
- Memcache,Redis,MongoDB(数据缓存系统)方案对比与分析
一.问题: 数据库表数据量极大(千万条),要求让服务器更加快速地响应用户的需求. 二.解决方案: 1.通过高速服务器Cache缓存数据库数据 2.内存数据库 (这里仅从 ...
- Nosql进阶笔记之redis MongoDB
Nosql 简介 NoSQL指的是非关系型的数据库.其实,NoSQL概念最早出现在1998年,当时的含义是反SQL技术革命运动,但并未引起太多的关注.直到2009年,NoSQL概念被来自Rackspa ...
- NoSQL数据库-MongoDB和Redis
NoSQL数据库-MongoDB和Redis 发布于2012-12-20,来源:比特网 1NoSQL简述 CAP(Consistency,Availabiity,Partitiontolera ...
- linux yun 安装 redis,Linux系统安装NoSQL(MongoDB和Redis)步骤及问题解决办法(总结篇)...
如下是我工作中的记录,介绍的是linux系统下NoSQL:MongoDB和Redis的安装过程和遇到的问题以及解决办法: 需要的朋友可以按照如下步骤进行安装,可以快速安装MongoDB和Redis,希 ...
- 基于Scrapy+redis+mongodb+scrapyd+scrapydweb+Pandas+BI的可视化操作分布式网络爬虫数据可视化分析
提示:所有代码已经开源到最大同性交友网站,有兴趣的朋友可以试试:Git地址 未经作者允许不得私自转发 请注明原作者:https://blog.csdn.net/qq_52420866/article/ ...
- NOSQL——redis的安装,配置与简单操作
内容预知 1.缓存的相关知识 1.1 缓存的概念 1.2 系统缓存 1.3 缓存保存位置及分层结构 DNS缓存 应用层缓存 数据层缓存 硬件缓存 2.关系型数据与非关系型数据库 2.1 关系型数据库 ...
- MongoDB(3)--有关NoSQL及MongoDB的一些概念
学习任何东西在没有理解的前提下去背熟一些概念是没有用的,就像只背会了几个概念而没有理解的开发人员去面试是经不住面试官的追问的.前面的两篇对MongoDB做了简单的介绍,能够很快上手,对MongoDB有 ...
最新文章
- 提高PHP编程效率的20个要点(转)
- Python模块之间的相互引用问题
- Eclipse配置的tomcat用debug模式启动不了start可以启动
- 201671030125+词频统计软件项目报告
- IDEA如何生成get和set方法
- Git图形化管理工具
- 重学java基础第十八课:卸载jdk和安装jdk
- 江湖不再平静---51CTO学院停服公告
- java.lang.UnsupportedClassVersionError: JVMCFRE003解决方法--jdk 1.6 中switch的参数无法使用String类型
- java多维数组的反射类型_Java多维数组和Arrays类方法总结详解
- centos系统安全设置
- python 日历热力图_Python如何绘制日历图和热力图
- 一篇文章看明白 TCP/IP,TCP,UDP,IP,Socket 之间的关系
- 实现基于小米的电子商务平台架构
- uefi如何安装linux系统教程,UEFI启动模式下安装Ubuntu教程
- 短说 3.7.1正式版更新【新增悬赏问答、打赏、付费看帖、IP属地】
- 京东物流-三维装箱(记录)
- 蓝懿ios技术交流和心得分享16.1.18
- 关于文字音译的网页(基于百度AI)
- C学习笔记——(4)数组和字符串说明,以及冒泡排序法