分布式对象是可从远程系统调用的对象。进程内客户端、进程外客户端或位于其他位置的客户端(在网络上)可以调用它。下图显示了客户端如何调用分布式对象。
Stub是一个客户端代理对象。它屏蔽了来自客户端的网络通信。使用套接字,按摩参数,存根可以通过网络调用。
Skeleton是一个服务器端代理。它屏蔽了分布式对象的网络通信。 Skeleton 负责接收套接字上的调用并且它知道如何去做。它知道如何将参数从网络表示传递到Java表示。
从客户端调用分布式对象的步骤如下:
- 客户端调用存根。
- Stub 通过网络调用骨架。
- 然后骨架将调用委托给适当的实现对象。完成工作后,此对象将控制权返回给骨架,骨架返回给存根,然后将控制权返回给客户端。
Note: Both stub & server-side implementation object must implement the same interface which is called remote interface.
这意味着分布式对象签名的克隆是由存根完成的。这里的客户端认为他是直接调用分布式对象,但实际上,他调用的是存根上的一个方法。因此,我们可以得出结论,分布对象是由存根、骨架和实现对象之间的合作创建的抽象。这里没有单个实体是分布式对象。
中间件服务:随着分布式对象的应用程序变大,需要诸如事务和安全等中间件服务。有2种获取方式:
- 显式中间件,我们显式获取中间件
- 隐式中间件,我们隐式获取中间件
显式中间件:您可以购买中间件并编写调用中间件 API 的代码。这样的过程被传统的分布式对象编程(如CORBA)使用。
示例:您可以通过写入交易 API 来获得交易,如下所示:
transferAmount(Account acc1, Account acc2, long amount)
{
// 1. Call middleware API to perform a security check
// 2. Call middleware API to start a transaction
// 3. Call middleware API to load rows from the database.
// 4. Subtract the balance from one account(acc1), add to the other(acc2)
// 5. Call middleware API to store updated rows in the database
// 6. // 1. Call middleware API to end the transaction
}
输出说明:
这里的transferAmount()是一个方法,它采用 Account 类型的 acc1、Account 类型的 acc2 和 long 类型的金额 3 个输入参数。调用此方法将金额从 acc1 转移到 acc2。
示例:这里可以将 Account 视为一个类,它的每个对象都指向不同的帐号。
在这里,业务逻辑与调用中间件 API 的逻辑交织在一起。
隐式中间件是没有的 写入中间件 API,您可以在企业应用程序中利用复杂的中间件。需要按照以下步骤来利用中间件的力量,如下图所示
程序:步骤如下:
- 不要写入复杂的中间件 API,将分布式对象写入仅包含业务逻辑。
- 在单独的描述符文件(例如纯文本文件)中,声明您的对象需要的中间件服务。示例:您可以声明您需要事务、安全性和持久性检查。
- 中间件供应商为您提供命令行工具,运行该工具。此工具将您的描述符文件作为输入并生成一个对象。我们称该对象为请求拦截器。
- 客户端的请求由请求拦截器接收。然后它执行您的分布式对象需要的中间件并将调用委托给分布式对象
示例:将在分布式对象中运行的代码是:
transferAmount(Account acc1, Account acc2, long amount){
// 1. subtract the amount from the balance of acc1 & add amount to balance of acc2
}
下面以表格形式显示了显式和隐式中间件之间的差异
Explicit Middleware |
Implicit Middleware |
---|---|
Here, business logic is intertwined with the logic to call the middleware APIs. | Do not write to complex middleware APIs, write the distributed object to contain only business logic. |
Difficult to maintain: Need to rewrite your code if you want to change the way you do middleware. | Easy to maintain: No need to rewrite your code if you want to change the way you do middleware. |
Difficult to write: To perform simple operations, it requires a large amount of code. | Easy to write: No need to write any code to middleware APIs, just declare what you need in the descriptor file |
Difficult to support: The customers cannot change their middleware( such as changing how security works) | Difficult to support: The customers can change the middleware they need by tweaking the descriptor file. |
No descriptor file is required here. | We need to write a separate descriptor file. |
Request interceptor is not required. | Request interceptor is required. |