WebLogicRMI与JMS的深入解析
立即解锁
发布时间: 2025-08-24 00:57:21 阅读量: 1 订阅数: 7 

### WebLogic RMI与JMS的深入解析
#### 1. WebLogic RMI的应用与特性
在证券系统中,我们有不同的客户端和服务器协同工作。`MarketMakerClient` 负责设置价格,`QuoteClient` 用于获取报价,`PriceServerImpl` 作为RMI服务器处理客户端请求。以下是 `QuoteClient` 和 `PriceServerImpl` 的输出示例:
**QuoteClient输出示例**
```plaintext
QuoteClient started.
QuoteClient getting quotes.
Quote time: Mon Apr 30 13:33:44 PDT 2001
Security: SUNW Price: 20.25
Security: INTC Price: 30.5
Security: BEAS Price: 39.75
QuoteClient getting quotes.
Quote time: Mon Apr 30 13:34:04 PDT 2001
Security: SUNW Price: 20.5
Security: INTC Price: 30.25
Security: BEAS Price: 40
```
**PriceServerImpl输出示例**
```plaintext
PriceServer: Call to setPrice for SUNW to 20.25
PriceServer: Call to setPrice for INTC to 30.5
PriceServer: Call to setPrice for BEAS to 39.75
PriceServer: Call to getPrice for symbol : SUNW
PriceServer: Call to getPrice for symbol : INTC
PriceServer: Call to getPrice for symbol : BEAS
PriceServer: Call to setPrice for SUNW to 20.5
PriceServer: Call to setPrice for INTC to 30.25
PriceServer: Call to setPrice for BEAS to 40
PriceServer: Call to getPrice for symbol : SUNW
PriceServer: Call to getPrice for symbol : INTC
PriceServer: Call to getPrice for symbol : BEAS
```
##### 1.1 单向通信的局限与双向通信的引入
当前的架构中,客户端到服务器的通信是单向的。这种架构在大多数情况下可行,但存在一些弱点。例如,当客户端调用服务器上的长时间运行方法时,如果是同步调用,客户端线程会被阻塞直到服务器方法返回;如果是异步调用,客户端无法得知服务器方法何时完成。
为了解决这个问题,引入了 `TradingClient`。`TradingClient` 会异步地向 `PriceServerImpl` 下达股票市场订单。`PriceServerImpl` 在人为延迟后执行订单,并通知 `TradingClient` 订单执行情况,这就需要 `PriceServerImpl` 和 `TradingClient` 之间进行双向通信。
```mermaid
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A([TradingClient]):::startend -->|异步下订单| B([PriceServerImpl]):::startend
B -->|通知订单执行情况| A
```
##### 1.2 订单和执行信息的传输
为了实现双向通信,创建了 `Order` 和 `Execution` 两个类,它们需要实现 `java.io.Serializable` 接口,以便通过RMI传输。
```java
public class Order implements java.io.Serializable {
private int number; // unique order number
private String symbol; // ticker symbol
private int shares; // number of shares to purchase
// plus method definitions
}
public class Execution implements java.io.Serializable {
private int number; // copied from order number
private String symbol; // ticker symbol
private int shares; // number of shares purchased
private float price; // price per share at execution
// plus method definitions
}
```
##### 1.3 TradingClient的实现
`TradingClient` 继承自 `java.util.TimerTask`,每30秒提交一个新订单。以下是提交订单的代码:
```java
// Get the list of securities managed by the server.
String securities[] = server.getSecurities();
// Create a new Order instance
Order order = new Order();
Random rand = new Random();
// Increment the order number
order.setNumber(++orderNumber);
// Choose one of the available securities at random
order.setSymbol(securities[rand.nextInt(securities.length)]);
// Choose a random number of shares
order.setShares(rand.nextInt(1000) + 1);
// Enter the order via a remote call to the server.
// Pass a reference to ourselves so the server can call back.
server.enterMarketOrder(order, this);
```
##### 1.4 PriceServerImpl的实现
`PriceServerImpl` 的 `enterMarketOrder` 方法异步处理订单,它会启动一个新线程来执行订单。
```java
public void enterMarketOrder(Order order, ExecutionAlert clientRef) {
// Receives an order from a client, and also a
// reference to the client. Spawns a new thread
// to execute the trade (which may take some time),
// then returns.
System.out.println("A client has placed an order!");
System.out.println("Time: " + new Date());
System.out.println(order + "\n");
DoExecution exec = new DoExecution(order, clientRef);
new Thread(exec).start();
}
// Inner class to handle order executions.
private class DoExecution implements Runnable {
private Order order;
private ExecutionAlert client;
public DoExecution(Order ord, ExecutionAlert clientRef) {
order = ord;
client = clientRef;
}
public void run() {
try {
// Wait 10 seconds to simulate submission of the order
// to a stock exchange.
Thread.currentThread().sleep(10000);
// Create an Execution instance and execute the order.
Execution execution = new Execution();
// Copy order data into the execution.
execution.setNumber(order.getNumber());
execution.setSymbol(order.getSymbol());
execution.setShares(order.getShares());
// Execute at the stock’s current price and write a
// status message to standard output.
execution.setPrice(getPrice(order.getSymbol()));
System.out.println("An order has been executed!");
System.out.println("Time: " + new Date());
System.out.println(execution + "\n");
// Make a remote call to the client to notify them
// of the execution.
client.notifyOfExecution(execution);
} catch (Exception e) {
e.printStackTrace();
}
}
}
```
#### 2. 客户端方法的调用与注册
`TradingClient` 的 `notifyOfExecution` 方法只是简单地将订单执行信息输出到标准输出。
```java
public void notifyOfExecution(Execution exec) {
System.out.println("An order has been executed!");
System.out.println("Time: " + new Date());
System.out.println(exec + "\n");
}
```
客户端可以实现扩展 `weblogic.rmi.remote` 的接口,并在WebLogic的类路径中提供客户端远程方法的存根,这样客户端之间或服务器就可以调用这些方法。
也可以将 `TradingClient` 注册到RMI注册表中:
```java
TradingClient client = new TradingClient();
Context ctx = Environment.getInitialContext();
ctx.bind("TradingClient", client);
System.out.println("TradingClient was started and bound " +
"in the registry to the name " +
"TradingClient");
```
从另一个客户端调用 `TradingClient` 的远程方法:
```java
InitialContext ctx = Environment.getInitialContext();
ExecutionAlert tc = (ExecutionAlert) ctx.lookup("TradingClient");
Execution exec = new Execution();
tc.notifyOfExecution(exec);
```
#### 3. 从RMI服务器调用EJB
在设计中引入了会话EJB `ExecuteTrade`,将执行代码从 `PriceServerImpl` 移到 `ExecuteTrade` 中。
```java
public void enterMarketOrder(Order order, ExecutionAlert client) {
try {
// Create a context with which to lookup
```
0
0
复制全文
相关推荐








