返回首页
当前位置: 主页 > j2ee介绍 >

为J2EE应用程序构建分布式对象管理框架5

时间:2009-06-19 14:19来源:未知 作者:admin 点击:
用来传递范围信息的上下文 在分布式环境中,范围跨多个组件。因此,在一个组件中创建的范围键必须被传递给其他组件,让这些组件可以使用键获取与这个范围相关联的对象。跨多个
  

用来传递范围信息的上下文

    在分布式环境中,范围跨多个组件。因此,在一个组件中创建的范围键必须被传递给其他组件,让这些组件可以使用键获取与这个范围相关联的对象。跨多个组件传递范围键的惟一方法是通过方法调用。为了帮助实现这种方式,需要用一个上下文对象存储范围信息。对于每个请求,创建一个上下文对象。这个对象存储当前请求范围、HTTP 会话范围和应用程序范围的键。然后,通过方法调用把这个对象传递给其他组件。当一个事务开始时,这个事务的范围键被添加到这个上下文对象中。当事务结束时,删除对应的范围键。清单 8 定义这个对象的 API.

    清单 8. RequestContext API

public interface RequestContext {
   /**
    * Get the scope key for the given scope type.
    *
    * @param scopeType
    * @return
    */
   public Object getScopeKey(int scopeType);

   /**
    * Set the scope key for the given scope type.
    *
    * @param scopeType
    * @param scopeKey
    */
   public void setScopeKey(int scopeType, Object scopeKey);
}

    因为需要跨组件传递上下文对象,所以这个对象应该是可序列化的。

    修改后的示例

    现在可以用 JMS 和 RequestContext 修改前面的示例。除了创建请求范围键之外,在处理请求之前,MyRequestProcessor 需要获得应用程序范围键和会话范围键,并把它们存储在 RequestContext 对象中。在处理请求之后,它发送一个 JMS 消息,表示这个请求范围已经结束。清单 9 演示实现方法。

    清单 9. 修改后的 RequestProcessor 类实现

public class MyRequestProcessor extends RequestProcessor{
   public void
          process(HttpServletRequest request, HttpServletResponse response)
      throws IOException, ServletException {

      // assume when application started, the application id was generated
      // and stored in ServletContext with attribute name " appScopeKey"
      String appScopeKey =
                request.getServletContext().getAttribute("appScopeKey");

      // session scope key
      String sessionScopeKey = request.getSession().getId();

      // request scope key
      String requestScopeKey = UniqueIDGenerator.GetID();

      RequestContext ctx = RequestContextFactory.getInstance();
      ctx.setScopeKey(ScopeType.APPLICATION, appScopeKey);
      ctx.setScopeKey(ScopeType.HTTP_SESSION, sessionScopeKey);
      ctx.setScopeKey(ScopeType.REQUEST, requestScopeKey);

      // store the request context in request
      request.setAttribute("requestContext", ctx);

      try {

         // process the request
         super.process(request, response);

      } finally {

         // after the request is processed, release all objects bound
         // to this request scope
         TopicConnectionFactory tcf = (TopicConnectionFactory)
         ctx.lookup("ObjectManagerJMSConnection");
         TopicConnection tc = tcf.createTopicConnection();
         tc.start();
         TopicSession ts = tc.createTopicSession(false, 1);
         Topic t = (Topic) ctx.lookup("ObjectManagerJMSTopic");
         TopicPublisher tp = ts.createPublisher(t);

         TextMessage tm = ts.createTextMessage();
         tm.setText(ScopeTypes.REQUEST + ":" + requestScopeKey);
         tp.publish(tm);

      }
   }

}

    修改后的 AnyAction 类(清单 10)演示如何从 RequestContext 对象获取请求范围键并把 RequestContext 对象传递给 EJB 组件。

    清单 10. 修改后的 Action 类实现

public class AnyAction extends Action{
   public ActionForward execute(ActionMapping mapping,
   ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response) {

         // ...

         RequestContext ctx =
              (RequestContext) request.getAttribute("requestContext");

         // get the request scope key from the context object
         String scopeKey = ctx.getScopeKey(ScopeType.REQUEST);
         ObjectManager objMgr = ObjectManagerFactory.GetInstance();
         obj =
              objMgr.getObject(obj.getClass(), ScopeTypes.REQUEST, scopeKey);

         // call methodY of sessionBeanX and pass the context object
         // as an parameter
        sessionBeanX.methodY(params, ctx);

         // ...
   }
}

    清单 10 中的示例代码并不像 清单 5 那样从 HttpServletRequest 获取范围键,而是从 HttpServletRequest 获取 RequestContext 对象。然后,从 RequestContext 对象获取范围键。在调用 EJB 对象的远程或本地接口时,通过参数传递 RequestContext 对象。

    我还添加了 SessionBeanX(清单 11),演示如何在 EJB 组件中使用 RequestContext 对象。

    清单 11. SessionBean 类实现

public class SessionBeanX implements SessionBean{

   public void methodY (Object params, RequestContext ctx) {

      // ...

      // get the request scope key from the context object
      String scopeKey = ctx.getScopeKey(ScopeType.REQUEST);
      ObjectManager objMgr = ObjectManagerFactory.GetInstance();
      obj = objMgr.getObject(obj.getClass(), ScopeTypes.REQUEST, scopeKey);

      // ...

   }

}

    为了获取范围信息,SessionBeanX 类的每个方法必须有 RequestContext 参数。如 清单 10 所示,当 EJB 客户机调用远程或本地接口时,它必须传递 RequestContext 对象,这个对象包含关于当前范围的信息。然后,bean 方法中的 RequestContext 对象可以获得当前范围的键 —— 例如,通过 methodY()。

    结束语

    本文介绍了一个用于在 J2EE 应用程序中管理对象实例的框架。这个框架的主要优点是,它使用在 J2EE 中定义的事件触发机制自动地释放对象实例。这不仅使开发人员不必在代码中显式地释放对象,还可以减少内存泄漏的风险。本文的前半部分针对服务器端代码在单一 JVM 中运行的系统。后半部分针对服务器端代码在多个 JVM 中运行的环境。在本文中,我通过示例代码解释了概念。性能基准测试超出了本文的范围,将在以后的文章中讨论。

顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
最新评论 查看所有评论
发表评论 查看所有评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
发布者资料
admin 查看详细资料 发送留言 加为好友 用户等级:高级会员 注册时间:2009-06-09 07:06 最后登录:2009-08-19 21:08
推荐内容