1、自己编写 Servlet 发布 Hprose 服务如果您对直接使用 HproseServlet 发布服务还有什么不满的话,当然可以自己编写一个Servlet 来发布 Hprose 服务。而且您会发现这并不是什么难事,因为 Hprose 已经为您提供了很好的基础,您只需要对 HproseServlet 做一下扩展,或者直接使用HproseHttpService 来构建自己的 Servlet 即可。扩展 HproseServlet我们先来介绍最简单的方式,那就是以 HproseServlet 为基类,通过创建子类的方式来扩展 HproseServlet。使用这种方式,您可以更灵活的控制方法的发布。
2、在前面直接使用 HproseServlet 发布服务时,您会发现我们只能以类为单位来发布方法,而不能单独发布类或对象上的某一个或几个方法,另外,如果我们想对某一个方法指定别名,而不是对整个对象或类上所有方法增加名称空间(别名前缀)的话,也是做不到的。上面这些需求您都可以通过扩展 HproseServlet 来实现。创建 HproseServlet 的子类非常容易, HproseServlet 提供了多个可以覆盖的方法,其中最重要是:setGlobalMethods。该方法的参数类型是 HproseMethods 类型的,下面我们先来对 HproseMethods 类型做一下介绍。HproseM
3、ethods 类型HproseMethods 类型用于表示发布方法的集合。它有以下几个方法:1. addMethod2. addMethods3. addInstanceMethods4. addStaticMethods5. addMissingMethod下面我们对这几个方法分别做一下介绍。addMethod 方法addMethod 用来控制单个方法的发布,它有十种重载形式。通过它可以发布任意对象上的任意 public 实例方法,或任意类上的任意 public 静态方法,并且可以为每个方法都指定别名。当您发布的方法具有相同个数参数的重载时,使用 addMethod 是唯一可行的方法。add
4、Methods 方法addMethods 用来控制一组方法的发布,它有九种重载形式。如果您所发布的方法来自同一个对象,或是同一个类,使用 addMethods 方法通常比直接使用 addMethod 方法更为方便。因为您不但可以为每个方法都指定别名,还可以为这一组方法指定同一个名称空间(别名前缀) 。但实际上我们很少情况会直接使用它。因为有更加简单的addInstanceMethods 和 addStaticMethods 方法。addInstanceMethods 方法addInstanceMethods 用来发布指定对象上的指定类层次上声明的所有 public 实例方法。它有四种重载形式。
5、如果您在使用 addInstanceMethods 方法时,不指定类层次,则发布这个对象所在类上声明的所有 public 实例方法。这个方法也支持指定名称空间(别名前缀)。addStaticMethods 方法addStaticMethods 用来发布指定类上声明的所有 public 静态方法。它有两种重载形式。这个方法也支持指定名称空间(别名前缀) 。addMissingMethod 方法这是一个很有意思的方法,它用来发布一个特定的方法,当客户端调用的方法在服务器发布的方法中没有查找到时,将调用这个特定的方法。它有两种重载形式。使用 addMissingMethod 发布的方法可以是实例方法
6、,也可以是静态方法,但是只能发布一个。如果多次调用 addMissingMethod 方法,将只有最后一次发布的有效。用 addMissingMethod 发布的方法参数应为以下形式:Java 代码 (String name, Object args) 第一个参数表示客户端调用时指定的方法名,方法名在传入该方法时全部是小写的。第二个参数表示客户端调用时传入的参数列表。例如客户端如果传入两个参数,则 args 的数组长度为2,客户端的第一个参数为 args 的第一个元素,第二个参数为 args 的第二个元素。如果客户端调用的方法没有参数,则 args 为长度为0的数组。现在,您对 HproseM
7、ethods 的以上方法应该有一定程度的认识了,下面我们再结合HproseServlet 的 setGlobalMethods 方法来看一下如何实际应用它们。setGlobalMethods 方法setGlobalMethods 方法的定义形式如下:Java 代码 protected void setGlobalMethods(HproseMethods methods) 实际上它是在 HproseServlet 的 init 方法最后被调用的,其参数为全局发布方法的集合。当我们需要在全局发布方法时,就可以覆盖这个方法来实现。例如我们只想要发布一个 Exam2对象上的 getID 方法,通过直
8、接配置 HproseServlet 并不能得到我们想要的效果,那么通过覆盖 setGlobalMethods,我们就可以实现这个功能了。下面看我们自己定义的 Servlet:Java 代码 package hprose.exam; import hprose.server.HproseServlet; import mon.HproseMethods; public class MyHproseServlet extends HproseServlet protected void setGlobalMethods(HproseMethods methods) Exam2 exam2 = ne
9、w Exam2(); methods.addMethod(“getID“, exam2); 是不是很简单,只需要9行代码,就完成我们自己的 HproseServlet 了。接下来我们看看如何使用 HproseHttpService 来构建 Servlet。使用 HproseHttpService 来构建 Servlet通常我们是不需要使用 HproseHttpService 来构建 Servlet 的,因为通过配置和扩展HproseServlet 已经几乎可以满足所有要求了。但您仍然有理由来使用 HproseHttpService 构建 Servlet,例如:您可能希望发布服务能够与 Spri
10、ng 集成;或者您可能不喜欢配置文件,而希望通过使用注解(annotation)方式来发布服务。当然,您还可能希望不在全局范围内发布方法,而是为每个请求或每个会话来创建对象并发布其上的方法。在这种情况下,使用 HproseHttpService 来构建 Servlet 将是个好主意。但是我们并不打算在这里介绍如何编写与 Spring 集成发布服务的 Servlet,也没有打算介绍如何编写一个使用注解(annotation)方式发布服务的 Servlet。因为这将花费不少篇幅,并且大部分代码脱离了我们要重点介绍的内容。我们这里主要来讲解在使用 HproseHttpService 来构建自己的 S
11、ervlet 时,需要注意的一些问题,以及如何为每个请求或每个会话来创建对象并发布其上的方法。按请求发布方法这里我们还是以发布 Exam2上面的方法为例,来说明如何编写 Servlet:Java 代码 package hprose.exam; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.
12、HttpServletResponse; import hprose.server.HttpContext; import hprose.server.HproseHttpMethods; import hprose.server.HproseHttpService; public class MyHproseServlet2 extends HttpServlet private HproseHttpService service = new HproseHttpService(); protected void processRequest(HttpServletRequest reque
13、st, HttpServletResponse response) throws ServletException, IOException Exam2 exam2 = new Exam2(); HproseHttpMethods methods = new HproseHttpMethods(); methods.addInstanceMethods(exam2); methods.addInstanceMethods(exam2, Exam1.class); service.handle(new HttpContext(request, response, this.getServletC
14、onfig(),this.getServletContext(), methods); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException processRequest(request, response); protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
15、IOException processRequest(request, response); public String getServletInfo() return “Hprose Servlet 1.0“; 您完全可以把上面的例子作为模版来改写成您自己的 Servlet。在这个例子中,关键的方法就是 processRequest 方法。首先创建 HproseHttpMethods 类的对象,之后通过该对象上的 addInstanceMethods 方法发布 Exam2对象上的方法,最后通过 HproseHttpService 对象的 handle 方法来处理请求。handle 方法的第一
16、个参数是 HttpContext 类型,这里需要通过创建 HttpContext 对象实例来初始化当前上下文,第二个参数就是我们要发布的方法集合。按请求发布方法时,发布的方法不必是线程安全的,按会话或者全局发布的方法应该保证方法本身是线程安全的。按请求发布方法的情况不多,但是按会话发布方法的情况却可能经常会遇到,下面我们就来说明一下如何按会话来发布方法。按会话发布方法因为按会话发布和按请求发布的主要区别在 processRequest 方法上,所以我们下面的例子中,只写这一个方法。Java 代码 protected void processRequest(HttpServletRequest
17、request, HttpServletResponse ponse) throws ServletException, IOException HttpSession session = request.getSession(); HproseHttpMethods methods = (HproseHttpMethods) session.getAttribute(“exam2“); if (methods = null) Exam2 exam2 = new Exam2(); methods = new HproseHttpMethods(); methods.addInstanceMet
18、hods(exam2); methods.addInstanceMethods(exam2, Exam1.class); session.setAttribute(“exam2“, methods); service.handle(new HttpContext(request, response, this.getServletConfig(), this.getServletContext(), methods); 在这个例子中我们首先获取了 session 对象。之后,我们查询 session 中是否已经包含了发布的方法集合,如果有就直接使用它,否则通过 new 运算符创建一个新的,在添
19、加完发布的方法后,将其以 exam2为名放入 session 中。之后就是发布 exam2上的方法了。这个例子很好懂,这里就不再多作解释啦。HproseHttpService 还有许多方法和属性,可以直接参见 HproseServlet 源码来了解它们的用法。自己编写 JSP 发布 Hprose 服务使用 JSP 来发布 Hprose 很简单,也是使用 HproseHttpService 来实现,但这是最不常用的方式,当然也是不推荐的方式。因为使用 JSP 方式相对于 Servlet 来说效率较低。所以,下面我们仅用一个简单的例子来结束本章,不再对例子作详细说明,因为有了前面的基础,相信您一定很容易看懂下面的例子:Java 代码 在某些服务器上用 JSP 方式发布服务,可能会出现一下错误信息:Java 代码 java.lang.IllegalStateException: getOutputStream() has already been called for this response 解决方法只需要在页面最后,加入以下语句即可:Java 代码 out.clear(); out = pageContext.pushBody(); 另外要注意保存 JSP 文件时请使用 UTF-8编码,并去掉 BOM。