SpringCloud微服务(简略笔记二)

Docker

概念

docker和虚拟机的差异

* docker是一个系统进程;虚拟机是在操作系统中的操作系统

* docker体积小,启动速度,性能好,虚拟机体积大,启动速度慢,性能一般

镜像和容器

镜像(image) : Docker将应用程序极其所需的依赖,数据库,环境,配置等文件打包在一起,称为镜像。

容器(Container):镜像中的应用程序运行后形成的进程就是容器,只是Docker会给容器做隔离,对外不可见。

DockerHub

* DockerHub:DockerHub是一个Docker镜像的托管平台,这样的平台称为Docker Registry。

Docker架构

Docker是一个CS架构的程序,由两部分组成:

* 服务端(server):Docker守护进程,负责处理Docker指令,管理镜像,容器等。

* 客户端(client) : 通过命令或RestAPI 向Docker服务端发送指令,可以在本地或远程服务端发送指令。

镜像,容器命令

拉取nginx镜像:docker pull nginx查看拉取到的镜像:docker images压缩镜像:docker save -o nginx.tar nginx:latest删除镜像:docker rmi nginx:latest读取镜像:docker load -i nginx.tar创建容器:docker run --name mn -p 80:80 -d nginx查看容器状态: docker ps查看虚拟机id地址:ifconfig  -a查看容器日志: docker logs mn(容器名称)
持续跟踪日志:docker logs  -f mn(容器名称)进入容器:docker exec -it mn bash退出容器:exit停止容器:docker stop mn启动容器:docker start删除容器:docker rm 
强制删除运行中的容器: docker rm -f mn

创建运行一个Nginx容器 

修改Nginx容器的html文件内容

容器地址:

进入html文件 :cd /usr/share/nginx/html修改内容:sed -i -e 's#Welcome to nginx#传智教育欢迎您#g' -e 's#<head>#<head><meta charset="utf-8">#g' index.html

创建运行一个redis容器

拉取redis容器:docker pull redis创建容器:docker run --name mr -p 6379:6379 -d redis redis-server --appendonly yes进入容器:  docker exec -it mr bash进入redis : redis-cli

数据卷

数据与容器耦合的问题

数据卷命令

启动docker :systemctl start docker查看停止的容器:docker ps -adocker volume [command]创建一个数据卷:docker volume create html [名字]查看个数的数据卷命令:docker volume ls查看数据卷位置: docker volume inspect html移除未使用的数据卷:docker volume prune删除使用的数据卷:docker volume rm html将容器挂载到数据卷上: docker run -d -p 80:80 --name mn2 -v html:/usr/share/html nginx查看数据卷信息:docker inspect html

Dockerfile自定义镜像

镜像是将应用程序极其需要的系统函数库,环境,配置,依赖打包而成。 

镜像是分层结构,每一层称为一个Layer

* BaseImage层,包含基本的系统函数库,环境变量,文件系统

 * Emtrypoint: 入口,是镜像中应用启动的命令

* 其它:在BaseImage基础上添加依赖,安装程序,完成整个应用的安装和配置

自定义镜像

什么是Dockerfile

Dockerfile就是一个文本文件,其中包含一个个的指令(Instruection),用指令说明要执行什么操作来构建镜像,每一个指令都会形成一层Layer.

MQ

什么是MQ?

MQ(MessageQueue),中文是消息队列,字面来看就是存放消息的队列,也就是事件驱动架构中的Broker.

安装:

步骤:

加载Mq镜像:docker load -i mq.tar运行Mq容器:docker run \-e RABBITMQ_DEFAULT_USER=itcast \-e RABBITMQ_DEFAULT_PASS=123321 \--name mq \--hostname mq1 \-p 15672:15672 \-p 5672:5672 \-d \rabbitmq:3-management访问页面:http://192.168.74.128:15672/

 * channel:操作MQ的工具

   exchange:路由消息队列中

   queue:缓存消息

  virtual host:虚拟主机,是对queue,exchange等资源的逻辑分组。

 消息队列模型

publisher : 消息发布者,将教习发送到队列queue

queue:消息队列,负责接受并缓存消息

consumer:订阅队列,处理队列中的消息

SpringAMQP

SpringAMQP是基于RabbitMQ封装的一套模板,并且还利用SpringBoot对其实现了自动装配,使用起来非常方便。

SpringAMQP提供了三个功能:

  • 自动声明队列、交换机及其绑定关系

  • 基于注解的监听器模式,异步接收消息

  • 封装了RabbitTemplate工具,用于发送消息

案例:发送和接收 信息

父工程依赖

<!--AMQP依赖,包含RabbitMQ-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

发送的yml配置

spring:rabbitmq:host: 192.168.74.128 # 主机名port: 5672 # 端口virtual-host: / # 虚拟主机username: itcast # 用户名password: 123321 # 密码

发送信息

package cn.itcast.mq.helloworld;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;/*** @author Mtz* @version 1.0* @2023/10/1114:49* @function* @comment*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringSMPQTest {@Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic void testSimpleQueue() {// 队列名称String queueName = "simple.queue";// 消息String message = "hello, spring amqp!";// 发送消息rabbitTemplate.convertAndSend(queueName, message);}}

接收的yml配置

spring:rabbitmq:host: 192.168.74.128 # 主机名port: 5672 # 端口virtual-host: / # 虚拟主机username: itcast # 用户名password: 123321 # 密码

接收信息的代码

package cn.itcast.mq.listener;import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;@Component
public class SpringRabbitListener {@RabbitListener(queues = "simple.queue")public void listenSimpleQueueMessage(String msg) throws InterruptedException {System.out.println("spring 消费者接收到消息:【" + msg + "】");}
}

模拟WorkQueue实现一个队列绑定多个消费者

发送者

package cn.itcast.mq.helloworld;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;/*** @author Mtz* @version 1.0* @2023/10/1114:49* @function* @comment*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringSMPQTest {@Autowiredprivate RabbitTemplate rabbitTemplate;/*** workQueue* 向队列中不停发送消息,模拟消息堆积。*/@Testpublic void testWorkQueue() throws InterruptedException {// 队列名称String queueName = "simple.queue";// 消息String message = "hello, message_";for (int i = 0; i < 50; i++) {// 发送消息rabbitTemplate.convertAndSend(queueName, message + i);Thread.sleep(20);}}}

消费者

package cn.itcast.mq.listener;import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.time.LocalTime;@Component
public class SpringRabbitListener {@RabbitListener(queues = "simple.queue")public void listenWorkQueue1(String msg) throws InterruptedException {System.out.println("消费者1接收到消息:【" + msg + "】" + LocalTime.now());Thread.sleep(20);}@RabbitListener(queues = "simple.queue")public void listenWorkQueue2(String msg) throws InterruptedException {System.err.println("消费者2........接收到消息:【" + msg + "】" + LocalTime.now());Thread.sleep(200);}
}

FanoutExchange交换机

发布(Publish),订阅(Subscribe)

发布订阅模式与之前案例的区别就是允许将同意消息发送给多个消费者,实现方式是加入了exchange(交换机)

常见交换机类型包括:

* Fanout:广播

* Direct:路由

Topic:话题

注意:exchange负责消息路由,而不是存储,路由失败则消息丢失。

FanoutExchange

绑定队列和交换机

package cn.itcast.mq.listener;import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FanoutConfig {/*** 声明交换机* @return Fanout类型交换机*/@Beanpublic FanoutExchange fanoutExchange(){return new FanoutExchange("itcast.fanout");}/*** 第1个队列*/@Beanpublic Queue fanoutQueue1(){return new Queue("fanout.queue1");}/*** 绑定队列和交换机*/@Beanpublic Binding bindingQueue1(Queue fanoutQueue1, FanoutExchange fanoutExchange){return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);}/*** 第2个队列*/@Beanpublic Queue fanoutQueue2(){return new Queue("fanout.queue2");}/*** 绑定队列和交换机*/@Beanpublic Binding bindingQueue2(Queue fanoutQueue2, FanoutExchange fanoutExchange){return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);}
}

接收信息

package cn.itcast.mq.listener;import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.time.LocalTime;@Component
public class SpringRabbitListener {@RabbitListener(queues = "fanout.queue1")public void listenFanoutQueue1(String msg) {System.out.println("消费者1接收到Fanout消息:【" + msg + "】");}@RabbitListener(queues = "fanout.queue2")public void listenFanoutQueue2(String msg) {System.out.println("消费者2接收到Fanout消息:【" + msg + "】");}
}

发送信息

    @Testpublic void testFanoutExchange() {// 队列名称String exchangeName = "itcast.fanout";// 消息String message = "hello, everyone!";rabbitTemplate.convertAndSend(exchangeName, "", message);}

DirectExchange交换机

DirectExchange会将接收的信息根据规则路由到指定的Queue,因此称为路由模式(routes)

@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue1"),exchange = @Exchange(name = "itcast.direct", type = ExchangeTypes.DIRECT),key = {"red", "blue"}
))
public void listenDirectQueue1(String msg){System.out.println("消费者接收到direct.queue1的消息:【" + msg + "】");
}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue2"),exchange = @Exchange(name = "itcast.direct", type = ExchangeTypes.DIRECT),key = {"red", "yellow"}
))
public void listenDirectQueue2(String msg){System.out.println("消费者接收到direct.queue2的消息:【" + msg + "】");
}
@Test
public void testSendDirectExchange() {// 交换机名称String exchangeName = "itcast.direct";// 消息String message = "红色警报!日本乱排核废水,导致海洋生物变异,惊现哥斯拉!";// 发送消息rabbitTemplate.convertAndSend(exchangeName, "red", message);
}

TopicExchange交换机

/*** topicExchange*/
@Test
public void testSendTopicExchange() {// 交换机名称String exchangeName = "itcast.topic";// 消息String message = "喜报!孙悟空大战哥斯拉,胜!";// 发送消息rabbitTemplate.convertAndSend(exchangeName, "china.news", message);
}
@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue1"),exchange = @Exchange(name = "itcast.topic", type = ExchangeTypes.TOPIC),key = "china.#"
))
public void listenTopicQueue1(String msg){System.out.println("消费者接收到topic.queue1的消息:【" + msg + "】");
}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue2"),exchange = @Exchange(name = "itcast.topic", type = ExchangeTypes.TOPIC),key = "#.news"
))
public void listenTopicQueue2(String msg){System.out.println("消费者接收到topic.queue2的消息:【" + msg + "】");
}

消息转换器

发送SprignAMQP的发送方法中,接收消息的类型是Object,也就是说我们可以发送任意对象类型的消息,SpringAMQ会棒我们序列化为字节后发送。

<dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId><version>2.9.10</version>
</dependency>

启动类添加Bean

@Bean
public MessageConverter jsonMessageConverter(){return new Jackson2JsonMessageConverter();
}

elesticearch搜索引擎

概念

elesticsearch是elstic stack的核心,负责存储,搜索,分析数据。

数据可视化:kibana

存储,计算,搜索数据:Elasticsearch

数据抓取:logstash,beats

什么是elasticsearch?

一个开源的分布式搜索引擎,可以用来实现搜索,日志统计,分析,系统监控等功能。

什么是elstic stack(ELK)?

是以elasticearch为核心的技术栈,包括beats,logstach,kibana,elasticesearch

什么是Luaene?

是Apache的开源搜索引擎类库,提供了搜索引擎的核心API

正向索引和倒排索引

elasticsearch采用倒排索引:

文档(document):每条数据就是一个文档

词条(trem):文档按照语义分成的词语

elasticsearch概念

文档

elasticsearch是面向文档存储的,可以是数据库的一条商品数据,一个订单信息。

文档数据会被序列化为json格式后存储在elasticsearch。

索引

索引(index):相同类型的文档的集合

映射(mapping):索引中文档的字段约束信息,类似表的结构约束

架构

Mysql:擅长事务类型操作,可以确保数据的安全和一致性

Elasticsearch:擅长海量数据的搜索,分析,计算。

部署es

创建网络

部署kibana容器,因此需要es和kibana容器互联,这里创建一个网络:

docker network create es-net

加载镜像

把压缩包导入tmp文件夹后加载镜像:docker load -i es.tardocker load -i kibana.tar 

运行

docker run -d \--name es \-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \-e "discovery.type=single-node" \-v es-data:/usr/share/elasticsearch/data \-v es-plugins:/usr/share/elasticsearch/plugins \--privileged \--network es-net \-p 9200:9200 \-p 9300:9300 \
elasticsearch:7.12.1

部署kibana

运行

docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
--network=es-net \
-p 5601:5601  \
kibana:7.12.1

分词器

离线安装ik分词器

查看位置:docker volume inspect es-plugins把id安装包放到 es目录中重启es容器:docker restart es

 测试分词器

# 最少切分
POST /_analyze
{"text": "黑马程序员学习太棒了", "analyzer": "ik_smart"
}# 最细切分POST /_analyze
{"text": "黑马程序员学习太棒了", "analyzer": "ik_max_word"
}

Mapping属性

创建索引库

Es中通过Resutful请求操作索引库,文档,请求内容用DSL语句表示。

 创建索引库

PUT /heima
{"mappings": {"properties": {"info": {"type": "text","analyzer": "ik_smart"},"email": {"type": "keyword","index": false},"name": {"type": "object","properties": {"firstName": {"type": "keyword"},"lastName":{"type":"keyword"}}}}}
}

查看,删除索引库

PUT /索引库名/_mapping
{"properties": {"新字段名":{"type": "integer"}}
}

语法

查看索引库语法:GET /索引库名GET  /heima删除索引库语法: DELETE /索引库名DELETE  /heima

修改索引库

PUT /heima/_mapping
{"properties":{"age":{"type":"integer"}}
}

 删除索引库

DELETE /索引库名

文档

插入,查询,删除

插入文档:
POST /heima/_doc/1
{"info": "黑马程序员Java讲师",
"email": "zy@itcast.cn",
"name": {
"firstName": "云",
"lastName": "赵"
}
}查询文档:GET /heima/_doc/1删除文档:DELETE /heima/_doc/1

全量修改文档

先删后添加:
PUT /heima/_doc/1
{"info": "黑马程序员Java讲师",
"email": "ZhaoYun@itcast.cn",
"name": {
"firstName": "云",
"lastName": "赵"
}
}

局部修改文档字段


POST /heima/_update/1
{"doc":{"email":"liuzihao@itcast.cn"}
}

RestClient

用来操作ES,组装DSL语句,通过http请求发送给ES

Elasticsearch Clients | Elastic

初始化JavaRestClient

<properties><java.version>1.8</java.version><elasticsearch.version>7.12.1</elasticsearch.version>
</properties><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>

测试

package cn.itcast.hotel;import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;import java.io.IOException;public class HotelIndexTest {private RestHighLevelClient client;@Testvoid testInit(){System.out.println(client);}@BeforeEachvoid setUp() {this.client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.74.128:9200")));}@AfterEachvoid tearDown() throws IOException {this.client.close();}
}

@Test
void createHotelIndex() throws IOException {// 1.创建Request对象CreateIndexRequest request = new CreateIndexRequest("hotel");// 2.准备请求的参数:DSL语句request.source(MAPPING_TEMPLATE, XContentType.JSON);// 3.发送请求client.indices().create(request, RequestOptions.DEFAULT);
}

删除索引库

@Test
void testDeleteHotelIndex() throws IOException {// 1.创建Request对象DeleteIndexRequest request = new DeleteIndexRequest("hotel");// 2.发送请求client.indices().delete(request, RequestOptions.DEFAULT);
}

判断索引库是否存在

@Test
void testExistsHotelIndex() throws IOException {// 1.创建Request对象GetIndexRequest request = new GetIndexRequest("hotel");// 2.发送请求boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);// 3.输出System.err.println(exists ? "索引库已经存在!" : "索引库不存在!");
}

java增删改查文档

package cn.itcast.hotel;import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpHost;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.io.IOException;
import java.util.List;@SpringBootTest
class HotelDocumentTest {private RestHighLevelClient client;@Autowiredprivate IHotelService hotelService;@Testvoid testAddDocument() throws IOException {// 1.查询数据库hotel数据Hotel hotel = hotelService.getById(61083L);// 2.转换为HotelDocHotelDoc hotelDoc = new HotelDoc(hotel);// 3.转JSONString json = JSON.toJSONString(hotelDoc);// 1.准备RequestIndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());// 2.准备请求参数DSL,其实就是文档的JSON字符串request.source(json, XContentType.JSON);// 3.发送请求client.index(request, RequestOptions.DEFAULT);}@Testvoid testGetDocumentById() throws IOException {// 1.准备Request      // GET /hotel/_doc/{id}GetRequest request = new GetRequest("hotel", "61083");// 2.发送请求GetResponse response = client.get(request, RequestOptions.DEFAULT);// 3.解析响应结果String json = response.getSourceAsString();HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println("hotelDoc = " + hotelDoc);}@Testvoid testDeleteDocumentById() throws IOException {// 1.准备Request      // DELETE /hotel/_doc/{id}DeleteRequest request = new DeleteRequest("hotel", "61083");// 2.发送请求client.delete(request, RequestOptions.DEFAULT);}@Testvoid testUpdateById() throws IOException {// 1.准备RequestUpdateRequest request = new UpdateRequest("hotel", "61083");// 2.准备参数request.doc("price", "870");// 3.发送请求client.update(request, RequestOptions.DEFAULT);}@Testvoid testBulkRequest() throws IOException {// 查询所有的酒店数据List<Hotel> list = hotelService.list();// 1.准备RequestBulkRequest request = new BulkRequest();// 2.准备参数for (Hotel hotel : list) {// 2.1.转为HotelDocHotelDoc hotelDoc = new HotelDoc(hotel);// 2.2.转jsonString json = JSON.toJSONString(hotelDoc);// 2.3.添加请求request.add(new IndexRequest("hotel").id(hotel.getId().toString()).source(json, XContentType.JSON));}// 3.发送请求client.bulk(request, RequestOptions.DEFAULT);}@BeforeEachvoid setUp() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("192.168.74.128:9200")));}@AfterEachvoid tearDown() throws IOException {client.close();}}

DSL查询

DSL查询语法

DSLQuery的分类

*  查询所有:一般测试用,例如:match_all

* 全文检索(full text)查询:充分利用分词器对用户输入内容分词,然后取倒排索引库中匹配,例如:

   * match_query

    * multi_match_query

* 精确查询:根据 精确词条值查找数据,一般是查找keyword,数值,日期,boolean等类型字段。

       例如: ids , range  ,  term

*  地理查询(geo): 根据经纬度查询。

       例如:geo_distance , geo_bounding_box

* 复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。

            例如:bool, function_score

查询全部:GET /hotel/_search
{"query":{"match_all":{}}
}match_查询
GET /hotel/_search
{"query":{"match": {"all": "外滩"}}
}multi_match 查询
GET /hotel/_search
{"query": {"multi_match": {"query": "外滩如家","fields": ["brand","name","business"]}}
}term查询
GET /hotel/_search
{"query":{"term":{"city": {"value": "上海"}}}
}range范围查询
GET /hotel/_search
{"query":{"range": {"price": {"gte": 100,"lte": 300}}}
}distance查询
GET /hotel/_search
{"query": {"geo_distance":{"distance":"15km","location":"31.21,121.5"}}
}// 相关性算分查询
GET /hotel/_search
{"query": {"function_score": {"query": {  .... }, // 原始查询,可以是任意条件"functions": [ // 算分函数{"filter": { // 满足的条件,品牌必须是如家"term": {"brand": "如家"}},"weight": 2 // 算分权重为2}],"boost_mode": "sum" // 加权模式,求和}}
}GET /hotel/_search
{"query": {"bool": {"must": [{"term": {"city": "上海" }}],"should": [{"term": {"brand": "皇冠假日" }},{"term": {"brand": "华美达" }}],"must_not": [{ "range": { "price": { "lte": 500 } }}],"filter": [{ "range": {"score": { "gte": 45 } }}]}}
}地理坐标排序
GET /indexName/_search
{"query": {"match_all": {}},"sort": [{"_geo_distance" : {"FIELD" : "纬度,经度", // 文档中geo_point类型的字段名、目标坐标点"order" : "asc", // 排序方式"unit" : "km" // 排序的距离单位}}]
}高亮显示
GET /hotel/_search
{"query": {"match": {"FIELD": "TEXT" // 查询条件,高亮一定要使用全文检索查询}},"highlight": {"fields": { // 指定要高亮的字段"FIELD": {"pre_tags": "<em>",  // 用来标记高亮字段的前置标签"post_tags": "</em>" // 用来标记高亮字段的后置标签}}}
}

相关性算分

 符合查询

RestClient查询文档

package cn.itcast.hotel;import cn.itcast.hotel.pojo.HotelDoc;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.io.IOException;
import java.util.Map;/*** @author Mtz* @version 1.0* @2023/10/1715:40* @function* @comment*/
@SpringBootTest
public class testdemoRestClient {@Autowiredprivate RestHighLevelClient client;@Testvoid testMatchAll() throws IOException {// 1.准备RequestSearchRequest request = new SearchRequest("hotel");// 2.准备DSLrequest.source().query(QueryBuilders.matchAllQuery());// 3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析响应handleResponse(response);}private void handleResponse(SearchResponse response) {// 4.解析响应SearchHits searchHits = response.getHits();// 4.1.获取总条数long total = searchHits.getTotalHits().value;System.out.println("共搜索到" + total + "条数据");// 4.2.文档数组SearchHit[] hits = searchHits.getHits();// 4.3.遍历for (SearchHit hit : hits) {// 获取文档sourceString json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println("hotelDoc = " + hotelDoc);}}@Testvoid testMatch() throws IOException {// 1.准备RequestSearchRequest request = new SearchRequest("hotel");// 2.准备DSLrequest.source().query(QueryBuilders.matchQuery("all", "如家"));// 3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析响应handleResponse(response);}@Testvoid testBool() throws IOException {// 1.准备RequestSearchRequest request = new SearchRequest("hotel");// 2.准备DSL// 2.1.准备BooleanQueryBoolQueryBuilder boolQuery = QueryBuilders.boolQuery();// 2.2.添加termboolQuery.must(QueryBuilders.termQuery("city", "杭州"));// 2.3.添加rangeboolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));request.source().query(boolQuery);// 3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析响应handleResponse(response);}@Testvoid testTermMatch() throws IOException {// 1.准备RequestSearchRequest request = new SearchRequest("hotel");// 2.准备DSL
//        request.source()
//                .query(QueryBuilders.termQuery("city","杭州"));request.source().query(QueryBuilders.rangeQuery("price").gte(100).lte(150));// 3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析响应handleResponse(response);}@Testvoid testPageAndSort() throws IOException {// 页码,每页大小int page = 1, size = 5;// 1.准备RequestSearchRequest request = new SearchRequest("hotel");// 2.准备DSL// 2.1.queryrequest.source().query(QueryBuilders.matchAllQuery());// 2.2.排序 sortrequest.source().sort("price", SortOrder.ASC);// 2.3.分页 from、sizerequest.source().from((page - 1) * size).size(5);// 3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析响应handleResponse(response);}@Testvoid testHighlight() throws IOException {// 1.准备RequestSearchRequest request = new SearchRequest("hotel");// 2.准备DSL// 2.1.queryrequest.source().query(QueryBuilders.matchQuery("all", "如家"));// 2.2.高亮request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));// 3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析响应handleResponse(response);}@BeforeEachvoid setUp() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("192.168.74.128:9200")));}@AfterEachvoid tearDown() throws IOException {client.close();}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 Python 实现简单的爬虫框架

爬虫是一种自动获取网页内容的程序&#xff0c;它可以帮助我们从网络上快速收集大量信息。在本文中&#xff0c;我们将学习如何使用 Python 编写一个简单的爬虫框架。 一、请求网页 首先&#xff0c;我们需要请求网页内容。我们可以使用 Python 的 requests 库来发送 HTTP 请…

【STM32F103】ADC 模拟数字转换器

ADC ADC&#xff08;Analog-to-Digital Converter&#xff09;&#xff0c;模拟-数字转换器&#xff0c;也叫模数转换器&#xff0c;可以将连续变化的模拟信号转换为离散的数字信号。 我们可以外接上将采集信号转为模拟信号的模块&#xff0c;如光敏电阻传感器&#xff0c;热…

仓库拣货应用案例

多个订单的光挑选 PTL用于WIP&#xff08;正在工作&#xff09;机架 首先&#xff0c;我们的过程。 制造工厂很大&#xff0c;有大量的制造工具&#xff0c;非常密集&#xff0c;而且大量的高设备可能会阻碍无线电 晶片储存在一个密封的载体中&#xff0c;它们从一台机器运输…

Windows CMD cd命令无法使用,路径无法更改解决方法

故障表现&#xff1a; 1.cmd使用命令cd更改路径后&#xff0c;路径仍然显示为初始路径 解决方法&#xff1a; 1.先更改至指定盘符&#xff0c;再使用cd命令 2.使用cd命令后&#xff0c;再更改至指定盘符

[C++进阶]---AVL树模拟实现

目录 1.AVL树的概念2.AVL树模拟实现2.1AVL树节点的定义2.2AVL的插入2.3AVL树的旋转2.3.1左单旋2.3.2右单旋2.3.3右左双旋2.3.3.1旋转情况分析2.3.3.2平衡因子更新分析 2.3.4右左双旋2.3.4.1旋转情况分析2.3.4.2平衡因子更新分析 2.3.5AVL树的验证 3.AVL模拟实现源码4.总结 1.AV…

jetpack compose 学习(2)

jetpack compose 学习(1) 学会了如何创建一个compose项目,并成功run了起来 今天学习run起来的界面配置 找启动界面,当然是先找到界面的配置文件: androidManifest.xml 这个文件,然后通过启动项找到主界面, 第二步 按住ctrl 鼠标指向MainActivity 即可跳转主界面 进入后的界面…

_try_finally原理探究

无论try结构体中是什么代码&#xff0c;都会执行finally里面的代码 局部展开 当try里面没有异常&#xff0c;而是return、continue、break等语句时&#xff0c;就不会走_except_handle3这个函数&#xff0c;而是调用_local_unwind2进行展开 然后调用[ebx esi*4 8] 跟进去就到…

MySQL低版本中:字符串中的数字、英文字符、汉字提取

我们如何提醒一个字段中的汉字和数字呢 高版本指mysql8.0以上 使用sql语句 SELECT REGEXP_REPLACE(column_name, [^\\p{Han}], ) AS chinese_characters FROM table_name;其中 column_name指名称列&#xff0c;table_name是表名 2.低版本使用 需要新建函数 DELIMITER $$DR…

Java调用百度翻译API和调用有道翻译API进行翻译

目录 界面编写 调用百度API 调用有道API 源代码 界面编写 我们首先需要设计出这个翻译程序的GUI界面&#xff0c;我们写一个类继承自JFrame类&#xff0c;用来展示程序的主窗口&#xff0c;设置好窗口的名称和大小&#xff0c;设置在关闭窗口时终止程序&#xff0c;为了界…

高效数组处理的Numpy入门总结

NumPy是Python中一个重要的数学库&#xff0c;它提供了高效的数组操作和数学函数&#xff0c;是数据科学、机器学习、科学计算等领域的重要工具。下面是一个简单的NumPy学习教程&#xff0c;介绍了NumPy的基本用法和常用函数。 安装NumPy 在使用NumPy之前&#xff0c;需要先安…

删除Tencent files

QQ或者TIM卸载后,它还会残留在电脑上.要修改会说需要权限,修改权限又会重新变回去.这时候可以把整个文档放到其它盘,然后就可以删除Tencent files 方法是右键文档 选中属性–位置 然后就可以改掉了

【后端学前端】第三天 css动画 动态搜索框(定位、动态设置宽度)

1、学习信息 视频地址&#xff1a;css动画 动态搜索框&#xff08;定位、动态设置宽度&#xff09;_哔哩哔哩_bilibili 2、源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>test3</title>…

14:00面试,14:08就出来了,问的问题有点变态。。。。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到5月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

Flutter的BuildContext简介

文章目录 BuildContext 简介BuildContext的主要作用 BuildContext 简介 BuildContext是Flutter中的一个重要概念&#xff0c;表示当前Widget在树中的位置上下文。它是一个对Widget树的一个位置的引用&#xff0c;用于查找、访问和操作该位置上的相关信息。每个Widget都有一个关…

VMware Fusion Pro 中文 for mac:好用的虚拟机

VMware Fusion 不仅能让你在 Mac 苹果电脑上运行 Windows 或 Linux 系统、使用非 Mac 平台的软件&#xff0c;而且还可以支持各种 USB硬件设备&#xff0c;它无疑是 macOS 用户的最佳助手。VMWare Fusion 是在 Mac 下虚拟运行 Windows / Linux 的最佳方式 无比轻松地在 Mac 上…

Map、Set集合与Gson注解

一、Map的序列化与反序列化 1.Map集合类型对象在反序列化时与List一样&#xff0c;需要使用TypeToken完成反序列化。 2.Set在反序列化时需要使用TypeToken完成反序列化。 创建User类和job类 public class User {Exposeprivate String userName;Exposeprivate String passwo…

Netflix Mac(奈飞客户端)激活版软件介绍

Netflix Mac(奈飞客户端)是一款流行的视频播放软件&#xff0c;专为Mac用户设计。它提供了大量的高质量电影、电视剧、纪录片和动画片资源&#xff0c;让用户可以随时随地观看自己喜欢的内容。 首先&#xff0c;Netflix Mac(奈飞客户端)以其简洁直观的用户界面而闻名。用户可以…

2024测试开发面试题完整版本(附答案)

目录 1. 什么是软件测试&#xff0c; 谈谈你对软件测试的了解 2. 我看你简历上有写了解常见的开发模型和测试模型, 那你跟我讲一下敏捷模型 3. 我看你简历上还写了挺多开发技能的, 那你给我讲讲哈希表的实现流程 4. 谈一谈什么是线程安全问题, 如何解决 5. 既然你选择走测…

Java - Spring中BeanFactory和FactoryBean的区别

BeanFactory Spring IoC容器的顶级对象&#xff0c;BeanFactory被翻译为“Bean工厂”&#xff0c;在Spring的IoC容器中&#xff0c;“Bean工厂”负责创建Bean对象。 BeanFactory是工厂。 FactoryBean FactoryBean&#xff1a;它是一个Bean&#xff0c;是一个能够辅助Spring实例…

【项目管理】CMMI对项目管理有哪些个人启发和思考

导读&#xff1a;本人作为项目经理参与公司CMMI5级评审相关材料准备工作&#xff0c;现梳理CMMI有关知识点&#xff0c;并结合项目给出部分示例参考&#xff0c;以及本人对于在整理材料过程中一些启发和体验思考。 目录 1、CMMI定义 2、CMMI-5级 3、CMMI文档清单 4、示例-度…