文章目录

  • 一、Elasticsearch 和 IK 分词器的安装
  • 二、Kibana 使用
  • 三、数据导入 Elasticsearch
    • 1、SpringData Elasticsearch 介绍
    • 2、搜索工程搭建
    • 3、数据导入
  • 四、关键字搜索
  • 五、分类统计
  • 六、总结

一、Elasticsearch 和 IK 分词器的安装

Elasticsearch 是一个 开源的 高扩展的 分布式全文检索引擎,它可以近乎实时地存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理 PB 级别的数据。 Elasticsearch 使用 Java开发,并使用 Lucene 作为其核心,来实现所有索引和搜索的功能,但是,它的目的 是通过简单的 RESTful API 来隐藏 Lucene 的复杂性,从而让全文搜索变得简单。

  • Elasticsearch 的安装

采用 Docker 安装 Elasticsearch。

(1)docker 镜像下载

docker pull elasticsearch:5.6.8


(2)安装 es 容器

docker run -di --name=changgou_elasticsearch -p 9200:9200  -p 9300:9300

9200 端口是 Web 管理平台端口;9300 是服务默认端口。

(3)开启远程连接
    上面完成安装后,es 并不能正常使用,elasticsearch 从 5 版本以后默认不开启远程连接,程序直接连接会报如下错误:
failed to load elasticsearch nodes : org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{5ttLpMhkRjKLkvoY7ltUWg}{192.168.211.132}{192.168.211.132:9300}]

我们需要修改es配置开启远程连接。

登录容器:

docker exec -it changgou_elasticsearch /bin/bash

查看目录结构:

进入 config 目录,修改 elasticsearch.yml 文件:

     重启后发现启动失败了,这与我们刚才修改的配置有关,因为elasticsearch 在启动的时候会进行一些检查,比如最多打开的文件的个数 以及 虚拟内存区域数量 等等,如果进行了配置,意味着需要打开更多的文件以及虚拟内存,所以我们还需要系统调优。
     执行 vi /etc/security/limits.conf ,追加内容 ( nofile 是单个进程允许打开的最大文件个数, soft nofile 是软限制, hard nofile是硬限制 )

执行 vi /etc/sysctl.conf,追加内容 (限制一个进程可以拥有的 VMA 虚拟内存区域 的数量 )

vm.max_map_count=655360

执行 sysctl -p 修改内核参数马上生效

     重新启动虚拟机,再次启动容器,发现已经可以启动并远程访问。
    
(4)跨域配置
     修改 elasticsearch/config 下的配置文件:elasticsearch.yml,增加以下三句命令,并重启:

http.cors.enabled: true
http.cors.allow-origin: "*"
network.host: 192.168.211.132

其中,http.cors.enabled: true为允许 elasticsearch 跨域访问,默认是false。 http.cors.allow-origin: "*"表示 跨域访问允许的域名地址(*表示任意)。
    
     重启:docker restart changgou_elasticsearch
     如果想让容器开启重启,执行 docker update --restart=always changgou_elasticsearch
    

     注意,地址栏中默认的是 localhost,需要改成虚拟机的 IP 地址喔。
    
     IK 分词器 是一个开源的,基于 Java 语言开发的 轻量级的 中文分词工具包。

  • IK 分词器安装

(1)安装 ik 分词器

IK分词器下载地址 https://github.com/medcl/elasticsearch-analysis-ik/releases

将 ik分词器 上传到服务器上,然后解压,并改名字为 ik

unzip elasticsearch-analysis-ik-5.6.8.zip
mv elasticsearch ik

将 ik 目录拷贝到 docker 容器的 plugins 目录下

docker cp ./ik changgou_elasticsearch:/usr/share/elasticsearch/plugins

(2)IK 分词器测试
访问:http://192.168.211.132:9200/_analyze?analyzer=ik_smart&pretty=true&text=我是程序员

访问:http://192.168.211.132:9200/_analyze?analyzer=ik_max_word&pretty=true&text=我是程序员 最细分词:

     如果想要自定义分词器,需要修改 IKAnalyzer.cfg.xml 配置文件,添加自定义分词文件,如果想要自定义停用词汇,则在该配置文件里添加停用词汇。

二、Kibana 使用

上面使用的是 elasticsearch-head 插件(默认端口是 9100 ) 实现数据查找的,但是它的功能比较单一,我们需要一个更专业的工具实现对日志的实时分析,也就是我们接下来要讲的 Kibana 。
    Kibana 是一款开源的数据分析和可视化平台,它是 Elastic Stack 成员之一, 用于和 Elasticsearch 协作,相当于 Elasticsearch 的数据分析工具。 可以使用 Kibana 对 Elasticsearch 索引中的数据进行搜索、查看、交互操作。 可以很方便的利用图表、表格及地图对数据进行多元化的分析和呈现。
     Kibana 可以使大数据通俗易懂。它很简单,基于浏览器的界面便于快速创建和分享动态数据仪表板来追踪 Elasticsearch 的实时数据变化。
     搭建 Kibana 非常简单,可以分分钟完成 Kibana 的安装并开始探索 Elasticsearch 的索引数据 — 没有代码、不需要额外的基础设施。

  • Kibana下载安装

(1)镜像下载

docker pull docker.io/kibana:5.6.8

(2)安装 kibana 容器

docker run -it -d -e ELASTICSEARCH_URL=http://192.168.211.132:9200 --name kibana --restart=always -p 5601:5601 kibana:5.6.8

参数说明:
① ELASTICSEARCH_URL=http://192.168.211.132:9200:是指链接的 ES 地址
② restart=always:每次服务都会重启,也就是开启启动
③ 5601:5601:端口号

(3)访问测试

访问 http://192.168.211.132:5601 如下:

  • Kibana 使用

    • 配置索引
           要使用 Kibana,必须至少配置一个索引。索引用于标识 Elasticsearch 索引,以运行搜索和分析。它们还用于配置字段,输入索引后,点击 create,会展示出当前配置的索引的域信息:
    • 数据搜索

Discover 为 数据搜索 部分,可以对日志信息进行搜索操作。

可以使用 Discover 实现数据搜索过滤和搜索条件显示以及关键词搜索:

比如,还可以把数据 以各种表的形式展示:

比如,绘制个饼状图:

三、数据导入 Elasticsearch

1、SpringData Elasticsearch 介绍

Spring Data 是一个 用于简化数据库访问,并支持云服务的开源框架。 其主要目标是使得对数据的访问变得方便快捷,并支持 map-reduce 框架和云计算数据服务。 Spring Data 可以极大的简化 JPA 的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了 CRUD 外,还包括如分页、排序等一些常用的功能。

Spring Data的官网:http://projects.spring.io/spring-data/

Spring Data ElasticSearch 基于 spring data API ,简化 ElasticSearch 操作,将原始操作 elasticSearch 的客户端 API 进行封装 。 Spring Data 为 Elasticsearch 项目提供集成搜索引擎。Spring Data Elasticsearch POJO的关键功能区域为中心的模型与 Elastichsearch 交互文档和轻松地编写一个存储库数据访问层。

Spring Data ElasticSearch 官方网站:http://projects.spring.io/spring-data-elasticsearch/

2、搜索工程搭建

创建搜索微服务工程 changgou-service-search,该工程主要提供 搜索服务 以及 索引数据的更新操作。

(1)API 工程搭建

首先创建 search 的 API 工程,在 changgou-service-api 中创建changgou-service-search-api,导入依赖:

<!--goods API依赖-->
<dependency><groupId>com.changgou</groupId><artifactId>changgou-service-goods-api</artifactId><version>1.0-SNAPSHOT</version>
</dependency>
<!--SpringDataES依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

因为是对商品的搜索(而且是针对 sku 进行搜索),所以应该向索引库中导入 sku 的数据,需要用到 goods 的 feign 调用。
    
(2)搜索微服务搭建
     在 changgou-service 中搭建 changgou-service-search 微服务,导入依赖:

    <!--依赖search api--><dependency><groupId>com.changgou</groupId><artifactId>changgou-service-search-api</artifactId><version>1.0-SNAPSHOT</version></dependency>

application.yml配置

server:port: 18085
spring:application:name: searchdata:elasticsearch:cluster-name: my-applicationcluster-nodes: 192.168.211.132:9300
eureka:client:service-url:defaultZone: http://127.0.0.1:7001/eurekainstance:prefer-ip-address: true
feign:hystrix:enabled: true
#超时配置
ribbon:ReadTimeout: 300000hystrix:command:default:execution:isolation:thread:timeoutInMilliseconds: 10000

配置说明:

  • connection-timeout:服务连接超时时间
  • socket-connect:HTTP请求超时时间
  • ribbon.ReadTimeout: Feign 请求读取数据超时时间
  • timeoutInMilliseconds:Feign 连接超时时间
  • cluster-name:Elasticsearch 的集群节点名称,这里需要和 Elasticsearch 集群节点名称保持一致
  • cluster-nodes:Elasticsearch 节点通信地址
        
    (3)启动类
        创建 SearchApplication 作为搜索微服务工程的启动类:
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
@EnableEurekaClient
public class SearchApplication {public static void main(String[] args) {/*** Springboot 整合 Elasticsearch 在项目启动前设置一下的属性,防止报错* 解决 netty 冲突后初始化 client 时还会抛出异常* availableProcessors is already set to [12], rejecting [12]***/System.setProperty("es.set.netty.runtime.available.processors", "false");SpringApplication.run(SearchApplication.class,args);}
}

还需要分别创建对应的包,dao、service、controller。

3、数据导入


数据导入流程如下:

  • 请求 search 服务
  • 根据注册中心中的注册的 goods 服务的地址,使用 Feign 方式查询所有已经审核的 Sku
  • 使用 SpringData Elasticsearch 将查询到的 Sku集合导入到 Elasticsearch 中

实现过程:

  • 创建一个 JavaBean,名为 skuInfo ,在该 JavaBean 中添加索引库映射配置
  • 创建 Feign,实现查询所有 sku 集合
  • 在 搜索微服务中调用 Feign,查询所有 sku 集合,并将 sku 集合转换成 skuinfo
  • 调用 dao(继承 ElasticsearchRepostory 接口),实现数据导入到 Elasticsearch 中

(1)文档映射 Bean 创建

搜索商品的时候,不是所有的属性都需要分词搜索,我们创建 JavaBean,将 JavaBean 数据存入到 Elasticsearch 中,要以 搜索条件 和 搜索展示结果 为依据,部分关键搜索条件分析如下:

  • 可能会根据商品名称搜素,而且可以搜索商品名称中的任意一个词语,所以需要分词
  • 可能会根据商品分类搜索,商品分类不需要分词
  • 可能会根据商品品牌搜索,商品品牌不需要分词
  • 可能会根据商品商家搜索,商品商家不需要分词
  • 可能根据规格进行搜索,规格需要一个键值对结构,用 Map

根据上面的分析,我们可以在 changgou-service-search-api 工程中创建com.changgou.search.pojo.SkuInfo:

@Document(indexName = "skuinfo",type = "docs")
public class SkuInfo implements Serializable {// 商品id,同时也是商品编号@Idprivate Long id;/*** SKU名称* type=Field.Type.Text,支持分词* analyzer = "ik_smart",创建索引的分词器* index=true,表示开启分词(默认)* store=false,表示不存储(默认)*/@Field(type = FieldType.Text, analyzer = "ik_smart")private String name;// 商品价格,单位为:元@Field(type = FieldType.Double)private Long price;// 库存数量private Integer num;// 商品图片private String image;// 商品状态,1-正常,2-下架,3-删除private String status;// 创建时间private Date createTime;// 更新时间private Date updateTime;// 是否默认private String isDefault;// SPUIDprivate Long spuId;// 类目IDprivate Long categoryId;/*** type = FieldType.Keyword 不支持分词*/// 类目名称@Field(type = FieldType.Keyword)private String categoryName;// 品牌名称@Field(type = FieldType.Keyword)private String brandName;// 规格private String spec;// 规格参数private Map<String,Object> specMap;// getter、setter 方法略
}

document 是 Elaticsearch 中的最小数据单元,一个 document 可以是一条商品数据,也可以是一条订单数据,通常用 JSON 格式表示,一个 document 里面有多个 field,每个 field 就是一个数据字段。属性上如果不加 @Field,是会自动添加域的。

(2) 搜索 Sku
     从数据导入的流程图中可以看出来,查询 sku 需要调用 goods 服务的 findAll 方法:

需要为它在 changgou-service-goods-api 包中提供 Feign 调用:

@FeignClient(value="goods")
@RequestMapping("/sku")
public interface SkuFeign {/*** 查询 sku 全部数据* @return*/@GetMapping("/findAll")Result<List<Sku>> findAll();}

接下来,提供 dao :

@Repository
public interface SkuEsMapper extends ElasticsearchRepository<SkuInfo,Long> {}

在 changgou-service-search 中 通过 service 层调用 feign 和 这个 SkuEsMapper :

public class SkuServiceImpl implements SkuService {@AutowiredSkuEsMapper skuEsMapper;@AutowiredSkuFeign skuFeign;/*** 导入索引库*/@Overridepublic void importData() {// Feign 调用,查询 List<Sku>Result<List<Sku>> skus = skuFeign.findAll();// 将 List<Sku> 转化成 List<SkuInfo>List<SkuInfo> skuInfos = JSON.parseArray(JSON.toJSONString(skus.getData()), SkuInfo.class);// 调用 dao 实现数据批量导入skuEsMapper.saveAll(skuInfos);}
}

因为用到了 Feign 和 SkuEsMapper 的调用,所以需要在启动类上添加 @EnableFeignClients 和 @EnableElasticsearchRepositories 注解:

提供控制层:

@RestController
@RequestMapping("/search")
@CrossOrigin
public class SkuController {@Autowiredprivate SkuService skuService;@GetMapping("/import")public Result importData(){// 数据导入skuService.importData();return new Result(true, StatusCode.OK,"导入数据到索引库成功!");}
}

运行结果:


现在有一个问题,我们设计的前端展示页面里,有 “显示屏尺寸”、“摄像头参数” :

而我们导入到索引库里的数据是这样的:

     我们需要提供 规格 和 对应的 域,之前在 SkuInfo 类中提供了 Map 类型的属性 specMap, spec 是 String 类型,我们把它转换成 Map,把它的 key 都提取出来,作为域的名称。在 importData 方法中添加:

 // 遍历当前 skuInfos,获取列表规格列表for (SkuInfo skuInfo : skuInfos) {Map<String, Object> specMap = JSON.parseObject(skuInfo.getSpec(), Map.class);// 将域存入 Map<String, Object>,key 就会生成动态域,// 域的名字为 key,值为 valueskuInfo.setSpecMap(specMap);}

这时删除 skuinfo 索引,重新运行,可以看到:

     这样和前端里的规格栏是相应的。

四、关键字搜索

我们先使用 SpringDataElasticsearch 实现一个简单的搜索功能,先实现 根据关键字搜索,从上面搜索图片可以看得到,每次搜索的时候,除了关键字外,还有可能有品牌、分类、规格等,后台接收搜索条件 使用 Map 接收比较合适。
    
(1)Service 层
修改 search 服务的 com.changgou.search.service.SkuService类,添加搜索方法:

Map search(Map<String, String> searchMap);

在 SkuServiceImpl 实现类中添加 ElasticsearchTemplat 类型属性,用来实现索引库的增删改查,适用于高级搜索:

   @AutowiredElasticsearchTemplate elasticsearchTemplate;

实现:

public Map<String, Object> search(Map<String, String> searchMap) {// 搜索条件构建对象NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();if(searchMap!=null && searchMap.size()>0){// 根据关键词搜索String keyWords = searchMap.get("keywords");if(!StringUtils.isEmpty(keyWords)){builder.withQuery(QueryBuilders.queryStringQuery(keyWords).field("name"));}}// 第二个参数需要搜索的结果类型(页面展示的是集合数据)// AggregatedPage<SkuInfo> 是对结果集的封装AggregatedPage<SkuInfo> page = elasticsearchTemplate.queryForPage(builder.build(), SkuInfo.class);// 获取数据结果集List<SkuInfo> contents = page.getContent();// 获取总记录数long totalNums = page.getTotalElements();// 获取总页数int totalPages = page.getTotalPages();// 封装 Map 存储数据作为结果Map<String,Object> resultMap=new HashMap<String,Object>();resultMap.put("rows",contents);resultMap.put("totalNums",totalNums);resultMap.put("totalPages", totalPages);return resultMap;
}

(2)控制层
在 com.changgou.search.controller.SkuController 增加方法:

    @GetMappingpublic Map search(@RequestParam(required = false) Map<String,String> searchMap) throws Exception{return  skuService.search(searchMap);}

测试一下,访问 http://localhost:18085/search,运行结果:

五、分类统计


     可以看到,这个前端页面中第一栏 “分类”,如果选择的分类不同,那么后续展示的也应该是不同的,比如,配件就不需要网络制式。所以,我们有必要对分类进行分组,先根据分类进行分组,因为对于不同的分类,页面展示的商品也是不同的。先实现根据分类查询商品的功能。
     先看看如果是 SQL 语句,在执行搜索的时候,第 1 条 SQL 语句是执行搜索,第 2 条语句是根据 分类名字 分组查看有多少分类。

-- 查询所有
SELECT * FROM tb_sku WHERE name LIKE '%手机%';
-- 根据分类名字分组查询
SELECT category_name FROM  tb_sku WHERE name LIKE '%手机%' GROUP BY category_name;

每次执行 搜索 的时候,需要显示商品分类名称,这里要显示的分类名称,其实就是符合搜素条件的所有商品的分类集合,我们可以按照上面的实现思路,使用 ES 根据分组名称,做一次分组查询。

(1) 分类分组统计实现
修改 SkuServiceImpl 类代码,search 方法变为:

    public Map<String, Object> search(Map<String, String> searchMap) {// 搜索条件构建对象NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();// 如果关键词不为空if (searchMap != null && searchMap.size() > 0) {// 根据关键词搜索String keyWords = searchMap.get("keywords");if (!StringUtils.isEmpty(keyWords)) {builder.withQuery(QueryBuilders.queryStringQuery(keyWords).field("name"));}}// 第二个参数需要搜索的结果类型(页面展示的是集合数据)// AggregatedPage<SkuInfo> 是对结果集的封装AggregatedPage<SkuInfo> page = elasticsearchTemplate.queryForPage(builder.build(), SkuInfo.class);/** 根据分类进行分组查询 */// 添加聚合操作builder.addAggregation(AggregationBuilders.terms("skuCategory").field("categoryName.keyword"));AggregatedPage<SkuInfo> page1 = elasticsearchTemplate.queryForPage(builder.build(), SkuInfo.class);// 因为可以根据多个域分组,所以先获取集合,再获取指定域的数据// 这时获取到的是 {电脑,手机配件,电视}StringTerms stringTerms = page1.getAggregations().get("skuCategory");List<String> categoryList=new ArrayList<>();for(StringTerms.Bucket bucket:stringTerms.getBuckets()){String categoryName=bucket.getKeyAsString();categoryList.add(categoryName);}/** 根据分类进行分组查询 */// 获取数据结果集List<SkuInfo> contents = page.getContent();// 获取总记录数long totalNums = page.getTotalElements();// 获取总页数int totalPages = page.getTotalPages();// 封装 Map 存储数据作为结果Map<String, Object> resultMap = new HashMap<String, Object>();resultMap.put("rows", contents);resultMap.put("totalNums", totalNums);resultMap.put("totalPages", totalPages);resultMap.put("categoryList",categoryList);return resultMap;}

运行结果:

六、总结

(1)Elasticsearch 是一个 高扩展的 分布式全文检索引擎,它可以近乎实时地存储、检索数据。MySQL 通过 数据库 存储数据,Elasticsearch 通过 索引库 存储索引。
    
(2)IK 分词器 是一个基于 Java 开发的 轻量级 中文分词工具包。
    
(3)Kibana 相当于 Elasticsearch 的数据分析工具,在浏览器里 看数据很直观(比如各种图表)。在 kibana 的配置文件中,会指向 Elasticsearch 的地址。
    
(4)Spring Data ElasticSearch 是 对 操作 elasticSearch 的客户端 API 进行的封装。
    
(5)因为搜索商品是对 sku 进行搜索,所以需要向 Elasticsearch 索引库中导入 sku 数据。需要提供 SkuInfo (是个 Java Bean) ,做索引库映射配置。然后把从 goods 商品微服务中查询到的 sku 数据,转化成 skuInfo, 调用继承了 ElasticsearchRepostory 接口的 skuEsMapper 的saveAll 方法,即可实现数据导入到 Elasticsearch。
     skuInfo 类上使用 @Document 注解,并声明索引名和类型,它的属性使用 @Field 注解,并声明是否开启分词和存储。skuInfo 对象的属性就对应域,一个个对象就对应一个个记录。
    
(6)使用 ElasticsearchTemplat 类,实现索引库的增删改查,适用于高级搜索。需要先使用 NativeSearchQueryBuilder 构建条件,然后调用具体查询语句,比如,本文中根据分类名称 categoryName 进行分组查询。

微服务商城系统(六)商品搜索 SpringBoot 整合 Elasticsearch相关推荐

  1. springcloud 整合 gateway_GitHub上最火的SpringCloud微服务商城系统项目,附全套教程

    项目介绍 mall-swarm是一套微服务商城系统,采用了 Spring Cloud Greenwich.Spring Boot 2.MyBatis.Docker.Elasticsearch等核心技术 ...

  2. mall-swarm是一套微服务商城系统

    介绍: mall-swarm是一套微服务商城系统,采用了 Spring Cloud Hoxton & Alibaba.Spring Boot 2.3.Oauth2.MyBatis.Elasti ...

  3. mall-swarm微服务商城系统

    mall-swarm是一套微服务商城系统,采用了 Spring Cloud 2021 & Alibaba.Spring Boot 2.7.Oauth2.MyBatis.Docker.Elast ...

  4. 微服务商城系统(十) Spring Security Oauth2 + JWT 用户认证

    文章目录 一.用户认证分析 1.认证 与 授权 2.单点登录 3.第三方账号登录 4.第三方认证 5.认证技术方案 6.Security Oauth 2.0 入门 7. 资源服务授权 (1)资源服务授 ...

  5. 微服务商城系统(十六)秒杀核心

    代码链接: https://github.com/betterGa/ChangGou 文章目录 一.防止秒杀重复排队 二. 并发超卖问题解决 三. 订单支付 1.实现根据不同类型订单识别不同操作队列 ...

  6. 微服务商城系统(一)框架搭建、商品微服务搭建

    文章目录 一.预备 1.微服务 2.缓存 3.通用Mapper 和 PageHelper 4.持久化 5.电商模式 二.系统设计 三.框架搭建 1.环境准备 2.项目结构介绍 3.公共工程搭建 (1) ...

  7. 微服务商城系统实战 后台管理页面、商家管理页面、商品列表跳转详情页

    文章目录 一.后台管理 1.根据点击的 div 展示相应页面 2.解决 height: 100% 不起作用问题 3. th:onclick 引用的函数参数是 model值 二.商家管理 1.th:ea ...

  8. 微服务商城系统(十四)微信支付

    文章目录 一.支付微服务 1.微信支付 API 2.HttpClient 工具类 3.支付微服务搭建 二.微信支付二维码生成 三.检测支付状态 四.内网穿透 五.支付结果通知 1.支付结果回调通知 2 ...

  9. 微服务商城系统(十三)订单、支付流程分析

    文章目录 一.订单 1.登录页面配置 2.用户收件地址查询 3. 下单 (1)表结构介绍 (2)下单实现 (3)库存变更 (4)增加积分 二. 支付流程分析 1. 二维码创建 2.微信扫码支付简介 ( ...

最新文章

  1. DNN 4.6.2的中文语言包
  2. linux备份文件到ftp上,Linux服务器下用FTP上传下载备份文件
  3. 【笔记】编译报错error: cannot convert ‘main(int, char**)::sockadrr*’ to ‘const sockaddr*’ for
  4. flash动画测试什么软件,flash测试(flash怎么测试动画)
  5. linux找不到fastboot驱动下载,fastboot 刷机傻瓜教程
  6. 永磁电机MTPA控制
  7. android 设置打印级别
  8. 项目管理——如何制定生产计划控制生产进度
  9. 骨传导耳机低频差理所当然?飞利浦A6606表示不服
  10. 30 道 Vue 面试题,内含详细讲解(涵盖入门到精通,自测 Vue 掌握程度)
  11. Java:冒泡排序法
  12. linux 路由转发 ipv6,IPv6路由
  13. 云原生边缘计算:探索与展望
  14. 高密度配线架选择指南
  15. 苹果iOS 10的备份加密减弱:破解速度提升2500倍
  16. For循环实现99乘法表
  17. HDU 6112 今夕何夕【2017百度之星】【日期模拟计算】【基姆拉尔森计算公式】【蔡勒公式】
  18. Application Verifier使用起步
  19. ALTER TABLE语句(Oracle)
  20. 打开IE自动弹出网页的处理办法

热门文章

  1. 机器学习 学习曲线 Python实现学习曲线及案例解析
  2. vue实现点击按钮,弹出对话框
  3. 基于STM32L431单片机和NB-IOT技术的低功耗追踪器
  4. 微小悬浮颗粒物粒子计数器ParticleCounter
  5. 网络协议:透彻解析HTTPS协议
  6. 10招步骤保护IIS服务器安全
  7. Google 几种常见的高级搜索技巧
  8. prometheus之分布式部署
  9. 【Vulnhub】之Nagini
  10. 利用汇编语言计算斐波那契数列