Hessian学习之(一):简单测试 + C#调用Java服务

开始调研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#客户端了。


以上只是我的两个想法,有待验证,或者有更好的方法请大家不吝赐教,谢谢!!!

你可能感兴趣的:(Hessian学习之(一):简单测试 + C#调用Java服务)