HM-SpringCloud微服務系列6.4【黑馬旅遊案例】
阿新 • • 發佈:2022-03-29
1 酒店搜尋和分頁
1.1 課件
1.2 需求分析
- 在專案的首頁,有一個大大的搜尋框,還有分頁按鈕
點選搜尋按鈕,可以看到瀏覽器控制檯發出了請求:
請求引數如下:
- 由此可以知道,我們這個請求的資訊如下:
- 請求方式:POST
- 請求路徑:/hotel/list
- 請求引數:JSON物件,包含4個欄位:
- key:搜尋關鍵字
- page:頁碼
- size:每頁大小
- sortBy:排序,目前暫不實現
- 返回值:分頁查詢,需要返回分頁結果PageResult,包含兩個屬性:
-
total
:總條數 -
List<HotelDoc>
:當前頁的資料
-
- 因此,我們實現業務的流程如下:
- 步驟一:定義實體類,接收請求引數的JSON物件
- 步驟二:編寫controller,接收頁面的請求
- 步驟三:編寫業務實現,利用RestHighLevelClient實現搜尋、分頁
1.3 定義實體類
實體類有兩個,一個是前端的請求引數實體,一個是服務端應該返回的響應結果實體。
1.3.1 請求引數
- 前端請求的json結構如下:
{ "key": "搜尋關鍵字", "page": 1, "size": 3, "sortBy": "default" }
- 因此,我們在
com.yppah.hoteldemo.pojo
包下定義一個實體類:package com.yppah.hoteldemo.pojo; import lombok.Data; @Data public class RequestParams { private String key; private Integer page; private Integer size; private String sortBy; }
1.3.2 返回值
- 分頁查詢,需要返回分頁結果PageResult,包含兩個屬性:
-
total
:總條數 -
List<HotelDoc>
:當前頁的資料
-
- 因此,我們在
com.yppah.hoteldemo.pojo
中定義返回結果:package com.yppah.hoteldemo.pojo; import lombok.Data; import java.util.List; @Data public class PageResult { private Long total; private List<HotelDoc> hotels; }
1.4 定義Controller
-
定義一個HotelController,宣告查詢介面,滿足下列要求:
- 請求方式:Post
- 請求路徑:/hotel/list
- 請求引數:物件,型別為RequestParam
- 返回值:PageResult,包含兩個屬性
-
Long total
:總條數 -
List<HotelDoc> hotels
:酒店資料
-
-
因此,我們在
com.yppah.hoteldemo.web
中定義HotelController:點選檢視程式碼
package com.yppah.hoteldemo.web; import com.yppah.hoteldemo.pojo.PageResult; import com.yppah.hoteldemo.pojo.RequestParams; import com.yppah.hoteldemo.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; @RestController @RequestMapping("/hotel") public class HotelController { @Autowired private IHotelService hotelService; @PostMapping("/list") public PageResult search(@RequestBody RequestParams params) { return hotelService.search(params); } }
1.5 實現搜尋業務
-
我們在controller呼叫了IHotelService,並沒有實現該方法,因此下面我們就在IHotelService中定義方法,並且去實現業務邏輯。
-
在
com.yppah.hoteldemo.service
中的IHotelService
介面中定義一個方法:點選檢視程式碼
package com.yppah.hoteldemo.service; import com.yppah.hoteldemo.pojo.Hotel; import com.baomidou.mybatisplus.extension.service.IService; import com.yppah.hoteldemo.pojo.PageResult; import com.yppah.hoteldemo.pojo.RequestParams; public interface IHotelService extends IService<Hotel> { /** * 根據關鍵字搜尋酒店資訊 * @param params 請求引數物件,包含使用者輸入的關鍵字 * @return 酒店文件列表 */ PageResult search(RequestParams params); }
-
在
com.yppah.hoteldemo.service.impl
中的HotelService
中實現search方法:點選檢視程式碼
package com.yppah.hoteldemo.service.impl; import com.alibaba.fastjson.JSON; import com.yppah.hoteldemo.mapper.HotelMapper; import com.yppah.hoteldemo.pojo.Hotel; import com.yppah.hoteldemo.pojo.HotelDoc; import com.yppah.hoteldemo.pojo.PageResult; import com.yppah.hoteldemo.pojo.RequestParams; import com.yppah.hoteldemo.service.IHotelService; 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.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.IOException; import java.util.ArrayList; import java.util.List; @Service public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService { @Autowired private RestHighLevelClient client; // 使用之前需要在專案啟動類HoteldemoApplication中用@Bean將其注入到spring中 @Override public PageResult search(RequestParams params) { try { // 1. 準備Request SearchRequest request = new SearchRequest("hotel"); // 2. 準備DSL // 2.1 關鍵字搜尋query String key = params.getKey(); if (key==null || "".equals(key)) { request.source().query(QueryBuilders.matchAllQuery()); } else { request.source().query(QueryBuilders.matchQuery("all", key)); } // 2.2 查詢結果分頁處理 int page = params.getPage(); // 自動拆箱 int size = params.getSize(); request.source().from((page-1)*size).size(size); // 3. 傳送Request,得到Response SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4. 解析Response return handleResponse(response); } catch (IOException e) { throw new RuntimeException(e); } } private PageResult handleResponse(SearchResponse response) { // 需要在PageResult中新增建構函式兩個 //4 解析響應 SearchHits searchHits = response.getHits(); //4.1 獲取總條數 long total = searchHits.getTotalHits().value; //4.2 獲取文件陣列 SearchHit[] hits = searchHits.getHits(); //4.3 遍歷陣列 List<HotelDoc> hotels = new ArrayList<>(); //用於存放PageResult所要求格式的資料 for (SearchHit hit : hits) { //4.3.1 獲取文件source String json = hit.getSourceAsString(); //4.3.2 反序列化解析json HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class); hotels.add(hotelDoc); } //4.4 封裝返回 return new PageResult(total, hotels); } }
-
實現搜尋業務,肯定離不開RestHighLevelClient,我們需要把它註冊到Spring中作為一個Bean。在
com.yppah.hoteldemo
中的HotelDemoApplication
中宣告這個Bean:@Bean public RestHighLevelClient client() { return new RestHighLevelClient(RestClient.builder( HttpHost.create("http://10.193.193.141:9200") )); }