springboot integrates rabbitmq to complete public account sending messages

springboot integrates rabbitmq to complete public account sending messages

1. Download rabbitmq

You can download it using brew

brew install rabbitmq

There may be problems, please ignore if not

fatal: not in a git directory Error: Command failed with exit 128: git

Solution:
Execute separately, and then re-execute: brew install rabbitmq

git config --global --add safe.directory /opt/homebrew/Library/Taps/homebrew/homebrew-core
git config --global --add safe.directory /opt/homebrew/Library/Taps/homebrew/homebrew-cask

2. Check whether rabbitmq is successful

Execution rabbitmq-serverIf the following figure appears, it indicates successful startup.
Please add image description

3. Write code

3.1 Import pom dependencies

<?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>org.example</groupId>
    <artifactId>whispers</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.9.RELEASE</version>
        <relativePath/>
    </parent>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
    </properties>

    <dependencies>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.2.0</version>
            </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>

        <!-- JSONObject的依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.71</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
            <version>2.2.3.RELEASE</version>
        </dependency>
        </dependencies>

    </project>

3.2 application.yml file configuration

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/whisper?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  rabbitmq:
    host: 127.0.0.1
    username: test
    port: 5672
    virtual-host: /whhx
    password: 123456

server:
  port: 9999
mybatis:
  mapper-locations:
    - classpath:/mapper/*.xml
wx:
  app-id: wxaa64d0c144ca81b5
  app-secret: fcb7b645ecb419b5e55868706dd842d5
  token-url: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s
  message-url: https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s

management:
  health:
    rabbit:
      enabled: false

3.3 Create a new MqSendMsgConfig configuration class

package com.xxx.config;

import com.xxx.constant.QueueConstant;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MqSendMsgConfig {

    // 微信消息队列
    @Bean
    public Queue sendWxQueue(){
        return new Queue(QueueConstant.WX_SEND_QUEUE);
    }

    @Bean
    public DirectExchange sendWxEx(){
        return new DirectExchange(QueueConstant.WX_SEND_EX);
    }

    @Bean
    public Binding sendWxBind(){
        return BindingBuilder.bind(sendWxQueue()).to(sendWxEx()).with(QueueConstant.WX_SEND_KEY);
    }
}

3.4 Create a new WxAutoConfiguration configuration class

package com.xxx.config;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;

@Configuration
@EnableConfigurationProperties(value = WxProperties.class)
@Slf4j
public class WxAutoConfiguration {

    @Autowired
    private RestTemplate restTemplate;

    private String wxAccessToken;

    /**
     * spring实现注解规范:方法在所有的Bean对象创建之后, 项目启动完成之前执行
     * 限制:不能有返回值,也不能有参数
     */
    @PostConstruct
    public void tokenInit(){
        getAccessToken();
    }

    @Scheduled(initialDelay = 0, fixedRate = 7100 * 1000)
    public void getAccessToken(){
        String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", "wxaa64d0c144ca81b5", "d81bb0ef2dc54f1754e7d2eef91df3f1");
        String accessTokenJsonStr = restTemplate.getForObject(url, String.class);
        JSONObject accessTokenJson = JSONObject.parseObject(accessTokenJsonStr);
        String accessToken = accessTokenJson.getString("access_token");
        if (!StringUtils.isEmpty(accessToken)){
            wxAccessToken = accessToken;
        }else {
            log.error("获取access_token失败");
        }

    }

    public String getWxAccessToken() {
        return wxAccessToken;
    }

    public void setWxAccessToken(String wxAccessToken) {
        this.wxAccessToken = wxAccessToken;
    }

}

3.5 Create a new WxProperties configuration class

package com.xxx.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Data
@ConfigurationProperties(prefix = "wx")
public class WxProperties {

    private String appID;

    private String appSecret;

    private String accessTokenUrl;

    private String sendMsgUrl;

}

3.6 Create a new QueueConstant interface

package com.xxx.constant;

public interface QueueConstant {

    /**
     * 发送微信消息的队列
     */
    String WX_SEND_QUEUE = "wx.send.queue";

    /**
     * 发送微信消息的交换机
     */
    String WX_SEND_EX = "wx.send.ex";

    /**
     * 发送微信消息的路由key
     */
    String WX_SEND_KEY = "wx.send.key";

}

3.7 Create a new controller

  @PostMapping("p/sms/sendWxMsg")
    public ResponseEntity<Void> sendWxMsg(@RequestBody OpenIdName openIdName){
        userService.sendWxMsg(openIdName.getOpenId(), openIdName.getUserName());
        return ResponseEntity.ok().build();

    }

3.8 Create a new OpenIdName class

package com.xxx.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class OpenIdName {

    private String openId;

    private String userName;
}

3.9 Create a new service implementation class

package com.xxx.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xxx.constant.QueueConstant;
import com.xxx.entity.User;
import com.xxx.mapper.UserMapper;
import com.xxx.model.WxMsgModel;
import com.xxx.service.UserService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

 
    /**
     * 发送微信消息
     *
     * @param openId
     * @param name
     */
    @Override
    public void sendWxMsg(String openId, String name) {
        WxMsgModel wxMsgModel = new WxMsgModel();
        wxMsgModel.setToUser(openId);
        wxMsgModel.setTemplateId("ByimXumDgKGmfDlqGPA2kgYCQK36hqGZy8e5KkCU2Dg");
        wxMsgModel.setUrl("https://www.baidu.com");
        wxMsgModel.setTopColor("#FF0000");

        HashMap<String, Map<String, String>> data = new HashMap<>();
        data.put("userName", WxMsgModel.buildMap(name, "#173177"));
        data.put("time", WxMsgModel.buildMap(new Date().toString(), "173177"));
        data.put("product", WxMsgModel.buildMap("女朋友", "173177"));
        data.put("money", WxMsgModel.buildMap("0.1", "173177"));
        wxMsgModel.setData(data);

        //用mq发送消息
        rabbitTemplate.convertAndSend(QueueConstant.WX_SEND_EX, QueueConstant.WX_SEND_KEY, JSON.toJSONString(wxMsgModel));
    }
}

3.10 Create a new service interface


    /**
     * 发送微信消息
     * @param openId
     * @param name
     */
    void sendWxMsg(String openId, String name);

3.11 Create a new WxMsgModel class

package com.xxx.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.HashMap;
import java.util.Map;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class WxMsgModel {

    // 注意使用的@JsonProperty
    @JsonProperty(value = "touser")
    private String toUser;

    @JsonProperty(value = "template_id")
    private String templateId;

    @JsonProperty(value = "url")
    private String url;

    @JsonProperty(value = "topcolor")
    private String topColor;

    @JsonProperty(value = "data")
    private Map<String, Map<String, String>> data;

    public static Map<String, String> buildMap(String value, String color){
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("value", value);
        hashMap.put("color", color);
        return hashMap;
    }
}

3.12 Create a new listener

package com.xxx.listener;

import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import com.xxx.config.WxAutoConfiguration;
import com.xxx.config.WxProperties;
import com.xxx.constant.QueueConstant;
import com.xxx.model.WxMsgModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
@Slf4j
public class WxListener {

    @Autowired
    private WxProperties wxProperties;

    @Autowired
    private WxAutoConfiguration wxAutoConfiguration;

    @Autowired
    private RestTemplate restTemplate;



    /**
     * 处理微信公众号消息
     */
    @RabbitListener(queues = QueueConstant.WX_SEND_QUEUE, concurrency = "3-5")
    public void wxHandler(Message message, Channel channel){
        String msgStr = new String(message.getBody());
        WxMsgModel wxMsgModel = JSONObject.parseObject(msgStr, WxMsgModel.class);
        try {
            String response = sendWxMsg(wxMsgModel);
            log.info("发送微信公众号消息成功");
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

        } catch (Exception e){
            log.error("发送微信公众号消息失败");
        }
    }

    /**
     * 发送微信消息
     */
    private String sendWxMsg(WxMsgModel wxMsgModel){
        String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
        String wxAccessToken = wxAutoConfiguration.getWxAccessToken();
        String url = String.format(accessTokenUrl, wxAccessToken);
        return restTemplate.postForObject(url, wxMsgModel, String.class);
    }
}


3.13 Startup class

package com.xxx;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@MapperScan(basePackages = "com.xxx.mapper")
@EnableScheduling
public class WhisperServiceApplication {

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

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

4. Overall project picture (user-related ones can be ignored)

This project is continued to be developed on a demo, and you can ignore the user-related aspects.
Please add image description

5. rabbitmq’s page

Page input URL: http://localhost:15672
Login account password: guest

5.1 Problems that may occur when starting the project

1、An unexpected connection driver error occured
2、Restarting Consumer@43f3c557: tags=[[]], channel=null, acknowledgeMode=AUTO

Wait, no matter what problem occurs, the problem related to mq is usually that mq cannot be connected. At this time, you need to create a new test account on the page. You can
refer to the link: https://blog.csdn.net/theRengar/article/details/ 118933418. Very simple

6. Project startup testing

You can use debug to test. Once the message is sent, the listener will immediately get the message and then consume it. Please add image description

Please add image description
Please add image description
Please add image description

Guess you like

Origin blog.csdn.net/qq_36151389/article/details/132982846