Redis缓存,泛型集合与json字符串的相互转换实例
作者:一只咸鱼的自我修养 发布时间:2021-07-18 16:57:15
难点是泛型如何转换
一、arrayList<Map<String, Object>>转化json字符串,存入redis缓存
ArrayList<Map<String, Object>> listProfit
//将ArrayList<Map<String, Object>>类型数据转换成json字符串
String listProfitPctJsonStr = JSON.toJSONString(listProfit);
//然后将json字符串存入redis缓存,唯一key value
JedisUtils.setex("listProfit", 600,listProfitPctJsonStr);
二、json字符串转回ArrayList<Map<String, Object>>(难点)
List<Map<String, Object>> listProfit=null;
//先从redis里面去查询数据,看是否能获取到对应json字符串
String jsonStrLp=JedisUtils.get("listProfit");
//如果能获取则说明缓存中有数据
if(!StringUtils.isBlank(jsonStrLp)){
//目的是为了泛型的转换
listProfit=new ArrayList<Map<String,Object>>();
//先把从redis缓存中取出来的json字符串转为List<Map>集合
List<Map> mapList=JSON.parseArray(jsonStrLp, Map.class);
//然后循环遍历这个List集合,得出的结果为Map,然后再强转为Map<String,Object>,
再循环 把 Map<String,Object>添加到List集合中,搞定!!!
for (Map map : mapList) {
Map<String,Object> sObj=(Map<String,Object>)map;
listProfit.add(sObj);
}
补充知识:Java的List和Json转换以及StringRedisTemplate往redis存泛型对象
List转Json
List<User> user= new ArrayList();
String str = JSON.toJSONString(user);
Json 转List方法一
List<User> user= JSON.parseArray(json,User.class);
如果是泛型方法需要使用TypeReference
Json 转List 方法二
String json = "[{}]";
List<user> user= JSON.parseObject(json,new TypeReference<List<User>>(){});
泛型T
Json 转List方法三
List<T> students = JSON.parseObject(listCache,new TypeReference<List<T>>(){});
综合例子:Springboot环境下利用StringRedisTemplate往redis存泛型对象
一开始要注入下StringRedisTemplate
@Autowired
private StringRedisTemplate redisTemplate;
Redis获取值不存在就从数据库取出来json化存缓存,存在则直接反序列化json为List
List<T> list;
String listCache=redisTemplate.opsForValue().get(key);
if(listCache!=null){
list = JSON.parseObject(listCache,new TypeReference<List<T>>(){});
}
else {
list = userService.getAllList();
redisTemplate.opsForValue().set(key, JSON.toJSONString(list), 60 * 1, TimeUnit.SECONDS);
}
附录:TypeReference源码
package com.alibaba.fastjson;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.alibaba.fastjson.util.ParameterizedTypeImpl;
import com.alibaba.fastjson.util.TypeUtils;
/**
* Represents a generic type {@code T}. Java doesn't yet provide a way to
* represent generic types, so this class does. Forces clients to create a
* subclass of this class which enables retrieval the type information even at
* runtime.
*
* <p>For example, to create a type literal for {@code List<String>}, you can
* create an empty anonymous inner class:
*
* <pre>
* TypeReference<List<String>> list = new TypeReference<List<String>>() {};
* </pre>
* This syntax cannot be used to create type literals that have wildcard
* parameters, such as {@code Class<?>} or {@code List<? extends CharSequence>}.
*/
public class TypeReference<T> {
static ConcurrentMap<Type, Type> classTypeCache
= new ConcurrentHashMap<Type, Type>(16, 0.75f, 1);
protected final Type type;
/**
* Constructs a new type literal. Derives represented class from type
* parameter.
*
* <p>Clients create an empty anonymous subclass. Doing so embeds the type
* parameter in the anonymous class's type hierarchy so we can reconstitute it
* at runtime despite erasure.
*/
protected TypeReference(){
Type superClass = getClass().getGenericSuperclass();
Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
Type cachedType = classTypeCache.get(type);
if (cachedType == null) {
classTypeCache.putIfAbsent(type, type);
cachedType = classTypeCache.get(type);
}
this.type = cachedType;
}
/**
* @since 1.2.9
* @param actualTypeArguments
*/
protected TypeReference(Type... actualTypeArguments){
Class<?> thisClass = this.getClass();
Type superClass = thisClass.getGenericSuperclass();
ParameterizedType argType = (ParameterizedType) ((ParameterizedType) superClass).getActualTypeArguments()[0];
Type rawType = argType.getRawType();
Type[] argTypes = argType.getActualTypeArguments();
int actualIndex = 0;
for (int i = 0; i < argTypes.length; ++i) {
if (argTypes[i] instanceof TypeVariable &&
actualIndex < actualTypeArguments.length) {
argTypes[i] = actualTypeArguments[actualIndex++];
}
// fix for openjdk and android env
if (argTypes[i] instanceof GenericArrayType) {
argTypes[i] = TypeUtils.checkPrimitiveArray(
(GenericArrayType) argTypes[i]);
}
// 如果有多层泛型且该泛型已经注明实现的情况下,判断该泛型下一层是否还有泛型
if(argTypes[i] instanceof ParameterizedType) {
argTypes[i] = handlerParameterizedType((ParameterizedType) argTypes[i], actualTypeArguments, actualIndex);
}
}
Type key = new ParameterizedTypeImpl(argTypes, thisClass, rawType);
Type cachedType = classTypeCache.get(key);
if (cachedType == null) {
classTypeCache.putIfAbsent(key, key);
cachedType = classTypeCache.get(key);
}
type = cachedType;
}
private Type handlerParameterizedType(ParameterizedType type, Type[] actualTypeArguments, int actualIndex) {
Class<?> thisClass = this.getClass();
Type rawType = type.getRawType();
Type[] argTypes = type.getActualTypeArguments();
for(int i = 0; i < argTypes.length; ++i) {
if (argTypes[i] instanceof TypeVariable && actualIndex < actualTypeArguments.length) {
argTypes[i] = actualTypeArguments[actualIndex++];
}
// fix for openjdk and android env
if (argTypes[i] instanceof GenericArrayType) {
argTypes[i] = TypeUtils.checkPrimitiveArray(
(GenericArrayType) argTypes[i]);
}
// 如果有多层泛型且该泛型已经注明实现的情况下,判断该泛型下一层是否还有泛型
if(argTypes[i] instanceof ParameterizedType) {
return handlerParameterizedType((ParameterizedType) argTypes[i], actualTypeArguments, actualIndex);
}
}
Type key = new ParameterizedTypeImpl(argTypes, thisClass, rawType);
return key;
}
/**
* Gets underlying {@code Type} instance.
*/
public Type getType() {
return type;
}
public final static Type LIST_STRING = new TypeReference<List<String>>() {}.getType();
}
TypeReference的存在是因为java中子类可以获取到父类泛型的真实类型。
其中核心的方法是:getActualTypeArguments,它可以得到父类的反省类型
ParameterizedType是一个记录类型泛型的接口, 继承自Type,一共三方法:
Type[] getActualTypeArguments(); //返回泛型类型数组
Type getRawType(); //返回原始类型Type
Type getOwnerType(); //返回 Type 对象,表示此类型是其成员之一的类型。
Map<String, Integer> intMap = new HashMap<>();
System.out.println("getSuperclass:" + intMap.getClass().getSuperclass());
System.out.println("getGenericSuperclass:" + intMap.getClass().getGenericSuperclass());
Type type = intMap.getClass().getGenericSuperclass();
if (type instanceof ParameterizedType) {
ParameterizedType p = (ParameterizedType)type;
for (Type t : p.getActualTypeArguments()) {
System.out.println("getActualTypeArguments>>>"+t);
}
}
扩展阅读Java如何获得泛型类的真实类型:
package com.paopaoedu.springboot.demo;
import com.paopaoedu.springboot.bean.User;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class BaseDao<T>{
private Class<T> clazz;
// 使用反射技术得到T的真实类型
public Class getRealType(){
Class c=this.getClass();
//getSuperclass()获得该类的父类
System.out.println("getSuperclass >>>"+c.getSuperclass());
//getGenericSuperclass()获得带有泛型的父类
System.out.println("getGenericSuperclass >>>"+c.getGenericSuperclass());
//Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
Type type=c.getGenericSuperclass();
System.out.println("Type >>>"+type);
//ParameterizedType参数化类型,即泛型
// 获取当前new的对象的泛型的父类类型
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
// 获取第一个类型参数的真实类型
this.clazz = (Class<T>) pt.getActualTypeArguments()[0];
c=(Class) pt.getActualTypeArguments()[0];
System.out.println(c);
return clazz;
}
}
class userdemo extends BaseDao<User>{
public static void main(String[] args) {
userdemo classB = new userdemo();
Class realType = classB.getRealType();
System.out.println(realType.getName());
}
}
来源:https://blog.csdn.net/weixin_40671802/article/details/79426243
猜你喜欢
- 前几篇主要集中在注册中心eureka的使用上,接下来可以创建服务提供者provider来注册到eureka。demo源码见: https:/
- Kotlin中的面向对象面向对象面向对象的含义大家应该并不陌生,通过将事物抽象成对象,大大简化了程序的开发难度。我们常用的Java、Pyth
- 前言从 Java 5.0 开始,String 类新增了一个强大的字符串格式化方法 format()。这个方法到现在用的人还是不多,实在是一种
- 我们首先看一下效果图,有个整体的印象好了,为了便于理解,这里就按照动画所见内容依次展开来说准备这里决定采用canvas(画布)和paint(
- 引言坦白从宽吧,我就是那个花了两天两夜把 1M 图片优化到 100kb 的家伙——王小二!自从因为一
- 之前有简单介绍过java多线程的使用,已经Thread类和Runnable类,为了更好地理解多线程,本文就Thread进行详细的分析。sta
- 前言众所周知,微信聊天中我们输入一些关键词会有表情雨下落,比如输入「生日快乐」「么么哒」会有相应的蛋糕、亲吻的表情雨下落,今天就来完成这个表
- 想要将一个项目导出为jar包,供其它项目使用,在eclipse中可以直接导出该项目为jar包,而 在AS中可以通过修改gradle才处理。接
- 前言刚看到这个题目的朋友第一反应肯定是好奇,之后再细细思考下就会发现这个题目眼熟了。就算是同一个答案,如果提问的方式不同,往往会对回答造成干
- 本人一直喜欢左手使用鼠标,但有时候同事会临时进行操作,还得在控制面板里进行更改,比较不便,何不编写一个控制台程序,双击一下即可切换左右键 代
- JPA的加锁机制有两种,乐观锁和悲观锁。乐观锁:乐观锁的特点在于认为数据冲突或者更新丢失等情况是很少发生的.当发生的时候,抛出异常和回滚就足
- 简介:Springboot使用Mybatis&Mybatis-plus 两者文件映射配置略有不同,之前我用的是Mybatis,但公司
- 大家好,在这篇文章中,我们将学习如何添加动画,同时从一个页面到其他在 Flutter。我们将覆盖不同类型的动画和实现基本动画 Flutter
- 为什么说是常见问题整合呢,因为小编我就是Genymotion模板器最悲剧的使用者,该见过的问题,我基本都见过了,在此总结出这血的教训,望大家
- 1. 效果图展示2. 工程目录结构注意: webapp下的resources目录放置easyui和js(jQuery文件是另外的) 
- 本文实例讲述了Java设计模式之工厂模式实现方法。分享给大家供大家参考,具体如下:工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体
- 简介optional类是java8中引入的针对NPE问题的一种优美处理方式,源码作者也希望以此替代null。历史1965年,英国一位名为To
- 实现InitializingBean接口或使用@PostConstruct注解实现InitializingBean如下public clas
- 本文实例为大家分享了UnityShader实现运动模糊的具体代码,供大家参考,具体内容如下原理:像素的当前帧的NDC坐标(x,y
- 第 1 步:将这个 Spring Boot 项目的打包方式设置为 war。<packaging>war</packagin