天天看點

SpringMVC微信公衆服務号接入

之前用的柳大神寫的Servlet+jdbc寫的微信服務号,别的項目全是Stringmvc,就把項目更改了,做個記錄

項目是maven管理,需要的包配置在pom檔案,在最底下,以後寫避免找不到

一些基礎類就不貼了,很多網站都有

Controller類:

<pre name="code" class="java"><span style="font-size:14px;">import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;  
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;


@Controller
@RequestMapping(value="core")
public class CoreServiceController {
	 private Logger log = Logger.getLogger(CoreServiceController.class);  
	  
	    /** 
	     * 校驗資訊是否是從微信伺服器發過來的。 
	     *  
	     * @param weChat 
	     * @param out 
	     */  
	    @RequestMapping(method = { RequestMethod.GET })  
	    public void doget(HttpServletRequest request, HttpServletResponse response, PrintWriter out) {  
	    	// 微信加密簽名
			String signature = request.getParameter("signature");
			// 時間戳
			String timestamp = request.getParameter("timestamp");
			// 随機數
			String nonce = request.getParameter("nonce");
			// 随機字元串
			String echostr = request.getParameter("echostr");
	  
	        // 通過檢驗signature對請求進行校驗,若校驗成功則原樣傳回echostr,表示接入成功,否則接入失敗  
	        if (SignUtil.checkSignature(signature, timestamp, nonce)) {  
	            out.print(echostr);  
	        } else {  
	            System.out.println("不是微信伺服器發來的請求!");  
	        }  
	        out.flush();  
	        out.close();  
	    }  
	    /** 
	     * 微信消息的處理 
	     * @param request 
	     */  
	    @RequestMapping(method = { RequestMethod.POST })  
	    public void dopose(HttpServletRequest request, HttpServletResponse response)throws Exception {  
	        /* 消息的接收、處理、響應 */  
	        // 将請求、響應的編碼均設定為UTF-8(防止中文亂碼)  
	        request.setCharacterEncoding("UTF-8");  
	        response.setCharacterEncoding("UTF-8");  
	        // 調用核心業務類接收消息、處理消息  
	        String respMessage = CoreService.processRequest(request,response);  
	        log.info(respMessage);  
	        // 響應消息  
	        PrintWriter out = response.getWriter();  
	        out.print(respMessage);  
	        out.close();  
	    }  

}</span>
           

CoreService類:

public class CoreService {
	private static Logger log = LoggerFactory.getLogger(CoreService.class);
	private static String emoji(int codePoint){
		return String.valueOf(Character.toChars(codePoint));
	}
		
	/**
	 * 處理微信發來的請求
	 * 
	 * @param request
	 * @return
	 */
	
	public static String processRequest(HttpServletRequest request,HttpServletResponse response) {
		
		// 預設傳回的文本消息内容
		String respMessage = null;
		try {
			String respContent = null;
			Map<String, String> requestMap = MessageUtil.parseXml(request);
			String fromUserName = requestMap.get("FromUserName");
			String toUserName = requestMap.get("ToUserName");
			String msgType = requestMap.get("MsgType");
			TextMessage textMessage = new TextMessage();
			textMessage.setToUserName(fromUserName);
			textMessage.setFromUserName(toUserName);
			textMessage.setCreateTime(new Date().getTime());
			textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
			textMessage.setFuncFlag(0);
  			   //文字資訊
             		 if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
 				respContent = emoji(0x274C)+"emoji(0x274C)"+"請點選菜單進行操作";  
               			 textMessage.setContent(respContent);
				respMessage = MessageUtil.textMessageToXml(textMessage); 
			} // 圖檔消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
				 respContent = emoji(0x274C)+"emoji(0x274C)"+"請點選菜單進行操作";
				 textMessage.setContent(respContent);respMessage = MessageUtil.textMessageToXml(textMessage); } 
			// 地理位置消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) { 
			} // 連結消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) { 
				respContent = "請點選菜單進行操作"; textMessage.setContent(respContent);
				respMessage = MessageUtil.textMessageToXml(textMessage); } 
			// 音頻消息 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
				 respContent = "請點選菜單進行操作"; textMessage.setContent(respContent);
				 respMessage = MessageUtil.textMessageToXml(textMessage); } 
			// 事件推送 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
				 // 事件類型 String eventType = requestMap.get("Event"); 
				// 訂閱 if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
					respContent = emoji(0x1F334)+"謝謝您關注";
					textMessage.setContent(respContent);
					 respMessage = MessageUtil.textMessageToXml(textMessage);}
				 // 自定義菜單點選事件 else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
					String eventKey = requestMap.get("EventKey");
					if (eventKey.equals("11")) {
					} else if (eventKey.equals("12")) {
					 } 
					}
			} catch (Exception e) {
			e.printStackTrace();
			} 
		return respMessage;}
           
</pre><p></p><pre>
           

BaseMessage類

/** 
 * 消息基類(公衆帳号 -> 普通使用者) 
 *  
 */ 
public class BaseMessage {
	// 接收方帳号(收到的OpenID)  
    private String ToUserName;  
    // 開發者微信号  
    private String FromUserName;  
    // 消息建立時間 (整型)  
    private long CreateTime;  
    // 消息類型(text/music/news)  
    private String MsgType;  
    // 位0x0001被标志時,星标剛收到的消息  
    private int FuncFlag;  
  
    public String getToUserName() {  
        return ToUserName;  
    }  
  
    public void setToUserName(String toUserName) {  
        ToUserName = toUserName;  
    }  
  
    public String getFromUserName() {  
        return FromUserName;  
    }  
  
    public void setFromUserName(String fromUserName) {  
        FromUserName = fromUserName;  
    }  
  
    public long getCreateTime() {  
        return CreateTime;  
    }  
  
    public void setCreateTime(long createTime) {  
        CreateTime = createTime;  
    }  
  
    public String getMsgType() {  
        return MsgType;  
    }  
  
    public void setMsgType(String msgType) {  
        MsgType = msgType;  
    }  
  
    public int getFuncFlag() {  
        return FuncFlag;  
    }  
  
    public void setFuncFlag(int funcFlag) {  
        FuncFlag = funcFlag;  
    }  
}
           

TextMessage

package com.ysh.message.resp;

/** 
 * 文本消息 
 *  
 */  
public class TextMessage extends BaseMessage {
	 // 回複的消息内容  
    private String Content;  
  
    public String getContent() {  
        return Content;  
    }  
  
    public void setContent(String content) {  
        Content = content;  
    }  
}
           

MessageUtil

import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;


import org.dom4j.io.SAXReader;
import org.dom4j.Document;
import org.dom4j.Element;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

/**
 * 消息工具類
 * 
 */
public class MessageUtil {
	/**
	 * 傳回消息類型:文本
	 */
	public static final String RESP_MESSAGE_TYPE_TEXT = "text";

	/**
	 * 傳回消息類型:音樂
	 */
	public static final String RESP_MESSAGE_TYPE_MUSIC = "music";

	/**
	 * 傳回消息類型:圖文
	 */
	public static final String RESP_MESSAGE_TYPE_NEWS = "news";

	/**
	 * 請求消息類型:文本
	 */
	public static final String REQ_MESSAGE_TYPE_TEXT = "text";

	/**
	 * 請求消息類型:圖檔
	 */
	public static final String REQ_MESSAGE_TYPE_IMAGE = "image";

	/**
	 * 請求消息類型:連結
	 */
	public static final String REQ_MESSAGE_TYPE_LINK = "link";

	/**
	 * 請求消息類型:地理位置
	 */
	public static final String REQ_MESSAGE_TYPE_LOCATION = "location";

	/**
	 * 請求消息類型:音頻
	 */
	public static final String REQ_MESSAGE_TYPE_VOICE = "voice";

	/**
	 * 請求消息類型:推送
	 */
	public static final String REQ_MESSAGE_TYPE_EVENT = "event";

	/**
	 * 事件類型:subscribe(訂閱)
	 */
	public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";

	/**
	 * 事件類型:unsubscribe(取消訂閱)
	 */
	public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";

	/**
	 * 事件類型:CLICK(自定義菜單點選事件)
	 */
	public static final String EVENT_TYPE_CLICK = "CLICK";

	/**
	 * 解析微信發來的請求(XML)
	 * 
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, String> parseXml(HttpServletRequest request)
			throws Exception {
		// 将解析結果存儲在HashMap中
		Map<String, String> map = new HashMap<String, String>();

		// 從request中取得輸入流
		InputStream inputStream = request.getInputStream();
		// 讀取輸入流
		SAXReader reader = new SAXReader();
		Document document = reader.read(inputStream);
		// 得到xml根元素
		Element root = document.getRootElement();
		// 得到根元素的所有子節點
		List<Element> elementList = root.elements();

		// 周遊所有子節點
		for (Element e : elementList)
			map.put(e.getName(), e.getText());

		// 釋放資源
		inputStream.close();
		inputStream = null;

		return map;
	}

	/**
	 * 文本消息對象轉換成xml
	 * 
	 * @param textMessage
	 *            文本消息對象
	 * @return xml
	 */
	public static String textMessageToXml(com.ysh.message.resp.TextMessage textMessage) {
		xstream.alias("xml", textMessage.getClass());
		return xstream.toXML(textMessage);
	}

	/**
	 * 音樂消息對象轉換成xml
	 * 
	 * @param musicMessage 音樂消息對象
	 * @return xml
	 */
	public static String messageToXml(MusicMessage musicMessage) {
		xstream.alias("xml", musicMessage.getClass());
		return xstream.toXML(musicMessage);
	}

	/**
	 * 圖文消息對象轉換成xml
	 * 
	 * @param newsMessage
	 *            圖文消息對象
	 * @return xml
	 */
	public static String newsMessageToXml(NewsMessage newsMessage) {
		xstream.alias("xml", newsMessage.getClass());
		xstream.alias("item", new Article().getClass());
		return xstream.toXML(newsMessage);
	}

	/**
	 * 擴充xstream,使其支援CDATA塊
	 * 
	 * @date 2013-05-19
	 */
	private static XStream xstream = new XStream(new XppDriver() {
		public HierarchicalStreamWriter createWriter(Writer out) {
			return new PrettyPrintWriter(out) {
				// 對所有xml節點的轉換都增加CDATA标記
				boolean cdata = true;

				@SuppressWarnings("unchecked")
				public void startNode(String name, Class clazz) {
					super.startNode(name, clazz);
				}

				protected void writeText(QuickWriter writer, String text) {
					if (cdata) {
						writer.write("<![CDATA[");
						writer.write(text);
						writer.write("]]>");
					} else {
						writer.write(text);
					}
				}
			};
		}
	});

	/**
	 * 主菜單
	 * 
	 * @return
	 */
	// public static String getMainMenu() {
	// StringBuffer buffer = new StringBuffer();
	// buffer.append("您好,雲生活機器人為您服務,請回複數字選擇服務:").append("\n\n");
	// buffer.append("1  曆史上的今天").append("\n");
	// buffer.append("2  經典遊戲").append("\n");
	// buffer.append("3  周邊搜尋(待開發)").append("\n");
	// buffer.append("4  天氣查詢(待開發)").append("\n");
	// buffer.append("6  美女電台(待開發)").append("\n");
	// buffer.append("7  公交查詢(待開發)").append("\n");
	// buffer.append("8  聊天唠嗑(待開發)").append("\n\n");
	// buffer.append("回複“?”顯示此幫助菜單");
	// return buffer.toString();
	// }
	//
	// public static String youxi() {
	// StringBuffer buffer = new StringBuffer();
	// buffer.append("可以直接點選玩").append("\n\n");
	// buffer.append("1  <a href=\"http://www.duopao.com/games/info?game_code=g20140120233048400063\">雷電</a>經典").append("\n");
	// buffer.append("2  <a href=\"http://www.duopao.com/games/info?game_code=g20140212153040377809\">Flappy Bird</a>就是小鳥").append("\n");
	// buffer.append("3  <a href=\"http://www.duopao.com/games/info?game_code=g20140324115109221580\">2048</a>數字遊戲").append("\n");
	// return buffer.toString();
	// }
	/**
	 * 文本消息對象轉換成xml
	 * 
	 * @param textMessage 文本消息對象
	 * @return xml
	 */
	public static String messageToXml(TextMessage textMessage) {
		xstream.alias("xml", textMessage.getClass());
		return xstream.toXML(textMessage);
	}
	/**
	 * 圖文消息對象轉換成xml
	 * 
	 * @param newsMessage 圖文消息對象
	 * @return xml
	 */
	public static String messageToXml(NewsMessage newsMessage) {
		xstream.alias("xml", newsMessage.getClass());
		xstream.alias("item", new Article().getClass());
		return xstream.toXML(newsMessage);
	}
	
	
           

NewsMessage

public class NewsMessage extends BaseMessage {

	 // 圖文消息個數,限制為10條以内  
    private int ArticleCount;  
    // 多條圖文消息資訊,預設第一個item為大圖  
    private List<Article> Articles;  
  
    public int getArticleCount() {  
        return ArticleCount;  
    }  
  
    public void setArticleCount(int articleCount) {  
        ArticleCount = articleCount;  
    }  
  
    public List<Article> getArticles() {  
        return Articles;  
    }  
  
    public void setArticles(List<Article> articles) {  
        Articles = articles;  
    }  
}
           

下面是配置檔案

web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<listener>
	     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
	<context-param> 
	    <param-name>contextConfigLocation</param-name> 
	    <param-value>classpath*:applicationContext.xml</param-value> 
	</context-param>

	<servlet>
	  <servlet-name>hello</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>  
          <param-name>contextConfigLocation</param-name>  
          <param-value>classpath:hello-servlet.xml</param-value>  
      </init-param> 
	</servlet>

	<servlet-mapping>
		<servlet-name>hello</servlet-name>
	    <url-pattern>/</url-pattern>
	</servlet-mapping>
    <servlet-mapping>
		<servlet-name>hello</servlet-name>
	    <url-pattern>/hello/*</url-pattern>
	</servlet-mapping>
	<welcome-file-list> 
	     <welcome-file>login.jsp</welcome-file>
	</welcome-file-list>
	
</web-app>
           

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
	<bean
		class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="username">
			<value>***</value>
		</property>
		<property name="password">
			<value><span style="font-family: Arial, Helvetica, sans-serif;">***</span><span style="font-family: Arial, Helvetica, sans-serif;"></value></span>
		</property>
		<property name="url">
			<value>jdbc:mysql://localhost:8080/test?zeroDateTimeBehavior=round&tinyInt1isBit=false
			</value>
		</property>
	</bean>
<!-- 事物 -->
<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" /></bean>
<!-- dao --> 
<bean id="testDao" class="dao.testDaoimpl">
<!-- service -->
<bean id="coreService" class="service.CoreService"></beans>
           

hello.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />
	
	<context:component-scan base-package="com.ysh.controller" />
	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/jsp/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	
	
	
</beans:beans>
           

pom

<dependency>
    <groupId>xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.2.2</version>
</dependency>
  
  
  
    <!-- log4j -->
	<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>
<dependency>
    <groupId>jcifs</groupId>
    <artifactId>jcifs</artifactId>
    <version>0.7.0b5</version>
</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>3.1.1.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>3.1.1.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>3.1.1.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>3.1.1.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>3.1.1.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>3.1.1.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.apache.geronimo.specs</groupId>
			<artifactId>geronimo-servlet_2.5_spec</artifactId>
			<version>1.2</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.0.5</version>
		</dependency>
		<dependency>
			<groupId>org.apache.axis2</groupId>
			<artifactId>axis2</artifactId>
			<version>1.5.4</version>
		</dependency>
<dependency>
			<groupId>org.jdom</groupId>
			<artifactId>jdom</artifactId>
			<version>1.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.axis2</groupId>
			<artifactId>axis2-spring</artifactId>
			<version>1.6.2</version>
		</dependency>
		
		
		<dependency>
			<groupId>org.apache.axis2</groupId>
			<artifactId>axis2-transport-http</artifactId>
			<version>1.5.4</version>
		</dependency>
		
		
		
		
		
		

		<dependency>
			<groupId>org.apache.axis2</groupId>
			<artifactId>axis2-transport-local</artifactId>
			<version>1.5.4</version>
		</dependency>

		<dependency>
			<groupId>org.apache.xmlbeans</groupId>
			<artifactId>xmlbeans</artifactId>
			<version>2.4.0</version>
		</dependency>
		<!-- json -->
		<dependency>
			<groupId>net.sf.json-lib</groupId>
			<artifactId>json-lib</artifactId>
			<version>2.3</version>
			<classifier>jdk15</classifier>
		</dependency>
		
		<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>integration</artifactId>
    <version>1.7.10</version>
</dependency>
	<dependency>
    <groupId>org.apache.directory.studio</groupId>
    <artifactId>org.dom4j.dom4j</artifactId>
    <version>1.6.1</version>
</dependency>


	</dependencies>