最近一直在考虑考研的事情,其实一直没有这个考虑,但是由于最近的一系列事情让我开始着手考虑这个事情了。
一直认为自己已经学得差不多了,但是越到毕业之际,越来越发现自己所学的东西太少,是不能适应现在社会的检验的。虽了解一点计算机基础知识,但是都不深 入,现在的状态是啥都知道,啥都不精通。
还有一个原因是在我实习的公司里,有一位牛人。国内人工智能遗传算法方面的专家(在方正数据库里是这样写着的),发现的确很牛,做的框架简洁,优 雅,性能高,自己对他很是崇拜。前几天,趁期末考试,没去上班,在寝室里面闲来没事打算做一个flex与java通信的框架。想来想去,最后选中了 hessian 做中间传输协议,写好框架,昨天本想到公司炫耀一下,刚到公司从svn上co出项目的最新内容,发现,里面已经用到了,而且框架和我写的一模一样,(错, 应该说我的和他写的一模一样)。才发现,这位博士是我一道不能逾越的高度,如果就这样走出校园,我可能会有所遗憾。发现这个暑假除了准备考研,真的也没有 别的事情可以做了。那就准备一下吧,谋事在人。
下面写出这个简单框架的代码。虽然看似简单,里面却有大学问。
框架源码:
[img]http://www.javaeye.com/upload/attachment/121926/856eeafa-9a54-319c-8675-a0fd25b269c2.jpeg[/img]
java端的代码
web.xml配置文件配置了一个servlet就是HessianServlet,然后规定java端将要实现的RPC接口函数对应的接口类,和实现该 接口的类。
对于配置这个问题,目前还是有很大争议,有的人认为用xml配置很好,有的人认为用元数据好。而我个人认为最好是没有配置更好。约定优于配置。这是 rails社区的比较夸奖的。其实java也可以做到这点,只是大家习惯用一大堆xml来配置。其实很多公司都有自己的一些规则,那就是约定。
Xml代码
Xml代码 [img]http://devbbs.doit.com.cn/attachments/images/118-icon_copy.gif[/img]
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>hessian-rpc</servlet-name>
<servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
<init-param>
<param-name>home-class</param-name>
<param-value>com.wangscu.rpc.hessian.HessianRPC</param-value>
</init-param>
<init-param>
<param-name>home-api</param-name>
<param-value>com.wangscu.rpc.RPC</param-value>
</init-param>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hessian-rpc</servlet-name>
<url-pattern>/flex/rpc</url-pattern>
</servlet-mapping>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>hessian-rpc</servlet-name>
<servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
<init-param>
<param-name>home-class</param-name>
<param-value>com.wangscu.rpc.hessian.HessianRPC</param-value>
</init-param>
<init-param>
<param-name>home-api</param-name>
<param-value>com.wangscu.rpc.RPC</param-value>
</init-param>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hessian-rpc</servlet-name>
<url-pattern>/flex/rpc</url-pattern>
</servlet-mapping>
</web-app>
RPC接口类,整个系统都通过这个接口来与外界交互,而不同的技术采用不同的实现罢,比如
dwr,gwt,struts,webwork,flex都可以有对应的实现。
call接口是将一个外部的请求通过不同技术的转化成java里面的一个Operation对象后,然后在call对象里面经过一系列转化最后生成一个 Result对象返回给各种技术框架,然后发送给前台。
Java代码
Java代码 [img]http://devbbs.doit.com.cn/attachments/images/118-icon_copy.gif[/img]
package com.wangscu.rpc;
import com.wangscu.operation.Operation;
public interface RPC
{
public <T extends Operation> Result<T> call(T operation) throws Exception;
}
package com.wangscu.rpc;
import com.wangscu.operation.Operation;
public interface RPC
{
public <T extends Operation> Result<T> call(T operation) throws Exception;
}
下面就是Hessian版的RPC的实现,里面没有撒逻辑,看客们可以根据自己的需求自己修改就可以了。
Java代码
Java代码 [img]http://devbbs.doit.com.cn/attachments/images/118-icon_copy.gif[/img]
package com.wangscu.rpc.hessian;
import com.wangscu.operation.Operation;
import com.wangscu.rpc.RPC;
import com.wangscu.rpc.Result;
public class HessianRPC implements RPC
{
private static final long serialVersionUID = 1L;
@Override
public <T extends Operation> Result<T> call(T operation) throws Exception
{
operation.execute();
Result<T> result = new Result<T>();
result.setData(operation);
return result;
}
}
package com.wangscu.rpc.hessian;
import com.wangscu.operation.Operation;
import com.wangscu.rpc.RPC;
import com.wangscu.rpc.Result;
public class HessianRPC implements RPC
{
private static final long serialVersionUID = 1L;
@Override
public <T extends Operation> Result<T> call(T operation) throws Exception
{
operation.execute();
Result<T> result = new Result<T>();
result.setData(operation);
return result;
}
}
这个就是将要被传递个前台的对象,里面的T是一个Operation,是该次请求的该操作对象修改后的值。
Java代码
Java代码 [img]http://devbbs.doit.com.cn/attachments/images/118-icon_copy.gif[/img]
package com.wangscu.rpc;
import java.io.Serializable;
import com.wangscu.operation.Operation;
public class Result<T extends Operation> implements Serializable
{
private static final long serialVersionUID = 1305765848332686451L;
private T data;
public T getData()
{
return data;
}
public void setData(T data)
{
this.data = data;
}
}
package com.wangscu.rpc;
import java.io.Serializable;
import com.wangscu.operation.Operation;
public class Result<T extends Operation> implements Serializable
{
private static final long serialVersionUID = 1305765848332686451L;
private T data;
public T getData()
{
return data;
}
public void setData(T data)
{
this.data = data;
}
}
这个接口是大家写java操作对象说必需实现的。里面的execute方法就是用来进行逻辑操作的,比如查询数据,然后将该数据加入到该操作的属性当中, 这样就可以将结果返回给了前台。
Java代码
Java代码 [img]http://devbbs.doit.com.cn/attachments/images/118-icon_copy.gif[/img]
package com.wangscu.operation;
import java.io.Serializable;
public interface Operation extends Serializable
{
public void execute() throws Exception;
}
package com.wangscu.operation;
import java.io.Serializable;
public interface Operation extends Serializable
{
public void execute() throws Exception;
}
flex端的代码:
fle端就相对简单一点,RPC里面就一个CALL函数,并且是静态,至于是不是可以一个运用只要一个HessianService对象就可以了呢?这个 我暂时不太请求,因此在每个请求里面都实例了一个对象,如果您有答案不妨告诉我。
Flex代码
Java代码 [img]http://devbbs.doit.com.cn/attachments/images/118-icon_copy.gif[/img]
package com.wangscu.rpc
{
import hessian.client.HessianService;
import mx.controls.Alert;
import mx.rpc.AsyncToken;
import mx.rpc.IResponder;
public class RPC
{
public static function call(operation:*, callback:Function=null):*
{
var service:HessianService=new HessianService("http://localhost:8080/hessian/flex/rpc");
var responser:IResponder=new SimpleResponser(callback);
var token:AsyncToken=service.call.send(operation);
token.addResponder(responser);
}
}
}
package com.wangscu.rpc
{
import hessian.client.HessianService;
import mx.controls.Alert;
import mx.rpc.AsyncToken;
import mx.rpc.IResponder;
public class RPC
{
public static function call(operation:*, callback:Function=null):*
{
var service:HessianService=new HessianService("http://localhost:8080/hessian/flex/rpc");
var responser:IResponder=new SimpleResponser(callback);
var token:AsyncToken=service.call.send(operation);
token.addResponder(responser);
}
}
}
该对象是每次一个请求的一个回应对象,即当请求通过服务端后返回时候,客户端可以同孤傲该对象对返回数据进行操作。
Flex代码
Java代码 [img]http://devbbs.doit.com.cn/attachments/images/118-icon_copy.gif[/img]
package com.wangscu.rpc
{
import hessian.client.HessianService;
import mx.controls.Alert;
import mx.rpc.IResponder;
import mx.rpc.events.ResultEvent;
public class SimpleResponser implements IResponder
{
private var callback:Function;
public function SimpleResponser(callback:Function)
{
this.callback=callback;
}
public function result(data:Object):void
{
var result:*=ResultEvent(data).result;
if (callback != null)
{
callback(result.data);
}
}
public function fault(fault:Object):void
{
Alert.show("ERROR:" + fault);
}
}
}
package com.wangscu.rpc
{
import hessian.client.HessianService;
import mx.controls.Alert;
import mx.rpc.IResponder;
import mx.rpc.events.ResultEvent;
public class SimpleResponser implements IResponder
{
private var callback:Function;
public function SimpleResponser(callback:Function)
{
this.callback=callback;
}
public function result(data:Object):void
{
var result:*=ResultEvent(data).result;
if (callback != null)
{
callback(result.data);
}
}
public function fault(fault:Object):void
{
Alert.show("ERROR:" + fault);
}
}
}
下面将写一个简单示例:
一个简单的测试操作
Java代码
Java代码 [img]http://devbbs.doit.com.cn/attachments/images/118-icon_copy.gif[/img]
package com.wangscu.operation;
public class Test implements Operation
{
private String test;
@Override
public void execute() throws Exception
{
this.test = "成功哦";
}
public String getTest()
{
return test;
}
public void setTest(String test)
{
this.test = test;
}
}
package com.wangscu.operation;
public class Test implements Operation
{
private String test;
@Override
public void execute() throws Exception
{
this.test = "成功哦";
}
public String getTest()
{
return test;
}
public void setTest(String test)
{
this.test = test;
}
}
对应上面java的flex端的操作对象,这里该对象可以是动态的,这样,你只需要有个空壳就可以,不必有写里面的属性。因为我看了一下hessian的 flex实现,它是根据类名和包名来判断是否为同一对象,因此只要该类名和包名和java端的对象一致级可。
Flex代码
Java代码 [img]http://devbbs.doit.com.cn/attachments/images/118-icon_copy.gif[/img]
package com.wangscu.operation
{
public dynamic class Test
{
public var test:String;
public function Test()
{
super();
}
}
}
package com.wangscu.operation
{
public dynamic class Test
{
public var test:String;
public function Test()
{
super();
}
}
}
最后是测试用的调用代码:
callback 函数用于flex远程调用完java中Operation的操作时的回调函数,其返回的data是一个flex端该对应类的实例,里面的属性是通过 java的Operation修改过后的值。比如该例子里面将data.test 将得到调用Test这个Operation后,里面的test变成了"成功哦"。
Xml代码
Xml代码 [img]http://devbbs.doit.com.cn/attachments/images/118-icon_copy.gif[/img]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import com.wangscu.rpc.RPC;
import com.wangscu.operation.Test;
import mx.rpc.AsyncToken;
import mx.rpc.IResponder;
import com.wangscu.rpc.SimpleResponser;
import hessian.client.HessianService;
import mx.controls.Alert;
private function onclick():void
{
var callback:Function=function(data:*):*
{
Alert.show(data.test);
}
var test:Test = new Test();
RPC.call(test,callback);
}
]]>
</mx:Script>
<mx:Button click="onclick()"/>
</mx:Application>
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import com.wangscu.rpc.RPC;
import com.wangscu.operation.Test;
import mx.rpc.AsyncToken;
import mx.rpc.IResponder;
import com.wangscu.rpc.SimpleResponser;
import hessian.client.HessianService;
import mx.controls.Alert;
private function onclick():void
{
var callback:Function=function(data:*):*
{
Alert.show(data.test);
}
var test:Test = new Test();
RPC.call(test,callback);
}
]]>
</mx:Script>
<mx:Button click="onclick()"/>
</mx:Application>
注意事项:要传入到flex端的对象一定要实现Serializable接口,否则flex会报流错误,这个让我郁闷了很久。
文章后面提供本次说要用到的文件及lib包文件
[img]http://www.javaeye.com/upload/attachment/121926/856eeafa-9a54-319c-8675-a0fd25b269c2.jpeg?1246682754[/img]
大小: 3 KB
flex-hessian-java.rar (1.5 MB)
下载次数: 181