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

来源:互联网 发布:网络协议测试仪 编辑:程序博客网 时间:2024/06/12 01:04

开始调研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 stubString 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 answeranswered Jun 17 '11 at 18:14Menefee192111add commentup vote0down voteFrom 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#客户端了。


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

0 0