wx-tools WxMessageRouter的使用例子
2.5.1 创建菜单栏
假设一下,我现在想把公众号的菜单栏设置成这样的:
我们可以写一个Main方法,来更改公众号的菜单栏,代码如下:
public class Menu {
public static void main(String[] args) {
IService iService = new WxService();
WxMenu menu = new WxMenu();
List<WxMenu.WxMenuButton> btnList = new ArrayList<>();
//飙升功能
WxMenu.WxMenuButton btn1 = new WxMenu.WxMenuButton();
btn1.setName("分类");
List<WxMenu.WxMenuButton> subList = new ArrayList<>();
WxMenu.WxMenuButton btn1_1 = new WxMenu.WxMenuButton();
btn1_1.setType(WxConsts.MENU_BUTTON_CLICK);
btn1_1.setKey(MenuKey.HOT_SONG);
btn1_1.setName("飙升榜");
WxMenu.WxMenuButton btn1_2 = new WxMenu.WxMenuButton();
btn1_2.setType(WxConsts.MENU_BUTTON_CLICK);
btn1_2.setKey(MenuKey.TOP_500);
btn1_2.setName("TOP500");
WxMenu.WxMenuButton btn1_3 = new WxMenu.WxMenuButton();
btn1_3.setType(WxConsts.MENU_BUTTON_CLICK);
btn1_3.setKey(MenuKey.NET_HOT_SONG);
btn1_3.setName("网络红歌");
WxMenu.WxMenuButton btn1_4 = new WxMenu.WxMenuButton();
btn1_4.setType(WxConsts.MENU_BUTTON_CLICK);
btn1_4.setKey(MenuKey.HUAYU_SONG);
btn1_4.setName("华语新歌");
WxMenu.WxMenuButton btn1_5 = new WxMenu.WxMenuButton();
btn1_5.setType(WxConsts.MENU_BUTTON_CLICK);
btn1_5.setKey(MenuKey.XINAO_SONG);
btn1_5.setName("洗脑神曲");
WxMenu.WxMenuButton btn2 = new WxMenu.WxMenuButton();
btn2.setType(WxConsts.MENU_BUTTON_CLICK);
btn2.setKey(MenuKey.CHANGE_NEWS);
btn2.setName("换一组");
WxMenu.WxMenuButton btn3 = new WxMenu.WxMenuButton();
btn3.setType(WxConsts.MENU_BUTTON_CLICK);
btn3.setKey(MenuKey.HELP);
btn3.setName("帮助");
subList.addAll(Arrays.asList(btn1_1, btn1_2, btn1_3, btn1_4, btn1_5));
btn1.setSub_button(subList);
//将三个按钮设置进btnList
btnList.add(btn1);
btnList.add(btn2);
btnList.add(btn3);
//设置进菜单类
menu.setButton(btnList);
//调用API即可
try {
//参数1--menu ,参数2--是否是个性化定制。如果是个性化菜单栏,需要设置MenuRule
iService.createMenu(menu, false);
} catch (WxErrorException e) {
e.printStackTrace();
}
}
}
- 接下来直接运行就行了,你就会看到你的公众号菜单栏的变化。
菜单栏的参数设置,请参考官方文档 - 菜单栏的创建, 菜单栏的按钮有分很多种类型(type),例如click,view等。详情建议先看官方文档。
2.5.2 创建消息路由并设置第一个规则(Rule)
假设需求如下: 我只接收菜单栏类型为:Click,且Key为MenuKey.HELP的消息,其他一律放弃不接收。
正常来说,常规写法应该是加一个if判断,例如:
if("CLICK".equals(message.event) && MenuKey.HELP.equals(message.eventKey)){
doSomething();
}
这样的写法会随着需求增多,而越来越庞大臃肿。
而wx-tools使用消息路由的方式去过滤处理消息,写法如下:
- 补充WxController中的Post处理方法:
@PostMapping public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter();
// 创建一个路由器 WxMessageRouter router = new WxMessageRouter(iService); try { // 微信服务器推送过来的是XML格式。 WxXmlMessage wx = XStreamTransformer.fromXml(WxXmlMessage.class, request.getInputStream()); System.out.println("消息:\n " + wx.toString()); router.rule().event(WxConsts.EVT_CLICK).eventKey(MenuKey.HELP).handler(HelpDocHandler.getInstance()).end(); // 把消息传递给路由器进行处理 WxXmlOutMessage xmlOutMsg = router.route(wx); if (xmlOutMsg != null) // 因为是明文,所以不用加密,直接返回给用户 out.print(xmlOutMsg.toXml());。
} catch (Exception e) { e.printStackTrace(); } finally { out.close(); }
}
- HelpDocHandler.java代码如下:
> Handler代码采用单例模式,为了解决消息重试的问题。但由于网络问题导致返回结果慢了。会自动重试,返回多条信息。当然,这种做法不建议你们使用,因为这样写,同一时间仅仅允许一个线程进来处理,并不适合多线程环境。
> 因为这个音乐爬虫项目是做给我女票使用的,用户仅仅只有一个。所以我可以这么做,而你不们作为项目,不可以!!!好了继续~
> 官方关于消息重试的机制[点击这里查看](https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140453)。
public class HelpDocHandler implements WxMessageHandler {
private static HelpDocHandler instance = null;
private boolean isRun = false;
private HelpDocHandler(){}
public static synchronized HelpDocHandler getInstance(){ if (instance == null) { instance = new HelpDocHandler(); } return instance; }
private synchronized boolean getIsRun() { return isRun; }
private synchronized void setRun(boolean run) { isRun = run; }
@Override public WxXmlOutMessage handle(WxXmlMessage wxMessage, Map<String, Object> context, IService iService) throws WxErrorException { WxXmlOutMessage response = null; if (!getIsRun()) { setRun(true); response = execute(wxMessage); setRun(false); } return response; }
private WxXmlOutMessage execute(WxXmlMessage wxMessage) { return WxXmlOutMessage.TEXT().content(ResponseConst.HELP).toUser(wxMessage.getFromUserName()).fromUser(wxMessage.getToUserName()).build(); } }
- 接下来测试一下,点击公众号的帮助按钮,正常返回帮助说明。而点击其他按钮,均无反应。
这样我们就成功利用消息路由和创建第一个规则(Rule)去过滤消息,并处理返回了。
是不是很简单~2333
现在我们尝试使用wx-tools其他特性,添加更多的功能进去吧~gogogo
更多建议: