使用Redis获取数据转json解决动态泛型传参的问题

上传人:仙*** 文档编号:112584900 上传时间:2022-06-23 格式:DOC 页数:5 大小:317.50KB
返回 下载 相关 举报
使用Redis获取数据转json解决动态泛型传参的问题_第1页
第1页 / 共5页
使用Redis获取数据转json解决动态泛型传参的问题_第2页
第2页 / 共5页
使用Redis获取数据转json解决动态泛型传参的问题_第3页
第3页 / 共5页
点击查看更多>>
资源描述
使用Redi获取数据转json解决动态泛型传参的问题场景:项目有两种角色需要不同的登录权限,将ed做为用户登录信息缓存数据库。码一个方法,希望能够根据传入不用用户实体类型来获取相应的数据。用户实体为:essionni、sessionni。json(使用SjSon先阐述遇到的几个问题:ied获取到的数据序列化后,转json经常提示转换异常(并不是每次,只是时常)。2不想每种用户都书写一个ed操作方法(显得i)。解决:ied获取到的数据序列化后,转json经常提示转换异常:先说edi&两种获取方式。1)redisTeme.opsFoue(et(key);)essionEntity)resulredisTemplate.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所以应该算是一种封装吧。我们一直釆用的是第二种方式。(第一种方式试过,也一样会出现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,)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(value);returnJSONObject.parseObject(json,newTypeReferenceSessionEntity(););看样子是没什么问题,而且泛型也被识别到了。但是依旧无法通过。2、不想每种用户都书写一个redis操作方法:上面说到就算加了泛型也依旧无法通过,尝试了多种方式依旧如此。百度了一圈,都是说使用TypeReference这个来解决,但是并没有提及动态泛型的问题。偶然间看到文章说Fastjson不支持,所以尝试替换Jackson。替换后的代码:SessionEntityresult=redisTemplate.execute(newRedisCallbackSessionEntity()publicSessionEntitydoInRedis(RedisConnectionconnection)throwsDataAccessExceptionRedisSerializerserializer=getRedisSerializer();bytekey=serializer.serialize(s);bytevalue=connection.get(key);if(value=null)returnnull;Stringjson=serializer.deserialize(value);ObjectMapperom=newObjectMapper();JavaTypejavatype=om.getTypeFactory().constructParametricType(SessionEntity.class,clazz);tryreturnom.readValue(json,javatype);catch(IOExceptione)e.printStackTrace();returnnull;/returnJSONObject.parseObject(json,newTypeReferenceSessionEntity(););这里使用到Tjackson的ObjectMapper。ObjectMapper类是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然。它使用JsonParser和JsonGenerator的实例实现JSON实际的读/写。(复制来的)发现问题解决。提供的抽象方法为:publicSessionEntityget(finalStrings,Classclazz);调用方式为:sessionEntityDao.get(key,User1.class);跟sessionEntityDao.get(key,User2.class);由于这里使用到的是jackson-databind-2.6.0的库,这个版本种constructParametricType这个方法已经快要过时,更高版本使用constructParametrizedType替换。这里我还没尝试过,等有空再玩。这里问题已经解决,纯粹做个笔记以供自己以后方便查阅。这里只提供自己项目中遇到的解决方式之一,相信应该还有其他方式可以解决。如果有说明错误的地方,请指出并见谅。补充知识:Redis爬坑Redis实现通用序列化器&解决Redis反序列化失败Redis默认序列化是JdkSerializationRedisSerializer,由此可见publicvoidafterPropertiesSet()super.afterPropertiesSet();booleandefaultUsed=false;if(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.valueSerializer=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&defaultUsed)Assert.notNull(this.defaultSerializer,defaultserializernullandnotallserializersinitialized);if(this.scriptExecutor=null)this.scriptExecutor=newDefaultScriptExecutor(this);this.initialized=true;这里因为我们的项目需要更改默认序列策略为Jackson2JsonRedisSerialize让它序列化为可视化的*json*语句我们首先定义自己的RedisTemplate,这里我们不要为了每一个类定义一个序列化器,我们定义一个统一的序列化器所以这里泛型是,key我们使用StringRedisSerializer,value使用Jackson2JsonRedisSerializer注释代码为修复反序列化bug的代码BeanpublicRedisTemplateobjectRedisTemplate(RedisConnectionFactoryredisConnectionFactory)throwsUnknownHostExceptionRedisTemplatetemplate=newRedisTemplate();Jackson2JsonRedisSerializerjsonSerial=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);template.setKeySerializer(RedisSerializer.string();template.setConnectionFactory(redisConnectionFactory);template.afterPropertiesSet();returntemplate;测试代码为TestpublicvoidredisSaveObject()UserDOob=newUserDO();ob.setName(name);ob.setCity(city);objectRedisTemplate.opsForValue().set(ob1,ob);Objectob2=objectRedisTemplate.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(NativeMethod)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.java:50)atorg.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)atorg.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)atorg.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)at很明显是对象强制转换错误这是因为泛型的原因,redis在序列化时候把他当成Object序列化的,所以这里反序列化为Object是可以的,但是因为这个Object没有类型定义所以无法强转。解决办法在RedisTemplate中对序列化器Jackson2JsonRedisSerializer进行修改添加如下代码,上文注释了/修复反序列化bugObjectMapperom=newObjectMapper();om.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jsonSerial.setObjectMapper(om);通过objectMapper.enableDefaultTyping()方法设置即使使用Object.class作为jcom.fasterxml.jackson.databind.JavaType也可以实现相应类型的序列化和反序列化好处:只定义一个序列化器就可以了(通用)这里我们也做个测试,分别用不修改ObjectMapper的和修改了ObjectMapper的看看生成的value有啥子不一样jnRedisTenplate-StringAObject*cbjectRedisTempla:el(fie吐LwfDneeicziiacFmttcjryredisConnec: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获取数据转json,解决动态泛型传参的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。publicKedisTmplatMStrirg,ob:MtRedlsTemDlei.ez(RisConniectlanFactoryIsccnnectiaiftory1throwsum,:附hRedisFe*plate5tring.ObjectsewpUte-nwtedlsTeflpUteiI;Jacson2Js&rrRi?disSerl3lizerjsoftSerlai2hawJatktanilJtchREciisSria112er(Objecttenolate.setDeiauLt5erlaLlzrCJso-ftSerlal!;tmpUte.seW&erlaiit訂(fieil$SeiIme.刃口叩订打tenolat电.selCorinecticrFactnry(redstewneetlenfactory):temlatc-aftc-rProjM!rthreturnLfserWob=bwUserWIJ;o&iSetNneCnaweM;etsttCity(HeityB)?cujectReaisTeiiipildi-el.opsFDr/aIdelhset;-1c4je*tRedi.taultTyping,WW_FfWIILJ;1jLag乂ttFtiT伍izck(宜口FSLiiiUtenDlat.setKeySierializerikEdisieriaUze-stng|l;Ims1.ite.se-ConniectiorFcto巧(r:terroLatc.attcrP-gperticsSet(!;t-ewlaiej
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 管理文书 > 施工组织


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!