对使用Hessian协议调用在程序中应用的理解
2010-11-29 21:04
363 查看
Hessian是romote procedure call协议。这个协议是一个二进制协议。在应用过程中的流程是“客户端->序列化写到输出流—>远程方法(服务器端)—>序列化写到输出流 —>客户端读取输入流—>输出结果”。
在我们的项目RingMaster中的应用是这样的。
首先,需要定义一个接口,这个接口是服务器端和客户端公用的。我们的项目中是RemoteInterface。
其次,在客户端需要通过HessianProxyFactory hessianFactory = new HessianProxyFactory();来获取一个hessianFactory的实例。调用factory.create(apiClass, url); 返回一个Proxy对象的实例,这个实例指出了handler是HessianProxy。
那么在我们的项目中,将这些部分结合起来,最终的调用将由HessianProxy来实现调用。在HessianProxy的invoke函数中,进行了最基本的http的链接,发送数据给Hessian的server端。同时,处理server端返回的内容进行反序列化转化成对象返回。
public Object invoke(Object proxy, Method method, Object []args)
throws Throwable
{
String mangleName;
synchronized (_mangleMap) {
mangleName = _mangleMap.get(method);
}
if (mangleName == null) {
String methodName = method.getName();
Class []params = method.getParameterTypes();
// equals and hashCode are special cased
if (methodName.equals("equals")
&& params.length == 1 && params[0].equals(Object.class)) {
Object value = args[0];
if (value == null || ! Proxy.isProxyClass(value.getClass()))
return new Boolean(false);
HessianProxy handler = (HessianProxy) Proxy.getInvocationHandler(value);
return new Boolean(_url.equals(handler.getURL()));
}
else if (methodName.equals("hashCode") && params.length == 0)
return new Integer(_url.hashCode());
else if (methodName.equals("getHessianType"))
return proxy.getClass().getInterfaces()[0].getName();
else if (methodName.equals("getHessianURL"))
return _url.toString();
else if (methodName.equals("toString") && params.length == 0)
return "HessianProxy[" + _url + "]";
if (! _factory.isOverloadEnabled())
mangleName = method.getName();
else
mangleName = mangleName(method);
synchronized (_mangleMap) {
_mangleMap.put(method, mangleName);
}
}
InputStream is = null;
URLConnection conn = null;
HttpURLConnection httpConn = null;
try {
if (log.isLoggable(Level.FINER))
log.finer("Hessian[" + _url + "] calling " + mangleName);
conn = sendRequest(mangleName, args);
if (conn instanceof HttpURLConnection) {
httpConn = (HttpURLConnection) conn;
int code = 500;
try {
code = httpConn.getResponseCode();
} catch (Exception e) {
}
parseResponseHeaders(conn);
if (code != 200) {
StringBuffer sb = new StringBuffer();
int ch;
try {
is = httpConn.getInputStream();
if (is != null) {
while ((ch = is.read()) >= 0)
sb.append((char) ch);
is.close();
}
is = httpConn.getErrorStream();
if (is != null) {
while ((ch = is.read()) >= 0)
sb.append((char) ch);
}
} catch (FileNotFoundException e) {
throw new HessianConnectionException("HessianProxy cannot connect to '" + _url, e);
} catch (IOException e) {
if (is == null)
throw new HessianConnectionException(code + ": " + e, e);
else
throw new HessianConnectionException(code + ": " + sb, e);
}
if (is != null)
is.close();
throw new HessianConnectionException(code + ": " + sb.toString());
}
}
is = conn.getInputStream();
if (log.isLoggable(Level.FINEST)) {
PrintWriter dbg = new PrintWriter(new LogWriter(log));
is = new HessianDebugInputStream(is, dbg);
}
AbstractHessianInput in = _factory.getHessianInput(is);
in.startReply();
Object value = in.readObject(method.getReturnType());
if (value instanceof InputStream) {
value = new ResultInputStream(httpConn, is, in, (InputStream) value);
is = null;
httpConn = null;
}
else
in.completeReply();
return value;
} catch (HessianProtocolException e) {
throw new HessianRuntimeException(e);
} finally {
try {
if (is != null)
is.close();
} catch (Exception e) {
log.log(Level.FINE, e.toString(), e);
}
try {
if (httpConn != null)
httpConn.disconnect();
} catch (Exception e) {
log.log(Level.FINE, e.toString(), e);
}
}
}
在我们的项目RingMaster中的应用是这样的。
首先,需要定义一个接口,这个接口是服务器端和客户端公用的。我们的项目中是RemoteInterface。
其次,在客户端需要通过HessianProxyFactory hessianFactory = new HessianProxyFactory();来获取一个hessianFactory的实例。调用factory.create(apiClass, url); 返回一个Proxy对象的实例,这个实例指出了handler是HessianProxy。
那么在我们的项目中,将这些部分结合起来,最终的调用将由HessianProxy来实现调用。在HessianProxy的invoke函数中,进行了最基本的http的链接,发送数据给Hessian的server端。同时,处理server端返回的内容进行反序列化转化成对象返回。
public Object invoke(Object proxy, Method method, Object []args)
throws Throwable
{
String mangleName;
synchronized (_mangleMap) {
mangleName = _mangleMap.get(method);
}
if (mangleName == null) {
String methodName = method.getName();
Class []params = method.getParameterTypes();
// equals and hashCode are special cased
if (methodName.equals("equals")
&& params.length == 1 && params[0].equals(Object.class)) {
Object value = args[0];
if (value == null || ! Proxy.isProxyClass(value.getClass()))
return new Boolean(false);
HessianProxy handler = (HessianProxy) Proxy.getInvocationHandler(value);
return new Boolean(_url.equals(handler.getURL()));
}
else if (methodName.equals("hashCode") && params.length == 0)
return new Integer(_url.hashCode());
else if (methodName.equals("getHessianType"))
return proxy.getClass().getInterfaces()[0].getName();
else if (methodName.equals("getHessianURL"))
return _url.toString();
else if (methodName.equals("toString") && params.length == 0)
return "HessianProxy[" + _url + "]";
if (! _factory.isOverloadEnabled())
mangleName = method.getName();
else
mangleName = mangleName(method);
synchronized (_mangleMap) {
_mangleMap.put(method, mangleName);
}
}
InputStream is = null;
URLConnection conn = null;
HttpURLConnection httpConn = null;
try {
if (log.isLoggable(Level.FINER))
log.finer("Hessian[" + _url + "] calling " + mangleName);
conn = sendRequest(mangleName, args);
if (conn instanceof HttpURLConnection) {
httpConn = (HttpURLConnection) conn;
int code = 500;
try {
code = httpConn.getResponseCode();
} catch (Exception e) {
}
parseResponseHeaders(conn);
if (code != 200) {
StringBuffer sb = new StringBuffer();
int ch;
try {
is = httpConn.getInputStream();
if (is != null) {
while ((ch = is.read()) >= 0)
sb.append((char) ch);
is.close();
}
is = httpConn.getErrorStream();
if (is != null) {
while ((ch = is.read()) >= 0)
sb.append((char) ch);
}
} catch (FileNotFoundException e) {
throw new HessianConnectionException("HessianProxy cannot connect to '" + _url, e);
} catch (IOException e) {
if (is == null)
throw new HessianConnectionException(code + ": " + e, e);
else
throw new HessianConnectionException(code + ": " + sb, e);
}
if (is != null)
is.close();
throw new HessianConnectionException(code + ": " + sb.toString());
}
}
is = conn.getInputStream();
if (log.isLoggable(Level.FINEST)) {
PrintWriter dbg = new PrintWriter(new LogWriter(log));
is = new HessianDebugInputStream(is, dbg);
}
AbstractHessianInput in = _factory.getHessianInput(is);
in.startReply();
Object value = in.readObject(method.getReturnType());
if (value instanceof InputStream) {
value = new ResultInputStream(httpConn, is, in, (InputStream) value);
is = null;
httpConn = null;
}
else
in.completeReply();
return value;
} catch (HessianProtocolException e) {
throw new HessianRuntimeException(e);
} finally {
try {
if (is != null)
is.close();
} catch (Exception e) {
log.log(Level.FINE, e.toString(), e);
}
try {
if (httpConn != null)
httpConn.disconnect();
} catch (Exception e) {
log.log(Level.FINE, e.toString(), e);
}
}
}
相关文章推荐
- android开发(26) 和其他应用交换数据方式一,使用intent指定自定义action调用其他程序里的activity,并获得其返回的结果
- android开发(26) 和其他应用交换数据方式一,使用intent指定自定义action调用其他程序里的activity,并获得其返回的结果
- android开发(26) 和其他应用交换数据方式一,使用intent指定自定义action调用其他程序里的activity,并获得其返回的结果
- android开发(26) 和其他应用交换数据方式一,使用intent指定自定义action调用其他程序里的activity,并获得其返回的结果
- 使用java理解程序逻辑第一章
- android从应用到驱动之—camera(1)---程序调用流程
- Reporting Service Tips 101(#4) - 使用RS实现报表的自动生成以及在程序中调用RS
- linux下使用jni实现c++调用java程序(5)参考资料总结
- redisson的理解和使用-调用流程
- 如何正确地应用Runtime类调用程序
- iOS程序中调用系统自带应用(短信,邮件,浏览器,地图,AppStore,拨打电话)
- Spring 的Hessian简单使用,快速理解Hessian运行方式
- 当我使用一个单例,调用一个类型对象的时候,程序出现了崩溃
- 使用NPAPI编写浏览器插件的调用本机上的程序
- Spark Pipe使用方法(外部程序调用方法)
- [java调用外部可执行程序] 1. java使用cmd命令(转)
- android 如何调用talk程序,集成到自己写的应用中
- 使用java理解程序逻辑第三章
- qt下的时钟程序(简单美丽,继承自QWidget的Clock,用timer调用update刷新,然后使用paintEvent作画就行了,超详细中文注释)good