JaVers是一个轻量级的对象比较/审计框架,非常易于使用。当前的JaVers版本3是用Java 8编写的,只能运行在JRE 8或以上版本。2.9.2是最后一个和Java 7兼容的版本。源代码在Github。
简介
如果你需要实时比较生产环境的处理结果和备份环境的处理结果,或是在新系统中重放生产环境的请求,或者像代码一样对对象进行版本管理,那么JaVers就可以成为你的好朋友。它不仅可以比较对象,也可以将比较结果存储在数据库中以便审计。审计是这样的一种需求:
作为用户,我希望知道谁改变了状态,
是什么时候改变的,以及原先的状态是什么。
本文仅关注于比较部分,对审计部分就不具体展开了。
快速一览
新建Maven工程,往pom.xml中增加dependency,最后的pom.xml看起来就像这样:
假设我们有一个名为的POJO如下:
在函数中如下编写:
即可得到以下输出结果:
大部分的代码都是我们创建对象所用的,可见JaVers非常易于使用。
对象类型
根据DDD,JaVers把要比较的对象分为三种类型:实体(Entity)、值对象(Value Object)和值(Value)。每种类型都有不同的比较方法。值最简单,就是看它们是否是的。实体和值对象都是按属性依次比较。它们俩的区别是实体拥有标识(Entity Id),而值对象并没有。标识不同的实体就会被认为是不同的对象,从而不再继续比较其余的字段。从DDD的角度上严格来说值对象不能单独存在,需要依附于实体。好在JaVers并不教条,值对象也可以用来单独比较。上面的代码其实就是把Staff对象当作值对象来比较。如果我们在类中,给添加一个的注解(所有的注解都在包里),那么比较结果就会不同:
只有当属性相同的时候,这两个对象才会被当成同一实体,从而依次比较其余属性。如果没有权限修改实体以增加注解,也可以用这样的方法来注册,效果相同:
如果的属性和注解都存在,那么以所注册的属性为准。
JaVers完全兼容Groovy,可以参考其文档来了解用例。
自定义比较方式
忽略属性
从业务上说,有些属性新、旧系统本来就不一样,或者是不关心,这时候我们可以在比较中“忽略”这些属性。如果有权限修改要比较的对象类,可以简单地在属性上面增加一个,比较的时候就会将其忽略。相当于黑名单,起到了白名单的效果。如果没有修改类的权限,那么也可以用这样的方法来注册,效果相同:
这里我们注册的是个值对象ValueObject,与上一个例子的实体Entity的区别就是有没有标识属性。
比较算法
一开始细心的读者们就可能注意到了,和的比较结果居然是:
这当然也是可以配置的:
这样的话,结果就变成了:
值得注意的是,这种算法在列表元素过多的时候可能会影响性能。
定制比较
我们可以注册自定义的比较器,例如,如果在业务上认为两个类型的和相等,这时候我们可以注册一个如下的类:
是当前比较对象的标识,如值对象的或是以name为标识的实体的。是当前比较的属性。可以通过这两个值来设置比较属性的黑名单或是白名单。然后注册进JaVers就好了:
需要注意的是,与是不同的,如果中的是类型,那么需要在调用时传入。自定义的比较在许多场合都比较有用,比如String类型的不同格式的日期等。
关联字段比较
关联字段就是说,如果几个字段之间有关联,我们就认为它们一样。比如说我们虚构一个需求:对于一个拥有和的类来说,如果也就是面积相等,我们就认为它们相等。在这种情况下,JaVers似乎并没有原生提供关联字段比较的办法。有一种办法是新建一个包装类,比如说,里面有一个和一个字段,分别赋值为要比较的对象和其。注册的时候,把类的和忽略即可。如果有更复杂的需求,例如当面积不同时需要报和不同而不是不同,那也可以通过生成多个对象,并多次调用来解决。方法返回的是一个对象,从中可以很方便地查看某些字段是否存在变化。就是要多写点代码咯。
领取专属 10元无门槛券
私享最新 技术干货