使用场景之一Jacksonmixins用于实现在声明和定义目标类时为目标类添加Jackson注解的效果。特别是当我们使用第三方库的时候,这个机制会特别有用。接下来我们展示一些实际使用场景的例子:以springsecurity为例假设我们要反序列化这个类:packageorg.springframework.security.web.csrf;·······publicfinalclassDefaultCsrfTokenimplementsCsrfToken{private最终字符串标记;私有最终字符串参数名;私有最终字符串标题名;······publicDefaultCsrfToken(StringheaderName,StringparameterName,Stringtoken){Assert.hasLength(headerName,"headerNamecannotbenullorempty");Assert.hasLength(parameterName,"parameterNamecannotbenullorempty");Assert.hasLength(token,"token不能为null或为空");this.headerName=headerName;this.parameterName=parameterName;this.token=令牌;}······}com.fasterxml.jackson.databind.exc.InvalidDefinitionException:没有找到类org.springframework.security.web.csrf的dserializer,也没有发现创建BeanDserializer的属性(为了避免异常,禁用SerializationFeature.FAIL_ON_EMPTY_BEANS)我们不能反序列化这两个类,因为这是一个典型的不可变类,所有的属性字段都在构造函数中初始化并且jackson默认的反序列化策略需要一个无参数的构造函数,并且提供了一个字段的自省(注1)函数.如果要改变反序列化策略,jackson需要我们在对象上添加相应的注解。现在让我们创建一个mixin类来解决这个问题!在我们的mixin中,我们会声明反序列化需要的注解:packageorg.springframework.security.web.jackson2;······@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS,include=JsonTypeInfo.As.PROPERTY,property="@class")@JsonIgnoreProperties(ignoreUnknown=true)classDefaultCsrfTokenMixin{·······@JsonCreatorpublicDefaultCsrfTokenMixin(@JsonProperty("headerName")StringheaderName,@JsonProperty("parameterName")StringparameterName,@JsonProperty("token")Stringtoken){}}在我们创建了一个mixin类并声明了typeInfo信息和要用于它的构造函数信息之后,我们需要告诉Jackson使用我们的Mixin。为此,我们需要通过jackson的模块扩展机制,现实自己的扩展器,告诉jackson需要使用我们的mixin:/***Jacksonmoduleforspring-security-web。该模块注册{@linkDefaultCsrfTokenMixin}和*{@linkPreAuthenticatedAuthenticationTokenMixin}。如果默认情况下没有启用默认类型,那么它将启用*它,因为需要类型信息才能正确序列化/反序列化对象。*为了使用这个模块,只需将这个模块添加到你的ObjectMapper配置中。**
*ObjectMapper映射器=newObjectMapper();*mapper.registerModule(newWebJackson2Module());**注意:使用{@linkSecurityJackson2Modules#getModules(ClassLoader)}获取所有安全模块的列表。**@authorJitendraSingh*@seeSecurityJackson2Modules*@since4.2*/publicclassWebJackson2ModuleextendsSimpleModule{publicWebJackson2Module(){super(WebJackson2Module.class.getName(),newVersion(1,0,0,null,null,null));}@OverridepublicvoidsetupModule(SetupContextcontext){SecurityJackson2Modules.enableDefaultTyping(context.getOwner());context.setMixInAnnotations(DefaultCsrfToken.class,DefaultCsrfTokenMixin.class);context.setMixInAnnotations(PreAuthenticatedAuthenticationToken.class,PreAuthenticatedAuthenticationTokenMixin.class);在这段代码中,提取自org.srpingframework.security:spring-security-web:5.1.5.RELEASE在这个例子中,springsecurity的设计者面临着一个典型的可扩展性问题:在访问jackson之前很久,springsecurity已经完成了DefaultCsrfToken的设计,但是最初的写法并不能很好的兼容jackson的反序列化策略。好在jackson提供了mixins机制,可以支持插件的序列化/反序列化Policy语句,从而避免了对springsecurity核心数据结构的侵入式改动。不得不说,设计真的很棒!总结如上所述,mixins机制的使用非常简单,从用户的角度来看完全是声明式的。而且更重要的是,不需要对原有的数据结构设计做任何侵入性的改动,这对于保证我们的代码足够干净,可以很方便的开放给其他JSON库,比如GSON,是非常重要的。那么mixins是如何工作的呢?请听下一章分解:保留传送门备注注1:Introspection:内省器,java中引用bean的getter/setter规范