3. HttpSession 集成
Spring Session 提供与javax.servlet.http.HttpSession
.这意味着开发人员
可以将HttpSession
实现,其实现由 Spring Session 支持。
Spring Session 允许插入多个不同的数据存储提供者(例如 Apache Geode)
为了管理HttpSession
州。
3.1. 为什么选择 Spring Session 和 HttpSession?
我们已经提到 Spring Session 提供了与HttpSession
,但有什么好处
我们能摆脱困境吗?
-
HttpSession - 启用
HttpSession
要聚类(即复制 实现高可用性),而无需绑定到特定于应用程序容器的解决方案。 -
REST API - 允许在协议标头中提供会话 ID 以使用 RESTful API。
-
WebSocket - 提供保留
HttpSession
在接收 WebSocket 消息时处于活动状态。 -
WebSession - 允许替换 Spring WebFlux 的
WebSession
以应用程序容器中立的方式。
3.2. 使用 Apache Geode 进行 HttpSession 管理
当 Apache Geode 与 Spring Session 一起使用时,Web 应用程序的javax.servlet.http.HttpSession
可以替换为 Apache Geode 管理的集群实现
并使用 Spring Session 的 API 方便地访问。
使用 Apache Geode 管理会话状态的两种最常见的拓扑包括:
此外,Apache Geode 支持使用 WAN 拓扑进行站点到站点复制。 配置和使用 Apache Geode 的 WAN 功能的能力独立于 Spring Session, 并且超出了本文档的范围。
有关使用 Spring Data for Apache Geode 配置 Apache Geode WAN 功能的更多详细信息 可以在这里找到。
3.2.1. Apache Geode 客户端-服务器
客户端-服务器拓扑可能是 在 Spring Session 中使用 Apache Geode 作为提供程序时,用户中最常见的配置选择,因为 Apache Geode 服务器具有与应用程序相比显着不同且独特的 JVM 堆要求。 使用客户端-服务器拓扑使应用程序能够独立管理(例如复制)应用程序状态 来自其他应用程序流程。
在客户端-服务器拓扑中,使用 Spring Session 的应用程序将打开 1 个或多个与远程集群的连接
的 Apache Geode 服务器将管理对所有HttpSession
州。
您可以使用以下任一方式配置客户端-服务器拓扑:
Apache Geode 客户端-服务器基于 Java 的配置
本节介绍如何配置 Apache Geode 的客户端-服务器拓扑以管理HttpSession
州
使用基于 Java 的配置。
HttpSession with Apache Geode (Client-Server) 提供了一个工作示例,演示了如何
将 Spring Session 与 Apache Geode 集成以管理HttpSession 使用 Java 配置的状态。你可以阅读
通过下面的基本集成步骤进行作,但鼓励您按照详细的“HttpSession”进行作
与您自己的应用程序集成时使用 Apache Geode (Client-Server) 指南。 |
Spring Java 配置
添加所需的依赖项和存储库声明后,我们可以创建 Spring 配置。
Spring 配置负责创建 ServletFilter
将HttpSession
具有由 Spring Session 和 Apache Geode 支持的实现。
客户端配置
添加以下 Spring 配置:
@ClientCacheApplication(name = "SpringSessionDataGeodeJavaConfigSampleClient", logLevel = "error",
readTimeout = 15000, retryAttempts = 1, subscriptionEnabled = true) (1)
@EnableGemFireHttpSession(poolName = "DEFAULT") (2)
public class ClientConfig extends ClientServerIntegrationTestsSupport {
@Bean
ClientCacheConfigurer gemfireServerReadyConfigurer( (3)
@Value("${spring.data.gemfire.cache.server.port:40404}") int cacheServerPort) {
return (beanName, clientCacheFactoryBean) -> waitForServerToStart("localhost", cacheServerPort);
}
}
1 | 首先,我们通过注释我们的ClientConfig 类
跟@ClientCacheApplication .此外,我们还调整了一些基本的“默认”Pool 设置(例如readTimeout ). |
2 | @EnableGemFireHttpSession 创建一个名为springSessionRepositoryFilter 实现javax.servlet.Filter .过滤器取代了HttpSession 与 Spring Session 提供的实现
并由 Apache Geode 提供支持。此外,配置还将创建必要的客户端Region (默认情况下,“ClusteredSpringSessions”,这是一个PROXY Region ) 对应于同一服务器端Region 按名称。所有会话状态都通过以下方式从客户端发送到服务器Region 数据访问作。
客户端Region 使用“默认”Pool . |
3 | 然后,我们等待确保 Apache Geode 服务器已启动并运行,然后再继续。这只是真正有用的 用于自动化(集成)测试目的。 |
在典型的 Apache Geode 生产部署中,集群可能包括数百或数千个 的服务器(又称数据节点),客户端更常见的是连接到 1 个或多个运行的 Apache Geode 定位器 在同一集群中。定位器将有关集群中可用服务器的元数据传递给客户端,即单个 服务器负载以及哪些服务器具有客户端感兴趣的数据,这对于直接、 单跳数据访问和延迟敏感型应用程序。有关客户端/服务器部署的更多详细信息,请参阅 Apache Geode 用户指南。 |
有关配置 Spring Data Geode 的更多信息,请参阅参考指南。 |
这@EnableGemFireHttpSession
注释使开发人员能够配置 Spring Session 的某些方面
以及使用以下属性的开箱即用的 Apache Geode:
-
clientRegionShortcut
- 使用 ClientRegionShortcut 在客户端上指定 Apache Geode 数据管理策略(默认值为PROXY
).此属性仅在配置客户端时使用Region
. -
indexableSessionAttributes
- 按名称标识应为查询目的编制索引的会话属性。 只有按名称显式标识的会话属性才会被编制索引。 -
maxInactiveIntervalInSeconds
- 控制 HttpSession 空闲超时过期(默认为 30 分钟)。 -
poolName
- 专用 Apache Geode 的名称Pool
用于将客户端连接到服务器集群。 仅当应用程序是缓存客户端时,才使用此属性。默认为gemfirePool
. -
regionName
- 指定 Apache Geode 的名称Region
用于存储和管理HttpSession
州 (默认为“ClusteredSpringSessions”)。 -
serverRegionShortcut
- 使用 RegionShortcut 指定服务器上的 Apache Geode 数据管理策略(默认值为PARTITION
).此属性仅在配置服务器时使用Regions
, 或者当采用 P2P 拓扑时。
重要的是要记住,Apache Geode 客户端Region 名称必须与服务器匹配Region 如果客户端Region 是一个PROXY 或CACHING_PROXY .客户端和服务器Region 名字
如果客户端Region 用于存储会话状态LOCAL .但是,请记住
该会话状态将不会传播到服务器,并且您失去了使用 Apache Geode 的所有好处
在分布式
复制的方式。 |
服务器配置
到目前为止,我们只涵盖了等式的一侧。我们还需要一个 Apache Geode 服务器供缓存客户端与之通信 并将会话状态发送到服务器进行管理。
在此示例中,我们将使用以下 Java 配置来配置和运行 Apache Geode 服务器:
@CacheServerApplication(name = "SpringSessionDataGeodeJavaConfigSampleServer", logLevel = "error") (1)
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 30) (2)
public class GemFireServer {
@SuppressWarnings("resource")
public static void main(String[] args) {
new AnnotationConfigApplicationContext(GemFireServer.class).registerShutdownHook();
}
}
1 | 首先,我们使用@CacheServerApplication 注释,以简化对等缓存实例的创建
包含CacheServer 用于连接缓存客户端。 |
2 | (可选)然后,GemFireServer 类的注释是@EnableGemFireHttpSession 创建必要的
服务器端Region (默认情况下,“ClusteredSpringSessions”)用于存储HttpSession 州。这一步是
可选,自会话Region 可以手动创建,也许可以使用外部方式。
用@EnableGemFireHttpSession 方便快捷。 |
Apache Geode 客户端-服务器基于 XML 的配置
本节介绍如何配置 Apache Geode 的客户端-服务器拓扑以管理HttpSession
州
使用基于 XML 的配置。
使用 XML 的 Apache Geode (Client-Server) 的 HttpSession 提供了一个工作示例
演示如何将 Spring Session 与 Apache Geode 集成以管理HttpSession 使用 XML 的状态
配置。您可以阅读下面的集成基本步骤,但我们鼓励您按照以下步骤作
在与 Apache Geode (Client-Server) 集成时使用 XML 指南的详细“HttpSession” 中
您自己的应用程序。 |
Spring XML 配置
添加所需的依赖项和存储库声明后,我们可以创建 Spring 配置。
Spring 配置负责创建一个Servlet
Filter
将javax.servlet.http.HttpSession
具有由 Spring Session 和 Apache Geode 支持的实现。
客户端配置
添加以下 Spring 配置:
<context:annotation-config/>
<context:property-placeholder/>
<bean class="sample.client.ClientServerReadyBeanPostProcessor"/>
(1)
<util:properties id="gemfireProperties">
<prop key="log-level">${spring.data.gemfire.cache.log-level:error}</prop>
</util:properties>
(2)
<gfe:client-cache properties-ref="gemfireProperties" pool-name="gemfirePool"/>
(3)
<gfe:pool read-timeout="15000" retry-attempts="1" subscription-enabled="true">
<gfe:server host="localhost" port="${spring.data.gemfire.cache.server.port:40404}"/>
</gfe:pool>
(4)
<bean class="org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration"
p:poolName="DEFAULT"/>
1 | (可选)首先,我们可以包含一个Properties bean 来配置 Apache Geode 的某些方面ClientCache 使用 Pivotal GemFire 属性。在这种情况下,我们只是
使用特定于应用程序的系统属性设置 Apache Geode 的“日志级别”,默认为“警告”
如果未指定。 |
2 | 我们必须创建一个 Apache Geode 的实例ClientCache .我们用我们的gemfireProperties . |
3 | 然后我们配置一个Pool 在我们的客户端/服务器拓扑中与 Apache Geode 服务器通信的连接数。
在我们的配置中,我们对超时、连接数等使用合理的设置。此外,我们的Pool 已配置为直接连接到服务器(使用嵌套的gfe:server 元素)。 |
4 | 最后,一个GemFireHttpSessionConfiguration bean 被注册以启用 Spring Session 功能。 |
在典型的 Apache Geode 生产部署中,集群可能包括数百或数千个 的服务器(又称数据节点),客户端更常见的是连接到 1 个或多个运行的 Apache Geode 定位器 在同一集群中。定位器将有关集群中可用服务器的元数据传递给客户端,即单个 服务器负载以及哪些服务器具有客户端感兴趣的数据,这对于直接、 单跳数据访问和延迟敏感型应用程序。有关客户端/服务器部署的更多详细信息,请参阅 Apache Geode 用户指南。 |
有关为 Apache Geode 配置 Spring Data 的更多信息,请参阅参考指南。 |
服务器配置
到目前为止,我们只涵盖了等式的一侧。我们还需要一个 Apache Geode 服务器供缓存客户端与之通信 并将会话状态发送到服务器进行管理。
在此示例中,我们将使用以下 XML 配置来启动 Apache Geode 服务器:
<context:annotation-config/>
<context:property-placeholder/>
(1)
<util:properties id="gemfireProperties">
<prop key="name">SpringSessionDataGeodeSampleXmlServer</prop>
<prop key="log-level">${spring.data.gemfire.cache.log-level:error}</prop>
</util:properties>
(2)
<gfe:cache properties-ref="gemfireProperties"/>
(3)
<gfe:cache-server port="${spring.data.gemfire.cache.server.port:40404}"/>
(4)
<bean class="org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration"
p:maxInactiveIntervalInSeconds="30"/>
1 | (可选)首先,我们可以包含一个Properties bean 来配置 Apache Geode 对等方的某些方面Cache 使用 Pivotal GemFire 属性。在这种情况下,我们只是
使用特定于应用程序的系统属性设置 Apache Geode 的“日志级别”,默认为“警告”
如果未指定。 |
2 | 我们必须配置一个 Apache Geode 对等方Cache 实例。我们使用 Apache Geode 属性初始化它。 |
3 | 接下来,我们定义一个CacheServer 具有合理的配置bind-address 和port 由我们的缓存客户端使用
应用程序连接到服务器并发送会话状态。 |
4 | 最后,我们启用了我们在客户端 XML 配置中声明的相同 Spring Session 功能
通过注册GemFireHttpSessionConfiguration ,除了我们设置了会话过期超时
到 30 秒。我们稍后会解释这意味着什么。 |
Apache Geode 服务器通过以下内容进行引导:
@Configuration (1)
@ImportResource("META-INF/spring/session-server.xml") (2)
public class GemFireServer {
public static void main(String[] args) {
new AnnotationConfigApplicationContext(GemFireServer.class).registerShutdownHook();
}
}
而不是使用main 方法,您可以考虑使用 Spring Boot 代替。 |
1 | 这@Configuration 注释将此 Java 类指定为 Spring 配置元数据的源,使用
7.9. 基于 Commentation 的容器配置[Spring 的 Commentation 配置支持]。 |
2 | 首先,配置来自META-INF/spring/session-server.xml 文件。 |
XML Servlet 容器初始化
我们的 Spring XML 配置创建了一个名为springSessionRepositoryFilter
实现javax.servlet.Filter
接口。这springSessionRepositoryFilter
bean 负责替换
这javax.servlet.http.HttpSession
使用 Spring Session 和 Apache Geode 提供的自定义实现。
为了我们的Filter
为了发挥它的魔力,我们需要指示 Spring 加载
我们session-client.xml
配置文件。
我们通过以下配置来执行此作:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/session-client.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
ContextLoaderListener 读取contextConfigLocation
context 参数值,并获取我们的session-client.xml配置文件。
最后,我们需要确保我们的 Servlet 容器(即 Tomcat)使用springSessionRepositoryFilter
对于每个请求。
以下代码段为我们执行了最后一步:
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
DelegatingFilterProxy 将查找名称为springSessionRepositoryFilter
并将其转换为Filter
.对于每个 HTTP 请求,
这DelegatingFilterProxy
被调用,它委托给springSessionRepositoryFilter
.
3.2.2. Apache Geode 点对点 (P2P)
一种不太常见的方法是将 Spring Session 应用程序配置为 Apache Geode 集群中的对等成员 使用点对点 (P2P) 拓扑。 在此配置中,Spring Session 应用程序将是 Apache Geode 中的实际服务器(或数据节点) 集群,而不仅仅是像以前那样的缓存客户端。
这种方法的一个优点是应用程序接近应用程序的状态(即其数据),
特别是HttpSession
州。然而,还有其他有效的方法可以实现类似的目标
数据相关计算,例如使用 Apache Geode 的函数执行。
Apache Geode 的任何其他功能都可以在以下情况下使用
Apache Geode 在 Spring Session 中充当提供者。
P2P 拓扑对于测试目的以及更小、更集中和独立的应用非常有用, 例如微服务架构中的那些,并且肯定会改进您的应用程序的感知 延迟和吞吐量需求。
您可以使用以下任一方式配置对等 (P2P) 拓扑:
Apache Geode 点对点 (P2P) 基于 Java 的配置
本节介绍如何配置 Apache Geode 的点对点 (P2P) 拓扑以管理HttpSession
州
使用基于 Java 的配置。
HttpSession with Apache Geode (P2P) 提供了一个工作示例,演示了如何
将 Spring Session 与 Apache Geode 集成以管理HttpSession 使用 Java 配置的状态。你可以阅读
通过下面的基本集成步骤进行作,但鼓励您按照详细的“HttpSession”进行作
与您自己的应用程序集成时使用 Apache Geode (P2P) 指南。 |
Spring Java 配置
添加所需的依赖项和存储库声明后,我们可以创建 Spring 配置。
Spring 配置负责创建一个Servlet
Filter
将javax.servlet.http.HttpSession
具有由 Spring Session 和 Apache Geode 支持的实现。
添加以下 Spring 配置:
@PeerCacheApplication(name = "SpringSessionDataGeodeJavaConfigP2pSample", logLevel = "error") (1)
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 30) (2)
public class Config {
}
1 | 首先,我们使用@PeerCacheApplication 注释以简化对等缓存实例的创建。 |
2 | 然后,Config 类的注释是@EnableGemFireHttpSession 创建必要的服务器端Region (默认情况下,“ClusteredSpringSessions”)用于存储HttpSession 州。 |
有关为 Apache Geode 配置 Spring Data 的更多信息,请参阅参考指南。 |
这@EnableGemFireHttpSession
注释使开发人员能够配置 Spring Session 的某些方面
以及使用以下属性的开箱即用的 Apache Geode:
-
clientRegionShortcut
- 使用 ClientRegionShortcut 在客户端上指定 Apache Geode 数据管理策略(默认值为PROXY
).此属性仅在配置客户端时使用Region
. -
indexableSessionAttributes
- 按名称标识应为查询目的编制索引的会话属性。 只有按名称显式标识的会话属性才会被编制索引。 -
maxInactiveIntervalInSeconds
- 控制 HttpSession 空闲超时过期(默认为 30 分钟)。 -
poolName
- 专用 Apache Geode 的名称Pool
用于将客户端连接到服务器集群。 仅当应用程序是缓存客户端时,才使用此属性。默认为gemfirePool
. -
regionName
- 指定 Apache Geode 的名称Region
用于存储和管理HttpSession
州 (默认为“ClusteredSpringSessions”)。 -
serverRegionShortcut
- 使用 RegionShortcut 指定服务器上的 Apache Geode 数据管理策略(默认值为PARTITION
).此属性仅在配置服务器时使用Regions
, 或者当采用 P2P 拓扑时。
Java Servlet 容器初始化
我们的<<[httpsession-spring-java-configuration-p2p,Spring Java Configuration>>创建了一个名为springSessionRepositoryFilter
实现javax.servlet.Filter
.这springSessionRepositoryFilter
豆
负责替换javax.servlet.http.HttpSession
使用由
Spring Session 和 Apache Geode。
为了我们的Filter
为了发挥它的魔力,Spring 需要加载我们的Config
类。我们还需要确保我们的
Servlet 容器(即 Tomcat)使用我们的springSessionRepositoryFilter
在每个 HTTP 请求上。
幸运的是,Spring Session 提供了一个名为AbstractHttpSessionApplicationInitializer
使两者兼而有之
步骤非常简单。
您可以在下面找到一个示例:
public class Initializer extends AbstractHttpSessionApplicationInitializer { (1)
public Initializer() {
super(Config.class); (2)
}
}
我们的类的名称 (Initializer )无关紧要。重要的是,我们扩展AbstractHttpSessionApplicationInitializer . |
1 | 第一步是延长AbstractHttpSessionApplicationInitializer .这确保了名为springSessionRepositoryFilter 在我们的 Servlet 容器中注册,并在每个 HTTP 请求中使用。 |
2 | AbstractHttpSessionApplicationInitializer 还提供了一种机制,可以轻松允许 Spring 加载
我们Config 类。 |
Apache Geode 点对点 (P2P) 基于 XML 的配置
本节介绍如何配置 Apache Geode 的点对点 (P2P) 拓扑以管理HttpSession
州
使用基于 XML 的配置。
使用 XML 的 HttpSession with Apache Geode (P2P) 提供了一个工作示例,演示了如何
将 Spring Session 与 Apache Geode 集成以管理HttpSession 状态。你可以阅读
通过下面的基本集成步骤进行作,但鼓励您按照详细的“HttpSession”进行作
与您自己的应用程序集成时使用 XML Guide 使用 Apache Geode (P2P)。 |
Spring XML 配置
添加所需的依赖项和存储库声明后,我们可以创建 Spring 配置。
Spring 配置负责创建一个Servlet
Filter
将javax.servlet.http.HttpSession
具有由 Spring Session 和 Apache Geode 支持的实现。
添加以下 Spring 配置:
<context:annotation-config/>
<context:property-placeholder/>
(1)
<util:properties id="gemfireProperties">
<prop key="name">SpringSessionDataGeodeXmlP2pSample</prop>
<prop key="log-level">${spring.data.gemfire.cache.log-level:error}</prop>
</util:properties>
(2)
<gfe:cache properties-ref="gemfireProperties"/>
(3)
<bean class="org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration"
p:maxInactiveIntervalInSeconds="30"/>
1 | (可选)首先,我们可以包含一个Properties bean 来配置 Apache Geode 对等方的某些方面Cache 使用 VMware Tanzu GemFire 属性。在这种情况下,我们只是
使用特定于应用程序的系统属性设置 Apache Geode 的“日志级别”,默认为“警告”
如果未指定。 |
2 | 我们必须配置一个 Apache Geode 对等方Cache 实例。我们使用 Apache Geode 属性初始化它。 |
3 | 最后,我们通过注册一个实例来启用 Spring Session 功能GemFireHttpSessionConfiguration . |
有关为 Apache Geode 配置 Spring Data 的更多信息,请参阅参考指南。 |
XML Servlet 容器初始化
Spring XML 配置创建了一个名为springSessionRepositoryFilter
实现javax.servlet.Filter
.这springSessionRepositoryFilter
bean 负责将javax.servlet.http.HttpSession
使用由 Spring Session 和 Apache Geode 支持的自定义实现。
为了我们的Filter
为了发挥它的魔力,我们需要指示 Spring 加载session.xml
配置文件。
我们通过以下配置来执行此作:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
ContextLoaderListener 读取contextConfigLocation
context 参数值,并获取我们的session.xml配置文件。
最后,我们需要确保我们的 Servlet 容器(即 Tomcat)使用springSessionRepositoryFilter
对于每个 HTTP 请求。
以下代码段为我们执行了最后一步:
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
DelegatingFilterProxy 将查找名称为springSessionRepositoryFilter
并将其转换为Filter
.对于每个 HTTP 请求
这DelegatingFilterProxy
被调用时,将委托给springSessionRepositoryFilter
.
3.3. 配置HttpSession
使用带有属性的 Apache Geode 进行管理
虽然@EnableGemFireHttpSession
注释易于使用,在开始使用 Spring Session 时很方便
和 Apache Geode 在你的 Spring Boot 应用程序中,你在从一个应用程序迁移时很快就会遇到限制
环境,例如,从 DEV 到 QA 再到 PROD 时。
使用@EnableGemFireHttpSession
注释属性,则无法从一个
环境到另一个。因此,Spring Session for Apache Geode 引入了众所周知的、记录在案的属性
对于所有@EnableGemFireHttpSession
注释属性。
属性 | 注释属性 | 描述 | 默认值 |
---|---|---|---|
spring.session.data.gemfire.cache.client.pool.name |
|
存储/访问会话状态的客户端区域使用的专用池的名称。 |
宝石火池 |
spring.session.data.gemfire.cache.client.region.shortcut |
|
在客户端-服务器拓扑中设置客户端区域数据管理策略。 |
客户端区域快捷方式.PROXY |
spring.session.data.gemfire.cache.server.region.shortcut |
|
在点对点 (P2P) 拓扑中设置对等区域数据管理策略。 |
区域快捷方式.PARTITION |
spring.session.data.gemfire.session.attributes.indexable |
|
要在会话区域中编制索引的会话属性的逗号分隔列表。 |
|
spring.session.data.gemfire.session.expiration.bean-name |
|
Spring 容器中实现过期策略的 bean 的名称 |
|
spring.session.data.gemfire.session.expiration.max-非活动间隔秒 |
|
会话过期超时(以秒为单位) |
1800 |
spring.session.data.gemfire.session.region.name |
|
用于存储和访问会话状态的客户端或对等区域的名称。 |
集群 SpringSessions |
spring.session.data.gemfire.session.serializer.bean-name |
|
实现序列化策略的 Spring 容器中 bean 的名称 |
SessionPdx序列化器 |
所有属性都记录在@EnableGemFireHttpSession 注释属性 Javadoc 也是如此。 |
因此,在使用 Apache Geode 时调整 Spring Session 的配置非常简单 作为提供程序,如下所示:
@SpringBootApplication
@ClientCacheApplication
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 900)
class MySpringSessionApplication {
// ...
}
然后,在application.properties
:
#application.properties
spring.session.data.gemfire.cache.client.region.shortcut=CACHING_PROXY
spring.session.data.gemfire.session.expiration.max-inactive-internval-seconds=3600
显式定义的任何属性都会覆盖相应的@EnableGemFireHttpSession
annotation 属性。
在上面的示例中,即使EnableGemFireHttpSession
注解maxInactiveIntervalInSeconds
属性
被设置为900
秒或 15 分钟,相应的属性属性
(即spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds
)
覆盖该值并将到期时间设置为3600
秒,或 60 分钟。
请记住,属性在运行时覆盖注释属性值。 |
3.3.1. 属性的属性
您甚至可以更复杂地使用其他属性配置您的属性,如下所示:
#application.properties
spring.session.data.gemfire.session.expiration.max-inactive-internval-seconds=${app.geode.region.expiration.timeout:3600}
此外,您可以使用 Spring 配置文件根据环境改变过期超时(或其他属性) 或您的申请,或您的申请要求规定的任何标准。
属性占位符和嵌套是核心 Spring Framework 的一个功能,而不是特定于 Spring Session 或 Apache Geode 的 Spring Session。 |
3.4. 配置HttpSession
使用 Apache Geode 和配置器的管理
除了属性之外,Spring Session for Apache Geode 还允许您调整
使用 Apache Geode 的 Spring 会话SpringSessionGemFireConfigurer
接口。该接口定义了一个
包含每个默认方法的合约@EnableGemFireHttpSession
可以覆盖的注释属性
以调整配置。
这SpringSessionGemFireConfigurer
在概念上类似于 Spring Web MVC 的 Configurer 接口
(例如o.s.web.servlet.config.annotation.WebMvcConfigurer
),它调整 Web 应用程序的各个方面
启动时的配置,例如配置异步支持。声明和实现Configurer
是它使您可以对配置进行编程控制。这在您需要的情况下很有用
轻松表达复杂的条件逻辑,用于确定是否应应用配置。
例如,要像之前一样调整客户端区域数据管理策略和会话过期超时, 使用以下内容:
@Configuration
class MySpringSessionConfiguration {
@Bean
SpringSessionGemFireConfigurer exampleSpringSessionGemFireConfigurer() {
return new SpringSessionGemFireConfigurer() {
@Override
public ClientRegionShortcut getClientRegionShortcut() {
return ClientRegionShortcut.CACHING_PROXY;
}
@Override
public int getMaxInactiveIntervalInSeconds() {
return 3600;
}
};
}
}
当然,这个例子不是很有创意。您当然可以使用更复杂的逻辑来确定 每个配置属性的配置。
您可以随心所欲地复杂,例如通过实现Configurer
就其他属性而言
使用 Spring 的@Value
注释,如下所示:
@Configuration
class MySpringSessionConfiguration {
@Bean
@Primary
@Profile("production")
SpringSessionGemFireConfigurer exampleSpringSessionGemFireConfigurer(
@Value("${app.geode.region.data-management-policy:CACHING_PROXY}") ClientRegionShortcut shortcut,
@Value("${app.geode.region.expiration.timeout:3600}") int timeout) {
return new SpringSessionGemFireConfigurer() {
@Override
public ClientRegionShortcut getClientRegionShortcut() {
return shortcut;
}
@Override
public int getMaxInactiveIntervalInSeconds() {
return timeout;
}
};
}
}
Spring Boot 将解析@Value 注释属性占位符值或 SpEL 表达式。
但是,如果您不使用 Spring Boot,则必须显式注册静态PropertySourcesPlaceholderConfigurer bean 定义。 |
但是,您只能声明 1SpringSessionGemFireConfigurer
bean 一次在 Spring 容器中,除非
您还在使用 Spring 配置文件或标记了多个配置文件中的 1 个SpringSessionGemFireConfigurer
豆作为主要
通过使用 Spring 的@Primary
上下文注释。
3.4.1. 配置优先级
一个SpringSessionGemFireConfigurer
优先于@EnableGemFireHttpSession
注释属性
或任何众所周知且有文档记录的 Apache Geode 属性的 Spring Session
(例如spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds
)
在 Spring Boot 中定义application.properties.
如果 Web 应用程序采用了 1 种以上的配置方法,则将适用以下优先级:
-
SpringSessionGemFireConfigurer
“实现”的回调方法 -
记录了 Apache Geode 属性的 Spring 会话(请参阅相应的
@EnableGemFireHttpSession
注解 属性 Javadoc;例如spring.session.data.gemfire.session.region.name
) -
@EnableGemFireHttpSession
注释属性
Spring Session for Apache Geode 小心翼翼地只应用来自SpringSessionGemFireConfigurer
豆
在 Spring 容器中为您实际实现的方法声明。
在上面的示例中,由于您没有实现getRegionName()
方法,Apache Geode 区域的名称
管理HttpSession
状态将不由配置器确定。
示例
例如,考虑以下配置:
@ClientCacheApplication
@EnableGemFireHttpSession(
maxInactiveIntervalInSeconds = 3600,
poolName = "DEFAULT"
)
class MySpringSessionConfiguration {
@Bean
SpringSessionGemFireConfigurer sessionExpirationTimeoutConfigurer() {
return new SpringSessionGemFireConfigurer() {
@Override
public int getMaxInactiveIntervalInSeconds() {
return 300;
}
};
}
}
此外,请考虑以下 Spring Bootapplication.properties
文件:
-
弹簧靴
application.properties
spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds = 900 spring.session.data.gemfire.session.region.name = Sessions
会话过期超时将为 300 秒或 5 分钟,重写这两个属性
(即spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds
) 的 900 秒,或 15 分钟,
以及显式@EnableGemFireHttpSession.maxInactiveIntervalInSeconds
注释属性值
3600 秒,或 1 小时。
由于“sessionExpirationTimeoutConfigurer”Bean 不会覆盖getRegionName()
方法,会话区域
名称将由属性(即spring.session.data.gemfire.session.region.name
),设置为“会话”,
它覆盖了隐式的@EnableGemFireHttpSession.regionName
annotation 属性的默认值为
“ClusteredSpringSessions”。
这@EnableGemFireHttpSession.poolName
注释属性的值“DEFAULT”将确定池的名称
在客户端和服务器之间发送区域作以管理服务器上的会话状态时使用,因为两者都不是
相应的属性(即 spring.session.data.gemfire.cache.client.pool.name')被设置,也没有
这SpringSessionGemFireConfigurer.getPoolName()
方法被“sessionExpirationTimeoutConfigurer”bean覆盖。
最后,用于管理会话状态的客户端区域将具有PROXY
,默认值
值@EnableGemFireHttpSession.clientRegionShortcut
annotation 属性,该属性未显式设置,也
是相应的属性(即spring.session.data.gemfire.cache.client.region.shortcut
) 来表示此属性。
而且,由于SpringSessionConfigurer.getClientRegionShortcut()
方法未被覆盖,则使用默认值。
3.5. Apache Geode 过期
默认情况下,Apache Geode 配置了区域条目、空闲超时 (TTI) 过期策略,使用 过期超时为 30 分钟,并将 INVALIDATE entry 作为作。这意味着当用户的会话保持非活动状态时 (即空闲)超过 30 分钟,会话将过期并失效,用户必须开始新的会话 以便继续使用该应用程序。
但是,如果你对会话状态管理和过期有特定于应用程序的要求,并且使用 默认的空闲超时 (TTI) 过期策略不足以满足您的用例 (UC)?
现在,Spring Session for Apache Geode 支持特定于应用程序的自定义过期策略。作为应用程序 developer,您可以指定自定义规则来管理由 Spring Session 管理的会话的过期时间,并由 阿帕奇晶洞。
Spring Session for Apache Geode 提供了新的SessionExpirationPolicy
策略界面。
@FunctionalInterface
interface SessionExpirationPolicy {
// determine timeout for expiration of individual Session
Optional<Duration> determineExpirationTimeout(Session session);
// define the action taken on expiration
default ExpirationAction getExpirationAction() {
return ExpirationAction.INVALIDATE;
}
enum ExpirationAction {
DESTROY,
INVALIDATE
}
}
实现此接口以指定应用程序所需的会话过期策略,然后注册 实例作为 Spring 应用程序上下文中的 bean。
使用@EnableGemFireHttpSession
注解sessionExpirationPolicyBeanName
属性来配置
这SessionExpirationPolicy
bean 实现会话过期的自定义应用程序策略和规则。
例如:
SessionExpirationPolicy
class MySessionExpirationPolicy implements SessionExpirationPolicy {
public Duration determineExpirationTimeout(Session session) {
// return a java.time.Duration specifying the length of time until the Session should expire
}
}
然后,在应用程序类中,简单地声明以下内容:
SessionExpirationPolicy
配置@SpringBootApplication
@EnableGemFireHttpSession(
maxInactiveIntervalInSeconds = 600,
sessionExpirationPolicyBeanName = "expirationPolicy"
)
class MySpringSessionApplication {
@Bean
SessionExpirationPolicy expirationPolicy() {
return new MySessionExpirationPolicy();
}
}
或者,的名称SessionExpirationPolicy bean 可以使用spring.session.data.gemfire.session.expiration.bean-name 属性,或通过声明SpringSessionGemFireConfigurer bean 并覆盖getSessionExpirationPolicyBeanName() 方法。 |
您只需实现determineExpirationTimeout(:Session):Optional<Duration>
方法
它封装了确定会话何时到期的规则。会话的过期超时
表示为Optional
之java.time.Duration
,指定会话过期之前的时间长度。
这determineExpirationTimeout
方法可以是特定于会话的,并且可能会随着每次调用而更改。
或者,您可以实现getAction
方法来指定会话到期时采取的作。默认情况下,
区域条目(即会话)无效。另一种选择是在到期时销毁区域条目,
这会删除键(会话 ID)和值(会话)。Invalidate 仅删除该值。
在引擎盖下,SessionExpirationPolicy 被改编到 Apache Geode 的实例中CustomExpiry 接口。
本届Spring SessionCustomExpiry 然后,对象设置为会话区域的自定义条目空闲超时过期策略。 |
在到期确定期间,CustomExpiry.getExpiry(:Region.Entry<String, Session>):ExpirationAttributes 每次运行过期线程时,都会为区域中的每个条目(即会话)调用方法,这反过来又会调用
调用我们的SessionExpirationPolicy.determineExpirationTimout(:Session):Optional<Duration> 方法。
返回的java.time.Duration 转换为秒,并用作ExpirationAttributes 从CustomExpiry.getExpiry(..) 方法调用。 |
Apache Geode 的过期线程每秒运行一次,评估区域中的每个条目(即会话)
以确定条目是否已过期。您可以使用gemfire.EXPIRY_THREADS 财产。有关更多详细信息,请参阅 Apache Geode 文档。 |
3.5.1. 过期超时配置
如果要为自定义设置过期超时SessionExpirationPolicy
上
这@EnableGemFireHttpSession
注解maxInactiveIntervalInSeconds
属性,或者,
相应的spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds
财产
然后您的自定义SessionExpirationPolicy
实现也可以实现SessionExpirationTimeoutAware
接口。
这SessionExpirationTimeoutAware
接口定义为:
interface SessionExpirationTimeoutAware {
void setExpirationTimeout(Duration expirationTimeout);
}
当您的自定义SessionExpirationPolicy
实现还实现了SessionExpirationTimeoutAware
接口
那么 Spring Session for Apache Geode 将为您的实现提供来自@EnableGemFireHttpSession
注解maxInactiveIntervalInSeconds
属性,或从spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds
属性(如果设置)或从任何SpringSessionGemFireConfigurer
bean 在 Spring 应用程序上下文中声明,作为java.time.Duration
.
如果使用1个以上的配置选项,则以以下顺序为准:
-
SpringSessionGemFireConfigurer.getMaxInactiveIntervalInSeconds()
-
spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds
属性 -
@EnableGemFireHttpSession
注解maxInactiveIntervalInSeconds
属性
3.5.2. 固定超时过期
为了更加方便,Spring Session for Apache Geode 提供了SessionExpirationPolicy
用于固定持续时间过期的接口(或核心 Spring Session Issue #922 中描述的“绝对会话超时”)。
在某些情况下,例如出于安全原因,可能需要在固定的 Session 后使用户的会话过期 时间长度(例如每小时),无论用户的会话是否仍然处于活动状态。
Spring Session for Apache Geode 提供了FixedTimeoutSessionExpirationPolicy
开箱即用的实施
适用于此确切的用例 (UC)。除了处理固定持续时间到期外,还要谨慎地考虑
并应用默认的空闲过期超时。
例如,考虑这样一个场景:用户登录,开始一个会话,活动 10 分钟,然后离开 让会话闲置。如果固定持续时间过期超时设置为 60 分钟,但空闲过期 timeout 仅设置为 30 分钟,并且用户不返回,则 Session 应该在 40 分钟后过期 而不是 60 分钟,当固定持续时间到期时。
相反,如果用户忙了整整 40 分钟,从而保持会话处于活动状态,从而避免了 30 分钟 空闲过期超时,然后离开,那么我们的固定持续时间过期超时应该启动并过期 用户的会话权限为 60 分钟,即使用户的空闲过期超时要到 70 分钟才会发生 在(40 分钟(活动)+ 30 分钟(空闲)= 70 分钟)。
嗯,这正是FixedTimeoutSessionExpirationPolicy
确实。
要配置FixedTimeoutSessionExpirationPolicy
,请执行以下作:
@SpringBootApplication
@EnableGemFireHttpSession(sessionExpirationPolicyBeanName = "fixedTimeoutExpirationPolicy")
class MySpringSessionApplication {
@Bean
SessionExpirationPolicy fixedTimeoutExpirationPolicy() {
return new FixedTimeoutSessionExpirationPolicy(Duration.ofMinutes(60L));
}
}
在上面的示例中,FixedTimeoutSessionExpirationPolicy
在 Spring 应用程序上下文中被声明为 bean
并以 60 分钟的固定持续时间过期超时进行初始化。因此,用户会话将
在空闲超时(默认为 30 分钟)或固定超时(配置为 60 分钟)后过期,
以先发生者为准。
还可以使用
Apache Geode 的 Spring SessionFixedDurationExpirationSessionRepositoryBeanPostProcessor .此 BPP 包装
任何特定于数据存储SessionRepository 在FixedDurationExpirationSessionRepository 实现
,仅评估访问时的会话过期。此方法与基础数据存储无关
因此可以与任何 Spring Session 提供程序一起使用。到期确定仅基于
会议creationTime 属性和所需的java.time.Duration 指定固定持续时间
过期超时。 |
这FixedDurationExpirationSessionRepository 不应在严格的过期超时情况下使用,例如
当会话必须在固定持续时间过期超时后立即过期时。此外,与
这FixedTimeoutSessionExpirationPolicy 这FixedDurationExpirationSessionRepository 不采取空闲到期
超时。也就是说,它在确定过期超时时仅使用固定持续时间
给定会话。 |
3.5.3.SessionExpirationPolicy
链接
使用复合软件设计模式,可以将一组SessionExpirationPolicy
instances 作为单个实例,其功能就像在一个链中一样,就像
Servlet 过滤器本身。
复合软件设计模式是一种功能强大的模式,由SessionExpirationPolicy
,@FunctionalInterface
,只需返回一个Optional
之java.time.Duration
从
这determineExpirationTimeout
方法。
这允许每个组合的SessionExpirationPolicy
“可选地”返回一个Duration
仅当到期时
可以由这个实例确定。或者,此实例可以弃踢到下一个实例SessionExpirationPolicy
或链,直到返回非空过期超时,或者最终返回
不会返回过期超时。
事实上,这个策略是由FixedTimeoutSessionExpirationPolicy
,这将返回Optional.empty()
在固定超时之前发生空闲超时的情况下。通过返回
没有过期超时,Apache Geode 将遵循默认的、配置的条目空闲超时过期策略
在管理会话状态的区域上。
3.6. Apache Geode 序列化
为了在客户端和服务器之间传输数据,或者在对等节点之间分发和复制数据时 在集群中,数据必须序列化。在这种情况下,有问题的数据是会话的状态。
每当在客户端/服务器拓扑中持久保存或访问会话时,会话的状态都会通过网络发送。 通常,启用了 Spring Session 的 Spring Boot 应用程序将是集群中服务器的客户端 的 Apache Geode 节点。
在服务器端,会话状态可能分布在集群中的多个服务器(数据节点)上进行复制 数据并保证会话状态的高可用性。使用 Apache Geode 时,可以对数据进行分区, 或分片,并且可以指定冗余级别。分发数据进行复制时,还必须 序列化以在集群中的对等节点之间传输会话状态。
Apache Geode 开箱即用,支持 Java 序列化。Java 序列化有很多优点, 例如处理对象图中的循环,或被任何用 Java 编写的应用程序普遍支持。 但是,Java 序列化非常冗长,并不是最有效的网络格式。
因此,Apache Geode 提供了自己的序列化框架来序列化 Java 类型:
3.6.1. Apache Geode 序列化背景
如上所述,Apache Geode 提供了 2 个额外的序列化框架:数据序列化和 PDX 序列化。
数据序列化
数据序列化是一种非常有效的格式(即快速和紧凑),与 Java 序列化相比,开销很小。
它通过发送 只有实际更改的数据位,而不是发送整个对象,这肯定会减少 除了在数据持久化时减少 IO 量外,还可以通过网络发送数据量 或溢出到磁盘。
但是,每当数据通过线路传输或持久化/溢出时,数据序列化都会产生 CPU 损失
并从磁盘访问,因为接收端执行反序列化。事实上,每当使用增量传播时,都必须在接收端对对象进行反序列化,以便应用“增量”。Apache Geode 适用
deltas 通过调用实现org.apache.geode.Delta
接口。显然,你不能
在序列化对象上调用方法。
PDX的
另一方面,PDX 代表便携式数据交换,保留了发送数据的形式。
例如,如果客户端以 PDX 格式向服务器发送数据,则服务器会将数据保留为 PDX 序列化字节
并将它们存储在缓存中Region
数据访问作的目标。
此外,PDX,顾名思义,是“可移植的”,这意味着它同时支持 Java 和本语客户端, 例如 C、C++ 和 C# 客户端,以在同一数据集上进行互作。
PDX 甚至允许对序列化字节执行 OQL 查询,而不会导致对象被反序列化 首先,为了评估查询谓词并执行查询。这可以从 Apache Geode 开始实现 维护一个“类型注册表”,其中包含序列化和存储在 使用 PDX 的 Apache Geod。
然而,可移植性确实是有代价的,其开销略高于数据序列化。尽管如此,PDX 还很遥远 比 Java 序列化更高效、更灵活,Java 序列化将类型元数据存储在对象的序列化字节中 而不是像 Apache Geode 在使用 PDX 时那样在单独的类型注册表中。
PDX 不支持 Delta。从技术上讲,PDX 可序列化对象可以通过实现
这org.apache.geode.Delta
接口,并且只有“delta”将是
发送,即使在 PDX 的上下文中也是如此。但是,必须反序列化 PDX 序列化对象才能应用增量。
请记住,调用一种方法来应用增量,这首先违背了使用 PDX 的目的。
在开发管理 {data-store-name} 集群中数据的本机客户端(例如 C)时,甚至在混合时 具有 Java 客户端的本机客户端,通常不会在类路径上提供任何关联的 Java 类型 集群中的服务器。使用 PDX,无需在类路径上提供 Java 类型,并且许多 仅开发和使用本机客户端访问存储在 {data-store-name} 中的数据的用户将不会提供任何 Java 类型,用于其相应的 C/C/C# 类型。
Apache Geode 还支持序列化到 PDX 或从 PDX 序列化的 JSON。在这种情况下,Java 类型很可能不会 在服务器类路径上提供,因为许多不同的语言(例如 JavaScript、Python、Ruby)支持 JSON 与 Apache Geade 一起使用。
尽管如此,即使有 PDX 在运行,用户也必须注意不要在集群中的服务器上导致 PDX 序列化对象 反序列化。
例如,考虑对序列化为 PDX 的以下 Java 类型的对象进行 OQL 查询...
@Region("People")
class Person {
private LocalDate birthDate;
private String name;
public int getAge() {
// no explicit 'age' field/property in Person
// age is just implemented in terms of the 'birthDate' field
}
}
随后,如果 OQL 查询调用Person
对象,例如:
SELECT * FROM /People p WHERE p.age >= 21
然后,这将导致 PDX 序列化Person
对象要反序列化,因为age
不是字段Person
,
而是一个方法,其中包含基于另一个字段的计算Person
(即birthDate
).同样,调用
任何java.lang.Object
方法,例如Object.toString()
,将导致反序列化发生
也。
Apache Geode 确实提供了read-serialized
配置设置,以便任何缓存Region.get(key)
可能在Function
不会导致 PDX 序列化对象反序列化。但是,没有什么能阻止考虑不周的 OQL 查询
导致反序列化,所以要小心。
数据序列化 + PDX + Java 序列化
Apache Geode 可以同时支持所有 3 种序列化格式。
例如,应用程序域模型可能包含实现java.io.Serialiable
接口
并且您可能将数据序列化框架与 PDX 结合使用。
虽然可以将 Java 序列化与数据序列化和 PDX 一起使用,但通常更可取 并建议使用1种序列化策略。 |
与 Java 序列化不同,数据序列化和 PDX 序列化不处理对象图周期。 |
有关 Apache Geode 序列化机制的更多背景信息,请参见此处。
3.6.2. 使用 Spring Session 序列化
以前,Spring Session for Apache Geode 仅支持 Apache Geode 数据序列化格式。主要 这背后的动机是利用 Apache Geode 的增量传播功能,因为会话的 状态可以任意大。
但是,从 Apache Geode 2.0 的 Spring Session 开始,PDX 也受支持,现在是新的默认序列化 选择。在 Apache Geode 2.0 的 Spring Session 中,默认值更改为 PDX,主要是因为 PDX 是 用户广泛使用和要求的格式。
PDX 无疑是最灵活的格式,以至于您甚至不需要 Apache Geode 的 Spring Session 或其对集群中服务器类路径的任何传递依赖关系,以将 Spring Session 与 阿帕奇晶洞。事实上,使用 PDX,您甚至不需要将应用程序域对象类型存储在 服务器类路径上的 (HTTP) 会话。
从本质上讲,在使用 PDX 序列化时,Apache Geode 不需要存在关联的 Java 类型 在服务器的类路径上。只要集群中的服务器上没有发生反序列化,您就很安全。
这@EnableGemFireHttpSession
注释引入了新的 sessionSerializerBeanName
用户认为
可用于配置在Spring容器中声明和注册的bean的名称,实现所需的
序列化策略。Spring Session for Apache Geode 使用序列化策略进行序列化
会话状态。
开箱即用的 Spring Session for Apache Geode 提供了 2 种序列化策略:1 种用于 PDX,1 种用于数据序列化。它会自动在 Spring 容器中注册两个序列化策略 bean。 然而,这些策略中只有 1 种在运行时实际使用,PDX!
在实现数据序列化和 PDX 的 Spring 容器中注册的 2 个 bean 被命名为SessionDataSerializer
和SessionPdxSerializer
分别。默认情况下,sessionSerializerBeanName
属性
设置为SessionPdxSerializer
,就好像用户注释了他/她的 Spring Boot、启用了 Spring Session 的应用程序一样
配置类,具有:
@SpringBootApplication
@EnableGemFireHttpSession(sessionSerializerBeanName = "SessionPdxSerializer")
class MySpringSessionApplication { }
将序列化策略更改为数据序列化是一件简单的事情,而是通过将sessionSerializerBeanName
属性设置为SessionDataSerializer
如下:
@SpringBootApplication
@EnableGemFireHttpSession(sessionSerializerBeanName = "SessionDataSerializer")
class MySpringSessionApplication { }
由于这两个值非常常见,因此 Spring Session for Apache Geode 为GemFireHttpSessionConfiguration
类:GemFireHttpSessionConfiguration.SESSION_PDX_SERIALIZER_BEAN_NAME
和GemFireHttpSessionConfiguration.SESSION_DATA_SERIALIZER_BEAN_NAME
.因此,您可以显式配置 PDX,
如下:
import org.springframework.session.data.geode.config.annotation.web.http.GemFireHttpSessionConfiguration;
@SpringBootApplication
@EnableGemFireHttpSession(sessionSerializerBeanName = GemFireHttpSessionConfiguration.SESSION_PDX_SERIALIZER_BEAN_NAME)
class MySpringSessionApplication { }
使用 1 个属性和 2 个现成的 bean 定义,您可以指定所需的序列化框架 与 Apache Geode 支持的 Spring Boot、启用 Spring Session 的应用程序一起使用。
3.6.3. Apache Geode 序列化框架的 Spring Session
为了抽象出 Apache Geode 的数据序列化和 PDX 序列化框架的细节, Spring Session for Apache Geode 提供了自己的序列化框架(门面),包装了 Apache Geode 的 序列化框架。
序列化 API 存在于org.springframework.session.data.gemfire.serialization
包。主要
此 API 中的接口是org.springframework.session.data.gemfire.serialization.SessionSerializer
.
接口定义为:
SessionSerializer
接口interface SessionSerializer<T, IN, OUT> {
void serialize(T session, OUT out);
T deserialize(IN in);
boolean canSerialize(Class<?> type);
boolean canSerialize(Object obj) {
// calls Object.getClass() in a null-safe way and then calls and returns canSerialize(:Class)
}
}
基本上,该接口允许您序列化和反序列化 SpringSession
对象。
这IN
和OUT
类型参数和这些类型的相应方法参数提供对对象的引用
负责编写Session
到字节流或读取Session
来自字节流。实际的
参数将基于配置的底层 Apache Geode 序列化策略特定于类型。
例如,当使用 Apache Geode 的 PDX 序列化框架时,IN
和OUT
将是org.apache.geode.pdx.PdxReader
和org.apache.geode.pdx.PdxWriter
分别。配置 Apache Geode 的数据序列化框架后,则IN
和OUT
将是java.io.DataInput
和java.io.DataOutput
分别。
这些参数提供给SessionSerializer
框架自动实现,并作为
前面提到的,基于配置的底层 Apache Geode 序列化策略。
从本质上讲,尽管 Apache Geode 的 Spring Session 提供了一个围绕 Apache Geode 的 序列化框架,在幕后 Apache Geode 仍然需要这些序列化框架之一 用于将数据序列化到 Apache Geode 或从 Apache Geode 序列化数据。
那么SessionSerializer
接口真的有用吗?
实际上,它允许用户自定义会话状态的哪些方面实际被序列化和存储
在 Apache Geode 中。应用程序开发人员可以提供自己的自定义、特定于应用程序SessionSerializer
实现,在 Spring 容器中将其注册为 bean,然后将其配置为 Spring Session 使用
让 Apache Geode 序列化会话状态,如下所示:
@EnableGemFireHttpSession(sessionSerializerBeanName = "MyCustomSessionSerializer")
class MySpringSessionDataGemFireApplication {
@Bean("MyCustomSessionSerializer")
SessionSerializer<Session, ?, ?> myCustomSessionSerializer() {
// ...
}
}
实现 SessionSerializer
Spring Session for Apache Geode 在用户想要实现自定义SessionSerializer
这适合 Apache Geode 的序列化框架之一。
如果用户只是实现了org.springframework.session.data.gemfire.serialization.SessionSerializer
接口
直接不从 Apache Geode 提供的抽象基类的 Spring Session 之一扩展,相关
到 Apache Geode 的序列化框架之一,则 Apache Geode 的 Spring Session 将包装用户的
习惯SessionSerializer
在org.springframework.session.data.gemfire.serialization.pdx.support.PdxSerializerSessionSerializerAdapter
并将其注册为 Apache Geodeorg.apache.geode.pdx.PdxSerializer
.
Spring Session for Apache Geode 小心翼翼地不要践踏任何现有的PdxSerializer
实现用户
可能已经通过其他方式在 Apache Geode 注册。事实上,提供了几种不同的
Apache Geode 的org.apache.geode.pdx.PdxSerializer
接口存在:
-
Apache Geode 本身提供了
org.apache.geode.pdx.ReflectionBasedAutoSerializer
. -
Spring Data for Apache Geode (SDG) 提供了
org.springframework.data.gemfire.mapping.MappingPdxSerializer
, 它在 SD 存储库抽象和 SDG 的扩展中用于处理将 PDX 序列化类型映射到 应用程序存储库接口中定义的应用程序域对象类型。
这是通过获取当前注册的任何PdxSerializer
实例并组合它
使用PdxSerializerSessionSerializerAdapter
包装用户的自定义应用程序SessionSerializer
实现并重新注册这个“复合" PdxSerializer
在 Apache Geode 缓存上。“复合"
PdxSerializer
实现由 Spring Session 为 Apache Geode 的org.springframework.session.data.gemfire.pdx.support.ComposablePdxSerializer
类
当实体作为 PDX 存储在 Apache Geode 中时。
如果没有其他PdxSerializer
当前已在 Apache Geode 缓存中注册,则适配器
只是简单地注册。
当然,您可以强制将底层 Apache Geode 序列化策略与自定义SessionSerializer
通过执行以下作之一来实现:
-
自定义
SessionSerializer
实现可以实现 Apache Geode 的org.apache.geode.pdx.PdxSerializer
接口,或者为了方便起见,将 Spring Session 扩展为 Apache Geode 的org.springframework.session.data.gemfire.serialization.pdx.AbstractPdxSerializableSessionSerializer
类 Spring Session for Apache Geode 将注册自定义SessionSerializer
作为PdxSerializer
使用 Apache Geode。 -
自定义
SessionSerializer
实现可以扩展 Apache Geode 的org.apache.geode.DataSerializer
类,或者为了方便起见,扩展 Apache Geode 的 Spring Sessionorg.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer
类 Spring Session for Apache Geode 将注册自定义SessionSerializer
作为DataSerializer
使用 Apache Geode。 -
最后,用户可以创建自定义
SessionSerializer
实现与之前一样,没有指定哪个 Apache Geode 序列化框架,因为自定义SessionSeriaizer
实现不实现 任何 Apache Geode 序列化接口或从 Apache Geode 提供的任何 Spring Session 扩展 抽象基类,并且仍然将其注册为 Apache Geode 中的DataSerializer
通过声明 类型为org.springframework.session.data.gemfire.serialization.data.support.DataSerializerSessionSerializerAdapter
这样。。。
@EnableGemFireHttpSession(sessionSerializerBeanName = "customSessionSerializer")
class Application {
@Bean
DataSerializerSessionSerializerAdapter dataSerializerSessionSerializer() {
return new DataSerializerSessionSerializerAdapter();
}
@Bean
SessionSerializer<Session, ?, ?> customSessionSerializer() {
// ...
}
}
仅凭DataSerializerSessionSerializerAdapter
在 Spring 容器中注册为 bean,
任何中性习俗SessionSerializer
实施将被视为并注册为DataSerializer
在 Apache Geode 中。
对数据序列化的额外支持
如果您正在配置和引导 Apache Geode 服务器,请随意跳过此部分 在使用 Spring (Boot) 的集群中,因为通常,以下信息将不适用。答案是肯定的 这完全取决于您声明的依赖项和 Spring 配置。但是,如果您使用 Gfsh 启动集群中的服务器,那么请务必继续阅读。 |
背景
使用 Apache Geode 的 DataSerialization 框架时,尤其是在序列化 (HTTP) 会话时从客户端 状态到集群中的服务器,您必须注意在集群中配置 Apache Geode 服务器 具有适当的依赖项。如上一节所述,当利用增量时尤其如此 关于数据序列化。
使用 DataSerialization 框架作为序列化策略时,从 您的 Web 应用程序客户端到服务器,则必须使用 Spring 会话正确配置服务器 用于表示 (HTTP) 会话及其内容的 Apache Geode 类类型。这意味着包括 服务器类路径上的 Spring JAR。
此外,使用 DataSerialization 可能还需要包含包含应用程序域的 JAR。 由 Web 应用程序使用并作为会话属性值放入 (HTTP) 会话的类, 特别是在以下情况下:
-
您的类型实现了
org.apache.geode.DataSerializable
接口。 -
您的类型实现了
org.apache.geode.Delta
接口。 -
您已注册
org.apache.geode.DataSerializer
标识和序列化类型。 -
您的类型实现了
java.io.Serializable
接口。
当然,您必须确保放置在 (HTTP) 会话中的应用程序域对象类型在某些 形式或其他形式。但是,您并不严格要求使用 DataSerialization,也不一定 如果出现以下情况,则需要在服务器类路径上具有应用程序域对象类型:
-
您的类型实现了
org.apache.geode.pdx.PdxSerializable
接口。 -
或者,您已经注册了
org.apache.geode.pdx.PdxSerializer
正确标识和序列化 应用程序域对象类型。
Apache Geode 在确定要使用的序列化策略时将应用以下优先级 要序列化对象图:
-
第一
DataSerializable
对象和/或任何已注册的DataSerializers
标识要序列化的对象。 -
然后
PdxSerializable
对象和/或任何已注册的PdxSerializer
标识要序列化的对象。 -
最后,所有
java.io.Serializable
类型。
这也意味着,如果特定的应用程序域对象类型(例如A
) 机具java.io.Serializable
,
但是,a(自定义)PdxSerializer
已在 Apache Geode 中注册,以识别同一应用程序
域对象类型(即A
),那么 Apache Geode 将使用 PDX 来序列化“A”,而不是 Java 序列化,
在这种情况下。
这特别有用,因为这样您就可以使用 DataSerialization 来序列化 (HTTP) Session 对象,利用 Deltas 和 DataSerialization 的所有强大功能,但随后使用 PDX 序列化应用程序域对象 类型,这大大简化了所涉及的配置和/或工作。
现在我们已经大致了解了为什么存在这种支持,您如何启用它?
配置
首先,创建一个 Apache Geodecache.xml
如下:
cache.xml
配置<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="http://geode.apache.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://geode.apache.org/schema/cache https://geode.apache.org/schema/cache/cache-1.0.xsd"
version="1.0">
<initializer>
<class-name>
org.springframework.session.data.gemfire.serialization.data.support.DataSerializableSessionSerializerInitializer
</class-name>
</initializer>
</cache>
然后,使用以下命令在 *Gfsh* 中启动服务器:
gfsh> start server --name=InitializedServer --cache-xml-file=/path/to/cache.xml --classpath=...
配置 Apache Geode 服务器classpath
具有适当的依赖关系是棘手的部分,
但一般来说,以下方法应该有效:
gfsh> set variable --name=REPO_HOME --value=${USER_HOME}/.m2/repository
gfsh> start server ... --classpath=\
${REPO_HOME}/org/springframework/spring-core/{spring-version}/spring-core-{spring-version}.jar\
:${REPO_HOME}/org/springframework/spring-aop/{spring-version}/spring-aop-{spring-version}.jar\
:${REPO_HOME}/org/springframework/spring-beans/{spring-version}/spring-beans-{spring-version}.jar\
:${REPO_HOME}/org/springframework/spring-context/{spring-version}/spring-context-{spring-version}.jar\
:${REPO_HOME}/org/springframework/spring-context-support/{spring-version}/spring-context-support-{spring-version}.jar\
:${REPO_HOME}/org/springframework/spring-expression/{spring-version}/spring-expression-{spring-version}.jar\
:${REPO_HOME}/org/springframework/spring-jcl/{spring-version}/spring-jcl-{spring-version}.jar\
:${REPO_HOME}/org/springframework/spring-tx/{spring-version}/spring-tx-{spring-version}.jar\
:${REPO_HOME}/org/springframework/data/spring-data-commons/{spring-data-commons-version}/spring-data-commons-{spring-data-commons-version}.jar\
:${REPO_HOME}/org/springframework/data/spring-data-geode/{spring-data-geode-version}/spring-data-geode-{spring-data-geode-version}.jar\
:${REPO_HOME}/org/springframework/session/spring-session-core/{spring-session-core-version}/spring-session-core-{spring-session-core-version}.jar\
:${REPO_HOME}/org/springframework/session/spring-session-data-geode/{spring-session-data-geode-version}/spring-session-data-geode-{spring-session-data-geode-version}.jar\
:${REPO_HOME}/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar
请记住,您可能还需要将应用程序域对象 JAR 文件添加到服务器类路径中。
若要全面了解其工作原理,请参阅示例。
自定义更改检测
默认情况下,每当 Session 被修改时(例如lastAccessedTime
更新到当前时间),会话
被 Spring Session for Apache Geode (SSDG) 视为脏的。使用 Apache Geode 数据序列化框架时,利用 Apache Geode 的增量传播功能也非常有用和有价值。
使用数据序列化时,SSDG 还使用增量传播仅发送对会话状态的更改 客户端和服务器。这包括可能已添加、删除或更新的任何会话属性。
默认情况下,任何时候Session.setAttribute(name, value)
调用时,Session 属性被视为“脏”
并将在客户端和服务器之间的增量中发送。即使应用程序域对象
没有改变。
通常,永远没有理由调用Session.setAttribute(..)
除非您的对象已更改。然而
如果可能发生这种情况,并且您的对象相对较大(具有复杂的对象层次结构),那么您可能需要
考虑以下任一:
-
在应用程序域对象中实现 Delta 接口 模型虽然有用,但侵入性很强,或者......
-
提供 SSDG 的自定义实现
org.springframework.session.data.gemfire.support.IsDirtyPredicate
策略接口。
开箱即用,SSDG 提供了 5 个实现的IsDirtyPredicate
策略接口:
类 | 描述 | 默认值 |
---|---|---|
|
新的会话属性值始终被视为脏。 |
|
|
新的会话属性值永远不会被视为脏的。 |
|
|
当旧值和新值时,新会话属性值被视为脏
如果新值的类型未实现 |
是的 |
|
如果旧值不等于
由 |
|
|
如果旧值与
使用恒等式运算符的新值(即 |
如上表所示,DeltaAwareDirtyPredicate
是 SSDG 使用的默认实现。
这DeltaAwareDirtyPredicate
自动考虑实现的应用程序域对象
阿帕奇晶洞Delta
接口。然而DeltaAwareDirtyPredicate
即使您的应用程序也能正常工作
domain 对象不会实现Delta
接口。SSDG 会将您的应用程序域对象视为脏
任何时候Session.setAttribute(name, newValue)
称为 如果新值与旧值不同,
或者新值未实现Delta
接口。
您只需在 Spring 容器中声明一个 bean 即可更改 SSDG 的脏实现、确定策略
的IsDirtyPredicate
接口类型:
IsDirtyPredicate
策略@EnableGemFireHttpSession
class ApplicationConfiguration {
@Bean
IsDirtyPredicate equalsDirtyPredicate() {
return EqualsDirtyPredicate.INSTANCE;
}
}
组成
这IsDirtyPredicate
接口还提供了andThen(:IsDirtyPredicate)
和orThen(:IsDirtyPredicate)
方法
组成 2 个或更多IsDirtyPredicate
实现,以便组织复杂的逻辑和规则
用于确定应用程序域对象是否脏。
例如,您可以同时组合EqualsDirtyPredicate
和DeltaAwareDirtyPredicate
使用 OR 运算符:
EqualsDirtyPredicate
跟DeltaAwareDirtyPredicate
使用逻辑 OR 运算符@EnableGemFireHttpSession
class ApplicationConfiguration {
@Bean
IsDirtyPredicate equalsOrThenDeltaDirtyPredicate() {
return EqualsDirtyPredicate.INSTANCE
.orThen(DeltaAwareDirtyPredicate.INSTANCE);
}
}
您甚至可以实现自己的自定义IsDirtyPredicates
基于特定的应用程序域对象类型:
IsDirtyPredicate
实现class CustomerDirtyPredicate implements IsDirtyPredicate {
public boolean isDirty(Object oldCustomer, Object newCustomer) {
if (newCustomer instanceof Customer) {
// custom logic to determine if a new Customer is dirty
}
return true;
}
}
class AccountDirtyPredicate implements IsDirtyPredicate {
public boolean isDirty(Object oldAccount, Object newAccount) {
if (newAccount instanceof Account) {
// custom logic to determine if a new Account is dirty
}
return true;
}
}
然后结合CustomerDirtyPredicate
使用AccountDirtyPredicate
以及回退的默认谓词,如下所示:
IsDirtyPredicates
@EnableGemFireHttpSession
class ApplicationConfiguration {
@Bean
IsDirtyPredicate typeSpecificDirtyPredicate() {
return new CustomerDirtyPredicate()
.andThen(new AccountDirtyPredicate())
.andThen(IsDirtyPredicate.ALWAYS_DIRTY);
}
}
组合和可能性是无限的。
实现自定义时要小心IsDirtyPredicate 策略。如果您错误地确定您的
应用程序域对象在实际脏时不是脏的,则不会在会话增量中发送
从客户端到服务器。 |
更改会话表示
在内部,Spring Session for Apache Geode 维护 (HTTP) 会话和会话的 2 个表示形式 属性。每个表示都基于是否支持 Apache Geode“Deltas”。
由于前面讨论的原因,只有在使用数据序列化时,Apache Geode 的 Spring Session 才会启用 Apache Geode 增量传播。
实际上,该策略是:
-
如果配置了 Apache Geode 数据序列化,则支持 Delta,并且
DeltaCapableGemFireSession
和DeltaCapableGemFireSessionAttributes
使用表示。 -
如果配置了 Apache Geode PDX 序列化,则将禁用增量传播 和
GemFireSession
和GemFireSessionAttributes
使用表示。
可以覆盖 Spring Session for Apache Geode 和用户使用的这些内部表示
提供自己的会话相关类型。唯一严格的要求是会话实现
必须实现核心 Spring Sessionorg.springframework.session.Session
接口。
举个例子,假设你想定义自己的 Session 实现。
首先,定义Session
类型。也许是你的习惯Session
类型甚至封装并处理 Session
属性,而无需定义单独的类型。
class MySession implements org.springframework.session.Session {
// ...
}
然后,您需要扩展org.springframework.session.data.gemfire.GemFireOperationsSessionRepository
类
并覆盖createSession()
方法来创建自定义的实例Session
实现类。
class MySessionRepository extends GemFireOperationsSessionRepository {
@Override
public Session createSession() {
return new MySession();
}
}
如果您提供自己的自定义SessionSerializer
实现和 Apache Geode PDX 序列化是
配置完毕,然后就完成了。
但是,如果您配置了 Apache Geode 数据序列化,则必须额外提供自定义
实现SessionSerializer
接口,并让它直接扩展 Apache Geode 的org.apache.geode.DataSerializer
类,或扩展 Apache Geode 的org.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer
类
并覆盖getSupportedClasses():Class<?>[]
方法。
例如:
class MySessionSerializer extends AbstractDataSerializableSessionSerializer {
@Override
public Class<?>[] getSupportedClasses() {
return new Class[] { MySession.class };
}
}
不幸getSupportedClasses()
无法返回通用 Spring Sessionorg.springframework.session.Session
接口类型。如果可以,那么我们可以避免显式需要覆盖getSupportedClasses()
方法
自定义DataSerializer
实现。但是,Apache Geode 的数据序列化框架只能匹配
在确切的类类型上,因为它错误地在内部按名称存储和引用类类型,然后
要求用户覆盖并实现getSupportedClasses()
方法。
3.7. HttpSession 集成的工作原理
幸运的是,两者javax.servlet.http.HttpSession
和javax.servlet.http.HttpServletRequest
(的 API
获取HttpSession
) 是接口。这意味着我们可以为每个 API 提供自己的实现。
本节介绍 Spring Session 如何提供透明的集成javax.servlet.http.HttpSession .
目的是让用户了解幕后发生的事情。此功能已实现
并集成,因此您无需自己实现此逻辑。 |
首先,我们创建一个自定义javax.servlet.http.HttpServletRequest
返回自定义实现javax.servlet.http.HttpSession
.它看起来像下面:
public class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper {
public SessionRepositoryRequestWrapper(HttpServletRequest original) {
super(original);
}
public HttpSession getSession() {
return getSession(true);
}
public HttpSession getSession(boolean createNew) {
// create an HttpSession implementation from Spring Session
}
// ... other methods delegate to the original HttpServletRequest ...
}
任何返回javax.servlet.http.HttpSession
被覆盖。所有其他方法都由javax.servlet.http.HttpServletRequestWrapper
并简单地委托给原始javax.servlet.http.HttpServletRequest
实现。
我们将javax.servlet.http.HttpServletRequest
使用 Servlet 实现Filter
叫SessionRepositoryFilter
. 伪代码可以在下面找到:
public class SessionRepositoryFilter implements Filter {
public doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
SessionRepositoryRequestWrapper customRequest = new SessionRepositoryRequestWrapper(httpRequest);
chain.doFilter(customRequest, response, chain);
}
// ...
}
通过传入自定义javax.servlet.http.HttpServletRequest
实现到FilterChain
我们确保
在我们的Filter
使用自定义javax.servlet.http.HttpSession
实现。
这凸显了为什么Spring Session的SessionRepositoryFilter
必须放在任何东西之前
与javax.servlet.http.HttpSession
.
3.8. HttpSessionListener
Spring Session 支持HttpSessionListener
通过翻译SessionCreatedEvent
和SessionDestroyedEvent
到HttpSessionEvent
通过声明SessionEventHttpSessionListenerAdapter
.
若要使用此支持,您需要:
-
确保您的
SessionRepository
实现支持并配置为触发SessionCreatedEvent
和'SessionDestroyedEvent'。 -
配置
SessionEventHttpSessionListenerAdapter
作为春豆。 -
注入每个
HttpSessionListener
进入SessionEventHttpSessionListenerAdapter
如果您将 HttpSession 中记录的配置支持与 Apache Geode 一起使用,
然后您需要做的就是注册每个HttpSessionListener
作为豆子。
例如,假设您想要支持 Spring Security 的并发控制,并且需要使用HttpSessionEventPublisher
,
然后你可以简单地添加HttpSessionEventPublisher
作为豆子。
3.10. 会话存储库
一个SessionRepository
负责创建、持久化和访问Session
实例和状态。
如果可能,开发人员不应直接与SessionRepository
或Session
.相反,开发人员
应该更喜欢与SessionRepository
和Session
间接通过javax.servlet.http.HttpSession
,WebSocket
和WebSession
集成。
3.11. FindByIndexNameSessionRepository
Spring Session 最基本的 API,用于使用Session
是SessionRepository
.API 故意非常简单
以便轻松提供具有基本功能的附加实现。
一些SessionRepository
实现可以选择实现FindByIndexNameSessionRepository
也。
例如,Spring Session 的 Apache Geode 支持实现FindByIndexNameSessionRepository
.
这FindByIndexNameSessionRepository
添加一个方法来查找特定用户的所有会话。
这是通过确保名称为FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME
填充了用户名。开发人员有责任确保填充属性,因为
Spring Session 不知道正在使用的身份验证机制。
的一些实现 |
3.12. EnableSpringHttpSession
这@EnableSpringHttpSession
注释可以添加到任何@Configuration
类来公开SessionRepositoryFilter
作为 Spring 容器中的一个 bean,名为“springSessionRepositoryFilter”。
为了利用注释,单个SessionRepository
必须提供 bean。
3.13. EnableGemFireHttpSession
这@EnableGemFireHttpSession
注释可以添加到任何@Configuration
class 代替@EnableSpringHttpSession
注释以公开SessionRepositoryFilter
作为 Spring 容器中的 bean,名为
“springSessionRepositoryFilter”,并将 Apache Geode 定位为管理javax.servlet.http.HttpSession
州。
使用@EnableGemFireHttpSession
注释,其他配置是开箱即用的导入,同时
提供了 Apache Geode 特定的SessionRepository
接口命名,GemFireOperationsSessionRepository
.
3.14. GemFireOperationsSession存储库
GemFireOperationsSessionRepository
是一个SessionRepository
使用 Spring Session 实现的实现
对于 Apache Geode 的s_GemFireOperationsSessionRepository
.
在 Web 环境中,此存储库与SessionRepositoryFilter
.
此实现支持SessionCreatedEvents
,SessionDeletedEvents
和SessionDestroyedEvents
通过SessionEventHttpSessionListenerAdapter
.
3.14.1. 在 Apache Geode 中使用索引
虽然关于正确定义对 Apache Geode 性能产生积极影响的索引的最佳实践 超出了本文档的范围,重要的是要认识到 Spring Session for Apache Geode 会创建 并使用索引来有效地查询和查找会话。
开箱即用的 Spring Session for Apache Geode 在主体名称上创建 1 个哈希类型索引。有两个
用于查找主体名称的不同内置策略。第一种策略是会话的值
属性,名称为FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME
将被索引到相同的
索引名称。
例如:
String indexName = FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME;
session.setAttribute(indexName, username);
Map<String, Session> idToSessions =
this.sessionRepository.findByIndexNameAndIndexValue(indexName, username);
3.14.2. 将索引与 Apache Geode 和 Spring Security 一起使用
或者,Apache Geode 的 Spring Session 将映射 Spring Security 的当前Authentication#getName()
自
索引FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME
.
例如,如果您使用的是 Spring Security,则可以使用以下方法查找当前用户的会话:
SecurityContext securityContext = SecurityContextHolder.getContext();
Authentication authentication = securityContext.getAuthentication();
String indexName = FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME;
Map<String, Session> idToSessions =
this.sessionRepository.findByIndexNameAndIndexValue(indexName, authentication.getName());
3.14.3. 在 Apache Geode 中使用自定义索引
这使得开发人员能够使用GemFireOperationsSessionRepository
以编程方式查询和查找所有会话
有效地使用给定的主体名称。
此外,Spring Session for Apache Geode 将在实现 Session 的
地图类型attributes
属性(即在任何任意 Session 属性上),当开发人员识别 1 个或多个
命名的 Session 属性,这些属性应由 Apache Geode 索引。
可以使用indexableSessionAttributes
属性@EnableGemFireHttpSession
注解。开发人员将此注释添加到他们的 Spring 应用程序中@Configuration
class 当他/她希望启用 Spring Session 对HttpSession
后盾
阿帕奇晶洞。
String indexName = "name1";
session.setAttribute(indexName, indexValue);
Map<String, Session> idToSessions =
this.sessionRepository.findByIndexNameAndIndexValue(indexName, indexValue);
仅在@EnableGemFireHttpSession 注释的indexableSessionAttributes 属性将定义一个索引。所有其他会话属性将不会被索引。 |
然而,有一个问题。存储在可索引会话属性中的任何值都必须实现java.lang.Comparable<T>
接口。如果这些对象值未实现Comparable
,然后是 Apache Geode
当为具有持久会话数据的区域定义索引时,将在启动时抛出错误,或者当尝试
在运行时为可索引的 Session 属性分配一个不是Comparable
并保存会话
到 Apache Geode。
任何未编制索引的 Session 属性都可以存储非Comparable 值。 |
要了解有关 Apache Geode 基于范围的索引的更多信息,请参阅在地图字段上创建索引。
要了解有关 Apache Geode 索引的一般信息,请参阅使用索引。