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

2023-11-22 01:40

本文主要是介绍微信公众平台开发实战(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
  • wxquan.V08.7z (268.4 KB)
  • 下载次数: 55

这篇关于微信公众平台开发实战(08) 基于地理信息的服务(LBS)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/406577

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof