4.4.4 使用CoreServlet类完成消息的接收与响应
接下来,在CoreServlet类的doPost()方法中完成消息的接收与响应。CoreServlet类的完整代码如下。
- 1 package org.liufeng.course.servlet;
- 2
- 3 import java.io.IOException;
- 4 import java.io.PrintWriter;
- 5 import javax.servlet.ServletException;
- 6 import javax.servlet.http.HttpServlet;
- 7 import javax.servlet.http.HttpServletRequest;
- 8 import javax.servlet.http.HttpServletResponse;
- 9 import org.liufeng.course.service.CoreService;
- 10 import org.liufeng.course.util.SignUtil;
- 11
- 12 /**
- 13 * 请求处理的核心类
- 14 *
- 15 * @author liufeng
- 16 * @date 2013-09-29
- 17 */
- 18 public class CoreServlet extends HttpServlet {
- 19 private static final long serialVersionUID = 4440739483644821986L;
- 20
- 21 /**
- 22 * 请求校验(确认请求来自微信服务器)
- 23 */
- 24 public void doGet(HttpServletRequest request, HttpServletResponse response)
- 25 throws ServletException, IOException {
- 26 // 微信加密签名
- 27 String signature = request.getParameter("signature");
- 28 // 时间戳
- 29 String timestamp = request.getParameter("timestamp");
- 30 // 随机数
- 31 String nonce = request.getParameter("nonce");
- 32 // 随机字符串
- 33 String echostr = request.getParameter("echostr");
- 34
- 35 PrintWriter out = response.getWriter();
- 36 // 请求校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
- 37 if (SignUtil.checkSignature(signature, timestamp, nonce)) {
- 38 out.print(echostr);
- 39 }
- 40 out.close();
- 41 out = null;
- 42 }
- 43
- 44 /**
- 45 * 请求校验与处理
- 46 */
- 47 public void doPost(HttpServletRequest request, HttpServletResponse response)
- 48 throws ServletException, IOException {
- 49 // 将请求、响应的编码均设置为UTF-8(防止中文乱码)
- 50 request.setCharacterEncoding("UTF-8");
- 51 response.setCharacterEncoding("UTF-8");
- 52
- 53 // 接收参数:微信加密签名、 时间戳、随机数
- 54 String signature = request.getParameter("signature");
- 55 String timestamp = request.getParameter("timestamp");
- 56 String nonce = request.getParameter("nonce");
- 57
- 58 PrintWriter out = response.getWriter();
- 59 // 请求校验
- 60 if (SignUtil.checkSignature(signature, timestamp, nonce)) {
- 61 // 调用核心服务类接收处理请求
- 62 String respXml = CoreService.processRequest(request);
- 63 out.print(respXml);
- 64 }
- 65 out.close();
- 66 out = null;
- 67 }
- 68 }
从代码中可以看出,doPost()方法的实现可以分为编码设置、请求校验、请求处理和响应消息4个部分,说明如下。
1.编码设置
50~51行代码用于编码设置。微信服务器向公众账号服务器POST(发送)消息时采用的是UTF-8编码,因此在doPost()方法的最开始处需要将请求、响应的字符集编码方式统一设置为UTF-8,否则可能会遇到中文乱码问题。
2.请求校验
第60行代码用于请求校验。为了防止他人向公众账号服务器发送恶意请求,需要对每个消息请求进行合法性验证。微信服务器向公众账号服务器POST消息时,也会在URL后面追加4个参数signature、timestamp、nonce和echostr,仍然是通过校验签名判断消息的真实性,这里的校验方式与第3章中介绍的完全一致。
3.请求处理
第62行代码用于请求处理。我们并没有将请求处理代码直接写在doPost()方法中,而是将这部分代码封装在CoreService类中,这样做能够在一定程度上实现解耦。CoreServlet类不用关心具体的业务处理逻辑,而是完全交由核心服务类CoreService处理。CoreService类的处理结果respXml是一个XML格式的消息。
4.响应消息
第63行代码用于响应消息。通过调用PrintWriter类的print()方法将处理结果respXml返回给微信服务器。微信服务器在收到消息后,会通过公众账号将消息发送给用户。