JWorkPlace 应用开发全解析
在软件开发领域,JWorkPlace 应用凭借其独特的功能和架构,为用户提供了强大的服务和便捷的交互体验。本文将深入探讨 JWorkPlace 应用中的多个关键部分,包括内容空间管理、消息服务、客户端服务发现、ServiceUI 项目以及应用的运行步骤等。
内容空间管理
在 JWorkPlace 中,内容空间管理是一个重要的功能。通过
getContentSpace
方法,可以检查访客是否已有定义的内容列表,并根据需要授予文件访问权限。以下是该方法的代码实现:
public ContentMap[] getContentSpace(String user) throws RemoteException, IOException {
List userSpaceList = (List)userMap.get(user);
if(userSpaceList == null)
return new ContentMap[0];
ArrayList contentList = new ArrayList(userSpaceList);
if(groupMap.containsKey(user)) {
List groupContent = (List)groupMap.get(user);
contentList.addAll(groupContent);
}
return (ContentMap[])contentList.toArray(new ContentMap[0]);
}
这个方法的逻辑是,首先从
userMap
中获取用户的内容空间列表。如果列表为空,则返回一个空的
ContentMap
数组。接着,将用户的内容空间列表添加到
contentList
中。如果
groupMap
中包含该用户,则将该用户所在组的内容也添加到
contentList
中。最后,将
contentList
转换为
ContentMap
数组并返回。
消息服务
消息服务是 JWorkPlace 中的一个重要组成部分,它是对第五章“JavaSpaces 服务”中开发的聊天应用的改进版本。
MessengerInterface
为 JavaSpace API 提供了简化的包装,而
MessengerService
实现了该接口。以下是
MessengerInterface
的代码:
package org.jworkplace.chat;
import java.rmi.RemoteException;
import java.rmi.MarshalledObject;
import java.io.IOException;
import net.jini.core.entry.Entry;
import net.jini.core.transaction.TransactionException;
import net.jini.core.entry.UnusableEntryException;
public interface MessengerInterface extends java.io.Serializable {
public Entry read(Entry template) throws RemoteException, TransactionException, UnusableEntryException, InterruptedException;
public Entry readIfExists(Entry template) throws RemoteException, TransactionException, UnusableEntryException, InterruptedException;
public void write(Entry entry) throws RemoteException, TransactionException, UnusableEntryException, InterruptedException;
public void write(Entry entry, long leaseTime) throws RemoteException, TransactionException, UnusableEntryException, InterruptedException;
public Entry take(Entry entry) throws RemoteException, TransactionException, UnusableEntryException, InterruptedException;
public Entry takeIfExists(Entry entry) throws RemoteException, TransactionException, UnusableEntryException, InterruptedException;
}
在 JWorkPlace 示例应用中,通信通道与活动的内容空间名称相关联。当激活一个内容空间时,就会使用 JavaSpaces 激活一个消息通道,从而可以向共享或有权访问该空间的所有成员发送消息。此外,还有一个默认通道
WorkPlaceChannel
,可用于向所有工作场所成员广播消息。
客户端服务发现
客户端服务发现是 JWorkPlace 中客户端开发的一个关键问题。
net.jini.lookup.ServiceDiscoveryManager
为客户端提供了服务发现支持。在 JWorkPlace 中,定义了两个辅助类
ClientStarter
和
ClientLookup
来使用该管理器。
ClientLookup
类的代码如下:
package org.jworkplace.client;
import net.jini.core.lookup.ServiceItem;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.lookup.ServiceDiscoveryManager;
import net.jini.lookup.LookupCache;
import net.jini.lookup.ServiceItemFilter;
import net.jini.lookup.ServiceDiscoveryListener;
import net.jini.discovery.DiscoveryManagement;
import net.jini.lease.LeaseRenewalManager;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
public class ClientLookup {
protected ServiceDiscoveryManager lookupMgr;
public ClientLookup() throws IOException {
this(null, null);
}
public ClientLookup(DiscoveryManagement discMgr, LeaseRenewalManager leaseMgr) throws IOException {
if (System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
}
lookupMgr = new ServiceDiscoveryManager(discMgr, leaseMgr);
}
public ServiceDiscoveryListener getListener() {
return null;
}
public ServiceItemFilter getFilter() {
return null;
}
public boolean requiredFailureAction(ServiceTemplate template) {
System.out.println(template);
return false;
}
public ServiceRegistrar getLookupService() throws RemoteException {
ServiceRegistrar registrar = null;
Class[] types = {ServiceRegistrar.class};
ServiceTemplate tmpl = new ServiceTemplate(null, types, null);
ServiceItem item = getServiceItem(tmpl);
if (!(item.service instanceof ServiceRegistrar)) {
throw new RemoteException();
}
return (ServiceRegistrar)item.service;
}
public ServiceItem getServiceItem(ServiceTemplate template) {
ServiceItem service = null;
try {
service = lookupMgr.lookup(template, getFilter(), 10000);
} catch (RemoteException ex) {
ex.printStackTrace();
} catch (InterruptedException ex) {}
if (service == null) {
boolean result = requiredFailureAction(template);
if (result) System.exit(1);
}
return service;
}
public ServiceItem[] getServiceItems(ServiceTemplate template) {
ServiceItem[] service = new ServiceItem[0];
try {
service = lookupMgr.lookup(template, 1, Integer.MAX_VALUE, getFilter(), 10000);
} catch (RemoteException ex) {
ex.printStackTrace();
} catch (InterruptedException ex) {}
if (service == null) {
boolean result = requiredFailureAction(template);
if (result) System.exit(1);
}
return service;
}
public LookupCache createCache(ServiceTemplate template) throws RemoteException {
return lookupMgr.createLookupCache(template, getFilter(), getListener());
}
public void terminate() {
lookupMgr.terminate();
}
}
ClientLookup
类的主要功能是使用
ServiceDiscoveryManager
进行服务发现。在构造函数中,会创建
ServiceDiscoveryManager
实例,并设置安全管理器。通过
getServiceItem
和
getServiceItems
方法可以查找单个或多个服务。同时,还提供了创建客户端缓存和终止发现过程的方法。
需要注意的是,
ServiceDiscoveryManager
会导出一个远程
ServiceDiscoveryListener
对象,因此客户端必须运行一个 HTTP 服务器,并提供代码库,以便查找服务能够访问必要的类。客户端的 jar 文件中需要包含以下四个文件:
-
net.jini.core.event.RemoteEvent.class
-
net.jini.core.event.RemoteEventListener.class
-
net.jini.core.event.UnknownEventException.class
-
net.jini.lookup.ServiceDiscoveryManager$LookupCacheImpl$LookupListener_Stub.class
ServiceUI 项目
ServiceUI 项目是 Jini 社区的一个项目,旨在标准化 Jini 服务的用户界面。该项目定义了三个用于将用户界面与 Jini 服务关联的项目:用户界面本身、生成 UI 的用户界面工厂以及描述 UI 的用户界面描述符。
以下是创建
UIDescriptor
条目的代码示例:
// describe the UI in a Set
Set typeNames = new HashSet();
// signifies this factory produces a JFrame
typeNames.add(JFrameFactory.TYPE_NAME);
Set attribs = new HashSet();
attribs.add(new UIFactoryTypes(typeNames));
// create the factory object
MarshalledObject factory = null;
try {
// WorkPlaceFactory implements the factory method
factory = new MarshalledObject(new WorkPlaceFactory());
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
// Create the UIDescriptor entry
Entry[] entries = new UIDescriptor(MainUI.ROLE, // Role string
WorkPlaceFactory.TOOLKIT, // Toolkit string
attribs, // attribute objects
factory); // UI factory
当前版本的 Jini 服务 UI API 定义了八个工厂接口,包括
DialogFactory
、
FrameFactory
、
JComponentFactory
等。这些接口用于生成不同类型的用户界面。
WorkPlaceFactory
类实现了
JFrameFactory
接口,用于创建
WorkPlaceFrame
:
package org.jworkplace.workplace;
import javax.swing.JFrame;
import net.jini.core.entry.Entry;
import net.jini.core.lookup.ServiceItem;
import net.jini.lookup.entry.UIDescriptor;
import net.jini.lookup.ui.attribute.UIFactoryTypes;
import net.jini.lookup.ui.factory.JFrameFactory;
import net.jini.lookup.ui.MainUI;
public class WorkPlaceFactory implements JFrameFactory {
public JFrame getJFrame(Object obj) {
if (!(obj instanceof ServiceItem)) {
return null;
}
ServiceItem item = (ServiceItem)obj;
// Get the attribute set
Entry[] entries = item.attributeSets;
// loop through attributes looking for UIDescriptor
for (int i = 0; i < entries.length; i++) {
if (entries[i] instanceof UIDescriptor) {
UIDescriptor descriptor = (UIDescriptor)entries[i];
// Ensure the role of this descriptor is for the MainUI
if (descriptor.role.equals(net.jini.lookup.ui.MainUI.ROLE)) {
// Now create JFrame for WorkPlace, passing the ServiceItem
JFrame frame = new WorkPlaceFrame(item, FRAME_TITLE);
return frame;
}
}
}
return null;
}
}
WorkPlaceFrame
类则确保
ServiceItem
实现了
IndexManager
接口,并初始化
WorkPlaceController
:
package org.jworkplace.workplace;
import net.jini.core.lookup.ServiceItem;
import net.jini.lookup.ui.MainUI;
import org.jworkplace.client.ServiceFrame;
import org.jworkplace.content.IndexManager;
public class WorkPlaceFrame extends ServiceFrame {
public WorkPlaceFrame(ServiceItem item, String name) {
super(item, name);
if (item.service instanceof IndexManager) {
WorkPlaceController workPlace = new WorkPlaceController();
workPlace.initialize(item.service);
getContentPane().add(workPlace);
this.pack();
}
}
}
应用运行步骤
要运行 JWorkPlace,需要按照以下步骤进行操作:
1.
启动共享服务器
:
- 切换到相关目录,找到
services/scripts
目录下的
startShare.cmd
脚本。
- 编辑
PORT
和
MYSHARE
变量,使其与你的安装相匹配。默认情况下,脚本使用端口 8081 和目录
chapter10\example1\MySpace
作为内容共享目录。
- 运行脚本:
C:\JiniJavaSpaces\Chapter10\services\scripts>startShare
以下是
startShare.cmd
脚本的内容:
@echo off
@call setup.cmd
set PORT=8081
set MYSHARE=chapter10\example1\MySpace
echo Jini and JavaSpaces Application Development
echo -------------------------------------------
echo Jini install directory %JINI_HOME%
echo Examples install directory %JWORK_HOME%
echo Default share port %PORT%
echo Default share space %JWORK_HOME%\%MYSHARE%
echo -------------------------------------------
echo Starting the Share Server...
java -jar %JINI_HOME%\lib\tools.jar -port 8081 -dir %JWORK_HOME%\%MYSHARE% -trees -verbose
-
启动事务服务和 JavaSpaces 服务
:
-
检查
services/scripts目录下的startMahalo.cmd和startOutrigger.cmd脚本,并运行它们,以确保mahalo事务服务和outriggerJavaSpaces 服务正常运行。
-
检查
-
启动工作场所服务
:
-
运行
services/scripts目录下的startWorkPlace1.cmd脚本:
-
运行
C:\JiniJavaSpaces\chapter10\services\scripts\startWorkPlace1.cmd
-
启动客户端
:
-
编辑
chapter10/example1目录下的startClient.cmd脚本,设置以下两个属性:
-
编辑
-Dorg.jworkplace.workport=%PORT%
-Dorg.jworkplace.workspace=%MYSHARE%
确保这些属性与
startShare.cmd
脚本中设置的
PORT
和
MYSHARE
变量相匹配。
- 运行脚本:
C:\JiniJavaSpaces\chapter10\example1\startClient.cmd
在运行 JWorkPlace 应用后,你需要创建一个账户,然后创建一个共享空间,将本地目录映射到内容空间名称。可以使用“Add”按钮将文件添加到共享空间中。同时,通过界面的左右面板,你可以查看已定义的空间和所有用户,并通过选择表格中的条目并按下“share”按钮来将空间映射到用户。
通过以上步骤和功能介绍,你可以全面了解 JWorkPlace 应用的开发和运行过程,包括内容空间管理、消息服务、客户端服务发现、ServiceUI 项目等方面的知识。希望这些内容能帮助你更好地使用和开发 JWorkPlace 应用。
JWorkPlace 应用开发全解析(续)
服务 UI 项目深入分析
在上半部分我们介绍了 ServiceUI 项目的基本概念和部分代码实现,接下来我们进一步深入分析其相关类和接口。
服务 UI 工厂接口
当前版本的 Jini 服务 UI API 定义了八个工厂接口,这些接口在创建不同类型的用户界面时发挥着重要作用。以下是这些接口及其功能的详细介绍:
| 接口名称 | 功能描述 |
|---|---|
DialogFactory
|
返回一个依赖于 AWT 库但不依赖于 Swing 库的
java.awt.Dialog
或其子类的实例
|
FrameFactory
|
返回一个依赖于 AWT 库但不依赖于 Swing 库的
java.awt.Frame
或其子类的实例
|
JComponentFactory
|
返回一个依赖于 AWT 和 Swing 库的
javax.swing.JComponent
或其子类的实例
|
JDialogFactory
|
返回一个依赖于 AWT 和 Swing 库的
javax.swing.JDialog
或其子类的实例
|
JFrameFactory
|
返回一个依赖于 AWT 和 Swing 库的
javax.swing.JFrame
或其子类的实例
|
JWindowFactory
|
返回一个依赖于 AWT 和 Swing 库的
javax.swing.JWindow
或其子类的实例
|
PanelFactory
|
返回一个依赖于 AWT 库但不依赖于 Swing 库的
java.awt.Panel
或其子类的实例
|
WindowFactory
|
返回一个依赖于 AWT 库但不依赖于
Frame
或
Dialog
的
java.awt.Window
或其子类的实例
|
这些工厂接口为开发者提供了丰富的选择,使得可以根据不同的需求创建出多样化的用户界面。
WorkPlaceFactory 类的工作流程
WorkPlaceFactory
类实现了
JFrameFactory
接口,其主要功能是创建
WorkPlaceFrame
。下面是其工作流程的 mermaid 流程图:
graph TD;
A[调用 getJFrame 方法] --> B{传入对象是否为 ServiceItem};
B -- 否 --> C[返回 null];
B -- 是 --> D[获取 ServiceItem 的属性集];
D --> E[遍历属性集查找 UIDescriptor];
E -- 未找到 --> C;
E -- 找到 --> F{UIDescriptor 的角色是否为 MainUI};
F -- 否 --> C;
F -- 是 --> G[创建 WorkPlaceFrame 并返回];
从流程图可以清晰地看到,
WorkPlaceFactory
类首先会检查传入的对象是否为
ServiceItem
,如果不是则直接返回
null
。如果是,则获取其属性集并遍历查找
UIDescriptor
。找到后,会检查其角色是否为
MainUI
,如果是则创建并返回
WorkPlaceFrame
,否则返回
null
。
服务控制器类分析
在 JWorkPlace 应用中,服务控制器类负责初始化和管理与服务相关的用户界面组件。下面我们详细分析几个重要的服务控制器类。
ServiceController 类
ServiceController
是一个抽象类,它定义了一个抽象方法
initialize
,用于初始化服务对象。以下是其代码:
import javax.swing.JComponent;
public abstract class ServiceController extends JComponent {
abstract public void initialize(Object service);
}
这个抽象类为具体的服务控制器类提供了一个统一的接口,使得不同的服务控制器可以按照相同的方式进行初始化。
AccountController 类
AccountController
是
ServiceController
的一个具体实现类,它用于初始化与
AccountManager
相关的用户界面组件。以下是其代码:
import java.awt.BorderLayout;
import org.jworkplace.ui.ServiceController;
import org.jworkplace.client.WorkPlaceClient;
public class AccountController extends ServiceController {
private AccountEditor editor;
private AccountModel model;
private static String accountMgrClass = AccountManager.class.getName();
public AccountController() {
super();
}
public void initialize(Object object) {
AccountManager accountMgr = null;
if (object instanceof AccountManager)
accountMgr = (AccountManager) object;
else
accountMgr = getServiceInterface();
model = new AccountModel(accountMgr);
editor = new AccountEditor(model);
setLayout(new BorderLayout());
add(editor, BorderLayout.CENTER);
}
public AccountManager getServiceInterface() {
AccountManager manager = null;
try {
manager = (AccountManager) WorkPlaceClient.getServiceInterface(Class.forName(accountMgrClass));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return manager;
}
}
AccountController
类的
initialize
方法首先会检查传入的对象是否为
AccountManager
,如果是则直接使用该对象,否则通过
getServiceInterface
方法获取
AccountManager
实例。然后,它会创建
AccountModel
和
AccountEditor
,并将
AccountEditor
添加到界面中。
JWorkPlace 应用的使用场景和优势
JWorkPlace 应用在团队协作和资源共享方面具有显著的优势,以下是一些具体的使用场景和优势分析。
使用场景
- 团队协作 :团队成员可以通过 JWorkPlace 的消息服务进行实时沟通,同时可以共享和管理团队的文档和资源。例如,在一个项目开发过程中,团队成员可以在共享空间中上传和下载项目文档,通过消息通道交流项目进展和问题。
- 资源管理 :用户可以将本地目录映射到内容空间名称,方便地管理和共享自己的文件。同时,通过内容空间管理功能,可以控制不同用户对文件的访问权限。
优势
- 标准化用户界面 :ServiceUI 项目为 Jini 服务提供了标准化的用户界面,使得不同的服务可以具有统一的外观和操作方式,提高了用户体验。
-
便捷的服务发现
:通过
ServiceDiscoveryManager和相关辅助类,客户端可以方便地发现和使用所需的服务,减少了开发的复杂度。 - 丰富的功能模块 :JWorkPlace 应用包含了内容空间管理、消息服务、账户管理等多个功能模块,满足了用户在不同场景下的需求。
总结
通过对 JWorkPlace 应用的全面分析,我们了解了其内容空间管理、消息服务、客户端服务发现、ServiceUI 项目等方面的功能和实现细节。同时,我们也介绍了服务 UI 项目的工厂接口、服务控制器类的作用以及 JWorkPlace 应用的使用场景和优势。
在实际开发和使用过程中,开发者可以根据自己的需求对这些功能进行定制和扩展,充分发挥 JWorkPlace 应用的优势。希望本文能为开发者和使用者提供有价值的参考,帮助他们更好地理解和应用 JWorkPlace 应用。
超级会员免费看
3029

被折叠的 条评论
为什么被折叠?



