Hessian 原理分析、代码示例

本文详细介绍了Hessian远程过程调用(RPC)的原理与实现,包括Binary-RPC协议、Hessian库的使用方法及其序列化机制。通过两个案例展示了如何利用Hessian进行远程调用和服务交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hessian 原理分析


一.      远程通讯协议的基本原理

网络通信需要做的就是将流从一台计算机传输到另外一台计算机,基于传输协议和网络 IO 来实现,其中传输协议比较出名的有 http 、 tcp 、 udp 等等, http 、 tcp 、 udp 都是在基于 Socket 概念上为某类应用场景而扩展出的传输协议,网络 IO ,主要有 bio 、 nio 、 aio 三种方式,所有的分布式应用通讯都基于这个原理而实现,只是为了应用的易用,各种语言通常都会提供一些更为贴近应用易用的应用层协议。

二.      应用级协议 Binary-RPC

Binary-RPC 是一种和 RMI 类似的远程调用的协议,它和 RMI 的不同之处在于它以标准的二进制格式来定义请求的信息 ( 请求的对象、方法、参数等 ) ,这样的好处是什么呢,就是在跨语言通讯的时候也可以使用。

来看下 Binary -RPC 协议的一次远程通信过程:

 

1 、客户端发起请求,按照 Binary -RPC 协议将请求信息进行填充;

2 、填充完毕后将二进制格式文件转化为流,通过传输协议进行传输;

3 、接收到在接收到流后转换为二进制格式文件,按照 Binary -RPC 协议获取请求的信息并进行处理;

4 、处理完毕后将结果按照 Binary -RPC 协议写入二进制格式文件中并返回。

         问题总结:

1 、传输的标准格式是?

    标准格式的二进制文件。

2 、怎么样将请求转化为传输的流?

    将二进制格式文件转化为流。

3 、怎么接收和处理流?

    通过监听的端口获取到请求的流,转化为二进制文件,根据协议获取请求的信息,进行处理并将结果写入 XML 中返回。

4 、传输协议是?

Http 。

三.      Hessian ——一种实现远程通讯的 library

Hessian 是由 caucho 提供的一个基于 binary-RPC 实现的远程通讯 library 。

1 、是基于什么协议实现的?

基于 Binary-RPC 协议实现。

2 、怎么发起请求?

需通过 Hessian 本身提供的 API 来发起请求。

3 、怎么将请求转化为符合协议的格式的?

Hessian 通过其自定义的串行化机制将请求信息进行序列化,产生二进制流。

4 、使用什么传输协议传输?

Hessian 基于 Http 协议进行传输。

5 、响应端基于什么机制来接收请求?

响应端根据 Hessian 提供的 API 来接收请求。

6 、怎么将流还原为传输格式的?

Hessian 根据其私有的串行化机制来将请求信息进行反序列化,传递给使用者时已是相应的请求信息对象了。

7 、处理完毕后怎么回应?

             处理完毕后直接返回, hessian 将结果对象进行序列化,传输至调用端。

四.      Hessian 源码分析

以 hessian 和 spring dm server 整合环境为例。

  1. 1.     客户端发起请求

Hessian 的这个远程过程调用,完全使用动态代理来实现的。有客户端可以看出。

除去 spring 对其的封装,客户端主要是通过 HessianProxyFactory 的 create 方法就是创建接口的代理类,该类实现了接口, JDK 的 proxy 类会自动用 InvocationHandler 的实现类(该类在 Hessian 中表现为 HessianProxy )的 invoke 方法体来填充所生成代理类的方法体。

客户端系统启动时:

         根据 serviceUrl 和 serviceInterface 创建代理。

         HessianProxyFactoryBean 类

        

HessianClientInterceptor 类

                  createHessianProxy(HessianProxyFactory proxyFactory)

 

HessianProxyFactory 类

                  public Object create(Class api, String urlName)

 

客户端调用 hessian 服务时:

                   HessianProxy 类的 invoke(Object proxy, Method method, Object []args) 方法

                            String methodName = method.getName();// 取得方法名

                            Object value = args[0]; // 取得传入参数

                            conn = sendRequest(mangleName, args) ;      // 通过该方法和服务器端取得连接

 

                            httpConn = (HttpURLConnection) conn;

                            code = httpConn.getResponseCode();    // 发出请求

 

// 等待服务器端返回相应…………

 

                            is = conn.getInputStream();

                            Object value = in.readObject(method.getReturnType()); // 取得返回值

 

HessianProxy 类的 URLConnection sendRequest(String methodName, Object []args) 方法:

                      URLConnection  conn = _factory.openConnection(_url);      // 创建 URLConnection 

                            OutputStream os = conn.getOutputStream();

 

                            AbstractHessianOutput out = _factory.getHessianOutput(os); // 封装为 hessian 自己的输入输出 API

                            out.call(methodName, args);

                            return conn;

        

 

  1. 2.     服务器端接收请求并处理请求

服务器端截获相应请求交给:

org.springframework.remoting.caucho.HessianServiceExporter

具体处理步骤如下:

a)       HessianServiceExporter 类

(HessianExporter) invoke(request.getInputStream(), response.getOutputStream());

 

b)       HessianExporter 类

(Hessian2SkeletonInvoker) this.skeletonInvoker.invoke(inputStream, outputStream);

c)       Hessian2SkeletonInvoker 类

将输入输出封转化为转化为 Hessian 特有的 Hessian2Input 和 Hessian2Output

      Hessian2Input in = new Hessian2Input(isToUse);

      in.setSerializerFactory(this.serializerFactory);

 

      AbstractHessianOutput out = null;

      int major = in.read();

      int minor = in.read();

      out = new Hessian2Output(osToUse);

      out = new HessianOutput(osToUse);

      out.setSerializerFactory(this.serializerFactory);

      (HessianSkeleton) this.skeleton.invoke(in, out);

 

d)       HessianSkeleton 类

           读取方法名

         String methodName = in.readMethod();

    Method method = getMethod(methodName);

 

           读取方法参数

         Class []args = method.getParameterTypes();

    Object []values = new Object[args.length];

 

           执行相应方法并取得结果

         result = method.invoke(service, values);

 

           结果写入到输出流

         out.writeObject(result);

        

总结: 由上面源码分析可知,客户端发起请求和服务器端接收处理请求都是通过 hessian 自己的 API 。输入输出流都要封装为 hessian 自己的 Hessian2Input 和 Hessian2Output ,接下来一节我们将去了解 hessian 自己封装的输入输出到底做了些什么!

五.      Hessian 的序列化和反序列化实现

hessian 源码中 com.caucho.hessian.io 这个包是 hessian 实现序列化与反序列化的核心包。其中 AbstractSerializerFactory , AbstractHessianOutput , AbstractSerializer , AbstractHessianInput , AbstractDeserializer 是 hessian 实现序列化和反序列化的核心结构代码。

 

  1. AbstractSerializerFactory ,它有 2 个抽象方法:

根据类来决定用哪种序列化工具类

abstract public Serializer getSerializer(Class cl)  throws HessianProtocolException; 

根据类来决定用哪种反序列化工具类

abstract public Deserializer getDeserializer(Class cl)  throws HessianProtocolException;

  1. SerializerFactory 继承 AbstractSerializerFactory 。

在 SerializerFactory 有很多静态 map 用来存放类与序列化和反序列化工具类的映射,这样如果已经用过的序列化工具就可以直接拿出来用,不必再重新实例化工具类。

在 SerializerFactory 中,实现了抽象类的 getSerializer 方法,根据不同的需要被序列化的类来获得不同的序列化工具,一共有 17 种序列化工具, hessian 为不同的类型的 java 对象实现了不同的序列化工具,默认的序列化工具是 JavaSerializer 。

在 SerializerFactory 中,也实现了抽象类的 getDeserializer 方法,根据不同的需要被反序列化的类来获得不同的反序列化工具,默认的反序列化工具类是 JavaDeserializer 。

  1. HessianOutput 继承 AbstractHessianOutput 成为序列化输出流的一种实现。

它会实现很多方法,用来做流输出。

需要注意的是方法,它会先调用 serializerFactory 根据类来获得 serializer 序列化工具类

public void writeObject(Object object)

throws IOException 

if (object == null) { 

writeNull(); 

return; 

 

Serializer serializer; 

 

serializer = _serializerFactory.getSerializer(object.getClass());  

 

serializer.writeObject(object, this); 

  1. 现在我们来看看 AbstractSerializer 。

其 writeObject 是必须在子类实现的方法, AbstractSerializer 有 17 种子类实现, hessian 根据不同的 java 对象类型来实现了不同的序列化工具类,其中默认的是 JavaSerializer 。

而 JavaSerializer 的 writeObject 方法的实现,遍历 java 对象的数据成员,根据数据成员的类型来获得各自的 FieldSerializer ,一共有 6 中默认的 FieldSerializer 。

拿默认的 FieldSerializer 举例,还是调用 AbstractHessianOutput 的子类来 writeObject ,这个时候,肯定能找到相应的 Serializer 来做序列化

 

同理可以反推出 hessian 的反序列化机制。 SerializerFactory 可以根据需要被反序列化的类来获得反序列化工具类来做反序列化操作。

 

总结:得益于 hessian 序列号和反序列化的实现机制, hessian 序列化的速度很快,而且序列化后的字节数也较其他技术少。

 

 

 

 

 

参考文献:

  1. 《 Java 远程通讯可选技术及原理》 http://java.chinaitlab.com/base/740383.html
  2. 《 Hessian-3.2.0 源码》
  3. 《 hessian 序列化实现初探》 http://www.javaeye.com/topic/245238
  4. 《 Hessian 2.0 序列化协议规范》

http://blog.youkuaiyun.com/xpspace/archive/2007/10/05/1811603.aspx




Hessian RPC示例和基于Http请求的Hessian序列化对象传输


本文主要介绍两个案例,第一个是使用Hessian来实现远程过程调用,第二个是通过Hessian提供的二进制RPC协议进行和Servlet进行数据交互,Hessian本身即是基于Http的RPC实现。

案例一:

1.准备工作

这里建立一个Maven项目,其中包含四个模块,父模块(仅用来聚合其它模块,不做实际使用),服务器端模块,客户端模块,API模块(远程过程接口,供服务器和客户端使用)。目录结构见下图:

wKiom1SwmzSRUDR1AAHOPhvwsXI742.jpg

2.添加Hessian的依赖

由于客户端和服务器都要依赖Hessian的包,这里可以添加到父模块的pom.xml中去。

<dependency>
			<groupId>com.caucho</groupId>
			<artifactId>hessian</artifactId>
			<version>4.0.38</version>
		</dependency>

关于其它的具体依赖配置,这里不做多余展示,本文末尾附有完整的下载地址。

3.在hessian-api模块定义过程接口

package secondriver.hessian.api;

import java.io.InputStream;
import java.util.List;

import secondriver.hessian.api.bean.Person;

public interface HelloHessian {

	public String sayHello();

	public String sayHello(String name);

	public List<Person> getPersons();

	public Person getPersonById(int id);

	public boolean uploadFile(String fileName, InputStream data);

	public byte[] downloadFile(String fileName);
}

上面的接口中定义的六个方法,有重载方法,有获取集合,有获取对象,有上传文件,下载文件等。需要注意的是在Hessian中定义过程接口的方法时输入输出流对象参数应该放置到方法的最后一个参数。另外在实际操作中发现对于流的处理通过远程调用还是会出现一个莫名其妙的问题,加上Hessian缺乏完整的文档(除Hessian的序列号协议)。

关于下载文件这个方法的定义使用了返回byte数组,这将受限与虚拟机的内存或其他因素。网上有说关于文件下载Hessian不支持(未能证实。引申案例二的方式,传输二进制就可以实现下载,不过这将与Hessian的RPC实现无关,而是应用到Hessian的序列号协议),这个可以算是一种策略,So,关于远程文件下载,谁会使用这样的方式呢?!!

4.服务器端实现具体功能

服务器端实现接口

package secondriver.hessian.server.bo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Random;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import secondriver.hessian.api.HelloHessian;
import secondriver.hessian.api.bean.Person;

public class HelloHessianImpl implements HelloHessian {

	private static Person[] persons = new Person[5];

	static {
		Random random = new Random();
		for (int i = 0, l = persons.length; i < l; i++) {
			persons[i] = new Person();
			persons[i].setId(i);
			persons[i].setGender(random.nextBoolean());
			persons[i].setName("name-" + i);
			persons[i].setPhone(random.nextLong());
			persons[i].setHeight(random.nextDouble());
			persons[i].setWeight(random.nextFloat());
			persons[i].setAddress(new String[] { "Address" + random.nextInt(),
					"Address" + random.nextInt() });

			Calendar c = Calendar.getInstance();
			c.set(Calendar.DATE, i + 1);
			persons[i].setBrithday(c.getTime());
		}
	}

	@Override
	public String sayHello() {
		return "Hello Hession " + new Date().toString();
	}

	@Override
	public String sayHello(String name) {
		return "Welcome " + name;
	}

	@Override
	public List<Person> getPersons() {
		return Arrays.asList(persons);
	}

	@Override
	public Person getPersonById(int id) {
		for (Person p : persons) {
			if (p.getId() == id) {
				return p;
			}
		}
		return null;
	}

	@Override
	public boolean uploadFile(String fileName, InputStream data) {
		List<String> temp;
		try {
			temp = IOUtils.readLines(data);
			String filePath = System.getProperty("user.dir") + "/temp/"
					+ fileName;
			FileUtils.writeLines(new File(filePath), temp);
			System.out.println("Upload file to " + filePath);
			return true;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	@Override
	public byte[] downloadFile(String fileName) {
		String filePath = System.getProperty("user.dir") + "/temp/" + fileName;
		InputStream data = null;
		try {
			data = new FileInputStream(filePath);
			int size = data.available();
			byte[] buffer = new byte[size];
			IOUtils.read(data, buffer);
			return buffer;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		} finally {
			IOUtils.closeQuietly(data);
		}
	}
}

5.服务器端配置远程服务地址

Hessian是Remote On Http工具,服务端是典型的Java Web应用,我们需要在web.xml中配置服务的请求地址。

<servlet>
		<servlet-name>HelloHessian</servlet-name>
		<servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class><!-- RPC HessianServlet处理类 -->
		<init-param>
			<param-name>home-class</param-name><!-- 远程服务实现类 -->
			<param-value>secondriver.hessian.server.bo.HelloHessianImpl</param-value>
		</init-param>
		<init-param>
			<param-name>home-api</param-name><!-- 远程服务接口 -->
			<param-value>secondriver.hessian.api.HelloHessian</param-value>
		</init-param>
	</servlet>

6.客户端调用远程对象方法

package secondriver.hessian.client;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.List;

import org.apache.commons.io.IOUtils;

import secondriver.hessian.api.HelloHessian;
import secondriver.hessian.api.bean.Person;

import com.caucho.hessian.client.HessianProxyFactory;

/**
 * Hessian RPC
 */
public class HelloHessianClient {

	public static String urlName = "http://localhost:8080/hessian-server/HelloHessian";

	public static void main(String[] args) throws MalformedURLException {

		HessianProxyFactory factory = new HessianProxyFactory();
		// 开启方法重载
		factory.setOverloadEnabled(true);

		HelloHessian helloHession = (HelloHessian) factory.create(
				HelloHessian.class, urlName);

		// 调用方法
		System.out.println("call sayHello():" + helloHession.sayHello());
		System.out.println("call sayHello(\"Tom\"):"
				+ helloHession.sayHello("Tom"));
		System.out.println("call getPersons():");

		// 调用方法获取集合对象
		List<Person> persons = helloHession.getPersons();
		if (null != persons && persons.size() > 0) {
			for (Person p : persons) {
				System.out.println(p.toString());
			}
		} else {
			System.out.println("No person.");
		}

		// 通过参数调用方法获取对象
		int id = 2;
		System.out.println(String.format("call getPersonById(%d)", id));
		Person person = helloHession.getPersonById(id);
		if (null != person) {
			System.out.println(person.toString());
		} else {
			System.out.println("Id is " + id + " person not exist.");
		}

		// 上传文件
		String fileName = "upload.txt";
		String filePath = System.getProperty("user.dir") + "/temp/" + fileName;
		InputStream data = null;
		try {
			data = new BufferedInputStream(new FileInputStream(filePath));
			if (helloHession.uploadFile(fileName, data)) {
				System.out.println("Upload file " + filePath + " succeed.");
			} else {
				System.out.println("Upload file " + filePath + " failed.");
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			IOUtils.closeQuietly(data);
		}

		// 下载文件
		fileName = "download.txt";
		filePath = System.getProperty("user.dir") + "/temp/" + fileName;
		try {

			byte[] temp = helloHession.downloadFile(fileName);
			if (null != temp) {
				FileWriter output = new FileWriter(filePath);
				IOUtils.write(temp, output, "UTF-8");
				System.out.println("Download file " + filePath + " succeed.");
				output.close();
			} else {
				System.out.println("Download file " + filePath + " failed.");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

通过客户端调用可以看出,远程方法的具体实现对于客户端来说是透明的。

7.运行程序

7.1启动服务器

7.2运行客户端程序

客户端请求远程服务对象方法调用结果:

call sayHello():Hello Hession Sat Jan 10 12:31:21 CST 2015
call sayHello("Tom"):Welcome Tom
call getPersons():
Person [id=0, gender=true, name=name-0, brithday=Thu Jan 01 12:31:21 CST 2015, height=0.04756537639163749, weight=0.24559122, phone=1359341198036930408, address=[Address2145973789, Address486043733]]
....省略
call getPersonById(2)
Person [id=2, gender=false, name=name-2, brithday=Sat Jan 03 12:31:21 CST 2015, height=0.07169451440704722, weight=0.8515671, phone=2732762596557481818, address=[Address8744397, Address-1690316438]]
Upload file F:\__eclipse\tomsworkspace\hessian-L-parent\hessian-client/temp/upload.txt succeed.
Download file F:\__eclipse\tomsworkspace\hessian-L-parent\hessian-client/temp/download.txt succeed.

案例二:

1. 客户端通过Hessian序列号协议序列化对象,通过Http Post方式提交到服务器端,然后通过反序列化服务器端响应数据。

package secondriver.hessian.data;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Date;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import secondriver.hessian.api.bean.Person;

import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;

public class Test3 {

	public static String urlName = "http://localhost:8080/hessian-server/PostDataServlet";

	public static void main(String[] args) throws Throwable {

		// 序列化
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		Hessian2Output h2o = new Hessian2Output(os);

		h2o.startMessage();
		h2o.writeObject(getPerson());
		h2o.writeString("I am client.");
		h2o.completeMessage();
		h2o.close();

		byte[] buffer = os.toByteArray();
		os.close();

		ByteArrayEntity byteArrayEntity = new ByteArrayEntity(buffer,
				ContentType.create("x-application/hessian", "UTF-8"));
		
		CloseableHttpClient client = HttpClients.createDefault();
		HttpPost post = new HttpPost(urlName);
		post.setEntity(byteArrayEntity);
		CloseableHttpResponse response = client.execute(post);

		System.out.println("response status:\n"
				+ response.getStatusLine().getStatusCode());
		HttpEntity body = response.getEntity();
		InputStream is = body.getContent();
		Hessian2Input h2i = new Hessian2Input(is);
		h2i.startMessage();

		Person person = (Person) h2i.readObject();
		System.out.println("response:\n" + person.toString());
		System.out.println(h2i.readString());

		h2i.completeMessage();
		h2i.close();
		is.close();
	}

	public static Person getPerson() {
		Person person = new Person();
		person.setAddress(new String[] { "Beijing", "TaiWan", "GuangZhou" });
		person.setBrithday(new Date());
		person.setGender(false);
		person.setHeight(168.5D);
		person.setId(300);
		person.setName("Jack");
		person.setPhone(188888888);
		person.setWeight(55.2F);
		return person;
	}
}

2.服务器端通过Hessian序列化协议反序列化对象,通过HttpServletResponse对请求进行响应,响应数据是Hessian序列化的二进制结果。

package secondriver.hessian.server.servlet;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import secondriver.hessian.api.bean.Person;

import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;

public class PostDataServlet extends HttpServlet {

	private static final long serialVersionUID = -4461061053732328507L;

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// 处理请求
		ServletInputStream sis = req.getInputStream();
		Hessian2Input h2i = new Hessian2Input(sis);

		h2i.startMessage();
		Person person = (Person) h2i.readObject();
		System.out.println("receive:\n" + person.toString());
		System.out.println(h2i.readString());
		h2i.completeMessage();
		h2i.close();
		sis.close();

		// 发送响应
		resp.setCharacterEncoding("UTF-8");
		resp.setContentType("x-application/hessian");

		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		Hessian2Output h2o = new Hessian2Output(bos);

		h2o.startMessage();
		h2o.writeObject(getPerson());
		h2o.writeString("I am server.");
		h2o.completeMessage();
		h2o.close();

		ServletOutputStream sos = resp.getOutputStream();
		sos.write(bos.toByteArray());
		sos.flush();
		bos.close();
		sos.close();

	}

	public static Person getPerson() {
		Person person = new Person();
		person.setAddress(new String[] { "ShangHai", "ShenZhen", "ChengDu" });
		person.setBrithday(new Date());
		person.setGender(true);
		person.setHeight(178.5D);
		person.setId(301);
		person.setName("Tom");
		person.setPhone(188218888);
		person.setWeight(55.2F);
		return person;
	}
}

3.在web.xml中配置PostDataServlet,此处略去具体配置信息,可以参考上面HelloHessian Servlet配置。

4.运行程序

4.1启动服务器

4.2运行客户端程序Test3.

运行结果:

服务器端输出:

[INFO] Restart completed at Sat Jan 10 12:34:51 CST 2015
receive:
Person [id=300, gender=false, name=Jack, brithday=Sat Jan 10 12:35:03 CST 2015, height=168.5, weight=55.2, phone=188888888, address=[Beijing, TaiWan, GuangZhou]]
I am client.

客户端输出:

response status:
200
response:
Person [id=301, gender=true, name=Tom, brithday=Sat Jan 10 12:35:03 CST 2015, height=178.5, weight=55.2, phone=188218888, address=[ShangHai, ShenZhen, ChengDu]]
I am server.

分析输出结果可见Hessian序列化对象通过Http的方式传输,并成功反序列化。

关于Hessian序列号协议可以参见: http://hessian.caucho.com/doc/hessian-serialization.html

写在最后:Hessian的相关资料网上还是比较少,而且例子不尽相同,而且 官方文档 错误之处清晰可见(仔细阅读方可一览无余),本文从Hessian的RPC使用和Hessian序列化和反序列化对象两个方面提供了示例,完整示例下载地址可见本文附件:HessionRPC示例(Eclipse Luna版工程,需要Mavn支持),另外带有源码的Hessian的API文档下载地址: http://down.51cto.com/data/1973896 。

一次不太愉快的Hessian体验使得对RPC的理解更加深刻,无论何种框架,对象的序列化和反序列化,数据的传输协议都是实现RPC的工作重点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值