微信公众平台java开发详解(工程代码+解析)

说明:
本次的教程主要是对微信公众平台开发者模式的讲解,网络上很多类似文章,但很多都让初学微信开发的人一头雾水,所以总结自己的微信开发经验,将微信开发的整个过程系统的列出,并对主要代码进行讲解分析,让初学者尽快上手。

在阅读本文之前,应对微信公众平台的官方开发文档有所了解,知道接收和发送的都是xml格式的数据。另外,在做内容回复时用到了捷微JEEWX这是一个自然语言解析的开放平台,可以帮我们解决整个微信开发过程中最困难的问题,此处不多讲,下面会有其详细的调用方式。


1.1 在登录微信官方平台之后,开启开发者模式,此时需要我们填写url和token,所谓url就是我们自己服务器的接口,用WechatServlet.java来实现,相关解释已经在注释中说明,代码如下:

[java] view plain copy
  1. packagedemo.servlet;
  2. importjava.io.BufferedReader;
  3. importjava.io.IOException;
  4. importjava.io.InputStream;
  5. importjava.io.InputStreamReader;
  6. importjava.io.OutputStream;
  7. importjavax.servlet.ServletException;
  8. importjavax.servlet.http.HttpServlet;
  9. importjavax.servlet.http.HttpServletRequest;
  10. importjavax.servlet.http.HttpServletResponse;
  11. importdemo.process.WechatProcess;
  12. /**
  13. *微信服务端收发消息接口
  14. *
  15. *@authorpamchen-1
  16. *
  17. */
  18. publicclassWechatServletextendsHttpServlet{
  19. /**
  20. *ThedoGetmethodoftheservlet.<br>
  21. *
  22. *Thismethodiscalledwhenaformhasitstagvaluemethodequalstoget.
  23. *
  24. *@paramrequest
  25. *therequestsendbytheclienttotheserver
  26. *@paramresponse
  27. *theresponsesendbytheservertotheclient
  28. *@throwsServletException
  29. *ifanerroroccurred
  30. *@throwsIOException
  31. *ifanerroroccurred
  32. */
  33. publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
  34. throwsServletException,IOException{
  35. request.setCharacterEncoding("UTF-8");
  36. response.setCharacterEncoding("UTF-8");
  37. /**读取接收到的xml消息*/
  38. StringBuffersb=newStringBuffer();
  39. InputStreamis=request.getInputStream();
  40. InputStreamReaderisr=newInputStreamReader(is,"UTF-8");
  41. BufferedReaderbr=newBufferedReader(isr);
  42. Strings="";
  43. while((s=br.readLine())!=null){
  44. sb.append(s);
  45. }
  46. Stringxml=sb.toString();//次即为接收到微信端发送过来的xml数据
  47. Stringresult="";
  48. /**判断是否是微信接入激活验证,只有首次接入验证时才会收到echostr参数,此时需要把它直接返回*/
  49. Stringechostr=request.getParameter("echostr");
  50. if(echostr!=null&&echostr.length()>1){
  51. result=echostr;
  52. }else{
  53. //正常的微信处理流程
  54. result=newWechatProcess().processWechatMag(xml);
  55. }
  56. try{
  57. OutputStreamos=response.getOutputStream();
  58. os.write(result.getBytes("UTF-8"));
  59. os.flush();
  60. os.close();
  61. }catch(Exceptione){
  62. e.printStackTrace();
  63. }
  64. }
  65. /**
  66. *ThedoPostmethodoftheservlet.<br>
  67. *
  68. *Thismethodiscalledwhenaformhasitstagvaluemethodequalsto
  69. *post.
  70. *
  71. *@paramrequest
  72. *therequestsendbytheclienttotheserver
  73. *@paramresponse
  74. *theresponsesendbytheservertotheclient
  75. *@throwsServletException
  76. *ifanerroroccurred
  77. *@throwsIOException
  78. *ifanerroroccurred
  79. */
  80. publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
  81. throwsServletException,IOException{
  82. doGet(request,response);
  83. }
  84. }

1.2 相应的web.xml配置信息如下,在生成WechatServlet.java的同时,可自动生成web.xml中的配置。前面所提到的url处可以填写例如:http;//服务器地址/项目名/wechat.do

[html] view plain copy
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <web-appversion="2.5"
  3. xmlns="http://java.sun.com/xml/ns/javaee"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
  6. http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  7. <servlet>
  8. <description>ThisisthedescriptionofmyJ2EEcomponent</description>
  9. <display-name>ThisisthedisplaynameofmyJ2EEcomponent</display-name>
  10. <servlet-name>WechatServlet</servlet-name>
  11. <servlet-class>demo.servlet.WechatServlet</servlet-class>
  12. </servlet>
  13. <servlet-mapping>
  14. <servlet-name>WechatServlet</servlet-name>
  15. <url-pattern>/wechat.do</url-pattern>
  16. </servlet-mapping>
  17. <welcome-file-list>
  18. <welcome-file>index.jsp</welcome-file>
  19. </welcome-file-list>
  20. </web-app>

1.3 通过以上代码,我们已经实现了微信公众平台开发的框架,即开通开发者模式并成功接入、接收消息和发送消息这三个步骤。


下面就讲解其核心部分——解析接收到的xml数据,并以文本类消息为例,通过图灵机器人api接口实现智能回复。


2.1 首先看一下整体流程处理代码,包括:xml数据处理、调用图灵api、封装返回的xml数据。
[java] view plain copy
  1. packagedemo.process;
  2. importjava.util.Date;
  3. importdemo.entity.ReceiveXmlEntity;
  4. /**
  5. *微信xml消息处理流程逻辑类
  6. *@authorpamchen-1
  7. *
  8. */
  9. publicclassWechatProcess{
  10. /**
  11. *解析处理xml、获取智能回复结果(通过图灵机器人api接口)
  12. *@paramxml接收到的微信数据
  13. *@return最终的解析结果(xml格式数据)
  14. */
  15. publicStringprocessWechatMag(Stringxml){
  16. /**解析xml数据*/
  17. ReceiveXmlEntityxmlEntity=newReceiveXmlProcess().getMsgEntity(xml);
  18. /**以文本消息为例,调用图灵机器人api接口,获取回复内容*/
  19. Stringresult="";
  20. if("text".endsWith(xmlEntity.getMsgType())){
  21. result=newTulingApiProcess().getTulingResult(xmlEntity.getContent());
  22. }
  23. /**此时,如果用户输入的是“你好”,在经过上面的过程之后,result为“你也好”类似的内容
  24. *因为最终回复给微信的也是xml格式的数据,所有需要将其封装为文本类型返回消息
  25. **/
  26. result=newFormatXmlProcess().formatXmlAnswer(xmlEntity.getFromUserName(),xmlEntity.getToUserName(),result);
  27. returnresult;
  28. }
  29. }

2.2 解析接收到的xml数据,此处有两个类,ReceiveXmlEntity.java和ReceiveXmlProcess.java,通过反射的机制动态调用实体类中的set方法,可以避免很多重复的判断,提高代码效率,代码如下:

[java] view plain copy
  1. packagedemo.entity;
  2. /**
  3. *接收到的微信xml实体类
  4. *@authorpamchen-1
  5. *
  6. */
  7. publicclassReceiveXmlEntity{
  8. privateStringToUserName="";
  9. privateStringFromUserName="";
  10. privateStringCreateTime="";
  11. privateStringMsgType="";
  12. privateStringMsgId="";
  13. privateStringEvent="";
  14. privateStringEventKey="";
  15. privateStringTicket="";
  16. privateStringLatitude="";
  17. privateStringLongitude="";
  18. privateStringPrecision="";
  19. privateStringPicUrl="";
  20. privateStringMediaId="";
  21. privateStringTitle="";
  22. privateStringDescription="";
  23. privateStringUrl="";
  24. privateStringLocation_X="";
  25. privateStringLocation_Y="";
  26. privateStringScale="";
  27. privateStringLabel="";
  28. privateStringContent="";
  29. privateStringFormat="";
  30. privateStringRecognition="";
  31. publicStringgetRecognition(){
  32. returnRecognition;
  33. }
  34. publicvoidsetRecognition(Stringrecognition){
  35. Recognition=recognition;
  36. }
  37. publicStringgetFormat(){
  38. returnFormat;
  39. }
  40. publicvoidsetFormat(Stringformat){
  41. Format=format;
  42. }
  43. publicStringgetContent(){
  44. returnContent;
  45. }
  46. publicvoidsetContent(Stringcontent){
  47. Content=content;
  48. }
  49. publicStringgetLocation_X(){
  50. returnLocation_X;
  51. }
  52. publicvoidsetLocation_X(StringlocationX){
  53. Location_X=locationX;
  54. }
  55. publicStringgetLocation_Y(){
  56. returnLocation_Y;
  57. }
  58. publicvoidsetLocation_Y(StringlocationY){
  59. Location_Y=locationY;
  60. }
  61. publicStringgetScale(){
  62. returnScale;
  63. }
  64. publicvoidsetScale(Stringscale){
  65. Scale=scale;
  66. }
  67. publicStringgetLabel(){
  68. returnLabel;
  69. }
  70. publicvoidsetLabel(Stringlabel){
  71. Label=label;
  72. }
  73. publicStringgetTitle(){
  74. returnTitle;
  75. }
  76. publicvoidsetTitle(Stringtitle){
  77. Title=title;
  78. }
  79. publicStringgetDescription(){
  80. returnDescription;
  81. }
  82. publicvoidsetDescription(Stringdescription){
  83. Description=description;
  84. }
  85. publicStringgetUrl(){
  86. returnUrl;
  87. }
  88. publicvoidsetUrl(Stringurl){
  89. Url=url;
  90. }
  91. publicStringgetPicUrl(){
  92. returnPicUrl;
  93. }
  94. publicvoidsetPicUrl(StringpicUrl){
  95. PicUrl=picUrl;
  96. }
  97. publicStringgetMediaId(){
  98. returnMediaId;
  99. }
  100. publicvoidsetMediaId(StringmediaId){
  101. MediaId=mediaId;
  102. }
  103. publicStringgetEventKey(){
  104. returnEventKey;
  105. }
  106. publicvoidsetEventKey(StringeventKey){
  107. EventKey=eventKey;
  108. }
  109. publicStringgetTicket(){
  110. returnTicket;
  111. }
  112. publicvoidsetTicket(Stringticket){
  113. Ticket=ticket;
  114. }
  115. publicStringgetLatitude(){
  116. returnLatitude;
  117. }
  118. publicvoidsetLatitude(Stringlatitude){
  119. Latitude=latitude;
  120. }
  121. publicStringgetLongitude(){
  122. returnLongitude;
  123. }
  124. publicvoidsetLongitude(Stringlongitude){
  125. Longitude=longitude;
  126. }
  127. publicStringgetPrecision(){
  128. returnPrecision;
  129. }
  130. publicvoidsetPrecision(Stringprecision){
  131. Precision=precision;
  132. }
  133. publicStringgetEvent(){
  134. returnEvent;
  135. }
  136. publicvoidsetEvent(Stringevent){
  137. Event=event;
  138. }
  139. publicStringgetMsgId(){
  140. returnMsgId;
  141. }
  142. publicvoidsetMsgId(StringmsgId){
  143. MsgId=msgId;
  144. }
  145. publicStringgetToUserName(){
  146. returnToUserName;
  147. }
  148. publicvoidsetToUserName(StringtoUserName){
  149. ToUserName=toUserName;
  150. }
  151. publicStringgetFromUserName(){
  152. returnFromUserName;
  153. }
  154. publicvoidsetFromUserName(StringfromUserName){
  155. FromUserName=fromUserName;
  156. }
  157. publicStringgetCreateTime(){
  158. returnCreateTime;
  159. }
  160. publicvoidsetCreateTime(StringcreateTime){
  161. CreateTime=createTime;
  162. }
  163. publicStringgetMsgType(){
  164. returnMsgType;
  165. }
  166. publicvoidsetMsgType(StringmsgType){
  167. MsgType=msgType;
  168. }
  169. }

[java] view plain copy
  1. packagedemo.process;
  2. importjava.lang.reflect.Field;
  3. importjava.lang.reflect.Method;
  4. importjava.util.Iterator;
  5. importorg.dom4j.Document;
  6. importorg.dom4j.DocumentHelper;
  7. importorg.dom4j.Element;
  8. importdemo.entity.ReceiveXmlEntity;
  9. /**
  10. *解析接收到的微信xml,返回消息对象
  11. *@authorpamchen-1
  12. *
  13. */
  14. publicclassReceiveXmlProcess{
  15. /**
  16. *解析微信xml消息
  17. *@paramstrXml
  18. *@return
  19. */
  20. publicReceiveXmlEntitygetMsgEntity(StringstrXml){
  21. ReceiveXmlEntitymsg=null;
  22. try{
  23. if(strXml.length()<=0||strXml==null)
  24. returnnull;
  25. //将字符串转化为XML文档对象
  26. Documentdocument=DocumentHelper.parseText(strXml);
  27. //获得文档的根节点
  28. Elementroot=document.getRootElement();
  29. //遍历根节点下所有子节点
  30. Iterator<?>iter=root.elementIterator();
  31. //遍历所有结点
  32. msg=newReceiveXmlEntity();
  33. //利用反射机制,调用set方法
  34. //获取该实体的元类型
  35. Class<?>c=Class.forName("demo.entity.ReceiveXmlEntity");
  36. msg=(ReceiveXmlEntity)c.newInstance();//创建这个实体的对象
  37. while(iter.hasNext()){
  38. Elementele=(Element)iter.next();
  39. //获取set方法中的参数字段(实体类的属性)
  40. Fieldfield=c.getDeclaredField(ele.getName());
  41. //获取set方法,field.getType())获取它的参数数据类型
  42. Methodmethod=c.getDeclaredMethod("set"+ele.getName(),field.getType());
  43. //调用set方法
  44. method.invoke(msg,ele.getText());
  45. }
  46. }catch(Exceptione){
  47. //TODO:handleexception
  48. System.out.println("xml格式异常:"+strXml);
  49. e.printStackTrace();
  50. }
  51. returnmsg;
  52. }
  53. }

2.3调用捷微JEEWXapi接口,获取智能回复内容

[java] view plain copy
  1. packagedemo.process;
  2. importjava.io.IOException;
  3. importjava.io.UnsupportedEncodingException;
  4. importjava.net.URLEncoder;
  5. importorg.apache.http.HttpResponse;
  6. importorg.apache.http.client.ClientProtocolException;
  7. importorg.apache.http.client.methods.HttpGet;
  8. importorg.apache.http.impl.client.HttpClients;
  9. importorg.apache.http.util.EntityUtils;
  10. importorg.json.JSONException;
  11. importorg.json.JSONObject;
  12. /**
  13. *调用图灵机器人api接口,获取智能回复内容
  14. *@authorpamchen-1
  15. *
  16. */
  17. publicclassTulingApiProcess{
  18. /**
  19. *调用图灵机器人api接口,获取智能回复内容,解析获取自己所需结果
  20. *@paramcontent
  21. *@return
  22. */
  23. publicStringgetTulingResult(Stringcontent){
  24. /**此处为图灵api接口,参数key需要自己去注册申请,先以11111111代替*/
  25. StringapiUrl="http://www.tuling123.com/openapi/api?key=11111111&info=";
  26. Stringparam="";
  27. try{
  28. param=apiUrl+URLEncoder.encode(content,"utf-8");
  29. }catch(UnsupportedEncodingExceptione1){
  30. //TODOAuto-generatedcatchblock
  31. e1.printStackTrace();
  32. }//将参数转为url编码
  33. /**发送httpget请求*/
  34. HttpGetrequest=newHttpGet(param);
  35. Stringresult="";
  36. try{
  37. HttpResponseresponse=HttpClients.createDefault().execute(request);
  38. if(response.getStatusLine().getStatusCode()==200){
  39. result=EntityUtils.toString(response.getEntity());
  40. }
  41. }catch(ClientProtocolExceptione){
  42. e.printStackTrace();
  43. }catch(IOExceptione){
  44. e.printStackTrace();
  45. }
  46. /**请求失败处理*/
  47. if(null==result){
  48. return"对不起,你说的话真是太高深了……";
  49. }
  50. try{
  51. JSONObjectjson=newJSONObject(result);
  52. //以code=100000为例,参考图灵机器人api文档
  53. if(100000==json.getInt("code")){
  54. result=json.getString("text");
  55. }
  56. }catch(JSONExceptione){
  57. //TODOAuto-generatedcatchblock
  58. e.printStackTrace();
  59. }
  60. returnresult;
  61. }
  62. }

2.4 将结果封装为微信规定的xml格式,并返回给1.1中创建的servlet接口。

[java] view plain copy
  1. packagedemo.process;
  2. importjava.util.Date;
  3. /**
  4. *封装最终的xml格式结果
  5. *@authorpamchen-1
  6. *
  7. */
  8. publicclassFormatXmlProcess{
  9. /**
  10. *封装文字类的返回消息
  11. *@paramto
  12. *@paramfrom
  13. *@paramcontent
  14. *@return
  15. */
  16. publicStringformatXmlAnswer(Stringto,Stringfrom,Stringcontent){
  17. StringBuffersb=newStringBuffer();
  18. Datedate=newDate();
  19. sb.append("<xml><ToUserName><![CDATA[");
  20. sb.append(to);
  21. sb.append("]]></ToUserName><FromUserName><![CDATA[");
  22. sb.append(from);
  23. sb.append("]]></FromUserName><CreateTime>");
  24. sb.append(date.getTime());
  25. sb.append("</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[");
  26. sb.append(content);
  27. sb.append("]]></Content><FuncFlag>0</FuncFlag></xml>");
  28. returnsb.toString();
  29. }
  30. }

总结,以上便是微信公众平台开发的全部流程,整体来看并不复杂,要非常感谢捷微JEEWX,帮我们解决了智能回复这一高难度问题。其他类型的消息处理与示例中类似,有兴趣的开发者可以联系我进行交流学习,希望本文对大家有所帮助。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值