-
Notifications
You must be signed in to change notification settings - Fork 187
Hprose 服务器
Hprose 2.0 for Java 支持多种底层网络协议绑定的服务器,比如:HTTP 服务器,TCP 服务器和 WebSocket 服务器。
HTTP 服务器支持在 HTTP、HTTPS 协议上通讯。
TCP 服务器支持在 TCP 协议上通讯,并且支持全双工和半双工两种模式。
WebSocket 服务器支持在 ws、wss 协议上通讯。
我们下面先从最常用的 HTTP 服务器说起。
通过 HproseServlet
发布服务很简单,直接通过配置方式就可以,如果要发布的类是现成的,您不需要编写一行代码就可以完成发布。
发布的方法可以是静态方法,也可以是实例方法。但必须是 public
方法。您还可以同时发布多个类中的方法。
下面我们来看一下 HproseServlet
都有哪些可配置项。
<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>
时,只发布 foobar
和 bar
方法。
当配置为:
<init-param>
<param-name>class</param-name>
<param-value>Service2|BaseService1</param-value>
</init-param>
时,将发布 foobar
,bar
和 foo
方法。
之所有这样做,是因为所有的类都是从祖先类 Object
继承下来的,如果将继承来的 public
方法都发布的话,势必会将从 Object
继承来的方法也一起发布,这很可能不是用户所期望的结果。另一个原因,用户定义的类的层次可能比较深,而其定义的基类上的方法可能并不想被一起发布。因此,默认情况下,只发布直接在该类中声明的 public
方法,而不会发布继承来的方法。
从上面的几个例子中,我们还会发现,后两部分的配置是可选的。
名称空间的用处是可以将同一个服务的不同对象上的同名方法区分开,例如:
<init-param>
<param-name>class</param-name>
<param-value>Service2|BaseService1|service2,Service1||service1</param-value>
</init-param>
将会发布两个对象上的方法,第一个是 Service2
类的实例对象,它上面的 foobar
,bar
和 foo
方法都会发布。第二个是 Service1
类的实例对象,它上面的 bar
方法会被发布。因为加了名称空间,所以实际发布的方法名是:
service2_foobar
service2_bar
service2_foo
service1_bar
这样就把两个 bar
方法区分开了,在客户端调用时,同样可以指定名称空间(在客户端部分有介绍),或者直接使用全名调用。
从上面的配置中,我们还可以看到,配置的第二部分可以忽略,但是在有第三部分时, |
不能忽略。
<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>
将只发布 foo
和 bar
方法,因为 foobar
方法不是静态方法。
<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");
注册之后的类型,在传输时将使用注册名来代替类名与客户端进行交互。
取值为有三个:
- FieldMode
- PropertyMode
- MemberMode
配置时,大小写无关。该选项表示采用何种模式序列化自定义对象。默认值为 MemberMode
,通常不需要配置该选项,采用默认方式就可以了。
配置方式如下:
<init-param>
<param-name>mode</param-name>
<param-value>propertyMode</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
默认情况下,在调用过程中,服务器端发生错误时,只返回有限的错误信息。当打开调试开关后,服务器会将错误堆栈信息全部发送给客户端,这样,在客户端可以得到详细的错误信息。
<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.xml
和 clientaccesspolicy.xml
的更多内容请参阅:
- http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html
- http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security.html
- http://msdn.microsoft.com/en-us/library/cc197955%28v=VS.95%29.aspx
- http://msdn.microsoft.com/en-us/library/cc838250%28v=VS.95%29.aspx
<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
<init-param>
<param-name>p3p</param-name>
<param-value>true</param-value>
</init-param>
这个配置项决定是否发送 P3P 的 HTTP 头,这个头的作用是让 IE 允许跨域接收的 Cookie。当您的服务需要在浏览器中被跨域调用,并且希望传递 Cookie 时(例如通过 Cookie 来传递 Session ID),您可以考虑将这个开关打开。否则,无需开启此开关。此开关默认是关闭状态。
<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
就可以了。
<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
事件被触发。
name
为客户端所调用的方法名。
args
为方法的参数。
byRef
表示是否是引用参数传递的调用。
context
为服务上下文,你可以将其转型为:ServiceContext
或 HttpContext
类型。通过该对象,你可以得到调用方法的更多信息,或者 HTTP 的各种上下文对象,例如:request,response, session 等。你还可以通过 HproseContext
上的方法来设置或获取一些你自己定义的一些数据。这些数据可以在各个事件,各个过滤器,各个中间件之间按执行顺序传递。
您可以在该事件中做用户身份验证,例如基于 session 的用户名密码验证,IP 验证等。也可以作日志记录。如果在该事件中想终止调用,抛出异常即可。
当服务器端发布的方法被成功调用后,onAfterInvoke
事件被触发,其中name
, args
, byRef
, context
与 onBeforeInvoke
事件一致,参数 result
表示调用结果。
当调用发生错误时,onAfterInvoke
事件将不会被触发。如果在该事件中抛出异常,则调用结果不会被返回,客户端将收到此事件抛出的异常。
当服务器端调用抛出异常,或者在 onBeforeInvoke
、onAfterInvoke
事件中抛出异常时,该事件被触发。
您可以在该事件中作日志记录。
如果你希望返回客户端的异常与传入的异常参数不同,你可以通过返回或抛出一个新的异常来代替传入的异常,否则返回 null
即可。
当服务器端与客户端无法通讯时并抛出异常时,会触发该事件。
您可以在该事件中作日志记录。
该事件中不应抛出任何异常。
当服务器返回响应头部时,onSendHeader 事件会被触发。
在该事件中,您可以发送您自己的头信息,例如设置 Cookie,自定义头等等。
该事件中不应抛出任何异常。
<init-param>
<param-name>filter</param-name>
<param-value>Filter1,Filter2,...</param-value>
</init-param>
通过该配置可以添加一个或多个 Filter
,关于 Filter
的更多内容,请参见:Hprose 过滤器一章。
<init-param>
<param-name>beforeFilter</param-name>
<param-value>Handler1,Handler1,...</param-value>
</init-param>
通过该配置可以添加一个或多个在 Filter 执行之前的输入输出中间件处理器,关于中间件的更多内容,请参见:Hprose 中间件一章。
<init-param>
<param-name>afterFilter</param-name>
<param-value>Handler1,Handler1,...</param-value>
</init-param>
通过该配置可以添加一个或多个在 Filter 执行之后的输入输出中间件处理器,关于中间件的更多内容,请参见:Hprose 中间件一章。
<init-param>
<param-name>invoke</param-name>
<param-value>Handler1,Handler1,...</param-value>
</init-param>
通过该配置可以添加一个或多个调用中间件处理器,关于中间件的更多内容,请参见:Hprose 中间件一章。
<init-param>
<param-name>topic</param-name>
<param-value>topic1|timeout1|heartbeat1,topic2|timeout2|heartbeat2,...</param-value>
</init-param>
通过该配置项,可以用于发布推送主题。多个主题之间用 ,
分隔,每个主题的参数之间用 |
分隔。timeout
和 heartbeat
参数都可以省略。
如果您觉得直接使用 HproseServlet
发布服务还不能满足您的要求,您当然也可以自己编写一个 Servlet 来发布 Hprose 服务。这并不是什么难事,因为 Hprose 已经为您提供了很好的基础,您只需要对 HproseServlet
做一下扩展,或者直接使用 HproseHttpService
来构建自己的Servlet 即可。
我们先来介绍最简单的方式,那就是以 HproseServlet
为基类,通过创建子类的方式来扩展 HproseServlet
。使用这种方式,您可以更灵活的控制方法的发布。
在前面直接使用 HproseServlet
发布服务时,您会发现我们只能以类为单位来发布方法,而不能单独发布类或对象上的某一个或几个方法,另外,如果我们想对某一个方法指定别名,而不是对整个对象或类上所有方法增加名称空间(别名前缀)的话,也是做不到的。
上面这些需求您都可以通过扩展 HproseServlet
来实现。
创建 HproseServlet
的子类非常容易,HproseServlet
提供了多个可以覆盖的方法,其中最重要是:setGlobalMethods
。
protected void setGlobalMethods(HproseMethods methods);
该方法的参数类型是 HproseMethods
类型的,下面我们先来对 HproseMethods
类型做一下介绍。
HproseMethods
类型用于表示发布方法的集合。它有以下几个方法:
addMethod
addMethods
addInstanceMethods
addStaticMethods
addMissingMethod
下面我们对这几个方法分别做一下介绍。
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
参数指定的类型一致时才会发布,通过该参数可以将同名重载方法区分发布。
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
参数)。但实际上我们很少情况会直接使用它。因为有更加简单的 addInstanceMethods
和 addStaticMethods
方法。
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
参数)。
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
参数)。
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
的以上方法应该有一定程度的认识了,下面我们再结合 HproseServlet
的 setGlobalMethods
方法来看一下如何实际应用它们。
setGlobalMethods
方法是在 HproseServlet
的 init
方法最后被调用的,其参数为全局发布方法的集合。当我们需要在全局发布方法时,就可以覆盖这个方法来实现。
例如:
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 等框架的集成。
HproseHttpService
是 HproseService
的一个子类。HproseService
还有另外两个子类实现:HproseTcpServer
和 HproseWebSocketService
。
你可能会奇怪,为什么 HproseHttpService
和 HproseWebSocketService
结尾都是 Service
,而 HproseTcpServer
的结尾是 Server
。这并不是拼写错误,而是因为 HproseHttpService
和 HproseWebSocketService
并不能单独启动,它们需要运行环境的支持。而 HproseTcpServer
是一个可以单独启动的服务器。
HproseService
实现了 Hprose 服务器代码的公共部分。这些子类实现了具体的传输协议部分。所以在介绍 HproseHttpService
之前,我们先来看一下,HproseService
中都包含了那些属性和方法。