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