Skip to content

Hprose 服务器

小马哥 edited this page Jun 30, 2016 · 44 revisions

概述

Hprose 2.0 for Java 支持多种底层网络协议绑定的服务器,比如:HTTP 服务器,TCP 服务器和 WebSocket 服务器。

HTTP 服务器支持在 HTTP、HTTPS 协议上通讯。

TCP 服务器支持在 TCP 协议上通讯,并且支持全双工和半双工两种模式。

WebSocket 服务器支持在 ws、wss 协议上通讯。

我们下面先从最常用的 HTTP 服务器说起。

直接使用 HproseServlet 发布服务

通过 HproseServlet 发布服务很简单,直接通过配置方式就可以,如果要发布的类是现成的,您不需要编写一行代码就可以完成发布。

发布的方法可以是静态方法,也可以是实例方法。但必须是 public 方法。您还可以同时发布多个类中的方法。

下面我们来看一下 HproseServlet 都有哪些可配置项。

class 配置项

<init-param>
    <param-name>class</param-name>
    <param-value>类1|类1的祖先类|名称空间1,类2|类2的祖先类|名称空间2,...</param-value>
</init-param>

上面选项中 param-value 部分比较复杂,我们来详细介绍一下。

通过 class 配置项可以发布的对象上的实例方法,对象会根据配置的类自动创建,可以同时发布多个对象,每个对象的配置通过逗号 , 分隔。

发布的多个对象可以是同一个类,也可以是不同类的对象,即上面所写的 类1类2 可以是相同的类,也可以是不同的类。

每个对象的配置分三个部分,这三个部分通过 | 来分隔。

第一部分表示创建对象的类,第二部分表示从创建的类到该祖先类上的方法全部发布,所指定的祖先类之上的父类中的方法不会被发布。

例如:

public class BaseService1 {
   public String foo() { return "foo" }
}

public class Service1 extends BaseService1 {
   public String bar() { return "bar" }
}

public class Service2 extends Service1 {
    public String foobar() { return "foobar" }
}

当配置为:

<init-param>
    <param-name>class</param-name>
    <param-value>Service2</param-value>
</init-param>

时,只发布 foobar 方法。

当配置为:

<init-param>
    <param-name>class</param-name>
    <param-value>Service2|Service1</param-value>
</init-param>

时,只发布 foobarbar 方法。

当配置为:

<init-param>
    <param-name>class</param-name>
    <param-value>Service2|BaseService1</param-value>
</init-param>

时,将发布 foobarbarfoo 方法。

之所有这样做,是因为所有的类都是从祖先类 Object 继承下来的,如果将继承来的 public 方法都发布的话,势必会将从 Object 继承来的方法也一起发布,这很可能不是用户所期望的结果。另一个原因,用户定义的类的层次可能比较深,而其定义的基类上的方法可能并不想被一起发布。因此,默认情况下,只发布直接在该类中声明的 public 方法,而不会发布继承来的方法。

从上面的几个例子中,我们还会发现,后两部分的配置是可选的。

名称空间的用处是可以将同一个服务的不同对象上的同名方法区分开,例如:

<init-param>
    <param-name>class</param-name>
    <param-value>Service2|BaseService1|service2,Service1||service1</param-value>
</init-param>

将会发布两个对象上的方法,第一个是 Service2 类的实例对象,它上面的 foobarbarfoo 方法都会发布。第二个是 Service1 类的实例对象,它上面的 bar 方法会被发布。因为加了名称空间,所以实际发布的方法名是:

  • service2_foobar
  • service2_bar
  • service2_foo
  • service1_bar

这样就把两个 bar 方法区分开了,在客户端调用时,同样可以指定名称空间(在客户端部分有介绍),或者直接使用全名调用。

从上面的配置中,我们还可以看到,配置的第二部分可以忽略,但是在有第三部分时, | 不能忽略。

staticClass 配置项

<init-param>
    <param-name>staticClass</param-name>
    <param-value>类1|名称空间1,类2|名称空间2,...</param-value>
</init-param>

通过 staticClass 配置项可以发布的类上的静态方法,每个类的配置通过逗号 , 分隔。类和名称空间之间用 | 分隔。

例如:

public class StaticService {
   public static String foo() { return "foo" }
   public static String bar() { return "bar" }
   public String foobar() { return "foobar" }
}

如果通过一下方式来发布:

<init-param>
    <param-name>staticClass</param-name>
    <param-value>StaticService</param-value>
</init-param>

将只发布 foobar 方法,因为 foobar 方法不是静态方法。

type 配置项

<init-param>
    <param-name>type</param-name>
    <param-value>类1|注册名1,类2|注册名2,...</param-value>
</init-param>

通过 type 配置项可以用来注册自定义类型,相当于通过 HproseClassManager 来注册。例如:

<init-param>
    <param-name>type</param-name>
    <param-value>hprose.example.io.User|User,hprose.example.io.Order|Order</param-value>
</init-param>

上面的配置相当于使用一下代码进行注册:

HproseClassManager.register(hprose.example.io.User.class, "User");
HproseClassManager.register(hprose.example.io.Order.class, "Order");

注册之后的类型,在传输时将使用注册名来代替类名与客户端进行交互。

mode 配置项

取值为有三个:

  • FieldMode
  • PropertyMode
  • MemberMode

配置时,大小写无关。该选项表示采用何种模式序列化自定义对象。默认值为 MemberMode,通常不需要配置该选项,采用默认方式就可以了。

配置方式如下:

<init-param>
    <param-name>mode</param-name>
    <param-value>propertyMode</param-value>
</init-param>

debug 配置项

<init-param>
    <param-name>debug</param-name>
    <param-value>true</param-value>
</init-param>

默认情况下,在调用过程中,服务器端发生错误时,只返回有限的错误信息。当打开调试开关后,服务器会将错误堆栈信息全部发送给客户端,这样,在客户端可以得到详细的错误信息。

crossDomain 配置项

<init-param>
    <param-name>crossDomain</param-name>
    <param-value>true</param-value>
</init-param>

Hprose 支持 JavaScript、ActionScript 和 SilverLight 客户端的跨域调用,对于 JavaScript 客户端来说,服务器提供了两种跨域方案,一种是 W3C 标准跨域方案(CORS 跨域资源共享),只要进行上面的设置就可以开启了。

另一种跨域方案同时适用于以上三种客户端,那就是通过设置跨域策略文件的方式。您只需要将 crossdomain.xml 文件放在网站发布的根目录上即可。

最后,Hprose 还提供了专门适用于 SilverLight 的跨域方案,那就是通过设置客户端访问策略文件的方式。做法跟 crossdomain.xml 类似,只需要将 clientaccesspolicy.xml 文件放在网站发布的根目录上即可。

关于 crossdomain.xmlclientaccesspolicy.xml 的更多内容请参阅:

origin 配置项

<init-param>
    <param-name>origin</param-name>
    <param-value>地址1,地址2,地址3...</param-value>
</init-param>

当开启 crossDomain 配置项后,是运行所有位置发出的跨域请求的,如果你需要限制跨域请求的来源,你可以通过配置该选项来实现。多个来源可以用 , 分隔。例如:

<init-param>
    <param-name>origin</param-name>
    <param-value>http://hprose.org,http://hprose.com</param-value>
</init-param>

就是只允许:

这两个来源下的请求。

注意,来源地址和请求页面地址并不相同,比如假设请求页面地址是:

http://hprose.com/test

它的来源地址是:

http://hprose.com

p3p 配置项

<init-param>
    <param-name>p3p</param-name>
    <param-value>true</param-value>
</init-param>

这个配置项决定是否发送 P3P 的 HTTP 头,这个头的作用是让 IE 允许跨域接收的 Cookie。当您的服务需要在浏览器中被跨域调用,并且希望传递 Cookie 时(例如通过 Cookie 来传递 Session ID),您可以考虑将这个开关打开。否则,无需开启此开关。此开关默认是关闭状态。

get 配置项

<init-param>
    <param-name>get</param-name>
    <param-value>false</param-value>
</init-param>

当该配置项设置为 false 时,关闭在 HTTP GET 请求时的发布列表显示功能。

发布列表的作用相当于 Web Service 的 WSDL,与 WSDL 不同的是,Hprose 的发布列表仅包含方法名,而不包含方法参数列表,返回结果类型,调用接口描述,数据类型描述等信息。这是因为 Hprose 是支持弱类型动态语言调用的,因此参数个数,参数类型,结果类型在发布期是不确定的,在调用期才会确定。所以,Hprose 与 Web Service 相比无论是服务的发布还是客户端的调用上都更加灵活。

但是有时候,您可能不希望用户直接通过浏览器就可以查看发布列表,这时只要将这个配置项设置为 false 就可以了。

event 配置项

<init-param>
    <param-name>event</param-name>
    <param-value>实现 HproseHttpServiceEvent 接口的事件类</param-value>
</init-param>

Hprose 服务器可以配置多个事件,对于 HTTP 服务器来说,这些事件定义在 HproseHttpServiceEvent 接口中,这些事件方法包括:

void onBeforeInvoke(String name, Object[] args, boolean byRef, HproseContext context) throws Throwable;
void onAfterInvoke(String name, Object[] args, boolean byRef, Object result, HproseContext context) throws Throwable;
Throwable onSendError(Throwable e, HproseContext context) throws Throwable;
void onServerError(Throwable e, HproseContext context);
void onSendHeader(HttpContext httpContext);

其中前 4 个继承自 HproseServiceEvent 接口,最后一个 onSendHeader 事件方法定义在 HproseHttpServiceEvent 接口中。

onBeforeInvoke 事件

当服务器端发布的方法被调用前,onBeforeInvoke 事件被触发。

name 为客户端所调用的方法名。

args 为方法的参数。

byRef 表示是否是引用参数传递的调用。

context 为服务上下文,你可以将其转型为:ServiceContextHttpContext 类型。通过该对象,你可以得到调用方法的更多信息,或者 HTTP 的各种上下文对象,例如:request,response, session 等。你还可以通过 HproseContext 上的方法来设置或获取一些你自己定义的一些数据。这些数据可以在各个事件,各个过滤器,各个中间件之间按执行顺序传递。

您可以在该事件中做用户身份验证,例如基于 session 的用户名密码验证,IP 验证等。也可以作日志记录。如果在该事件中想终止调用,抛出异常即可。

onAfterInvoke 事件

当服务器端发布的方法被成功调用后,onAfterInvoke 事件被触发,其中name, args, byRef, contextonBeforeInvoke 事件一致,参数 result 表示调用结果。

当调用发生错误时,onAfterInvoke 事件将不会被触发。如果在该事件中抛出异常,则调用结果不会被返回,客户端将收到此事件抛出的异常。

onSendError 事件

当服务器端调用抛出异常,或者在 onBeforeInvokeonAfterInvoke 事件中抛出异常时,该事件被触发。

您可以在该事件中作日志记录。

如果你希望返回客户端的异常与传入的异常参数不同,你可以通过返回或抛出一个新的异常来代替传入的异常,否则返回 null 即可。

onServerError 事件

当服务器端与客户端无法通讯时并抛出异常时,会触发该事件。

您可以在该事件中作日志记录。

该事件中不应抛出任何异常。

onSendHeader 事件

当服务器返回响应头部时,onSendHeader 事件会被触发。

在该事件中,您可以发送您自己的头信息,例如设置 Cookie,自定义头等等。

该事件中不应抛出任何异常。

filter 配置项

<init-param>
    <param-name>filter</param-name>
    <param-value>Filter1,Filter2,...</param-value>
</init-param>

通过该配置可以添加一个或多个 Filter,关于 Filter 的更多内容,请参见:Hprose 过滤器一章。

beforeFilter 配置项

<init-param>
    <param-name>beforeFilter</param-name>
    <param-value>Handler1,Handler1,...</param-value>
</init-param>

通过该配置可以添加一个或多个在 Filter 执行之前的输入输出中间件处理器,关于中间件的更多内容,请参见:Hprose 中间件一章。

afterFilter 配置项

<init-param>
    <param-name>afterFilter</param-name>
    <param-value>Handler1,Handler1,...</param-value>
</init-param>

通过该配置可以添加一个或多个在 Filter 执行之后的输入输出中间件处理器,关于中间件的更多内容,请参见:Hprose 中间件一章。

invoke 配置项

<init-param>
    <param-name>invoke</param-name>
    <param-value>Handler1,Handler1,...</param-value>
</init-param>

通过该配置可以添加一个或多个调用中间件处理器,关于中间件的更多内容,请参见:Hprose 中间件一章。

topic 配置项

<init-param>
    <param-name>topic</param-name>
    <param-value>topic1|timeout1|heartbeat1,topic2|timeout2|heartbeat2,...</param-value>
</init-param>

通过该配置项,可以用于发布推送主题。多个主题之间用 , 分隔,每个主题的参数之间用 | 分隔。timeoutheartbeat 参数都可以省略。

自己编写 Servlet 发布 Hprose 服务

如果您觉得直接使用 HproseServlet 发布服务还不能满足您的要求,您当然也可以自己编写一个 Servlet 来发布 Hprose 服务。这并不是什么难事,因为 Hprose 已经为您提供了很好的基础,您只需要对 HproseServlet 做一下扩展,或者直接使用 HproseHttpService 来构建自己的Servlet 即可。

扩展 HproseServlet

我们先来介绍最简单的方式,那就是以 HproseServlet 为基类,通过创建子类的方式来扩展 HproseServlet。使用这种方式,您可以更灵活的控制方法的发布。

在前面直接使用 HproseServlet 发布服务时,您会发现我们只能以类为单位来发布方法,而不能单独发布类或对象上的某一个或几个方法,另外,如果我们想对某一个方法指定别名,而不是对整个对象或类上所有方法增加名称空间(别名前缀)的话,也是做不到的。

上面这些需求您都可以通过扩展 HproseServlet 来实现。

创建 HproseServlet 的子类非常容易,HproseServlet 提供了多个可以覆盖的方法,其中最重要是:setGlobalMethods

protected void setGlobalMethods(HproseMethods methods);

该方法的参数类型是 HproseMethods 类型的,下面我们先来对 HproseMethods 类型做一下介绍。

HproseMethods 类

HproseMethods 类型用于表示发布方法的集合。它有以下几个方法:

  • addMethod
  • addMethods
  • addInstanceMethods
  • addStaticMethods
  • addMissingMethod

下面我们对这几个方法分别做一下介绍。

addMethod 方法

public void addMethod(String aliasName, HproseMethod method);

public void addMethod(HproseMethod method);

public void addMethod(Method method, Object obj, String aliasName);
public void addMethod(Method method, Object obj, String aliasName, HproseResultMode mode);
public void addMethod(Method method, Object obj, String aliasName, boolean simple);
public void addMethod(Method method, Object obj, String aliasName, HproseResultMode mode, boolean simple);
public void addMethod(Method method, Object obj, String aliasName, HproseResultMode mode, boolean simple, boolean oneway);

public void addMethod(Method method, Object obj);
public void addMethod(Method method, Object obj, HproseResultMode mode);
public void addMethod(Method method, Object obj, boolean simple);
public void addMethod(Method method, Object obj, HproseResultMode mode, boolean simple);
public void addMethod(Method method, Object obj, HproseResultMode mode, boolean simple, boolean oneway);

public void addMethod(String methodName, Object obj, Class<?>[] paramTypes, String aliasName) throws NoSuchMethodException;
public void addMethod(String methodName, Object obj, Class<?>[] paramTypes, String aliasName, HproseResultMode mode) throws NoSuchMethodException;
public void addMethod(String methodName, Object obj, Class<?>[] paramTypes, String aliasName, boolean simple) throws NoSuchMethodException;
public void addMethod(String methodName, Object obj, Class<?>[] paramTypes, String aliasName, HproseResultMode mode, boolean simple) throws NoSuchMethodException;
public void addMethod(String methodName, Object obj, Class<?>[] paramTypes, String aliasName, HproseResultMode mode, boolean simple, boolean oneway) throws NoSuchMethodException;

public void addMethod(String methodName, Class<?> type, Class<?>[] paramTypes, String aliasName) throws NoSuchMethodException;
public void addMethod(String methodName, Class<?> type, Class<?>[] paramTypes, String aliasName, HproseResultMode mode) throws NoSuchMethodException;
public void addMethod(String methodName, Class<?> type, Class<?>[] paramTypes, String aliasName, boolean simple) throws NoSuchMethodException;
public void addMethod(String methodName, Class<?> type, Class<?>[] paramTypes, String aliasName, HproseResultMode mode, boolean simple) throws NoSuchMethodException;
public void addMethod(String methodName, Class<?> type, Class<?>[] paramTypes, String aliasName, HproseResultMode mode, boolean simple, boolean oneway) throws NoSuchMethodException;

public void addMethod(String methodName, Object obj, Class<?>[] paramTypes) throws NoSuchMethodException;
public void addMethod(String methodName, Object obj, Class<?>[] paramTypes, HproseResultMode mode) throws NoSuchMethodException;
public void addMethod(String methodName, Object obj, Class<?>[] paramTypes, boolean simple) throws NoSuchMethodException;
public void addMethod(String methodName, Object obj, Class<?>[] paramTypes, HproseResultMode mode, boolean simple) throws NoSuchMethodException;
public void addMethod(String methodName, Object obj, Class<?>[] paramTypes, HproseResultMode mode, boolean simple, boolean oneway) throws NoSuchMethodException;

public void addMethod(String methodName, Class<?> type, Class<?>[] paramTypes) throws NoSuchMethodException;
public void addMethod(String methodName, Class<?> type, Class<?>[] paramTypes, HproseResultMode mode) throws NoSuchMethodException;
public void addMethod(String methodName, Class<?> type, Class<?>[] paramTypes, boolean simple) throws NoSuchMethodException;
public void addMethod(String methodName, Class<?> type, Class<?>[] paramTypes, HproseResultMode mode, boolean simple) throws NoSuchMethodException;
public void addMethod(String methodName, Class<?> type, Class<?>[] paramTypes, HproseResultMode mode, boolean simple, boolean oneway) throws NoSuchMethodException;

public void addMethod(String methodName, Object obj, String aliasName);
public void addMethod(String methodName, Object obj, String aliasName, HproseResultMode mode);
public void addMethod(String methodName, Object obj, String aliasName, boolean simple);
public void addMethod(String methodName, Object obj, String aliasName, HproseResultMode mode, boolean simple);
public void addMethod(String methodName, Object obj, String aliasName, HproseResultMode mode, boolean simple, boolean oneway);

public void addMethod(String methodName, Class<?> type, String aliasName);
public void addMethod(String methodName, Class<?> type, String aliasName, HproseResultMode mode);
public void addMethod(String methodName, Class<?> type, String aliasName, boolean simple);
public void addMethod(String methodName, Class<?> type, String aliasName, HproseResultMode mode, boolean simple);
public void addMethod(String methodName, Class<?> type, String aliasName, HproseResultMode mode, boolean simple, boolean oneway);

public void addMethod(String methodName, Object obj);
public void addMethod(String methodName, Object obj, HproseResultMode mode);
public void addMethod(String methodName, Object obj, boolean simple);
public void addMethod(String methodName, Object obj, HproseResultMode mode, boolean simple);
public void addMethod(String methodName, Object obj, HproseResultMode mode, boolean simple, boolean oneway);

public void addMethod(String methodName, Class<?> type);
public void addMethod(String methodName, Class<?> type, HproseResultMode mode);
public void addMethod(String methodName, Class<?> type, boolean simple);
public void addMethod(String methodName, Class<?> type, HproseResultMode mode, boolean simple);
public void addMethod(String methodName, Class<?> type, HproseResultMode mode, boolean simple, boolean oneway);

addMethod 用来控制单个方法的发布,它有许多的重载形式。通过它可以发布任意对象上的任意 public 的实例方法,或任意类上的任意 public 的静态方法。

参数 aliasName 可以为每个方法都指定别名。当您发布的方法具有相同个数参数的重载时,你需要为这些重载方法指定不同的别名。在 Hprose 2.0 中,除了用这种方式以外,还可以在定义方法时,在方法上加上 @MethodName(别名) 注解来标注该方法发布时的别名。

参数 mode 用来指明方法调用结果的类型。如果返回结果就是普通对象,那么不需要加这个参数,也就是默认值 HproseResultMode.Normal。如果返回结果是 Hprose 序列化之后的数据(byte[] 类型),那么设置该参数为 HproseResultMode.Serialized 可以避免该结果被二次序列化。如果返回结果是一个完整的响应,当这个响应结果不带 Hprose 结束符时,需要将该参数设置为 HproseResultMode.Raw,如果这个响应结果带Hprose 结束符,则设置这个参数为 HproseResultMode.RawWithEndTag。这个参数主要用于存储转发的 Hprose 代理服务器。通常我们不需要用到这个参数。在 Hprose 2.0 中,除了用这种方式以外,还可以在定义方法时,在方法上加上 @ResultMode(HproseResultMode 枚举值) 注解来标注该方法的调用结果类型。

参数 simple 表示结果在传输给客户端时,是否使用简单序列化方式。对于简单类型的返回结果,将该参数设置为 true 可以加快一点速度。在 Hprose 2.0 中,除了用这种方式以外,还可以在定义方法时,在方法上加上 @Simple 注解来标注该方法以简单类型返回结果。

参数 oneway 表示在收到调用时,是否立即返回空响应之后再执行调用。通常对于没有返回值的服务方法,而且又不需要保证跟后续调用有同步关系的情况下,可以将该参数设置为 true,这将加快客户端的响应速度。在 Hprose 2.0 中,除了用这种方式以外,还可以在定义方法时,在方法上加上 @Oneway 注解来标注该方法以简单类型返回结果。

参数 HproseMethod method 用来指定 Hprose 包装的服务方法,用户通常不需要使用该重载版本。

参数 Method method 用来指定通过反射获取到的服务方法,用户通常也不需要使用该重载版本。

参数 methodName 表示服务方法名,obj 表示方法所在的对象,type 表示方法所在的类。当发布实例方法时指定 obj 参数,当发布静态方法时,指定 type 参数。

参数 paramTypes 表示服务方法的参数类型列表,当指定该参数时,只有服务方法的参数类型跟 paramTypes 参数指定的类型一致时才会发布,通过该参数可以将同名重载方法区分发布。

addMethods 方法

public void addMethods(String[] methodNames, Object obj, String[] aliasNames);
public void addMethods(String[] methodNames, Object obj, String[] aliasNames, HproseResultMode mode);
public void addMethods(String[] methodNames, Object obj, String[] aliasNames, boolean simple);
public void addMethods(String[] methodNames, Object obj, String[] aliasNames, HproseResultMode mode, boolean simple);
public void addMethods(String[] methodNames, Object obj, String[] aliasNames, HproseResultMode mode, boolean simple, boolean oneway);

public void addMethods(String[] methodNames, Object obj, String aliasPrefix);
public void addMethods(String[] methodNames, Object obj, String aliasPrefix, HproseResultMode mode);
public void addMethods(String[] methodNames, Object obj, String aliasPrefix, boolean simple);
public void addMethods(String[] methodNames, Object obj, String aliasPrefix, HproseResultMode mode, boolean simple);
public void addMethods(String[] methodNames, Object obj, String aliasPrefix, HproseResultMode mode, boolean simple, boolean oneway);

public void addMethods(String[] methodNames, Object obj);
public void addMethods(String[] methodNames, Object obj, HproseResultMode mode);
public void addMethods(String[] methodNames, Object obj, boolean simple);
public void addMethods(String[] methodNames, Object obj, HproseResultMode mode, boolean simple);
public void addMethods(String[] methodNames, Object obj, HproseResultMode mode, boolean simple, boolean oneway);

public void addMethods(String[] methodNames, Class<?> type, String[] aliasNames);
public void addMethods(String[] methodNames, Class<?> type, String[] aliasNames, HproseResultMode mode);
public void addMethods(String[] methodNames, Class<?> type, String[] aliasNames, boolean simple);
public void addMethods(String[] methodNames, Class<?> type, String[] aliasNames, HproseResultMode mode, boolean simple);
public void addMethods(String[] methodNames, Class<?> type, String[] aliasNames, HproseResultMode mode, boolean simple, boolean oneway);

public void addMethods(String[] methodNames, Class<?> type, String aliasPrefix);
public void addMethods(String[] methodNames, Class<?> type, String aliasPrefix, HproseResultMode mode);
public void addMethods(String[] methodNames, Class<?> type, String aliasPrefix, boolean simple);
public void addMethods(String[] methodNames, Class<?> type, String aliasPrefix, HproseResultMode mode, boolean simple);
public void addMethods(String[] methodNames, Class<?> type, String aliasPrefix, HproseResultMode mode, boolean simple, boolean oneway);

public void addMethods(String[] methodNames, Class<?> type);
public void addMethods(String[] methodNames, Class<?> type, HproseResultMode mode);
public void addMethods(String[] methodNames, Class<?> type, boolean simple);
public void addMethods(String[] methodNames, Class<?> type, HproseResultMode mode, boolean simple);
public void addMethods(String[] methodNames, Class<?> type, HproseResultMode mode, boolean simple, boolean oneway);

addMethods 用来同时发布一组服务方法。如果您所发布的方法来自同一个对象(obj 参数),或是同一个类(type 参数),使用 addMethods 方法通常比直接使用 addMethod 方法更为方便。因为您不但可以为每个方法都指定别名(aliasNames 参数),还可以为这一组方法(methodNames 参数)指定同一个名称空间(aliasPrefix 参数)。但实际上我们很少情况会直接使用它。因为有更加简单的 addInstanceMethodsaddStaticMethods 方法。

addInstanceMethods 方法

public void addInstanceMethods(Object obj, Class<?> type, String aliasPrefix, HproseResultMode mode, boolean simple, boolean oneway);
public void addInstanceMethods(Object obj, Class<?> type, String aliasPrefix, HproseResultMode mode, boolean simple);
public void addInstanceMethods(Object obj, Class<?> type, String aliasPrefix, boolean simple);
public void addInstanceMethods(Object obj, Class<?> type, String aliasPrefix, HproseResultMode mode);
public void addInstanceMethods(Object obj, Class<?> type, String aliasPrefix);

public void addInstanceMethods(Object obj, Class<?> type, HproseResultMode mode, boolean simple, boolean oneway);
public void addInstanceMethods(Object obj, Class<?> type, HproseResultMode mode, boolean simple);
public void addInstanceMethods(Object obj, Class<?> type, boolean simple);
public void addInstanceMethods(Object obj, Class<?> type, HproseResultMode mode);
public void addInstanceMethods(Object obj, Class<?> type);

public void addInstanceMethods(Object obj, String aliasPrefix);
public void addInstanceMethods(Object obj, String aliasPrefix, HproseResultMode mode);
public void addInstanceMethods(Object obj, String aliasPrefix, boolean simple);
public void addInstanceMethods(Object obj, String aliasPrefix, HproseResultMode mode, boolean simple);
public void addInstanceMethods(Object obj, String aliasPrefix, HproseResultMode mode, boolean simple, boolean oneway);

public void addInstanceMethods(Object obj)
public void addInstanceMethods(Object obj, HproseResultMode mode);
public void addInstanceMethods(Object obj, boolean simple);
public void addInstanceMethods(Object obj, HproseResultMode mode, boolean simple);
public void addInstanceMethods(Object obj, HproseResultMode mode, boolean simple, boolean oneway);

addInstanceMethods 用来发布指定对象上的指定类层次上声明的所有 public 实例方法。如果您在使用 addInstanceMethods 方法时,不指定类层次(type 参数),则发布这个对象所在类上声明的所有 public 实例方法。这个方法也支持指定名称空间(aliasPrefix 参数)。

addStaticMethods 方法

public void addStaticMethods(Class<?> type, String aliasPrefix, HproseResultMode mode, boolean simple, boolean oneway);
public void addStaticMethods(Class<?> type, String aliasPrefix, HproseResultMode mode, boolean simple);
public void addStaticMethods(Class<?> type, String aliasPrefix, boolean simple);
public void addStaticMethods(Class<?> type, String aliasPrefix, HproseResultMode mode);
public void addStaticMethods(Class<?> type, String aliasPrefix);

public void addStaticMethods(Class<?> type, HproseResultMode mode, boolean simple, boolean oneway);
public void addStaticMethods(Class<?> type, HproseResultMode mode, boolean simple);
public void addStaticMethods(Class<?> type, boolean simple);
public void addStaticMethods(Class<?> type, HproseResultMode mode);
public void addStaticMethods(Class<?> type);

addStaticMethods 用来发布指定类(type 参数)上声明的所有 public 静态方法。这个方法也支持指定名称空间(aliasPrefix 参数)。

addMissingMethod 方法

public void addMissingMethod(String methodName, Object obj) throws NoSuchMethodException;
public void addMissingMethod(String methodName, Object obj, HproseResultMode mode) throws NoSuchMethodException;
public void addMissingMethod(String methodName, Object obj, boolean simple) throws NoSuchMethodException;
public void addMissingMethod(String methodName, Object obj, HproseResultMode mode, boolean simple) throws NoSuchMethodException;
public void addMissingMethod(String methodName, Object obj, HproseResultMode mode, boolean simple, boolean oneway) throws NoSuchMethodException;

public void addMissingMethod(String methodName, Class<?> type) throws NoSuchMethodException;
public void addMissingMethod(String methodName, Class<?> type, HproseResultMode mode) throws NoSuchMethodException;
public void addMissingMethod(String methodName, Class<?> type, boolean simple) throws NoSuchMethodException;
public void addMissingMethod(String methodName, Class<?> type, HproseResultMode mode, boolean simple) throws NoSuchMethodException;
public void addMissingMethod(String methodName, Class<?> type, HproseResultMode mode, boolean simple, boolean oneway) throws NoSuchMethodException;

这是一个很有意思的方法,它用来发布一个特定的方法,当客户端调用的方法在服务器发布的方法中没有查找到时,将调用这个特定的方法。

使用 addMissingMethod 发布的方法可以是实例方法,也可以是静态方法,但是只能发布一个。如果多次调用 addMissingMethod 方法,将只有最后一次发布的有效。

addMissingMethod 发布的方法应为以下形式:

public Object missingMethod(String name, Object[] args);

第一个参数表示客户端调用时指定的方法名,方法名在传入该方法时全部是小写的。

第二个参数表示客户端调用时传入的参数列表。例如客户端如果传入两个参数,则 args 的数组长度为 2,客户端的第一个参数为 args 的第一个元素,第二个参数为 args 的第二个元素。如果客户端调用的方法没有参数,则 args 为长度为 0 的数组。

现在,您对 HproseMethods 的以上方法应该有一定程度的认识了,下面我们再结合 HproseServletsetGlobalMethods 方法来看一下如何实际应用它们。

setGlobalMethods 方法

setGlobalMethods 方法是在 HproseServletinit 方法最后被调用的,其参数为全局发布方法的集合。当我们需要在全局发布方法时,就可以覆盖这个方法来实现。

例如:

package hprose.exam.server;
import hprose.common.HproseMethods;
import hprose.server.HproseServlet;
public class MyHproseServlet extends HproseServlet {
    public String hello(String name) {
        return "Hello " + name;
    }
    @Override
    protected void setGlobalMethods(HproseMethods methods) {
        methods.addMethod("hello", this);
    }
}

HproseServlet 代码并不复杂,它的主要代码几乎全是关于配置的加载,而功能实现部分是在 HproseHttpService 类中完成的,因此你也可以直接使用 HproseHttpService 来实现自己的 Servlet,或者通过它来使用 JSP 发布服务,又或者通过它来实现与 Spring 等框架的集成。

HproseHttpServiceHproseService 的一个子类。HproseService 还有另外两个子类实现:HproseTcpServerHproseWebSocketService

你可能会奇怪,为什么 HproseHttpServiceHproseWebSocketService 结尾都是 Service,而 HproseTcpServer 的结尾是 Server。这并不是拼写错误,而是因为 HproseHttpServiceHproseWebSocketService 并不能单独启动,它们需要运行环境的支持。而 HproseTcpServer 是一个可以单独启动的服务器。

HproseService 实现了 Hprose 服务器代码的公共部分。这些子类实现了具体的传输协议部分。所以在介绍 HproseHttpService 之前,我们先来看一下,HproseService 中都包含了那些属性和方法。

HproseService 类

getCurrentContext 静态方法

public static ServiceContext getCurrentContext();

该方法返回当前执行环境的上下文对象。

对于 HproseService 的三个子类,还分别有三个重载版本:

public static HttpContext getCurrentContext();       // HproseHttpService
public static TcpContext getCurrentContext();        // HproseTcpServer
public static WebSocketContext getCurrentContext();  // HproseWebSocketService

通过该方法获取到的是一个本地线程变量,因此你可以安全的存取它。

关于 Hprose 上下文对象的更多介绍,请查阅 Hprose 上下文 一章。

globalMethods 属性

public HproseMethods getGlobalMethods();
public void setGlobalMethods(HproseMethods methods);

该属性用来设置或获取全局服务方法集合。用户一般不需要自己来设置。不能在服务启动之后再设置该属性,否则会产生不可预测的结果。

mode 属性

public final HproseMode getMode();
public final void setMode(HproseMode mode);

该属性用来设置或获取服务器序列化模式。默认值为 HproseMode.MemberMode 通常不需要修改。

debugEnabled 属性

public final boolean isDebugEnabled();
public final void setDebugEnabled(boolean enabled);

该属性用来设置或获取服务器是否是工作在调试模式下,在调试模式下,当服务器端发生异常时,将会将详细的错误堆栈信息返回给客户端,否则,只返回错误信息。默认值为 false

errorDelay 属性

public int getErrorDelay();
public void setErrorDelay(int errorDelay);

该属性表示在调用执行时,如果发生异常,将延时一段时间后再返回给客户端。

在关闭该功能的情况下,如果某个服务因为编写错误抛出异常,客户端又反复重试该调用,可能会导致服务器不能正常处理其它业务请求而造成的假死机现象。使用该功能,可以避免这种问题发生。

如果你不需要该功能,设置为 0 就可以关闭它。

该属性默认值为 10000,单位是毫秒。

event 属性

public final HproseServiceEvent getEvent();
public final void setEvent(HproseServiceEvent event);

该属性用于设置或获取 Hprose 服务器端的事件,对于 HTTP 和 TCP 服务器还有两个子接口,HproseHttpServiceEventHproseTcpServiceEvent

关于 HproseServiceEventHproseHttpServiceEvent 接口在前面已经介绍过了。这里再介绍一下 HproseTcpServiceEvent 接口。

HproseTcpServiceEvent 接口中有两个事件方法:

void onAccept(TcpContext tcpContext);
void onClose(TcpContext tcpContext);

当服务器端接收到客户端连接时,onAccept 事件被触发。当客户端到服务器端的连接关闭时,onClose 事件被触发。

至于可以在这些事件里能够做什么,用户可以自由发挥。

filter 属性

public final HproseFilter getFilter();
public final void setFilter(HproseFilter filter);

该属性默认值为 null。

该属性的作用是可以设置一个 Filter 对象。关于 Filter 对象,我们将作为单独的章节进行介绍,这里暂且略过。

因为通过该属性只能设置一个 Filter 当你需要设置多个 Filter 时,应使用 addFilter 方法代替该属性。

addFilter 方法

public final void addFilter(HproseFilter filter);

该方法同设置 filter 属性类似。该方法用于添加一个 filter 对象到 Filter 链的末尾,并可以连续添加多个 filter

removeFilter 方法

public final boolean removeFilter(HproseFilter filter);

该方法同设置 filter 属性类似。该方法用于从 Filter 链中删除指定的 filter 对象。

add 方法

public final void add(Method method, Object obj, String aliasName);
public final void add(Method method, Object obj, String aliasName, HproseResultMode mode);
public final void add(Method method, Object obj, String aliasName, boolean simple);
public final void add(Method method, Object obj, String aliasName, HproseResultMode mode, boolean simple);
public final void add(Method method, Object obj, String aliasName, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(Method method, Object obj);
public final void add(Method method, Object obj, HproseResultMode mode);
public final void add(Method method, Object obj, boolean simple);
public final void add(Method method, Object obj, HproseResultMode mode, boolean simple);
public final void add(Method method, Object obj, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(String methodName, Object obj, Class<?>[] paramTypes, String aliasName) throws NoSuchMethodException;
public final void add(String methodName, Object obj, Class<?>[] paramTypes, String aliasName, HproseResultMode mode) throws NoSuchMethodException;
public final void add(String methodName, Object obj, Class<?>[] paramTypes, String aliasName, boolean simple) throws NoSuchMethodException;
public final void add(String methodName, Object obj, Class<?>[] paramTypes, String aliasName, HproseResultMode mode, boolean simple) throws NoSuchMethodException;
public final void add(String methodName, Object obj, Class<?>[] paramTypes, String aliasName, HproseResultMode mode, boolean simple, boolean oneway) throws NoSuchMethodException;

public final void add(String methodName, Class<?> type, Class<?>[] paramTypes, String aliasName) throws NoSuchMethodException;
public final void add(String methodName, Class<?> type, Class<?>[] paramTypes, String aliasName, HproseResultMode mode) throws NoSuchMethodException;
public final void add(String methodName, Class<?> type, Class<?>[] paramTypes, String aliasName, boolean simple) throws NoSuchMethodException;
public final void add(String methodName, Class<?> type, Class<?>[] paramTypes, String aliasName, HproseResultMode mode, boolean simple) throws NoSuchMethodException;
public final void add(String methodName, Class<?> type, Class<?>[] paramTypes, String aliasName, HproseResultMode mode, boolean simple, boolean oneway) throws NoSuchMethodException;

public final void add(String methodName, Object obj, Class<?>[] paramTypes) throws NoSuchMethodException;
public final void add(String methodName, Object obj, Class<?>[] paramTypes, HproseResultMode mode) throws NoSuchMethodException;
public final void add(String methodName, Object obj, Class<?>[] paramTypes, boolean simple) throws NoSuchMethodException;
public final void add(String methodName, Object obj, Class<?>[] paramTypes, HproseResultMode mode, boolean simple) throws NoSuchMethodException;
public final void add(String methodName, Object obj, Class<?>[] paramTypes, HproseResultMode mode, boolean simple, boolean oneway) throws NoSuchMethodException;

public final void add(String methodName, Class<?> type, Class<?>[] paramTypes) throws NoSuchMethodException;
public final void add(String methodName, Class<?> type, Class<?>[] paramTypes, HproseResultMode mode) throws NoSuchMethodException;
public final void add(String methodName, Class<?> type, Class<?>[] paramTypes, boolean simple) throws NoSuchMethodException;
public final void add(String methodName, Class<?> type, Class<?>[] paramTypes, HproseResultMode mode, boolean simple) throws NoSuchMethodException;
public final void add(String methodName, Class<?> type, Class<?>[] paramTypes, HproseResultMode mode, boolean simple, boolean oneway) throws NoSuchMethodException;

public final void add(String methodName, Object obj, String aliasName);
public final void add(String methodName, Object obj, String aliasName, HproseResultMode mode);
public final void add(String methodName, Object obj, String aliasName, boolean simple);
public final void add(String methodName, Object obj, String aliasName, HproseResultMode mode, boolean simple);
public final void add(String methodName, Object obj, String aliasName, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(String methodName, Class<?> type, String aliasName);
public final void add(String methodName, Class<?> type, String aliasName, HproseResultMode mode);
public final void add(String methodName, Class<?> type, String aliasName, boolean simple);
public final void add(String methodName, Class<?> type, String aliasName, HproseResultMode mode, boolean simple);
public final void add(String methodName, Class<?> type, String aliasName, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(String methodName, Object obj);
public final void add(String methodName, Object obj, HproseResultMode mode);
public final void add(String methodName, Object obj, boolean simple);
public final void add(String methodName, Object obj, HproseResultMode mode, boolean simple);
public final void add(String methodName, Object obj, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(String methodName, Class<?> type);
public final void add(String methodName, Class<?> type, HproseResultMode mode);
public final void add(String methodName, Class<?> type, boolean simple);
public final void add(String methodName, Class<?> type, HproseResultMode mode, boolean simple);
public final void add(String methodName, Class<?> type, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(String[] methodNames, Object obj, String[] aliasNames);
public final void add(String[] methodNames, Object obj, String[] aliasNames, HproseResultMode mode);
public final void add(String[] methodNames, Object obj, String[] aliasNames, boolean simple);
public final void add(String[] methodNames, Object obj, String[] aliasNames, HproseResultMode mode, boolean simple);
public final void add(String[] methodNames, Object obj, String[] aliasNames, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(String[] methodNames, Object obj, String aliasPrefix);
public final void add(String[] methodNames, Object obj, String aliasPrefix, HproseResultMode mode);
public final void add(String[] methodNames, Object obj, String aliasPrefix, boolean simple);
public final void add(String[] methodNames, Object obj, String aliasPrefix, HproseResultMode mode, boolean simple);
public final void add(String[] methodNames, Object obj, String aliasPrefix, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(String[] methodNames, Object obj);
public final void add(String[] methodNames, Object obj, HproseResultMode mode);
public final void add(String[] methodNames, Object obj, boolean simple);
public final void add(String[] methodNames, Object obj, HproseResultMode mode, boolean simple);
public final void add(String[] methodNames, Object obj, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(String[] methodNames, Class<?> type, String[] aliasNames);
public final void add(String[] methodNames, Class<?> type, String[] aliasNames, HproseResultMode mode);
public final void add(String[] methodNames, Class<?> type, String[] aliasNames, boolean simple);
public final void add(String[] methodNames, Class<?> type, String[] aliasNames, HproseResultMode mode, boolean simple);
public final void add(String[] methodNames, Class<?> type, String[] aliasNames, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(String[] methodNames, Class<?> type, String aliasPrefix);
public final void add(String[] methodNames, Class<?> type, String aliasPrefix, HproseResultMode mode);
public final void add(String[] methodNames, Class<?> type, String aliasPrefix, boolean simple);
public final void add(String[] methodNames, Class<?> type, String aliasPrefix, HproseResultMode mode, boolean simple);
public final void add(String[] methodNames, Class<?> type, String aliasPrefix, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(String[] methodNames, Class<?> type);
public final void add(String[] methodNames, Class<?> type, HproseResultMode mode);
public final void add(String[] methodNames, Class<?> type, boolean simple);
public final void add(String[] methodNames, Class<?> type, HproseResultMode mode, boolean simple);
public final void add(String[] methodNames, Class<?> type, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(Object obj, Class<?> type, String aliasPrefix);
public final void add(Object obj, Class<?> type, String aliasPrefix, HproseResultMode mode);
public final void add(Object obj, Class<?> type, String aliasPrefix, boolean simple);
public final void add(Object obj, Class<?> type, String aliasPrefix, HproseResultMode mode, boolean simple);
public final void add(Object obj, Class<?> type, String aliasPrefix, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(Object obj, Class<?> type);
public final void add(Object obj, Class<?> type, HproseResultMode mode);
public final void add(Object obj, Class<?> type, boolean simple);
public final void add(Object obj, Class<?> type, HproseResultMode mode, boolean simple);
public final void add(Object obj, Class<?> type, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(Object obj, String aliasPrefix);
public final void add(Object obj, String aliasPrefix, HproseResultMode mode);
public final void add(Object obj, String aliasPrefix, boolean simple);
public final void add(Object obj, String aliasPrefix, HproseResultMode mode, boolean simple);
public final void add(Object obj, String aliasPrefix, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(Object obj);
public final void add(Object obj, HproseResultMode mode);
public final void add(Object obj, boolean simple);
public final void add(Object obj, HproseResultMode mode, boolean simple);
public final void add(Object obj, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(Class<?> type, String aliasPrefix);
public final void add(Class<?> type, String aliasPrefix, HproseResultMode mode);
public final void add(Class<?> type, String aliasPrefix, boolean simple);
public final void add(Class<?> type, String aliasPrefix, HproseResultMode mode, boolean simple);
public final void add(Class<?> type, String aliasPrefix, HproseResultMode mode, boolean simple, boolean oneway);

public final void add(Class<?> type);
public final void add(Class<?> type, HproseResultMode mode);
public final void add(Class<?> type, boolean simple);
public final void add(Class<?> type, HproseResultMode mode, boolean simple);
public final void add(Class<?> type, HproseResultMode mode, boolean simple, boolean oneway);

add 有许多的重载形式。它其实是 HproseMethods 上的 addMethod, addMethods, addIntanceMethods, addStaticMethods 四个方法的简写,参数跟这四个的参数完全一致,只是不再区分方法名。对于记不住该用哪个方法名的用户,直接使用 add 是个不错的方式。

Clone this wiki locally