httpInvoker获取客户端request

来源:互联网 发布:java打印数字菱形 编辑:程序博客网 时间:2024/05/22 12:49

最近在使用HttpInvoker需要获取客户端的request进行额外操作,上网搜了一些资料,不过没有找到相关资料,区别去xfire获取request时使用的XfireServletAction.getRequest(),貌似没有看到httpInvoker提供这样的API
所以不能不去看源码。

先来看下HttpInvokerServiceExporter服务导出的源码:

    RemoteInvocation invocation;
    try
    {
      invocation = readRemoteInvocation(request);
      RemoteInvocationResult result = invokeAndCreateResult(invocation, getProxy());
      writeRemoteInvocationResult(request, response, result);
    }

handlerRequest执行了三部操作:

   1、获取客户端request请求,通过HTTP请求,得到客户端传过来的RemoteInvocation对象,该对象中封装了服务调用需要的基本信息。

   2、服务方法的调用,构建远端服务返回的结果,以RemoteInvocationResult返回,这一过程中蛮重要的一点是完成对象序列化。(后来在比较中才发现hessian和http-invoker的content-type的区别就在于这个地方)

   3、设置response的content-type,同时将result输出到http的response.

(个人理解还不够透彻.....我说错的地方,还请指出!谢谢)

所以其实Http-invoker这边还是可以获取到request,只是并没有提供一个地方保存当前线程的request,所以在这个地方进行了改动。

首先自定义一个类,用于保存当前request

public class HttpInvokerRequestContext {
 private HttpServletRequest _request;
 private static final ThreadLocal<HttpInvokerRequestContext> _localContext = new ThreadLocal<HttpInvokerRequestContext>() {
  public HttpInvokerRequestContext initialValue() {
   return new HttpInvokerRequestContext();
  }
 };
 
 private HttpInvokerRequestContext() {}
 
 public static final void setRequest(HttpServletRequest request) {
  _localContext.get()._request = request;
 }
 
 public static final HttpServletRequest getRequest() {
  return _localContext.get()._request;
 }
 
 public static final void clear() {
  _localContext.get()._request = null;
 }
}

然后修改HttpInvokerServiceExporter,在获取客户端request的时候将当前request保存进来

public class SelfHttpInvokerExporter extends HttpInvokerServiceExporter
  implements HttpRequestHandler {

 public void handleRequest(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
  RemoteInvocation remoteInvocation;
  try {
   remoteInvocation = this.readRemoteInvocation(request);
   HttpInvokerResponseContext.setHttpResponse(response);
   RemoteInvocationResult result = this.invokeAndCreateResult(remoteInvocation, super.getProxy());
   this.writeRemoteInvocationResult(request, response, result);
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  } finally {
   HttpInvokerRequestContext.clear();
   HttpInvokerResponseContext.clear();
  }
//  super.handleRequest(arg0, arg1);
 }
 
 protected RemoteInvocation readRemoteInvocation(HttpServletRequest request)
   throws IOException, ClassNotFoundException {
  HttpInvokerRequestContext.setRequest(request);
  return super.readRemoteInvocation(request);
 }

 protected void writeRemoteInvocationResult(HttpServletRequest request,
   HttpServletResponse response, RemoteInvocationResult result)
   throws IOException {
  super.writeRemoteInvocationResult(request, response, result);
 }

 protected RemoteInvocationResult invokeAndCreateResult(
   RemoteInvocation remoteInvocation, Object arg1) {
  return super.invokeAndCreateResult(remoteInvocation, arg1);
 }

最后修改下配置

 <bean name="/userLoginService" class="com.pokercity.core.httpInvoker.SelfHttpInvokerExporter">
  <property name="service" ref="userLoginService" />
  <property name="serviceInterface" value="com.pokercity.service.IUserLoginService" />
 </bean>

userLoginService里面需要用到request的时候,直接使用HttpInvokerRequestContext .getRequest()就可以了

测试了下可以获取到request对象

PS:个人使用总结,对于有些地方认识还不够深刻,如有错误,劳烦指出!

原创粉丝点击