统一对象消息编程(9)—对象消息编程框架应用3(demo—应用server)

   通过前面hello小明案例的介绍,我们对对象消息编模式或框架有了初步认识。为了验证这种模式是否的可用,我还对数据库、网络应用等方面进行了测试,在tlobjdemo下有案例代码。编码质量比较低,当时完全是为了测试。dbdemo包是数据库方面的测试,http是网络方面的测试,包括客户端和服务器。

    我认为对象消息编程框架一个优点是逻辑清晰,因为对象之间只调用一个方法putmsg,跟随这个方法,就能清晰看到消息的传输途径。还有一个特点是模块化,程序之间都是模块的组合。掌握了消息对象原理再加上这些特点使代码阅读变得容易、清晰。现在我们看看demo下http包下的serverstart。这个类是启动一个应用server。这个应用server通过json和客户端传递消息。

代码:

public class serverstart extends TLBaseModule {
    public serverstart(String main, TLObjectFactory myfactory) {
        super(main, myfactory);
    }

    @Override
    protected void init() {
    }
    @Override
    protected TLMsg checkMsgAction(Object fromWho, TLMsg msg) {
        switch (msg.getAction()){
            default :
        }
        return null;
    }
    public static void main(String[] args) {
        String configdir = System.getProperty("user.dir") + "\\config\\person\\";
        Myfactory myfactory = Myfactory.getInstance(configdir, "applicationServer_appConfig.xml");
        myfactory.boot();
        serverstart serverstart = new serverstart("main", (TLObjectFactory) myfactory);
        MyAppCenter appCenter = (MyAppCenter) serverstart .getModule("appCenter");
    }
}

这次入口类直接继承了TLBaseModule,主要是为了编程方便,可以直接使用putmsg。在入口main方法内,和hello小明类似,先启动工厂实例,然后启动appCenter。稍微不同的是在启动工厂类时,直接指定了配置文件applicationServer_appConfig.xml"。然后执行工厂boot。这个main方法也很简单,看不出做什么,我们看配置文件,看主要部分:

<msgTable>
    <msgid  value="setup" >
        <msg action="run" destination="managerServer" waitFlag="false"  />
        <msg action="run" destination="HSServer" waitFlag="false" />
        <msg action="getModule" destination="moduleFactory" moduleName="myserviceRegistTask" waitFlag="false" />
    </msgid>
</msgTable>
<initMsg>
    <msg msgid="setup" />
</initMsg>
<factoryBoot>
    <factoryBoot>
        <msg action="getModule"  moduleName="log" usePreReturnMsg="false" />
        <msg action="getModule"  moduleName="monitorConfig" usePreReturnMsg="false" />
        <msg action="getModule"  moduleName="cache" usePreReturnMsg="false" />
        <msg action="getModule"  moduleName="dbserver1" usePreReturnMsg="false" />
        <msg action="getModule"  moduleName="dbserver2" usePreReturnMsg="false" />
        <msg action="getModule"  moduleName="HSServer" usePreReturnMsg="false"/>
        <msg action="getModule"  moduleName="managerServer" usePreReturnMsg="false"/>
        <msg action="getModule"  moduleName="serviceModle" usePreReturnMsg="false"/>
    </factoryBoot>
</factoryBoot>

在工厂boot表中,工厂顺序启动了八个模块。

log--日志模块

monitorConfig---配置文件监听模块,配置文件变化是动态配置模块

cache--缓存模块

dbserver1、dbserver2 --数据库链接模块

HSServer----这是我们要启动的应用server

managerServer---管理server,应用server启动后,通过管理server管理应用server的启动、停止等

serviceModle---一个自定义的服务模块,这里启动是为了放在主线程,可以共用。可以不用在这启动,用户调用服务时启动。

工厂boot完毕后,上面模块都由工厂创建完毕。appCenter启动,执行初始化消息“setup” 。在路由消息表<msgTable>中,setup消息对应三个消息,然后依次执行这三个消息。分别是管理server运行,应用server运行。myserviceRegistTask是一个服务注册模块,用于将应用server注册到服务中心,如不注册可以不用。该模块用一个异步方式启动,在新的一个线程里运行,周期给服务中心发生注册消息。至此,程序启动完毕,结果如下:

程序启动,应用server监听8081端口,管理server监听8082端口。观察上面启动,发现没有myserviceRegistTask的周期服务注册消息日志。这是因为在日志配置log_config.xml中屏蔽了该模块的日志:

<?xml version="1.0" encoding="UTF-8" ?>
<moduleConfig>
    <params>
        <log4jConfigFile value="config/person/log4j.properties" />
        <level value="warn" />
        <noLogModules value="httpClient;myserviceRegistTask;userw1;HttpJsonClientHandler1"/>
    </params>
    <logModules>
        <module name="HSServer"  levels="info;warn;debug" actions=""  ></module>
    </logModules>
</moduleConfig>

配置项noLogModules 中为不进行日志输出的模块,现在我们把屏蔽取消,同时日志level改为info:

我们看到对于日志配置的修改,日志模块重新加载了配置,myserviceRegistTask的周期注册信息出现了。监听配置文件修改就是工厂boot时启动的monitorConfig 模块。该模块在单独的线程周期监听配置文件,monitorConfig的配置文件如下:

<?xml version="1.0" encoding="UTF-8" ?>
<moduleConfig>
    <params>
        <delay value="5" />
        <modules value="appCenter;HSServer;serviceMsgMap;log"  />
    </params>
</moduleConfig>

配置中,delay的值为5,意思是以5秒周期检测文件变化。项modules 定义监听那些模块的配置。 

细心的同学会发现管理server 和应用server 都是一个类,不过是配置不同。

  <module name="managerServer" proxyModule="HSServer"   configfile="managerServer_config.xml"/>

在应用server运行任务已满或者停止的时候,我们的管理客户端无法直接连接到应用server,这时候其实我们是另起了一个应用server担当管理的责任,客户端通过连接管理server而控制应用server。管理server和应用server在一个应用内,所以可以通信。server只是和客户端一个网络接口,负责消息的收发,具体提供的服务功能要依据后端的模块。看应用server的配置HSServer_config.xml : 

<?xml version="1.0" encoding="UTF-8" ?>
<moduleConfig>
    <!-- 目录相对于filter配置目录下-->
    <params>
        <serviceName value="HSServer" />
        <serviceType value="usermanager" />
        <hostname value="127.0.0.1" />
        <port value="8081" />
        <maxTaskNumb value="30" />
        <serviceHander value="serviceMsgMap" />
        <serviceAuth value="myServiceAuth" />
    </params>
    <msg-mapping>
        <msgid value="index" >
            <!-- client的msg 对应的服务msg-->
            <msg  destination="serviceModle"  action="index"/>
        </msgid>
        <msgid value="user" >
            <!-- client的msg 对应的服务msg-->
            <msg  destination="serviceModle"  action="user"/>
        </msgid>
        <msgid  value="dbmodle" >
            <!--msg  destination="serviceModle" action="dbservice" newModule="true" / -->
            <msg  destination="serviceModle" action="dbservice"  />
        </msgid>
        <msgid  value="putdb" >
            <msg  destination="serviceModle" action="putdb" />
        </msgid>
        <msgid  value="insertMap" >
            <!--//异步并发操作 对于不需要返回结果
            <msg  destination="serviceModle" action="insertMap" waitFlag="false" />
            -->
            <msg  destination="serviceModle" action="insertMap"  />
        </msgid>
    </msg-mapping>

</moduleConfig>

应用server收到的消息转发到前面提到的自定义服务模块serviceModle上,由服务模块处理。

<msgid  value="dbmodle" >
    <!--msg  destination="serviceModle" action="dbservice" newModule="true" / -->
    <msg  destination="serviceModle" action="dbservice"  />
</msgid>

对于上面的映射,对于客户端消息ID为dbmodle的消息,转发至serviceModle , 处理行为dbservice 。

看管理server的配置managerServer_config.xml :

<moduleConfig>
    <!-- 目录相对于filter配置目录下-->
    <params>
        <port value="8082" />
        <maxTaskNumb value="20" />
        <serviceHander value="managerMsgMap" />
        <serviceAuth value="myServiceAuth" />
    </params>
    <msg-mapping>
        <msgid  value="reloadConfig" >
            <msg  destination="HSServer" action="reloadConfig"  />
        </msgid>
        <msgid  value="setTaskNumb" >
            <msg  destination="HSServer" action="setTaskNumb"  />
        </msgid>
        <msgid  value="stopServer" >
            <msg  destination="HSServer" action="stop"  />
        </msgid>
        <msgid  value="startServer" >
            <msg  destination="HSServer" action="run"  />
        </msgid>
        <msgid  value="getTasks" >
            <msg  destination="HSServer" action="getTasks"  />
        </msgid>
        <msgid  value="getParams" >
            <msg  destination="HSServer" action="getParams"  />
        </msgid>
        <msgid  value="reloadConfig" >
            <msg  destination="HSServer" action="reloadConfig"  />
        </msgid>
    </msg-mapping>

</moduleConfig>

管理server收到的控制消息直接送给了应用server,控制应用server的启动、停止等。

server只负责接收客户端的消息,并负责转解码,对于客户端的消息,不能随便在server上执行,因此<msg-mapping>定义客户消息与服务消息的映射,服务端不开放的消息不在映射表内。TLWebServiceMsgMap负责消息的映射,功能类似web框架(后面介绍)中的url到消息的转换。

http案例包下的clientkeepalive为一个客户端,stopServer为一个管理客户端,都仅为代码测试。

在我的设想中,应用server布置在webserver后端,主要负责业务逻辑。这时候webserver即为客户端。为保持效率,默认采用长连接方式。应用server类似于远程过程调用或webservice,不过在我们对象消息编程概念里,一切都是消息对象,因此不存在远程调用的概念,只能说消息可以通过网络传输到位于其他机器上的模块。

     我觉得我的网络部分模块代码写的很差,我自己都不满意,当一个参考思路吧。但我觉得我的设计思想还是是对的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值