目录
一、前言
二、项目展示
三、部分代码展示
本文章教程来自于黑马程序员的微服务教程 的黑马旅游网项目。
前端技术栈
html5、css3、JavaScript、vue、element-ui、axios
后端技术栈
springboot、Elasticsearch、RabbitMQ、Docker、mybatis-plus等。
控制层
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.*;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/hotel")
public class HotelController {
@Autowired
private IHotelService hotelService;
@PostMapping("/list")
public PageResult search(@RequestBody RequestParams params) throws IOException {
return hotelService.search(params);
}
@PostMapping("/filters")
public Map> filters(@RequestBody RequestParams params) throws IOException {
return hotelService.filters(params);
}
@GetMapping("suggestion")
public List getSuggestions(@RequestParam("key") String prefix){
return hotelService.getSuggestions(prefix);
}
}
service层
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.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
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.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.swing.border.SoftBevelBorder;
import java.io.IOException;
import java.util.*;
@Service
public class HotelService extends ServiceImpl implements IHotelService {
@Autowired
private RestHighLevelClient client;
@Override
public PageResult search(RequestParams params) {
try {
// 准备request
SearchRequest request = new SearchRequest("hotel");
buildBasicQuery(params, request);
// 分页
int page = params.getPage();
int size = params.getSize();
request.source().from((page - 1) * size).size(size);
// 排序
String location = params.getLocation();
if (location != null && !location.equals("")){
request.source().sort(SortBuilders
.geoDistanceSort("location", new GeoPoint(location))
.order(SortOrder.ASC)
.unit(DistanceUnit.KILOMETERS)
);
}
// 发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
return handleResponse(response);
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public Map> filters(RequestParams params) {
try {
// 准备request
SearchRequest request = new SearchRequest("hotel");
// query
buildBasicQuery(params, request);
// 准备dsl
// 设置size
request.source().size(0);
// 聚合
buildAggregation(request);
// 发送请求
Map> result = new HashMap<>();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 解析响应
// 根据名称获取品牌的结果
Aggregations aggregations = response.getAggregations();
// 获取聚合结果
List brandList = getAggByName(aggregations, "brandAgg");
result.put("brand", brandList);
List cityList = getAggByName(aggregations, "cityAgg");
result.put("city", cityList);
List starList = getAggByName(aggregations, "starAgg");
result.put("starName", starList);
return result;
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public List getSuggestions(String prefix) {
// System.out.println("prefix = " + prefix);
try {
// 准备request
SearchRequest request = new SearchRequest("hotel");
request.source().suggest(new SuggestBuilder().addSuggestion(
"suggestions",
SuggestBuilders.completionSuggestion("suggestion")
.prefix(prefix)
.skipDuplicates(true)
.size(10)
));
// 发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 解析结果
Suggest suggest = response.getSuggest();
// 根据补全的名称,获取补全的结果
CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");
// 获取 options
List options = suggestions.getOptions();
// 遍历
List list = new ArrayList<>();
for (CompletionSuggestion.Entry.Option option : options) {
String s = option.getText().toString();
list.add(s);
}
return list;
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public void deleteById(Long id) {
try {
// 1.准备Request
DeleteRequest request = new DeleteRequest("hotel", id.toString());
// 2.发送请求
client.delete(request, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void insertById(Long id) {
try {
// 0.根据id查询酒店数据
Hotel hotel = getById(id);
// 转换为文档类型
HotelDoc hotelDoc = new HotelDoc(hotel);
// 1.准备Request对象
IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
// 2.准备Json文档
request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
// 3.发送请求
client.index(request, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private List getAggByName(Aggregations aggregations,String aggName) {
Terms brandTerms = aggregations.get(aggName);
// 获取 buckets
List extends Terms.Bucket> buckets = brandTerms.getBuckets();
// 遍历
List brandList = new ArrayList<>();
for (Terms.Bucket bucket : buckets) {
// 获取key
String key = bucket.getKeyAsString();
brandList.add(key);
System.out.println("key = " + key);
}
return brandList;
}
private void buildAggregation(SearchRequest request) {
request.source().aggregation(AggregationBuilders
.terms("brandAgg")
.field("brand")
.size(100)
);
request.source().aggregation(AggregationBuilders
.terms("cityAgg")
.field("city")
.size(100)
);
request.source().aggregation(AggregationBuilders
.terms("starAgg")
.field("starName")
.size(100)
);
}
private void buildBasicQuery(RequestParams params, SearchRequest request) {
// 准备dsl,获取数据
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
String sortBy = params.getSortBy();
if (!Objects.equals(sortBy, "default")) {
request.source().query(QueryBuilders.matchAllQuery());
request.source().sort(sortBy, SortOrder.ASC);
}
// 关键字搜索
String key = params.getKey();
if (Objects.equals(key, "") || key == null) {
boolQuery.must(QueryBuilders.matchAllQuery());
} else {
boolQuery.must(QueryBuilders.matchQuery("all", key));
}
// 城市条件
if (params.getCity() != null && !params.getCity().equals("")){
boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
}
// 品牌条件
if (params.getBrand() != null && !params.getBrand().equals("")){
boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
}
// 星级条件
if (params.getStarName() != null && !params.getStarName().equals("")){
String temp = "";
if (Objects.equals(params.getStarName(), "四星")){
temp = params.getStarName() + "级";
boolQuery.filter(QueryBuilders.termQuery("starName", temp));
}else if (Objects.equals(params.getStarName(), "五星")){
temp = params.getStarName() + "级";
boolQuery.filter(QueryBuilders.termQuery("starName", temp));
}else {
boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));
}
}
// 价格条件
if (params.getMinPrice() != null && params.getMaxPrice() != null){
boolQuery.filter(QueryBuilders
.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
}
FunctionScoreQueryBuilder functionScoreQuery =
QueryBuilders.functionScoreQuery(
// 原始查询
boolQuery,
new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
// 其中一个function score 元素
new FunctionScoreQueryBuilder.FilterFunctionBuilder(
// 过滤条件
QueryBuilders.termQuery("isAD", true),
// 算分函数,默认为乘法
ScoreFunctionBuilders.weightFactorFunction(10)
)
}
);
request.source().query(functionScoreQuery);
}
// 抽取方法
private PageResult handleResponse(SearchResponse response) {
// 响应解析
SearchHits searchHits = response.getHits();
// 获取条数
long total = searchHits.getTotalHits().value;
System.out.println(total);
// 获取htis(黑丝)
SearchHit[] hits = searchHits.getHits();
List hotels = new ArrayList<>();
for (SearchHit hit : hits) {
// 获取文档source
String json = hit.getSourceAsString();
// 反序列化
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
Object[] sortValues = hit.getSortValues();
if (sortValues.length > 0){
Object sortValue = sortValues[0];
hotelDoc.setDistance(sortValue);
}
hotels.add(hotelDoc);
}
return new PageResult(total, hotels);
}
}
mapper层
//@Mapper
public interface HotelMapper extends BaseMapper {
}
主启动类
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);
}
@Bean
public RestHighLevelClient client(){
return new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.71.133:9200")
));
}
}
四、文件获取
链接:百度网盘 请输入提取码 提取码:zhui