溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java如何用Redis存儲(chǔ)復(fù)雜json格式數(shù)據(jù)并返回給前端

發(fā)布時(shí)間:2020-07-16 14:12:54 來源:億速云 閱讀:884 作者:小豬 欄目:開發(fā)技術(shù)

這篇文章主要為大家展示了Java如何用Redis存儲(chǔ)復(fù)雜json格式數(shù)據(jù)并返回給前端,內(nèi)容簡(jiǎn)而易懂,下面讓小編帶大家一起學(xué)習(xí)一下吧。

問題背景

在Java Web項(xiàng)目中,經(jīng)常需要前端請(qǐng)求數(shù)據(jù),后臺(tái)從數(shù)據(jù)庫(kù)中查詢并計(jì)算最后返回json格式數(shù)據(jù)給前端。

而每次請(qǐng)求都需要計(jì)算一次可能比較浪費(fèi)時(shí)間,這時(shí)我們可以將計(jì)算好的結(jié)果保存在redis中,下次請(qǐng)求時(shí)先判斷redis中是否已經(jīng)存在,如果是則直接從redis里取出返回,因?yàn)槭窃趦?nèi)存中,所以比較快。

而自己在項(xiàng)目中遇到的json格式數(shù)據(jù)比較復(fù)雜,下面記錄一下redis存儲(chǔ)對(duì)象和json格式數(shù)據(jù)的幾種方式以及遇到的問題。

存儲(chǔ)方式

1. 直接使用String存儲(chǔ)

String類型是Redis中最簡(jiǎn)單的類型了,每個(gè)key對(duì)應(yīng)一個(gè)String,我們可以直接將要存儲(chǔ)的對(duì)象轉(zhuǎn)換成json字符串,代碼如下:

 //存儲(chǔ)
 public static void setJsonString(String key, Object obj) {
 Jedis jedis = RedisConnection.getJedis();
 jedis.set(key, JSON.toJSONString(obj));
 jedis.close();
 }
 //獲取
 public static String getJsonString(String key) {
 Jedis jedis = RedisConnection.getJedis();
 String value = jedis.get(key);
 jedis.close();
 return value;
 }

這里是使用fastjson的相關(guān)函數(shù)toJSONString將對(duì)象轉(zhuǎn)換為字符串進(jìn)行存儲(chǔ)。獲取的時(shí)候直接返回json字符串給前端就可以了。使用這種方式可能只能存儲(chǔ)簡(jiǎn)單的json字符串,對(duì)于復(fù)雜格式的可能會(huì)解析錯(cuò)誤。

2. 使用對(duì)象序列化方式存儲(chǔ)

先將對(duì)象以字節(jié)序列化存儲(chǔ),然后再反序列化得到對(duì)象,這里可以封裝一個(gè)序列化和反序列化的工具類:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializeUtil {
  /*
   * 序列化
   * */
  public static byte[] serizlize(Object object){
    ObjectOutputStream oos = null;
    ByteArrayOutputStream baos = null;
    try {
      baos = new ByteArrayOutputStream();
      oos = new ObjectOutputStream(baos);
      oos.writeObject(object);
      byte[] bytes = baos.toByteArray();
      return bytes;
    } catch (Exception e) {
      e.printStackTrace();
    }finally {
      try {
        if(baos != null){
          baos.close();
        }
        if (oos != null) {
          oos.close();
        }
      } catch (Exception e2) {
        e2.printStackTrace();
      }
    }
    return null;
  }
  /*
   * 反序列化
   * */
  public static Object deserialize(byte[] bytes){
    ByteArrayInputStream bais = null;
    ObjectInputStream ois = null; 
    try{
      bais = new ByteArrayInputStream(bytes);
      ois = new ObjectInputStream(bais);
      return ois.readObject();
    }catch(Exception e){
      e.printStackTrace();
    }finally {
      try {

      } catch (Exception e2) {
        e2.printStackTrace();
      }
    }
    return null;
  }
}

相應(yīng)存儲(chǔ)和獲取代碼如下:

 public static void setObject(String key,Object object){
    Jedis jedis = RedisConnection.getJedis();
    jedis.set(key.getBytes(), SerializeUtil.serizlize(object));
    jedis.close();
  }
  public static Object getObject(String key){
    Jedis jedis = RedisConnection.getJedis();
    byte[] bytes = jedis.get(key.getBytes());
    jedis.close();
    return SerializeUtil.deserialize(bytes);
  }

使用這種方式可能遇到嵌套的對(duì)象或者json數(shù)組等不太好解決。

3. 使用hash存儲(chǔ)

第三種方式也是解決我問題的一種方式,由于我的json格式數(shù)據(jù)比較復(fù)雜,形如:

{
 "cd": [{"Condition": {...}, segs:[1,2,3]}, { }, ...]
 "rs": {"way": "休寧路", "road":[{},{},..], "segList": [{object}, {}, ...] }
}

我剛開始是直接使用fastjson將其轉(zhuǎn)換為字符串進(jìn)行存儲(chǔ),但在返回解析時(shí)發(fā)現(xiàn)格式不太對(duì)了。分析其原因可能是json格式太復(fù)雜,然后使用redis中hash方式將數(shù)據(jù)進(jìn)行分割存儲(chǔ),即cd對(duì)應(yīng)一個(gè)key存儲(chǔ),rs為一個(gè)key進(jìn)行存儲(chǔ),將這兩部分都放入一個(gè)hash中。

相應(yīng)代碼如下:

Jedis jedis = RedisConnection.getJedis();
JSONObject res = new JSONObject(); //最終結(jié)果
//如果redis中存在,則直接從redis中取,否則計(jì)算并存儲(chǔ)至redis
if(jedis.exists(lm)) {
 String rs_value = jedis.hget(lm, "rs");
 String cd_value = jedis.hget(lm, "cd");
 res.put("cd", JSONArray.parseArray(cd_value));
 res.put("rs", JSONObject.parseObject(rs_value));
 System.out.println("redis get success");
} else {
 res = computeRes(lm);
 //更新redis
 jedis.hset(lm, "cd", res.getJSONArray("cd").toJSONString());
 jedis.hset(lm, "rs", JSON.toJSONString(res.getJSONObject("rs")));
 System.out.println("redis set success");
}
jedis.close();
 
//候選結(jié)果集轉(zhuǎn)json字符串
String jsonStr = JSON.toJSONString(res, SerializerFeature.DisableCircularReferenceDetect);
//返回給前端
System.out.println("json string: " + jsonStr);
response.setContentType("text/html;charset=utf-8"); //解決前端中文亂碼
PrintWriter out = response.getWriter();
out.print(jsonStr);

我是以路名(lm)作為hash的key,首先判斷是否存在該key,不存在的話先進(jìn)行計(jì)算res = computeRes(lm);,得到上述的json格式數(shù)據(jù),然后使用hset方法將其分別作為兩個(gè)key進(jìn)行存儲(chǔ)。注意上述cd為一個(gè)JSONArray對(duì)象,需要使用調(diào)用toJSONString()方法轉(zhuǎn)換成字符串,而rs為一個(gè)JSONObject對(duì)象,使用的是JSON.toJSONString。

在獲取時(shí)首先分別獲取其字符串形式,然后分別轉(zhuǎn)換成相應(yīng)的類型JSONArray.parseArray(cd_value)和JSONObject.parseObject(rs_value),最終包裹在一個(gè)JSONObject中。

以上就是關(guān)于Java如何用Redis存儲(chǔ)復(fù)雜json格式數(shù)據(jù)并返回給前端的內(nèi)容,如果你們有學(xué)習(xí)到知識(shí)或者技能,可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI