3. HttpSession 集成

Spring Session 提供与javax.servlet.http.HttpSession.这意味着开发人员 可以将HttpSession实现,其实现由 Spring Session 支持。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

  • HttpSession - 启用HttpSession聚类(即复制 实现高可用性),而无需绑定到特定于应用程序容器的解决方案。spring-doc.cadn.net.cn

  • REST API - 允许在协议标头中提供会话 ID 以使用 RESTful API。spring-doc.cadn.net.cn

  • WebSocket - 提供保留HttpSession在接收 WebSocket 消息时处于活动状态。spring-doc.cadn.net.cn

  • WebSession - 允许替换 Spring WebFlux 的WebSession以应用程序容器中立的方式。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 堆要求。 使用客户端-服务器拓扑使应用程序能够独立管理(例如复制)应用程序状态 来自其他应用程序流程。spring-doc.cadn.net.cn

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

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

Apache Geode 客户端-服务器基于 Java 的配置

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

HttpSession with Apache Geode (Client-Server) 提供了一个工作示例,演示了如何 将 Spring Session 与 Apache Geode 集成以管理HttpSession使用 Java 配置的状态。你可以阅读 通过下面的基本集成步骤进行作,但鼓励您按照详细的“HttpSession”进行作 与您自己的应用程序集成时使用 Apache Geode (Client-Server) 指南
Spring Java 配置

添加所需的依赖项和存储库声明后,我们可以创建 Spring 配置。 Spring 配置负责创建 ServletFilterHttpSession具有由 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.此外,我们还调整了一些基本的“默认”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:spring-doc.cadn.net.cn

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

  • indexableSessionAttributes- 按名称标识应为查询目的编制索引的会话属性。 只有按名称显式标识的会话属性才会被编制索引。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).此属性仅在配置服务器时使用Regions, 或者当采用 P2P 拓扑时。spring-doc.cadn.net.cn

重要的是要记住,Apache Geode 客户端Region名称必须与服务器匹配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 (可选)然后,GemFireServer类的注释是@EnableGemFireHttpSession创建必要的 服务器端Region(默认情况下,“ClusteredSpringSessions”)用于存储HttpSession州。这一步是 可选,自会话Region可以手动创建,也许可以使用外部方式。 用@EnableGemFireHttpSession方便快捷。
Apache Geode 客户端-服务器基于 XML 的配置

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

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

添加所需的依赖项和存储库声明后,我们可以创建 Spring 配置。 Spring 配置负责创建一个Servlet Filterjavax.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 属性。在这种情况下,我们只是 使用特定于应用程序的系统属性设置 Apache Geode 的“日志级别”,默认为“警告” 如果未指定。
2 我们必须创建一个 Apache Geode 的实例ClientCache.我们用我们的gemfireProperties.
3 然后我们配置一个Pool在我们的客户端/服务器拓扑中与 Apache Geode 服务器通信的连接数。 在我们的配置中,我们对超时、连接数等使用合理的设置。此外,我们的Pool已配置为直接连接到服务器(使用嵌套的gfe:server元素)。
4 最后,一个GemFireHttpSessionConfigurationbean 被注册以启用 Spring Session 功能。
在典型的 Apache Geode 生产部署中,集群可能包括数百或数千个 的服务器(又称数据节点),客户端更常见的是连接到 1 个或多个运行的 Apache Geode 定位器 在同一集群中。定位器将有关集群中可用服务器的元数据传递给客户端,即单个 服务器负载以及哪些服务器具有客户端感兴趣的数据,这对于直接、 单跳数据访问和延迟敏感型应用程序。有关客户端/服务器部署的更多详细信息,请参阅 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 属性。在这种情况下,我们只是 使用特定于应用程序的系统属性设置 Apache Geode 的“日志级别”,默认为“警告” 如果未指定。
2 我们必须配置一个 Apache Geode 对等方Cache实例。我们使用 Apache Geode 属性初始化它。
3 接下来,我们定义一个CacheServer具有合理的配置bind-addressport由我们的缓存客户端使用 应用程序连接到服务器并发送会话状态。
4 最后,我们启用了我们在客户端 XML 配置中声明的相同 Spring Session 功能 通过注册GemFireHttpSessionConfiguration,除了我们设置了会话过期超时 到 30 秒。我们稍后会解释这意味着什么。

Apache Geode 服务器通过以下内容进行引导: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. 基于 Commentation 的容器配置[Spring 的 Commentation 配置支持]。
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

src/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

src/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.2.2. Apache Geode 点对点 (P2P)

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

这种方法的一个优点是应用程序接近应用程序的状态(即其数据), 特别是HttpSession州。然而,还有其他有效的方法可以实现类似的目标 数据相关计算,例如使用 Apache Geode 的函数执行。 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 with Apache Geode (P2P) 提供了一个工作示例,演示了如何 将 Spring Session 与 Apache Geode 集成以管理HttpSession使用 Java 配置的状态。你可以阅读 通过下面的基本集成步骤进行作,但鼓励您按照详细的“HttpSession”进行作 与您自己的应用程序集成时使用 Apache Geode (P2P) 指南
Spring Java 配置

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

Spring 配置负责创建一个Servlet Filterjavax.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 然后,Config类的注释是@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- 按名称标识应为查询目的编制索引的会话属性。 只有按名称显式标识的会话属性才会被编制索引。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).此属性仅在配置服务器时使用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

src/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 集成以管理HttpSession状态。你可以阅读 通过下面的基本集成步骤进行作,但鼓励您按照详细的“HttpSession”进行作 与您自己的应用程序集成时使用 XML Guide 使用 Apache Geode (P2P)。
Spring XML 配置

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

Spring 配置负责创建一个Servlet Filterjavax.servlet.http.HttpSession具有由 Spring Session 和 Apache Geode 支持的实现。spring-doc.cadn.net.cn

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

src/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 属性。在这种情况下,我们只是 使用特定于应用程序的系统属性设置 Apache Geode 的“日志级别”,默认为“警告” 如果未指定。
2 我们必须配置一个 Apache Geode 对等方Cache实例。我们使用 Apache Geode 属性初始化它。
3 最后,我们通过注册一个实例来启用 Spring Session 功能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

src/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

src/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

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

表 4.众所周知的、记录在案的属性@EnableGemFireHttpSession注释属性。
属性 注释属性 描述 默认值

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

EnableGemFireHttpSession.poolNamespring-doc.cadn.net.cn

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

宝石火池spring-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

客户端区域快捷方式.PROXYspring-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

区域快捷方式.PARTITIONspring-doc.cadn.net.cn

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

EnableGemFireHttpSession.indexableSessionAttributesspring-doc.cadn.net.cn

要在会话区域中编制索引的会话属性的逗号分隔列表。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-非活动间隔秒spring-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

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

集群 SpringSessionsspring-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

SessionPdx序列化器spring-doc.cadn.net.cn

所有属性都记录在@EnableGemFireHttpSession注释属性 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) 覆盖该值并将到期时间设置为3600秒,或 60 分钟。spring-doc.cadn.net.cn

请记住,属性在运行时覆盖注释属性值。

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 或 Apache Geode 的 Spring Session。

3.4. 配置HttpSession使用 Apache Geode 和配置器的管理

除了属性之外,Spring Session for Apache Geode 还允许您调整 使用 Apache Geode 的 Spring 会话SpringSessionGemFireConfigurer接口。该接口定义了一个 包含每个默认方法的合约@EnableGemFireHttpSession可以覆盖的注释属性 以调整配置。spring-doc.cadn.net.cn

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

例如,要像之前一样调整客户端区域数据管理策略和会话过期超时, 使用以下内容: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;
      }
    };
  }
}

当然,这个例子不是很有创意。您当然可以使用更复杂的逻辑来确定 每个配置属性的配置。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 将解析@Value注释属性占位符值或 SpEL 表达式。 但是,如果您不使用 Spring Boot,则必须显式注册静态PropertySourcesPlaceholderConfigurerbean 定义。

但是,您只能声明 1SpringSessionGemFireConfigurerbean 一次在 Spring 容器中,除非 您还在使用 Spring 配置文件或标记了多个配置文件中的 1 个SpringSessionGemFireConfigurer豆作为主要 通过使用 Spring 的@Primary上下文注释。spring-doc.cadn.net.cn

3.4.1. 配置优先级

一个SpringSessionGemFireConfigurer优先于@EnableGemFireHttpSession注释属性 或任何众所周知且有文档记录的 Apache Geode 属性的 Spring Session (例如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. 记录了 Apache Geode 属性的 Spring 会话(请参阅相应的@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()方法,Apache Geode 区域的名称 管理HttpSession状态将不由配置器确定。spring-doc.cadn.net.cn

示例

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

Apache Geode 配置的 Spring 会话示例
@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. 弹簧靴application.propertiesspring-doc.cadn.net.cn

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 小时。spring-doc.cadn.net.cn

由于“sessionExpirationTimeoutConfigurer”Bean 不会覆盖getRegionName()方法,会话区域 名称将由属性(即spring.session.data.gemfire.session.region.name),设置为“会话”, 它覆盖了隐式的@EnableGemFireHttpSession.regionNameannotation 属性的默认值为 “ClusteredSpringSessions”。spring-doc.cadn.net.cn

@EnableGemFireHttpSession.poolName注释属性的值“DEFAULT”将确定池的名称 在客户端和服务器之间发送区域作以管理服务器上的会话状态时使用,因为两者都不是 相应的属性(即 spring.session.data.gemfire.cache.client.pool.name')被设置,也没有 这SpringSessionGemFireConfigurer.getPoolName()方法被“sessionExpirationTimeoutConfigurer”bean覆盖。spring-doc.cadn.net.cn

最后,用于管理会话状态的客户端区域将具有PROXY,默认值 值@EnableGemFireHttpSession.clientRegionShortcutannotation 属性,该属性未显式设置,也 是相应的属性(即spring.session.data.gemfire.cache.client.region.shortcut) 来表示此属性。 而且,由于SpringSessionConfigurer.getClientRegionShortcut()方法未被覆盖,则使用默认值。spring-doc.cadn.net.cn

3.5. Apache Geode 过期

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

但是,如果你对会话状态管理和过期有特定于应用程序的要求,并且使用 默认的空闲超时 (TTI) 过期策略不足以满足您的用例 (UC)?spring-doc.cadn.net.cn

现在,Spring Session for Apache Geode 支持特定于应用程序的自定义过期策略。作为应用程序 developer,您可以指定自定义规则来管理由 Spring Session 管理的会话的过期时间,并由 阿帕奇晶洞。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

    }
}

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

使用@EnableGemFireHttpSession注解sessionExpirationPolicyBeanName属性来配置 这SessionExpirationPolicybean 实现会话过期的自定义应用程序策略和规则。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
    }
}

然后,在应用程序类中,简单地声明以下内容: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 并覆盖getSessionExpirationPolicyBeanName()方法。

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

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

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

在引擎盖下,SessionExpirationPolicy被改编到 Apache Geode 的实例中CustomExpiry接口。 本届Spring SessionCustomExpiry然后,对象设置为会话区域的自定义条目空闲超时过期策略
在到期确定期间,CustomExpiry.getExpiry(:Region.Entry<String, Session>):ExpirationAttributes每次运行过期线程时,都会为区域中的每个条目(即会话)调用方法,这反过来又会调用 调用我们的SessionExpirationPolicy.determineExpirationTimout(:Session):Optional<Duration>方法。 返回的java.time.Duration转换为秒,并用作ExpirationAttributesCustomExpiry.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接口。spring-doc.cadn.net.cn

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

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属性(如果设置)或从任何SpringSessionGemFireConfigurerbean 在 Spring 应用程序上下文中声明,作为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)。除了处理固定持续时间到期外,还要谨慎地考虑 并应用默认的空闲过期超时。spring-doc.cadn.net.cn

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

相反,如果用户忙了整整 40 分钟,从而保持会话处于活动状态,从而避免了 30 分钟 空闲过期超时,然后离开,那么我们的固定持续时间过期超时应该启动并过期 用户的会话权限为 60 分钟,即使用户的空闲过期超时要到 70 分钟才会发生 在(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 分钟的固定持续时间过期超时进行初始化。因此,用户会话将 在空闲超时(默认为 30 分钟)或固定超时(配置为 60 分钟)后过期, 以先发生者为准。spring-doc.cadn.net.cn

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

3.5.3.SessionExpirationPolicy链接

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

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

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

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

3.6. Apache Geode 序列化

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

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

在服务器端,会话状态可能分布在集群中的多个服务器(数据节点)上进行复制 数据并保证会话状态的高可用性。使用 Apache Geode 时,可以对数据进行分区, 或分片,并且可以指定冗余级别。分发数据进行复制时,还必须 序列化以在集群中的对等节点之间传输会话状态。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

但是,每当数据通过线路传输或持久化/溢出时,数据序列化都会产生 CPU 损失 并从磁盘访问,因为接收端执行反序列化。事实上,每当使用增量传播时,都必须在接收端对对象进行反序列化,以便应用“增量”。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 开始实现 维护一个“类型注册表”,其中包含序列化和存储在 使用 PDX 的 Apache Geod。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 序列化对象才能应用增量。 请记住,调用一种方法来应用增量,这首先违背了使用 PDX 的目的。spring-doc.cadn.net.cn

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

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

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

例如,考虑对序列化为 PDX 的以下 Java 类型的对象进行 OQL 查询...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接口 并且您可能将数据序列化框架与 PDX 结合使用。spring-doc.cadn.net.cn

虽然可以将 Java 序列化数据序列化和 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 的增量传播功能,因为会话的 状态可以任意大。spring-doc.cadn.net.cn

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

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

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

@EnableGemFireHttpSession注释引入了新的 sessionSerializerBeanName用户认为 可用于配置在Spring容器中声明和注册的bean的名称,实现所需的 序列化策略。Spring Session for Apache Geode 使用序列化策略进行序列化 会话状态。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 的应用程序一样 配置类,具有:spring-doc.cadn.net.cn

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

将序列化策略更改为数据序列化是一件简单的事情,而是通过将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 Boot、启用 Spring Session 的应用程序一起使用。spring-doc.cadn.net.cn

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

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

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

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

春季课程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对象。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

这些参数提供给SessionSerializer框架自动实现,并作为 前面提到的,基于配置的底层 Apache Geode 序列化策略。spring-doc.cadn.net.cn

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

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

实际上,它允许用户自定义会话状态的哪些方面实际被序列化和存储 在 Apache Geode 中。应用程序开发人员可以提供自己的自定义、特定于应用程序SessionSerializer实现,在 Spring 容器中将其注册为 bean,然后将其配置为 Spring Session 使用 让 Apache Geode 序列化会话状态,如下所示: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接口 直接不从 Apache Geode 提供的抽象基类的 Spring Session 之一扩展,相关 到 Apache Geode 的序列化框架之一,则 Apache Geode 的 Spring Session 将包装用户的 习惯SessionSerializerorg.springframework.session.data.gemfire.serialization.pdx.support.PdxSerializerSessionSerializerAdapter并将其注册为 Apache Geodeorg.apache.geode.pdx.PdxSerializer.spring-doc.cadn.net.cn

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

这是通过获取当前注册的任何PdxSerializer实例并组合它 使用PdxSerializerSessionSerializerAdapter包装用户的自定义应用程序SessionSerializer实现并重新注册这个“复合" PdxSerializer在 Apache Geode 缓存上。“复合" PdxSerializer实现由 Spring Session 为 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

当然,您可以强制将底层 Apache Geode 序列化策略与自定义SessionSerializer通过执行以下作之一来实现:spring-doc.cadn.net.cn

  1. 自定义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。spring-doc.cadn.net.cn

  2. 自定义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。spring-doc.cadn.net.cn

  3. 最后,用户可以创建自定义SessionSerializer实现与之前一样,没有指定哪个 Apache Geode 序列化框架,因为自定义SessionSeriaizer实现不实现 任何 Apache Geode 序列化接口或从 Apache Geode 提供的任何 Spring Session 扩展 抽象基类,并且仍然将其注册为 Apache Geode 中的DataSerializer通过声明 类型为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, 任何中性习俗SessionSerializer实施将被视为并注册为DataSerializer在 Apache Geode 中。spring-doc.cadn.net.cn

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

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

使用 DataSerialization 框架作为序列化策略时,从 您的 Web 应用程序客户端到服务器,则必须使用 Spring 会话正确配置服务器 用于表示 (HTTP) 会话及其内容的 Apache Geode 类类型。这意味着包括 服务器类路径上的 Spring JAR。spring-doc.cadn.net.cn

此外,使用 DataSerialization 可能还需要包含包含应用程序域的 JAR。 由 Web 应用程序使用并作为会话属性值放入 (HTTP) 会话的类, 特别是在以下情况下: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) 会话中的应用程序域对象类型在某些 形式或其他形式。但是,您并不严格要求使用 DataSerialization,也不一定 如果出现以下情况,则需要在服务器类路径上具有应用程序域对象类型: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 中注册,以识别同一应用程序 域对象类型(即A),那么 Apache Geode 将使用 PDX 来序列化“A”,而不是 Java 序列化, 在这种情况下。spring-doc.cadn.net.cn

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

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

配置

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

阿帕奇晶洞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* 中启动服务器:spring-doc.cadn.net.cn

使用 Gfsh 启动服务器
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 文件添加到服务器类路径中。spring-doc.cadn.net.cn

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

自定义更改检测

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

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

默认情况下,任何时候Session.setAttribute(name, value)调用时,Session 属性被视为“脏” 并将在客户端和服务器之间的增量中发送。即使应用程序域对象 没有改变。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.IsDirtyPredicate策略接口。spring-doc.cadn.net.cn

开箱即用,SSDG 提供了 5 个实现的IsDirtyPredicate策略接口:spring-doc.cadn.net.cn

表 5.IsDirtyPredicate实现
描述 默认值

IsDirtyPredicate.ALWAYS_DIRTYspring-doc.cadn.net.cn

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

IsDirtyPredicate.NEVER_DIRTYspring-doc.cadn.net.cn

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

DeltaAwareDirtyPredicatespring-doc.cadn.net.cn

当旧值和新值时,新会话属性值被视为脏 如果新值的类型未实现Delta或新值的Delta.hasDelta()方法返回 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自动考虑实现的应用程序域对象 阿帕奇晶洞Delta接口。然而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;
  }
}
组成

IsDirtyPredicate接口还提供了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以及回退的默认谓词,如下所示: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策略。如果您错误地确定您的 应用程序域对象在实际脏时不是脏的,则不会在会话增量中发送 从客户端到服务器。
更改会话表示

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

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

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

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

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

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

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

首先,定义Session类型。也许是你的习惯Session类型甚至封装并处理 Session 属性,而无需定义单独的类型。spring-doc.cadn.net.cn

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

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

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

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

如果您提供自己的自定义SessionSerializer实现和 Apache Geode PDX 序列化是 配置完毕,然后就完成了。spring-doc.cadn.net.cn

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

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

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

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

3.7. HttpSession 集成的工作原理

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

本节介绍 Spring Session 如何提供透明的集成javax.servlet.http.HttpSession. 目的是让用户了解幕后发生的事情。此功能已实现 并集成,因此您无需自己实现此逻辑。

首先,我们创建一个自定义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.HttpServletRequest实现到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. HttpSessionListener

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

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

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

例如,假设您想要支持 Spring Security 的并发控制,并且需要使用HttpSessionEventPublisher, 然后你可以简单地添加HttpSessionEventPublisher作为豆子。spring-doc.cadn.net.cn

3.9. 会话

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

3.10. 会话存储库

一个SessionRepository负责创建、持久化和访问Session实例和状态。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 故意非常简单 以便轻松提供具有基本功能的附加实现。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

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

3.12. EnableSpringHttpSession

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

为了利用注释,单个SessionRepository必须提供 bean。spring-doc.cadn.net.cn

3.13. EnableGemFireHttpSession

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

使用@EnableGemFireHttpSession注释,其他配置是开箱即用的导入,同时 提供了 Apache Geode 特定的SessionRepository接口命名,GemFireOperationsSessionRepository.spring-doc.cadn.net.cn

3.14. GemFireOperationsSession存储库

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 会创建 并使用索引来有效地查询和查找会话。spring-doc.cadn.net.cn

开箱即用的 Spring Session for Apache Geode 在主体名称上创建 1 个哈希类型索引。有两个 用于查找主体名称的不同内置策略。第一种策略是会话的值 属性,名称为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 一起使用

或者,Apache Geode 的 Spring Session 将映射 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

可以使用indexableSessionAttributes属性@EnableGemFireHttpSession注解。开发人员将此注释添加到他们的 Spring 应用程序中@Configurationclass 当他/她希望启用 Spring Session 对HttpSession后盾 阿帕奇晶洞。spring-doc.cadn.net.cn

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

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

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

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