微信公众平台开发实战(08) 基于地理信息的服务(LBS)

转自:http://coderdream.iteye.com/blog/2147716

微信公众平台开发实战(08) 基于地理信息的服务(LBS)

 

实现查找附近功能;

1)发送地理位置;

点击窗口底部的“+”按钮,选择“位置”,点“发送”

2)指定关键词搜索;

格式:附近+关键词\n例如:附近ATM、附近KTV、附近厕所

 

目录结构

  • 项目结构图
  • 增加和修改相关源代码
    1. 百度地点类
    2. 用户位置类
    3. 用户位置访问类
    4. 百度地图工具类
    5. 地图网页文件
    6. 核心Service

    7. 消息处理工具类
    8. Maven项目文件
  • 上传本地代码到GitHub
  • 上传工程WAR档至SAE
  • 微信客户端测试
  • 参考文档
  • 完整项目源代码

项目结构图


 

源代码文件说明

序号文件名说明操作
1BaiduPlace.java百度地点类新增
2UserLocation.java用户位置类新增
3UserLocationDao.java用户位置访问类新增
4BaiduMapUtil.java百度地图工具类新增
5route.jsp导航页面新增
6CoreService.java核心服务类,新增处理各种输入,返回不同图文信息更新
7MessageUtil.java新增生成图文信息的方法更新
8pom.xml新增json和Base64等jar更新

 

增加和修改相关源代码

百度地点类

BaiduPlace.java

Java代码   收藏代码
  1. package com.coderdream.model;  
  2.   
  3. /** 
  4.  * 地址信息 
  5.  *  
  6.  */  
  7. public class BaiduPlace implements Comparable<BaiduPlace> {  
  8.     /** 
  9.      * 名称 
  10.      */  
  11.     private String name;  
  12.     /** 
  13.      * 详细地址 
  14.      */  
  15.     private String address;  
  16.     /** 
  17.      * 经度 
  18.      */  
  19.     private String lng;  
  20.     /** 
  21.      * 纬度 
  22.      */  
  23.     private String lat;  
  24.     /** 
  25.      * 联系电话 
  26.      */  
  27.     private String telephone;  
  28.     /** 
  29.      * 距离 
  30.      */  
  31.     private int distance;  
  32.   
  33.     public String getName() {  
  34.         return name;  
  35.     }  
  36.   
  37.     public void setName(String name) {  
  38.         this.name = name;  
  39.     }  
  40.   
  41.     public String getAddress() {  
  42.         return address;  
  43.     }  
  44.   
  45.     public void setAddress(String address) {  
  46.         this.address = address;  
  47.     }  
  48.   
  49.     public String getLng() {  
  50.         return lng;  
  51.     }  
  52.   
  53.     public void setLng(String lng) {  
  54.         this.lng = lng;  
  55.     }  
  56.   
  57.     public String getLat() {  
  58.         return lat;  
  59.     }  
  60.   
  61.     public void setLat(String lat) {  
  62.         this.lat = lat;  
  63.     }  
  64.   
  65.     public String getTelephone() {  
  66.         return telephone;  
  67.     }  
  68.   
  69.     public void setTelephone(String telephone) {  
  70.         this.telephone = telephone;  
  71.     }  
  72.   
  73.     public int getDistance() {  
  74.         return distance;  
  75.     }  
  76.   
  77.     public void setDistance(int distance) {  
  78.         this.distance = distance;  
  79.     }  
  80.   
  81.     public int compareTo(BaiduPlace baiduPlace) {  
  82.         return this.distance - baiduPlace.getDistance();  
  83.     }  
  84. }  

 

用户位置类 

UserLocation.java

Java代码   收藏代码
  1. package com.coderdream.model;  
  2.   
  3. /** 
  4.  * 用户地理位置 
  5.  */  
  6. public class UserLocation {  
  7.     private String openId;  
  8.     /** 
  9.      * 经度 
  10.      */  
  11.     private String lng;  
  12.     /** 
  13.      * 纬度 
  14.      */  
  15.     private String lat;  
  16.     /** 
  17.      * 百度地图经度 
  18.      */  
  19.     private String bd09Lng;  
  20.     /** 
  21.      * 百度地图纬度 
  22.      */  
  23.     private String bd09Lat;  
  24.   
  25.     public String getOpenId() {  
  26.         return openId;  
  27.     }  
  28.   
  29.     public void setOpenId(String openId) {  
  30.         this.openId = openId;  
  31.     }  
  32.   
  33.     public String getLng() {  
  34.         return lng;  
  35.     }  
  36.   
  37.     public void setLng(String lng) {  
  38.         this.lng = lng;  
  39.     }  
  40.   
  41.     public String getLat() {  
  42.         return lat;  
  43.     }  
  44.   
  45.     public void setLat(String lat) {  
  46.         this.lat = lat;  
  47.     }  
  48.   
  49.     public String getBd09Lng() {  
  50.         return bd09Lng;  
  51.     }  
  52.   
  53.     public void setBd09Lng(String bd09Lng) {  
  54.         this.bd09Lng = bd09Lng;  
  55.     }  
  56.   
  57.     public String getBd09Lat() {  
  58.         return bd09Lat;  
  59.     }  
  60.   
  61.     public void setBd09Lat(String bd09Lat) {  
  62.         this.bd09Lat = bd09Lat;  
  63.     }  
  64. }  

 

用户位置访问类

UserLocationDao.java

Java代码   收藏代码
  1. package com.coderdream.dao;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.PreparedStatement;  
  5. import java.sql.ResultSet;  
  6. import java.sql.SQLException;  
  7.   
  8. import com.coderdream.model.UserLocation;  
  9. import com.coderdream.util.DBUtil;  
  10.   
  11. /** 
  12.  *  
  13.  */  
  14. public class UserLocationDao {  
  15.   
  16.     /** 
  17.      * 保存用户地理位置 
  18.      *  
  19.      * @param request 
  20.      *          请求对象 
  21.      * @param openId 
  22.      *          用户的OpenID 
  23.      * @param lng 
  24.      *          用户发送的经度 
  25.      * @param lat 
  26.      *          用户发送的纬度 
  27.      * @param bd09_lng 
  28.      *          经过百度坐标转换后的经度 
  29.      * @param bd09_lat 
  30.      *          经过百度坐标转换后的纬度 
  31.      */  
  32.     public int saveUserLocation(String openId, String lng, String lat, String bd09_lng, String bd09_lat) {  
  33.         String sql = "insert into user_location(open_id, lng, lat, bd09_lng, bd09_lat) values (?, ?, ?, ?, ?)";  
  34.         int count = 0;  
  35.         Connection con = null;  
  36.         PreparedStatement ps = null;  
  37.         try {  
  38.             con = DBUtil.getConnection();  
  39.             ps = con.prepareStatement(sql);  
  40.             ps.setString(1, openId);  
  41.             ps.setString(2, lng);  
  42.             ps.setString(3, lat);  
  43.             ps.setString(4, bd09_lng);  
  44.             ps.setString(5, bd09_lat);  
  45.             count = ps.executeUpdate();  
  46.         } catch (Exception e) {  
  47.             e.printStackTrace();  
  48.         } finally {  
  49.             // 释放资源  
  50.             DBUtil.close(ps);  
  51.             DBUtil.close(con);  
  52.         }  
  53.         return count;  
  54.     }  
  55.   
  56.     /** 
  57.      * 获取用户最后一次发送的地理位置 
  58.      *  
  59.      * @param request 
  60.      *          请求对象 
  61.      * @param openId 
  62.      *          用户的OpenID 
  63.      * @return UserLocation 
  64.      */  
  65.     public UserLocation getLastLocation(String openId) {  
  66.         UserLocation userLocation = null;  
  67.         String sql = "select open_id, lng, lat, bd09_lng, bd09_lat from user_location where open_id=? order by id desc limit 0,1";  
  68.         Connection con = null;  
  69.         PreparedStatement pre = null;  
  70.         ResultSet rs = null;  
  71.         try {  
  72.             con = DBUtil.getConnection();  
  73.             pre = con.prepareStatement(sql);  
  74.             pre.setString(1, openId);  
  75.             rs = pre.executeQuery();  
  76.             if (rs.next()) {  
  77.                 userLocation = new UserLocation();  
  78.                 userLocation.setOpenId(rs.getString("open_id"));  
  79.                 userLocation.setLng(rs.getString("lng"));  
  80.                 userLocation.setLat(rs.getString("lat"));  
  81.                 userLocation.setBd09Lng(rs.getString("bd09_lng"));  
  82.                 userLocation.setBd09Lat(rs.getString("bd09_lat"));  
  83.             }  
  84.             // 释放资源  
  85.             rs.close();  
  86.         } catch (SQLException e) {  
  87.             e.printStackTrace();  
  88.         } finally {  
  89.             DBUtil.close(rs);  
  90.             DBUtil.close(pre);  
  91.             DBUtil.close(con);  
  92.         }  
  93.         return userLocation;  
  94.     }  
  95. }  

 

百度地图工具类

BaiduMapUtil.java

Java代码   收藏代码
  1. package com.coderdream.util;  
  2.   
  3. import it.sauronsoftware.base64.Base64;  
  4.   
  5. import java.io.BufferedReader;  
  6. import java.io.InputStream;  
  7. import java.io.InputStreamReader;  
  8. import java.io.UnsupportedEncodingException;  
  9. import java.net.HttpURLConnection;  
  10. import java.net.URL;  
  11. import java.net.URLEncoder;  
  12. import java.util.ArrayList;  
  13. import java.util.Collections;  
  14. import java.util.List;  
  15.   
  16. import net.sf.json.JSONObject;  
  17.   
  18. import org.dom4j.Document;  
  19. import org.dom4j.DocumentHelper;  
  20. import org.dom4j.Element;  
  21.   
  22. import com.coderdream.model.Article;  
  23. import com.coderdream.model.BaiduPlace;  
  24. import com.coderdream.model.UserLocation;  
  25.   
  26. /** 
  27.  * 百度地图操作类 javabase64-1.3.1.jar 
  28.  *  
  29.  */  
  30. public class BaiduMapUtil {  
  31.     /** 
  32.      * 圆形区域检索 
  33.      *  
  34.      * @param query 
  35.      *          检索关键词 
  36.      * @param lng 
  37.      *          经度 
  38.      * @param lat 
  39.      *          纬度 
  40.      * @return List<BaiduPlace> 
  41.      * @throws UnsupportedEncodingException 
  42.      */  
  43.     public static List<BaiduPlace> searchPlace(String query, String lng, String lat) throws Exception {  
  44.         // 拼装请求地址  
  45.         String requestUrl = "http://api.map.baidu.com/place/v2/search?&query=QUERY&location=LAT,LNG&radius=2000&output=xml&scope=2&page_size=10&page_num=0&ak=CA21bdecc75efc1664af5a195c30bb4e";  
  46.         requestUrl = requestUrl.replace("QUERY", URLEncoder.encode(query, "UTF-8"));  
  47.         requestUrl = requestUrl.replace("LAT", lat);  
  48.         requestUrl = requestUrl.replace("LNG", lng);  
  49.         // 调用Place API圆形区域检索  
  50.         String respXml = httpRequest(requestUrl);  
  51.         // 解析返回的xml  
  52.         List<BaiduPlace> placeList = parsePlaceXml(respXml);  
  53.         return placeList;  
  54.     }  
  55.   
  56.     /** 
  57.      * 发送http请求 
  58.      *  
  59.      * @param requestUrl 
  60.      *          请求地址 
  61.      * @return String 
  62.      */  
  63.     public static String httpRequest(String requestUrl) {  
  64.         StringBuffer buffer = new StringBuffer();  
  65.         try {  
  66.             URL url = new URL(requestUrl);  
  67.             HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();  
  68.             httpUrlConn.setDoInput(true);  
  69.             httpUrlConn.setRequestMethod("GET");  
  70.             httpUrlConn.connect();  
  71.   
  72.             // 将返回的输入流转换成字符串  
  73.             InputStream inputStream = httpUrlConn.getInputStream();  
  74.             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
  75.             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
  76.             String str = null;  
  77.             while ((str = bufferedReader.readLine()) != null) {  
  78.                 buffer.append(str);  
  79.             }  
  80.             bufferedReader.close();  
  81.             inputStreamReader.close();  
  82.             // 释放资源  
  83.             inputStream.close();  
  84.             inputStream = null;  
  85.             httpUrlConn.disconnect();  
  86.         } catch (Exception e) {  
  87.             e.printStackTrace();  
  88.         }  
  89.         return buffer.toString();  
  90.     }  
  91.   
  92.     /** 
  93.      * 根据百度地图返回的流解析出地址信息 
  94.      *  
  95.      * @param inputStream 
  96.      *          输入流 
  97.      * @return List<BaiduPlace> 
  98.      */  
  99.     @SuppressWarnings("unchecked")  
  100.     private static List<BaiduPlace> parsePlaceXml(String xml) {  
  101.         List<BaiduPlace> placeList = null;  
  102.         try {  
  103.             Document document = DocumentHelper.parseText(xml);  
  104.             // 得到xml根元素  
  105.             Element root = document.getRootElement();  
  106.             // 从根元素获取<results>  
  107.             Element resultsElement = root.element("results");  
  108.             // 从<results>中获取<result>集合  
  109.             List<Element> resultElementList = resultsElement.elements("result");  
  110.             // 判断<result>集合的大小  
  111.             if (resultElementList.size() > 0) {  
  112.                 placeList = new ArrayList<BaiduPlace>();  
  113.                 // POI名称  
  114.                 Element nameElement = null;  
  115.                 // POI地址信息  
  116.                 Element addressElement = null;  
  117.                 // POI经纬度坐标  
  118.                 Element locationElement = null;  
  119.                 // POI电话信息  
  120.                 Element telephoneElement = null;  
  121.                 // POI扩展信息  
  122.                 Element detailInfoElement = null;  
  123.                 // 距离中心点的距离  
  124.                 Element distanceElement = null;  
  125.                 // 遍历<result>集合  
  126.                 for (Element resultElement : resultElementList) {  
  127.                     nameElement = resultElement.element("name");  
  128.                     addressElement = resultElement.element("address");  
  129.                     locationElement = resultElement.element("location");  
  130.                     telephoneElement = resultElement.element("telephone");  
  131.                     detailInfoElement = resultElement.element("detail_info");  
  132.   
  133.                     BaiduPlace place = new BaiduPlace();  
  134.                     place.setName(nameElement.getText());  
  135.                     place.setAddress(addressElement.getText());  
  136.                     place.setLng(locationElement.element("lng").getText());  
  137.                     place.setLat(locationElement.element("lat").getText());  
  138.                     // 当<telephone>元素存在时获取电话号码  
  139.                     if (null != telephoneElement)  
  140.                         place.setTelephone(telephoneElement.getText());  
  141.                     // 当<detail_info>元素存在时获取<distance>  
  142.                     if (null != detailInfoElement) {  
  143.                         distanceElement = detailInfoElement.element("distance");  
  144.                         if (null != distanceElement)  
  145.                             place.setDistance(Integer.parseInt(distanceElement.getText()));  
  146.                     }  
  147.                     placeList.add(place);  
  148.                 }  
  149.                 // 按距离由近及远排序  
  150.                 Collections.sort(placeList);  
  151.             }  
  152.         } catch (Exception e) {  
  153.             e.printStackTrace();  
  154.         }  
  155.         return placeList;  
  156.     }  
  157.   
  158.     /** 
  159.      * 根据Place组装图文列表 
  160.      *  
  161.      * @param placeList 
  162.      * @param bd09Lng 
  163.      *          经度 
  164.      * @param bd09Lat 
  165.      *          纬度 
  166.      * @return List<Article> 
  167.      */  
  168.     public static List<Article> makeArticleList(List<BaiduPlace> placeList, String bd09Lng, String bd09Lat) {  
  169.         // 项目的根路径  
  170.         String basePath = "http://1.wxquan.sinaapp.com/";  
  171.         List<Article> list = new ArrayList<Article>();  
  172.         BaiduPlace place = null;  
  173.         for (int i = 0; i < placeList.size(); i++) {  
  174.             place = placeList.get(i);  
  175.             Article article = new Article();  
  176.             article.setTitle(place.getName() + "\n距离约" + place.getDistance() + "米");  
  177.             // P1表示用户发送的位置(坐标转换后),p2表示当前POI所在位置  
  178.             article.setUrl(String.format(basePath + "route.jsp?p1=%s,%s&p2=%s,%s", bd09Lng, bd09Lat, place.getLng(),  
  179.                     place.getLat()));  
  180.             // 将首条图文的图片设置为大图  
  181.             if (i == 0)  
  182.                 article.setPicUrl(basePath + "images/poisearch.png");  
  183.             else  
  184.                 article.setPicUrl(basePath + "images/navi.png");  
  185.             list.add(article);  
  186.         }  
  187.         return list;  
  188.     }  
  189.   
  190.     /** 
  191.      * 将微信定位的坐标转换成百度坐标(GCJ-02 -> Baidu) 
  192.      *  
  193.      * @param lng 
  194.      *          经度 
  195.      * @param lat 
  196.      *          纬度 
  197.      * @return UserLocation 
  198.      */  
  199.     public static UserLocation convertCoord(String lng, String lat) {  
  200.         // 百度坐标转换接口  
  201.         String convertUrl = "http://api.map.baidu.com/ag/coord/convert?from=2&to=4&x={x}&y={y}";  
  202.         convertUrl = convertUrl.replace("{x}", lng);  
  203.         convertUrl = convertUrl.replace("{y}", lat);  
  204.   
  205.         UserLocation location = new UserLocation();  
  206.         try {  
  207.             String jsonCoord = httpRequest(convertUrl);  
  208.             JSONObject jsonObject = JSONObject.fromObject(jsonCoord);  
  209.             // 对转换后的坐标进行Base64解码  
  210.             location.setBd09Lng(Base64.decode(jsonObject.getString("x"), "UTF-8"));  
  211.             location.setBd09Lat(Base64.decode(jsonObject.getString("y"), "UTF-8"));  
  212.         } catch (Exception e) {  
  213.             location = null;  
  214.             e.printStackTrace();  
  215.         }  
  216.         return location;  
  217.     }  
  218. }  

 

导航页面

route.jsp

Html代码   收藏代码
  1. <%@ page language="java" pageEncoding="UTF-8"%>  
  2. <%  
  3.     String path = request.getContextPath();  
  4.     String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
  5. %>  
  6. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  7. <html>  
  8. <head>  
  9.     <base href="<%=basePath%>">  
  10.     <title>步行导航</title>  
  11.     <meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=0;">  
  12.     <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />  
  13.     <style type="text/css">  
  14.         body, html,#allmap {width: 100%;height: 100%;overflow: hidden;margin:0;}  
  15.     </style>  
  16.     <script type="text/javascript" src="http://api.map.baidu.com/api?v=1.5&ak=CA21bdecc75efc1664af5a195c30bb4e"></script>  
  17. </head>  
  18. <%  
  19.     String p1 = request.getParameter("p1");  
  20.     String p2 = request.getParameter("p2");  
  21. %>  
  22. <body>  
  23.     <div id="allmap"></div>  
  24. </body>  
  25. <script type="text/javascript">  
  26.     // 创建起点、终点的经纬度坐标点  
  27.     var p1 = new BMap.Point(<%=p1%>);  
  28.     var p2 = new BMap.Point(<%=p2%>);  
  29.       
  30.     // 创建地图、设置中心坐标和默认缩放级别  
  31.     var map = new BMap.Map("allmap");  
  32.     map.centerAndZoom(new BMap.Point((p1.lng+p2.lng)/2, (p1.lat+p2.lat)/2), 17);  
  33.     // 右下角添加缩放按钮  
  34.     map.addControl(new BMap.NavigationControl({anchor: BMAP_ANCHOR_BOTTOM_RIGHT, type: BMAP_NAVIGATION_CONTROL_ZOOM}));  
  35.       
  36.     // 步行导航检索  
  37.     var walking = new BMap.WalkingRoute(map, {renderOptions:{map: map, autoViewport: true}});  
  38.     walking.search(p1, p2);  
  39. </script>  
  40. </html>  

 

核心服务类

更新代码后,能实现查找附近功能;

1)发送地理位置;

点击窗口底部的“+”按钮,选择“位置”,点“发送”

2)指定关键词搜索;

格式:附近+关键词\n例如:附近ATM、附近KTV、附近厕所。

CoreService.java

Java代码   收藏代码
  1. package com.coderdream.service;  
  2.   
  3. import java.io.InputStream;  
  4. import java.text.DateFormat;  
  5. import java.text.SimpleDateFormat;  
  6. import java.util.ArrayList;  
  7. import java.util.Calendar;  
  8. import java.util.Date;  
  9. import java.util.List;  
  10. import java.util.Map;  
  11.   
  12. import org.apache.log4j.Logger;  
  13.   
  14. import com.coderdream.bean.Logging;  
  15. import com.coderdream.dao.LoggingDao;  
  16. import com.coderdream.dao.UserLocationDao;  
  17. import com.coderdream.model.Article;  
  18. import com.coderdream.model.BaiduPlace;  
  19. import com.coderdream.model.Music;  
  20. import com.coderdream.model.MusicMessage;  
  21. import com.coderdream.model.NewsMessage;  
  22. import com.coderdream.model.TextMessage;  
  23. import com.coderdream.model.UserLocation;  
  24. import com.coderdream.util.BaiduMapUtil;  
  25. import com.coderdream.util.MessageUtil;  
  26.   
  27. /** 
  28.  * 核心服务类 
  29.  */  
  30. public class CoreService {  
  31.   
  32.     public static String TAG = "CoreService";  
  33.   
  34.     private Logger logger = Logger.getLogger(CoreService.class);  
  35.   
  36.     private LoggingDao loggingDao = new LoggingDao(this.getClass().getName());  
  37.   
  38.     private UserLocationDao userLocationDao = new UserLocationDao();  
  39.   
  40.     /** 
  41.      * 处理微信发来的请求 
  42.      *  
  43.      * @param request 
  44.      * @return xml 
  45.      */  
  46.     public String processRequest(InputStream inputStream) {  
  47.         logger.debug(TAG + " #1# processRequest");  
  48.         SimpleDateFormat f_timestamp = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");  
  49.         Logging logging = new Logging(f_timestamp.format(Calendar.getInstance().getTime()), "DEBUG", TAG,  
  50.                         "#1# processRequest");  
  51.         loggingDao.addLogging(logging);  
  52.         // xml格式的消息数据  
  53.         String respXml = null;  
  54.         // 默认返回的文本消息内容  
  55.         String respContent = "未知的消息类型!";  
  56.         try {  
  57.             // 调用parseXml方法解析请求消息  
  58.             Map<String, String> requestMap = MessageUtil.parseXml(inputStream);  
  59.             // 发送方帐号  
  60.             String fromUserName = requestMap.get("FromUserName");  
  61.             // 开发者微信号  
  62.             String toUserName = requestMap.get("ToUserName");  
  63.             // 消息类型  
  64.             String msgType = requestMap.get("MsgType");  
  65.             String logStr = "#2# fromUserName: " + fromUserName + ", toUserName: " + toUserName + ", msgType: "  
  66.                             + msgType;  
  67.             logger.debug(TAG + logStr);  
  68.             logging = new Logging(f_timestamp.format(Calendar.getInstance().getTime()), "DEBUG", TAG, logStr);  
  69.             loggingDao.addLogging(logging);  
  70.   
  71.             // 回复文本消息  
  72.             TextMessage textMessage = new TextMessage();  
  73.             textMessage.setToUserName(fromUserName);  
  74.             textMessage.setFromUserName(toUserName);  
  75.             textMessage.setCreateTime(new Date().getTime());  
  76.             textMessage.setMsgType(MessageUtil.MESSAGE_TYPE_TEXT);  
  77.             logStr = "#3# textMessage: " + textMessage.toString();  
  78.             logger.debug(TAG + logStr);  
  79.             logging = new Logging(f_timestamp.format(Calendar.getInstance().getTime()), "DEBUG", TAG, logStr);  
  80.             loggingDao.addLogging(logging);  
  81.   
  82.             // 文本消息  
  83.             if (msgType.equals(MessageUtil.MESSAGE_TYPE_TEXT)) {  
  84.                 // respContent = "您发送的是文本消息!";  
  85.   
  86.                 // 接收用户发送的文本消息内容  
  87.                 String content = requestMap.get("Content").trim();  
  88.   
  89.                 // 创建图文消息  
  90.                 NewsMessage newsMessage = new NewsMessage();  
  91.                 newsMessage.setToUserName(fromUserName);  
  92.                 newsMessage.setFromUserName(toUserName);  
  93.                 newsMessage.setCreateTime(new Date().getTime());  
  94.                 newsMessage.setMsgType(MessageUtil.MESSAGE_TYPE_NEWS);  
  95.                 newsMessage.setFuncFlag(0);  
  96.   
  97.                 List<Article> articleList = new ArrayList<Article>();  
  98.   
  99.                 // 翻译  
  100.                 if (content.startsWith("翻译")) {  
  101.                     String keyWord = content.replaceAll("^翻译""").trim();  
  102.                     if ("".equals(keyWord)) {  
  103.                         textMessage.setContent(getTranslateUsage());  
  104.                     } else {  
  105.                         textMessage.setContent(BaiduTranslateService.translate(keyWord));  
  106.                     }  
  107.                     respContent = textMessage.getContent();  
  108.                 }  
  109.                 // 如果以“歌曲”2个字开头  
  110.                 else if (content.startsWith("歌曲")) {  
  111.                     // 将歌曲2个字及歌曲后面的+、空格、-等特殊符号去掉  
  112.                     String keyWord = content.replaceAll("^歌曲[\\+ ~!@#%^-_=]?""");  
  113.                     // 如果歌曲名称为空  
  114.                     if ("".equals(keyWord)) {  
  115.                         logging = new Logging(f_timestamp.format(Calendar.getInstance().getTime()), "DEBUG", TAG,  
  116.                                         "#歌曲名称为空#");  
  117.                         loggingDao.addLogging(logging);  
  118.                         respContent = getMusicUsage();  
  119.                     } else {  
  120.                         String[] kwArr = keyWord.split("@");  
  121.                         // 歌曲名称  
  122.                         String musicTitle = kwArr[0];  
  123.                         // 演唱者默认为空  
  124.                         String musicAuthor = "";  
  125.                         if (2 == kwArr.length) {  
  126.                             musicAuthor = kwArr[1];  
  127.                         }  
  128.                         // 搜索音乐  
  129.                         Music music = BaiduMusicService.searchMusic(musicTitle, musicAuthor);  
  130.                         // 未搜索到音乐  
  131.                         if (null == music) {  
  132.                             respContent = "对不起,没有找到你想听的歌曲<" + musicTitle + ">。";  
  133.                             logging = new Logging(f_timestamp.format(Calendar.getInstance().getTime()), "DEBUG", TAG,  
  134.                                             "#未搜索到音乐 respContent# " + respContent);  
  135.                             loggingDao.addLogging(logging);  
  136.                         } else {  
  137.                             // 音乐消息  
  138.                             logger.info("找到 " + musicTitle + " 了!!!");  
  139.                             MusicMessage musicMessage = new MusicMessage();  
  140.                             musicMessage.setToUserName(fromUserName);  
  141.                             musicMessage.setFromUserName(toUserName);  
  142.                             musicMessage.setCreateTime(new Date().getTime());  
  143.                             musicMessage.setMsgType(MessageUtil.MESSAGE_TYPE_MUSIC);  
  144.                             musicMessage.setMusic(music);  
  145.                             newsMessage.setFuncFlag(0);  
  146.   
  147.                             respXml = MessageUtil.messageToXml(musicMessage);  
  148.                             logging = new Logging(f_timestamp.format(Calendar.getInstance().getTime()), "DEBUG", TAG,  
  149.                                             "#return respXml# " + respXml);  
  150.                             loggingDao.addLogging(logging);  
  151.                             return respXml;  
  152.                         }  
  153.                     }  
  154.                 }  
  155.                 // 如果以“历史”2个字开头  
  156.                 else if (content.startsWith("历史")) {  
  157.                     // 将歌曲2个字及歌曲后面的+、空格、-等特殊符号去掉  
  158.                     String dayStr = content.substring(2);  
  159.   
  160.                     // 如果只输入历史两个字,在输出当天的历史  
  161.                     if (null == dayStr || "".equals(dayStr.trim())) {  
  162.                         DateFormat df = new SimpleDateFormat("MMdd");  
  163.                         dayStr = df.format(Calendar.getInstance().getTime());  
  164.                     }  
  165.   
  166.                     respContent = TodayInHistoryService.getTodayInHistoryInfoFromDB(dayStr);  
  167.                 }  
  168.                 // 周边搜索  
  169.                 else if (content.startsWith("附近")) {  
  170.                     String keyWord = content.replaceAll("附近""").trim();  
  171.                     // 获取用户最后一次发送的地理位置  
  172.                     UserLocation location = userLocationDao.getLastLocation(fromUserName);  
  173.                     // 未获取到  
  174.                     if (null == location) {  
  175.                         respContent = getLocationUsage();  
  176.                     } else {  
  177.                         // 根据转换后(纠偏)的坐标搜索周边POI  
  178.                         List<BaiduPlace> placeList = BaiduMapUtil.searchPlace(keyWord, location.getBd09Lng(),  
  179.                                         location.getBd09Lat());  
  180.                         // 未搜索到POI  
  181.                         if (null == placeList || 0 == placeList.size()) {  
  182.                             respContent = String.format("/难过,您发送的位置附近未搜索到“%s”信息!", keyWord);  
  183.                         } else {  
  184.                             articleList = BaiduMapUtil.makeArticleList(placeList, location.getBd09Lng(),  
  185.                                             location.getBd09Lat());  
  186.                             // 回复图文消息  
  187.                             newsMessage = new NewsMessage();  
  188.                             newsMessage.setToUserName(fromUserName);  
  189.                             newsMessage.setFromUserName(toUserName);  
  190.                             newsMessage.setCreateTime(new Date().getTime());  
  191.                             newsMessage.setMsgType(MessageUtil.MESSAGE_TYPE_NEWS);  
  192.                             newsMessage.setArticles(articleList);  
  193.                             newsMessage.setArticleCount(articleList.size());  
  194.                             return MessageUtil.messageToXml(newsMessage);  
  195.                         }  
  196.                     }  
  197.                 }  
  198.                 // 单图文消息  
  199.                 else if ("1".equals(content)) {  
  200.                     Article article = new Article();  
  201.                     article.setTitle("微信公众帐号开发教程Java版");  
  202.                     article.setDescription("柳峰,80后,微信公众帐号开发经验4个月。为帮助初学者入门,特推出此系列教程,也希望借此机会认识更多同行!");  
  203.                     article.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");  
  204.                     article.setUrl("http://blog.csdn.net/lyq8479?toUserName=" + fromUserName + "&toUserName="  
  205.                                     + toUserName);  
  206.                     articleList.add(article);  
  207.                     // 设置图文消息个数  
  208.                     newsMessage.setArticleCount(articleList.size());  
  209.                     // 设置图文消息包含的图文集合  
  210.                     newsMessage.setArticles(articleList);  
  211.                     // 将图文消息对象转换成xml字符串  
  212.                     return MessageUtil.messageToXml(newsMessage);  
  213.                 }  
  214.                 // 单图文消息---不含图片  
  215.                 else if ("2".equals(content)) {  
  216.                     Article article = new Article();  
  217.                     article.setTitle("微信公众帐号开发教程Java版");  
  218.                     // 图文消息中可以使用QQ表情、符号表情  
  219.                     article.setDescription("柳峰,80后,"  
  220.                     // + emoji(0x1F6B9)  
  221.                                     + ",微信公众帐号开发经验4个月。为帮助初学者入门,特推出此系列连载教程,也希望借此机会认识更多同行!\n\n目前已推出教程共12篇,包括接口配置、消息封装、框架搭建、QQ表情发送、符号表情发送等。\n\n后期还计划推出一些实用功能的开发讲解,例如:天气预报、周边搜索、聊天功能等。");  
  222.                     // 将图片置为空  
  223.                     article.setPicUrl("");  
  224.                     article.setUrl("http://blog.csdn.net/lyq8479?toUserName=" + fromUserName + "&toUserName="  
  225.                                     + toUserName);  
  226.                     articleList.add(article);  
  227.                     newsMessage.setArticleCount(articleList.size());  
  228.                     newsMessage.setArticles(articleList);  
  229.                     return MessageUtil.messageToXml(newsMessage);  
  230.                 }  
  231.                 // 多图文消息  
  232.                 else if ("3".equals(content)) {  
  233.                     Article article1 = new Article();  
  234.                     article1.setTitle("微信公众帐号开发教程\n引言");  
  235.                     article1.setDescription("");  
  236.                     article1.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");  
  237.                     article1.setUrl("http://blog.csdn.net/lyq8479/article/details/8937622?toUserName=" + fromUserName  
  238.                                     + "&toUserName=" + toUserName);  
  239.   
  240.                     Article article2 = new Article();  
  241.                     article2.setTitle("第2篇\n微信公众帐号的类型");  
  242.                     article2.setDescription("");  
  243.                     article2.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");  
  244.                     article2.setUrl("http://blog.csdn.net/lyq8479/article/details/8941577?toUserName=" + fromUserName  
  245.                                     + "&toUserName=" + toUserName);  
  246.   
  247.                     Article article3 = new Article();  
  248.                     article3.setTitle("关注页面");  
  249.                     article3.setDescription("关注页面");  
  250.                     article3.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");  
  251.                     article3.setUrl("http://wxquan.sinaapp.com/follow.jsp?toUserName=" + fromUserName + "&toUserName="  
  252.                                     + toUserName);  
  253.   
  254.                     articleList.add(article1);  
  255.                     articleList.add(article2);  
  256.                     articleList.add(article3);  
  257.                     newsMessage.setArticleCount(articleList.size());  
  258.                     newsMessage.setArticles(articleList);  
  259.                     return MessageUtil.messageToXml(newsMessage);  
  260.                 }  
  261.                 // 多图文消息---首条消息不含图片  
  262.                 else if ("4".equals(content)) {  
  263.                     Article article1 = new Article();  
  264.                     article1.setTitle("微信公众帐号开发教程Java版");  
  265.                     article1.setDescription("");  
  266.                     // 将图片置为空  
  267.                     article1.setPicUrl("");  
  268.                     article1.setUrl("http://blog.csdn.net/lyq8479");  
  269.   
  270.                     Article article2 = new Article();  
  271.                     article2.setTitle("第4篇\n消息及消息处理工具的封装");  
  272.                     article2.setDescription("");  
  273.                     article2.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");  
  274.                     article2.setUrl("http://blog.csdn.net/lyq8479/article/details/8949088?toUserName=" + fromUserName  
  275.                                     + "&toUserName=" + toUserName);  
  276.   
  277.                     Article article3 = new Article();  
  278.                     article3.setTitle("第5篇\n各种消息的接收与响应");  
  279.                     article3.setDescription("");  
  280.                     article3.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");  
  281.                     article3.setUrl("http://blog.csdn.net/lyq8479/article/details/8952173?toUserName=" + fromUserName  
  282.                                     + "&toUserName=" + toUserName);  
  283.   
  284.                     Article article4 = new Article();  
  285.                     article4.setTitle("第6篇\n文本消息的内容长度限制揭秘");  
  286.                     article4.setDescription("");  
  287.                     article4.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");  
  288.                     article4.setUrl("http://blog.csdn.net/lyq8479/article/details/8967824?toUserName=" + fromUserName  
  289.                                     + "&toUserName=" + toUserName);  
  290.   
  291.                     articleList.add(article1);  
  292.                     articleList.add(article2);  
  293.                     articleList.add(article3);  
  294.                     articleList.add(article4);  
  295.                     newsMessage.setArticleCount(articleList.size());  
  296.                     newsMessage.setArticles(articleList);  
  297.                     return MessageUtil.messageToXml(newsMessage);  
  298.                 }  
  299.                 // 多图文消息---最后一条消息不含图片  
  300.                 else if ("5".equals(content)) {  
  301.                     Article article1 = new Article();  
  302.                     article1.setTitle("第7篇\n文本消息中换行符的使用");  
  303.                     article1.setDescription("");  
  304.                     article1.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");  
  305.                     article1.setUrl("http://blog.csdn.net/lyq8479/article/details/9141467?toUserName=" + fromUserName  
  306.                                     + "&toUserName=" + toUserName);  
  307.   
  308.                     Article article2 = new Article();  
  309.                     article2.setTitle("第8篇\n文本消息中使用网页超链接");  
  310.                     article2.setDescription("");  
  311.                     article2.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");  
  312.                     article2.setUrl("http://blog.csdn.net/lyq8479/article/details/9157455?toUserName=" + fromUserName  
  313.                                     + "&toUserName=" + toUserName);  
  314.   
  315.                     Article article3 = new Article();  
  316.                     article3.setTitle("如果觉得文章对你有所帮助,请通过博客留言或关注微信公众帐号xiaoqrobot来支持柳峰!");  
  317.                     article3.setDescription("");  
  318.                     // 将图片置为空  
  319.                     article3.setPicUrl("");  
  320.                     article3.setUrl("http://blog.csdn.net/lyq8479");  
  321.   
  322.                     articleList.add(article1);  
  323.                     articleList.add(article2);  
  324.                     articleList.add(article3);  
  325.                     newsMessage.setArticleCount(articleList.size());  
  326.                     newsMessage.setArticles(articleList);  
  327.                     return MessageUtil.messageToXml(newsMessage);  
  328.                 }  
  329.                 // 其他,弹出帮助信息  
  330.                 else {  
  331.                     respContent = getUsage();  
  332.                 }  
  333.             }  
  334.             // 图片消息  
  335.             else if (msgType.equals(MessageUtil.MESSAGE_TYPE_IMAGE)) {  
  336.                 respContent = "您发送的是图片消息!";  
  337.             }  
  338.             // 语音消息  
  339.             else if (msgType.equals(MessageUtil.MESSAGE_TYPE_VOICE)) {  
  340.                 respContent = "您发送的是语音消息!";  
  341.             }  
  342.             // 视频消息  
  343.             else if (msgType.equals(MessageUtil.MESSAGE_TYPE_VIDEO)) {  
  344.                 respContent = "您发送的是视频消息!";  
  345.             }  
  346.             // 地理位置消息  
  347.             else if (msgType.equals(MessageUtil.MESSAGE_TYPE_LOCATION)) {  
  348.                 respContent = "您发送的是地理位置消息!";  
  349.                 // 用户发送的经纬度  
  350.                 String lng = requestMap.get("Location_Y");  
  351.                 String lat = requestMap.get("Location_X");  
  352.                 // 坐标转换后的经纬度  
  353.                 String bd09Lng = null;  
  354.                 String bd09Lat = null;  
  355.                 // 调用接口转换坐标  
  356.                 UserLocation userLocation = BaiduMapUtil.convertCoord(lng, lat);  
  357.                 if (null != userLocation) {  
  358.                     bd09Lng = userLocation.getBd09Lng();  
  359.                     bd09Lat = userLocation.getBd09Lat();  
  360.                 }  
  361.                 logger.info("lng= " + lng + "; lat= " + lat);  
  362.                 logger.info("bd09Lng= " + bd09Lng + "; bd09Lat= " + bd09Lat);  
  363.   
  364.                 // 保存用户地理位置  
  365.                 int count = userLocationDao.saveUserLocation(fromUserName, lng, lat, bd09Lng, bd09Lat);  
  366.                 loggingDao.debug("fromUserName" + fromUserName + "lng= " + lng + "; lat= " + lat + "bd09Lng= "  
  367.                                 + bd09Lng + "; bd09Lat= " + bd09Lat + "count" + count);  
  368.   
  369.                 StringBuffer buffer = new StringBuffer();  
  370.                 buffer.append("[愉快]").append("成功接收您的位置!").append("\n\n");  
  371.                 buffer.append("您可以输入搜索关键词获取周边信息了,例如:").append("\n");  
  372.                 buffer.append("        附近ATM").append("\n");  
  373.                 buffer.append("        附近KTV").append("\n");  
  374.                 buffer.append("        附近厕所").append("\n");  
  375.                 buffer.append("必须以“附近”两个字开头!");  
  376.                 respContent = buffer.toString();  
  377.             }  
  378.             // 链接消息  
  379.             else if (msgType.equals(MessageUtil.MESSAGE_TYPE_LINK)) {  
  380.                 respContent = "您发送的是链接消息!";  
  381.             }  
  382.             // 事件推送  
  383.             else if (msgType.equals(MessageUtil.MESSAGE_TYPE_EVENT)) {  
  384.                 // 事件类型  
  385.                 String eventType = requestMap.get("Event");  
  386.                 // 关注  
  387.                 if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {  
  388.                     respContent = "谢谢您的关注!/n";  
  389.                     respContent += getSubscribeMsg();  
  390.                 }  
  391.                 // 取消关注  
  392.                 else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {  
  393.                     // TODO 取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复  
  394.                 }  
  395.                 // 扫描带参数二维码  
  396.                 else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {  
  397.                     // TODO 处理扫描带参数二维码事件  
  398.                 }  
  399.                 // 上报地理位置  
  400.                 else if (eventType.equals(MessageUtil.EVENT_TYPE_LOCATION)) {  
  401.                     // TODO 处理上报地理位置事件  
  402.                 }  
  403.                 // 自定义菜单  
  404.                 else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {  
  405.                     // TODO 处理菜单点击事件  
  406.                 }  
  407.             }  
  408.   
  409.             logStr = "#4# respContent: " + respContent;  
  410.             logger.debug(TAG + logStr);  
  411.             logging = new Logging(f_timestamp.format(Calendar.getInstance().getTime()), "DEBUG", TAG, logStr);  
  412.             loggingDao.addLogging(logging);  
  413.   
  414.             // 设置文本消息的内容  
  415.             textMessage.setContent(respContent);  
  416.             // 将文本消息对象转换成xml  
  417.             respXml = MessageUtil.messageToXml(textMessage);  
  418.             logStr = "#5# respXml: " + respXml;  
  419.             logger.debug(TAG + logStr);  
  420.             logging = new Logging(f_timestamp.format(Calendar.getInstance().getTime()), "DEBUG", TAG, logStr);  
  421.             loggingDao.addLogging(logging);  
  422.         } catch (Exception e) {  
  423.             e.printStackTrace();  
  424.         }  
  425.           
  426.         return respXml;  
  427.     }  
  428.   
  429.     /** 
  430.      * 翻译使用指南 
  431.      *  
  432.      * @return 
  433.      */  
  434.     public static String getTranslateUsage() {  
  435.         StringBuffer buffer = new StringBuffer();  
  436.         // buffer.append(XiaoqUtil.emoji(0xe148)).append("Q译通使用指南").append("\n\n");  
  437.         buffer.append("Q译通为用户提供专业的多语言翻译服务,目前支持以下翻译方向:").append("\n");  
  438.         buffer.append("    中 -> 英").append("\n");  
  439.         buffer.append("    英 -> 中").append("\n");  
  440.         buffer.append("    日 -> 中").append("\n\n");  
  441.         buffer.append("使用示例:").append("\n");  
  442.         buffer.append("    翻译我是中国人").append("\n");  
  443.         buffer.append("    翻译dream").append("\n");  
  444.         buffer.append("    翻译さようなら").append("\n\n");  
  445.         buffer.append("回复“?”显示主菜单");  
  446.         return buffer.toString();  
  447.     }  
  448.   
  449.     /** 
  450.      * 歌曲点播使用指南 
  451.      *  
  452.      * @return 
  453.      */  
  454.     public static String getMusicUsage() {  
  455.         StringBuffer buffer = new StringBuffer();  
  456.         buffer.append("歌曲点播操作指南").append("\n\n");  
  457.         buffer.append("回复:歌曲+歌名").append("\n");  
  458.         buffer.append("例如:歌曲存在").append("\n");  
  459.         buffer.append("或者:歌曲存在@汪峰").append("\n\n");  
  460.         buffer.append("回复“?”显示主菜单");  
  461.         return buffer.toString();  
  462.     }  
  463.   
  464.     /** 
  465.      * 歌曲点播使用指南 
  466.      *  
  467.      * @return 
  468.      */  
  469.     public static String getUsage() {  
  470.         StringBuffer buffer = new StringBuffer();  
  471.         buffer.append("历史年月(历史0403)").append("\n");  
  472.         buffer.append("歌曲歌名(歌曲)").append("\n");  
  473.         buffer.append("翻译词语(翻译明天)-支持中英日语").append("\n");  
  474.         buffer.append("回复“?”显示主菜单");  
  475.         return buffer.toString();  
  476.     }  
  477.   
  478.     /** 
  479.      * 关注提示语 
  480.      *  
  481.      * @return 
  482.      */  
  483.     public static String getSubscribeMsg() {  
  484.         StringBuffer buffer = new StringBuffer();  
  485.         buffer.append("您是否有过出门在外四处找ATM或厕所的经历?").append("\n\n");  
  486.         buffer.append("您是否有过出差在外搜寻美食或娱乐场所的经历?").append("\n\n");  
  487.         buffer.append("周边搜索为您的出行保驾护航,为您提供专业的周边生活指南,回复“附近”开始体验吧!");  
  488.         return buffer.toString();  
  489.     }  
  490.   
  491.     /** 
  492.      * 使用说明 
  493.      *  
  494.      * @return 
  495.      */  
  496.     public static String getLocationUsage() {  
  497.         StringBuffer buffer = new StringBuffer();  
  498.         buffer.append("周边搜索使用说明").append("\n\n");  
  499.         buffer.append("1)发送地理位置").append("\n");  
  500.         buffer.append("点击窗口底部的“+”按钮,选择“位置”,点“发送”").append("\n\n");  
  501.         buffer.append("2)指定关键词搜索").append("\n");  
  502.         buffer.append("格式:附近+关键词\n例如:附近ATM、附近KTV、附近厕所");  
  503.         return buffer.toString();  
  504.     }  
  505. }  

 

消息处理工具类

MessageUtil.java

Java代码   收藏代码
  1. package com.coderdream.util;  
  2.   
  3. import java.io.InputStream;  
  4. import java.io.Writer;  
  5. import java.util.HashMap;  
  6. import java.util.List;  
  7. import java.util.Map;  
  8.   
  9. import org.apache.log4j.Logger;  
  10. import org.dom4j.Document;  
  11. import org.dom4j.Element;  
  12. import org.dom4j.io.SAXReader;  
  13.   
  14. import com.coderdream.model.Article;  
  15. import com.coderdream.model.MusicMessage;  
  16. import com.coderdream.model.NewsMessage;  
  17. import com.coderdream.model.TextMessage;  
  18. import com.thoughtworks.xstream.XStream;  
  19. import com.thoughtworks.xstream.core.util.QuickWriter;  
  20. import com.thoughtworks.xstream.io.HierarchicalStreamWriter;  
  21. import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;  
  22. import com.thoughtworks.xstream.io.xml.XppDriver;  
  23.   
  24. /** 
  25.  * 消息处理工具类 
  26.  *  
  27.  */  
  28. public class MessageUtil {  
  29.   
  30.     public static String TAG = "MessageUtil";  
  31.   
  32.     private static Logger logger = Logger.getLogger(MessageUtil.class);  
  33.   
  34.     /** 
  35.      * 请求消息类型:文本 
  36.      */  
  37.     public static final String MESSAGE_TYPE_TEXT = "text";  
  38.   
  39.     /** 
  40.      * 请求消息类型:图片 
  41.      */  
  42.     public static final String MESSAGE_TYPE_IMAGE = "image";  
  43.   
  44.     /** 
  45.      * 请求消息类型:语音 
  46.      */  
  47.     public static final String MESSAGE_TYPE_VOICE = "voice";  
  48.   
  49.     /** 
  50.      * 请求消息类型:视频 
  51.      */  
  52.     public static final String MESSAGE_TYPE_VIDEO = "video";  
  53.   
  54.     /** 
  55.      * 请求消息类型:地理位置 
  56.      */  
  57.     public static final String MESSAGE_TYPE_LOCATION = "location";  
  58.   
  59.     /** 
  60.      * 请求消息类型:链接 
  61.      */  
  62.     public static final String MESSAGE_TYPE_LINK = "link";  
  63.   
  64.     /** 
  65.      * 请求消息类型:事件推送 
  66.      */  
  67.     public static final String MESSAGE_TYPE_EVENT = "event";  
  68.   
  69.     /** 
  70.      * 事件类型:subscribe(订阅) 
  71.      */  
  72.     public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";  
  73.   
  74.     /** 
  75.      * 事件类型:unsubscribe(取消订阅) 
  76.      */  
  77.     public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";  
  78.   
  79.     /** 
  80.      * 事件类型:scan(用户已关注时的扫描带参数二维码) 
  81.      */  
  82.     public static final String EVENT_TYPE_SCAN = "scan";  
  83.   
  84.     /** 
  85.      * 事件类型:LOCATION(上报地理位置) 
  86.      */  
  87.     public static final String EVENT_TYPE_LOCATION = "LOCATION";  
  88.   
  89.     /** 
  90.      * 事件类型:CLICK(自定义菜单) 
  91.      */  
  92.     public static final String EVENT_TYPE_CLICK = "CLICK";  
  93.     /** 
  94.      * 响应消息类型:图文 
  95.      */  
  96.     public static final String MESSAGE_TYPE_NEWS = "news";  
  97.   
  98.     /** 
  99.      * 响应消息类型:音乐 
  100.      */  
  101.     public static final String MESSAGE_TYPE_MUSIC = "music";  
  102.   
  103.     /** 
  104.      * 解析微信发来的请求(XML) 
  105.      *  
  106.      * @param request 
  107.      * @return Map<String, String> 
  108.      * @throws Exception 
  109.      */  
  110.     @SuppressWarnings("unchecked")  
  111.     public static Map<String, String> parseXml(InputStream inputStream) throws Exception {  
  112.         // 将解析结果存储在HashMap中  
  113.         Map<String, String> map = new HashMap<String, String>();  
  114.         logger.debug(TAG + " begin");  
  115.         // 从request中取得输入流  
  116.         // InputStream inputStream = request.getInputStream();  
  117.         // 读取输入流  
  118.         SAXReader reader = new SAXReader();  
  119.         Document document = reader.read(inputStream);  
  120.         logger.debug(TAG + " read inputStream");  
  121.         // 得到xml根元素  
  122.         Element root = document.getRootElement();  
  123.         // 得到根元素的所有子节点  
  124.         List<Element> elementList = root.elements();  
  125.         // 遍历所有子节点  
  126.         for (Element e : elementList) {  
  127.             map.put(e.getName(), e.getText());  
  128.             logger.debug(TAG + " ###### log4j debug" + e.getName() + " : " + e.getText());  
  129.         }  
  130.   
  131.         // 释放资源  
  132.         inputStream.close();  
  133.         inputStream = null;  
  134.   
  135.         return map;  
  136.     }  
  137.   
  138.     /** 
  139.      * 扩展xstream使其支持CDATA 
  140.      */  
  141.     private static XStream xstream = new XStream(new XppDriver() {  
  142.         public HierarchicalStreamWriter createWriter(Writer out) {  
  143.             return new PrettyPrintWriter(out) {  
  144.                 // 对所有xml节点的转换都增加CDATA标记  
  145.                 boolean cdata = true;  
  146.   
  147.                 @SuppressWarnings("rawtypes")  
  148.                 public void startNode(String name, Class clazz) {  
  149.                     super.startNode(name, clazz);  
  150.                 }  
  151.   
  152.                 protected void writeText(QuickWriter writer, String text) {  
  153.                     if (cdata) {  
  154.                         writer.write("<![CDATA[");  
  155.                         writer.write(text);  
  156.                         writer.write("]]>");  
  157.                     } else {  
  158.                         writer.write(text);  
  159.                     }  
  160.                 }  
  161.             };  
  162.         }  
  163.     });  
  164.   
  165.     /** 
  166.      * 文本消息对象转换成xml 
  167.      *  
  168.      * @param textMessage 
  169.      *            文本消息对象 
  170.      * @return xml 
  171.      */  
  172.     public static String messageToXml(TextMessage textMessage) {  
  173.         xstream.alias("xml", textMessage.getClass());  
  174.         return xstream.toXML(textMessage);  
  175.     }  
  176.   
  177.     /** 
  178.      * 图文消息对象转换成xml 
  179.      *  
  180.      * @param newsMessage 
  181.      *            图文消息对象 
  182.      * @return xml 
  183.      */  
  184.     public static String messageToXml(NewsMessage newsMessage) {  
  185.         xstream.alias("xml", newsMessage.getClass());  
  186.         xstream.alias("item"new Article().getClass());  
  187.         return xstream.toXML(newsMessage);  
  188.     }  
  189.       
  190.     /** 
  191.      * 音乐消息对象转换成xml 
  192.      *  
  193.      * @param musicMessage 
  194.      *          音乐消息对象 
  195.      * @return xml 
  196.      */  
  197.     public static String messageToXml(MusicMessage musicMessage) {  
  198.         xstream.alias("xml", musicMessage.getClass());  
  199.         String musicString = xstream.toXML(musicMessage);  
  200.   
  201.         return musicString;  
  202.     }  
  203.   
  204. }  

 

Maven工程配置文件

pom.xml

Xml代码   收藏代码
  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.     <groupId>com.coderdream</groupId>  
  5.     <artifactId>wxquan</artifactId>  
  6.     <packaging>war</packaging>  
  7.     <version>0.0.1-SNAPSHOT</version>  
  8.     <name>wxquan Maven Webapp</name>  
  9.     <url>http://maven.apache.org</url>  
  10.   
  11.     <properties>  
  12.         <junit.version>4.11</junit.version>  
  13.         <servlet.api.version>2.5</servlet.api.version>  
  14.         <jsp.api.version>2.1</jsp.api.version>  
  15.         <slf4j.version>1.7.5</slf4j.version>  
  16.         <dom4j.version>1.6.1</dom4j.version>  
  17.         <xstream.version>1.4.7</xstream.version>  
  18.         <mysql.version>5.1.17</mysql.version>  
  19.         <dbunit.version>2.4.9</dbunit.version>  
  20.         <gson.version>2.2.4</gson.version>  
  21.         <json.version>2.4</json.version>  
  22.         <javabase.version>1.3.1</javabase.version>  
  23.     </properties>  
  24.   
  25.     <dependencies>  
  26.         <!-- 测试的时候用到,打包的时候没有 -->  
  27.         <dependency>  
  28.             <groupId>junit</groupId>  
  29.             <artifactId>junit</artifactId>  
  30.             <version>${junit.version}</version>  
  31.             <scope>test</scope>  
  32.         </dependency>  
  33.   
  34.         <!-- 编译的时候用到,打包的时候没有 -->  
  35.         <dependency>  
  36.             <groupId>javax.servlet</groupId>  
  37.             <artifactId>servlet-api</artifactId>  
  38.             <version>${servlet.api.version}</version>  
  39.             <scope>provided</scope>  
  40.         </dependency>  
  41.   
  42.         <!-- 编译的时候用到,打包的时候没有 -->  
  43.         <dependency>  
  44.             <groupId>javax.servlet.jsp</groupId>  
  45.             <artifactId>jsp-api</artifactId>  
  46.             <version>${jsp.api.version}</version>  
  47.             <scope>provided</scope>  
  48.         </dependency>  
  49.   
  50.         <!-- 日志包 -->  
  51.         <dependency>  
  52.             <groupId>org.slf4j</groupId>  
  53.             <artifactId>slf4j-log4j12</artifactId>  
  54.             <version>${slf4j.version}</version>  
  55.         </dependency>  
  56.   
  57.         <!-- 打包的时候剔除 xml-apis-1.0.b2.jar SAE中不支持 -->  
  58.         <dependency>  
  59.             <groupId>dom4j</groupId>  
  60.             <artifactId>dom4j</artifactId>  
  61.             <version>${dom4j.version}</version>  
  62.             <exclusions>  
  63.                 <exclusion>  
  64.                     <groupId>xml-apis</groupId>  
  65.                     <artifactId>xml-apis</artifactId>  
  66.                 </exclusion>  
  67.             </exclusions>  
  68.         </dependency>  
  69.   
  70.         <!-- 打包的时候剔除 xml-apis-1.0.b2.jar SAE中不支持 -->  
  71.         <!-- 这个jar必须用1.4.7的高版本,否则SAE不支持 -->  
  72.         <!-- 详细原因:http://blog.csdn.net/lyq8479/article/details/38878543 -->  
  73.         <dependency>  
  74.             <groupId>com.thoughtworks.xstream</groupId>  
  75.             <artifactId>xstream</artifactId>  
  76.             <version>${xstream.version}</version>  
  77.         </dependency>  
  78.   
  79.         <!-- 编译的时候用到,打包的时候没有,SAE已包含此jar -->  
  80.         <dependency>  
  81.             <groupId>mysql</groupId>  
  82.             <artifactId>mysql-connector-java</artifactId>  
  83.             <version>${mysql.version}</version>  
  84.             <scope>provided</scope>  
  85.         </dependency>  
  86.   
  87.         <!-- 测试的时候用到,打包的后WAR里没有 -->  
  88.         <dependency>  
  89.             <groupId>org.dbunit</groupId>  
  90.             <artifactId>dbunit</artifactId>  
  91.             <version>${dbunit.version}</version>  
  92.             <scope>test</scope>  
  93.         </dependency>  
  94.   
  95.         <dependency>  
  96.             <groupId>com.google.code.gson</groupId>  
  97.             <artifactId>gson</artifactId>  
  98.             <version>${gson.version}</version>  
  99.         </dependency>  
  100.           
  101.         <dependency>  
  102.             <groupId>net.sf.json-lib</groupId>  
  103.             <artifactId>json-lib</artifactId>  
  104.             <version>${json.version}</version>  
  105.         </dependency>  
  106.   
  107.         <dependency>  
  108.             <groupId>it.sauronsoftware</groupId>  
  109.             <artifactId>javabase64</artifactId>  
  110.             <version>${javabase.version}</version>  
  111.         </dependency>       
  112.   
  113.     </dependencies>  
  114.     <build>  
  115.         <finalName>wxquan</finalName>  
  116.     </build>  
  117. </project>  

 

 

上传本地代码到GitHub

将新增和修改过的代码上传到GitHub


 

上传工程WAR档至SAE

将eclipse中的工程导出为wxquan.war档,上传到SAE中,更新已有的版本。

 

微信客户端测试

 登录微信网页版:https://wx.qq.com/

 先提交位置信息,然后输入“附近咖啡厅”,返回附近咖啡厅的图文信息。


 
 

 

参考文档

  1.  

 

完整源代码

  • 大小: 27.9 KB
  • 大小: 55.6 KB
  • 大小: 144.8 KB

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值