Spring认证中国教育管理中心-Apache Geode的Spring数据教程二十二
发布于 2 年前 作者 lei55 4301 次浏览 来自 分享

原标题:Spring认证中国教育管理中心-Apache Geode 的 Spring 数据教程二十二(Spring中国教育管理中心)

Apache Geode 的 Spring 数据教程二十二
9.2.1.按区域类型的实体映射
除了@Region注释,为Apache的Geode春数据也承认特定类型的区域映射注释: @ClientRegion@LocalRegion@PartitionRegion,和@ReplicateRegion

在功能上,这些注释的处理方式@Region与 SDG 映射基础设施中的通用注释完全相同。然而,这些额外的映射注解在 Spring Data for Apache Geode 的注解配置模型中很有用。结合@
EnableEntityDefinedRegionsSpring@Configuration注解类上的配置注解,可以在本地缓存中生成Region,无论应用是client还是peer。

这些注释让您可以更具体地了解您的应用程序实体类应该映射到什么类型的 Region,并且还会影响 Region 的数据管理策略(例如,分区 — 也称为分片 — 与复制数据)。

将这些特定于类型的区域映射注释与 SDG 注释配置模型结合使用,您不必在配置中明确定义这些区域。

9.3.存储库映射
除了使用@Region实体类上的@Region注解指定存储实体的 Region 之外,您还可以在实体的Repository接口上指定注解。有关更多详细信息,请参阅Apache Geode 存储库的 Spring 数据。

但是,假设您想Person在多个 Apache Geode 区域(例如,People 和Customers)中存储一条记录。然后你可以定义你相应的Repository接口扩展如下:

@Region(“People”)
public interface PersonRepository extends GemfireRepository<Person, String> {

}

@Region(“Customers”)
public interface CustomerRepository extends GemfireRepository<Person, String> {

}
然后,单独使用每个存储库,您可以将实体存储在多个 Apache Geode 区域中,如以下示例所示:

@Service
class CustomerService {

CustomerRepository customerRepo;

PersonRepository personRepo;

Customer update(Customer customer) {
customerRepo.save(customer);
personRepo.save(customer);
return customer;
}
您甚至可以将update服务方法包装在 Spring 管理的事务中,作为本地缓存事务或全局事务。

9.4.MappingPdxSerializer
Spring Data for Apache Geode 提供了一个PdxSerializer 名为的自定义实现MappingPdxSerializer,它使用 Spring Data 映射元数据来自定义实体序列化。

序列化程序还允许您使用 Spring DataEntityInstantiator抽象自定义实体实例化。默认情况下,序列化程序使用
ReflectionEntityInstantiator,它使用映射实体的持久性构造函数。持久性构造函数要么是默认构造函数,要么是单独声明的构造函数,要么是显式用@PersistenceConstructor.

为了为构造函数参数提供参数,序列化器从提供的 中读取具有命名构造函数参数的字段,使用 Spring 的@Value注解 明确标识PdxReader,如下面的示例所示:

示例 4. 使用@Value实体构造函数参数

public class Person {

public Person(@Value("#root.thing") String firstName, @Value(“bean”) String lastName) {

}
}
以这种方式注释的实体类具有从 读取PdxReader并作为构造函数参数的参数值传递的“事物”字段firstname。的值lastName是一个名为“bean”的 Spring bean。

除了Apache Geode 提供的自定义实例化逻辑和策略之外EntityInstantiators,MappingPdxSerializer它还提供了远远超出 Apache Geode 自身的功能
ReflectionBasedAutoSerializer。

虽然 Apache
GeodeReflectionBasedAutoSerializer方便地使用 Java 反射来填充实体并使用正则表达式来识别序列化器应该处理(序列化和反序列化)的类型,但与 不同MappingPdxSerializer,它不能执行以下操作:

为PdxSerializer每个实体字段或属性名称和类型注册自定义对象。
方便地识别 ID 属性。
自动处理只读属性。
自动处理瞬态属性。
允许以null类型安全的方式进行更健壮的类型过滤(例如,不限于仅使用正则表达式表达类型)。
我们现在MappingPdxSerializer更详细地探讨 的每个功能。

9.4.1.自定义 PdxSerializer 注册
这MappingPdxSerializer使您能够PdxSerializers根据实体的字段或属性名称和类型注册自定义。

例如,假设您已经定义了一个建模 a 的实体类型User,如下所示:

package example.app.security.auth.model;

public class User {

private String name;

private Password password;


}
虽然用户名可能不需要任何特殊逻辑来序列化值,但另一方面,序列化密码可能需要额外的逻辑来处理字段或属性的敏感性质。

也许您想在通过网络在客户端和服务器之间发送值时保护密码,而不仅仅是 TLS,并且您只想存储加盐哈希。使用时MappingPdxSerializer,可以注册一个自定义PdxSerializer来处理用户的密码,如下:

示例 5.PdxSerializers按 POJO 字段/属性类型注册自定义

Map<?, PdxSerializer> customPdxSerializers = new HashMap<>();

customPdxSerializers.put(Password.class, new SaltedHashPasswordPdxSerializer());

mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);

SaltedHashPasswordPdxSerializer使用Password 应用程序域模型类型注册应用程序定义的实例后,MappingPdxSerializer将咨询自定义PdxSerializer 以序列化和反序列化所有Password对象,而不管包含对象(例如,User)。

但是,假设您想自定义的序列化Passwords只User对象。为此,您可以通过指定字段或属性的完全限定名称PdxSerializer来为该User类型注册自定义Class’s,如以下示例所示:

示例 6.PdxSerializers通过 POJO 字段/属性名称注册自定义

Map<?, PdxSerializer> customPdxSerializers = new HashMap<>();

customPdxSerializers.put(“example.app.security.auth.model.User.password”, new SaltedHashPasswordPdxSerializer());

mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);
请注意使用完全限定的字段或属性名称(即
example.app.security.auth.model.User.password)作为自定义PdxSerializer注册键。

你可以通过使用一个更合乎逻辑的代码片段,如下面的结构注册码: User.class.getName().concat(".password");。我们在前面显示的示例中推荐了这一点。前面的示例试图尽可能明确地说明注册的语义。

9.4.2.映射 ID 属性
与 Apache Geode 一样
ReflectionBasedAutoSerializer,SDGMappingPdxSerializer也能够确定实体的标识符。但是,MappingPdxSerializer这是通过使用 Spring Data 的映射元数据来实现的,特别是通过使用 Spring Data 的@Id注释查找指定为标识符的实体属性 。或者,任何名为“id”的字段或属性,未明确用 注释@Id,也被指定为实体的标识符。

例如:

class Customer {

@Id
Long id;


}
在这种情况下,该Customer id字段被标记为PDX类型元数据中的标识符字段,在序列化过程中调用
PdxWriter.markIdentifierField(:String) 该PdxSerializer.toData(…)方法时使用 。

9.4.3.映射只读属性
当您的实体定义只读属性时会发生什么?

首先,了解什么是“只读”属性很重要。如果您按照JavaBeans规范定义 POJO (如 Spring 所做的那样),您可以定义一个具有只读属性的 POJO,如下所示:

package example;

class ApplicationDomainType {

private AnotherType readOnly;

public AnotherType getReadOnly() [
this.readOnly;
}


}
该readOnly属性是只读的,因为它不提供 setter 方法。它只有一个 getter 方法。在这种情况下,readOnly属性(不要与readOnly DomainType字段混淆)被认为是只读的。

其结果是,在MappingPdxSerializer将不会尝试填充的实例时设置此属性的一个值 ApplicationDomainType的PdxSerializer.fromData(:Class<ApplicationDomainType>, :PdxReader)反序列化过程的方法,尤其是当的值是存在于PDX序列字节。

这在您可能要返回某个实体类型的视图或投影并且只想设置可写状态的情况下很有用。也许实体的视图或投影基于授权或其他一些标准。关键是,您可以根据应用程序的用例和要求来利用此功能。如果您希望始终写入字段或属性,只需定义一个 setter 方法。

9.4.4.映射瞬态属性
同样,当您的实体定义transient属性时会发生什么?

transient在序列化实体时,您希望实体的字段或属性不会被序列化为 PDX。这正是发生的事情,不像 Apache Geode 自己的
ReflectionBasedAutoSerializer,它通过 Java 反射序列化对象可访问的所有内容。

该MappingPdxSerializer不会序列化是合格的为暂时性的任何字段或属性,无论是使用Java本身的transient关键字(在类的实例字段的情况下)或者通过使用 @Transient 对字段或属性春季数据注解。

例如,您可以定义一个具有瞬态字段和属性的实体,如下所示:

package example;

class Process {

private transient int id;

private File workingDirectory;

private String name;

private Type type;

@Transient
public String getHostname() {

}


}
无论是Process id现场还是可读的hostname财产被写入PDX。

9.4.5.按类类型过滤
与 Apache Geode 类似
ReflectionBasedAutoSerializer,SDGMappingPdxSerializer允许您过滤序列化和反序列化的对象类型。

但是,与 Apache
GeodeReflectionBasedAutoSerializer使用复杂的正则表达式来表达序列化程序处理的类型不同,SDGMappingPdxSerializer使用更强大的 java.util.function.Predicate接口和 API 来表达类型匹配标准。

如果你喜欢使用正则表达式,你可以实现一个Predicateusing Java 的 正则表达式支持。

关于Java的漂亮的部分Predicate界面,你可以撰写Predicates通过使用便捷和适当的API方法,包括: and(:Predicate), or(:Predicate),和negate()。

以下示例显示了PredicateAPI 的运行情况:

Predicate<Class<?>> customerTypes =
type -> Customer.class.getPackage().getName().startsWith(type.getName()); // Include all types in the same package as Customer

Predicate includedTypes = customerTypes
.or(type -> User.class.isAssignble(type)); // Additionally, include User sub-types (e.g. Admin, Guest, etc)

mappingPdxSerializer.setIncludeTypeFilters(includedTypes);

mappingPdxSerializer.setExcludeTypeFilters(
type -> !Reference.class.getPackage(type.getPackage()); // Exclude Reference types
Class传递给您的 任何对象Predicate都保证不是null.

SDGMappingPdxSerializer包括对包含和排除类类型过滤器的支持。

排除类型过滤
默认情况下,SDG 的MappingPdxSerializer寄存器预定义Predicates该过滤器,或从以下包中排除类型:

java.*
com.gemstone.gemfire.*
org.apache.geode.*
org.springframework.*
此外,调用 和调用时的MappingPdxSerializer过滤器null对象PdxSerializer.toData(:Object, :PdxWriter)null调用PdxSerializer.fromData(:Class<?>, :PdxReader)方法时的类类型。

很容易为其他类类型或整个类型包添加排除项,只需定义 aPredicate 并将其添加到MappingPdxSerializer前面所示的。


MappingPdxSerializer.setExcludeTypeFilters(:Predicate<Class<?>>)方法是可加的,这意味着它将您的应用程序定义的类型过滤器与Predicates上面使用该Predicate.and(:Predicate<Class<?>>)方法指示的现有的、预定义的类型过滤器组合在一起。

但是,如果您想包含java.security Principal被排除类型过滤器隐式排除的类类型(例如,)怎么办?请参阅包含类型过滤。

包含类型过滤
如果要显式包含类类型,或覆盖隐式排除应用程序所需的类类型的类类型过滤器(例如,java.security.Principal默认情况下使用java.* 包排除类型过滤器将排除在 上MappingPdxSerializer),则只需定义适当的Predicate并将其添加到使用
MappingPdxSerializer.setIncludeTypeFilters(:Predicate<Class<?>>)方法的序列化程序中,如下所示:

Predicate<Class<?>> principalTypeFilter =
type -> java.security.Principal.class.isAssignableFrom(type);

mappingPdxSerializer.setIncludeTypeFilters(principalTypeFilters);
同样,该
MappingPdxSerializer.setIncludeTypeFilters(:Predicate<Class<?>>)方法,如setExcludeTypeFilters(:Predicate<Class<?>>),是可加的,因此使用 组成任何传递类型过滤器Predicate.or(:Predicate<Class<?>>)。这意味着你可以打电话setIncludeTypeFilters(:Predicate<Class<?>>) 根据需要多次。

当包含类型过滤器存在时,MappingPdxSerializer当类类型未被隐式排除或当类类型被显式包含时,以返回 true 的方式决定是否反/序列化类类型的实例。然后,类类型的实例将被适当地序列化或反序列化。

例如,当一个类型过滤器Predicate<Class<Principal>>如前面所示被显式注册时,它会取消对java.*包类型的隐式排除类型过滤器。

回到顶部