具有Hazelcast会话复制的自定义会话侦听器

时间:2016-07-22 15:38:50

标签: java session listener hazelcast session-replication

我为会话复制配置了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>

在我的Web应用程序中,用户可以使Order在会话中持续存在直到完成。如果订单未完成且会话被销毁(用户注销或会话已过期),我想备份该订单处理的所有数据。

没有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会创建并销毁它自己的会话,而我不能(或不知道如何)收听此会话事件。

是否可以保持两个会话同步或为Hz会话实现自己的侦听器?

2 个答案:

答案 0 :(得分: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>

答案 1 :(得分:0)

正如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<String, SessionState>监听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是任何事件的解决方案。