SpringBoot+SpringCloud+ElasticSearch+RabbitMQ整合Demo

需求一:

  1. 基於spring boot搭建商家服務,商品服務

  2. 搭建Eureka server 註冊中心

  3. 用戶服務

    1. 根據ID查詢商家信息
    2. 添加商品信息(調用商品服務)
  4. 商品服務

    1. 添加商品信息到MySQL

      {
      	"title":"榮耀X10 5G雙模 麒麟820 4300mAh續航 4000萬高感光影像系統 6.63英寸升降全面屏 全網通6GB+128GB 競速藍",
      	"price":2199.00,
      	"saleNum":6521,
      	"categoryName":"手機",
      	"brandName":"華爲"
      }
      
  5. 使用Hystix 對添加商品進行降級處理

搭建環境

  1. 數據庫

在這裏插入圖片描述
鏈接:https://pan.baidu.com/s/1v0y5Yc6RiPKtcPsto6F9Ew
提取碼:18v8

  1. 創建springcloud的父工程

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.itheima</groupId>
        <artifactId>fuxi_parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <packaging>pom</packaging>
    
        <!--spring boot 環境 -->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.0.RELEASE</version>
            <relativePath/>
        </parent>
    
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
            <!--spring cloud 版本-->
            <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
        </properties>
    
        <!--引入Spring Cloud 依賴-->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    </project>
    
  2. 創建公用的模塊,封裝JavaBean

在這裏插入圖片描述

注意: 如果需要使用流來傳輸對象,需要實現IO包的序列化接口。一般可以默認加上。

搭建註冊中心

步驟:

① 創建 eureka-server 模塊

   <!-- 繼承父工程 -->
	<parent>
        <artifactId>spring-cloud-parent</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

② 引入 SpringCloud 和 euraka-server 相關依賴

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        
    </dependencies>

③ 完成 Eureka Server 相關配置

server:
  port: 8761

# eureka 配置
# eureka 一共有4部分 配置
# 1. dashboard:eureka的web控制檯配置
# 2. server:eureka的服務端配置
# 3. client:eureka的客戶端配置
# 4. instance:eureka的實例配置


eureka:
  instance:
    hostname: localhost # 主機名
  client:
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka # eureka服務端地址,將來客戶端使用該地址和eureka進行通信
    register-with-eureka: false # 是否將自己的路徑 註冊到eureka上。eureka server 不需要的,eureka provider client 需要
    fetch-registry: false # 是否需要從eureka中抓取路徑。eureka server 不需要的,eureka consumer client 需要
  server:
    enable-self-preservation: false # 關閉自我保護機制
    eviction-interval-timer-in-ms: 3000 # 檢查服務的時間間隔

④ 啓動該模塊

@SpringBootApplication
// 啓用EurekaServer
@EnableEurekaServer
public class EurekaApp {

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

    }
}

搭建商家服務

  1. 創建fuxi_seller模塊

  2. 基於spring boot搭建SSM模塊

    1. 添加依賴,配置pom.xml

          <dependencies>
              <dependency>
                  <groupId>com.itheima</groupId>
                  <artifactId>fuxi_pojo</artifactId>
                  <version>1.0-SNAPSHOT</version>
              </dependency>
      
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
              <dependency>
                  <groupId>org.mybatis.spring.boot</groupId>
                  <artifactId>mybatis-spring-boot-starter</artifactId>
                  <version>2.1.0</version>
              </dependency>
              <dependency>
                  <groupId>mysql</groupId>
                  <artifactId>mysql-connector-java</artifactId>
              </dependency>
              
              <!-- eureka-client -->
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
              </dependency>
          </dependencies>
      
    2. 編寫啓動類

      @SpringBootApplication
      @EnableEurekaClient
      public class SellerApp {
      
          public static void main(String[] args) {
              SpringApplication.run(SellerApp.class,args);
          }
      }
      
      
    3. 編寫配置文件

      server:
        port: 9001
      
      eureka:
        instance:
          hostname: localhost # 主機名
        client:
          service-url:
            defaultZone: http://localhost:8761/eureka # eureka服務端地址,將來客戶端使用該地址和eureka進行通信
      spring:
        application:
          name: seller # 設置當前應用的名稱。將來會在eureka中Application顯示。將來需要使用該名稱來獲取路徑
      
        datasource:
          url: jdbc:mysql:///db_user?serverTimezone=Asia/Shanghai
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
      

根據ID查詢商家信息

  1. dao

    @Mapper
    public interface SellerMapper {
    
        @Select("select * from seller where id =#{id}")
        public Seller findById(Integer id);
    
    }
    
    
  2. service

    @Service
    public class SellerService {
    
        @Autowired
        SellerMapper sellerMapper;
    
        public Seller findSellerById(Integer id){
            return sellerMapper.findById(id);
        }
    }
    
  3. controller

    
    @RestController
    @RequestMapping("/seller")
    public class SellerController {
    
    
        @Autowired
        SellerService sellerService;
    
        @GetMapping("/{id}")
        public Seller findSellerById(@PathVariable("id") Integer id){
    
            return sellerService.findSellerById(id);
        }
    }
    
  4. 測試

搭建商品服務

  1. 創建fuxi_goods模塊

  2. 基於spring boot搭建SSM模塊

    1. 添加依賴,配置pom.xml

          <dependencies>
              <dependency>
                  <groupId>com.itheima</groupId>
                  <artifactId>fuxi_pojo</artifactId>
                  <version>1.0-SNAPSHOT</version>
              </dependency>
      
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
              <dependency>
                  <groupId>org.mybatis.spring.boot</groupId>
                  <artifactId>mybatis-spring-boot-starter</artifactId>
                  <version>2.1.0</version>
              </dependency>
              <dependency>
                  <groupId>mysql</groupId>
                  <artifactId>mysql-connector-java</artifactId>
              </dependency>
              
              <!-- eureka-client -->
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
              </dependency>
          </dependencies>
      
    2. 編寫啓動類

      @SpringBootApplication
      @EnableEurekaClient
      public class GoodsApp {
      
          public static void main(String[] args) {
              SpringApplication.run(GoodsApp.class,args);
          }
      
      }
      
      
    3. 編寫配置文件

      server:
        port: 9002
      
      eureka:
        instance:
          hostname: localhost # 主機名
        client:
          service-url:
            defaultZone: http://localhost:8761/eureka # eureka服務端地址,將來客戶端使用該地址和eureka進行通信
      spring:
        application:
          name: goods # 設置當前應用的名稱。將來會在eureka中Application顯示。將來需要使用該名稱來獲取路徑
      
        datasource:
          url: jdbc:mysql:///db_goods?serverTimezone=Asia/Shanghai
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver
      

提供方-商品添加

  1. dao

    @Mapper
    public interface GoodsMapper {
    
        @Insert(" INSERT  INTO `goods`(`title`,`price`,`stock`,`saleNum`,`createTime`,`categoryName`,`brandName`,`spec`,`seller`,`company`) \n" +
                "VALUES (\n" +
                "#{title},\n" +
                "#{price},\n" +
                "NULL,\n" +
                "#{saleNum},\n" +
                "#{createTime},\n" +
                "#{categoryName},\n" +
                "#{brandName},\n" +
                "#{specStr},\n" +
                "#{seller},\n" +
                "#{company}\n" +
                ") ")
        public void saveGoods(Goods goods);
    }
    
  2. service

    @Service
    public class GoodsService {
    
        @Autowired
        GoodsMapper goodsMapper;
    
        public void saveGoods(Goods goods){
            goodsMapper.saveGoods(goods);
        }
    }
    
    
  3. controller

    
    @RestController
    @RequestMapping("/goods")
    public class GoodsController {
    
        @Autowired
        GoodsService goodsService;
    
        @PostMapping("/save")
        public Reslut saveGoods(@RequestBody Goods goods){
            try{
                goodsService.saveGoods(goods);
                return new Reslut(true,"商品添加成功!");
            }catch (Exception e){
                e.printStackTrace();
                return new Reslut(false,"系統錯誤,添加失敗!");
            }
    
        }
    }
    
    
  4. 測試

    {
    	"title":"榮耀X10 5G雙模 麒麟820 4300mAh續航 4000萬高感光影像系統 6.63英寸升降全面屏 全網通6GB+128GB 競速藍",
    	"price":2199.00,
    	"saleNum":6521,
    	"categoryName":"手機",
    	"brandName":"華爲"
    }
    

調用方-商品添加

  1. 添加feign依賴,開啓開關

            <!--feign-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
    
  2. 啓動feign

    @SpringBootApplication
    @EnableEurekaClient
    @EnableFeignClients //開啓Feign的功能
    public class SellerApp {
    
        public static void main(String[] args) {
            SpringApplication.run(SellerApp.class,args);
        }
    }
    
  3. 配置rest Template對象

        @LoadBalanced
        @Bean
        public RestTemplate restTemplate(){
            return new RestTemplate();
        }
    
  4. 編寫Feign客戶端,配置

    @FeignClient(value = "goods")
    public interface GoodsFeign {
    
        @PostMapping("/goods/save")
        public Reslut saveGoods(@RequestBody Goods goods);
    }
    
    
  5. 再controller中,調用feign客戶端

        @Autowired
        GoodsFeign goodsFeign;
    
        @PostMapping("/saveGoods/{sellerId}")
        public Reslut saveGoods(@PathVariable("sellerId") Integer sellerId,@RequestBody Goods goods){
    
            Seller seller = sellerService.findSellerById(sellerId);
    
            goods.setSeller(seller.getSeller());
            goods.setCompany(seller.getCompany());
    
            goods.setCreateTime(new Date());
            goods.setSpecStr("{\"機身內存\":\"16G\",\"網絡\":\"聯通3G\"}");
    
            Reslut reslut = goodsFeign.saveGoods(goods);
            
            return reslut;
    
        }
    
  6. 測試

    {
    	"title":"榮耀X10 5G雙模 麒麟820 4300mAh續航 4000萬高感光影像系統 6.63英寸升降全面屏 全網通6GB+128GB 競速藍",
    	"price":2199.00,
    	"saleNum":6521,
    	"categoryName":"手機",
    	"brandName":"華爲"
    }
    
  7. 遇到一個啓動異常,缺少 spring-cloud-starter-netflix-ribbon 修復

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            </dependency>
    

Hystix 降級處理-服務提供方

操作步驟:

  1. 在服務提供方,引入 hystrix 依賴

            <!-- hystrix -->
             <dependency>
                 <groupId>org.springframework.cloud</groupId>
                 <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
             </dependency>
    
  2. 在啓動類上開啓Hystrix功能:@EnableCircuitBreaker

    /**
     * 啓動類
     */
    
    @EnableEurekaClient 
    @SpringBootApplication
    @EnableCircuitBreaker // 開啓Hystrix功能
    public class GoodsApp {
    
  3. 定義降級方法

        /**
         * 定義降級方法:
         *  1. 方法的返回值需要和原方法一樣
         *  2. 方法的參數需要和原方法一樣
         *  3. 就是隻有方法名不同
         */
        public Reslut saveGoods_fallback(@RequestBody Goods goods){
            return new Reslut(false,"服務方降級!");
        }
    
  4. 使用 @HystrixCommand 註解配置降級方法

        @PostMapping("/save")
        @HystrixCommand(fallbackMethod = "saveGoods_fallback")
        public Reslut saveGoods(@RequestBody Goods goods){
    
           if(goods.getPrice()<100){
                throw new RuntimeException("太便宜了,不能添加!");
            }
            
            goodsService.saveGoods(goods);
            return new Reslut(true,"商品添加成功!");
    
        }
    
        public Reslut saveGoods_fallback(@RequestBody Goods goods){
            return new Reslut(false,"服務方降級!");
        }
    

Hystix 降級處理-調用方

操作步驟:

  1. feign 組件已經集成了 hystrix 組件。
    在這裏插入圖片描述

  2. 在application.yml中配置開啓 feign.hystrix.enabled = true

    # 開啓feign對hystrix的支持
    feign:
      hystrix:
        enabled: true
    
  3. 定義feign 調用接口實現類,複寫方法,即 降級方法

    /**
     * Feign 客戶端的降級處理類
     * 1. 定義類 實現 Feign 客戶端接口
     * 2. 使用@Component註解將該類的Bean加入SpringIOC容器
     */
    @Component
    public class GoodsFeignClientFallback implements GoodsFeignClient {
        @Override
        public Goods findGoodsById(int id) {
            Goods goods = new Goods();
            goods.setTitle("又被降級了~~~");
            return goods;
        }
    }
    
    
  4. 在 @FeignClient 註解中使用 fallback 屬性設置降級處理類。

    @FeignClient(value = "HYSTRIX-PROVIDER",fallback = GoodsFeignClientFallback.class)
    public interface GoodsFeignClient {
    
    
        @GetMapping("/goods/findOne/{id}")
        public Goods findGoodsById(@PathVariable("id") int id);
    
    }
    

需求二:

  1. 基於spring boot搭建商品搜索服務
  2. 搜索服務
    1. 向ES添加商品信息
    2. 商品關鍵字搜索(儘量符合用戶的使用,參考京東)
  3. 商品服務發送消息,搜索服務接收消息完成MYSQL添加商品後自動同步到ES

在這裏插入圖片描述

商品服務發送消息

  1. 導入amqp的起步依賴

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-amqp</artifactId>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.47</version>
            </dependency>
    
  2. 在application.yml配置mq的連接信息

      rabbitmq:
        host: 192.168.200.129
        port: 5672
        virtual-host: /itcast
        username: heima
        password: heima
    
  3. 配置RabbitMQConfig類

    1. 創建queue
    2. 創建Exchange
    3. 綁定
    @Configuration
    public class RabbitMQConfig {
    
        //交換機名稱
        public static final String ITEM_TOPIC_EXCHANGE = "goods_topic_exchange";
        //隊列名稱
        public static final String ITEM_QUEUE = "goods_queue";
    
        //聲明交換機
        @Bean("itemTopicExchange")
        public Exchange topicExchange(){
            return ExchangeBuilder.topicExchange(ITEM_TOPIC_EXCHANGE).durable(true).build();
        }
    
        //聲明隊列
        @Bean("itemQueue")
        public Queue itemQueue(){
            return QueueBuilder.durable(ITEM_QUEUE).build();
        }
    
        //綁定隊列和交換機
        @Bean
        public Binding itemQueueExchange(@Qualifier("itemQueue") Queue queue,
                                         @Qualifier("itemTopicExchange") Exchange exchange){
            return BindingBuilder.bind(queue).to(exchange).with("goods.#").noargs();
        }
    
    }
    
  4. GoodsService 注入RabbitTempalte,發送消息

    @Autowired
    RabbitTemplate rabbitTemplate;

    public void saveGoods(Goods goods){
        //將goods信息存入mysql
        goodsMapper.saveGoods(goods);

        //準備消息內容
        String specStr = goods.getSpecStr();

        Map spec = JSON.parseObject(specStr,Map.class);
        goods.setSpec(spec);
        
        String data = JSON.toJSONString(goods);
        System.out.println(data);

        //發送消息
        rabbitTemplate.convertAndSend(RabbitMQConfig.ITEM_TOPIC_EXCHANGE,"goods.save",data);
    }

搭建搜索服務

  1. 添加依賴(web,amqp,es相關依賴)

     <dependencies>
            <dependency>
                <groupId>com.itheima</groupId>
                <artifactId>fuxi_pojo</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!-- eureka-client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
            <!-- hystrix -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-amqp</artifactId>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.47</version>
            </dependency>
    
            <!--引入es的座標-->
            <dependency>
                <groupId>org.elasticsearch.client</groupId>
                <artifactId>elasticsearch-rest-high-level-client</artifactId>
                <version>7.4.0</version>
            </dependency>
            <dependency>
                <groupId>org.elasticsearch.client</groupId>
                <artifactId>elasticsearch-rest-client</artifactId>
                <version>7.4.0</version>
            </dependency>
            <dependency>
                <groupId>org.elasticsearch</groupId>
                <artifactId>elasticsearch</artifactId>
                <version>7.4.0</version>
            </dependency>
    
        </dependencies>
    
  2. 啓動類

    @SpringBootApplication
    @EnableEurekaClient
    public class SearchApp {
        public static void main(String[] args) {
            SpringApplication.run(SearchApp.class,args);
        }
    }
    
    
  3. 配置文件

application.yml

server:
  port: 9003

eureka:
  instance:
    hostname: localhost # 主機名
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka # eureka服務端地址,將來客戶端使用該地址和eureka進行通信
spring:
  application:
    name: search # 設置當前應用的名稱。將來會在eureka中Application顯示。將來需要使用該名稱來獲取路徑

  rabbitmq:
    host: 192.168.200.129
    port: 5672
    virtual-host: /itcast
    username: heima
    password: heima

elasticsearch:
  host: 192.168.200.129
  port: 9200

搜索服務接收消息

  1. 複製消息生產者的配置類

在這裏插入圖片描述

  1. 編寫消息的監聽類

    @Component
    public class GoodsListener {
        
        @RabbitListener(queues = RabbitMQConfig.ITEM_QUEUE)
        public void goodsListener(String jsonGoods){
    
            System.out.println("接收到了消息:"+jsonGoods);
            
        }
        
    }
    
  2. 測試消息

在這裏插入圖片描述

搜索服務添加ES文檔

  1. 搭建ES環境,創建索引和映射

    
    PUT fuxi_goods
    {
    	"mappings": {
    		"properties": {
    			"title": {
    				"type": "text",
    				"analyzer": "ik_smart"
    			},
    			"price": { 
    				"type": "double"
    			},
    			"createTime": {
    				"type": "date"
    			},
    			"categoryName": {	
    				"type": "keyword"
    			},
    			"brandName": {	
    				"type": "keyword"
    			},
    	
    			"spec": {		
    				"type": "object"
    			},
    			"saleNum": {	
    				"type": "integer"
    			},
    			
    			"stock": {	
    				"type": "integer"
    			},
    			"seller": {	
    				"type": "keyword"
    			},
    			"company": {	
    				"type": "keyword"
    			}
    		}
    	}
    }
    
  2. 創建ES 高級客戶端配置類

    @Configuration
    @ConfigurationProperties(prefix="elasticsearch")
    public class ElasticSearchConfig {
    
        private String host;
    
        private int port;
        public String getHost() {
            return host;
        }
    
        public void setHost(String host) {
            this.host = host;
        }
    
        public int getPort() {
            return port;
        }
    
        public void setPort(int port) {
            this.port = port;
        }
        @Bean
        public RestHighLevelClient client(){
            return new RestHighLevelClient(RestClient.builder(
                    new HttpHost(host,port,"http")
            ));
        }
    }
    
  3. 編寫service保存文檔

    @Service
    public class GoodsESService {
    
    
        @Autowired
        RestHighLevelClient client;
    
        //添加ES文檔
        public void saveGoods(String jsonGoods) throws IOException {
    
            Goods goods = JSON.parseObject(jsonGoods,Goods.class);
    
            IndexRequest request=new IndexRequest("itcast").id(goods.getId()+"").source(jsonGoods, XContentType.JSON);
            IndexResponse response = client.index(request, RequestOptions.DEFAULT);
    
        }
    }
    
    
  4. 在listener進行調用

    @Component
    public class GoodsListener {
    
        @Autowired
        GoodsESService service;
    
        @RabbitListener(queues = RabbitMQConfig.ITEM_QUEUE)
        public void goodsListener(String jsonGoods){
    
            System.out.println("接收到了消息:"+jsonGoods);
    
            //添加文檔
            try {
                service.saveGoods(jsonGoods);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
    }
    
  5. 測試

    問題: 消息內容中goods沒有id,ES文檔操作變成了覆蓋.

    解決: 消息中應該將goods id添加到信息中,goods id是由mysql自增長,所以在mapper中insert中配置返回主鍵。

    GoodsMapper

        @Options(keyProperty = "id",useGeneratedKeys = true)
        public void saveGoods(Goods goods);
    

搜索服務商品查詢

  1. 需求分析

    1. 沒有輸入查詢關鍵字 keyword ,不進行查詢
    2. keyword ,使用query String進行查詢,從title,brand,category進行查詢,操作OR
    3. 添加brand條件 ,filter
    4. 添加價格 最大值最小值 price=1000-2000
  2. 設計

    參數 Map

    返回 List

  3. 編寫service,商品查詢

        /*
        1. 沒有輸入查詢關鍵字 keyword ,不進行查詢
        2. keyword ,使用query String進行查詢,從title,brand,category進行查詢,操作OR
        3. 添加brand條件   ,filter
        4. 添加價格   最大值最小值   price=1000-2000
         */
    
        //商品查詢
        public List<Goods> findGoods(Map<String,String> param) throws IOException {
    
    
            SearchRequest searchRequest = new SearchRequest("fuxi_goods");
    
            SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
    
    
            //1.構建boolQuery
            BoolQueryBuilder query = QueryBuilders.boolQuery();
    
            //沒有輸入查詢關鍵字 keyword ,不進行查詢
            if(param==null && StringUtils.isBlank(param.get("keyword"))){
                return new ArrayList<>();
            }
            //keyword ,使用query String進行查詢,從title,brand,category進行查詢,操作OR
            QueryStringQueryBuilder qsquery = QueryBuilders.queryStringQuery(param.get("keyword"))
                    .field("title").field("categoryName").field("brandName")
                    .defaultOperator(Operator.OR);
            query.must(qsquery);
    
    
            //添加brand條件   ,filter
            if(StringUtils.isNotBlank(param.get("brand"))) {
                QueryBuilder termQuery = QueryBuilders.termQuery("brandName", param.get("brand"));
                query.filter(termQuery);
            }
    
            //查詢價格在:2000-3000
            if(StringUtils.isNotBlank(param.get("price"))) {
    
                String[] ps = param.get("price").split("-");
    
                QueryBuilder rangeQuery = QueryBuilders.rangeQuery("price");
                ((RangeQueryBuilder) rangeQuery).gte(ps[0]);
                ((RangeQueryBuilder) rangeQuery).lte(ps[1]);
                query.filter(rangeQuery);
            }
    
    
            //3.使用boolQuery連接
    
            sourceBulider.query(query);
    
            searchRequest.source(sourceBulider);
    
    
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
    
            SearchHits searchHits = searchResponse.getHits();
            //獲取記錄數
            long value = searchHits.getTotalHits().value;
            System.out.println("總記錄數:"+value);
    
            List<Goods> goodsList = new ArrayList<>();
            SearchHit[] hits = searchHits.getHits();
            for (SearchHit hit : hits) {
                String sourceAsString = hit.getSourceAsString();
    
                //轉爲java
                Goods goods = JSON.parseObject(sourceAsString, Goods.class);
    
                goodsList.add(goods);
            }
            return goodsList;
    
        }
    
  4. controller

    
    @RestController
    public class ESGoodsController {
    
        @Autowired
        GoodsESService goodsESService;
    
        @PostMapping("/search")
        public List<Goods> findGoods(@RequestBody Map<String,String> param){
            List<Goods> list = null;
            try {
                list = goodsESService.findGoods(param);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return list;
        }
    
    }
    
    
  5. 測試

在商家服務中調用商品搜索

  1. 編寫feign客戶端
  2. 遠程調用搜索服務

作爲作業

需求三:

  1. 搭建網關gateway,配置路由
  2. 搭建註冊中心 config server
  3. 將配置信息上傳上gitee
  4. 將商家服務,商品服務,搜索服務的信息配置到配置中心
  5. 配置bus一鍵刷新
  6. 使用docker部署商家服務,商品服務,搜索服務

網關的配置

操作步驟:

  1. 搭建網關模塊,導入資料中的初始化代碼

    其實就是創建一個最基本的spring cloud模塊。

  2. 引入依賴:starter-gateway

        <dependencies>
            <!--引入gateway 網關-->
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
    
            <!-- eureka-client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
        </dependencies>
    
  3. 編寫啓動類,無特殊操作

    @SpringBootApplication
    @EnableEurekaClient
    public class GatewayApp {
    
        public static void main(String[] args) {
            SpringApplication.run(GatewayApp.class,args);
        }
    }
    
    
  4. 編寫配置文件

    server:
      port: 80
    
    spring:
      application:
        name: fuxi-gateway-server
    
      cloud:
        # 網關配置
        gateway:
          # 路由配置:轉發規則
          routes: #集合。
          # id: 唯一標識。默認是一個UUID
          # uri: 轉發路徑
          # predicates: 條件,用於請求網關路徑的匹配規則
    
          - id: gateway-seller
            uri: lb://seller
            predicates:
            - Path=/seller/**
            
          - id: gateway-goods
            uri: lb://goods
            predicates:
            - Path=/goods/**
              
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka
    
  5. 測試

配置中心服務

搭建配置中心服務

  1. 準備環境,創建git倉庫

在這裏插入圖片描述

  1. 在本地克隆git倉庫,管理配置文件

    應該配置在註冊中心的信息,除了註冊中心意外的信息,都可以通過配置中心進行管理。

在這裏插入圖片描述
3. 搭建配置中心

  1. 添加依賴

        <dependencies>
    
            <!-- config-server -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-config-server</artifactId>
            </dependency>
    
            <!-- eureka-client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
        </dependencies>
    
  2. 啓動類

    @SpringBootApplication
    @EnableEurekaClient
    @EnableConfigServer // 啓用config server功能
    public class ConfigServerApp {
    
        public static void main(String[] args) {
            SpringApplication.run(ConfigServerApp.class,args);
        }
    }
    
    
  3. 配置文件

    server:
      port: 9527
    
    spring:
      application:
        name: config-server
      # spring cloud config
      cloud:
        config:
          server:
            # git 的 遠程倉庫地址
            git:
              uri: https://gitee.com/easyitcast/fuxi_config.git
          label: master # 分支配置
    
    
    
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka
    
  4. 測試

    http://localhost:9527/master/seller-dev.yml

配置中心客戶端

  1. 在客戶端應用 fuxi_seller添加依賴

            <!--config client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
    
  2. 在客戶端模塊中,添加配置文件 bootstrap.yml

    # 配置config-server地址
    # 配置獲得配置文件的名稱等信息
    spring:
      cloud:
        config:
          # 配置config-server地址
          # uri: http://localhost:9527
          # 配置獲得配置文件的名稱等信息
          name: seller # 文件名
          profile: dev # profile指定,  seller-dev.yml
          label: master # 分支
          discovery:
                  enabled: true
                  service-id: config-server
    
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka
    

BUS全局刷新

熱部署,fuxi_seller配置文件修改後無需重啓。

config client刷新操作步驟:

  1. 在 config 客戶端引入 actuator 依賴

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
    
  2. 獲取配置信息類上,添加 @RefreshScope 註解

    @RestController
    @RequestMapping("/seller")
    @RefreshScope // 開啓刷新功能
    public class SellerController {
    
  3. 添加配置 bootstrap.yml
    management.endpoints.web.exposure.include: refresh

    management:
      endpoints:
        web:
          exposure:
            include: '*'     # 暴漏的endpoint,*表示所有
    
  4. 使用curl工具發送post請求
    curl -X POST http://localhost:9001/actuator/refresh

通過BUS進行統一部署

  1. 分別在 fuxi_config_server 和 fuxi_seller中引入 bus依賴:bus-amqp

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>  
    
    		<!-- bus -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-bus-amqp</artifactId>
            </dependency>
    
  2. 分別在 config-server 和 config-client中配置 RabbitMQ(3個模塊都配置)

    bootstrap.yml和config-server的application.yml

      #配置rabbitmq信息
      rabbitmq:
        host: 192.168.200.129
        port: 5672
        username: guest
        password: guest
        virtual-host: /
    

    注意位置:是spring節點的屬性

  3. 在config-server中設置暴露監控斷點:bus-refresh

    是通過actuator來實現,添加對actuator的依賴

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
    

    暴漏endpoint的配置

    # 暴露bus的刷新端點
    management:
      endpoints:
        web:
          exposure:
            include: 'bus-refresh'
    
  4. 啓動測試

    訪問的是config-server的刷新節點:

    curl -X POST http://localhost:9527/actuator/bus-refresh

項目部署上線

  1. 項目打包

    springboot項目打jar包,添加打包插件。

    需要打包的工程中的添加

        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    1. 執行maven打包命令 package

    2. 從target中,複製打包好的jar,然後進行運行

      java -jar fuxi_seller-1.0-SNAPSHOT.jar

      問題:

      打包失敗,找不到pojo工程。

      解決方法: clean,並install應用。

  2. jar包部署

  3. docker容器部署

    springboot應用,要連接docker中運行的mysql容器,那麼數據源的配置應該使用 宿主機的IP和映射的端口。

在這裏插入圖片描述

  1. dockfile製作鏡像

    1. 修改數據源信息,並打包應用。

    2. 編寫dockerfile文件

      springboot_dockerfile

      FROM java:8
      MAINTAINER itheima<[email protected]>
      
      ADD fuxi_seller-1.0-SNAPSHOT.jar app.jar
      CMD java -jar app.jar
      

在這裏插入圖片描述

  3. 將打包好的jar和springboot_dockerfile上傳到服務器上

     在虛擬機中創建目錄

     ```shell
     cd ~
     
     mkdir apps
     
     cd apps
     ```

     CRT中打開上傳fstp.alt+p

     ```shell
     #在windows下,進入有jar和dockfile文件的目錄(不能帶中文)
     lcd C:\Users\admin\Desktop\apps
     
     #進服務器,進入上面新建的apps目錄中
     cd apps
     
     #上傳文件
     put fuxi_seller-1.0-SNAPSHOT.jar
     put springboot_dockerfile       
     
     ```

  4. 根據上傳的文件創建docker鏡像

     ```shell
     docker build -f ./springboot_dockerfile -t itheima_app:1 .
     ```

在這裏插入圖片描述

  5. 根據鏡像啓動容器

     ```sh
     docker run -id --name=c_springboot -p 9001:9001 itheima_app:1
     ```

     

  6. 測試

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章