43、消息驱动Bean与CORBA技术解析

消息驱动Bean与CORBA技术解析

1. 消息驱动Bean概述

消息驱动Bean是一种特殊的企业级JavaBean(EJB),它在容器的Java消息服务(JMS)系统中充当消息消费者。与标准的JMS消息消费者类似,消息驱动Bean从JMS队列或主题接收消息,并根据消息内容执行业务逻辑。

在EJB部署时,部署者会为队列或主题创建监听器,容器会根据需要自动创建和移除消息驱动Bean实例,以处理传入的消息。

以下是一个发送消息的示例代码:

message.setInt("ScheduleID",15);
message.setDouble("Price",1700);
message.setString("CreditCard","1234-1234-1234-1234");
message.setLong("CreditCardExp",System.currentTimeMillis());
message.setString("CreditCardType","Visa");
//Send Message
qs.send(message);
}
catch (NamingException ex) {
ex.printStackTrace();
}catch (JMSException ex) {
ex.printStackTrace();
}
}
}

操作步骤如下:
1. 保存客户端应用程序代码。
2. 编译客户端应用程序。
3. 运行客户端应用程序。

消息驱动Bean相较于标准JMS消费者具有以下优势:
- 实例管理 :消息驱动Bean实例由EJB容器完全管理。容器可以根据需要创建多个EJB实例,以并发处理大量消息。而在标准JMS系统中,开发者需要创建一个使用服务器范围会话池的消息监听器类。
- 服务支持 :容器为消息驱动Bean提供其他标准EJB服务,如安全服务和自动事务管理。
- 可移植性 :消息驱动Bean具有EJB的“一次编写,随处部署”的特性。JMS消息监听器与特定的会话池、队列或主题绑定,而消息驱动Bean可以独立于可用的服务器资源进行开发。消息驱动Bean的队列和主题仅在部署时分配,使用特定容器实例上的可用资源。

在使用消息驱动Bean时,我们可能会有以下思考:
- 何时使用JMS,何时使用消息驱动Bean?
- 应该使用队列还是主题?
- 是否需要消息持久性?

2. CORBA技术介绍
2.1 CORBA定义

通用对象请求代理体系结构(CORBA)是一种规范,它描述了对象如何通过网络与其他对象进行通信。该规范提供了与供应商和实现语言无关的特性。对象管理组织(OMG)创建并维护CORBA规范,其成员包括3M、IBM、花旗集团、惠普、太阳微系统、富士通、甲骨文、美国银行、雪佛龙、福特和波音等800多家公司。

许多供应商都实现了CORBA规范,例如Borland的Visibroker,它是Borland企业服务器包的一部分。

当一个程序与运行在另一台机器上的对象进行通信时,会遇到以下问题:
- 程序如何找到对象?
- 程序如何与对象进行通信?
- 程序如何将参数转换为对象所需的正确格式?
- 如果对象未运行,程序如何处理错误?

CORBA通过指定系统各部分必须遵守的接口来解决这些问题:
- 查找对象 :程序通过定位CORBA命名服务,并请求命名服务提供对象的位置来找到对象。这使得应用程序可以在对象位于任何位置的情况下运行。
- 通信方式 :CORBA指定对象请求代理(ORB)管理对象之间的通信。对象使用互联网ORB间协议(IIOP)进行通信。
- 参数转换 :CORBA指定了多种语言的数据类型映射。ORB将数据类型从一种格式转换为另一种格式,例如将一种语言中的字符串转换为另一种语言中的字符串。支持的语言包括COBOL、C、C++、Java、Delphi等。
- 错误处理 :CORBA指定了系统级和应用级错误的格式。错误的抛出由ORB库处理。例如,C++和Java有不同的错误抛出方法和标准,CORBA通过允许将C++错误抛出并传递到Java应用程序中,实现了这些语言之间的桥接。

除了CORBA,还有其他对象互操作性模型,如微软的COM、DCOM和COM+,以及SUN的远程方法调用(RMI)和企业JavaBean(EJB)。这些通信方法都是专有的,但都有与CORBA对象通信的适配器。EJB通过在其规范中包含CORBA要求,朝着与CORBA的完全互操作性发展。

尽管存在多种对象互操作性模型,但CORBA仍然是唯一具有真正供应商和语言独立性的开放标准。

2.2 CORBA组件

CORBA系统包含以下重要组件:
|组件|说明|
|----|----|
|ORB|一组通信库,使对象能够在分布式环境中透明地通信。它处理进程内、进程外和跨网络的对象通信。客户端应用程序通常进行标准的本地方法调用,ORB库将其转换为实际的对象调用,包括数据编组、对象定位和方法调用。不同机器上的ORB可以不同,但它们必须使用标准的IIOP协议进行通信。|
|客户端存根和服务器骨架|CORBA定义了接口定义语言(IDL),用于完全描述对象的公共接口。使用IDL,可生成客户端存根和服务器骨架代码,用于处理与ORB库的底层通信、控制网络连接以及数据的编组和解组。不同供应商的IDL编译器生成的代码实现可能不同,但类名和公共接口相同。例如,Visibroker根据服务端的位置优化通信方式,若服务端在同一进程中,使用本地方法调用,可大幅提高性能;若在同一机器的不同进程中,使用进程间通信方法,性能有一定提升;若在不同服务器上,则使用IIOP进行标准的CORBA调用。客户端存根用于创建客户端代理对象,透明地调用服务器对象的方法;服务器骨架为服务端提供CORBA功能框架,激活对象、监听网络连接并处理传入的调用。|
|对象适配器(OA)|管理服务端与ORB的交互。它生成对象引用并激活服务端,负责管理方法调用。早期的CORBA版本中,OA称为基本对象适配器(BOA),由于规范不完善,不同供应商的实现不同,导致服务端在不同供应商之间迁移困难。后来的规范将其重命名为可移植对象适配器(POA),POA提供了对服务端创建、生命周期、持久性和命名的控制。单个ORB可以创建多个POA,每个POA可以有不同的策略和服务端。|
|互操作性对象引用(IOR)和命名服务|每个服务端都可以生成一个IOR,它是一个标准引用,包含了与服务端进行通信所需的所有信息。IOR可以写成字符串形式,称为字符串化的IOR。客户端存根提供方法将字符串化的对象引用转换回对象引用。将IOR写入文件并与客户端应用程序共享不是一个好方法,因为每次运行对象时IOR可能会改变。CORBA定义了命名服务来解决这个问题,它是一个分层的命名图,使客户端应用程序能够找到并绑定到服务端。许多供应商提供了更易于使用的命名服务实现,例如Visibroker的OSAgent。OSAgent运行在一台机器上,提供扁平的命名空间。服务端使用UDP广播自动定位并注册到OSAgent,客户端应用程序通过调用绑定方法找到网络上的OSAgent并请求服务端,OSAgent将对象引用返回给客户端应用程序。|

以下是Visibroker客户端应用程序、服务端和OSAgent命名服务之间的交互流程:

graph LR
    A[启动OSAgent服务] --> B[启动服务端]
    B --> C[服务端广播本地子网查找OSAgent]
    C --> D[选择第一个响应的OSAgent]
    D --> E[服务端向OSAgent注册服务器名称]
    E --> F[服务端等待激活]
    G[客户端应用程序启动] --> H[客户端广播本地子网查找OSAgent]
    H --> I[选择第一个响应的OSAgent]
    I --> J[客户端调用服务端方法]
    J --> K[客户端向OSAgent请求服务端对象引用]
    K --> L[OSAgent返回对象引用]
    L --> M[客户端绑定对象引用并调用方法]
    M --> N[POA激活服务端并调用方法,返回结果给客户端]
    N --> O[客户端可继续使用对象,无需再次使用OSAgent]
2.3 接口定义语言(IDL)

IDL为服务端和访问服务端的应用程序之间提供了公共接口契约,对于创建可从任何平台上的任何语言访问的CORBA对象至关重要。实际的IDL文件是一个文本文件,JBuilder根据其 .IDL 文件扩展名识别它。

IDL使用一组定义好的数据类型和结构来建模公共接口,其中没有编程语句或变量定义。创建公共接口后,IDL编译器将IDL文件转换为所选语言的客户端存根和服务器骨架代码。这里的“编译器”并不进行真正的编译,只是生成文件。IDL模仿C++的语法,使用花括号、转义标识符和注释。

以下是一个示例IDL文件:

module ChalkTalk {
    typedef sequence<string> CourseName;
    interface CourseData {
        string getCourseList(inout CourseName names);
    };
};

该IDL文件的说明如下:
- module 语句指定了一个Java包名,包含在IDL中定义的接口。在上述示例中, ChalkTalk 模块生成一个名为 ChalkTalk 的Java包,模块内定义的所有接口和数据类型都将放在该包中。
- typedef 定义了一个新的数据类型 CourseName ,它是一个字符串序列,映射到Java数组。
- interface 表示一个CORBA对象,在示例中, CourseData 接口映射到一个名为 CourseData 的Java类,该类包含一个 getCourseList 方法,返回一个字符串,并将 CourseName 数据类型作为输入和输出参数。

IDL方法签名的格式为:
<return type> methodName( direction datatype name, direction datatype name, ...)
其中:
- return type 是有效的数据类型,包括用户定义的数据类型。
- direction 表示参数的流向,具体如下:
|方向|定义|
|----|----|
|in|数据从客户端传递到服务器|
|out|数据从服务器传递到客户端|
|inout|数据在客户端和服务器之间双向传递|
- 有效的数据类型包括用户定义的数据类型和基本数据类型,基本数据类型与Java数据类型的映射如下:
|IDL数据类型|Java数据类型|定义|
|----|----|----|
|boolean|boolean|标准的布尔值,真或假|
|char|char|IDL中char是8位值,Java中char是16位值。Java原生支持Unicode,即16位字符集。如果Java char超过8位值,会抛出CORBA数据转换异常|
|wchar|char|IDL扩展规范以包含Unicode和16位字符数据类型,IDL的wchar直接映射到Java char|

通过以上介绍,我们了解了消息驱动Bean和CORBA技术的基本概念、特点和使用方法。消息驱动Bean在JMS系统中提供了高效的消息处理能力,而CORBA则为分布式对象通信提供了跨平台和跨语言的解决方案。在实际应用中,我们可以根据具体需求选择合适的技术来构建分布式系统。

3. 构建CORBA服务器和客户端
3.1 构建CORBA服务器

构建CORBA服务器的关键步骤包括定义IDL接口、编译IDL文件、实现服务器端代码。

步骤1:定义IDL接口
我们可以使用之前提到的示例IDL文件 course.idl

module ChalkTalk {
    typedef sequence<string> CourseName;
    interface CourseData {
        string getCourseList(inout CourseName names);
    };
};

这个IDL文件定义了一个模块 ChalkTalk ,其中包含一个新的数据类型 CourseName 和一个接口 CourseData ,接口中有一个方法 getCourseList

步骤2:编译IDL文件
使用Visibroker的 idl2java 编译器(位于Borland Enterprise Server目录的 bin 子目录)来编译IDL文件。编译后会生成一系列Java文件,包括客户端存根和服务器骨架代码。

步骤3:实现服务器端代码
以下是一个简单的服务器端代码示例:

import ChalkTalk.*;
import org.omg.CORBA.*;
import org.omg.PortableServer.*;

public class CourseDataServer {
    public static void main(String[] args) {
        try {
            // 初始化ORB
            ORB orb = ORB.init(args, null);

            // 获取根POA的引用
            org.omg.CORBA.Object poaObj = orb.resolve_initial_references("RootPOA");
            POA rootPOA = POAHelper.narrow(poaObj);
            rootPOA.the_POAManager().activate();

            // 创建服务端实例
            CourseDataImpl courseDataImpl = new CourseDataImpl();

            // 将服务端对象转换为CORBA对象引用
            org.omg.CORBA.Object ref = rootPOA.servant_to_reference(courseDataImpl);
            CourseData href = CourseDataHelper.narrow(ref);

            // 将对象引用绑定到命名服务(这里假设使用OSAgent)
            // 具体绑定代码根据命名服务实现不同而不同
            // 例如,使用OSAgent时,服务端会自动注册

            // 等待客户端请求
            System.out.println("CourseDataServer ready and waiting ...");
            orb.run();
        } catch (Exception e) {
            System.err.println("ERROR: " + e);
            e.printStackTrace(System.out);
        }
    }
}

class CourseDataImpl extends CourseDataPOA {
    @Override
    public String getCourseList(org.omg.CORBA.StringSeqHolder names) {
        // 实现具体的业务逻辑
        names.value = new String[]{"Course1", "Course2", "Course3"};
        return "Course list retrieved successfully";
    }
}

在这个示例中,我们首先初始化了ORB,获取了根POA的引用并激活它。然后创建了服务端实例,并将其转换为CORBA对象引用。最后,服务端等待客户端的请求。

3.2 构建CORBA客户端

构建CORBA客户端的步骤包括编译IDL文件(与服务器端相同)、实现客户端代码。

步骤1:编译IDL文件
同样使用 idl2java 编译器编译之前的 course.idl 文件,生成客户端所需的存根代码。

步骤2:实现客户端代码
以下是一个简单的客户端代码示例:

import ChalkTalk.*;
import org.omg.CORBA.*;

public class CourseDataClient {
    public static void main(String[] args) {
        try {
            // 初始化ORB
            ORB orb = ORB.init(args, null);

            // 获取命名服务对象引用(这里假设使用OSAgent)
            // 具体获取代码根据命名服务实现不同而不同
            // 例如,使用OSAgent时,客户端通过广播查找
            org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
            org.omg.CosNaming.NamingContextExt ncRef = org.omg.CosNaming.NamingContextExtHelper.narrow(objRef);

            // 绑定到服务端对象
            org.omg.CORBA.Object courseDataObj = ncRef.resolve_str("CourseData");
            CourseData courseData = CourseDataHelper.narrow(courseDataObj);

            // 调用服务端方法
            org.omg.CORBA.StringSeqHolder names = new org.omg.CORBA.StringSeqHolder();
            String result = courseData.getCourseList(names);

            // 输出结果
            System.out.println("Result: " + result);
            System.out.println("Course list:");
            for (String name : names.value) {
                System.out.println(name);
            }
        } catch (Exception e) {
            System.err.println("ERROR: " + e);
            e.printStackTrace(System.out);
        }
    }
}

在这个示例中,我们首先初始化了ORB,然后获取命名服务对象引用,通过命名服务绑定到服务端对象。接着调用服务端的 getCourseList 方法,并输出结果。

4. 总结与思考

消息驱动Bean和CORBA技术在分布式系统开发中都有着重要的作用。消息驱动Bean为JMS系统提供了高效的消息处理机制,使得开发者可以专注于业务逻辑的实现,同时享受EJB容器提供的各种服务。而CORBA则为分布式对象通信提供了跨平台、跨语言的解决方案,通过IDL定义接口,使得不同语言编写的对象可以方便地进行交互。

在实际应用中,我们需要根据具体的需求来选择合适的技术。如果主要关注消息处理和异步通信,消息驱动Bean可能是一个不错的选择;如果需要构建分布式系统,实现不同平台和语言之间的对象通信,CORBA则更具优势。

同时,我们也应该思考一些问题,例如在使用CORBA时,如何选择合适的命名服务实现,如何优化ORB的性能等。在使用消息驱动Bean时,如何确保消息的顺序性和持久性等。通过不断地学习和实践,我们可以更好地掌握这些技术,构建出更加高效、稳定的分布式系统。

总之,消息驱动Bean和CORBA技术为我们提供了强大的工具,帮助我们应对分布式系统开发中的各种挑战。在未来的开发中,我们可以根据具体场景灵活运用这些技术,创造出更有价值的应用。

考虑可再生能源出力不确定性的商业园区用户需求响应策略(Matlab代码实现)内容概要:本文围绕“考虑可再生能源出力不确定性的商业园区用户需求响应策略”展开,结合Matlab代码实现,研究在可再生能源(如风电、光伏)出力具有不确定性的背景下,商业园区如何制定有效的需求响应策略以优化能源调度和提升系统经济性。文中可能涉及不确定性建模(如场景生成缩减)、优化模型构建(如随机规划、鲁棒优化)以及需求响应机制设计(如价格型、激励型),并通过Matlab仿真验证所提策略的有效性。此外,文档还列举了大量相关的电力系统、综合能源系统优化调度案例代码资源,涵盖微电网调度、储能配置、负荷预测等多个方向,形成一个完整的科研支持体系。; 适合人群:具备一定电力系统、优化理论和Matlab编程基础的研究生、科研人员及从事能源系统规划运行的工程技术人员。; 使用场景及目标:①学习如何建模可再生能源的不确定性并应用于需求响应优化;②掌握使用Matlab进行商业园区能源系统仿真优化调度的方法;③复现论文结果或开展相关课题研究,提升科研效率创新能力。; 阅读建议:建议结合文中提供的Matlab代码实例,逐步理解模型构建求解过程,重点关注不确定性处理方法需求响应机制的设计逻辑,同时可参考文档中列出的其他资源进行扩展学习交叉验证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值