MQ消息丟失和消息重複的解決方案和實戰

場景

假設支付寶轉賬1000元到餘額寶, 通過RabbitMQ對轉賬過程進行解耦,

支付寶將轉賬的消息投遞到RabbitMQ, 餘額寶通過監聽RibbitMQ的消息隊列獲得消息, 然後通過應答隊列告訴支付寶消息已經消費

遇到的問題

1. 當餘額寶獲取到消息之後, 可能轉賬失敗, 消息隊列不會關心餘額寶是否操作成功, 這就是消息丟失的問題

2. 如果餘額寶成功轉賬, 但響應隊列遲遲沒有將消費成功的消息告訴支付寶, 導致支付寶重複發送消息, 這就是消息重複發送的問題.

解決方案

1. 第一種是引入ZK, 順序消費

2. 本地消息表

在支付寶端和餘額寶端同時建立消息表

1. 當在支付寶端扣款成功的同時, 在消息表中建立一條記錄, 狀態標識爲unconfirm, 將消息投遞到消息隊列

2. 餘額寶從消息隊列中獲取消息後, 在餘額寶中扣款成功後, 同時在消息表中建立一條消息, 狀態標識爲confirmed.

3. 餘額寶將響應消息投遞到響應隊列, 支付寶獲得響應後, 查詢餘額寶的消息表, 如果其中沒有消費記錄, 則插入新的消息。如果查詢有消費的消息, 就停止插入, 並返回已經消費的消息。這樣可以避免消息重複消費的問題。

4. 支付寶端會有一個定時任務, 相隔一段時間就從消息表中將unconfirm的消息拉取並重新發送, 這樣可以避免消息丟失的問題

代碼

數據庫腳本

DROP DATABASE IF EXISTS `rabbit_taobao_consumer`;
CREATE DATABASE IF NOT EXISTS `rabbit_taobao_consumer` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
USE `rabbit_taobao_consumer`;



DROP TABLE IF EXISTS `tb_account`;
CREATE TABLE IF NOT EXISTS `tb_account` (
  `user_id` varchar(10) NOT NULL,
  `amount` int(11) NOT NULL,
  `update_time` datetime NOT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


INSERT INTO `tb_account` (`user_id`, `amount`, `update_time`) VALUES
	('SAM0000001', 0, '2019-09-22 14:30:49'),
	('SAM0000002', 0, '2019-09-22 14:02:59'),
	('SAM0000003', 0, '2019-09-22 14:03:09');

DROP TABLE IF EXISTS `tb_message`;
CREATE TABLE IF NOT EXISTS `tb_message` (
  `message_id` varchar(100) NOT NULL,
  `user_id` varchar(10) NOT NULL,
  `amount` int(11) NOT NULL,
  `state` varchar(10) NOT NULL,
  `update_time` datetime NOT NULL,
  PRIMARY KEY (`message_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


DROP DATABASE IF EXISTS `rabbit_taobao_provider`;
CREATE DATABASE IF NOT EXISTS `rabbit_taobao_provider` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
USE `rabbit_taobao_provider`;


DROP TABLE IF EXISTS `tb_account`;
CREATE TABLE IF NOT EXISTS `tb_account` (
  `user_id` varchar(10) NOT NULL,
  `amount` int(11) NOT NULL,
  `update_time` datetime NOT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


INSERT INTO `tb_account` (`user_id`, `amount`, `update_time`) VALUES
	('SAM0000001', 64000, '2019-09-22 14:30:48'),
	('SAM0000002', 80000, '2019-09-21 18:10:44'),
	('SAM0000003', 70000, '2019-09-21 18:10:57');


DROP TABLE IF EXISTS `tb_message`;
CREATE TABLE IF NOT EXISTS `tb_message` (
  `message_id` varchar(100) NOT NULL,
  `user_id` varchar(10) NOT NULL,
  `amount` int(11) NOT NULL,
  `state` varchar(10) NOT NULL,
  `update_time` datetime NOT NULL,
  PRIMARY KEY (`message_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

建立alipay-server工程, 下面是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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.1.8.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>com.teddy</groupId>
   <artifactId>alipay-server</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>alipay-server</name>
   <description>Demo project for Spring Boot</description>

   <properties>
      <java.version>1.8</java.version>
   </properties>

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

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

      <dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>druid-spring-boot-starter</artifactId>
         <version>1.1.10</version>
      </dependency>
      <dependency>
         <groupId>tk.mybatis</groupId>
         <artifactId>mapper-spring-boot-starter</artifactId>
         <version>2.0.2</version>
      </dependency>
      <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <scope>runtime</scope>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>org.springframework.amqp</groupId>
         <artifactId>spring-rabbit-test</artifactId>
         <scope>test</scope>
      </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.28</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>

</project>

支付寶端的Dao文件

package com.teddy.alipayserver.dao;

import com.teddy.alipayserver.bean.Account;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Update;

public interface AccountMapper {
    @Update("update tb_account set amount=amount-#{amount}, update_time=now() where user_id=#{userId}")
    int updateAccount(Account account);
    @Insert("insert tb_account(user_id, amount, update_time) values(#{userId}, #{amount}, now())")
    int addAccount(Account account);
}
package com.teddy.alipayserver.dao;

import com.teddy.alipayserver.bean.Message;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Insert;

import java.util.List;

public interface MessageMapper {
    @Update("update tb_message set state=#{state} where message_id=#{message_id}")
    int updateMessage(Message message);

    @Insert("insert into tb_message(user_id, message_id, amount, state, update_time) values (#{user_id}, #{message_id}, #{amount}, 'unconfirm', now())")
    int addMessage(Message message);

    @Select("select * from tb_message where state=#{state}")
    List<Message> queryMessageByState(String state);
}

service接口

package com.teddy.alipayserver.service;

public interface AlipayService {
    //修改支付寶賬戶餘額的接口
    public void updateAmount(int amount, String userId);
    //回調接口 修改本地消息表消息的狀態
    public void updateMessage(String param);
}

service接口實現

package com.teddy.alipayserver.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.teddy.alipayserver.bean.Account;
import com.teddy.alipayserver.bean.Message;
import com.teddy.alipayserver.config.RabbitmqSender;
import com.teddy.alipayserver.dao.AccountMapper;
import com.teddy.alipayserver.dao.MessageMapper;
import com.teddy.alipayserver.service.AlipayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Random;
@Service
public class AlipayServiceImpl implements AlipayService{
    @Autowired
    TransactionTemplate transactionTemplate;
    @Autowired
    AccountMapper accountMapper;
    @Autowired
    MessageMapper messageMapper;
    @Autowired
    RabbitmqSender rabbitmqSender;

    private static String SUCCESS="OK";

    /**
     * 1. 修改支付寶賬戶餘額信息
     * 2. 插入本地消息表
     * 3. 往mq中插入消息, 供餘額寶業務消息
     * @param amount
     * @param userId
     */
    @Override
    public void updateAmount(int amount, String userId) {
        String messageId=(String)transactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Object doInTransaction(TransactionStatus status) {
                //1. 修改餘額寶賬戶餘額信息
                Account account = new Account();
                account.setUserId(userId);
                account.setAmount(amount);
                int count=accountMapper.updateAccount(account);
                if(count==1){
                    //構建一個本地消息對賬表
                    String messageId="Sam"+System.currentTimeMillis()+new Random().nextInt(Integer.MAX_VALUE);
                    Message message = new Message();
                    message.setMessage_id(messageId);
                    message.setUser_id(userId);
                    message.setAmount(amount);
                    //dao
                    int result = 0;
                    result = messageMapper.addMessage(message);

                    if(result==1){
                        return messageId;
                    }else{
                        System.out.println("update local message table failure");
                        return null;
                    }
                }
                //2. 插入本地消息表
                return null;
            }
        });

        if(messageId!=null && messageId.trim().length()>1){
            // 構建待確認消息給MQ
            Message message = new Message();
            message.setMessage_id(messageId);
            message.setUser_id(userId);
            message.setAmount(amount);
            message.setState("unconfirm");
            // 消息發送模板發送這個消息
            rabbitmqSender.sendMessage("exchange.message", "teddy.message.routeKey", message);
        }
    }

    @Override
    public void updateMessage(String param) {
        JSONObject jsonObject= JSONObject.parseObject(param);
        String respCode=jsonObject.getString("respCode");
        String messageId=jsonObject.getString("messageId");
        if(SUCCESS.equals(respCode)){
            Message message=new Message();
            message.setState("confirm");
            message.setMessage_id(messageId);
            messageMapper.updateMessage(message);
        }
    }
}

這裏通過Spring的TransactionTemplate引入了編程式事務, 因爲本地操作要成爲一個事務, 遠程的操作不可能和本地一個事務, 但是所有操作需要在一個方法裏, 所以引入了編程式的事務。

實體

package com.teddy.alipayserver.bean;

import java.util.Date;

public class Account {
    private String userId;
    private Integer amount;
    private Date updateTime;

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public Integer getAmount() {
        return amount;
    }

    public void setAmount(Integer amount) {
        this.amount = amount;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }
}
package com.teddy.alipayserver.bean;

import java.io.Serializable;

public class Message implements Serializable{

    private static final long serialVersionUID=1L;

    private String message_id;
    private String user_id;
    private Integer amount;
    private String state;

    public String getMessage_id() {
        return message_id;
    }

    public void setMessage_id(String message_id) {
        this.message_id = message_id;
    }

    public String getUser_id() {
        return user_id;
    }

    public void setUser_id(String user_id) {
        this.user_id = user_id;
    }

    public Integer getAmount() {
        return amount;
    }

    public void setAmount(Integer amount) {
        this.amount = amount;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
}

RabbitMQ的配置文件

package com.teddy.alipayserver.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitmqConfig {

    @Bean(name="message")
    public Queue queueMessage(){
        return new Queue("teddy.message");
    }

    @Bean
    public TopicExchange exchange(){
        return new TopicExchange("exchange.message");
    }

    @Bean
    Binding bindingExchangeMessage(@Qualifier("message") Queue queueMessage, TopicExchange exchange){
        return BindingBuilder.bind(queueMessage).to(exchange).with("teddy.message.routeKey");
    }
}

RabbitMQ的服務

package com.teddy.alipayserver.config;

import com.alibaba.fastjson.JSONObject;
import com.teddy.alipayserver.bean.Message;
import org.springframework.amqp.core.AmqpTemplate;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


@Component
public class RabbitmqSender {
    @Autowired
    private AmqpTemplate amqpTemplate;

    public void sendMessage(String exchange, String routeKey, Message content){
        String message= JSONObject.toJSONString(content);
        System.out.println("send message to MQ, waiting for alipay consuming:"+message);
        amqpTemplate.convertAndSend(exchange, routeKey, message);
    }
}

Controller

package com.teddy.alipayserver.controller;

import com.teddy.alipayserver.service.AlipayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AlipayController {
    @Autowired
    AlipayService alipayService;

    @RequestMapping("/transfer")
    @ResponseBody
    public String transferAmount(String userId, int amount){
        try {
            alipayService.updateAmount(amount, userId);
        } catch (Exception e) {
            e.printStackTrace();
            return "fail";
        }
        return"OK";
    }
}

配置文件

spring:
  datasource:
    druid:
      url: jdbc:mysql://192.168.25.132:3306/rabbit_taobao_provider?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: 123456
      initial-size: 1
      min-idle: 1
      max-active: 20
      test-on-borrow: true
      driver-class-name: com.mysql.jdbc.Driver
  application:
    name: aplipay-server
  rabbitmq:
    host: 192.168.25.137
    port: 5672
    username: rabbit
    password: 123456
server:
  port: 8090

定時器, 用來重發消息

package com.teddy.alipayserver.timer;

import com.alibaba.fastjson.JSONObject;
import com.teddy.alipayserver.bean.Message;
import com.teddy.alipayserver.config.RabbitmqSender;
import com.teddy.alipayserver.dao.MessageMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Component
public class ScheduledService {
    private static SimpleDateFormat sdf=new SimpleDateFormat("YYYY-MM-dd");
    @Autowired
    MessageMapper messageMapper;
    @Autowired
    RabbitmqSender rabbitmqSender;

    @Scheduled(cron="0/60 0/1 * * * ?")
    public void scheduledProcess(){
        System.out.println("============>>>>>>>>>use cron "+sdf.format(new Date())+" start scan ......");
        List<Message> unconfirmMessages=messageMapper.queryMessageByState("unconfirm");
        if(unconfirmMessages!=null&&unconfirmMessages.size()>0){
            System.out.println("query unconfirmed message:"+JSONObject.toJSONString(unconfirmMessages));
            for(Message message:unconfirmMessages){
                System.out.println("============timer send unconfirm message to mq"+ JSONObject.toJSONString(message));
                rabbitmqSender.sendMessage("exchange.message", "teddy.message.routeKey", message);
            }
        }
    }
}

監聽器, 用來監聽響應隊列中的消息

package com.teddy.alipayserver.listener;

import com.teddy.alipayserver.service.AlipayService;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class listener {
    @Autowired
    AlipayService alipayService;

    @RabbitListener(queues="teddy.message.response")
    public void process(final String result){
        System.out.println("=====================receive balance transaction successul response message========"+result);
        alipayService.updateMessage(result);
    }
}

啓動文件

package com.teddy.alipayserver;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * http://localhost:8090/transfer?userId=SAM0000001&amount=3000
 */
@SpringBootApplication(scanBasePackages = "com.teddy.alipayserver")
@MapperScan(basePackages = {"com.teddy.alipayserver.dao"})
@EnableScheduling
public class AlipayServerApplication {

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

}

下面是餘額寶的工程, pom.xml和支付寶是一樣的

dao

package com.teddy.balanceserver.dao;


import com.teddy.balanceserver.bean.Account;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;

public interface AccountMapper {
    @Update("update tb_account set amount=amount-#{amount}, update_time=now() where user_id=#{userId}")
    int updateAccount(@Param("amount")int amount, @Param("userId") String userId);
    @Insert("insert tb_account(user_id, amount, update_time) values(#{userId}, #{amount}, now())")
    int addAccount(Account account);
}
package com.teddy.balanceserver.dao;


import com.teddy.balanceserver.bean.Message;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;

public interface MessageMapper {
    @Update("update tb_message set state=#{state} where message_id=#{message_id}")
    int updateMessage(Message message);

    @Insert("insert into tb_message(user_id, message_id, amount, state, update_time) values (#{userId}, #{messageId}, #{amount}, 'confirm', now())")
    int addMessage(@Param("userId")String userId, @Param("messageId")String messageId, @Param("amount")int amount);

    @Select("select * from tb_message where state=#{state}")
    List<Message> queryMessageByState(@Param("state") String state);

    @Select("select * from tb_message where message_id=#{messageId}")
    List<Message> queryMessaegCountByMessageId(@Param("messageId") String messageId);
}

service

package com.teddy.balanceserver.service;

import com.teddy.balanceserver.bean.Account;

public interface BalanceService {
    public int queryMessaegCountByMessageId(String messageId);

    public void updateAmount(int amount, String userId);

    public void addMessage(String userId, String messageId, int amount);
}

service的實現

package com.teddy.balanceserver.service.impl;

import com.teddy.balanceserver.bean.Account;
import com.teddy.balanceserver.bean.Message;
import com.teddy.balanceserver.dao.AccountMapper;
import com.teddy.balanceserver.dao.MessageMapper;
import com.teddy.balanceserver.service.BalanceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class BalanceServiceImpl implements BalanceService{

    @Autowired
    AccountMapper accountMapper;
    @Autowired
    MessageMapper messageMapper;

    @Override
    public int queryMessaegCountByMessageId(String messageId) {
        List<Message> messages = messageMapper.queryMessaegCountByMessageId(messageId);
        return messages.size();
    }

    @Override
    public void updateAmount(int amount, String userId) {
        accountMapper.updateAccount(amount, userId);
    }

    @Override
    public void addMessage(String userId, String messageId, int amount) {
        messageMapper.addMessage(userId, messageId, amount);
    }
}

隊列的配置

package com.teddy.balanceserver.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitmqConfig {

    @Bean(name="message")
    public Queue queueMessage(){
        return new Queue("teddy.message.response");
    }

    @Bean
    public TopicExchange exchange(){
        return new TopicExchange("exchange.message.response");
    }

    @Bean
    Binding bindingExchangeMessage(@Qualifier("message") Queue queueMessage, TopicExchange exchange){
        return BindingBuilder.bind(queueMessage).to(exchange).with("teddy.message.routeKey.response");
    }
}

發送服務

package com.teddy.balanceserver.config;

import com.alibaba.fastjson.JSONObject;
import com.teddy.balanceserver.bean.Message;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


@Component
public class RabbitmqSender {
    @Autowired
    private AmqpTemplate amqpTemplate;

    public void sendMessage(String exchange, String routeKey, String content){
        System.out.println("send message to MQ, waiting for alipay consuming:"+content);
        amqpTemplate.convertAndSend(exchange, routeKey, content);
    }
}

監聽器

package com.teddy.balanceserver.listener;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.teddy.balanceserver.bean.Message;
import com.teddy.balanceserver.config.RabbitmqSender;
import com.teddy.balanceserver.service.BalanceService;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

@Component
public class ReceiveListener {

    private static String SUCCESS="OK";

    @Autowired
    BalanceService balanceService;
    @Autowired
    TransactionTemplate transactionTemplate;
    @Autowired
    RabbitmqSender rabbitmqSender;

    @RabbitListener(queues="teddy.message")
    public void process(String jsonStr){
        final Message message=JSONObject.parseObject(jsonStr, Message.class);
        System.out.println("========balance start to consume MQ's message, message is: "+jsonStr);

        boolean isSuccess = (Boolean) transactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Boolean doInTransaction(TransactionStatus status) {
                //1. 修改本地餘額寶的賬戶餘額
                //2. 修改本地餘額成功消息插入本地消息對賬表
                //編程式事務
                String message_id=message.getMessage_id();
                int count=balanceService.queryMessaegCountByMessageId(message_id);
                // count==0代表餘額寶沒有處理過該流水號的記錄
                if(count==0){
                    balanceService.updateAmount(message.getAmount(), message.getUser_id());
                    balanceService.addMessage(message.getUser_id(), message_id, message.getAmount());
                    return true;
                }else{
                    System.out.println("this message id:"+message_id+"already consumed. transaction stopped");
                    return false;
                }
            }
        });
        //3. 修改本地餘額成功消息通過MQ的應答隊列發送給支付寶進行確認
        if(isSuccess){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("messageId", message.getMessage_id());
            jsonObject.put("respCode", SUCCESS);
            System.out.println("===========send transaction successful response message to alipay======"+jsonObject.toJSONString());
            rabbitmqSender.sendMessage("exchange.message.response", "teddy.message.routeKey.response", jsonObject.toJSONString());
        }else{

        }
    }
}

配置文件

spring:
  datasource:
    druid:
      url: jdbc:mysql://192.168.25.132:3306/rabbit_taobao_consumer?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: 123456
      initial-size: 1
      min-idle: 1
      max-active: 20
      test-on-borrow: true
      driver-class-name: com.mysql.jdbc.Driver
  application:
    name: balance-server
  rabbitmq:
    host: 192.168.25.137
    port: 5672
    username: rabbit
    password: 123456
server:
  port: 8080

啓動類

package com.teddy.balanceserver;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication(scanBasePackages = "com.teddy.balanceserver")
@MapperScan(basePackages = {"com.teddy.balanceserver.dao"})
@EnableScheduling
public class BalanceServerApplication {

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

}

 

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