2007年5月25日星期五

Java RMI 极速攻略

回家作业上要用到RMI,这两天抽了点时间学习了一下,感觉上手还算简单,但有些设置之类的时间长了怕记不住,因此花点时间写了这个入门攻略。

---------------------------------

RMI简介

RMI就是Remote Method Invocation,类似与RPC。 它的原理同CORBA, DCOM,.net remoting相似,但是比他们要简单很多。详细的介绍可以看参考资料部分的[SUN公司的RMI教程]http://java.sun.com/developer/onlineTraining/rmi/RMI.html

实做

下面分几步来完成一个简单例子----login(这个功能用的快烂了)

想法是,server端程序提供接口方法login,接收两个参数,用户名和密码,为了简单起见,我们直接返回true。在client端调用server端的方法,看看是否能够顺利返回true。

该程序没有任何意义,仅仅用于演示RMI的开发过程。

1. 定义远程接口

远程接口如下:(ICustomer.java)

import java.rmi.Remote;
import java.rmi.RemoteException;
//
// This is remote interface for Customer
public interface ICustomer extends Remote{

public boolean login(String username, String password)
throws RemoteException;
}

2. 实现远程接口

实现文件是真正的业务逻辑所在。和RMI基本上没有任何关系。

要注意的是

  • 类要继承java.rmi.UnicastRemoteObject 并且实现刚才定义的接口。
  • 每个方法都要抛RemoteException
  • 要有显示的构造函数

实现文件如下: (ICustomerImpl.java)

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;


public class ICustomerImpl extends UnicastRemoteObject
implements ICustomer{

public ICustomerImpl() throws RemoteException{
}
public boolean login(String username, String password )
throws RemoteException{
return true;

}
}

3. 服务器端启动程序

服务器端启动程序做两件事

  • 加载服务器端对象到JVM中
  • 将该对象注册到RMI Registry

在这个例子里面,我使用的是一般的控制台程序,据说可以用Tomcat代替,我想这个应该是可行的。毕竟,只要有个JVM能够加载对象,就能把对象注册到RMI Registry里面去。

代码如下(Server.java):

import java.rmi.Naming;

public class Server.java{
public static void main(String[] arg){
try{
ICustomerImpl cu = new ICustomerImpl();
//创建服务器端对象
Naming.rebind("cust", cu);
//注册
}catch(Exception e){
System.err.println("launcher error");
e.printStackTrace();
}
}
}

4. 编译服务器端程序

先假设所有的代码都放在d:\rmitest\下面

先到该目录下,编译所有的代码

javac Server.java

接下来,肉戏来了,需要用rmic来编译实现文件产生存根(stub),如果对这个词不是很了解,请参考一些跨进程访问的资料,一般的解决方案都是用存根/代理实现。

rmic -keep ICustomerImpl

在 运行rmic之前一定要用javac编过,rmic是找编译好的类的,不是找源程序的。rmic的工作原理是,首先反编译 ICustomerImpl.class,加入rmi架构需要的代码,然后把这个中间过程产生的Java文件编译成 ICustomerImpl_stub.class

-keep 就是让它保留中间产生的java文件。

这样基本上服务器端的事情都做完了。

客户端做这几件事情:

  1. 查找服务器端接口,要指定ip地址,端口号,接口注册名
  2. 然后可以是用接口的方法
import java.rmi.Naming;
import java.rmi.RemoteException;

public class Client{
public static void main(String[] args){
try{
ICustomer p =
(ICustomer)Naming.lookup("rmi://localhost/cust");
System.out.println(p.login("linghao","1234"));
}catch(RemoteException re){
System.out.println(re);
}catch(Exception e){
System.out.println(e);
}
}
}

客户端实际上是通过stub类来和服务器端通讯的,因此,运行的时候需要把接口文件,stub文件和客户文件放一块儿。

6. 安全策略

跨进程,跨机器访问一个不能避免的问题就是权限问题。

RMI中,是用java的访问权限管理 有两种方法来设置权限

1. 建立一个新文件test.policy,放在和server端代码一起,文件内容为

grant codeBase "file:/d:/rmitest/"
{
permission java.security.AllPermission;
};

或者在命令行中运行policytool,选"添加规则项目",在后面出来的那个对话框中,codebase填 file:/d:/rmitest/ ,然后选择"添加权限",许可中设置"All Permission".然后一路ok返回。然后选文件->另存为,取名字为test.policy放到server端程序的同一目录。

7. server端启动

首先要启动RMI注册器,这时候会出现一个空白的dos窗口,不要关掉它,否则注册服务器就没有了。

start rmiregistry

其次启动服务器端程序

java -Djava.rmi.server.codebase=file:/d:/rmitest/
-Djava.security.policy=test.policy Server

如果出现access permission exception的话,说明可能权限文件没设好,打开来看看。

注意,服务器端的两个程序都是不会返回的,每次你都要开个新窗口

8. Client端启动

注意ICustomer,ICustomerImpl_Stub.class 和 Client.class要放在一起

java Client运行后,如果一步一步照着做的话,应该能看到返回值为true;

9. 小结

本文是对RMI开发的一个极其简单,极其粗浅的介绍。很多系统的知识都没有写出来,目的就为了大家刚接触的时候上手快一些。

很多介绍也是某一种可选的方案(为了快速学习而选择的方案)罢了,专业的代码需要考虑更多的内容,比如下面列出的一些就需要考虑:

  • 服务器端程序不一定要继承java.rmi.UnicastRemoteObject, 实现更灵活
  • 端口号如果不写就是用默认的1099,但是也可以自己指定
  • 服务器端的安全设置
  • 远程调用的开销很大,是否要考虑一些模式如Gateway, DTO之类的。
  • 服务器端的宿主容器选择

更深层次的介绍还是请查看参考资料里面列的链接。

参考资料

事实上,大多数的书都很厚,如果像快速的学习RMI的用法就不要看那些书。看完了,项目也结束了。

一些有用的Link

[sun公司的RMI教程]http://java.sun.com/developer/onlineTraining/rmi/RMI.html

[sun公司的RMI培训资料]http://java.sun.com/docs/books/tutorial/rmi/running.html

2007年5月15日星期二

windows server 2003 中DCOM 权限设置

Windows2003加强了DCOM的权限管理,其设置和window2000中稍有不同。

首先打开 注册表,在HKLM\Software\Microsoft\Ole下面加上两个DWORD类型的键
ActivationFailureLoggingLevel (1)
CallFailureLoggingLevel(1)
这两个键可以把失败的登录尝试记录下来。比如你用xxx尝试登录,结果得到800706ba的错误

然后运行DCOMCNFG,在My Computer上面右键,然后选择Default Property标签,Default Authentication Level 选择None,Default Impersonation Level选择Impersonate.
这里很奇怪,就算选择别的选项,关掉再打开,又会回到这两个选项。

然后选择 COM Security标签,在Access Permission , Launch and Run Permission 里面把刚才失败的用户名加上,并赋予 Remote Access, Remote Launch 的权限。

然后最重要的,在防火墙里面把RPC服务的端口135打开。打开端口似乎需要重启计算机,否则用netstat -a -b 查看一下是否真的打开。

当然,这个方法只能运用于信任度高的局域网内,否则就危险了。

2007年5月14日星期一

NB的签名

刚才逛POPGO,看到一个签名,绝了!

看动画,要求别太高
没有新作,遗作也可
没有佳作,臭作也可
没有神作,鬼作也可

2007年5月4日星期五

《大剑》Claymore


这次的四月新番中最吸引我的莫过于《Claymore》(译为大剑或猎魔战记)这部动画了。

它的背景设定和《Berserk》(剑风传奇)有些类似,都是在一个妖魔当道的世界,为了与妖怪对抗,人类制作出了有着妖魔血统的半人半妖的女性战士。因为她们的金眼银瞳,她们也被人类所惧怕;因为她们总是背着一把双刃大剑,她们被人类称为Claymore。

她们在斩杀妖魔的过程中不断得释放自己的妖气,直到临界点。超过临界点,她们就会妖魔化,这时候就成为了比一般妖魔厉害得多的“觉醒者”。在她们还有一些理智的时候,她们会给自己最好的伙伴发“黑函”,让自己最好的伙伴把自己杀了,因为她们都希望做为人类而生,也做为人类而死。毕竟,她们原先是人类。

她们按照实力排名从No.1 到No.47。我们的主人公克莱雅就是实力最差的No.47。但她不是通过和妖魔合体被制造出来的,她是一个非常特殊的个体。她是和之前的No.1 微笑的特蕾莎的血肉结合而被制造出来的只拥有妖魔1/4血统的Claymore。
这部作品显然比其他的四月新番有更多的东西要表达。它并不是一部主人公的复仇记那么简单。Claymore们其实是最痛苦的一群人,组织认为她们只是被造出来对付妖魔的工具,而工具使用到一定次数就该扔掉,否则工具就会有了自己的思想,那是很危险的。因此组织一旦发现Claymore们的异常,就会把她们派到极其危险的任务中去,借刀杀人。Claymore们也不被人类所理解,人类其实就和惧怕妖魔一样惧怕她们。但是她们还是要挥舞大剑帮助人类。最后还要带着对这个世界的眷恋,流着泪,让自己的同伴杀死自己。她们是在这个世界的夹缝中生存着。

Claymore都是冷酷的战士,但是当她们和人类有了纽带之后,她们的命运将会完全被改变--或者是失去战士的资格而被杀,亦或有了更强大的动力,激发自己的潜能。前者的代表是特蕾莎,做为No.1的她可以不用释放妖力就轻易斩杀妖魔和对付从No.2到No.5的围剿,但是由于她和克蕾雅的接触,使得她那完美的做为战士的冷酷的心出现了裂缝,一念之仁导致被觉醒的No.2菲斯娜斩去了头颅。这也是克蕾雅加入组织追讨菲斯娜的原因。但历史总是相似的,克蕾雅遇到了少年拉基(垃圾还是Lucky?),勾起了自己以前的回忆,因此带着拉基一起旅行。

值得一提的就是这部动画的画风,这也是我一看就有了兴趣的原因。八木教广对我来说是个十分陌生的名字,但是他的画风却让人映象深刻。他笔下的少女都有过分纤细的身材,但看上去又十分的和谐。线条干净利落,将少女战士的柔美和坚强一齐表现了出来。尤其是人物的眼镜,嘴唇和头发,非常的有特点。

2007年5月2日星期三

heroes实在是太精彩了

这一集(1E20)中,HIRO来到了未来,见到了未来的HIRO。尽管上一集的时候我已经预料到这是一个黑暗的未来,但是没想到竟然会这么黑暗。

塞拉杀了内森和那个会变身的女人,结果变成了美国总统,愚弄民众长达5年。一个骗子能做到这个份上真是神乎其技了。超级白痴的马特助纣为虐,终于帮着塞拉获得了克莱尔的再生能力,又杀了未来的HIRO。克莱尔的fans们估计要哭了,编剧们为了将邪恶进行到底终于那她开刀了(还真是开刀呢)。妮其失去了自己的儿子迈伽和D.L.,成为了彼特的女友。伯纳特好像成了地下党,专门帮有特异功能的人逃脱塞拉的掌控。Mohinder变成了塞拉(总统)的御用教授,看来读书人就是好骗。

变化最大的还是要数彼特,似乎他已经完全掌握了自己靠近别人所学到的能力。连HIRO的时间静止都学会了。人也变得非常稳重成熟起来。(没办法,不变的酷一点,怎么能把大美女妮其骗到手呢?)除了塞拉他是唯一一个身怀数种技能的人了,不愧是塞拉的宿敌。不过塞拉最强的那招念力不知道他学会了没有?那简直是和JEDI武士一样的王道能力啊。如果他也会念力,再学习一下日本剑,穿个灰袍子,绝对是一个JEDI。

真是佩服编剧的天马行空的能力啊,不过本来这种科幻片玩的就是想象力。没有点special ability 怎么行。

片尾最后就是塞拉终于熬不住显出真面目和彼特对决。两个人都有超强的实力,一个是靠杀人吸收了无数的能力,一个是通过修炼,慢慢掌握自己靠近有能力的人所暂时学到的能力。

两人的对决谁会赢呢?不知道,也没有必要知道,无论如何,那个黑暗的时代是不会改变了。重要的是现在,不是吗?现在将会更难了!