SpringCloud Alibaba 开发微信公众号 (使用策略模式处理复杂消息)

简介: SpringCloud Alibaba 开发微信公众号 (使用策略模式处理复杂消息)

上篇讲了基础消息能力,对用户的消息做响应,但对于复杂消息如何进行对应的处理呢?本篇将进行讲解。

1.通过解析返回的MsgType判断消息类型,并作出相应的处理。

上代码: ImageMessage 图片信息实体类

import cn.org.spring.common.util.XmlUtils;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
import java.util.Map;
/**
 * Created with IntelliJ IDEA.
 * User:  wanghongjie
 * Date:  2020/10/18 - 19:12
 * <p>
 * Description:
 */
@Data
@XStreamAlias("xml")
public class ImageMessage extends BaseMessage {
    /**
     * 图片链接
     */
    @XStreamAlias("PicUrl")
    private String picUrl;
    /**
     * 图片素材ID
     */
    @XStreamAlias("MediaId")
    private String mediaId;
    @XStreamAlias("Image")
    private Image image;
    public static ImageMessage ofSend(Map<String, Object> param, Image image) {
        ImageMessage imageMessage = new ImageMessage();
        imageMessage.init(param);
        imageMessage.setImage(image);
        imageMessage.setMsgType("image");
        String from = imageMessage.getFromUserName();
        imageMessage.setFromUserName(imageMessage.getToUserName());
        imageMessage.setToUserName(from);
        return imageMessage;
    }
    /**
     * 测试使用,接收什么图片返回什么图片
     *
     * @param param
     * @return
     */
    @Deprecated
    public static ImageMessage ofSend(Map<String, Object> param) {
        ImageMessage imageMessage = new ImageMessage();
        imageMessage.init(param);
        imageMessage.setImage(Image.of(param.get("MediaId").toString()));
        imageMessage.setMsgType("image");
        String from = imageMessage.getFromUserName();
        imageMessage.setFromUserName(imageMessage.getToUserName());
        imageMessage.setToUserName(from);
        return imageMessage;
    }
    /**
     * 对象转XML
     *
     * @return
     */
    public String toXml() {
        return XmlUtils.beanToXml(this, ImageMessage.class);
    }
}
复制代码

图片消息对象

import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Getter;
import java.io.Serializable;
/**
 * 图片消息对象
 * Created with IntelliJ IDEA.
 * User:  wanghongjie
 * Date:  2020/10/18 - 19:15
 * <p>
 * Description:
 */
@Getter
@XStreamAlias("Image")
public class Image implements Serializable {
    @XStreamAlias("MediaId")
    private String mediaId;
    public Image(String mediaId) {
        this.mediaId = mediaId;
    }
    public Image() {
    }
    /**
     * OF 模式
     *
     * @param mediaId 素材ID
     * @return
     */
    public static Image of(String mediaId) {
        return new Image(mediaId);
    }
}
复制代码

ImageMessageService

import com.ctsi.sddx.bean.message.ImageMessage;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
 * @Author : lizzu
 * @create 2022/10/2 14:19
 */
@Service
public class ImageMessageService {
    /**
     * 测试响应图片信息
     *
     * @param param 接收到参数
     * @return
     */
    public String sendMessage(Map<String,Object> param){
        return  ImageMessage.ofSend(param).toXml();
    }
}
复制代码

WeCharController

//    获取微信返回数据
@PostMapping
public String getWeChar(@RequestBody String message) throws Exception {
    System.out.println("接收到微信返回的消息:"+message);
    Map<String, Object> stringObjectMap = XmlUtils.xmlStrToMap(message);
    if (stringObjectMap.get("MsgType").equals("image")){//图片类型处理
        return imageMessageService.sendMessage(stringObjectMap);
    }else {
        TextMessage textMessage = TextMessage.ofSendMsg(stringObjectMap, "你好呀,欢迎关注我的测试公众号!!");
        return textMessage.toXml();
    }
}
复制代码

测试

网络异常,图片无法展示
|

根据接口文档可以看出,消息的类型有:文本消息、图片消息、语音消息、视频消息、小视频消息、地理位置消息、链接消息。。。,如果直只用if-else来处理的话明显代码显得比较复杂,因此可以用策略模式来处理不同消息的情况。

#### 2.使用策略模式

1.创建消息类型枚举类 MessageType

/**
 * 消息类型枚举
 * Created by wanghongjie on 2020/10/18 19:34
 */
public enum MessageType {
    /**
     * 文本类型
     */
    TEXT,
    /**
     * 图片类消息
     */
    IMAGE,
    /**
     * 语音消息
     */
    VOICE,
    /**
     * 视频消息
     */
    VIDEO,
    /**
     * 小视频消息
     */
    SHORTVIDEO,
    /**
     * 连接消息
     */
    LINK,
    /**
     * 事件消息
     */
    EVENT,
    /**
     * 位置消息
     */
    LOCATION,
    /**
     * 图文列表
     */
    NEWS;
    /**
     * 根据类型名称获取类型
     *
     * @param type 类型名称
     * @return 枚举类型
     */
    public static MessageType getType(String type) {
        for (MessageType item : MessageType.values()) {
            if (item.name().toLowerCase().equals(type.toLowerCase())) {
                return item;
            }
        }
        return TEXT;
    }
}
复制代码

2.定义消息处理接口 IMessage

import java.util.Map;
/**
 * @Author : lizzu
 * @create 2022/10/3 13:43
 */
public interface IMessage {
    /**
     * 消息处理接口
     *
     * @param param 微信公众号推送的消息数据
     * @return 响应数据
     */
    String handler(Map<String, Object> param);
}
复制代码

将ImageMessageService,TextMessageService 实现 IMessage 接口,并实现handler方法.

3.消息处理工厂类ContextMessageFactory

import com.ctsi.sddx.constants.MessageType;
import com.ctsi.sddx.service.message.IMessage;
import java.util.HashMap;
import java.util.Map;
/**
 * @Author : lizzu
 * @create 2022/10/3 13:46
 * 消息处理工厂类
 */
public class ContextMessageFactory {
    /**
     * 消息处理集合类key:消息类型 value:对应消息类型的处理方法
     */
    private Map<MessageType, IMessage> messageMap = new HashMap<>();
    public Map<MessageType, IMessage> getMessageMap() {
        return messageMap;
    }
    /**
     * setter
     *
     * @param messageMap 消息处理集合
     */
    public void setMessageMap(Map<MessageType, IMessage> messageMap) {
        this.messageMap = messageMap;
    }
    /**
     * builder
     *
     * @param messageType 消息类型
     * @param message     对应消息类型处理类
     */
    public ContextMessageFactory builder(MessageType messageType, IMessage message) {
        this.messageMap.putIfAbsent(messageType, message);
        return this;
    }
    /**
     * 消息处理方式
     *
     * @param messageType 消息类型
     * @param param       处理参数(数据)
     * @return
     */
    public String doAction(MessageType messageType, Map<String, Object> param) {
        if (this.messageMap.get(messageType) != null) {
            return this.messageMap.get(messageType).handler(param);
        }
        return "success";
    }
}
复制代码

4.创建MessageConfig 消息配置类

import com.ctsi.sddx.constants.MessageType;
import com.ctsi.sddx.context.ContextMessageFactory;
import com.ctsi.sddx.service.message.ImageMessageService;
import com.ctsi.sddx.service.message.TextMessageService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @Author : lizzu
 * @create 2022/10/3 13:50
 * 消息配置类
 */
@Configuration
public class MessageConfig {
    private ApplicationContext applicationContext;
    public MessageConfig(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
    @Bean
    public ContextMessageFactory getContextMessageFactory() {
        ContextMessageFactory contextMessageFactory = new ContextMessageFactory();
        contextMessageFactory.builder(MessageType.IMAGE, applicationContext.getBean(ImageMessageService.class))
                .builder(MessageType.TEXT, applicationContext.getBean(TextMessageService.class));
    }
}
复制代码

修改WeCharController

private final ContextMessageFactory contextMessageFactory;
private final AccessTokenService accessTokenService;
public WeCharController(AccessTokenService accessTokenService, ContextMessageFactory contextMessageFactory) {
    this.accessTokenService = accessTokenService;
    this.contextMessageFactory = contextMessageFactory;
}
 //    获取微信返回数据
    @PostMapping
    public String getWeChar(@RequestBody String message) throws Exception {
        System.out.println("接收到微信返回的消息:"+message);
        Map<String, Object> stringObjectMap = XmlUtils.xmlStrToMap(message);
        MessageType msgType = MessageType.getType(stringObjectMap.get("MsgType").toString());
        return contextMessageFactory.doAction(msgType, stringObjectMap);
//        if (stringObjectMap.get("MsgType").equals("image")){//图片类型处理
//            return imageMessageService.sendMessage(stringObjectMap);
//        }else {
//            return textMessageService.sendMessage(stringObjectMap);
//        }
    }
复制代码

说明: 在服务启动时加载MessageConfig配置类 并初始化ContextMessageFactory bean,调用builder方法给messageMap赋值(key:消息类型 value:对应消息类型的处理方法) ,这样就有了消息类型对应的消息处理方法,在WeCharController中引入ContextMessageFactory 并调用doAction 方法,处理对应消息. 测试:

网络异常,图片无法展示
|

到此使用策略模式处理复杂消息完成 下一篇:事件处理



相关文章
|
3月前
|
消息中间件 人工智能 Java
抖音微信爆款小游戏大全:免费休闲/竞技/益智/PHP+Java全筏开源开发
本文基于2025年最新行业数据,深入解析抖音/微信爆款小游戏的开发逻辑,重点讲解PHP+Java双引擎架构实战,涵盖技术选型、架构设计、性能优化与开源生态,提供完整开源工具链,助力开发者从理论到落地打造高留存、高并发的小游戏产品。
|
4月前
|
小程序 JavaScript API
uni-halo + 微信小程序开发实录:我的第一个作品诞生记
这篇文章介绍了使用uni-halo框架进行微信小程序开发的过程,包括选择该框架的原因、开发目标以及项目配置和部署的步骤。
204 0
uni-halo + 微信小程序开发实录:我的第一个作品诞生记
|
7月前
|
小程序 前端开发 Android开发
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
1546 29
小程序微信分享功能如何开发?开放平台已绑定仍不能使用的问题?-优雅草卓伊凡
|
6月前
|
监控 数据可视化 数据处理
微信养号脚本,全自动插件,AUTOJS开发版
这是一套自动化微信养号工具,包含主脚本`wechat_auto.js`与配置文件`config.json`。主脚本实现自动浏览朋友圈、随机阅读订阅号文章及搜索指定公众号三大功能,支持自定义滚动次数、阅读时长等参数。代码通过随机化操作间隔模拟真实用户行为,具备完善的错误处理和日志记录功能。配套UI模块提供可视化操作界面,可实时监控任务状态与运行日志,便于调整参数设置。控制器部分扩展了批量数据处理能力,如学生信息的增删改查操作,适用于多场景应用。下载地址:https://www.pan38.com/share.php?code=n6cPZ 提取码:8888(仅供学习参考)。
|
9月前
|
人工智能 自然语言处理 小程序
技术小白如何利用DeepSeek半小时开发微信小程序?
通过通义灵码的“AI程序员”功能,即使没有编程基础也能轻松创建小程序或网页。借助DeepSeek V3和R1满血版模型,用户只需用自然语言描述需求,就能自动生成代码并优化程序。例如,一个文科生仅通过描述需求就成功开发了一款记录日常活动的微信小程序。此外,通义灵码还提供智能问答模式,帮助用户解决开发中的各种问题,极大简化了开发流程,让普通人的开发体验更加顺畅。
2796 11
技术小白如何利用DeepSeek半小时开发微信小程序?
|
8月前
|
小程序 Java 关系型数据库
weixin163基于微信小程序的校园二手交易平台系统设计与开发ssm(文档+源码)_kaic
本文介绍了一款基于微信小程序的校园二手物品交易平台的开发与实现。该平台采用Java语言开发服务端,使用MySQL数据库进行数据存储,前端以微信小程序为载体,支持管理员和学生两种角色操作。管理员可管理用户、商品分类及信息、交易记录等,而学生则能注册登录、发布购买商品、参与交流论坛等。系统设计注重交互性和安全性,通过SSM框架优化开发流程,确保高效稳定运行,满足用户便捷交易的需求,推动校园资源共享与循环利用。
|
8月前
|
小程序 关系型数据库 Java
weixin168“返家乡”高校暑期社会实践微信小程序设计与开发ssm(文档+源码)_kaic
本文探讨高校暑期社会实践微信小程序的开发与应用,旨在通过信息化手段提升活动管理效率。借助微信小程序技术、SSM框架及MySQL数据库,实现信息共享、流程规范和操作便捷。系统涵盖需求分析、可行性研究、设计实现等环节,确保技术可行、操作简便且经济合理。最终,该小程序可优化活动发布、学生信息管理和心得交流等功能,降低管理成本并提高工作效率。
|
9月前
|
小程序 JavaScript 前端开发
微信小程序开发全流程:从注册到上线的完整指南
这篇文章详细记录了微信小程序的完整开发到最终上线的每一个步骤。适合对小程序开发感兴趣的个人开发者或希望了解完整流程的学习者,涵盖了云开发、事件绑定、生命周期管理、组件使用等关键内容。
6057 11
|
9月前
|
负载均衡 Dubbo Java
Spring Cloud Alibaba与Spring Cloud区别和联系?
Spring Cloud Alibaba与Spring Cloud区别和联系?
|
10月前
|
JSON 缓存 小程序
微信小程序组件封装与复用:提升开发效率
本文深入探讨了微信小程序的组件封装与复用,涵盖组件的意义、创建步骤、属性与事件处理,并通过自定义弹窗组件的案例详细说明。组件封装能提高代码复用性、开发效率和可维护性,确保UI一致性。掌握这些技能有助于构建更高质量的小程序。