开始调研Hessian和Mina,目的是希望能够建立一个简单的“高性能分布式服务调用框架”!类似于Dubbo或者淘宝的HSF那种,但是是要跨平台的,而不仅仅局限在Java领域。
hessian是一种远程调用的机制(RPC) ,类似于web service,不过它是使用自己的序列化协议(二进制序列化)。淘宝的HSF高性能服务框架中两台机器通信用到的序列化技术就是Hessian的,它的内部实现就是基于Hessian和Mina,这里是几篇关于Hessian源码解析的文章可以参考。
基于Hessian的远程调用协议。
- 连接个数:多连接
- 连接方式:短连接
- 传输协议:HTTP
- 传输方式:同步传输
- 序列化:Hessian二进制序列化
- 适用范围:传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。
- 适用场景:页面传输,文件传输,或与原生hessian服务互操作
约束:
- 参数及返回值需实现Serializable接口
- 参数及返回值不能自定义实现List, Map, Number, Date, Calendar等接口,只能用JDK自带的实现,因为hessian会做特殊处理,自定义实现类中的属性值都会丢失。
这里我们主要先讲一下如果利用Hessian实现RPC:
(一)Java客户端调用Java服务:
1 下载Eclipse IDE for JavaEE Developer(http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/keplersr1)
2 下载hessian-4.0.37.jar (http://hessian.caucho.com/index.xtp#IntroductiontoHessian)
3 创建Dynamic Web Project,记得Target Runtime选择Tomcat,最后记得勾选上生成Web.xml
4 引入hessian的jar文件
5 服务器端开发:
(1)创建接口以及实现类:
package com.jiq.hessian;
/**
*
*/
/**
* @author Think
*
*/
public interface IHelloService {
public String SayHello();
}
package com.jiq.hessian;
//import com.caucho.hessian.server.HessianServlet;
/**
* @author Think
*
*/
public class HelloService implements IHelloService{
public String SayHello()
{
return "hello, Hessian!";
}
}
(2)配置Web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>WebProjTest</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
<init-param>
<param-name>service-class</param-name>
<param-value>com.jiq.hessian.HelloService</param-value>
</init-param>
<init-param>
<param-name>home-api</param-name>
<param-value>com.jiq.hessian.IHelloService</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
(3)编写一个测试用的JSP:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ page import="com.caucho.hessian.client.HessianProxyFactory" %>
<%@ page import="com.jiq.hessian.IHelloService" %>
<%
HessianProxyFactory factory = new HessianProxyFactory();
String url = "http://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/hello";
IHelloService proxy = (IHelloService)factory.create(IHelloService.class, url);
out.print(proxy.SayHello());
%>
在view中打开servers试图,空白处右击,创建server,选择你的tomcat(我选择的是tomcat 7),然后add你的工程,启动服务器。
在浏览器中输入 http://localhost:8390/WebProjTest/hello.jsp 可以看到期望的输出。说明成功了。
6 客户端开发:
需要创建一个一模一样的IHelloService的接口,下面是代码:
package com.jiq.test;
import java.net.MalformedURLException;
import com.caucho.hessian.client.HessianProxyFactory;
import com.jiq.hessian.*;
public class HessianTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
String url = "http://localhost:8390/WebProjTest/hello";
HessianProxyFactory factory = new HessianProxyFactory();
try {
IHelloService proxy =(IHelloService)factory.create(IHelloService.class, url);
System.out.println(proxy.SayHello());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
右击,运行,可以看到期望输出。
本文参考: http://blog.sina.com.cn/s/blog_a27c1c670101fphf.html
这里是我提供的源码下载: 下载地址是我export为Archive file的。
(二)C#客户端调用Java服务:
(1)引入Hessiancsharp.dll;
(2)编写一个接口IHelloService,和Java服务端的一样(类似WCF中的契约):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NETHessianTest
{
interface IHelloService
{
string SayHello();
}
}
(3)编写测试代码:
namespace NETHessianTest
{
class Program
{
static void Main(string[] args)
{
string url = @"http://192.168.1.100:80/WebProjTest/hello";
CHessianProxyFactory factory = new CHessianProxyFactory();
IHelloService proxy = (IHelloService)factory.Create(typeof(IHelloService), url);
Console.WriteLine(proxy.SayHello());
Console.ReadKey();
}
}
}
这就OK了,但是我不知道为什么调用很慢很慢,有待继续深入。
这里是.NET客户端测试工程下载,里面有Hessiancsharp.dll
(三)关于DataTable的返回:
接下来最关键的就是,以前C#开发都是WCF来请求服务,一般查询数据库都会返回DataSet,里面包含了DataTable,那么Java服务查询了数据库之后,怎么返回数据(结果集)给C#的客户端呢?Java又没有DataSet或者DataTable,我大概有两个思路,不过还没有亲自尝试:
(1)自己模拟一个DataTable对象:
大概像这样:
A workaround I've used is JTable. It doesn't have the robust data features of a proper DataTable but it will allow you grab some data and bind it to a control with some structure.
class TableModel extends AbstractTableModel
{
String[] columnNames = {“FirstName”,”LastName”,”Title”};
Object[][] rowData= {{‘John,”Smith”,”President”},{“John”,”Doe”,”Employee”}};
public int getColumnCount()
{
return columnNames.length;
}
public int getRowCount()
{
return rowData.length;
}
public String getColumnName(int col)
{
return columnNames[col];
}
public Object getValueAt(int row, int col)
{
return data[row][col];
}
}
And then to use you simply:
JTable table = new JTable(new TableModel());
Again, this is quick and simple and if you are dealing with large amounts of data I would recommend using a proper ORM tool.
share|improve this answer
answered Jun 17 '11 at 18:14
Menefee
192111
add comment
up vote
0
down vote
From Standard Library DefaultTableModel is good class.
ResultSet set = s.getResultSet();
ResultSetMetaData metaData = set.getMetaData();
int totalColumn = metaData.getColumnCount();
Object[] dataRow = new Object[totalColumn];
if(set!= null)
{
for(int i=1;i<=totalColumn;i++)
{
table.addColumn(metaData.getColumnName(i));
}
while(set.next())
{
for(int i=1;i<=totalColumn;i++)
{
dataRow[i-1] = set.getObject(i);
}
table.addRow(dataRow);
}
}
(2) 使用ORM,即实体关系映射。
采用实体关系映射,比如Hibernate之后,java查询数据库直接返回List<Object>,就可以直接返回给C#客户端了。
以上只是我的两个想法,有待验证,或者有更好的方法请大家不吝赐教,谢谢!!!