Dubbo+Solr+RabbitMQ实现数据同步功能

该博客详细介绍了如何使用Spring Boot搭建项目环境,集成Solr、Dubbo和RabbitMQ。首先,创建父工程并引入相关依赖,接着创建pojo、mapper、api和provider子模块,实现数据存储和远程调用。然后,通过RabbitMQ实现实时同步Solr,确保商品新增操作的高效性和异步性。最后,提供了完整的代码示例和配置文件,帮助开发者快速理解和应用。
摘要由CSDN通过智能技术生成
网页右边,向下滑有目录索引,可以根据标题跳转到你想看的内容
如果右边没有就找找左边
整个案例的源码(可作为日后开发脚手架):https://download.csdn.net/download/grd_java/21094886
Solr讲解:https://blog.csdn.net/grd_java/article/details/119476059
Dubbo讲解:https://blog.csdn.net/grd_java/article/details/119322297
RabbitMQ讲解:https://blog.csdn.net/grd_java/article/details/119696892

启动solr、RabbitMQ、Zookeeper
在这里插入图片描述

在这里插入图片描述

一、创建项目,搭建环境

1. 创建父工程,引入依赖

在这里插入图片描述

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.10.RELEASE</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <!--Spring boot不带web依赖,不会提供端口,因为一些-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
                <version>2.5.3</version>
            </dependency>
            <!--Spirng boot带web,会自动提供端口-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>2.5.3</version>
            </dependency>
            <!--thymeleaf 模板依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
                <version>2.5.3</version>
            </dependency>
            <!--spring boot data  封装了solrJ 的jar包-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-solr</artifactId>
                <version>2.1.10.RELEASE</version>
            </dependency>
            <!--amqp RabbitMQ-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-amqp</artifactId>
                <version>2.1.10.RELEASE</version>
            </dependency>
            <!--Dubbo整合-->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-spring-boot-starter</artifactId>
                <version>2.7.3</version>
            </dependency>
            <!--Zookeeper整合-->
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-recipes</artifactId>
                <version>4.2.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-framework</artifactId>
                <version>4.2.0</version>
            </dependency>
            <!--myBatis -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
            <!--mysql-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.19</version>
            </dependency>
            <!--apace commons工具-->
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.11.0</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
2. 创建pojo模块存放实体类,创建与solr和数据库对应的实体类(必须继承序列化接口)

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

3. 创建mapper模块,处理所有数据库相关操作
  1. 依赖,从父工程依赖中复制过来,然后引入自己的实体类子模块

在这里插入图片描述

  1. mapper接口
    在这里插入图片描述
  2. xml文件
    在这里插入图片描述
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yzpnb.mapper.ProductMapper">
    <insert id="insertProduct" parameterType="com.yzpnb.bean.Product">
        insert into t_product(name,price) value(#{name},#{price});
    </insert>
</mapper>
  1. 配置文件
    在这里插入图片描述
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.47.1:3306/dubbo_demo?serverTimezone=CST&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true #?后面参数表示时区,非常重要
    username: root
    password: 123456
# MyBatis
mybatis:
  # 搜索指定包别名
  type-handlers-package: com.yzpnb.bean
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath:mybatis/*Mapper.xml
4. 创建api模块,存放Dubbo远程调用接口
  1. 引入依赖(引入自己pojo和mapper子模块即可)
    在这里插入图片描述
  2. 远程调用接口
    在这里插入图片描述
5. 创建provider子模块,生产所有远程调用接口
  1. 依赖(需要api子模块,自动继承api中依赖)
    在这里插入图片描述
    <dependencies>
        <dependency>
            <groupId>com.yzpnb</groupId>
            <artifactId>api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--Spring boot不带web依赖,不会提供端口,因为一些-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--Dubbo整合-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <!--Zookeeper整合-->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
        </dependency>
    </dependencies>
  1. 配置文件
    在这里插入图片描述
dubbo:
  application:
    name: dubbo-provider # 在dubbo注册中心的名字
  registry:
    address: zookeeper://192.168.10.105:2181 # zookeeper地址,用zookeeper协议
  protocol:
    port: 20884 #dubbo端口,可以不写,和Dubbo注册中心取到联系
spring:
  profiles:
    active: mybatis # 加载其它配置文件,加载的是 application-*.yaml,我们只要指定*所代表的即可
  1. 启动类
    在这里插入图片描述
  2. 远程api接口实现类
    在这里插入图片描述

二、商品新增

1. 创建子模块product,用来处理所有和product相关的服务
  1. 依赖,需要调用远程api接口,其它就是必须的spring-web,dubbo,zookeeper
    在这里插入图片描述
  2. service
    在这里插入图片描述
  3. controller
    在这里插入图片描述
import com.yzpnb.bean.Product;
import com.yzpnb.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping("/product")
public class ProductController {
    @Autowired
    private ProductService productService;

	//http://localhost:8080/product/insertProduct/huawei/6999
    @GetMapping("insertProduct/{name}/{price}")
    public int findAllDept(@PathVariable("name") String name,@PathVariable("price") Double price){
        Product product = new Product();
        product.setPrice(price);
        product.setName(name);
        return productService.insertProduct(product);
    }
}

三、Solr同步

1. 创建子模块solr-pojo,存放solr需要使用的实体类
  1. 引入依赖
    在这里插入图片描述
  2. 创建实体类
    在这里插入图片描述
2. 创建子模块search,用于操作solr
  1. 引入依赖(amqp rabbitmq的包不需要引入)
    在这里插入图片描述
  2. 启动类
    在这里插入图片描述
  3. 配置文件
    在这里插入图片描述
  4. service
    在这里插入图片描述
import com.yzpnb.bean.search_pojo.SearchProduct;
import com.yzpnb.service.SearchService;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.stereotype.Service;

@Service
public class SearchServiceImpl implements SearchService {

    //相当于SolrJ的Solr客户端,这里Spirng data帮我们封装了
    @Autowired
    private SolrTemplate solrTemplate;

    /**
     * 插入数据到solr
     * @param searchProduct
     * @return
     */
    @Override
    public boolean insert(SearchProduct searchProduct) {
        //这里我们执行添加修改操作时,需要指定对哪个核心做操作,这里操作testcore核心
        UpdateResponse response = solrTemplate.saveBean("testcore", searchProduct);
        solrTemplate.commit("testcore");//提交也需要指定提交到哪个核心
        if(response.getStatus() == 0){
            return true;
        }
        return false;
    }
}
  1. 编写配置类,定义SolrTemplate的Bean实例,否则会报错,找不到SolrTemplate
    在这里插入图片描述
import org.apache.solr.client.solrj.SolrClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.solr.core.SolrTemplate;

@Configuration
public class SolrConfig {
    @Autowired
    SolrClient solrClient;

    @Bean
    public SolrTemplate getSolrTemplate(){
        return new SolrTemplate(solrClient);
    }
}
  1. 先编写一个controller测试一下业务是否正常
    在这里插入图片描述
import com.yzpnb.bean.search_pojo.SearchProduct;
import com.yzpnb.service.SearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/product-search")
public class SearchController {
    @Autowired
    private SearchService searchService;

    @GetMapping("insertSearchProduct/{name}/{price}")
    public boolean insert(@PathVariable("name") String name,@PathVariable("price") Double price){
        SearchProduct searchProduct = new SearchProduct();
        searchProduct.setName(name);
        searchProduct.setPrice(price);
        return searchService.insert(searchProduct);
    }
}
  1. 运行测试(测试完,就可以将controller删除了,他和mapper子模块一样,只是一个用来远程调用使用的接口)
    在这里插入图片描述
3. 同步solr
  1. api子模块中引入search子模块(方便我们远程调用)
    在这里插入图片描述
  2. 重写Provider 调用接口
    在这里插入图片描述
import com.yzpnb.bean.Product;
import com.yzpnb.bean.search_pojo.SearchProduct;
import com.yzpnb.dubbo.service.ProductDubboService;
import com.yzpnb.mapper.ProductMapper;
import com.yzpnb.service.SearchService;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

@Service
public class ProductDubboServiceImpl implements ProductDubboService {

    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private SearchService searchService;

    @Override
    public int insertProduct(Product product) {

        int i = productMapper.insertProduct(product);
        if(i == 1){
            SearchProduct searchProduct = new SearchProduct();
            BeanUtils.copyProperties(product,searchProduct);//把product的属性复制给searchProduct
            boolean b = searchService.insert(searchProduct);
            if(b == true){
                return 1;//同步插入成功
            }
        }
        //否则插入失败,
        //删除刚刚插入到数据库的数据,这里省略这些步骤,id我们也自增的,实际项目都是需要自己生成id,记录,这一步,通过记录的id,删除
        //为了简单直接返回0
        return 0;
    }
}
  1. 启动provider和product,测试
    在这里插入图片描述

四、通过RabbitMQ 实现异步同步solr

  1. 前面的代码有一个问题,solr的同步都写到了一起,这样做,每次存储,都会浪费同步的时间
  2. 通过RabbitMQ就可以异步完成这件事,数据存储到数据库,不用关心同步问题,让RabbitMQ帮忙干这件事即可
首先,因为RabbitMQ规定,如果发送消息是一个对象,那么必须序列化实体类对象

在这里插入图片描述

public static final long serialVersionUID=1l;
其次,因为Solr子模块search,我们刚刚删除了controller和启动类,需要相应更改
  1. 因为没有启动类,所以需要依赖其它模块的服务器进行加载,那么首先需要修改配置文件的名字,方便之后加载
    在这里插入图片描述
1. 创建子模块rabbitmq,存放RabbitMQ的所有发送操作(发送消息到队列)
  1. 依赖
    在这里插入图片描述
  2. 配置文件(因为这同样是一个不需要启动的模块,需要借助其它模块加载配置文件)
    在这里插入图片描述
  3. 配置类,配置队列实例Bean
    在这里插入图片描述
  4. 发送类,提供发送消息到队列的方法
    在这里插入图片描述
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Sender {

    @Autowired
    private AmqpTemplate amqpTemplate;

    public void send(Object obj){
        amqpTemplate.convertAndSend("MyQueue",obj);
        System.out.println("RabbitMQ-----------A obj send to MyQueue");
    }
}
2. 创建子模块receive,存放所有接收队列消息的操作
  1. 依赖
    在这里插入图片描述
  2. 配置文件
    在这里插入图片描述
  3. 启动类
    在这里插入图片描述
  4. 接收类
    在这里插入图片描述
import com.yzpnb.bean.search_pojo.SearchProduct;
import com.yzpnb.service.SearchService;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

@Component//启动项目,自动注入这个类
public class Receive {

    @Autowired
    private SearchService searchService;

    @RabbitListener(queues = "MyQueue")//标注此方法为接收MyQueue队列消息的方法
    public void solr(Object obj){
        System.out.println("RabbitMQ solr方法 收到 MyQueue的消息---------");

        Message msg = (Message) obj;
        ByteArrayInputStream bIS = null;
        ObjectInputStream oIS = null;
        try{
            bIS = new ByteArrayInputStream(msg.getBody());
            oIS = new ObjectInputStream(bIS);
            Object o = oIS.readObject();
            SearchProduct searchProduct = (SearchProduct) o;

            boolean b = searchService.insert(searchProduct);
            if(b == true){//同步成功结束代码执行
                return;
            }else{
                //同步失败,执行逻辑,数据库内容删除,这里省略
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                bIS.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                oIS.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}
  1. 重写provider的远程调用,同步不需要它来同步了
    在这里插入图片描述
运行测试
  1. 启动provider
  2. 启动receive
  3. 启动product
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

殷丿grd_志鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值