您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了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í)或者技能,可以把它分享出去讓更多的人看到。
免責(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)容。