持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情
上篇讲了基础消息能力,对用户的消息做响应,但对于复杂消息如何进行对应的处理呢?本篇将进行讲解。
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 方法,处理对应消息. 测试:
到此使用策略模式处理复杂消息完成 下一篇:事件处理