摘要:支持等眾多語言。此處的是經過封裝的,和中類似。相關模板均在類中定義,諸如。優化后的使用方法為中的錯誤先看看這段代碼反序列化后獲取,因為中是類型,這里面可能是,也可能是,因此需要注意。參考資料讓版支持類型
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是一個基于二進制高效的對象序列化Library用于跨語言通信。它可以像JSON那樣,在許多種語言之間交換結構對象;但是它比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中的數據
yii2將session數據寫入redis中,為了在java api中可以使用后臺用戶登錄的信息,則需要通過java解析session數據。
先看看如何使用:
// sessionBytes是byte類型 if (null != sessionBytes) { MessagePack pack = new MessagePack(); // new一個msgpack對象 Map map = null; try { map = (Map) pack.read(sessionBytes); // 通過Msgpack的read讀取字節,強制轉換為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寫入的數據是uid、un、avt、cst、mbl這樣的key,經過Msgpack序列化后的key都加上了",強制轉換為Map對象后,map中的key并沒有去掉這些轉義字符,value也不例外,因此使用trim去掉了value兩邊的"。需要注意,如果是yii2的話,一般key都有前綴,此處作者把前綴刪掉了,下面所有代碼均如此。
此處的trim是經過封裝的,和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; }優化getMessagePackValue方法,不再使用trim處理數據
@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有很多數據模板,這里使用TString模板和TValue模板。相關模板均在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優化后的使用方法
// 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; }錯誤: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,因為User中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報錯,錯誤:org.msgpack.type.intValueImpl cannot be cast to java.lang.Long,于是修改為下面這般,如果是IntegerValue的實例,則強制轉換為Long類型,但是依然報錯:
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); } }
最后強制類型轉換IntegerValue,再獲取longValue,即為上面函數中的那般才解決此錯誤。
參考資料1.讓java版msgpack支持Object類型
2.MessagePack
3.msgpack
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/66570.html
摘要:的簡介是一個基于分布式消息傳輸的異步任務隊列,它專注于實時處理,同時也支持任務調度。目前支持等作為消息代理,但適用于生產環境的只有和官方推薦。任務處理完后保存狀態信息和結果,以供查詢。 celery的簡介 ??celery是一個基于分布式消息傳輸的異步任務隊列,它專注于實時處理,同時也支持任務調度。它的執行單元為任務(task),利用多線程,如Eventlet,gevent等,它們能被...
摘要:是一個高效的二進制序列化框架它像一樣支持不同語言間的數據交換但是它的性能更快序列化之后的碼流更小的特點如下編解碼高效性能高序列化之后的碼流小支持跨語言編碼器和解碼器開發編碼器開發負責將類型的對象編碼為數組然后添加到集合中解碼器開發首先從數 MessagePack 是一個高效的二進制序列化框架, 它像 JSON 一樣支持不同語言間的數據交換, 但是它的性能更快, 序列化之后的碼流更小. ...
摘要:這里序列化的概念可能更為廣泛和籠統一些,包括傳統的等。就目前來看,等二進制序列化無論是速度上還是數據大小上,都要比文本序列化更好。,反序列化方法。用法,序列化方法。 原文地址:https://t.ti-node.com/thread/... 數據的序列化是一個非常有用的功能,然而目測很多人跟我一樣,在剛接觸這玩意的時候壓根就不理解這貨色到底是干啥用的,反正老師說了,實在理解不了就先背...
摘要:第二集非必選持續集成編譯打包部署到線上環境集成前言在持續集成第一集中講解了關于如果編譯,打包,發布包到私服。在下面一集中,也就是第二集中,開始講解如何持續集成可運行的服務包到測試和正式環境。 第二集 hudson+gradle+git+maven(非必選)持續集成編譯,打包,部署到線上環境集成 前言 在持續集成第一集中,講解了關于如果編譯,打包,發布jar包到maven私服。在下面一集...
摘要:是一個基于分布式消息傳輸的異步任務隊列,它專注于實時處理,同時也支持任務調度。本文將介紹如何使用來加速爬蟲。本文爬蟲的例子來自文章爬蟲的種姿勢。雖然沒有這個爬蟲框架和異步框架來的快,但這也可以作為一種爬蟲的思路。 ??celery是一個基于分布式消息傳輸的異步任務隊列,它專注于實時處理,同時也支持任務調度。關于celery的更多介紹及例子,筆者可以參考文章Python之celery的簡...
閱讀 1074·2021-11-19 09:40
閱讀 2213·2021-11-15 18:00
閱讀 1267·2021-10-18 13:34
閱讀 2248·2021-09-02 15:40
閱讀 1533·2019-08-30 14:01
閱讀 1113·2019-08-30 11:11
閱讀 2482·2019-08-29 15:26
閱讀 722·2019-08-29 14:15