摘要:支持等眾多語言。此處的是經(jīng)過封裝的,和中類似。相關(guān)模板均在類中定義,諸如。優(yōu)化后的使用方法為中的錯(cuò)誤先看看這段代碼反序列化后獲取,因?yàn)橹惺穷愋停@里面可能是,也可能是,因此需要注意。參考資料讓版支持類型
Msgpack簡介
MessagePack is an efficient binary serialization format. It lets you exchange data among multiple languages like JSON. But it"s faster and smaller. Small integers are encoded into a single byte, and typical short strings require only one extra byte in addition to the strings themselves.
MessagePack是一個(gè)基于二進(jìn)制高效的對象序列化Library用于跨語言通信。它可以像JSON那樣,在許多種語言之間交換結(jié)構(gòu)對象;但是它比JSON更快速也更輕巧。 支持Python、Ruby、Java、C/C++、Javascript等眾多語言。 比Google Protocol Buffers還要快4倍。
Graddle依賴管理// msgpack compile "org.msgpack:msgpack:0.6.12" // 依賴javassist和json-simple //slf-logback compile "org.slf4j:jcl-over-slf4j:1.7.7" compile "org.slf4j:jcl-over-slf4j:1.7.7" // 依賴lf4j-api,故lf4j-api可以不多帶帶配置 compile "org.slf4j:slf4j-api:1.7.7" // javassist compile "org.javassist:javassist:3.20.0-GA" // 如果其他有依賴,則可不多帶帶配置 compile "com.googlecode.json-simple:json-simple:1.1.1"使用Msgpack解析yii2 session中的數(shù)據(jù)
yii2將session數(shù)據(jù)寫入redis中,為了在java api中可以使用后臺用戶登錄的信息,則需要通過java解析session數(shù)據(jù)。
先看看如何使用:
// sessionBytes是byte類型 if (null != sessionBytes) { MessagePack pack = new MessagePack(); // new一個(gè)msgpack對象 Map map = null; try { map = (Map) pack.read(sessionBytes); // 通過Msgpack的read讀取字節(jié),強(qiáng)制轉(zhuǎn)換為Map對象 } catch (IOException e) { LOGGER.warn("get request user from redis failed: ", e); } if (!com.joyven.util.Utils.isEmpty(map)) { map.forEach((k, v) -> { String key = String.valueOf(k); String value = String.valueOf(v); if (Const.SESSION_KEY_UID.equals(key)) { user.setUid(Long.parseLong(trim(value, USER_STRING_REDUNDANCY))); } if (Const.SESSION_KEY_USERNAME.equals(key)) { user.setUsername(trim(value, USER_STRING_REDUNDANCY)); } if (Const.SESSION_KEY_AVATAR.equals(key)) { user.setAvatar(trim(value, USER_STRING_REDUNDANCY)); } if (Const.SESSION_KEY_CST.equals(key)) { user.setCraftsmanStatus(Integer.parseInt(trim(value, USER_STRING_REDUNDANCY)) + 1); } if (Const.SESSION_KEY_MOBILE.equals(key)) { user.setMobile(trim(value, USER_STRING_REDUNDANCY)); } }); } }
上述代碼中常量的定義:
public static final String SESSION_KEY_UID = ""uid""; public static final String SESSION_KEY_USERNAME = ""un""; public static final String SESSION_KEY_AVATAR = ""avt""; public static final String SESSION_KEY_CST = ""cst""; public static final String SESSION_KEY_MOBILE = ""mbl""; public static final String USER_STRING_REDUNDANCY = """;
php寫入的數(shù)據(jù)是uid、un、avt、cst、mbl這樣的key,經(jīng)過Msgpack序列化后的key都加上了",強(qiáng)制轉(zhuǎn)換為Map對象后,map中的key并沒有去掉這些轉(zhuǎn)義字符,value也不例外,因此使用trim去掉了value兩邊的"。需要注意,如果是yii2的話,一般key都有前綴,此處作者把前綴刪掉了,下面所有代碼均如此。
此處的trim是經(jīng)過封裝的,和php中trim api類似。
上面的這塊代碼,Msgpack反序列化可以抽象封裝為工具類:
@SuppressWarnings("unchecked") public static Map getMessagePackValue(final byte[] bytes) throws IOException { MessagePack pack = new MessagePack(); Map map = (Map) pack.read(bytes); Map result = new HashMap<>(); if (null != map) { map.forEach((k, v) -> result.put(trim(String.valueOf(k), USER_STRING_REDUNDANCY), trim(String.valueOf(v), USER_STRING_REDUNDANCY))); } return result; }優(yōu)化getMessagePackValue方法,不再使用trim處理數(shù)據(jù)
@SuppressWarnings("unchecked") public static Map getMessagePackValue(final byte[] bytes) throws IOException { MessagePack pack = new MessagePack(); Mapmap = (Map) pack.read(bytes, Templates.tMap(Templates.TString, Templates.TValue)); Map result = new HashMap<>(); if (map != null) { map.forEach((k, v) -> { Object object = rawObjToObj(v); result.put(k, object); }); } return result; }
Msgpack有很多數(shù)據(jù)模板,這里使用TString模板和TValue模板。相關(guān)模板均在org.msgpack.template.Template類中定義,諸如:TValue、TByte、TShort、TInteger、TLong、TCharacter、TBigInteger、TBigDecimal、TFloat、TBoolean、TString、TByteArray、TByteBuffer、TDate、tNotNullable、tList、tMap、tCollection、tOrdinalEnum。
private static Object rawObjToObj(Object obj) { Object objResu = null; if (obj instanceof IntegerValue) { objResu = ((IntegerValue) obj).asIntegerValue(); } else if (obj instanceof ArrayValue) { ArrayValue v = ((ArrayValue) obj).asArrayValue(); List優(yōu)化后的使用方法
// appId 為php中的session id public User getAdminUser(String appId) { byte[] sessionKey = getSessionKey(appId).getBytes(); byte[] sessionAdmin; User user = new User(); try (Jedis jedis = jedisPool.getResource()) { jedis.select(RedisDB.DB12); sessionAdmin = jedis.get(sessionKey); user.setExpire(jedis.ttl(sessionKey)); } if (sessionAdmin != null) { Map map = new HashMap<>(); try { map = Utils.getMessagePackValue(sessionAdmin); } catch (IOException e) { LOGGER.warn("parse session admin error: " + e.getMessage()); } if (!isEmpty(map)) { if (map.containsKey("id")) { if (map.get("id") instanceof IntegerValue) { user.setAid(((IntegerValue) map.get("id")).longValue()); } else if(!isEmpty((String) map.get("id"))){ user.setAid(Long.parseLong((String) map.get("id"))); } else { user.setAid(0L); } } if (map.containsKey("un")) { user.setUsername((String) map.get("un")); } if (map.containsKey("rn")) { user.setRealname((String) map.get("rn")); } } } return user; }錯(cuò)誤:org.msgpack.type.intValueImpl cannot be cast to java.lang.Long
先看看這段代碼:
if (map.containsKey("id")) { if (map.get("id") instanceof IntegerValue) { user.setAid(((IntegerValue) map.get("id")).longValue()); } else if(!isEmpty((String) map.get("id"))){ user.setAid(Long.parseLong((String) map.get("id"))); } else { user.setAid(0L); } }
反序列化后獲取id,因?yàn)閁ser中id是Long類型,這里面id可能是String,也可能是Integer,因此需要注意。最開的代碼是這樣寫的:
if (map.containsKey("id") && !isEmpty((String) map.get("id"))) { user.setAid(Long.parseLong((String) map.get("id"))); }
通過Long.parseLong解析id報(bào)錯(cuò),錯(cuò)誤:org.msgpack.type.intValueImpl cannot be cast to java.lang.Long,于是修改為下面這般,如果是IntegerValue的實(shí)例,則強(qiáng)制轉(zhuǎn)換為Long類型,但是依然報(bào)錯(cuò):
if (map.containsKey("id")) { if (map.get("id") instanceof IntegerValue) { user.setAid((Long) map.get("id")); } else if(!isEmpty((String) map.get("id"))){ user.setAid(Long.parseLong((String) map.get("id"))); } else { user.setAid(0L); } }
最后強(qiáng)制類型轉(zhuǎn)換IntegerValue,再獲取longValue,即為上面函數(shù)中的那般才解決此錯(cuò)誤。
參考資料1.讓java版msgpack支持Object類型
2.MessagePack
3.msgpack
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/66570.html
摘要:的簡介是一個(gè)基于分布式消息傳輸?shù)漠惒饺蝿?wù)隊(duì)列,它專注于實(shí)時(shí)處理,同時(shí)也支持任務(wù)調(diào)度。目前支持等作為消息代理,但適用于生產(chǎn)環(huán)境的只有和官方推薦。任務(wù)處理完后保存狀態(tài)信息和結(jié)果,以供查詢。 celery的簡介 ??celery是一個(gè)基于分布式消息傳輸?shù)漠惒饺蝿?wù)隊(duì)列,它專注于實(shí)時(shí)處理,同時(shí)也支持任務(wù)調(diào)度。它的執(zhí)行單元為任務(wù)(task),利用多線程,如Eventlet,gevent等,它們能被...
摘要:是一個(gè)高效的二進(jìn)制序列化框架它像一樣支持不同語言間的數(shù)據(jù)交換但是它的性能更快序列化之后的碼流更小的特點(diǎn)如下編解碼高效性能高序列化之后的碼流小支持跨語言編碼器和解碼器開發(fā)編碼器開發(fā)負(fù)責(zé)將類型的對象編碼為數(shù)組然后添加到集合中解碼器開發(fā)首先從數(shù) MessagePack 是一個(gè)高效的二進(jìn)制序列化框架, 它像 JSON 一樣支持不同語言間的數(shù)據(jù)交換, 但是它的性能更快, 序列化之后的碼流更小. ...
摘要:這里序列化的概念可能更為廣泛和籠統(tǒng)一些,包括傳統(tǒng)的等。就目前來看,等二進(jìn)制序列化無論是速度上還是數(shù)據(jù)大小上,都要比文本序列化更好。,反序列化方法。用法,序列化方法。 原文地址:https://t.ti-node.com/thread/... 數(shù)據(jù)的序列化是一個(gè)非常有用的功能,然而目測很多人跟我一樣,在剛接觸這玩意的時(shí)候壓根就不理解這貨色到底是干啥用的,反正老師說了,實(shí)在理解不了就先背...
摘要:第二集非必選持續(xù)集成編譯打包部署到線上環(huán)境集成前言在持續(xù)集成第一集中講解了關(guān)于如果編譯,打包,發(fā)布包到私服。在下面一集中,也就是第二集中,開始講解如何持續(xù)集成可運(yùn)行的服務(wù)包到測試和正式環(huán)境。 第二集 hudson+gradle+git+maven(非必選)持續(xù)集成編譯,打包,部署到線上環(huán)境集成 前言 在持續(xù)集成第一集中,講解了關(guān)于如果編譯,打包,發(fā)布jar包到maven私服。在下面一集...
摘要:是一個(gè)基于分布式消息傳輸?shù)漠惒饺蝿?wù)隊(duì)列,它專注于實(shí)時(shí)處理,同時(shí)也支持任務(wù)調(diào)度。本文將介紹如何使用來加速爬蟲。本文爬蟲的例子來自文章爬蟲的種姿勢。雖然沒有這個(gè)爬蟲框架和異步框架來的快,但這也可以作為一種爬蟲的思路。 ??celery是一個(gè)基于分布式消息傳輸?shù)漠惒饺蝿?wù)隊(duì)列,它專注于實(shí)時(shí)處理,同時(shí)也支持任務(wù)調(diào)度。關(guān)于celery的更多介紹及例子,筆者可以參考文章Python之celery的簡...
閱讀 1089·2021-11-19 09:40
閱讀 2227·2021-11-15 18:00
閱讀 1278·2021-10-18 13:34
閱讀 2258·2021-09-02 15:40
閱讀 1543·2019-08-30 14:01
閱讀 1122·2019-08-30 11:11
閱讀 2489·2019-08-29 15:26
閱讀 735·2019-08-29 14:15