[转载]java微信平台,发源码 – wxwall – 博客园.
最近写了一个微信平台的架构,采用servlet + spring3.0 + hibernate4.1。整体架构由我负责建设,部份设计估计以后会被改的乱七八糟,所以,我尽可能的把业务模块分出来。趁着刚搭好的框架,留着这版。 以后要是被改出翔了,我也无能为力。代码是大部份都由其他成熟框架直接 copy过来整合,去掉了一些没用的配置。部分我加入的设计也都是自己经过长时间项目提炼出来的,所有代码稳定性大可放心,并且难度不大。源码我也贴网 上,希望有人帮我一起完善一下!不足处也请批评指正。
贴出部分代码,用到了部分设计模式,代码可读性比较好。没什么技术含量,里面有一些涉及微信平台的业务代码可能会有点难懂,如果您认为还不错,那就点个赞。如果认为还值得改进,那也麻烦提出来,我也近期慢慢改进。
代码贴在这里,如果有人愿意一同学习进步,后期就放到github上面去,现阶段我将持续改进。
下载地址
http://pan.baidu.com/s/1i320J3n
spring部分代码:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
">
<!-- 扫描注解Bean -->
<context:component-scan base-package="com.cpic">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:resources.properties</value>
</list>
</property>
</bean>
<bean id="dataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
<property name="alias" value="proxoolDataSource"/>
<property name="driver" value="${connection.driver_class}" />
<property name="driverUrl" value="${connection.url}" />
<property name="user" value="${connection.username}" />
<property name="password" value="${connection.password}" />
<property name="maximumConnectionCount" value="${proxool.maximum.connection.count}"/>
<property name="minimumConnectionCount" value="${proxool.minimum.connection.count}" />
<property name="statistics" value="${proxool.statistics}" />
<property name="simultaneousBuildThrottle" value="${proxool.simultaneous.build.throttle}"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan">
<list>
<value>com.cpic</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.query.substitutions">${hibernate.query.substitutions}</prop>
<prop key="hibernate.default_batch_fetch_size">${hibernate.default_batch_fetch_size}</prop>
<prop key="hibernate.max_fetch_depth">${hibernate.max_fetch_depth}</prop>
<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">${hibernate.bytecode.use_reflection_optimizer}</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
<prop key="net.sf.ehcache.configurationResourceName">${net.sf.ehcache.configurationResourceName}</prop>
<prop key="hibernate.cache.use_structured_entries">${hibernate.cache.use_structured_entries}</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<!--
<prop key="hibernate.connection.datasource">${hibernate.connection.datasource}</prop>
<prop key="hibernate.connection.provider_class">${hibernate.connection.provider_class}</prop>
<prop key="hibernate.jndi.class">${hibernate.jndi.class}</prop>
-->
</props>
</property>
</bean>
<!-- 开启AOP监听 只对当前配置文件有效 -->
<aop:aspectj-autoproxy expose-proxy="true"/>
<!-- 开启注解事务 只对当前配置文件有效 -->
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="merge*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="put*" propagation="REQUIRED" />
<tx:method name="use*" propagation="REQUIRED"/>
<tx:method name="send*" propagation="REQUIRED" />
<!--hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到-->
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="count*" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" propagation="REQUIRED" read-only="true" />
<tx:method name="list*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" read-only="true" />
</tx:attributes>
</tx:advice>
<aop:config expose-proxy="true">
<!-- 只对业务逻辑层实施事务 -->
<aop:pointcut id="txPointcut" expression="execution(* com.cpic..service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
<!-- spring启动时加载spring工具类 -->
<bean id="springUtils" class="com.cpic.common.util.SpringContextUtil"></bean>
</beans>
部分业务 spring配置:
<bean id="textReceviService" class="com.cpic.basemsg.service.impl.TextReceviService"></bean>
<bean id="eventReceviService" class="com.cpic.basemsg.service.impl.EventReceviService"></bean>
<!-- 在线咨询 -->
<bean id="onlineAskEventImpl" class="com.cpic.basemsg.service.event.impl.OnlineAskEventImpl"></bean>
<!-- 卡单激活 -->
<bean id="activeCareEventImpl" class="com.cpic.basemsg.service.event.impl.ActiveCareEventImpl"></bean>
<!-- 客户回访 -->
<bean id="custReVisEventImpl" class="com.cpic.basemsg.service.event.impl.CustReVisEventImpl"></bean>
<!-- 道路救援 -->
<bean id="roadHelpEventImpl" class="com.cpic.basemsg.service.event.impl.RoadHelpEventImpl"></bean>
<!-- 自助报案 -->
<bean id="selfPoliceEventImpl" class="com.cpic.basemsg.service.event.impl.SelfPoliceEventImpl"></bean>
<bean id="wechatMng" class="com.cpic.basemsg.service.WeChatMng">
<property name="map">
<map>
<entry key="text">
<ref local="textReceviService"/>
</entry>
<entry key="event">
<ref local="eventReceviService"/>
</entry>
</map>
</property>
<property name="baseMap">
<map>
<entry key="btn13">
<ref local="onlineAskEventImpl"/>
</entry>
<entry key="btn21">
<ref local="roadHelpEventImpl"/>
</entry>
<entry key="btn22">
<ref local="selfPoliceEventImpl"/>
</entry>
<entry key="btn23">
<ref local="custReVisEventImpl"/>
</entry>
<entry key="btn24">
<ref local="activeCareEventImpl"/>
</entry>
</map>
</property>
</bean>
业务解耦类
package com.cpic.basemsg.service;
import java.util.Map;
/**
* 设计这个类,主要是为了解耦,可实现对逻辑层的配置,将业务更细化
* 将一些共同特性统一处理
* @author wuxw
*
*/
public class WeChatMng {
static Logger logger = Logger.getLogger(WeChatMng.class);
@SuppressWarnings("unchecked")
public WeChatService weChatService;
@SuppressWarnings("unchecked")
private Map<String,WeChatService> map;
private Map<String,BaseEventService> baseMap;
/** 点击事件*/
public BaseEventService baseEventService;
public void setMap(Map<String, WeChatService> map) {
this.map = map;
}
public void setBaseMap(Map<String, BaseEventService> baseMap) {
this.baseMap = baseMap;
}
/**
* 对不同消息类型的控制转发
* @param msgType
* @param wxMsgXml
* @return
*/
public String process(String msgType,String wxMsgXml) throws BaseMsgException{
if(msgType == null || msgType == ""){
logger.error("请求消息:" + msgType);
throw new BaseMsgException("请求消息为空!");
}
weChatService = map.get(msgType);
if(null == weChatService){
throw new BaseMsgException("不支持的接口类型:" + msgType);
}
return weChatService.process(wxMsgXml);
}
/**
* 对不同事件的控制转发
* @parama clickKey 按钮编号
* @return
* @throws BaseMsgException 业务异常
*/
public String processEvent(String click,EventMsgModel model) throws BaseMsgException{
if(click == null){
throw new BaseMsgException("不存在的点击事件:" + click);
}
if(model == null){
throw new BaseMsgException("传入的事件消息为null!" );
}
baseEventService = baseMap.get(click);
if(baseEventService == null){
throw new BaseMsgException("暂时不支持的点击参数:" + click);
}
return baseEventService.process(model);
}
}
部分类的核心设计
/**
* 抽象出功能模块
* 信息的处理流程分三步依次进行:
* 1. 接收信息
* 2. 处理信息
* 3. 返回信息
* 并且这个顺序不能变,强制使用处理信息的流程
* 我们只需要关心业务处理的方式
* @author wuxw
*
*/
public abstract class WeChatServiceAbs<T extends BaseMsgModel> extends CommonHibernateDao implements WeChatService<BaseMsgModel> {
/**
* 处理消息,用模版的形式对各模块独立
* @param xmlMsg 传入消息
* @return 返回处理后的消息
* @throws WeChatException
*/
public String process(String xmlMsg) throws BaseMsgException{
MsgModel msg = reviceMsg(xmlMsg);
return processMsg(msg).toString();
}
}
Mikel