【SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】
案例1:实现黑马旅游的酒店搜索功能,完成关键字搜索和分页
我们课前提供的hotel-demo项目中,自带了前端页面,启动后可以看到:

妙啊
先实现其中的关键字搜索功能,实现步骤如下:
定义实体类,接收前端请求
定义controller接口,接收页面请求,调用IHotelService的search方法
定义IHotelService中的search方法,利用match查询实现根据关键字搜索酒店信息

启动服务

OK, 成功运行,8089 端口直接访问

我超,但是我的数据库里面只有201 条,这应该是写死的假数据了【嗯】
看看网络请求

步骤1:定义类,接收前端请求参数
package cn.itcast.hotel.pojo;import lombok.Data;/*** ClassName: RequestParams* date: 2022/11/2 11:03** @author DingJiaxiong*/@Data
public class RequestParams {private String key;private Integer page;private Integer size;private String sortBy;}

OK, 请求参数实体类
步骤2:定义controller接口,接收前端请求
定义一个HotelController,声明查询接口,满足下列要求:
先来一个返回结果的实体类
package cn.itcast.hotel.pojo;import lombok.Data;import java.util.List;/*** ClassName: PageResult* date: 2022/11/2 11:06** @author DingJiaxiong*/@Data
public class PageResult {private Long total;private List hotels;public PageResult() {}public PageResult(Long total, List hotels) {this.total = total;this.hotels = hotels;}
}

OK
定义controller
package cn.itcast.hotel.web;import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import cn.itcast.hotel.service.IHotelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** ClassName: HotelController* date: 2022/11/2 11:07** @author DingJiaxiong*/@RestController
@RequestMapping("/hotel")
public class HotelController {@Autowiredprivate IHotelService hotelService;@PostMapping("/list")public PageResult search(@RequestBody RequestParams params){return hotelService.search(params);}
}
修改服务接口
package cn.itcast.hotel.service;import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import com.baomidou.mybatisplus.extension.service.IService;public interface IHotelService extends IService {PageResult search(RequestParams params);
}
注入client
package cn.itcast.hotel;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;@MapperScan("cn.itcast.hotel.mapper")
@SpringBootApplication
public class HotelDemoApplication {public static void main(String[] args) {SpringApplication.run(HotelDemoApplication.class, args);}@Beanpublic RestHighLevelClient client() {return new RestHighLevelClient(RestClient.builder(HttpHost.create("http://118.195.248.48:9200")));}
}

修改业务实现类
package cn.itcast.hotel.service.impl;import cn.itcast.hotel.mapper.HotelMapper;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PBEParameterSpec;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;@Service
public class HotelService extends ServiceImpl implements IHotelService {@Autowiredprivate RestHighLevelClient client;@Overridepublic PageResult search(RequestParams params) {try {//1. 准备RequestSearchRequest request = new SearchRequest("hotel");//2. 准备DSL//2.1 关键字搜索queryString key = params.getKey();//健壮判断if (key == null || "".equals(key)) {request.source().query(QueryBuilders.matchAllQuery());} else {request.source().query(QueryBuilders.matchQuery("all", key));}//2.2 分页Integer page = params.getPage();Integer size = params.getSize();request.source().from((page - 1) * size).size(size);//3. 发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);//4. 解析响应return handleResponse(response);}catch (IOException e){throw new RuntimeException(e);}}private PageResult 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 遍历List hotels = new ArrayList<>();for (SearchHit hit : hits) {//获取文档sourceString json = hit.getSourceAsString();//反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);hotels.add(hotelDoc);}//4.4 封装返回return new PageResult(total, hotels);}
}
OK, 重启服务进行测试

OK, 我数据库里面确实只有201 条数据

试试分页

OK, 没问题
搜索“如家”

没毛病
查看控制台
发起的请求参数:

响应结果

没毛病