微服务技术栈SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式(五):分布式搜索 ES-中


一、DSL查询文档

在这里插入图片描述

1.1 简单查询

# 1. DSL查询
# 1.1 查询所有

GET /hotel/_search
{
  "query": {
    "match_all": {}
  }
}

# 1.2 全文检索查询:对用户输入的内容分词后查询,常用于搜索框查询
# 1)match查询 :all字段是在创建hotel索引库时创建的,里面包括brand name busiess字段(copy to)
# 例子:查询hotel中brand、name、businiss中有"外滩"二字的文档
GET /hotel/_search
{
  "query": {
    "match": {
      "all": "外滩"
    }
  }
}
# 2)muiti_match查询:效果和上面一样
# 例子:查询hotel中brand、name、businiss中有"外滩如家"四字的文档
GET /hotel/_search
{
  "query": {
    "multi_match": {
      "query": "外滩如家",
      "fields": ["brand","name","business"]
    }
  }
}
# 3)match与multi_match的区别在于:match是单字段查询;而multi_match是多字段查询,字段越多性能越差;建议用copy to将多个字段拷到一个字段用match查询


# 1.3 精确查询:一般查找类型为keyword、boolean、数值、日期等字段,不分词
# 1)term:根据词条的精确值查询
# 例子:查询hotel中city="上海"的文档
GET /hotel/_search
{
  "query": {
    "term": {
      "city": {
        "value": "上海"
      }
    }
  }
}
# 2)range:根据值的范围查询
# 例子:查询price在(1000,2000]的文档
GET /hotel/_search
{
  "query": {
    "range": {
      "price": {
        "gt": 1108,
        "lte": 2000
      }
    }
  }
}

# 1.4 经纬度查询
# 1)geo_bounding_box:查询geo_point值落在某个矩形范围的所有文档
# 例子:查询hotel中location两个经纬度点矩形范围内内的文档
GET /hotel/_search
{
  "query": {
    "geo_bounding_box": {
      "location": {
        "top_left": {
          "lat": 31.1,
          "lon": 121.5
        },
        "bottom_right": {
          "lat": 30.9,
          "lon": 121.7
        }
      }
    }
  }
}

# 2)geo_distance:查询到指定中心点小于某个距离值的所有文档
# 例子:查询(31.21,121.5)范围内5km的的文档
GET /hotel/_search
{
  "query": {
    "geo_distance": {
      "distance": "5km",
      "location": "31.21, 121.5"
    }
  }
}

1.2 复合查询

在这里插入图片描述
在这里插入图片描述

# 1.5 复合查询
# 1function socre:算分函数查询,可以控制文档相关性算分,控制文档的排名
# 例:在all为"外滩"的查询中将"如家"这个品牌的酒店排名靠前一些
GET /hotel/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "all": "外滩"
        }
      },
      "functions": [
        {
          "filter": {
            "term": {
              "brand": "如家"
            }
          },
          "weight": 10
        }
      ],
      "boost_mode": "sum"
    }
  }
}

# 2)布尔查询:组合多个子查询
# must:必须匹配每个子查询,相当于“与”
# should:选择性匹配子查询,相当于“或”
# must_not:必须不匹配【不参与算分】,相当于“非”
# filter:必须匹配【不参与算法】

# 例:查询name包含"如家",价格不高于400,坐标(31.21,121.5)范围内10km的hotel
# 下面代码中,如果将price和location放入must中会参与算分,为了节省性能,一般放在must_not或者filter中
GET /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "如家"
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "gt": 400
            }
          }
        }
      ],
      "filter": [
        {
          "geo_distance": {
            "distance": "10km",
            "location": {
              "lat": 31.21,
              "lon": 121.5
            }
          }
        }
      ]
    }
  }
}


二、搜索结果处理

深度分页问题
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

# 2. 搜索结果处理
# 2.1 排序:es默认根据算分排序。可以用来排序的字段有:keyword、数值、坐标、日期
# 例1:对hotel数据按用户评价score降序,相同评价按价格price升序
GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "score": "desc"
    },
    {
      "price": "asc"
    }
  ]
}

# 例2:对hotel数据按你的坐标位置(115.450059,38.866053)距离升序排序
# 获取经纬度的方式:https://lbs.amap.com/demo/jsapi-v2/example/map/click-to-get-lnglat/
GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 38.866053,
          "lon": 115.45005
        },
        "order": "asc",
        "unit": "km"
      }
    }
  ]
}



# 2.2 分页:es默认返回top10的数据,想要查询更多需要设置
# from表示分页开始位置,默认为0;size表示期望获取文档数

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "from": 5,
  "size": 1,
  "sort": [
    {
      "price": "asc"
    }
  ]
}

# 2.3 高亮:将搜索结果的搜索关键字突出显示
# 原理:将搜索结果的关键字用标签标记出来,在页面中给标签添加css样式
# 注意:默认情况下ES搜索字段必须与高亮字段保持一致,而下面搜索字段为all,高亮字段为name,虽然all包括name,但是需要设置require_field_match=false
GET /hotel/_search
{
  "query": {
    "match": {
      "all": "如家"
    }
  },
  "highlight": {
    "fields": {
      "name": {
        "require_field_match": "false", 
        "pre_tags": "<em>",
        "post_tags": "</em>"
      }
    }
  }
}

在这里插入图片描述

三、RestClient演示 查询与结果分析

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

@SpringBootTest
class HotelSearchTest {

    private RestHighLevelClient client;

    @BeforeEach
    void setUp() {
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.1.101:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        client.close();
    }

    /**
     * 解析json文档
     */
    private void handleResponse(SearchResponse response) {
        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) {
            // 4.4.获取source
            String json = hit.getSourceAsString();
            // 4.5.反序列化,非高亮的
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            // 4.6.处理高亮结果
            // 1)获取高亮map
            Map<String, HighlightField> map = hit.getHighlightFields();
            // 2)根据字段名,获取高亮结果
            HighlightField highlightField = map.get("name");
            // 3)获取高亮结果字符串数组中的第1个元素
            String hName = highlightField.getFragments()[0].toString();
            // 4)把高亮结果放到HotelDoc中
            hotelDoc.setName(hName);
            // 4.7.打印
            System.out.println(hotelDoc);
            System.out.println(json);
        }
    }

    /**
     * 查询所有文档
     */
    @Test
    void testMatchAll() throws IOException {
        // 1.准备request
        SearchRequest request = new SearchRequest("hotel");
        // 2.准备请求参数
        request.source().query(QueryBuilders.matchAllQuery());
        // 3.发送请求,得到响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 4.结果解析
        handleResponse(response);
    }

    /**
     * 全文检索查询:match、multi_match
     */
    @Test
    void testMatch() throws IOException {
        // 1.准备request
        SearchRequest request = new SearchRequest("hotel");
        // 2.准备请求参数
        //request.source().query(QueryBuilders.matchQuery("all", "外滩如家"));
        request.source().query(QueryBuilders.multiMatchQuery("外滩如家", "name", "brand", "city"));
        // 3.发送请求,得到响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 4.结果解析
        handleResponse(response);
    }

    /**
     * 1.精确查询:term、range
     * 2.boolean组合查询
     * 查询city为杭州,price>=250的文档
     */
    @Test
    void testBool() throws IOException {
        // 1.准备request
        SearchRequest request = new SearchRequest("hotel");
        // 2.准备请求参数
       /*
         BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // 2.1.must
        boolQuery.must(QueryBuilders.termQuery("city", "上海"));
        // 2.2.filter
        boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));
        request.source().query(boolQuery);
        */

        request.source().query(
                QueryBuilders.boolQuery()
                        .must(QueryBuilders.termQuery("city", "上海"))
                        .filter(QueryBuilders.rangeQuery("price").lte(250))
        );
        // 3.发送请求,得到响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 4.结果解析
        handleResponse(response);
    }


    /**
     * 排序和分页
     */
    @Test
    void testSortAndPage() throws IOException {
        int page = 2,size = 5;

        // 1.准备request
        SearchRequest request = new SearchRequest("hotel");
        // 2.准备请求参数
        // 2.1.query
        request.source()
                .query(QueryBuilders.matchAllQuery());
        // 2.2.排序sort
        request.source().sort("price", SortOrder.ASC);
        // 2.3.分页 from\size
        request.source().from((page - 1) * size).size(size);

        // 3.发送请求,得到响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 4.结果解析
        handleResponse(response);
    }

    /**
     * 结果高亮
     */
    @Test
    void testHighlight() throws IOException {
        // 1.准备request
        SearchRequest request = new SearchRequest("hotel");
        // 2.准备请求参数
        // 2.1.query
        request.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);
    }
}

四、案例

4.1 问题解析

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.2 代码

在这里插入图片描述

4.2.1 实体bean

PageResult.java 响应结果类:由搜索框得到的查询结果类

/**
 * 响应结果类:由搜索框得到的查询结果类
 */
@Data
public class PageResult {
    private Long total; // 总条数
    private List<HotelDoc> hotels; // 酒店信息

    public PageResult() {
    }

    public PageResult(Long total, List<HotelDoc> hotels) {
        this.total = total;
        this.hotels = hotels;
    }
}

RequestParams.java 请求参数类:搜索框中有哪些参数

/**
 * 请求参数类:搜索框中有哪些参数
 */
@Data
public class RequestParams {
    private String key;  // 搜索关键字
    private Integer page;// 当前页码
    private Integer size;// 每页大小
    private String sortBy;// 排序字段
    private String brand;// 品牌
    private String city;// 城市
    private String starName;// 星级
    private Integer minPrice;// 最低价格
    private Integer maxPrice;// 最高价格
    private String location;// 位置
}

4.2.2 控制层

@RestController
@RequestMapping("hotel")
public class HotelController {

    @Autowired
    private IHotelService hotelService;

    @PostMapping("list")
    public PageResult search(@RequestBody RequestParams params) {
        return hotelService.search(params);
    }
}

4.2.3 业务service

public interface IHotelService extends IService<Hotel> {
    PageResult search(RequestParams params);
}
@Slf4j
@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Override
    public PageResult search(RequestParams params) {
        try {
            // 1.准备Request
            SearchRequest request = new SearchRequest("hotel");

            // 2.准备请求参数

            // 2.1.多条件查询和过滤
            buildBasicQuery(params, request);

            // 2.2.分页
            int page = params.getPage();
            int size = params.getSize();
            request.source().from((page - 1) * size).size(size);

            /**
             * 2.3.距离排序
             */
            String location = params.getLocation();
            if (StringUtils.isNotBlank(location)) {// 不为空则查询
                request.source().sort(SortBuilders
                        .geoDistanceSort("location", new GeoPoint(location))
                        .order(SortOrder.ASC)
                        .unit(DistanceUnit.KILOMETERS)
                );
            }

            // 3.发送请求
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);

            // 4.解析响应
            return handleResponse(response);
        } catch (IOException e) {
            throw new RuntimeException("搜索数据失败", e);
        }
    }

    private void buildBasicQuery(RequestParams params, SearchRequest request) {
        // 1.准备Boolean复合查询
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        /**
         * 1.查询关键字
         * must参与 算分
         */
        // 1.1.关键字搜索,match查询,放到must中
        String key = params.getKey();
        if (StringUtils.isNotBlank(key)) {
            // 不为空,根据关键字查询
            boolQuery.must(QueryBuilders.matchQuery("all", key));
        } else {
            // 为空,查询所有
            boolQuery.must(QueryBuilders.matchAllQuery());
        }
        /**
         * 2.条件过滤:多条件复合查询
         * 根据 “品牌 城市 星级 价格范围” 过滤数据
         * filter不参与 算分
         */

        // 1.2.品牌
        String brand = params.getBrand();
        if (StringUtils.isNotBlank(brand)) { // 不为空则查询
            boolQuery.filter(QueryBuilders.termQuery("brand", brand));
        }
        // 1.3.城市
        String city = params.getCity();
        if (StringUtils.isNotBlank(city)) {// 不为空则查询
            boolQuery.filter(QueryBuilders.termQuery("city", city));
        }
        // 1.4.星级
        String starName = params.getStarName();
        if (StringUtils.isNotBlank(starName)) {// 不为空则查询
            boolQuery.filter(QueryBuilders.termQuery("starName", starName));
        }
        // 1.5.价格范围
        Integer minPrice = params.getMinPrice();
        Integer maxPrice = params.getMaxPrice();
        if (minPrice != null && maxPrice != null) {// 不为空则查询
            maxPrice = maxPrice == 0 ? Integer.MAX_VALUE : maxPrice;
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(minPrice).lte(maxPrice));
        }

        /**
         * 3.算分函数查询
         * 置顶功能:给你置顶的酒店添加一个标记,并按其算分
         */
        FunctionScoreQueryBuilder functionScoreQuery = QueryBuilders.functionScoreQuery(
                boolQuery, // 原始查询,boolQuery
                new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{ // function数组
                        new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                                QueryBuilders.termQuery("isAD", true), // 过滤条件
                                ScoreFunctionBuilders.weightFactorFunction(10) // 算分函数
                        )
                }
        );

        /**
         * 4.设置查询条件
          */
        request.source().query(functionScoreQuery);
    }

    private PageResult handleResponse(SearchResponse response) {
        SearchHits searchHits = response.getHits();
        // 4.1.总条数
        long total = searchHits.getTotalHits().value;
        // 4.2.获取文档数组
        SearchHit[] hits = searchHits.getHits();
        // 4.3.遍历
        List<HotelDoc> hotels = new ArrayList<>(hits.length);
        for (SearchHit hit : hits) {
            // 4.4.获取source
            String json = hit.getSourceAsString();
            // 4.5.反序列化,非高亮的
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            // 4.6.处理高亮结果
            // 1)获取高亮map
            Map<String, HighlightField> map = hit.getHighlightFields();
            if (map != null && !map.isEmpty()) {
                // 2)根据字段名,获取高亮结果
                HighlightField highlightField = map.get("name");
                if (highlightField != null) {
                    // 3)获取高亮结果字符串数组中的第1个元素
                    String hName = highlightField.getFragments()[0].toString();
                    // 4)把高亮结果放到HotelDoc中
                    hotelDoc.setName(hName);
                }
            }
            // 4.8.排序信息
            Object[] sortValues = hit.getSortValues(); // 获取排序结果
            if (sortValues.length > 0) {
                /**
                 * 由于该程序是根据距离[酒店距你选择位置的距离]进行排序,所以排序结果为距离
                 */
                hotelDoc.setDistance(sortValues[0]);
            }

            // 4.9.放入集合
            hotels.add(hotelDoc);
        }
        return new PageResult(total, hotels);
    }
}

4.2.4 启动类

@MapperScan("cn.itcast.hotel.mapper")
@SpringBootApplication
public class HotelDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(HotelDemoApplication.class, args);
    }

    @Bean
    public RestHighLevelClient restHighLevelClient(){
        return new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.1.101:9200")
        ));   // 服务器IP+端口9200
    }
}
  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于Vue+SpringCloud博客的设计与实现---微服务基础版本组件1.0版本 博客采用Vue+SpringCloud前后分离的方式。博客采用了高可用Eureka(可以替换成其他微服务组件)以及高可用Zuul,使用以Es搜索引擎作为Zpkin的存储方式去跟踪定位博客的微服务的Api指标,微服务之间负载均衡使用Feign接口,整个项目均写了回退不会发生级联效应。 项目的亮点 所有互联网常用的代表间件均涉及使用,基本是一个完整的全项目,整个博客用的是微服务架构设计与分布式部署方式,整体代码均有注释,并且扩展方便,最终部署的方式需要采用Docker方式。 博客的功能介绍 用户的个人心:用户的登录与注册的Token验证,前后拦截器拦截Token。拼图,阿里云智能验证,动态加载JS,控制Token也可以在Zuul路由上操作。 用户安全心:SMTP邮箱注册邮箱,阿里云短信API注册手机以及其他个人安全信息和调用安全认证服务的接口,安全完成度最全。 用户文件头像上传心:博客所用到的所有的图片和用户的图片均用阿里云OSS文件服务器,外网url,也可以采用本地机器存储。 用户签到心:持续签到和累计签到奖励机制,以及会员导致经验值增益不同的机制,博客每日任务,排名特权,基本按照贴吧写的。 用户会员心:SVIP与VIP,定时任务/RabbitMQ延迟队列/登录验证三种判定会员截止时间到期用邮箱去提醒 用户支付心:我的钱包和支付宝支付以及打印我的账单,内网穿透获得异步通知作为结果判定标志,原始支付的普通会员,二维码支付的超级会员,账单分页,Csv定制,消费图,优惠券,基于RabbitMQ/Redis两种实现的延迟队列 用户博客心:发布,更新,删除,评论,点赞,收藏,转发,排行榜已经完成。博客心是博客的核心,分页和轮滑加载均实现,用Redisson来实现分布式锁控制文章 搜索引擎心:文章提示信息的增删改查,分页,高亮模糊排序查询 用户的消息心:websocket聊天与用户的所有个人消息 用户的个人空间:这个会涉及到个人博客空间与博客好友,博客云会控制上传和下载文件,会员会有速度特权,类似百度云,后续会完成上传。
1.项目代码功能经验证ok,确保稳定可靠运行。欢迎下载使用!在使用过程,如有问题或建议,请及时私信沟通。 2.主要针对各个计算机相关专业,包括计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师或企业员工使用。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、初期项目立项演示等用途。 4.当然也鼓励大家基于此进行二次开发。 5.期待你能在项目找到乐趣和灵感,也欢迎你的分享和反馈! 【资源说明】 项目简介 开发环境 * 操作系统:Windows 10 * 开发工具:Intellij IDEA * 数据库:MySQL 5.7.22 * Java SDK:Oracle JDK 1.8.0_131 部署环境 * 操作系统:Linux centos7 x64 * 虚拟化技术:VMware + Docker 项目管理工具 * 项目构建:Maven + Nexus * 代码管理:Git + GitLab * 镜像管理:Docker Registry 后台主要技术 * 核心框架:Spring Boot + Spring Cloud * 视图框架:Spring MVC * 页面引擎:Thymeleaf * ORM 框架:tk.mybatis 简化 MyBatis 开发 * 数据库连接池:Alibaba Druid * 数据库缓存:Redis Sentinel * 消息间件:RabbitMQ (后期考虑加入) * 接口文档引擎:Swagger2 RESTful 风格 API 文档生成 * 全文检索引擎:ElasticSearch (后期考虑加入) * 分布式链路追踪:ZipKin * 分布式文件系统:Alibaba FastDFS * 分布式服务监控:Spring Boot Admin * 分布式协调系统:Spring Cloud Eureka * 分布式配置心:Spring Cloud Config * 分布式日志系统:ELK(ElasticSearch + Logstash + Kibana)(后期考虑加入) * 反向代理负载均衡:Nginx * CDN服务器:基于Nginx搭建 前端主要技术 * 前端框架:Bootstrap + jQuery * 前端模板:AdminLTE 自动化运维 * 持续集成:GitLab * 持续交付:Jenkins (后期考虑加入) * 容器编排:Kubernetes 系统架构 ![image]( /image/system.png) 服务规划 # Cloud | 服务名称 | 服务端口 | 服务说明 | | --- | --- | --- | | itoken-eureka | 8761 | 服务注册与发现 | | itoken-config | 8888 | 分布式配置心 | | itoken-zipkin | 9411 | 分布式链路追踪 | | itoken-zuul | 8768 | 分布式路由网关 | | itoken-admin | 8084 | 分布式系统监控 | # service | 服务名称 | 服务端口 | 服务说明 | | --- | --- | --- | |itoken-service-admin|8501|管理员服务提供者| |itoken-service-redis|8502|数据缓存服务提供者| |itoken-service-sso|8503|单点登录服务提供者| |itoken-service-posts|8504|文章服务提供者| |itoken-service-upload|8505|文件上传服务提供者| |itoken-service-digiccy|8506|数字货币服务提供者| |itoken-service-collection|8507|数据采集服务提供者| # web | 服务名称 | 服务端口 | 服务说明 | | --- | --- | --- | |itoken-web-admin|8601|管理员服务消费者| |itoken-web-posts|8602|文章服务消费者| |itoken-web-backend|8603|后台服务聚合| |itoken-web-digiccy|8604|数字货币服务消费者| 页面效果 # 管理员服务页面 ![image]( /image/main.jpg) # 文章服务页面 ![image]( /image/posts.jpg) # 交易所页面 ![image]( /image/digiccy.jpg)
数据库系统期末项目基于Spring boot+Vue.js的图书销售系统源码+sql数据库+项目部署说明 【资源说明】 1、该资源内项目代码都是经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能。 系统功能描述 前台销售系统功能 图书展示和分类检索:图书分类展示、图书搜索、图书详细信息浏览 会员事务:会员注册、登陆、信息更改、注销 订单事务:购物车管理、订单填写和查询、订单取消 留言与反馈事务:用户售后评价、用户留言、功能和需求反馈 后台应用系统功能 图书管理和更新:图书库存更新、增加、信息修改、销售统计 订单管理:订单统计、查询、状态跟踪 普通管理业务:销售记录浏览和修改、订单状态处理、订单浏览 用户管理:用户查询统计、用户消费情况统计、用户删除,留言回复和反馈处理 数据库表 图书表bms_book 折扣表bms_book_discount 满减表bms_book_full_reduction 类别表bms_category 评价表bms_comment 回复表bms_comment_reply 回复内容表bms_comment_reply_content 评价内容表bms_comment_content 购物车oms_cart_item 订单表oms_order 权限表role 用户邮箱表ums_user_email 用户信息表ums_user_info 收货用户信息表ums_user_receive 用户统计表ums_user_statistics 用户表user 用户权限关系表user_role 开发环境 操作系统:Windows 10 Enterprise 开发工具:Eclipse 2020 Java SDK:Open JDK 1.8.261 数据库:MySQL 8.0、Redis、ElasticSearch 部署环境 操作系统:Linux Ubuntu Server 18.04 X64 项目管理工具 项目构建:Maven 代码管理:Git 镜像管理:Docker Registry 后台主要技术 核心框架:Spring Boot ORM框架:Mybatis 数据库连接池:HikariCP 数据库缓存:Redis 消息间件:RabbitMQ 全文检索引擎:ElasticSearch 分布式文件系统:Minio 反向代理+负载均衡:Nginx 前后端分离 前端框架:NodeJs + Vue + Axios 前端模板:Ant Design Vue + ElementUI
Novel-Cloud是基于小说精品屋-plus构建的Spring Cloud 微服务技术学习型小说项目,致力于原创文学阅读与写作,提供了爬虫工具用于开发过程测试数据的采集。采用了时下最新的Spring Boot 2.2.5.RELEASE 、Spring Cloud Hoxton.SR4、 MyBatis3DynamicSql、Sharding-Jdbc、RedisRabbitMq、ElasticSearch、Docker等流行技术,集成了Nacos注册心/配置心、Spring Cloud Gateway网关、Spring Boot Admin监控心、ELK分布式日志分析等基础服务。前端计划使用Vue开发。 Novel-Cloud安装步骤: 1、下载源码,如果是ZIP包,下载后需要解压。 2、开发环境配置,请确保开发机器上已安装如下软件环境。  Java开发工具包jdk1.8+  IDE(Eclipse或IntelliJ IDEA)  项目管理工具maven  微服务注册心/配置心nacos  分布式缓存服务Redis  搜索引擎服务ElasticSearch  ElasticSearch可视化客户端Kibana  消息间件RabbitMq  数据库服务Mysql 3、登陆nacos配置心导入下载源码的配置文件。 4、使用IDE导入下载的源码(这里以IntelliJ IDEA为例)。 5、修改通用配置的配置心地址和命名空间ID。 6、启动微服务网关。  修改网关服务的配置心地址和命名空间ID  修改网关配置文件注册心地址和命名空间ID  启动网关服务novel-gateway 7、启动监控服务。  修改监控服务的配置心地址和命名空间ID  修改监控微服务的注册心地址和命名空间ID以及登陆的用户名和密码  启动监控服务novel-monitor,启动方法和网关服务相同  访问监控服务,因为网关配置了监控服务的路由,所以可直接或通过网关来访问监控服务:http://<网关ip>:<网关端口号>/monitor 8、启动业务微服务,这里以小说微服务为例。  修改网关配置文件book-service.yml的注册心地址和命名空间ID,以及其他配置(数据库/redis/elasticsearch/mq等),方法同上  启动novel-service服务,方法同上  访问接口文档:http://<服务IP>:<服务端口号>/swagger-ui.html,  例如:http://127.0.0.1:620/swagger-ui.html 9、通过网关统一接口访问路径。 http://<网关IP>:<网关端口号>/api/<接口路径> 以小说小说分类列表查询接口为例:http://127.0.0.1:527/api/book/listBookCategory 10、访问用户心/作家心等需要认证的接口。  访问登陆接口获取JWT  设置JWT认证  访问需要认证的接口

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值