| 
| 
| 如何使用XML实现多渠道接入网站的构架 |  
| 时间:2014-05-04 10:30:08  来源:JSP天空网  作者:未知 |  
| 如何使用XML实现多渠道接入网站的构架 
 其实写这篇文章的目的最多的想法是把自己在去年在瑞士做项目时应用的一个框架给展现出来让
 大家共享,但我又有点担心我的表达能力不能将我在里面使用的思想很好的表现出来,所以迟迟
 不敢下笔,最后还是下了决心,写吧, 不行就在好好改改,当然也希望大家多提些意见。
 
 
 一.背景
 
 在现在的网站中,接入的渠道是越来越多了,技术也是越来越先进,WAP, SMS,EMAIL, 传统的
 Web, Socket等等,如果连数据库和LDAP也算接入的话,那在设计之中需要扩展的空间要做到很好
 很好,才保证在添加新的渠道情况下不需要更多的修改代码甚至不改代码的情况。但可能吗?我
 想也不可能,但有什么方式可以更好的解决这种多渠道接入的框架的完美性呢?
 
 
 二.构架
 
 
 
 
 
 
 screen.width-333)this.width=screen.width-333;">
 【图一】
 
 如图一所显示,在现有的所有接入都已经使用上的时候,设计者看的都眼花缭乱了,如果是为了
 凑份子,那这些程序怎么写都可以,而且也肯定可以实现,但维护起来就会比较痛苦,还是回到
 那个问题,怎么可以实现更完美呢?在项目组的构架讨论中,我提出了路由的感念,并得到了大
 家统一的认可,如图二显示
 
 
 
 
 
 
 screen.width-333)this.width=screen.width-333;">
 【图二】
 
 
 图二看起来象个八爪的章鱼,章鱼腿分别连接所有的接入渠道,进行连接所有这些渠道的核心就
 是这个章鱼的头XMLRouter,Router在此的作用是沟通所有渠道,实现数据的路由,争强系统在构
 架上的扩展性和灵活性,好处会很多很多。称呼为XMLRouter是因为如果不使用XML这种灵活而又
 规范的语言来做为数据传输的媒介,那Router的工作量也同样会成倍的增加,定义好XML的规范后将
 为以后的扩展带来很多好处.
 
 
 三.思想和模式
 
 XMLRouter的最初想法来自于计算机的主板和<<Design Pattern>>之中的Builder Pattern, 计算
 机主板的PCI 插槽定义了PCI的规范,只要你生产的卡符合PCI标准,那你插入到这个主板上就可以
 工作, 至于里面是怎么工作的则是已经封装好了. Builder Pattern则是提出将复杂的构建分离开
 来, 一步一步的进行实现.XMLRouter是将这些复杂的渠道分离开来,一个个的进行表现.
 
 Services思想:为了能和Router进行沟通,在这些渠道接入时必须定义统一的接口,这里成为
 Services, 只要符合Services规范的程序就可以接入到Router并进行数据的路由.
 
 Factory模式和Composite模式
 XMLRouter在实际的设计中将采用Factory模式产生,Router由RouterFactory生产, 在投入使用时
 将放置于队列中,传递数据和接收数据以及返回数据都从队列中取相应的Router来调用,应用了
 Composite的模式.
 
 
 四.XML配置文件
 
 XML文件对于Router之中的使用分为两个部分, 第一个是Router的配置,如:
 
 
 <?xml version="1.0" ?>
 <services>
 <!-- database Service -->
 <service name="database" type="database"class="com.web.service.DBService">
 <connectordriver="com.microsoft.jdbc.sqlserver.SQLServerDriver"
 url="jdbc:microsoft:sqlserver://192.168.0.179:1433" user="test"
 passwd="test" />
 </service>
 <!-- Web Service-->
 <service name="web" type="web" class="com.web.service.WebService" >
 <connector />
 </service>……</services>
 
 
 这是Router的配置文件, service节点代表需要接入的渠道, service节点包含
 
 
 connector子节点, 子节点的配置根据type来区分, 如果是database则包含url, user, passwd,
 driver等属性, 如果是socket则包含 port, maxthread等属性, 属性值可以根据自己的定义来配
 置.
 
 另一种XML文件则是XML交易数据文件,用于在所有的services中传递数据,每个Services自己包涵
 一个相应的XML文件,比如webtrans.xml格式如下:
 
 <?xml version="1.0" ?>
 <transaction>
 <trans name="addDoc" service="database" method="insert">
 <property name="createtime" type="timestamp"/>
 <property name="creatorid" type="long"/>
 <property name="doctypeid" type="int"/>
 <property name="docstatusid" type="int"/>
 </trans>
 </transaction>
 
 相应的dbtrans.xml格式如下
 
 <trans name="addDoc" table="TDOC_DOCS" method="insert">
 <primarykey name="docid" />
 <set>
 <property name="createtime" type="timestamp"/>
 <property name="creatorid" type="long"/>
 <property name="doctypeid" type="int"/>
 <property name="docstatusid" type="int"/>
 </set>
 </trans>
 
 其余XML则可按这样的规则来定制
 
 Ps:请参阅我之前写的文章
 ”使用XML封装数据库操作语句的实现”
 
 
 
 五.技术实现
 
 
 RouterFactory
 
 
 
 package com.web.router;
 import com.web.platform.Exception.RouterException;
 import java.util.Hashtable;/** * Router产生和清除的类 */
 public class RouterFactory
 { /** * Router存储的树front */
 private static Hashtable QueuePairFront = null; /** * Router存储的树back */
 private static Hashtable QueuePairBack = null; /** * Router存储的树 */
 private static Hashtable QueueRouter = null; /** * 返回的XMLRouter */ public static XMLRouter instance = null; /** * Router的定义 */
 public static RouterDefine routerdefine = null; /** * Router的ID号 */
 public static long routeIndex = 0; /** * @roseuid 3F169C21027C */
 public RouterFactory() { } /** * 初始化Hashtable和Vector */
 public static void initFactory() throws Exception
 { QueuePairFront = new Hashtable();
 QueuePairBack = new Hashtable();
 QueueRouter = new Hashtable();
 initRouteDefine();
 }/** * 初始化Route的设置 * */
 private static void initRouteDefine() throws Exception
 { if( routerdefine == null )
 routerdefine = new RouterDefine();
 routerdefine.loadRouterDef();
 } /** * 返回实例 * @return com.web.router.XMLRouter */
 public static XMLRouter getInstance(long index) throws RouterException
 {
 return (XMLRouter)QueueRouter.get(new Long(index));
 } /** * 产生一个XMLRouter的实例
 * @return com.web.router.XMLRouter
 * @roseuid 3F1618A103BC */
 public static XMLRouter popInstance() throws RouterException
 {
 routeIndex ++;
 instance = new XMLRouter(routeIndex);
 setDefine( instance );
 QueueRouter.put(new Long(routeIndex), instance); return instance;
 } /** * 清空Hashtable,Vector等 * @roseuid 3F1618B203C1 */
 private static void freeResource() throws Exception
 { QueuePairFront.clear();
 QueuePairBack.clear();
 QueueRouter.clear();
 QueuePairFront = QueuePairBack = QueueRouter = null;
 } /** * 清除实例 * @param instanceID * @throws Exception */
 public static void removeInstance(XMLRouter instance) throws Exception
 { instance.clear();
 QueueRouter.remove( new Long(instance.getIndex() ) ) ;
 } /** * Method isNull. * @return boolean */
 public static boolean isNull()
 {…… return false;
 }}
 
 
 
 
 XMLRouter
 
 
 
 package com.web.router;
 import com.web.platform.Exception.RouterException;
 import com.web.common.*;import java.util.*;
 import java.lang.reflect.Method;import java.lang.reflect.Constructor;
 /** * @author keli * @version 0.0.1 * 平台的关键,路由的类,每个Router将从
 RouterFactory里读取 * Router存储的树front,和back,routeIndex,目的是为了能在路由 * 之后
 可以清除申请的对象。 * Router可以实现同步和异步的功能. */
 
 public class XMLRouter
 { /** * Router存储的树front */
 private static Hashtable QueuePairFront = null;
 /** * Router存储的树back */
 private static Hashtable QueuePairBack = null;
 /** * 本router的index号码 */
 private long routeIndex = 0;
 /** * router的设置 */
 private RouterDefine define = null;
 /** * 用于判断是路由的起回点 */
 private String action = "";
 /** *此变量只是用于在routeto方法中申请新的class */
 private String classname = "";
 /** */
 public XMLRouter(long index)
 { routeIndex = index; }
 /** * 路由 * @throws Exception * @roseuid 3F1616BD0186 */
 public void routing(Env env) throws RouterException, Exception
 { /*如果为起点*/
 if( action.equalsIgnoreCase( RouterConstant.CFG_FUNC_ROUTETO ) )
 {……}
 /*如果为返回点*/
 else if( action.equalsIgnoreCase( RouterConstant.CFG_FUNC_ROUTEBACK ) )
 {……}
 /*否则为错误*/
 else
 throw new RouterException("Set Router action error."); }
 /** * 读取本Router的id号. * @return long */
 public long getIndex(){
 return routeIndex;
 }
 /** * 清除所有对象. * @throws RouterException */
 public void clear() throws RouterException {
 QueuePairFront.remove(new Long(routeIndex));
 QueuePairBack.remove(new Long(routeIndex));
 /*系统回收*/
 System.runFinalization();
 }
 /** * 设置本Router的设置.
 * @param def
 * @throws RouterException
 */
 public void setDefine(RouterDefine def) throws RouterException
 {
 define = def;
 }
 /**
 * 设置action的值
 * @param actionName
 * @throws RouterException
 */
 public void setAction( String actionName )
 {
 action = actionName;
 }
 }
 [h5]Service类[/h5]
 package com.web.common;
 import com.web.platform.Exception.RouterException;
 /**
 * Service的父类,abstract
 */
 public abstract class RouteService
 {
 /**
 */
 public RouteService()
 {
 }
 /**
 * routeTo方法,是交易的起点。
 * @param env
 * @throws RouterException
 */
 public abstract void routeto(Env env) throws RouterException;
 /**
 * routeBack,交易的结束点,
 * @param env
 * @throws RouterException
 */
 public abstract void routeback(Env env) throws RouterException;
 /**
 * routeaccept方法,是交易的接收点,也是routeto的接收函数,
 * routeaccept为被动交易对象的主要处理函数
 * @param env
 * @throws RouterException
 */
 public abstract void routeaccept(Env env) throws RouterException;
 /**
 * routing方法,是Service对外的接口函数
 * @throws RouterException
 */
 public abstract void routing() throws RouterException;
 }
 
 
 接下来则需要实现所有的Services的类了,这里就不做介绍了.
 
 
 
 六.说明
 
 这个Router到目前为止只能实现同步的交易, 暂时不支持异步的交易,但是由于对Router使用了
 Composite的模式设计的,实现异步交易也是可以扩展的,这里不做详细分析.
 
 
 这篇文章是我工作的一个总结,希望能对大家有所帮助.不足之处希望多多指教.
 
 
 
 Good Luck, Enjoy.
 
 Keli thisishnh@163.com
 |  |  |  |