ES搜索引擎


☣ ☣

  • ES搜索引擎
    • 一、Kibana
    • 二、IK Analysis 中文分词器
      • 1、单机配置
        • ① 安装配置
        • ② 测试
    • 三、Elasticsearch导入MySQL数据
      • 1、安装Mysql⭐
      • 2、修改密码和配置
      • 3、数据库忘记密码
      • 4、安装Logstash
        • ① 安装与测试
        • ② 同步mysql数据
        • ③ 创建索引库shop与mapping
    • 四、Elasticsearch的JavaAPI
      • 1、创建项目并配置、测试
      • 2、SpingBooot整合ES
        • ①、创建项目并配置
        • ②、测试

一、Kibana

一款开源的数据分析和可视化平台,此处不做主要介绍


二、IK Analysis 中文分词器

  • Es的常用插件之一
  • IK Analysis插件将Lucene IK分析器集成到elasticsearch中,支持自定义词典。

1、单机配置

官网下载地址


① 安装配置

直接上传资源到linux,解压指定位置,并进行授权

# 创建ik目录
mkdir -p /usr/local/elasticsearch/es1/elasticsearch-7.4.2/plugins/ik
# 解压至ik目录
unzip elasticsearch-analysis-ik-7.4.2.zip -d /usr/local/elasticsearch/es1/elasticsearch-7.4.2/plugins/ik/
#授权个es账户
chown -Rf es:es /usr/local/elasticsearch/


重启ES,测试


② 测试

直接创建索引库和设置mapping

# 创建索引库
curl -X PUT http://localhost:9200/ik -H 'Content-Type:application/json' - d'{"settings": { "number_of_shards": 5, "number_of_replicas": 1
}
}'# 设置mapping
# Analyzer分词配置解释:
#ik_smart:粗粒度分词,比如中华人民共和国国歌,会拆分为中华人民共和国,国歌;
#ik_max_word:细粒度分词,比如中华人民共和国国歌,会拆分为中华人民共和国,中华
#人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌,会穷
#尽各种可能的组合。


插入数据

curl -XPOST http://localhost:9200/ik/_create/1 -H 'Content- Type:application/json' -d' {"content":"美国留给伊拉克的是个烂摊子吗"} '
curl -XPOST http://localhost:9200/ik/_create/2 -H 'Content- Type:application/json' -d' {"content":"公安部:各地校车将享最高路权"} '
curl -XPOST http://localhost:9200/ik/_create/3 -H 'Content- Type:application/json' -d' {"content":"中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"} '
curl -XPOST http://localhost:9200/ik/_create/4 -H 'Content- Type:application/json' -d' {"content":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"} '

启动Es(启动es要切换到es用户下)和head客户端查看结果:
这里看出,es自动加载了插件ik




进行数据索引查询


三、Elasticsearch导入MySQL数据

1、安装Mysql⭐

本文使用5.7.2X版本,如果找不到对应的版本信息,可以通过该地址获取: 下载(es可以说是一个非关系型数据库)



安装

yum -y install mysql57-community-release-el7.rpm
yum -y install mysql-community-server
#如果报错则更新wget
yum -y install wget
#启动查看服务器状态
systemctl start mysqld
systemctl status mysqld

这种安装方式会将MySQL添加至环境变量和启动服务


如果安装后启动失败:

#查看是否安装过数据库
rpm -qa|grep mysql
#删除以前安装的数据库
rpm -e 数据库文件名
#查看数据库安装后的目录
find / -name mysql
find / -name mysqld
#在重新安装

2、修改密码和配置

修改密码并授权

#获取安装后提供的密码
grep "password" /var/log/mysqld.log
#登录数据库
mysql -u root –p
#修改密码规则
set global validate_password_policy=0;
set global validate_password_length=4;
#修改密码
set password = password('root');
#退出重新进入

授权

# 改表法
# 选择数据库
use mysql;
# 最后授权MySQL,允许远程用户登录访问
MySQL update user set host = '%' where user = 'root';
# 刷新权限
flush privileges;
# 授权法
# 允许192.168.10.105(linuxIP地址)连接访问所有库的所有表(*.*),连接密码为1234
GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.10.105' IDENTIFIED BY '1234' WITH GRANT OPTION;
# 允许所有连接访问所有库的所有表(*.*),连接密码为1234
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '1234' WITH GRANT OPTION;
# 刷新权限
FLUSH PRIVILEGES;
#关闭防火墙
systemctl stop firewalld
#查看防火墙状态
systemctl status firewalld

一定要设置防火墙,否则windons客户端无法访问


3、数据库忘记密码

忘记密码的修改方法

# 展示所有数据库
show databases;
# 选择数据库
use mysql;
# 展示所有表
show tables;
# 忘记密码后修改密码
# 第一步的作用是启动时跳过验证
1. vi /etc/my.cnf在[mysqld]里加入skip-grant-tables
2. 重启mysql服务,连接mysql无密码登入use mysql;选择数据库
3. 敲下面这行代码修改密码 update mysql.user set authentication_string=password('root') where user='root';
4. vi /etc/my.cnf在[mysqld]里删除skip-grant-tables 重启mysql服务,新密码登录即可


4、安装Logstash

Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到您最喜欢的 “存储库” 中,Logstash技术,导入数据,实现数据录入,数据处理管道。下载地址


① 安装与测试

直接安装

#创建安装目录
mkdir -p /usr/local/logstash
#解压
tar -zxvf logstash-7.4.2.tar.gz -C /usr/local/logstash/


安装

cd /usr/local/logstash/logstash-7.4.2
bin/logstash -e 'input { stdin {} } output { stdout {} }'

成功运行输入helloworld返回一个helloworld就成功了


② 同步mysql数据

上传一个驱动jar,和两个配置文件jdbc.conf,jdbc.sql

#注意:请将mysql的驱动包上传至 logstash-7.4.2/logstash-core/lib/jars/ 目录下
/usr/local/logstash/logstash-7.4.2/logstash-core/lib/jars/
# jdbc.conf
# cd /usr/local/logstash/logstash-7.4.2
# vim jdbc.confjdbc {# 配置数据库信息jdbc_connection_string => "jdbc:mysql://192.168.168.129:3306/shop?useUnicode=true&cha
racterEncoding=UTF-8&useSSL=false"      jdbc_driver_class => "com.mysql.jdbc.Driver"jdbc_user => "root"jdbc_password => "1234"jdbc_paging_enabled => "true"jdbc_page_size => "50000"# 执行 sql 语句文件statement_filepath => "/usr/local/logstash/logstash-7.4.2/jdbc.sql"# 定时字段 各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新schedule => "* * * * *"# 是否将 sql 中 column 名称转小写lowercase_column_names => false}
}
output {elasticsearch {hosts => ["192.168.168.129:9200"]index => "shop"# 文档_id,%{goods_id}意思是取查询出来的goods_id的值,并将其映射到es的_id字段中# 文档_id,%{goodsId}如果是别名,意思是取查询出来的goodsId的值,并将其映射到es的_id
字段中        document_id => "%{goodsId}"}stdout {codec => json_lines}
}
--------------------------------------------------------------
# jdbc.sql
SELECTgoods_id goodsId,goods_name goodsName,market_price marketPrice,original_img originalImg
FROMt_goods
# 检测配置文件是否编写正确
bin/logstash -f /usr/local/logstash/logstash-7.4.2/jdbc.conf -t


③ 创建索引库shop与mapping

索引库

mapping:


# 执行数据导入(前提是数据库中shop数据库有数据)
cd /usr/local/logstash/logstash-7.4.2/
#配置文件回去直接调用jdbc.sql语句将查出来的数据导入到es中
bin/logstash -f /usr/local/logstash/logstash-7.4.2/jdbc.conf
#导入较慢

最终结果


查询测试:


四、Elasticsearch的JavaAPI

整合IDEA

1、创建项目并配置、测试

Elasticsearch有两种连接方式: transport 、 rest,ES官方建议使用 rest 方式,

  • 直接创建一个maven,java项目引入依赖
  <dependencies><!-- junit 单元测试依赖 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- elasticsearch 服务依赖 --><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.4.2</version></dependency><!-- rest-client 客户端依赖 --><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-client</artifactId><version>7.4.2</version></dependency><!-- rest-high-level-client 客户端依赖 --><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.4.2</version></dependency></dependencies>

创建测试类测试:

//连接服务器
public class EsTest {// ES服务器IPprivate final static String HOST = "192.168.168.129";// ES服务器连接方式private final static String SCHEME = "http";// 初始化 ES 服务器集群// 参数分别为:IP,端口,连接方式(默认为http)private final static HttpHost[] httpHosts = {new HttpHost(HOST, 9200, SCHEME)};//客户端private RestHighLevelClient client=null;/*** 获取客户端 */@Beforepublic void getConnect() {client = new RestHighLevelClient(RestClient.builder(httpHosts));}/*** 关闭连接 */@Afterpublic void closeConnect() {try {if (null != client)client.close();} catch (IOException e) {e.printStackTrace();}}/*** 查询数据 */@Testpublic void testRetrieve() throws IOException {// 指定索引库和idGetRequest getRequest = new GetRequest("ik", "4");// 执行请求GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);System.out.println(getResponse.getSource());}/*** 添加数据 */@Testpublic void testCreate() throws IOException {// 准备数据Map<String, Object> jsonMap = new HashMap<>();jsonMap.put("username", "zhangsan");jsonMap.put("age", 18);jsonMap.put("address", "sh");// 指定索引库和id及数据IndexRequest indexRequest = new IndexRequest("ik").id("5").source(jsonMap);//执行请求IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);System.out.println(indexResponse.toString());}/*** 修改数据 */@Testpublic void testUpdate() throws IOException {// 准备数据Map<String, Object> jsonMap = new HashMap<>();jsonMap.put("username", "lisi"); jsonMap.put("age", 20);jsonMap.put("address", "bj");// 指定索引库和id及数据UpdateRequest updateRequest = new UpdateRequest("ik", "5").doc(jsonMap);// 执行请求UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);System.out.println(updateResponse.toString());}/*** 批量查询-分页查询-高亮查询 */@Testpublic void testHighlight() throws IOException {// 指定索引库SearchRequest searchRequest = new SearchRequest("shop");// 构建查询对象SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();// 添加分页条件,从第 0 个开始,返回 5 个searchSourceBuilder.from((5-1)).size(5);// 构建高亮对象HighlightBuilder highlightBuilder = new HighlightBuilder();// 指定高亮字段和高亮样式highlightBuilder.field("goodsName").preTags("<span style='color:red;'>").postTags("</span>");searchSourceBuilder.highlighter(highlightBuilder);// 添加查询条件// 指定从 goodsName 字段中查询String key = "中国移动联通电信";searchSourceBuilder.query(QueryBuilders.multiMatchQuery(key, "goodsName"));// 执行请求searchRequest.source(searchSourceBuilder);SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);// 总条数System.out.println(searchResponse.getHits().getTotalHits().value);// 结果数据(如果不设置返回条数,大于十条默认只返回十条)SearchHit[] hits = searchResponse.getHits().getHits();for (SearchHit hit : hits) {// 构建项目中所需的数据结果集String highlightMessage = String.valueOf(hit.getHighlightFields().get("goodsName").fragments()[0]);Integer goodsId = Integer.valueOf((Integer) hit.getSourceAsMap().get("goodsId"));String goodsName = String.valueOf(hit.getSourceAsMap().get("goodsName"));BigDecimal marketPrice = new BigDecimal(String.valueOf(hit.getSourceAsMap().get("marketPrice")));String originalImg = String.valueOf(hit.getSourceAsMap().get("originalImg"));System.out.println("goodsId -> " + goodsId);System.out.println("goodsName -> " + goodsName);System.out.println("highlightMessage -> " + highlightMessage);System.out.println("marketPrice -> " + marketPrice);System.out.println("originalImg -> " + originalImg);System.out.println("----------------------------");}}
}


2、SpingBooot整合ES

①、创建项目并配置
  • 创建maven中java项目,引入依赖
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.0.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>

编写dao层与pojo接收对象

//dao层提供接口
public interface GoodsInter extends ElasticsearchRepository<Goods,Integer> {/*更具商品名查询*/public List<Goods> findByGoodsName(String goodsName);
}
//-------------------------------------------------------
//pojo
@Document(indexName = "shop",shards = 5,replicas = 1,createIndex = false)
public class Goods implements Serializable {/*** 商品id */@Idprivate Integer goodsId;/*** 商品名称 */@Field(type = FieldType.Text,analyzer = "ik_max_word")private String goodsName;/*** 市场价 */@Field(type = FieldType.Double)private BigDecimal marketPrice;/*** 商品上传原始图 */@Field(type = FieldType.Keyword)private String originalImg;/*** t_goods */private static final long serialVersionUID = 1L;//此处省略构造器和toString set get方法/**为需要使用索引库的实体类加上注解 @Document 部分属性如下
indexName="索引库名" shards = 分片数量(默认1) replicas = 副本数量(默认1)
为id属性 添加 @Id 注释
各个字段加上注解并制定类型 @Field 部分属性如下
type= FieldType.枚举 : 指定字段类型 Keyword不分词, Text分词 对应着
elasticsearch的字段类型
为需要分词的字段添加分词器 analyzer="分词器名" (ik分词器固定写法 ik_max_word )
是否创建索引 createIndex=boolean(默认true)**/

编写启动类

@SpringBootApplication
public class Start {public static void main(String[] args) {SpringApplication.run(Start.class,args);}
}
//测试文件目录与项目文件加目录要一直,否则扫描不到启动类,导致启动失败

②、测试

编写测试类

@SpringBootTest
public class EsTest {@AutowiredGoodsInter goodsInter;@Autowiredprivate ElasticsearchRestTemplate elasticsearchRestTemplate;/*** 根据商品名查询 */@Testpublic void testFindByName() {List<Goods> list = goodsInter.findByGoodsName("%中国%");list.forEach(System.out::println);}/*** 批量插入,查询所有 */@Test public void testSaveAll() {//批量插入List<Goods> list = new ArrayList<>();list.add(new Goods(152, "测试手机1", new BigDecimal("500"), "jpg"));list.add(new Goods(153, "测试手机2", new BigDecimal("800"), "png"));goodsInter.saveAll(list);//查询所有Iterable<Goods> all = goodsInter.findAll(); all.forEach(System.out::println);}/*** 索引操作 (已经纯在)*///等值收缩由局限性于是使用esTemplate的检索方法@Testpublic void testIndex() {//设置索引信息(实体类),返回indexOperationsIndexOperations indexOperations = elasticsearchRestTemplate.indexOps(Goods.class);indexOperations.create();//创建索引映射Document mapping = indexOperations.createMapping();//将映射写入索引indexOperations.putMapping(mapping);//获取索引Map<String, Object> map = indexOperations.getMapping();map.forEach((k, v) -> System.out.println(k + "-->" + v));//索引是否存在boolean exists = indexOperations.exists(); System.out.println(exists);//删除索引indexOperations.delete();}/*** 增删改 */@Testpublic void testDocument() {/** 根据id和索引删除,返回删除的id* 第一个参数:id,String类型 * 第二个参数:索引库对象 */String count = elasticsearchRestTemplate.delete("150", IndexCoordinates.of("shop"));System.out.println(count);/*** 删除查询结果 * 第一个参数:查询对象 * 第二个参数:索引类字节码 * 第三个参数:索引库对象 */elasticsearchRestTemplate.delete( new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("goodsName", "测试")).build(), Goods.class, IndexCoordinates.of("shop"));//新增/更新(id不存在就新增,存在就更新)List<Goods> list = new ArrayList<>();list.add(new Goods(150, "测试手机3", new BigDecimal("100"), "jpg"));list.add(new Goods(151, "测试手机4", new BigDecimal("200"), "png"));Iterable<Goods> save = elasticsearchRestTemplate.save(list);save.forEach(System.out::println);}/*** 匹配查询 */@Testpublic void testSearchMatch() {NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();NativeSearchQuery query = nativeSearchQueryBuilder/*** 第一个参数:关键词 * 第二个参数:对应es的字段 */.withQuery(QueryBuilders.multiMatchQuery("中国移动联通电信", "goodsName")).build(); SearchHits<Goods> search = elasticsearchRestTemplate.search(query, Goods.class);search.forEach(searchHit -> System.out.println(searchHit.getContent()));}/*** 分页,排序,高亮查询 */@Testpublic void testSearchPage() {NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();NativeSearchQuery query = nativeSearchQueryBuilder/*** 第一个参数:关键词 * 第二个参数:对应es的字段 */.withQuery(QueryBuilders.multiMatchQuery("中国移动联通电 信", "goodsName"))/*** 第一个参数:当前页,0开始 * 第二个参数:每个条数 * 第三个参数:排序对象 * 升序/降序 * 比较字段 *///.withPageable(PageRequest.of(0, 5, Sort.Direction.DESC, "goodsId", "marketPrice"))// 分页.withPageable(PageRequest.of(0, 5))//.withSort(SortBuilders.fieldSort("marketPrice").order(SortOrder.ASC))//高亮,默认样式<em></em>(斜体)//.withHighlightFields(new HighlightBuilder.Field("goodsName"))//高亮,指定样式.withHighlightBuilder(new HighlightBuilder().field("goodsName").preTags("<span style='color:red;'>").postTags("</span>")).build();SearchHits<Goods> search = elasticsearchRestTemplate.search(query, Goods.class);for (SearchHit<Goods> searchHit : search) {//idSystem.out.println(searchHit.getId());//分数System.out.println(searchHit.getScore());//排序的值Double sortValues = (Double) searchHit.getSortValues().get(0);System.out.println(sortValues);//高亮信息String highlightMessage = searchHit.getHighlightField("goodsName").get(0);System.out.println(highlightMessage);//结果对象System.out.println(searchHit.getContent());System.out.println("----------------------------------------");}}}


SpringBoot整合中,实现类接口ElasticsearchRepository,此接口为我们提供了很多方法,并且可以更具一些常用的需求组合出需要的方法,不需要我们手动去写实现方法,爆赞

ElasticSearch搜索引擎✧完结相关推荐

  1. 第三百六十二节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)基本的索引和文档CRUD操作、增、删、改、查...

    第三百六十二节,Python分布式爬虫打造搜索引擎Scrapy精讲-elasticsearch(搜索引擎)基本的索引和文档CRUD操作.增.删.改.查 elasticsearch(搜索引擎)基本的索引 ...

  2. ElasticSearch搜索引擎: 内存分析与设置

    在 Elasticsearch 的运行过程中,如何合理分配与设置内存是一件十分重要的事情,否则十分容易出现各种问题. 一.Elasticsearch为什么吃内存: 我们先看下 ES 服务器的总体内存消 ...

  3. ElasticSearch搜索引擎常见面试题总结

    一.ElasticSearch基础: 1.什么是Elasticsearch: Elasticsearch 是基于 Lucene 的 Restful 的分布式实时全文搜索引擎,每个字段都被索引并可被搜索 ...

  4. 第三百六十节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的基本概念...

    第三百六十节,Python分布式爬虫打造搜索引擎Scrapy精讲-elasticsearch(搜索引擎)的基本概念 elasticsearch的基本概念 1.集群:一个或者多个节点组织在一起 2.节点 ...

  5. day06 Elasticsearch搜索引擎2

    day06 Elasticsearch搜索引擎2 1.DSL查询文档 1.1.DSL查询分类 Elasticsearch提供了基于JSON的DSL(Domain Specific Language)来 ...

  6. ElasticSearch搜索引擎详解-持续更新中

    ElasticSearch搜索引擎详解 1. ElasticSearch概述 1.1 elasticsearch是什么 1.2 全文搜索引擎 1.3 elasticsearch and solr 1. ...

  7. Elasticsearch搜索引擎(一)——基础使用

    Elasticsearch搜索引擎 关键词是中文的建议使用,英文和数字不要,模糊就行 如果普通数据库查询,无法解决如下问题 如果表记录上千万上亿了这个性能问题,另外一个如果有一个本文字段要在里面模糊配 ...

  8. day07 Elasticsearch搜索引擎3

    day07 Elasticsearch搜索引擎3 1.数据聚合 聚合(aggregations)可以让我们极其方便的实现对文档数据的统计.分析.运算.例如: 什么品牌的手机最受欢迎? 这些手机的平均价 ...

  9. 一步一步学爬虫(4)数据存储之Elasticsearch搜索引擎存储

    Elasticsearch搜索引擎存储 1. Elasticsearch 介绍 2. Elasticsearch 相关概念 3. 准备工作 3.1 下载程序 3.2 解压缩,配置文件修改 4. 创建索 ...

最新文章

  1. 图灵2010.04书讯
  2. docker启动elasticsearch失败--jvm内存不足解决方案
  3. 我被面试官问到的问题-5
  4. 转:ECharts图表组件之简单关系图:如何轻松实现另类站点地图且扩展节点属性实现点击节点页面跳转...
  5. 3150 Pibonacci数 - Wikioi
  6. 爬虫-14-利用代理爬取数据
  7. Modularity(模块化-AMD规范)
  8. 阿里工程师手把手教你设计 B 端垂类营销中心!
  9. Shiro学习笔记四(Shiro集成WEB)
  10. Java基础:常用的API
  11. 关于蓝天准系统换京东方屏后不显bios的解决方案
  12. 【Unity3D开发小游戏】《超级马里奥》游戏教程
  13. 2021年,小灰都读了哪些书?
  14. 安装Gentoo要点
  15. 采用analysis-dynamic-synonym插件,动态文件的方式同步同义词
  16. MySQL Partition 相关使用总结
  17. 购物中心智能管理系统该如何选择
  18. 【实验2 选择结构】7-3 sdut-C语言实验-时间间隔
  19. arduino舵机门锁 红外遥控控制 刷卡 diy
  20. Mysql数据库之结构同步

热门文章

  1. 手把手教你注册itume store免费账户☆☆更新 iTunes 9 注册方法☆☆
  2. angularJS学习小结——$apply方法和$watch方法
  3. kill -15、kill -9 与 kill
  4. 内存1G malloc1.6G是否成功?
  5. 餐饮业的持久战,激流之下如何突围?
  6. 你还在 for 循环里使用 + 拼接字符串吗?
  7. shel统计文件每行某字符出现频率
  8. vim配置入门,到豪华版vim配置
  9. 基于ssh的学生成绩管理系统的设计与实现
  10. 错误为0x8002801D 库没有注册 解决方案