使用Redis获取数据转json,解决动态泛型传参的问题_第1页
使用Redis获取数据转json,解决动态泛型传参的问题_第2页
使用Redis获取数据转json,解决动态泛型传参的问题_第3页
使用Redis获取数据转json,解决动态泛型传参的问题_第4页
使用Redis获取数据转json,解决动态泛型传参的问题_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、使用Redi获取数据转json解决动态泛型传参的问题场景:项目有两种角色需要不同的登录权限,将ed做为用户登录信息缓存数据库。码一个方法,希望能够根据传入不用用户实体类型来获取相应的数据。用户实体为:essionni、sessionni。json(使用SjSon先阐述遇到的几个问题:ied获取到的数据序列化后,转json经常提示转换异常(并不是每次,只是时常)。2不想每种用户都书写一个ed操作方法(显得i)。解决:ied获取到的数据序列化后,转json经常提示转换异常:先说edi&两种获取方式。1)redisTeme.opsFoue(et(key);)essionEntity)resulred

2、isTemplate.execute(new)RedisCallback)serializergetRedisserializer();e)key)=)serializer.serialize(seue)=)connection.get(key)if)(lue)=)nu)ren)nulingjson)=)serializer.deserialize(value);)returnObjecrseObject(json,sessionEntity.class);显然第一种的方式比较简单。查看源码,发现第一种方式底层调用的也是edisee方法,e所以应该算是一种封装吧。我们一直釆用的是第二种方式。(

3、第一种方式试过,也一样会出现son强转异常)。这里出现过json异常,怀疑是跟泛型有关。这里手动指定泛型反序列化类型。修改后:essionEntity)resulredisTemplate.execute(new)RedisCallback)serializer)=)getRedisserializer()e)key)=)serializer.serialize(s);eue)=)connection.get(key);)if)(lue)=)nu)ren)nulingjson)=)serializer.deserialize(value);)returnObjecrseObject(json,

4、)new)TypeReferencesessionEntityUse完美,确实解决了json强转异常。那么问题来了,这里的eRee需要手动指定明确的的实体类型,尝试添加泛型:essionEntity)result)=)redisTemplate.execute(new)RedisCallback)serializegetRedisserializer();)byte)key)=)serializer.serialize(s);)byte)value)=)connection.get(key)if)(value)=)nuen)nStringjson=serializer.deserialize(

5、value);returnJSONObject.parseObject(json,newTypeReferenceSessionEntity(););看样子是没什么问题,而且泛型也被识别到了。但是依旧无法通过。2、不想每种用户都书写一个redis操作方法:上面说到就算加了泛型也依旧无法通过,尝试了多种方式依旧如此。百度了一圈,都是说使用TypeReference这个来解决,但是并没有提及动态泛型的问题。偶然间看到文章说Fastjson不支持,所以尝试替换Jackson。替换后的代码:SessionEntityresult=redisTemplate.execute(newRedisCallba

6、ckSessionEntity()publicSessionEntitydoInRedis(RedisConnectionconnection)throwsDataAccessExceptionRedisSerializerserializer=getRedisSerializer();bytekey=serializer.serialize(s);bytevalue=connection.get(key);if(value=null)returnnull;Stringjson=serializer.deserialize(value);ObjectMapperom=newObjectMapp

7、er();JavaTypejavatype=om.getTypeFactory().constructParametricType(SessionEntity.class,clazz);tryreturnom.readValue(json,javatype);catch(IOExceptione)e.printStackTrace();returnnull;/returnJSONObject.parseObject(json,newTypeReferenceSessionEntity(););这里使用到Tjackson的ObjectMapper。ObjectMapper类是Jackson库的主

8、要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然。它使用JsonParser和JsonGenerator的实例实现JSON实际的读/写。(复制来的)发现问题解决。提供的抽象方法为:publicSessionEntityget(finalStrings,Classclazz);调用方式为:sessionEntityDao.get(key,User1.class);跟sessionEntityDao.get(key,User2.class);由于这里使用到的是jackson-databind-2.6.0的库,这个版本种constructParametricType这个方法已经快要

9、过时,更高版本使用constructParametrizedType替换。这里我还没尝试过,等有空再玩。这里问题已经解决,纯粹做个笔记以供自己以后方便查阅。这里只提供自己项目中遇到的解决方式之一,相信应该还有其他方式可以解决。如果有说明错误的地方,请指出并见谅。补充知识:Redis爬坑Redis实现通用序列化器&解决Redis反序列化失败Redis默认序列化是JdkSerializationRedisSerializer,由此可见publicvoidafterPropertiesSet()super.afterPropertiesSet();booleandefaultUsed=false;i

10、f(this.defaultSerializer=null)this.defaultSerializer=newJdkSerializationRedisSerializer(this.classLoader!=null?this.classLoader:this.getClass().getClassLoader();if(this.enableDefaultSerializer)if(this.keySerializer=null)this.keySerializer=this.defaultSerializer;defaultUsed=true;if(this.valueSerializ

11、er=null)this.valueSerializer=this.defaultSerializer;defaultUsed=true;if(this.hashKeySerializer=null)this.hashKeySerializer=this.defaultSerializer;defaultUsed=true;if(this.hashValueSerializer=null)this.hashValueSerializer=this.defaultSerializer;defaultUsed=true;if(this.enableDefaultSerializer&default

12、Used)Assert.notNull(this.defaultSerializer,defaultserializernullandnotallserializersinitialized);if(this.scriptExecutor=null)this.scriptExecutor=newDefaultScriptExecutor(this);this.initialized=true;这里因为我们的项目需要更改默认序列策略为Jackson2JsonRedisSerialize让它序列化为可视化的*json*语句我们首先定义自己的RedisTemplate,这里我们不要为了每一个类定义一

13、个序列化器,我们定义一个统一的序列化器所以这里泛型是,key我们使用StringRedisSerializer,value使用Jackson2JsonRedisSerializer注释代码为修复反序列化bug的代码BeanpublicRedisTemplateobjectRedisTemplate(RedisConnectionFactoryredisConnectionFactory)throwsUnknownHostExceptionRedisTemplatetemplate=newRedisTemplate();Jackson2JsonRedisSerializerjsonSerial=

14、newJackson2JsonRedisSerializer(Object.class);/修复反序列化bug/ObjectMapperom=newObjectMapper();/om.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);/om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);/jsonSerial.setObjectMapper(om);template.setDefaultSerializer(jsonSerial);templ

15、ate.setKeySerializer(RedisSerializer.string();template.setConnectionFactory(redisConnectionFactory);template.afterPropertiesSet();returntemplate;测试代码为TestpublicvoidredisSaveObject()UserDOob=newUserDO();ob.setName(name);ob.setCity(city);objectRedisTemplate.opsForValue().set(ob1,ob);Objectob2=objectRe

16、disTemplate.opsForValue().get(ob1);UserDOob1=(UserDO)ob2;System.out.println(ob1);运行结果为java.lang.ClassCastException:java.util.LinkedHashMapcannotbecasttocom.hcy.core.model.UserDOatcom.hcy.core.redistest.RedisTest.redisSaveObject(RedisTest.java:42)atsun.reflect.NativeMethodAccessorImpl.invoke0(NativeM

17、ethod)atsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)atsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)atjava.lang.reflect.Method.invoke(Method.java:498)atorg.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.

18、java:50)ernal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)atorg.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)ernal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)at很明显是对象强制转换错误这是因为泛型的原因,redis在序列化时候把他当成O

19、bject序列化的,所以这里反序列化为Object是可以的,但是因为这个Object没有类型定义所以无法强转。解决办法在RedisTemplate中对序列化器Jackson2JsonRedisSerializer进行修改添加如下代码,上文注释了/修复反序列化bugObjectMapperom=newObjectMapper();om.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jsonS

20、erial.setObjectMapper(om);通过objectMapper.enableDefaultTyping()方法设置即使使用Object.class作为jcom.fasterxml.jackson.databind.JavaType也可以实现相应类型的序列化和反序列化好处:只定义一个序列化器就可以了(通用)这里我们也做个测试,分别用不修改ObjectMapper的和修改了ObjectMapper的看看生成的value有啥子不一样jnRedisTenplate-StringAObject*cbjectRedisTempla:el(fie吐LwfDneeicziiacFmttcjr

21、yredisConnec:ticnfactnr1Tit旷耐5._4cdlFempliecStrinyjODjeci.epiatt=mwRizdisTiefflplariJ;2ac4ED-n2JoriRtd;isScrlaLiztrjEfluSerial-n电常2ackscrtXJscnRdi&Scrializ0rtDti-2t1*5$钉A*jtcvircidReifisTen需1讥亡巧匸JjiCLte:egobjectKtdisTmulatel;AjtMircdFKc1istct;pUTe5iring,abjectRetiisiwnp1atez:restpublicvoidreditSaveObjectfH运行结果:obi:com.hcy.core.model.UserDO,userid:null,openid:null,name:name,city:cityob2:userid:null,openid:null,name:name,city:city这里结果很明显啦希望对大家有帮助以上这篇使用Redis获取数据转js

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论