上篇讲了基础消息能力,对用户的消息做响应,但对于复杂消息如何进行对应的处理呢?本篇将进行讲解。
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 方法,处理对应消息. 测试:
网络异常,图片无法展示
|
到此使用策略模式处理复杂消息完成 下一篇:事件处理