【问题标题】:Custom session Listener with Hazelcast session replication具有 Hazelcast 会话复制的自定义会话侦听器
【发布时间】:2016-07-22 15:38:49
【问题描述】:

我为会话复制配置了 Hazelcast:

<filter>
  <filter-name>hazelcast-filter</filter-name>
  <filter-class>com.hazelcast.web.WebFilter</filter-class>

  <init-param>
    <param-name>map-name</param-name>
    <param-value>my-sessions</param-value>
  </init-param>
  <init-param>
    <param-name>cookie-name</param-name>
    <param-value>hazelcast.sessionId</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>hazelcast-filter</filter-name>
  <url-pattern>/</url-pattern>
  <dispatcher>FORWARD</dispatcher>
  <dispatcher>INCLUDE</dispatcher>
  <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<listener>
  <listener-class>com.hazelcast.web.SessionListener</listener-class>
</listener>

在我的网络应用程序中,用户可以创建在会话中持续存在直到完成的订单。如果订单未完成并且会话被破坏(用户注销或会话过期),我想备份该订单处理的所有数据。

在没有 Hz 会话复制的情况下,我使用自定义 HttpSessionListener 实现来完成此操作,例如:

@Override
public void sessionDestroyed(HttpSessionEvent se) {
    Order order = (Order) se.getSession().getAttribute("order");
    if (order != null) {
      // Backup all data processed by order
    }
}

它工作正常,但使用 Hz 我得到了 2 个未同步的不同会话:

switch (action) {
    case "addOrderItems":
        System.out.print("sesId=" + req.getSession().getId());
        System.out.println("order=" + req.getSession().getAttribute("order"));

打印sesId=HZDCDC1C77E7934E03A9FE329AAB7053B0 order=Order@6a5f7445

同时

@Override
public void sessionDestroyed(HttpSessionEvent se) {
    System.out.print("sesId=" + se.getSession().getId());
    System.out.println("order=" + se.getSession().getAttribute("order"));

打印sesId=8748D170885C44B425FEEAA94AAB8A86 order=null

Hazelcast 似乎创建并销毁了它自己的会话,而我无法(或不知道如何)监听此会话事件。

是否可以使两个会话保持同步或实现您自己的 Listener for Hz 会话?

【问题讨论】:

    标签: java session listener hazelcast session-replication


    【解决方案1】:

    两个步骤应该可以让你到达那里

    如果您先创建一个 Hazelcast 实例,那么您可以将其名称作为参数传递,

    <init-param>
      <param-name>instance-name</param-name>
      <param-value>whatever</param-value>
    </init-param>
    

    因此会话复制将使用该预先存在的 Hazelcast 实例,而不是生成一个新实例。

    当您创建该实例时,您可以以正常方式将侦听器附加到会话存储映射。

    <map name="my-sessions">
      <entry-listeners>
        <entry-listener local="true" include-value="true">your.entry.Listener</entry-listener>
      </entry-listeners>
    </map>
    

    【讨论】:

    • 求你的帮助,它按你说的那样工作。但是,我并不完全理解为什么要创建另一个 Hz 实例。它在默认实例下工作得非常好,无需为instance-name 指定init-param。我只是将entry-listener 添加到hazelcast-default.xml。很快将添加另一个答案,具体说明如何完成。
    【解决方案2】:

    正如 Neil Stevenson 所提到的,Hazelcast 实例应该使用 EntryListener 预配置为 my-sessions 映射。在我的情况下使用会话复制过滤器,我添加了

    <map name="my-sessions">
      <entry-listeners>
        <entry-listener local="true" include-value="true">path.to.NewOrderSessionListener</entry-listener>
        </entry-listeners>
    </map>
    

    hazelcast.xml(位于right place)。

    EntryRemovedListener&lt;String, SessionState&gt; 的实现来监听 Hz 会话删除事件将是这样的

    public class NewOrderSessionListener implements EntryRemovedListener<String, SessionState> {
      @Override
      public void entryRemoved(EntryEvent<String, SessionState> event) {
        SessionState state = event.getOldValue();
        Map<String, Data> map = state.getAttributes();
        Data orderData = map.get("order");
        if (orderData != null) {
          // Backup all data processed by order
        }
    

    实际上,Hazelcast provides 是任何事件的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-26
      • 2023-03-16
      • 1970-01-01
      相关资源
      最近更新 更多