Hprose for Java 服务器(二)

李捷
2023-12-01
[b][size=x-large]隐藏发布列表[/size][/b]

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

如果您不希望用户直接通过浏览器就可以查看发布列表的话,您可以禁止服务器接收GET请求。方法很简单,只需要将初始化参数get设置为false即可,配置如下:
<init-param>
<param-name>get</param-name>
<param-value>false</param-value>
</init-param>


好了,现在通过GET方式访问不再显示发布列表啦。但是客户端调用仍然可以正常执行,丝毫不受影响。不过在调试期间,不建议禁用发布列表,否则将会给您的调试带来很大的麻烦。也许您更希望能够在调试期得到更多的调试信息,那这个可以做到吗?答案是肯定的,您只要打开调试开关就可以了。

[b][size=x-large]调试开关[/size][/b]

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

配置方法与隐藏发布列表类似,只需要将初始化参数debug设置为true即可。
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>


[b][size=x-large]对象序列化模式[/size][/b]

前面我们发布的getUserList方法传递的是自定义可序列化对象列表。在介绍自定义可序列化对象上我们也多次提到有两种序列化模式:字段模式和属性模式。那么如何来配置使用哪种模式呢?

同样,通过设置初始化参数就可以完成配置,例如如果要设置成属性模式(默认是字段模式),只需要加入以下配置信息即可:
<init-param>
<param-name>mode</param-name>
<param-value>propertyMode</param-value>
</init-param>

设置为属性模式传输时,属性名首字母自动以小写表示,其它部分大小写不变,这样不但可以跟字段序列化模式统一,跟其它语言对象中的字段或属性命名也统一。

[b][size=x-large]P3P开关[/size][/b]

在Hprose的http服务中还有一个P3P开关,这个开关决定是否发送P3P的http头,这个头的作用是让IE允许跨域接收的Cookie。当您的服务需要在浏览器中被跨域调用,并且希望传递Cookie时(例如通过Cookie来传递Session ID),您可以考虑将这个开关打开。否则,无需开启此开关。此开关默认是关闭状态。开启方法如下:
<init-param>
<param-name>p3p</param-name>
<param-value>true</param-value>
</init-param>


[b][size=x-large]服务器事件[/size][/b]

也许您可能还希望设置其它的http头,或者希望在发生错误时,能够在服务器端进行日志记录。甚至希望在调用发生的前后可以做一些权限检查或日志记录等。在Hprose中,这些都可以轻松做到。Hprose提供了这样的事件机制。

Hprose服务器提供了4个事件,它们被定义为HproseServiceEvent接口的四个方法:

package hprose.server;
public interface HproseServiceEvent {
void onBeforeInvoke(String name, Object[] args, boolean byRef);
void onAfterInvoke(String name, Object[] args, boolean byRef, Object result);
void onSendHeader();
void onSendError(String error);
}


您只需要实现此接口就可以完成事件的定义啦。

[b][size=large]事件配置[/size][/b]

如果您已经定义好了事件类(这里我们假设事件类的类名为hprose.exam.Event),那么只需要在Servlet的初始化参数中配置以下参数即可:

<init-param>
<param-name>event</param-name>
<param-value>hprose.exam.Event</param-value>
</init-param>

那这个事件类该如何定义呢?下面我们就来对这四个事件分别做一下介绍。

[b][size=large]onBeforeInvoke事件[/size][/b]

当服务器端发布的方法被调用前,onBeforeInvoke事件被触发,其中name为客户端所调用的方法名,args为方法的参数,byRef表示是否是引用参数传递的调用。
您可以在该事件中做用户身份验证,例如IP验证。也可以作日志记录。如果在该事件中想终止调用,抛出异常即可。

[b][size=large]onAfterInvoke事件[/size][/b]

当服务器端发布的方法被成功调用后,onAfterInvoke事件被触发,其中前三个参数与onBeforeInvoke事件一致,最后一个参数result表示调用结果。
当调用发生错误时,onAfterInvoke事件将不会被触发。如果在该事件中抛出异常,则调用结果不会被返回,客户端将收到此事件抛出的异常。

[b][size=large]onSendHeader事件[/size][/b]

当服务器返回响应头部时,onSendHeader事件会被触发。
在该事件中,您可以发送您自己的头信息,例如设置Cookie。该事件中不应抛出任何异常。

[b][size=large]onSendError事件[/size][/b]

当服务器端调用发生错误,或者在onBeforeInvoke、onAfterInvoke事件中抛出异常时,该事件被触发。

您可以在该事件中作日志记录,但该事件中不应再抛出任何异常。

[b][size=x-large]存取环境上下文[/size][/b]

在上面介绍的服务器事件或者服务器发布的方法中,您可能会需要存取环境上下文,例如Request,Response,Session,Application,那么有什么方便的方法来获取它们吗?
Hprose提供了HttpContext这个帮助类来表示在http环境下的上下文信息,通过HproseHttpService类的getCurrentContext静态方法,您可以获取到当前的环境上下文对应的HttpContext对象。然后再通过该对象上的getRequest、getResponse、getSession、getConfig、getApplication方法就可以获取到您需要的对象了。

HttpContext帮助类可以在服务器事件中使用,也可以在服务器发布的方法中使用。另外,在服务器发布的方法中还有另外一种方式来获取环境上下文,那就是将方法的最后一个参数定义为相应的环境上下文类型。

例如要获取Session对象,只需要将最后一个参数定义为HttpSession类型即可:
public String getSessionID(HttpSession session) {
return session.getId();
}

客户端在调用该方法时,不需要代入任何参数,服务器会自动传递session参数给该方法。与上面方法等价的使用HttpContext帮助类实现的方法写法如下:
public String getSessionID() {
HttpContext context = HproseHttpService.getCurrentContext();
HttpSession session = context.getSession();
return session.getId();
}

通过对比,您会发现直接通过参数传递方式的写法更简洁一些。通过参数方式可以传递HttpContext本身和它所包含的所有的环境上下文类型,但是通过参数传递方式只能传递一个环境上下文参数。

[b][size=x-large]发布静态方法[/size][/b]

发布静态方法跟发布实例方法类似,只不过您在定义类时,需要把方法都定义成static public方法。之后在配置时,添加参数名为staticClass的初始化参数。staticClass的值就是静态方法所在的类名,可以指定多个,使用“,”分隔。同样,也可以为静态方法的类指定名称空间(别名前缀),用“|”分隔。

假设我们有hprose.exam.Exam3和hprose.exam.Exam4两个类中的静态方法要发布,并且希望给hprose.exam.Exam3指定名称空间的话,可以这样配置:

<init-param>
<param-name>staticClass</param-name>
<param-value>hprose.exam.Exam3|ex3,hprose.exam.Exam4</param-value>
</init-param>

静态方法和实例方法的发布可以在同一个Servlet中配置。如果有同名方法,就是用名称空间(别名前缀)来区分。否则同名静态方法会覆盖同名实例方法的发布。

好了,直接使用HproseServlet发布服务到这里我们就全部介绍完了。如果您觉得它已经可以满足您的全部需求,那么您就可以直接跳过下面几节进入下一章了。如果它还不能完全满足您的需求,那么接下来的几节可能对您就非常重要了,下面几节将让您更加灵活的控制服务的发布。
 类似资料: