java微信开发API解析(六)-综合运用(消息处理、自定义菜单响应处理、用户自动分组处理;包含源码)

java微信开发API解析(六)

全局说明

* 详细说明请参考前两篇文章。

本文说明

* 本文主要是对前面学习的知识进行综合整合。
* 我们对需要的bean、工具类、xml、file进行必要的包装。
* 我们构建一个可以直接使用的Java微信应用。
* 文后包含该部分效果的测试微信公众号
* 文后包含构建好的源码供下载

bean的构建

  • public class Access_token,获取Access_token对应的bean。

    private String access_token;
    private String expires_in;
    
  • public class BaseMsg,所有消息共有成员变量bean。

    private String ToUserName;
    private String FromUserName;
    private long CreateTime;
    private String MsgType;
    
  • public class TextMsg extends BaseMsg,文本消息bean。

    private String Content;
    
  • public class Group,分组所需要的成员变量bean。

    private int id;
    private String name;
    private int count;
    private String openid;
    private String to_groupid;
    private String groupid;
    

工具类的构建

  • public class AccessTokenUtils,该工具类前文已经详细说明过了,在此处没有改动。
  • public class GlobalParamsUtils,该工具类存储了全局常量,包括APPID、SECERT、token等;以及微信服务器响应的消息类型(类型较多,可以直接查看源码,不再此处列出)。
  • public class GroupUtils ,包括对分组的各种操作。除了上一篇文章所说的对用户分组,还有一个保存用户信息的两个工具方法,如下

    public class GroupUtils {
        private static final String TAG = "GroupUtils";
    
        /*
         * 该方法测试将用户移动到指定分组
         */
        public static String updateGroup(String openid, String to_groupid) {
            ...
        }
    
        public static boolean existUser(String openid) {
            try {
                BufferedReader dr = new BufferedReader(new InputStreamReader(
                        new FileInputStream(new File("user.txt"))));
                String line = dr.readLine();
                while (line != null) {
                    if (openid.equals(line))
                        return true;
                    line = dr.readLine();
                }
                dr.close();
                return false;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return false;
            }
        }
    
        public static boolean AddGroup(String openid) {
            try {
                File file = new File("user.txt");
                if (!file.exists())
                    file.createNewFile();
                BufferedWriter dw = new BufferedWriter(new OutputStreamWriter(
                        new FileOutputStream(file, true)));
                dw.write(openid);
                dw.newLine();
                dw.flush();
                dw.close();
                return true;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return false;
            }
        }
    
        @Test
        public void Test1() {
            AddGroup("asdas");
        }
    }
    
  • public class MyHttpUtils,关于http的请求的简单封装。

  • public class SHAUtils,对sha加密的抽取。
  • public class XmlUtils ,对xml处理的工具抽取,如下

        package com.gist.utils;
    
        import java.io.InputStream;
        import java.util.HashMap;
        import java.util.List;
        import java.util.Map;
    
        import org.dom4j.Document;
        import org.dom4j.DocumentException;
        import org.dom4j.Element;
        import org.dom4j.io.SAXReader;
        import org.junit.Test;
    
        import com.gist.bean.TextMsg;
        import com.thoughtworks.xstream.XStream;
    
        /**
         * @author 高远</n>
         * 编写日期   2016-4-24下午2:28:07</n>
         * 邮箱  wgyscsf@163.com</n>
         * 博客  http://blog.csdn.net/wgyscsf</n>
         * TODO</n>
         */
        public class XmlUtils {
            private static final String TAG = "XmlUtils";
    
            /*
             * 解析用户发送过来的请求。将请求的xml全部封装到map里面
             */
            public static Map<String, String> handleXmlMsg(InputStream is) {
                Map<String, String> map = new HashMap<String, String>();
                try {
                    SAXReader saxReader=new SAXReader();
                    Document document = saxReader.read(is);
                    Element root = document.getRootElement();
                    List<Element> elements = root.elements();
                    for (Element e : elements) {
                        map.put(e.getName(), e.getText());
                    }
                    elements = null;
                    root = null;
                    document = null;
                    return map;
                } catch (DocumentException e) {
                    e.printStackTrace();
                }
                return null;
            }
    
            /**
             * TODO
             */
            public static String str2Xml(TextMsg textMsg) {
                XStream xStream=new XStream();
                xStream.alias("xml", TextMsg.class);
                String xmlStr = xStream.toXML(textMsg);
                return xmlStr;
            }
            @Test
            public void Test() {
                // 我们封装一个回复文本的信息.
                TextMsg textMsg = new TextMsg();
                textMsg.setFromUserName("from");
                textMsg.setToUserName("to");
                textMsg.setMsgType(GlobalParamsUtils.MSGTYPE_TEXT);
                String content = "默认回复消息.";
                textMsg.setContent(content);
                textMsg.setCreateTime(System.currentTimeMillis());
                System.out.println(str2Xml(textMsg));
            }
        }
    

servlet的构建以及业务层service的构建

  • public class CoreServlet extends HttpServlet,该方法改动很小,其中的POST请求如下

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // 特别注意,req.getInputStream()只能获取一次,并且只能读取一次。如果想要多次读取,需要另外想办法。
        // 设置编码
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        CoreService coreService = new CoreService();
        /*
         * 获取用户发送过来的消息
         */
        InputStream is = req.getInputStream();
    
        String reqXml = coreService.handleRequest(is);// 接收处理过之后的xml
        /*
         * 给用户回复消息
         */
        PrintWriter writer = resp.getWriter();
        writer.print(reqXml);
        writer.flush();
    }
    
  • public class CoreService,业务核心类,如下

    package com.gist.service;
    
    import java.io.InputStream;
    import java.util.Map;
    
    import com.gist.bean.TextMsg;
    import com.gist.utils.GlobalParamsUtils;
    import com.gist.utils.GroupUtils;
    import com.gist.utils.XmlUtils;
    
    /**
     * @author 高远</n>
     * 编写日期   2016-4-24下午2:10:32</n>
     * 邮箱  wgyscsf@163.com</n>
     * 博客  http://blog.csdn.net/wgyscsf</n>
     * TODO</n>
     */
    public class CoreService {
        // private static final String TAG = "CoreService";
    
        public String handleRequest(InputStream is) {
            boolean flag = false;// 设置一个标记,供下面分组用
            // 用户发送过来消息是xml格式的。虽然消息类型繁多,但是格式基本固定(参看资料包中的“请求资料.txt”)。我们使用xstram对其进行xml解析。
            Map<String, String> handleXmlMsg = XmlUtils.handleXmlMsg(is);
            /*
             * 我们查看资料包中的“请求资料.txt”可以发现,所有的请求都包括以下字段
             * <ToUserName><![CDATA[toUser]]></ToUserName>
             * <FromUserName><![CDATA[fromUser]]></FromUserName>
             * <CreateTime>1348831860</CreateTime>
             * <MsgType><![CDATA[text]]></MsgType>
             * 特别的,对于关注和取消关注、自定义菜单,还有一个共有的字段“Event
             * ”,并且它们的“MsgType”内容全部都是“event”(需要仔细观察
             * )。请参考GlobalParamsUtils中关于该部分参数的设置。
             */
            /*
             * 第一步,我们先获取所有事件共有的参数
             */
            String ToUserName = handleXmlMsg.get("ToUserName");
            String FromUserName = handleXmlMsg.get("FromUserName");
            String CreateTime = handleXmlMsg.get("CreateTime");
            String MsgType = handleXmlMsg.get("MsgType");
    
            // 我们封装一个回复文本的信息.
            TextMsg textMsg = new TextMsg();
            textMsg.setFromUserName(ToUserName);
            textMsg.setToUserName(FromUserName);
            textMsg.setMsgType(GlobalParamsUtils.MSGTYPE_TEXT);
            String content = "默认回复消息.wgyscsf";
    
            // 我们在这里测试一下用户自动分组(强制选择)
    
            boolean exist = GroupUtils.existUser(FromUserName);
    
            if (!exist) {
    
                String text = handleXmlMsg.get("Content");
                if (text.equals("1")) {
    
                    content = GroupUtils.updateGroup(FromUserName, "101");
                    GroupUtils.AddGroup(FromUserName);
                } else if (text.equals("2")) {
    
                    content = GroupUtils.updateGroup(FromUserName, "102");
                    GroupUtils.AddGroup(FromUserName);
                } else {
    
                    content = "请先选择分组(选择对应数字)<\n>:1、开发人员;2、普通用户";
                }
                textMsg.setContent(content);
                textMsg.setCreateTime(System.currentTimeMillis());
                String xmlStr = XmlUtils.str2Xml(textMsg);
                return xmlStr;
            }
    
    
            /*
             * 第二步,根据MsgType判断用户的请求类型。两大类:普通消息、事件推送
             */
            // 推送消息
            if (MsgType.equals(GlobalParamsUtils.MSGTYPE_EVENT)) {
                // 这里面在细节判断是何种推送事件
                String EVENT = handleXmlMsg.get("Event");
    
                if (EVENT.equals(GlobalParamsUtils.EVENT_SUBSCRIBE)) {
                    // 用户关注
                    content = "欢迎您的关注。";
                } else if (EVENT.equals(GlobalParamsUtils.EVENT_UNSUBSCRIBE)) {
                    // 取消关注
                    content = "取消关注。";
                } else if (EVENT.equals(GlobalParamsUtils.EVENT_SCAN)) {
                    // 扫描二维码
                    content = "扫描二维码。";
                } else if (EVENT.equals(GlobalParamsUtils.EVENT_LOCATION)) {
                    // 地理位置
                    content = "地理位置。";
                } else if (EVENT.equals(GlobalParamsUtils.EVENT_CLICK)) {
                    // click事件
                    content = "click事件。";
                } else if (EVENT.equals(GlobalParamsUtils.EVENT_VIEW)) {
                    // view事件
                    content = "view事件。";
                }
    
            } else {
                // 普通消息
                if (MsgType.equals(GlobalParamsUtils.MSGTYPE_TEXT)) {
                    // 普通文本
                    content = "普通文本。";
                } else if (MsgType.equals(GlobalParamsUtils.MSGTYPE_IMAGE)) {
                    // 图片消息
                    content = "图片消息。";
                } else if (MsgType.equals(GlobalParamsUtils.MSGTYPE_VOICE)) {
                    // 语音消息
                    content = "语音消息。";
                } else if (MsgType.equals(GlobalParamsUtils.MSGTYPE_VIDEO)) {
                    // 视频消息
                    content = "视频消息。";
                } else if (MsgType.equals(GlobalParamsUtils.MSGTYPE_SHORTVIDEO)) {
                    // 小视频消息
                    content = "小视频消息。";
                } else if (MsgType.equals(GlobalParamsUtils.MSGTYPE_LOCATION)) {
                    // 地理位置消息
                    content = "地理位置消息。";
                } else if (MsgType.equals(GlobalParamsUtils.MSGTYPE_LINK)) {
                    // 链接消息
                    content = "链接消息。";
                }
            }
            textMsg.setContent(content);
            textMsg.setCreateTime(System.currentTimeMillis());
            String xmlStr = XmlUtils.str2Xml(textMsg);
            return xmlStr;
    
        }
    }
    

测试的微信号二维码(包含上述所说的效果)

java微信开发API解析(六)-综合运用(消息处理、自定义菜单响应处理、用户自动分组处理;包含源码)
这是平时写的一些技术文章的微信公众号,欢迎关注:
java微信开发API解析(六)-综合运用(消息处理、自定义菜单响应处理、用户自动分组处理;包含源码)

源码下载

http://download.csdn.net/detail/wgyscsf/9501213

java微信开发API解析(六)-综合运用(消息处理、自定义菜单响应处理、用户自动分组处理;包含源码)

上一篇:获取微信的access_tokey,处理json格式的数据


下一篇:.Net实现微信公众平台开发接口(三) 之 “信息回复”