3. HttpSession 集成

Spring Session 提供了与javax.servlet.http.HttpSession.这意味着开发人员 可以将HttpSessionimplementation 替换为 Spring Session 支持的 implementation。spring-doc.cadn.net.cn

Spring Session 支持插入多个不同的数据存储提供程序(例如,如 Apache Geode) 为了管理HttpSession州。spring-doc.cadn.net.cn

3.1. 为什么选择Spring Session和HttpSession?

我们已经提到 Spring Session 提供了与HttpSession但是有什么好处 我们能摆脱这一切吗?spring-doc.cadn.net.cn

3.2. 使用 Apache Geode 进行 HttpSession 管理

Apache Geode 与 Spring Session 一起使用时,Web 应用程序的javax.servlet.http.HttpSession可以替换为由 Apache Geode 管理的群集实现 并使用 Spring Session 的 API 方便地访问。spring-doc.cadn.net.cn

使用 Apache Geode 管理会话状态的两种最常见拓扑包括:spring-doc.cadn.net.cn

此外,Apache Geode 还支持使用 WAN 拓扑进行站点到站点复制。 配置和使用 Apache Geode 的 WAN 功能的能力独立于 Spring Session、 并且超出了本文档的范围。spring-doc.cadn.net.cn

有关使用 Spring Data for Apache Geode 配置 Apache Geode WAN 功能的更多详细信息 可以在这里找到。spring-doc.cadn.net.cn

3.2.1. Apache Geode 客户端-服务器

客户端-服务器拓扑可能是 在 Spring Session 中使用 Apache Geode 作为提供程序时,用户最常见的配置选择,因为 与应用程序相比,Apache Geode 服务器具有明显不同且独特的 JVM 堆要求。 使用 Client-Server 拓扑使应用程序能够独立管理(例如复制)应用程序状态 从其他应用程序进程。spring-doc.cadn.net.cn

在 Client-Server 拓扑中,使用 Spring Session 的应用程序将打开与远程集群的 1 个或多个连接 的 Apache Geode 服务器,这些服务器将管理对所有HttpSession州。spring-doc.cadn.net.cn

您可以使用以下任一方式配置客户端-服务器拓扑:spring-doc.cadn.net.cn

Apache Geode Client-Server 基于 Java 的配置

本节介绍如何配置 Apache Geode 的客户端-服务器拓扑以管理HttpSession州 使用基于 Java 的配置。spring-doc.cadn.net.cn

带有 Apache Geode(客户端-服务器)的 HttpSession 提供了一个工作示例,演示如何 将 Spring Session 与 Apache Geode 集成以管理HttpSessionstate 使用 Java 配置。您可以阅读 通过下面的基本集成步骤,但我们鼓励您按照详细的 'HttpSession' 进行作 与 Apache Geode (客户端-服务器) 指南集成时。
Spring Java 配置

添加所需的依赖项和存储库声明后,我们可以创建 Spring 配置。 Spring 配置负责创建一个 ServletFilter,它取代了HttpSession以及由 Spring Session 和 Apache Geode 支持的实现。spring-doc.cadn.net.cn

客户端配置

添加以下 Spring 配置:spring-doc.cadn.net.cn

@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.此外,我们还调整了一些基本的 “DEFAULT”Pool设置(例如readTimeout).
2 @EnableGemFireHttpSession创建一个名为springSessionRepositoryFilter实现javax.servlet.Filter.过滤器将替换HttpSession使用 Spring Session 提供的实现 并由 Apache Geode 提供支持。此外,该配置还将创建必要的客户端Region(默认情况下,“ClusteredSpringSessions”,它是一个PROXY Region) 对应于同一服务器端Region按名称。所有会话状态都通过Region数据访问作。 客户端Region使用 “DEFAULT”Pool.
3 然后,我们等待确保 Apache Geode Server 已启动并运行,然后再继续。这才真正有用 用于自动化 (集成) 测试目的。
在典型的 Apache Geode 生产部署中,集群可能包括数百或数千个 的服务器(也称为数据节点)中,客户端更常见的是连接到 1 个或多个正在运行的 Apache Geode 定位器 在同一个集群中。Locator 将有关集群中可用服务器的元数据传递给客户端,单个 server load 以及哪些服务器具有感兴趣的客户端数据,这对于 Direct 尤为重要。 单跳数据访问和延迟敏感型应用程序。有关客户端/服务器部署的更多详细信息,请参阅 Apache Geode 用户指南。
有关配置 Spring Data Geode 的更多信息,请参阅参考指南

@EnableGemFireHttpSession注解使开发人员能够配置 Spring Session 的某些方面 和 Apache Geode 开箱即用,使用以下属性:spring-doc.cadn.net.cn

  • clientRegionShortcut- 使用 ClientRegionShortcut 在客户端上指定 Apache Geode 数据管理策略(默认值为PROXY).此属性仅在配置客户端时使用Region.spring-doc.cadn.net.cn

  • indexableSessionAttributes- 按名称标识 Session 应为查询目的编制索引的属性。 只有 name 显式标识的 Session 属性才会被索引。spring-doc.cadn.net.cn

  • maxInactiveIntervalInSeconds- 控制 HttpSession 空闲超时过期时间(默认为 30 分钟)。spring-doc.cadn.net.cn

  • poolName- 专用 Apache Geode 的名称Pool用于将客户端连接到服务器集群。 仅当应用程序是高速缓存客户端时,才使用此属性。默认为gemfirePool.spring-doc.cadn.net.cn

  • regionName- 指定 Apache Geode 的名称Region用于存储和管理HttpSession州 (默认为 “ClusteredSpringSessions”)。spring-doc.cadn.net.cn

  • serverRegionShortcut- 使用 RegionShortcut 在服务器上指定 Apache Geode 数据管理策略(默认值为PARTITION).此属性仅在配置 server 时使用Regions, 或者当采用 P2P 拓扑时。spring-doc.cadn.net.cn

请务必记住,Apache Geode 客户端Regionname 必须与 server 匹配Region如果客户端Region是一个PROXYCACHING_PROXY.客户端和服务器Region名字 如果客户端Region用于存储会话状态的是LOCAL.但是,请记住 该会话状态不会传播到服务器,并且您将失去使用 Apache Geode 的所有好处 要在分布式 复制方式。
服务器配置

到目前为止,我们只介绍了等式的一面。我们还需要一个 Apache Geode 服务器,以便我们的缓存客户端与之通信 并将会话状态发送到服务器进行管理。spring-doc.cadn.net.cn

在此示例中,我们将使用以下 Java 配置来配置和运行 Apache Geode 服务器:spring-doc.cadn.net.cn

@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 (可选)然后,GemFireServerclass 的@EnableGemFireHttpSession创建必要的 服务器端Region(默认情况下为 “ClusteredSpringSessions”)用于存储HttpSession州。此步骤为 可选,因为会话Region可以手动创建,也许使用外部方法。 用@EnableGemFireHttpSession方便快捷。
Apache Geode 客户端-服务器基于 XML 的配置

本节介绍如何配置 Apache Geode 的客户端-服务器拓扑以管理HttpSession州 使用基于 XML 的配置。spring-doc.cadn.net.cn

使用 XML 的 HttpSession 与 Apache Geode(客户端-服务器)提供了一个工作示例 演示如何将 Spring Session 与 Apache Geode 集成以管理HttpSession使用 XML 的状态 配置。您可以阅读下面的集成基本步骤,但我们鼓励您按照 在详细的 'HttpSession' with Apache Geode (Client-Server) using XML Guide 中集成时 您自己的应用程序。
Spring XML 配置

添加所需的依赖项和存储库声明后,我们可以创建 Spring 配置。 Spring 配置负责创建一个Servlet Filter,它取代了javax.servlet.http.HttpSession以及由 Spring Session 和 Apache Geode 支持的实现。spring-doc.cadn.net.cn

客户端配置

添加以下 Spring 配置:spring-doc.cadn.net.cn

	<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 (可选)首先,我们可以包含一个Propertiesbean 配置 Apache Geode 的某些方面ClientCache使用 Pivotal GemFire 属性。在这种情况下,我们只是 使用特定于应用程序的 System 属性设置 Apache Geode 的 “log-level”,默认为 “warning” 如果未指定。
2 我们必须创建一个 Apache Geode 的实例ClientCache.我们使用gemfireProperties.
3 然后我们配置一个Pool与客户端/服务器拓扑中的 Apache Geode 服务器通信的连接数。 在我们的配置中,我们对超时、连接数等使用合理的设置。此外,我们的Pool已配置为直接连接到服务器(使用嵌套的gfe:server元素)。
4 最后,一个GemFireHttpSessionConfigurationbean 以启用 Spring Session 功能。
在典型的 Apache Geode 生产部署中,集群可能包括数百或数千个 的服务器(也称为数据节点)中,客户端更常见的是连接到 1 个或多个正在运行的 Apache Geode 定位器 在同一个集群中。Locator 将有关集群中可用服务器的元数据传递给客户端,单个 server load 以及哪些服务器具有感兴趣的客户端数据,这对于 Direct 尤为重要。 单跳数据访问和延迟敏感型应用程序。有关客户端/服务器部署的更多详细信息,请参阅 Apache Geode 用户指南。
有关为 Apache Geode 配置 Spring Data 的更多信息,请参阅参考指南
服务器配置

到目前为止,我们只介绍了等式的一面。我们还需要一个 Apache Geode 服务器,以便我们的缓存客户端与之通信 并将会话状态发送到服务器进行管理。spring-doc.cadn.net.cn

在此示例中,我们将使用以下 XML 配置来启动 Apache Geode 服务器:spring-doc.cadn.net.cn

	<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 (可选)首先,我们可以包含一个Propertiesbean 配置 Apache Geode 对等节点的某些方面Cache使用 Pivotal GemFire 属性。在这种情况下,我们只是 使用特定于应用程序的 System 属性设置 Apache Geode 的 “log-level”,默认为 “warning” 如果未指定。
2 我们必须配置 Apache Geode 对等体Cache实例。我们使用 Apache Geode 属性对其进行初始化。
3 接下来,我们定义一个CacheServer具有合理的配置bind-addressport由我们的缓存客户端使用 应用程序连接到服务器并发送会话状态。
4 最后,我们启用我们在客户端 XML 配置中声明的相同 Spring Session 功能 通过注册GemFireHttpSessionConfiguration,但我们设置了会话过期超时 设置为 30 秒。我们稍后会解释这意味着什么。

Apache Geode Server 使用以下方法进行引导:spring-doc.cadn.net.cn

@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. 基于注解的容器配置[Spring 的注解配置支持]。
2 首先,配置来自META-INF/spring/session-server.xml文件。
XML Servlet 容器初始化

我们的 Spring XML 配置创建了一个名为springSessionRepositoryFilter实现javax.servlet.Filter接口。这springSessionRepositoryFilterbean 负责替换 这javax.servlet.http.HttpSession使用由 Spring Session 和 Apache Geode 提供的自定义实现。spring-doc.cadn.net.cn

为了我们的Filter为了发挥它的魔力,我们需要指示 Spring 加载 我们session-client.xml配置文件。spring-doc.cadn.net.cn

我们使用以下配置执行此作:spring-doc.cadn.net.cn

来源/main/webapp/WEB-INF/web.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 读取contextConfigLocationcontext 参数值,并选取我们的 session-client.xml 配置文件。spring-doc.cadn.net.cn

最后,我们需要确保我们的 Servlet 容器(即 Tomcat)使用我们的springSessionRepositoryFilter对于每个请求。spring-doc.cadn.net.cn

以下代码片段为我们执行了最后一步:spring-doc.cadn.net.cn

来源/main/webapp/WEB-INF/web.xml
<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调用,该 API 将委托给springSessionRepositoryFilter.spring-doc.cadn.net.cn

3.2.2. Apache Geode 点对点 (P2P)

一种不太常见的方法是将 Spring Session 应用程序配置为 Apache Geode 集群中的对等成员 使用点对点 (P2P) 拓扑。 在此配置中,Spring Session 应用程序将是 Apache Geode 中的实际服务器(或数据节点) cluster 的 CLUSTER,而不仅仅是像以前那样只是一个缓存客户端。spring-doc.cadn.net.cn

这种方法的一个优点是应用程序接近应用程序的状态(即它的数据), 特别是HttpSession州。但是,还有其他有效的方法可以实现类似的 依赖于数据的计算,例如使用 Apache Geode 的 Function Execution。 在以下情况下可以使用 Apache Geode 的任何其他功能 Apache Geode 在 Spring Session 中充当提供程序。spring-doc.cadn.net.cn

P2P 拓扑结构对于测试目的以及更小、更专注和独立的应用程序非常有用。 例如微服务架构中的那些,并且肯定会改善您的应用程序的感知 延迟和吞吐量需求。spring-doc.cadn.net.cn

您可以使用以下任一方式配置点对点 (P2P) 拓扑:spring-doc.cadn.net.cn

Apache Geode 点对点 (P2P) 基于 Java 的配置

本节介绍如何配置 Apache Geode 的点对点 (P2P) 拓扑以管理HttpSession州 使用基于 Java 的配置。spring-doc.cadn.net.cn

HttpSession 与 Apache Geode (P2P) 提供了一个工作示例,演示如何 将 Spring Session 与 Apache Geode 集成以管理HttpSessionstate 使用 Java 配置。您可以阅读 通过下面的基本集成步骤,但我们鼓励您按照详细的 'HttpSession' 进行作 与 Apache Geode (P2P) 指南集成时。
Spring Java 配置

添加所需的依赖项和存储库声明后,我们可以创建 Spring 配置。spring-doc.cadn.net.cn

Spring 配置负责创建一个Servlet Filter,它取代了javax.servlet.http.HttpSession以及由 Spring Session 和 Apache Geode 支持的实现。spring-doc.cadn.net.cn

添加以下 Spring 配置:spring-doc.cadn.net.cn

@PeerCacheApplication(name = "SpringSessionDataGeodeJavaConfigP2pSample", logLevel = "error") (1)
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 30) (2)
public class Config {

}
1 首先,我们使用@PeerCacheApplication注解来简化对等缓存实例的创建。
2 然后,Configclass 的@EnableGemFireHttpSession创建必要的服务器端Region(默认情况下为 “ClusteredSpringSessions”)用于存储HttpSession州。
有关为 Apache Geode 配置 Spring Data 的更多信息,请参阅参考指南

@EnableGemFireHttpSession注解使开发人员能够配置 Spring Session 的某些方面 和 Apache Geode 开箱即用,使用以下属性:spring-doc.cadn.net.cn

  • clientRegionShortcut- 使用 ClientRegionShortcut 在客户端上指定 Apache Geode 数据管理策略(默认值为PROXY).此属性仅在配置客户端时使用Region.spring-doc.cadn.net.cn

  • indexableSessionAttributes- 按名称标识 Session 应为查询目的编制索引的属性。 只有 name 显式标识的 Session 属性才会被索引。spring-doc.cadn.net.cn

  • maxInactiveIntervalInSeconds- 控制 HttpSession 空闲超时过期时间(默认为 30 分钟)。spring-doc.cadn.net.cn

  • poolName- 专用 Apache Geode 的名称Pool用于将客户端连接到服务器集群。 仅当应用程序是高速缓存客户端时,才使用此属性。默认为gemfirePool.spring-doc.cadn.net.cn

  • regionName- 指定 Apache Geode 的名称Region用于存储和管理HttpSession州 (默认为 “ClusteredSpringSessions”)。spring-doc.cadn.net.cn

  • serverRegionShortcut- 使用 RegionShortcut 在服务器上指定 Apache Geode 数据管理策略(默认值为PARTITION).此属性仅在配置 server 时使用Regions, 或者当采用 P2P 拓扑时。spring-doc.cadn.net.cn

Java Servlet 容器初始化

我们的<<[httpsession-spring-java-configuration-p2p,Spring Java Configuration>>创建了一个名为springSessionRepositoryFilter实现javax.servlet.Filter.这springSessionRepositoryFilter豆 负责替换javax.servlet.http.HttpSession使用由 Spring Session 和 Apache Geode。spring-doc.cadn.net.cn

为了我们的Filter为了发挥它的魔力,Spring 需要加载我们的Config类。我们还需要确保我们的 Servlet 容器(即 Tomcat)使用我们的springSessionRepositoryFilter在每个 HTTP 请求上。spring-doc.cadn.net.cn

幸运的是,Spring Session 提供了一个名为AbstractHttpSessionApplicationInitializer使两者 步骤非常简单。spring-doc.cadn.net.cn

您可以在下面找到一个示例:spring-doc.cadn.net.cn

来源/main/java/sample/Initializer.java
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 的配置。spring-doc.cadn.net.cn

使用 XML 的 HttpSession with Apache Geode (P2P) 提供了一个工作示例,演示如何 将 Spring Session 与 Apache Geode 集成以管理HttpSessionstate 使用 XML 配置。您可以阅读 通过下面的基本集成步骤,但我们鼓励您按照详细的 'HttpSession' 进行作 与 Apache Geode (P2P) 集成时,使用 XML 指南
Spring XML 配置

添加所需的依赖项和存储库声明后,我们可以创建 Spring 配置。spring-doc.cadn.net.cn

Spring 配置负责创建一个Servlet Filter,它取代了javax.servlet.http.HttpSession以及由 Spring Session 和 Apache Geode 支持的实现。spring-doc.cadn.net.cn

添加以下 Spring 配置:spring-doc.cadn.net.cn

来源/main/webapp/WEB-INF/spring/session.xml
<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 (可选)首先,我们可以包含一个Propertiesbean 配置 Apache Geode 对等节点的某些方面Cache使用 VMware Tanzu GemFire 属性。在这种情况下,我们只是 使用特定于应用程序的 System 属性设置 Apache Geode 的 “log-level”,默认为 “warning” 如果未指定。
2 我们必须配置 Apache Geode 对等体Cache实例。我们使用 Apache Geode 属性对其进行初始化。
3 最后,我们通过注册GemFireHttpSessionConfiguration.
有关为 Apache Geode 配置 Spring Data 的更多信息,请参阅参考指南
XML Servlet 容器初始化

Spring XML 配置创建了一个名为springSessionRepositoryFilter实现javax.servlet.Filter.这springSessionRepositoryFilterbean 负责替换javax.servlet.http.HttpSession使用由 Spring Session 和 Apache Geode 支持的自定义实现。spring-doc.cadn.net.cn

为了我们的Filter为了发挥它的魔力,我们需要指示 Spring 加载我们的session.xml配置文件。spring-doc.cadn.net.cn

我们使用以下配置执行此作:spring-doc.cadn.net.cn

来源/main/webapp/WEB-INF/web.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 读取contextConfigLocationcontext 参数值,并选取我们的 session.xml 配置文件。spring-doc.cadn.net.cn

最后,我们需要确保我们的 Servlet 容器(即 Tomcat)使用我们的springSessionRepositoryFilter对于每个 HTTP 请求。spring-doc.cadn.net.cn

以下代码片段为我们执行了最后一步:spring-doc.cadn.net.cn

来源/main/webapp/WEB-INF/web.xml
<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.spring-doc.cadn.net.cn

3.3. 配置HttpSession使用具有属性的 Apache Geode 进行管理

虽然@EnableGemFireHttpSession注解在开始使用 Spring Session 时易于使用和方便 和 Apache Geode 在 Spring Boot 应用程序中迁移时,您很快就会遇到限制 环境转换为另一个环境,例如,从 DEV 迁移到 QA 再到 PROD 时。spring-doc.cadn.net.cn

使用@EnableGemFireHttpSessionannotation 属性,则无法更改 环境到另一个。因此,Spring Session for Apache Geode 引入了众所周知的、记录在案的属性 对于所有的@EnableGemFireHttpSessionannotation 属性。spring-doc.cadn.net.cn

表 4.已知的、记录在@EnableGemFireHttpSessionannotation 属性。
财产 Annotation 属性 描述 违约

spring.session.data.gemfire.cache.client.pool.namespring-doc.cadn.net.cn

EnableGemFireHttpSession.poolNamespring-doc.cadn.net.cn

客户端区域存储/访问 Session 状态使用的专用池的名称。spring-doc.cadn.net.cn

gemfirePoolspring-doc.cadn.net.cn

spring.session.data.gemfire.cache.client.region.shortcutspring-doc.cadn.net.cn

EnableGemFireHttpSession.clientRegionShortcutspring-doc.cadn.net.cn

在客户端-服务器拓扑中设置客户端区域数据管理策略。spring-doc.cadn.net.cn

ClientRegionShortcut.代理spring-doc.cadn.net.cn

spring.session.data.gemfire.cache.server.region.shortcutspring-doc.cadn.net.cn

EnableGemFireHttpSession.serverRegionShortcutspring-doc.cadn.net.cn

在对等 (P2P) 拓扑中设置对等区域数据管理策略。spring-doc.cadn.net.cn

RegionShortcut.PARTITION 分区spring-doc.cadn.net.cn

spring.session.data.gemfire.session.attributes.indexablespring-doc.cadn.net.cn

EnableGemFireHttpSession.indexableSessionAttributesspring-doc.cadn.net.cn

要在 Session 区域中编制索引的 Session 属性的逗号分隔列表。spring-doc.cadn.net.cn

spring.session.data.gemfire.session.expiration.bean-namespring-doc.cadn.net.cn

EnableGemFireHttpSession.sessionExpirationPolicyBeanNamespring-doc.cadn.net.cn

实现过期策略的 Spring 容器中的 Bean 的名称spring-doc.cadn.net.cn

spring.session.data.gemfire.session.expiration.max-inactive-interval-secondsspring-doc.cadn.net.cn

EnableGemFireHttpSession.maxInactiveIntervalInSecondsspring-doc.cadn.net.cn

会话过期超时(秒)spring-doc.cadn.net.cn

1800spring-doc.cadn.net.cn

spring.session.data.gemfire.session.region.namespring-doc.cadn.net.cn

EnableGemFireHttpSession.regionNamespring-doc.cadn.net.cn

用于存储和访问 Session 状态的客户端或对等区域的名称。spring-doc.cadn.net.cn

ClusteredSpringSessions 集群spring-doc.cadn.net.cn

spring.session.data.gemfire.session.serializer.bean-namespring-doc.cadn.net.cn

EnableGemFireHttpSession.sessionSerializerBeanNamespring-doc.cadn.net.cn

实现序列化策略的 Spring 容器中的 Bean 的名称spring-doc.cadn.net.cn

SessionPdxSerializerspring-doc.cadn.net.cn

所有属性都记录在@EnableGemFireHttpSessionannotation 属性 Javadoc 中。

因此,在使用 Apache Geode 时,调整 Spring Session 的配置非常简单 作为您的提供商,如下所示:spring-doc.cadn.net.cn

@SpringBootApplication
@ClientCacheApplication
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 900)
class MySpringSessionApplication {
  // ...
}

然后,在application.properties:spring-doc.cadn.net.cn

#application.properties
spring.session.data.gemfire.cache.client.region.shortcut=CACHING_PROXY
spring.session.data.gemfire.session.expiration.max-inactive-internval-seconds=3600

显式定义的任何属性都会覆盖相应的@EnableGemFireHttpSessionannotation 属性。spring-doc.cadn.net.cn

在上面的示例中,即使EnableGemFireHttpSession注解maxInactiveIntervalInSeconds属性 设置为900秒或 15 分钟,则相应的属性属性 (即spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds) 覆盖该值并将 Expiration 设置为3600秒,即 60 分钟。spring-doc.cadn.net.cn

请记住,属性会在运行时覆盖 annotation 属性值。

3.3.1. 属性的属性

您甚至可以变得更复杂,并使用其他属性配置您的属性,如下所示:spring-doc.cadn.net.cn

#application.properties
spring.session.data.gemfire.session.expiration.max-inactive-internval-seconds=${app.geode.region.expiration.timeout:3600}

此外,您可以使用 Spring 配置文件根据环境改变过期超时(或其他属性) 或您的应用程序,或者您的应用程序要求的任何标准。spring-doc.cadn.net.cn

属性占位符和嵌套是核心 Spring Framework 的一个功能,并不特定于 Spring Session 或 Spring Session for Apache Geode。

3.4. 配置HttpSession使用 Apache Geode 和 Configurer 进行管理

除了属性之外,Spring Session for Apache Geode 还允许您调整 使用 Apache Geode 的 Spring SessionSpringSessionGemFireConfigurer接口。该接口定义了一个 Contract 包含每个@EnableGemFireHttpSessionannotation 属性 调整配置。spring-doc.cadn.net.cn

SpringSessionGemFireConfigurer在概念上类似于 Spring Web MVC 的 Configurer 接口 (例如o.s.web.servlet.config.annotation.WebMvcConfigurer),它调整 Web 应用程序的 配置,例如配置异步支持。声明和实现Configurer是它允许您对配置进行编程控制。这在您需要的情况下非常有用 轻松表达确定是否应应用配置的复杂条件逻辑。spring-doc.cadn.net.cn

例如,要像以前一样调整 client Region data management policy (客户端区域数据管理策略) 和 Session expiration timeout (会话过期超时),请执行以下作: 使用以下内容:spring-doc.cadn.net.cn

@Configuration
class MySpringSessionConfiguration {

  @Bean
  SpringSessionGemFireConfigurer exampleSpringSessionGemFireConfigurer() {

    return new SpringSessionGemFireConfigurer() {

      @Override
      public ClientRegionShortcut getClientRegionShortcut() {
        return ClientRegionShortcut.CACHING_PROXY;
      }

      @Override
      public int getMaxInactiveIntervalInSeconds() {
        return 3600;
      }
    };
  }
}

当然,这个例子不是很有创意。您肯定可以使用更复杂的逻辑来确定 每个 configuration 属性的 configuration。spring-doc.cadn.net.cn

您可以根据需要进行调试,例如通过实施Configurer在其他属性方面 使用 Spring 的@Value注解,如下所示:spring-doc.cadn.net.cn

@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 将解析@Valueannotation 属性占位符值或 SpEL 表达式。 但是,如果您不使用 Spring Boot,则必须显式注册一个静态PropertySourcesPlaceholderConfigurerbean 定义。

但是,您只能声明 1SpringSessionGemFireConfigurerbean 中,除非 您还在使用 Spring 配置文件或标记了多个SpringSessionGemFireConfigurer以 bean 为主要 通过使用 Spring 的@Primarycontext 注释。spring-doc.cadn.net.cn

3.4.1. 配置优先级

一个SpringSessionGemFireConfigurer优先于@EnableGemFireHttpSession注释属性 或任何已知且记录在 案的 Spring Session for Apache Geode 属性 (例如spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds) 在 Spring Boot 中定义application.properties.spring-doc.cadn.net.cn

如果您的 Web 应用程序使用了 1 种以上的配置方法,则以下优先级将适用:spring-doc.cadn.net.cn

  1. SpringSessionGemFireConfigurer“已实现” 回调方法spring-doc.cadn.net.cn

  2. 记录的 Spring Session for Apache Geode 属性(请参阅相应的@EnableGemFireHttpSession注解 属性 Javadoc;例如spring.session.data.gemfire.session.region.name)spring-doc.cadn.net.cn

  3. @EnableGemFireHttpSession注释属性spring-doc.cadn.net.cn

Spring Session for Apache Geode 会小心翼翼地仅应用来自SpringSessionGemFireConfigurer豆 在 Spring 容器中声明。spring-doc.cadn.net.cn

在上面的示例中,由于您没有实现getRegionName()method,即 Apache Geode 区域的名称 管理HttpSessionstate 不会由 Configurer 决定。spring-doc.cadn.net.cn

例如,请考虑以下配置:spring-doc.cadn.net.cn

Spring Session for Apache Geode 配置示例
@ClientCacheApplication
@EnableGemFireHttpSession(
    maxInactiveIntervalInSeconds = 3600,
    poolName = "DEFAULT"
)
class MySpringSessionConfiguration {

  @Bean
  SpringSessionGemFireConfigurer sessionExpirationTimeoutConfigurer() {

    return new SpringSessionGemFireConfigurer() {

      @Override
      public int getMaxInactiveIntervalInSeconds() {
        return 300;
      }
    };
  }
}

此外,请考虑以下 Spring Bootapplication.properties文件:spring-doc.cadn.net.cn

  1. Spring Bootapplication.propertiesspring-doc.cadn.net.cn

spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds = 900
spring.session.data.gemfire.session.region.name = Sessions

Session expiration timeout (会话过期超时) 将为 300 秒或 5 分钟,覆盖 (即spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds) 为 900 秒或 15 分钟, 以及显式的@EnableGemFireHttpSession.maxInactiveIntervalInSecondsannotation 属性值为 3600 秒,即 1 小时。spring-doc.cadn.net.cn

由于 “sessionExpirationTimeoutConfigurer” bean 不会覆盖getRegionName()方法中,Session Region name 将由属性(即spring.session.data.gemfire.session.region.name)、设置为 “会话”、 这会覆盖隐式的@EnableGemFireHttpSession.regionNameannotation 属性的默认值 “ClusteredSpringSessions” 的 ClusteredSpringSessions 中。spring-doc.cadn.net.cn

@EnableGemFireHttpSession.poolNameannotation 属性的值 “DEFAULT” 将决定存储池的名称 在客户端和服务器之间发送 Region作以管理服务器上的 Session 状态时使用,因为 设置了相应的属性(即 spring.session.data.gemfire.cache.client.pool.name'),也未设置 这SpringSessionGemFireConfigurer.getPoolName()方法被 “sessionExpirationTimeoutConfigurer” Bean 覆盖。spring-doc.cadn.net.cn

最后,用于管理 Session 状态的 Client Region 将具有PROXY,则默认的 值@EnableGemFireHttpSession.clientRegionShortcutannotation 属性,该属性未显式设置,也 是相应的属性(即spring.session.data.gemfire.cache.client.region.shortcut) 的 S 属性。 而且,由于SpringSessionConfigurer.getClientRegionShortcut()method 未被覆盖,则使用默认值。spring-doc.cadn.net.cn

3.5. Apache Geode 过期

默认情况下,Apache Geode 使用 过期超时为 30 分钟,并将 INVALIDATE 条目作为作。这意味着当用户的 Session 保持非活动状态时 (即空闲)超过 30 分钟,Session 将过期并失效,用户必须开始新的 Session 以便继续使用该应用程序。spring-doc.cadn.net.cn

但是,如果您对会话状态管理和过期以及使用 默认的空闲超时 (TTI) 过期策略不足以满足您的用例 (UC) 需求?spring-doc.cadn.net.cn

现在,Spring Session for Apache Geode 支持特定于应用程序的自定义过期策略。作为应用程序 开发者,你可以指定自定义规则来管理由 Spring Session 管理的 Session 的过期,由 Apache Geode 的 Apache。spring-doc.cadn.net.cn

Spring Session for Apache Geode 提供了新的SessionExpirationPolicy 策略界面。spring-doc.cadn.net.cn

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

    }
}

您实施此接口以指定应用程序所需的 Session 过期策略,然后注册 实例作为 Spring 应用程序上下文中的 Bean。spring-doc.cadn.net.cn

使用@EnableGemFireHttpSession注解sessionExpirationPolicyBeanName属性来配置 这SessionExpirationPolicy实现 Session 过期的自定义应用程序策略和规则的 bean。spring-doc.cadn.net.cn

习惯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
    }
}

然后,在您的 application 类中,简单地声明以下内容:spring-doc.cadn.net.cn

习惯SessionExpirationPolicy配置
@SpringBootApplication
@EnableGemFireHttpSession(
    maxInactiveIntervalInSeconds = 600,
    sessionExpirationPolicyBeanName = "expirationPolicy"
)
class MySpringSessionApplication {

    @Bean
    SessionExpirationPolicy expirationPolicy() {
        return new MySessionExpirationPolicy();
    }
}
或者,该SessionExpirationPolicybean 可以使用spring.session.data.gemfire.session.expiration.bean-name属性,或者通过声明SpringSessionGemFireConfigurerbean 并覆盖 Spring 容器中的getSessionExpirationPolicyBeanName()方法。

您只需实现determineExpirationTimeout(:Session):Optional<Duration>方法 它封装了规则以确定 Session 何时到期。Session 的过期超时 表示为Optionaljava.time.Duration,它指定会话过期之前的时间长度。spring-doc.cadn.net.cn

determineExpirationTimeoutmethod 可以是特定于 Session 的,并且可能会随着每次调用而更改。spring-doc.cadn.net.cn

或者,您可以实现getAction方法指定 Session 过期时执行的作。默认情况下, 区域条目(即 Session)无效。另一种选择是在过期时销毁 Region Entry, 这将删除键 (Session ID) 和值 (Session)。Invalidate 仅删除该值。spring-doc.cadn.net.cn

在后台,SessionExpirationPolicy改编为 Apache Geode 的实例CustomExpiry接口。 本届Spring SessionCustomExpiry对象设置为会话区域的自定义条目空闲超时过期策略
在确定到期时间期间,CustomExpiry.getExpiry(:Region.Entry<String, Session>):ExpirationAttributes每次运行过期线程时,都会为区域中的每个条目(即 Session)调用 method,这反过来又会调用 调用我们的SessionExpirationPolicy.determineExpirationTimout(:Session):Optional<Duration>方法。 返回的java.time.Duration转换为秒,并用作ExpirationAttributesCustomExpiry.getExpiry(..)方法调用。
Apache Geode 的过期线程每秒运行一次,评估区域中的每个条目(即会话) 以确定条目是否已过期。您可以使用gemfire.EXPIRY_THREADS财产。有关更多详细信息,请参阅 Apache Geode 文档

3.5.1. Expiration Timeout 配置

如果要将过期超时作为自定义SessionExpirationPolicy上 这@EnableGemFireHttpSession注解maxInactiveIntervalInSeconds属性,或者 相应的spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds财产 然后是您的自定义SessionExpirationPolicyimplementation 还可以实现SessionExpirationTimeoutAware接口。spring-doc.cadn.net.cn

SessionExpirationTimeoutAwareinterface 定义为:spring-doc.cadn.net.cn

SessionExpirationTimeoutAware 接口
interface SessionExpirationTimeoutAware {

    void setExpirationTimeout(Duration expirationTimeout);

}

当您的自定义SessionExpirationPolicyimplementation 还会实现SessionExpirationTimeoutAware接口 则 Spring Session for Apache Geode 将为您的实现提供@EnableGemFireHttpSession注解maxInactiveIntervalInSeconds属性,或者从spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds属性(如果已设置)或从任何SpringSessionGemFireConfigurerbean 作为java.time.Duration.spring-doc.cadn.net.cn

如果使用了 1 个以上的配置选项,则以下顺序优先:spring-doc.cadn.net.cn

  1. SpringSessionGemFireConfigurer.getMaxInactiveIntervalInSeconds()spring-doc.cadn.net.cn

  2. spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds财产spring-doc.cadn.net.cn

  3. @EnableGemFireHttpSession注解maxInactiveIntervalInSeconds属性spring-doc.cadn.net.cn

3.5.2. 固定超时过期

为了更加方便,Spring Session for Apache Geode 提供了SessionExpirationPolicy固定持续时间过期的接口(或核心 Spring Session Issue #922 中描述的“绝对会话超时”)。spring-doc.cadn.net.cn

在某些情况下,例如出于安全原因,可能需要在固定 时间长度 (例如每小时),无论用户的 Session 是否仍处于活动状态。spring-doc.cadn.net.cn

Spring Session for Apache Geode 提供了FixedTimeoutSessionExpirationPolicy开箱即用的实施 对于此确切的用例 (UC)。除了处理固定期限到期外,还要小心地仍然考虑 并应用默认的 Idle Expiration 超时。spring-doc.cadn.net.cn

例如,考虑这样一个场景:用户登录,开始一个会话,处于活动状态 10 分钟,然后离开 让 Session 处于空闲状态。如果固定持续时间过期超时设置为 60 分钟,但空闲过期 超时仅设置为 30 分钟,并且用户未返回,则 Session 应在 40 分钟后过期 而不是 60 分钟,此时将发生固定持续时间过期。spring-doc.cadn.net.cn

相反,如果用户忙碌了整整 40 分钟,从而使 Session 保持活动状态,从而避免了 30 分钟 idle expiration timeout,然后离开,那么我们的固定持续时间过期超时应该开始并过期 用户的 Session 时间,即使用户的空闲过期超时要到 70 分钟才会发生 in(40 分钟 (活动) + 30 分钟 (空闲) = 70 分钟)。spring-doc.cadn.net.cn

嗯,这正是FixedTimeoutSessionExpirationPolicy确实。spring-doc.cadn.net.cn

要配置FixedTimeoutSessionExpirationPolicy,执行以下作:spring-doc.cadn.net.cn

固定持续时间到期配置
@SpringBootApplication
@EnableGemFireHttpSession(sessionExpirationPolicyBeanName = "fixedTimeoutExpirationPolicy")
class MySpringSessionApplication {

    @Bean
    SessionExpirationPolicy fixedTimeoutExpirationPolicy() {
        return new FixedTimeoutSessionExpirationPolicy(Duration.ofMinutes(60L));
    }
}

在上面的示例中,FixedTimeoutSessionExpirationPolicy在 Spring 应用程序上下文中声明为 Bean 并使用 60 分钟的固定持续时间过期超时进行初始化。因此,用户的 Session 将 在空闲超时(默认为 30 分钟)或固定超时(配置为 60 分钟)后过期, 哪个先发生。spring-doc.cadn.net.cn

还可以使用 Apache Geode 的 Spring SessionFixedDurationExpirationSessionRepositoryBeanPostProcessor.此 BPP 包装 任何特定于 Data Store 的SessionRepositoryFixedDurationExpirationSessionRepository实现 ,仅评估 Sessions 在访问时过期。此方法与基础数据存储无关 因此可以与任何 Spring Session 提供程序一起使用。到期确定完全基于 会话creationTime属性和所需的java.time.Duration指定固定持续时间 过期超时。
FixedDurationExpirationSessionRepository不应在严格的过期超时情况下使用,例如 当 Session 必须在固定持续时间过期超时后立即过期时。此外,与 这FixedTimeoutSessionExpirationPolicyFixedDurationExpirationSessionRepository不采用空闲过期 timeout 的考虑。也就是说,在确定过期超时时,它只使用固定持续时间 对于给定的 Session。

3.5.3.SessionExpirationPolicy链接

使用 Composite 软件设计模式,您可以将一组SessionExpirationPolicy实例作为单个实例,就像在一个链中一样工作,就像 Servlet 过滤器本身。spring-doc.cadn.net.cn

复合软件设计模式是一种功能强大的模式,由SessionExpirationPolicy,@FunctionalInterface,只需返回Optionaljava.time.Duration从 这determineExpirationTimeout方法。spring-doc.cadn.net.cn

这允许每个组合SessionExpirationPolicy以 “optionally” 返回一个Duration仅当 可以由此实例确定。或者,此实例可能会传送到下一个SessionExpirationPolicy在组合中,或链,直到返回非空过期超时,或者最终返回 不返回过期超时。spring-doc.cadn.net.cn

事实上,这个策略正是由FixedTimeoutSessionExpirationPolicy,它将返回Optional.empty()在固定超时之前发生空闲超时的情况下。通过返回 无过期超时,Apache Geode 将遵循默认的、配置的条目空闲超时过期策略 在管理 Session 状态的区域上。spring-doc.cadn.net.cn

3.6. Apache Geode 序列化

为了在客户端和服务器之间传输数据,或者在对等节点之间分发和复制数据 在集群中,数据必须序列化。在这种情况下,有问题的数据是 Session 的状态。spring-doc.cadn.net.cn

每当 Session 在 client/server 拓扑中被持久化或访问时,Session 的状态都会通过网络发送。 通常,启用了 Spring Session 的 Spring Boot 应用程序将是集群中服务器的客户端 Apache Geode 节点。spring-doc.cadn.net.cn

在服务器端,Session 状态可能分布在集群中的多个服务器(数据节点)之间进行复制 数据,并保证 Session 状态的高可用性。使用 Apache Geode 时,可以对数据进行分区, 或 sharded,并且可以指定 redundancy-level 。当分发数据以进行复制时,它还必须 serialized 在集群中的 Peer 节点之间传输 Session 状态。spring-doc.cadn.net.cn

开箱即用的 Apache Geode 支持 Java 序列化Java 序列化有很多优点, 例如处理对象图中的循环,或者被任何用 Java 编写的应用程序普遍支持。 但是,Java 序列化非常冗长,并不是最有效的在线格式。spring-doc.cadn.net.cn

因此,Apache Geode 提供了自己的序列化框架来序列化 Java 类型:spring-doc.cadn.net.cn

3.6.1. Apache Geode 序列化背景

如上所述,Apache Geode 提供了 2 个额外的序列化框架:数据序列化和 PDX 序列化spring-doc.cadn.net.cn

数据序列化

数据序列化是一种非常有效的格式(即快速紧凑),与 Java 序列化相比开销很小。spring-doc.cadn.net.cn

通过发送 只发送实际更改的数据位,而不是发送整个对象,这肯定会减少 除了在持久保存数据时减少 IO 量外,还关注通过网络发送的数据量 或溢出到磁盘。spring-doc.cadn.net.cn

但是,每当数据通过网络传输或持久化/溢出到 并从磁盘访问,因为接收端执行反序列化。事实上,无论何时使用 Delta Propagation,都必须在接收端对对象进行反序列化,以便应用 “delta”。Apache Geode 适用 deltas 的org.apache.geode.Delta接口。显然,你不能 在序列化对象上调用方法。spring-doc.cadn.net.cn

PDX

另一方面,PDX 代表便携式数据交换,它保留了发送数据的形式。 例如,如果客户端以 PDX 格式将数据发送到服务器,则服务器会将数据保留为 PDX 序列化字节 并将它们存储在缓存中Region数据访问作是其目标。spring-doc.cadn.net.cn

此外,PDX,顾名思义,是“可移植的”,这意味着它支持 Java 和本地语言客户端。 例如 C、C++ 和 C# 客户端,以对同一数据集进行互作。spring-doc.cadn.net.cn

PDX 甚至允许对序列化的字节执行 OQL 查询,而不会导致对象被反序列化 首先,以便评估查询谓词并执行查询。这可以从 Apache Geode 开始实现 维护一个 “Type Registry”,其中包含被序列化和存储的对象的类型元数据 使用 PDX 的 Apache Geode。spring-doc.cadn.net.cn

但是,可移植性确实有成本,其开销略高于数据序列化。尽管如此,PDX 还很遥远 比 Java 序列化更高效、更灵活,Java 序列化将类型元数据存储在对象的序列化字节中 而不是像 Apache Geode 在使用 PDX 时那样在单独的类型注册表中。spring-doc.cadn.net.cn

PDX 不支持 Delta。从技术上讲,PDX 可序列化对象可以通过实现org.apache.geode.Delta接口,并且只有 “delta” 会是 发送的,即使在 PDX 的上下文中也是如此。但是,必须反序列化 PDX 序列化对象才能应用增量。 请记住,调用一个方法来应用 delta,这首先违背了使用 PDX 的目的。spring-doc.cadn.net.cn

在开发管理 {data-store-name} 集群中数据的 Native Client(例如 C)时,甚至在混合 具有 Java 客户端的 Native Client,通常不会在 Classpath 上提供任何关联的 Java 类型 集群中 的服务器。使用 PDX,无需在 Classpath 上提供 Java 类型,并且许多 仅开发和使用 Native Client 来访问存储在 {data-store-name} 中的数据的用户将不会提供任何 Java 类型。spring-doc.cadn.net.cn

Apache Geode 还支持序列化为 PDX 或从 PDX 序列化的 JSON。在这种情况下,Java 类型很可能不会 在服务器 Classpath 上提供,因为支持 JSON 的许多不同语言(例如 JavaScript、Python、Ruby)可以是 与 Apache Geode 一起使用。spring-doc.cadn.net.cn

尽管如此,即使 PDX 正在运行,用户也必须注意不要在集群中的服务器上导致 PDX 序列化对象 进行反序列化。spring-doc.cadn.net.cn

例如,考虑对序列化为 PDX...spring-doc.cadn.net.cn

@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对象,例如:spring-doc.cadn.net.cn

SELECT * FROM /People p WHERE p.age >= 21spring-doc.cadn.net.cn

然后,这将导致 PDX 序列化Person对象进行反序列化,因为age不是Person, 而是一个包含基于另一个字段Person(即birthDate).同样,调用 任何java.lang.Object方法,例如Object.toString()将导致反序列化发生 也。spring-doc.cadn.net.cn

Apache Geode 确实提供了read-serialized配置设置,以便任何缓存Region.get(key)可能在Function不会导致 PDX 序列化对象被反序列化。但是,没有什么能阻止构思不周的 OQL 查询 导致反序列化,所以要小心。spring-doc.cadn.net.cn

数据序列化 + PDX + Java 序列化

Apache Geode 可以同时支持所有 3 种序列化格式。spring-doc.cadn.net.cn

例如,您的应用程序域模型可能包含实现java.io.Serialiable接口 并且您可能正在使用 Data Serialization 框架和 PDX 的组合。spring-doc.cadn.net.cn

虽然可以将 Java 序列化Data Serialization 和 PDX 一起使用,但通常更可取 ,建议使用 1 个序列化策略。
Java 序列化不同,数据序列化和 PDX 序列化不处理对象图周期。

有关 Apache Geode 序列化机制的更多背景信息,请参阅此处spring-doc.cadn.net.cn

3.6.2. 使用 Spring Session 进行序列化

以前,Spring Session for Apache Geode 仅支持 Apache Geode 数据序列化格式。主要的 这背后的动机是利用 Apache Geode 的 Delta Propagation 功能,因为 Session 的 state 可以是任意大的。spring-doc.cadn.net.cn

但是,从 Spring Session for Apache Geode 2.0 开始,PDX 也受支持,现在是新的默认序列化 选择。在 Spring Session for Apache Geode 2.0 中,默认值更改为 PDX,主要是因为 PDX 是最 用户广泛使用和请求的格式。spring-doc.cadn.net.cn

PDX 无疑是最灵活的格式,以至于您甚至不需要 Spring Session for Apache Geode 或其对集群中服务器的 Classpath 的任何传递依赖项,以使用 Spring Session Apache Geode 的 Apache。事实上,使用 PDX,您甚至不需要将应用程序域对象类型存储在 服务器的 Classpath 上的 (HTTP) Session。spring-doc.cadn.net.cn

实质上,在使用 PDX 序列化时,Apache Geode 不需要存在关联的 Java 类型 在服务器的 Classpath 上。只要集群中的服务器上没有发生反序列化,您就是安全的。spring-doc.cadn.net.cn

@EnableGemFireHttpSessionannotation 引入了新的 sessionSerializerBeanName属性,该属性将用户 可用于配置在 Spring 容器中声明和注册的 bean 的名称,该 bean 实现了所需的 序列化策略。Spring Session for Apache Geode 使用序列化策略进行序列化 Session 状态。spring-doc.cadn.net.cn

Spring Session for Apache Geode 提供 2 种开箱即用的序列化策略:1 种用于 PDX,1 种用于数据序列化。它会自动在 Spring 容器中注册两个序列化策略 bean。 但是,这些策略中只有 1 种在运行时实际使用,即 PDX!spring-doc.cadn.net.cn

在实现数据序列化和 PDX 的 Spring 容器中注册的 2 个 bean 被命名为SessionDataSerializerSessionPdxSerializer分别。默认情况下,sessionSerializerBeanName属性 设置为SessionPdxSerializer,就好像用户注释了他/她的 Spring Boot、启用了 Spring Session 的应用程序一样 configuration 类替换为:spring-doc.cadn.net.cn

@SpringBootApplication
@EnableGemFireHttpSession(sessionSerializerBeanName = "SessionPdxSerializer")
class MySpringSessionApplication {  }

将序列化策略更改为 Data Serialization 是一件简单的事情,只需将sessionSerializerBeanName属性设置为SessionDataSerializer如下:spring-doc.cadn.net.cn

@SpringBootApplication
@EnableGemFireHttpSession(sessionSerializerBeanName = "SessionDataSerializer")
class MySpringSessionApplication {  }

由于这两个值非常常见,因此 Spring Session for Apache Geode 为GemFireHttpSessionConfiguration类:GemFireHttpSessionConfiguration.SESSION_PDX_SERIALIZER_BEAN_NAMEGemFireHttpSessionConfiguration.SESSION_DATA_SERIALIZER_BEAN_NAME.因此,您可以显式配置 PDX, 如下:spring-doc.cadn.net.cn

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 Session 的 Spring Boot 应用程序一起使用。spring-doc.cadn.net.cn

3.6.3. Spring Session for Apache Geode 序列化框架

为了抽象出 Apache Geode 的数据序列化和 PDX 序列化框架的细节, Spring Session for Apache Geode 提供了自己的序列化框架(门面),将 Apache Geode 的 序列化框架。spring-doc.cadn.net.cn

序列化 API 位于org.springframework.session.data.gemfire.serialization包。主要 接口是org.springframework.session.data.gemfire.serialization.SessionSerializer.spring-doc.cadn.net.cn

接口定义为:spring-doc.cadn.net.cn

Spring SessionSessionSerializer接口
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对象。spring-doc.cadn.net.cn

INOUT类型参数和这些类型的相应方法参数提供对对象的引用 负责编写Session转换为字节流或读取Session从字节流中。实际的 参数将特定于类型,具体取决于配置的基础 Apache Geode 序列化策略。spring-doc.cadn.net.cn

例如,当使用 Apache Geode 的 PDX 序列化框架时,INOUT将是org.apache.geode.pdx.PdxReaderorg.apache.geode.pdx.PdxWriter分别。配置 Apache Geode 的数据序列化框架后,则INOUT将是java.io.DataInputjava.io.DataOutput分别。spring-doc.cadn.net.cn

这些参数提供给SessionSerializerimplementation 和 前面提到的是基于配置的底层 Apache Geode 序列化策略。spring-doc.cadn.net.cn

从本质上讲,尽管 Spring Session for Apache Geode 为 Apache Geode 的 序列化框架,在后台 Apache Geode 仍然需要这些序列化框架之一 用于将数据序列化到 Apache Geode 或从 Apache Geode 序列化数据。spring-doc.cadn.net.cn

那么SessionSerializer接口真的有用吗?spring-doc.cadn.net.cn

实际上,它允许用户自定义 Session 状态的哪些方面实际被序列化和存储 在 Apache Geode 中。应用程序开发人员可以提供自己的自定义、特定于应用程序的SessionSerializer实现,在 Spring 容器中将其注册为 Bean,然后将其配置为由 Spring Session 使用 用于序列化 Session 状态,如下所示:spring-doc.cadn.net.cn

@EnableGemFireHttpSession(sessionSerializerBeanName = "MyCustomSessionSerializer")
class MySpringSessionDataGemFireApplication {

  @Bean("MyCustomSessionSerializer")
  SessionSerializer<Session, ?, ?> myCustomSessionSerializer() {
    // ...
  }
}
实现 SessionSerializer

Spring Session for Apache Geode 在用户想要实现自定义SessionSerializer它适合 Apache Geode 的序列化框架之一。spring-doc.cadn.net.cn

如果用户只是实现org.springframework.session.data.gemfire.serialization.SessionSerializer接口 直接扩展,而无需从 Spring Session for Apache Geode 提供的抽象基类之一扩展,相关的 添加到 Apache Geode 的 Serialization 框架之一,则 Spring Session for Apache Geode 会将用户的 习惯SessionSerializerorg.springframework.session.data.gemfire.serialization.pdx.support.PdxSerializerSessionSerializerAdapter并将其注册为 Apache Geode 的org.apache.geode.pdx.PdxSerializer.spring-doc.cadn.net.cn

Spring Session for Apache Geode 小心翼翼地避免STOMP踏任何现有的PdxSerializer实现,即用户 可能已经通过其他方式向 Apache Geode 注册。事实上,有几种不同的,只要 Apache Geode 的org.apache.geode.pdx.PdxSerializerinterface 存在:spring-doc.cadn.net.cn

这是通过获取任何当前注册的PdxSerializer实例并组合它 使用PdxSerializerSessionSerializerAdapter包装用户的自定义应用程序SessionSerializer实现并重新注册此 “复合" PdxSerializer在 Apache Geode 缓存上。“复合" PdxSerializer实现由 Spring Session for Apache Geode 的org.springframework.session.data.gemfire.pdx.support.ComposablePdxSerializer类 当实体作为 PDX 存储在 Apache Geode 中时。spring-doc.cadn.net.cn

如果没有其他PdxSerializer当前已注册到 Apache Geode 缓存,则适配器 只是注册了。spring-doc.cadn.net.cn

当然,您可以强制使用与自定义SessionSerializer通过执行以下 1 项作来实现:spring-doc.cadn.net.cn

  1. 自定义SessionSerializer实现可以实现 Apache Geode 的org.apache.geode.pdx.PdxSerializer接口,或者为方便起见,扩展 Spring Session for Apache Geode 的org.springframework.session.data.gemfire.serialization.pdx.AbstractPdxSerializableSessionSerializer类 Spring Session for Apache Geode 将注册自定义SessionSerializer作为PdxSerializer与 Apache Geode 一起使用。spring-doc.cadn.net.cn

  2. 自定义SessionSerializerimplementation 可以扩展 Apache Geode 的org.apache.geode.DataSerializer类,或者为了方便起见,扩展 Spring Session for Apache Geode 的org.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer类 Spring Session for Apache Geode 将注册自定义SessionSerializer作为DataSerializer与 Apache Geode 一起使用。spring-doc.cadn.net.cn

  3. 最后,用户可以创建自定义SessionSerializerimplementation 一样,不指定哪个 Apache Geode 序列化框架,因为自定义SessionSeriaizerimplementation 未实现 任何 Apache Geode 序列化接口或从 Spring Session for Apache Geode 提供的任何 抽象基类,并且仍将其在 Apache Geode 中注册为DataSerializer通过声明 其他 Spring Session for Apache Geode bean 在 Spring 容器中的类型为org.springframework.session.data.gemfire.serialization.data.support.DataSerializerSessionSerializerAdapter这样。。。spring-doc.cadn.net.cn

在 Apache Geode 中强制将自定义 SessionSerializer 注册为 DataSerializer
@EnableGemFireHttpSession(sessionSerializerBeanName = "customSessionSerializer")
class Application {

	@Bean
	DataSerializerSessionSerializerAdapter dataSerializerSessionSerializer() {
		return new DataSerializerSessionSerializerAdapter();
	}

	@Bean
	SessionSerializer<Session, ?, ?> customSessionSerializer() {
		// ...
	}
}

仅凭DataSerializerSessionSerializerAdapter在 Spring 容器中注册为 Bean, 任何中立自定义SessionSerializerimplementation 将被处理并注册为DataSerializer在 Apache Geode 中。spring-doc.cadn.net.cn

对数据序列化的额外支持
如果您正在配置和引导 Apache Geode 服务器,请随时跳过本节 在您的集群中使用 Spring (Boot),因为通常以下信息将不适用。答案是肯定的 这完全取决于你声明的依赖项和 Spring 配置。但是,如果您使用 Gfsh 启动集群中的服务器,那么请务必继续阅读。
背景

使用 Apache Geode 的 DataSerialization 框架时,尤其是在序列化 (HTTP) 会话时从客户端 状态添加到集群中的服务器,则必须注意在集群中配置 Apache Geode 服务器 替换为适当的依赖项。如前一节所述,在利用增量时尤其如此 在 Data Serialization 上。spring-doc.cadn.net.cn

当使用 DataSerialization 框架作为序列化策略来序列化 (HTTP) 会话状态时 你的 Web 应用程序客户端连接到服务器,那么服务器必须正确地配置 Spring Session ,用于表示 (HTTP) 会话及其内容的 Apache Geode 类类型。这意味着包括 服务器 Classpath 上的 Spring JAR。spring-doc.cadn.net.cn

此外,使用 DataSerialization 可能还需要包含包含应用程序域的 JAR 类,这些类由 Web 应用程序使用,并作为 Session Attribute 值放入 (HTTP) Session 中, 特别是在以下情况下:spring-doc.cadn.net.cn

  1. 您的类型实现org.apache.geode.DataSerializable接口。spring-doc.cadn.net.cn

  2. 您的类型实现org.apache.geode.Delta接口。spring-doc.cadn.net.cn

  3. 您已注册了org.apache.geode.DataSerializer,用于标识和序列化类型。spring-doc.cadn.net.cn

  4. 您的类型实现java.io.Serializable接口。spring-doc.cadn.net.cn

当然,您必须确保放置在 (HTTP) Session 中的应用程序域对象类型在某些 形式或其他形式。但是,并非严格要求您使用 DataSerialization,也不必如此 在以下情况下,需要将应用程序域对象类型放在 servers 类路径上:spring-doc.cadn.net.cn

  1. 您的类型实现org.apache.geode.pdx.PdxSerializable接口。spring-doc.cadn.net.cn

  2. 或者,您已经注册了org.apache.geode.pdx.PdxSerializer正确识别和序列化 您的应用程序域对象类型。spring-doc.cadn.net.cn

Apache Geode 在确定要使用的序列化策略时,将应用以下优先顺序 要序列化对象图:spring-doc.cadn.net.cn

  1. 第一DataSerializable对象和/或任何已注册的DataSerializers标识要序列化的对象。spring-doc.cadn.net.cn

  2. 然后PdxSerializable对象和/或任何已注册的PdxSerializer标识要序列化的对象。spring-doc.cadn.net.cn

  3. 最后,所有java.io.Serializable类型。spring-doc.cadn.net.cn

这也意味着,如果特定的应用程序域对象类型(例如A) 实现java.io.Serializable, 但是,A (自定义)PdxSerializer已在 Apache Geode 中注册,以标识相同的应用程序 domain 对象类型(即A),则 Apache Geode 将使用 PDX 来序列化 “A” 而不是 Java 序列化, 在这种情况下。spring-doc.cadn.net.cn

这特别有用,因为您可以使用 DataSerialization 来序列化 (HTTP) Session 对象,利用 增量和 DataSerialization 的所有强大功能,但随后使用 PDX 序列化应用程序域对象 类型,这大大简化了所涉及的配置和/或工作。spring-doc.cadn.net.cn

现在我们已经大致了解了为什么存在这种支持,您如何启用它?spring-doc.cadn.net.cn

配置

首先,创建 Apache Geodecache.xml如下:spring-doc.cadn.net.cn

Apache Geodecache.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* 中使用以下命令启动您的服务器:spring-doc.cadn.net.cn

使用 Gfsh 启动 Server
gfsh> start server --name=InitializedServer --cache-xml-file=/path/to/cache.xml --classpath=...

配置 Apache Geode 服务器classpath使用适当的依赖项是棘手的部分, 但一般来说,以下内容应该有效:spring-doc.cadn.net.cn

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 文件添加到服务器 Classpath 中。spring-doc.cadn.net.cn

要全面了解其工作原理,请参阅示例spring-doc.cadn.net.cn

自定义变化检测

默认情况下,每当 Session 被修改时(例如lastAccessedTime更新为当前时间),则 Session 被 Spring Session for Apache Geode (SSDG) 视为脏的。在使用 Apache Geode 数据序列化框架时,利用 Apache Geode 的增量传播功能也非常有用和有价值。spring-doc.cadn.net.cn

使用数据序列化时,SSDG 还使用增量传播仅发送对 Session 状态的更改 客户端和服务器。这包括可能已添加、删除或更新的任何 Session 属性。spring-doc.cadn.net.cn

默认情况下,随时Session.setAttribute(name, value)时,Session 属性被视为 “dirty” ,并将在 Client 端和 Server 之间的 delta 中发送。即使您的应用程序域对象 未更改。spring-doc.cadn.net.cn

通常,从来没有理由调用Session.setAttribute(..)除非您的对象已更改。然而 如果发生这种情况,并且您的对象相对较大(具有复杂的对象层次结构),则可能需要 请考虑以下任一内容:spring-doc.cadn.net.cn

  1. 在应用程序域对象中实现 Delta 接口 模型虽然有用,但侵入性很强,或者......spring-doc.cadn.net.cn

  2. 提供 SSDG 的自定义实现org.springframework.session.data.gemfire.support.IsDirtyPredicatestrategy 界面。spring-doc.cadn.net.cn

SSDG 提供了 5 种开箱即用的IsDirtyPredicate策略界面:spring-doc.cadn.net.cn

表 5.IsDirtyPredicate实现
描述 违约

IsDirtyPredicate.ALWAYS_DIRTYspring-doc.cadn.net.cn

新的 Session 属性值始终被视为脏。spring-doc.cadn.net.cn

IsDirtyPredicate.NEVER_DIRTYspring-doc.cadn.net.cn

新的 Session 属性值永远不会被视为脏。spring-doc.cadn.net.cn

DeltaAwareDirtyPredicatespring-doc.cadn.net.cn

当旧值和新值 不同,如果新值的 type 没有实现Delta或新值的Delta.hasDelta()method 返回 truespring-doc.cadn.net.cn

是的spring-doc.cadn.net.cn

EqualsDirtyPredicatespring-doc.cadn.net.cn

如果旧值不等于 新值由Object.equals(:Object)方法。spring-doc.cadn.net.cn

IdentityEqualsPredicatespring-doc.cadn.net.cn

如果旧值与 使用标识等于运算符的新值(即oldValue != newValue).spring-doc.cadn.net.cn

如上表所示,DeltaAwareDirtyPredicate是 SSDG 使用的默认实现。 这DeltaAwareDirtyPredicate自动考虑实现 Apache GeodeDelta接口。然而DeltaAwareDirtyPredicate即使您的应用程序 domain 对象不实现Delta接口。SSDG 会将您的应用程序域对象视为脏 任何时候Session.setAttribute(name, newValue)如果新值与旧值不同,则调用 或新值未实现Delta接口。spring-doc.cadn.net.cn

您只需在 Spring 容器中声明一个 bean 即可更改 SSDG 的脏实现、确定策略 的IsDirtyPredicate接口类型:spring-doc.cadn.net.cn

覆盖 SSDG 的默认值IsDirtyPredicate策略
@EnableGemFireHttpSession
class ApplicationConfiguration {

  @Bean
  IsDirtyPredicate equalsDirtyPredicate() {
    return EqualsDirtyPredicate.INSTANCE;
  }
}
组成

IsDirtyPredicateinterface 还提供了andThen(:IsDirtyPredicate)orThen(:IsDirtyPredicate)方法 编写 2 个或更多IsDirtyPredicate实现,以便组织复杂的逻辑和规则 用于确定应用程序域对象是否脏。spring-doc.cadn.net.cn

例如,您可以将EqualsDirtyPredicateDeltaAwareDirtyPredicate使用 OR 运算符:spring-doc.cadn.net.cn

构成EqualsDirtyPredicateDeltaAwareDirtyPredicate使用逻辑 OR 运算符
@EnableGemFireHttpSession
class ApplicationConfiguration {

  @Bean
  IsDirtyPredicate equalsOrThenDeltaDirtyPredicate() {

    return EqualsDirtyPredicate.INSTANCE
      .orThen(DeltaAwareDirtyPredicate.INSTANCE);
  }
}

您甚至可以实现自己的自定义IsDirtyPredicates基于特定的应用程序域对象类型:spring-doc.cadn.net.cn

特定于应用程序域对象类型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以及 fallback 的默认谓词,如下所示:spring-doc.cadn.net.cn

组合和配置特定于类型IsDirtyPredicates
@EnableGemFireHttpSession
class ApplicationConfiguration {

  @Bean
  IsDirtyPredicate typeSpecificDirtyPredicate() {

    return new CustomerDirtyPredicate()
      .andThen(new AccountDirtyPredicate())
      .andThen(IsDirtyPredicate.ALWAYS_DIRTY);
  }
}

组合和可能性是无穷无尽的。spring-doc.cadn.net.cn

实施自定义时要小心IsDirtyPredicate策略。如果您错误地确定 application domain 对象在实际脏时不是脏的,则不会在 Session delta 中发送 从客户端到服务器。
更改 Session 表示

在内部,Spring Session for Apache Geode 维护 (HTTP) Session 和 Session 的 属性。每种表示形式都基于是否支持 Apache Geode“增量”。spring-doc.cadn.net.cn

由于前面讨论的原因,在使用数据序列化时,只有 Spring Session for Apache Geode 才会启用 Apache Geode 增量传播spring-doc.cadn.net.cn

实际上,该策略是:spring-doc.cadn.net.cn

  1. 如果配置了 Apache Geode 数据序列化,则支持增量,并且DeltaCapableGemFireSessionDeltaCapableGemFireSessionAttributes使用表示。spring-doc.cadn.net.cn

  2. 如果配置了 Apache Geode PDX 序列化,则将禁用增量传播GemFireSessionGemFireSessionAttributes使用表示。spring-doc.cadn.net.cn

可以覆盖 Spring Session for Apache Geode 和用户使用的这些内部表示 来提供自己的 Session 相关类型。唯一严格的要求是 Session 实现 必须实现核心 Spring Sessionorg.springframework.session.Session接口。spring-doc.cadn.net.cn

举个例子,假设你想定义自己的 Session 实现。spring-doc.cadn.net.cn

首先,定义Session类型。也许您的自定义Sessiontype 甚至封装并处理 Session 属性,而不必定义单独的类型。spring-doc.cadn.net.cn

用户定义的 Session 接口实现
class MySession implements org.springframework.session.Session {
  // ...
}

然后,您需要扩展org.springframework.session.data.gemfire.GemFireOperationsSessionRepository类 并覆盖createSession()创建自定义实例的方法Sessionimplementation 类。spring-doc.cadn.net.cn

自定义 SessionRepository 实现创建并返回自定义 Session 类型的实例
class MySessionRepository extends GemFireOperationsSessionRepository {

  @Override
  public Session createSession() {
    return new MySession();
  }
}

如果您提供自己的自定义SessionSerializerimplementation 和 Apache Geode PDX 序列化是 configured,然后您完成了。spring-doc.cadn.net.cn

但是,如果您配置了 Apache Geode 数据序列化,则必须另外提供自定义 实现SessionSerializer接口,并让它直接扩展 Apache Geode 的org.apache.geode.DataSerializer类,或扩展 Spring Session for Apache Geode 的org.springframework.session.data.gemfire.serialization.data.AbstractDataSerializableSessionSerializer类 并覆盖getSupportedClasses():Class<?>[]方法。spring-doc.cadn.net.cn

自定义 Session 类型的自定义 SessionSerializer
class MySessionSerializer extends AbstractDataSerializableSessionSerializer {

  @Override
  public Class<?>[] getSupportedClasses() {
    return new Class[] { MySession.class };
  }
}

不幸getSupportedClasses()无法返回通用的 Spring Sessionorg.springframework.session.Sessioninterface 类型。如果可以,那么我们可以避免显式地覆盖getSupportedClasses()method 开启 定制DataSerializer实现。但是,Apache Geode 的数据序列化框架只能匹配 在确切的类类型上,因为它错误地在内部存储并按名称引用类类型,然后 要求用户覆盖并实现getSupportedClasses()方法。spring-doc.cadn.net.cn

3.7. HttpSession 集成的工作原理

幸运的是,两者都javax.servlet.http.HttpSessionjavax.servlet.http.HttpServletRequest(用于 获取HttpSession) 是接口。这意味着我们可以为每个 API 提供自己的实现。spring-doc.cadn.net.cn

本节描述了 Spring Session 如何提供与javax.servlet.http.HttpSession. 其目的是让用户了解后台发生的事情。此功能已实现 和 integrated 的,因此您无需自己实现此 logic。

首先,我们创建一个自定义javax.servlet.http.HttpServletRequest,它返回javax.servlet.http.HttpSession.它看起来像下面这样:spring-doc.cadn.net.cn

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实现。spring-doc.cadn.net.cn

我们将javax.servlet.http.HttpServletRequest使用 Servlet 的实现FilterSessionRepositoryFilter.伪代码可以在下面找到:spring-doc.cadn.net.cn

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.HttpServletRequestimplementation 导入到FilterChain我们确保 在我们的Filter使用自定义的javax.servlet.http.HttpSession实现。spring-doc.cadn.net.cn

这凸显了为什么 Spring Session 的SessionRepositoryFilter必须放在任何内容之前 它与javax.servlet.http.HttpSession.spring-doc.cadn.net.cn

3.8. HttpSession监听器

Spring Session 支持HttpSessionListener通过翻译SessionCreatedEventSessionDestroyedEventHttpSessionEvent通过声明SessionEventHttpSessionListenerAdapter.spring-doc.cadn.net.cn

要使用此支持,您需要:spring-doc.cadn.net.cn

  • 确保您的SessionRepositoryimplementation 支持并配置为触发SessionCreatedEvent和 'SessionDestroyedEvent' 的 Package。spring-doc.cadn.net.cn

  • 配置SessionEventHttpSessionListenerAdapter作为 Spring bean 进行。spring-doc.cadn.net.cn

  • 注入每个HttpSessionListenerSessionEventHttpSessionListenerAdapterspring-doc.cadn.net.cn

如果您将 HttpSession 中记录的配置支持与 Apache Geode 结合使用, 然后您需要做的就是注册每个HttpSessionListener作为 Bean 进行。spring-doc.cadn.net.cn

例如,假设您希望支持 Spring Security 的并发控制,并且需要使用HttpSessionEventPublisher, 然后您只需添加HttpSessionEventPublisher作为 Bean 进行。spring-doc.cadn.net.cn

3.9. 会话

一个Session是简化的Map的键/值对,支持过期。spring-doc.cadn.net.cn

3.10. SessionRepository

一个SessionRepository负责创建、持久化和访问Sessioninstances 和 state 的spring-doc.cadn.net.cn

如果可能,开发人员不应直接与SessionRepositorySession.相反,开发人员 应该更愿意与SessionRepositorySession间接通过javax.servlet.http.HttpSession,WebSocketWebSession集成。spring-doc.cadn.net.cn

3.11. FindByIndexNameSessionRepository

Spring Session 最基本的 API 用于使用SessionSessionRepository.API 故意非常简单 这样就很容易提供具有基本功能的其他 implementations。spring-doc.cadn.net.cn

一些SessionRepository实现可以选择实现FindByIndexNameSessionRepository也。 例如,Spring Session 的 Apache Geode 支持实现了FindByIndexNameSessionRepository.spring-doc.cadn.net.cn

FindByIndexNameSessionRepository添加单个方法以查找特定用户的所有会话。 这是通过确保名称为FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME中填充了用户名。开发人员有责任确保填充该属性,因为 Spring Session 不知道正在使用的身份验证机制。spring-doc.cadn.net.cn

的一些 implementationFindByIndexNameSessionRepository将提供钩子来自动索引其他会话属性。 例如,许多实现将自动确保当前的 Spring Security 用户名使用 索引名称FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME.spring-doc.cadn.net.cn

3.12. 启用 SpringHttpSession

@EnableSpringHttpSession注释可以添加到任何@Configuration类来公开SessionRepositoryFilter作为 Spring 容器中名为“springSessionRepositoryFilter”的 Bean。spring-doc.cadn.net.cn

为了利用注释,单个SessionRepositorybean 的 bean 中。spring-doc.cadn.net.cn

3.13. 启用 GemFireHttpSession

@EnableGemFireHttpSession注释可以添加到任何@Configuration类代替@EnableSpringHttpSession注解来公开SessionRepositoryFilter作为 Spring 容器中名为 “springSessionRepositoryFilter”,并将 Apache Geode 定位为管理javax.servlet.http.HttpSession州。spring-doc.cadn.net.cn

使用@EnableGemFireHttpSession注解中,额外的配置是开箱即用的,并且 提供了SessionRepositoryinterface 名称为GemFireOperationsSessionRepository.spring-doc.cadn.net.cn

3.14. GemFireOperationsSessionRepository

GemFireOperationsSessionRepository是一个SessionRepository使用 Spring Session 实现的实现 适用于 Apache Geode's_GemFireOperationsSessionRepository.spring-doc.cadn.net.cn

在 Web 环境中,此存储库与SessionRepositoryFilter.spring-doc.cadn.net.cn

此实现支持SessionCreatedEvents,SessionDeletedEventsSessionDestroyedEvents通过SessionEventHttpSessionListenerAdapter.spring-doc.cadn.net.cn

3.14.1. 在 Apache Geode 中使用索引

虽然有关正确定义对 Apache Geode 性能有积极影响的索引的最佳实践 超出了本文档的范围,重要的是要认识到 Spring Session for Apache Geode 会创建 并使用 Indexes 高效地查询和查找 Sessions。spring-doc.cadn.net.cn

Spring Session for Apache Geode 在主体名称上创建 1 个哈希类型的索引。有两个 用于查找 Principal Name 的不同内置策略。第一个策略是 Session 的值 属性,名称为FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME将被索引为相同的 索引名称。spring-doc.cadn.net.cn

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 中使用索引

或者,Spring Session for Apache Geode 将映射 Spring Security 的当前Authentication#getName()自 索引FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME.spring-doc.cadn.net.cn

例如,如果您使用的是 Spring Security,则可以使用以下方法查找当前用户的会话:spring-doc.cadn.net.cn

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-doc.cadn.net.cn

此外,Spring Session for Apache Geode 将在实现 Session 的 地图类型attributes属性(即在任何任意 Session 属性上),当开发人员标识 1 个或多个 命名的 Session 属性,这些属性应由 Apache Geode 编制索引。spring-doc.cadn.net.cn

要索引的 Sessions 属性可以使用indexableSessionAttributes属性@EnableGemFireHttpSession注解。开发人员将此注释添加到他们的 Spring 应用程序中@Configuration类,当他/她希望启用 Spring Session 对HttpSession支持 Apache Geode 的 Apache。spring-doc.cadn.net.cn

String indexName = "name1";

session.setAttribute(indexName, indexValue);
Map<String, Session> idToSessions =
	this.sessionRepository.findByIndexNameAndIndexValue(indexName, indexValue);
仅在@EnableGemFireHttpSession注解的indexableSessionAttributes属性将定义一个 Index。不会为所有其他 Session 属性编制索引。

但是,有一个问题。存储在可索引 Session 属性中的任何值都必须实现java.lang.Comparable<T>接口。如果这些对象值未实现Comparable,然后是 Apache Geode 将在启动时引发错误,当为具有持久 Session 数据的区域定义 Index 时,或者尝试 在运行时为可索引的 Session 属性分配一个不是Comparable,并且 Session 已保存 到 Apache Geode。spring-doc.cadn.net.cn

任何未编入索引的 Session 属性都可以存储非Comparable值。

要了解有关 Apache Geode 基于范围的索引的更多信息,请参阅在映射字段上创建索引spring-doc.cadn.net.cn

要了解有关 Apache Geode 索引的一般信息,请参阅使用索引spring-doc.cadn.net.cn