1. 程式人生 > >關於型別轉換這件事

關於型別轉換這件事

有同事和我討論了一個問題:怎樣把Date轉換成正確的格式給前端?當然可以手動轉換,但是他更期望通過框架配置的方式解決。關於這個問題有兩種思路:1、在orm框架中轉換;2、在json框架中轉換。在這裡我想分享一下自己的理解和經驗。

誰可以做?

型別轉換不是什麼神奇的事,看原始碼就會發現,它只是一堆的if else。如果是基本型別怎麼轉,如果是列舉類怎麼轉,如果是日期怎麼轉,如果是普通Object怎麼轉。也就是各種的type handler。只要做了型別轉換這件事,正常一點的框架,很自然都會支援配置這種handler,以及新增handler。

FastJson的程式碼片段

        if
(writer == null) { if (Map.class.isAssignableFrom(clazz)) { config.put(clazz, MapSerializer.instance); } else if (List.class.isAssignableFrom(clazz)) { config.put(clazz, ListSerializer.instance); } else if (Collection.class.isAssignableFrom(clazz)) { config.put(clazz, CollectionSerializer.instance); }
else if (Date.class.isAssignableFrom(clazz)) { config.put(clazz, DateSerializer.instance); } else if (JSONAware.class.isAssignableFrom(clazz)) { config.put(clazz, JSONAwareSerializer.instance); } else if (JSONStreamAware.class.isAssignableFrom(clazz)) { config.put(clazz, JSONStreamAwareSerializer.instance); }
else if (clazz.isEnum() || (clazz.getSuperclass() != null && clazz.getSuperclass().isEnum())) { config.put(clazz, EnumSerializer.instance); } else if (clazz.isArray()) { Class<?> componentType = clazz.getComponentType(); ObjectSerializer compObjectSerializer = getObjectWriter(componentType); config.put(clazz, new ArraySerializer(componentType, compObjectSerializer)); } else if (Throwable.class.isAssignableFrom(clazz)) { config.put(clazz, new ExceptionSerializer(clazz)); } else if (TimeZone.class.isAssignableFrom(clazz)) { config.put(clazz, TimeZoneCodec.instance); } else if (Appendable.class.isAssignableFrom(clazz)) { config.put(clazz, AppendableSerializer.instance); } else if (Charset.class.isAssignableFrom(clazz)) { config.put(clazz, CharsetCodec.instance); } else if (Enumeration.class.isAssignableFrom(clazz)) { config.put(clazz, EnumerationSeriliazer.instance); } else if (Calendar.class.isAssignableFrom(clazz)) { config.put(clazz, CalendarCodec.instance); } else if (Clob.class.isAssignableFrom(clazz)) { config.put(clazz, ClobSeriliazer.instance); } else { boolean isCglibProxy = false; boolean isJavassistProxy = false; for (Class<?> item : clazz.getInterfaces()) { if (item.getName().equals("net.sf.cglib.proxy.Factory")) { isCglibProxy = true; break; } else if (item.getName().equals("javassist.util.proxy.ProxyObject")) { isJavassistProxy = true; break; } } if (isCglibProxy || isJavassistProxy) { Class<?> superClazz = clazz.getSuperclass(); ObjectSerializer superWriter = getObjectWriter(superClazz); config.put(clazz, superWriter); return superWriter; } if (Proxy.isProxyClass(clazz)) { config.put(clazz, config.createJavaBeanSerializer(clazz)); } else { config.put(clazz, config.createJavaBeanSerializer(clazz)); } }
View Code

ORM or JSON?

java bean中的欄位,反映的應該是該欄位的最原始的型別。日期就應該是Date,列舉值就應該是列舉型別。如何把它在資料庫中正確地存取,是orm框架的事;如何正確地轉換成字串或者從字串解析,是json框架的事。所以針對“把Date轉換成正確的格式給前端”這件事,我理解還是由json框架來做比較合適。

GSON

gson要自定義配置可通過GsonBuilder來構造Gson物件。

示例程式碼

        Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
        String jsonString = gson.toJson(eventProcess);

FASTJSON

阿里的fastjson的自定義轉換格式的處理方式更為簡單明瞭,只需使用com.alibaba.fastjson.annotation.JSONField註解。

示例程式碼

    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

Mybatis

Mybatis可以在mybatis-config.xml中定義自己的typeHandlers。下面的程式碼示例中,java bean的欄位為列舉型別,資料庫儲存為數字,使用列舉物件的getOrder方法值進行轉換。

mybatis-config.xml

    <typeHandlers>
        <typeHandler handler="com.common.mybatis.EnumTypeOrderHandler" javaType="com.massage.enumType.OrderStatus"/>
    </typeHandlers>

com.common.mybatis.EnumTypeOrderHandler

public class EnumTypeOrderHandler<E extends Enum<E>> extends BaseTypeHandler<E> {

    private Class<E> type;
    private final E[] enums;

    public EnumTypeOrderHandler(Class<E> type) {
        if (type == null) throw new IllegalArgumentException("Type argument cannot be null");
        this.type = type;
        this.enums = type.getEnumConstants();
        if (this.enums == null) throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
    }


    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
        int order = parameter.ordinal();
        try {
            Method getOrder = type.getMethod("getOrder");
            order = (int) getOrder.invoke(parameter);
        } catch (Exception e) {
        }
        ps.setInt(i, order);
    }

    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        int order = rs.getInt(columnName);
        if (rs.wasNull()) {
            return null;
        } else {
            return parseOrder(order);
        }
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        int order = rs.getInt(columnIndex);
        if (rs.wasNull()) {
            return null;
        } else {
            return parseOrder(order);
        }
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        int order = cs.getInt(columnIndex);
        if (cs.wasNull()) {
            return null;
        } else {
            return parseOrder(order);
        }
    }

    private E parseOrder(int order) throws SQLException {
        try {
            for (E anEnum : enums) {
                try {
                    Method getOrder = type.getMethod("getOrder");
                    int anOrder = (int) getOrder.invoke(anEnum);
                    if (anOrder == order) {
                        return anEnum;
                    }
                } catch (Exception e) {
                    return enums[order];
                }
            }
        } catch (Exception ex) {
            throw new IllegalArgumentException("Cannot convert " + order + " to " + type.getSimpleName() + " by ordinal value.", ex);
        }
        throw new IllegalArgumentException("Cannot convert " + order + " to " + type.getSimpleName() + " by ordinal value.");
    }

}
View Code

Spring

說到Spring,大家想到的就是ioc和aop。然而spring並不只有ioc和aop。這些年來Spring家出了很多產品,都是基於Spring核心API,也都天然地擴充套件性相當之強。Spring似乎提供了做一個基礎框架所需的一切,包括型別轉換(參見http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#validation一章)。比如,SpringMVC接收請求引數轉為bean,Spring Batch的Reader讀取記錄為bean,都用到了PropertyEditor。

自定義TimeEditor

public class TimeEditor extends PropertyEditorSupport {

    private String format = "H:mm";

    public TimeEditor() {
    }

    public TimeEditor(String format) {
        this.format = format;
    }

    public void setAsText(String text) {
        DateFormat df = new SimpleDateFormat(format);
        try {
            Date date = df.parse(text);
            Time time = new Time(date.getTime());
            setValue(time);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

}
View Code

在Controller中使用自定義PropertyEditor來解析時間格式

    public Entity parseModel(HttpServletRequest request) {
        Object o = null;
        try {
            o = getEntityClass().newInstance();
        } catch (Exception e) {
            throw new RuntimeException("無法建立類的例項:" + getEntityClass());
        }
        DataBinder dataBinder = new DataBinder(o);
        dataBinder.registerCustomEditor(Time.class, new TimeEditor());
        MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request);
        dataBinder.bind(mpvs);

        return (Entity) o;
    }
View Code

相關推薦

關於型別轉換

有同事和我討論了一個問題:怎樣把Date轉換成正確的格式給前端?當然可以手動轉換,但是他更期望通過框架配置的方式解決。關於這個問題有兩種思路:1、在orm框架中轉換;2、在json框架中轉換。在這裡我想分享一下自己的理解和經驗。 誰可以做? 型別轉換不是什麼神奇的事,看原始碼就會發現,它只是一堆的if

阿裏王堅:機器比人做得好的,那就不該由人來做

關於 無效 管控 產出 快的 驅動 tro 內核 增長 去年雲棲大會上,杭州市政府聯合阿裏雲在內的13家企業提出建設“城市大腦”項目。 雷鋒網了解到,“城市大腦”可以理解為一座城市的人工智能中樞。其內核采用阿裏雲ET人工

以Spring整合EhCache為例從根本上了解Spring緩存(轉)

內置 tor 重要 date 清單 one display 結合 boa 前兩節“Spring緩存抽象”和“基於註解驅動的緩存”是為了更加清晰的了解Spring緩存機制,整合任何一個緩存實現或者叫緩存供應商都應該了解並清楚前兩

NGOT空投活動第三波,幣圈老司機都在做,註冊有禮!

type 大小 png fda watermark 第三波 操作 51cto 提交 最近,Fcoin就像一陣龍卷風,吹遍了整個幣圈。NGOT也借此發起了第三波空投活動,註冊就有禮,僅限今天(2018.6.30)。按照如下操作就可以免費領好禮:1.註冊Fcoin賬號(www.

厲害!Google用Python幹了

Google曾給出了一幅世界女性胸部尺寸分佈地圖,從地圖中可以明顯看出中國大部分地區呈現綠色(表示平均胸部尺寸為A罩杯),少部分地區呈現藍色(表示平均胸部尺寸為B罩杯)。 現在李寧老師也來驗證一下這個說法對不對。本文實現一個非常有趣的專案,這個專案是關於胸罩銷售資料分析的。 本專案會從天貓抓取胸罩銷售

論跳槽

跳槽在任何行業都是屢見不鮮的一種現象,尤其是在年關將近,年終獎即將發放的此時,很多人都開始去尋找新的下家,為年後跳槽做準備。跳槽後出現的情況無非就是‘我現在過得比以前好’和‘還是以前的工作好’。當你出現第二種情況的時候,說明你並沒有理智的去看清你所在的行業,只是盲目的看到了比你過得好的那些人,盲目的

java (x) 關於多執行緒的CPU密集型和IO密集型

CPU密集型 CPU密集型會消耗掉大量的CPU資源,例如需要大量的計算,視訊渲染啊,模擬啊之類的。這個時候CPU就卯足了勁在執行,這個時候切換執行緒,反而浪費了切換的時間,效率不高。 就像你的大腦是CPU,你本來就在一本心思地寫作業,多執行緒這時候就是要你寫會作業,然後立刻敲一會程式碼,然後在P個圖,然後

18年年終總結之談談焦慮

  眼看著18年也到頭了,無總結不年終,來個總結回顧一下2018年,這一年,娛樂圈的瓜多的吃不過來,P2P一家家不斷暴雷,股市依舊一片綠,共享單車倒得差不多,沒倒的都一一被收購,傳說有很多大公司裁員,人工智慧的畢業生被高價哄搶。工資上漲不了多少,房價物價依然居高不下,年輕人越來越關注自己的髮量了,做IT行業的

外牆清洗,到底怎樣才算安全?

廣州繼上次5月“蜘蛛人”墜亡事故之後10月又被報出一起外牆清洗工不幸墜落的事故訊息。10月8日下午5點左右,南方財經的記者收到街坊報料,在廣州市白雲區廣園中路333號一家汽車4s店門口,外牆清潔工作架倒塌,造成一死一傷。當記者趕到現場的時候,發現一個白色的鐵架子橫在路邊,一頭壓在一輛汽車上,死者是一名女性外牆

外墻清洗,到底怎樣才算安全?

結構 汽車 靜態 分享圖片 場景 其他 避免 mark blog 廣州繼上次5月“蜘蛛人”墜亡事故之後10月又被報出一起外墻清洗工不幸墜落的事故消息。10月8日下午5點左右,南方財經的記者收到街坊報料,在廣州市白雲區廣園中路333號一家汽車4s店門口,外墻清潔工作架倒塌,造

如何用大資料來看IG在LOL世界錦標賽上奪冠

11月5日(NBD)-中國傳奇聯盟(LOL)俱樂部Invictus Gming在週六以3比0擊敗對手Fnatic獲得2018年世界傳奇聯賽冠軍。 值得注意的是,Invictus Gming是8年來第一家獲得世界冠軍的LPL俱樂部。LPL,LOL專業聯賽,通常指的

阿里雲釋出遷移解決方案,“遷移上雲”有專業的人做

近日,阿里雲釋出了遷移解決方案,旨在為客戶提供一站式遷移綜合解決方案,將遷移相關的資源統一呈現,幫助客戶安全、穩定和高效遷移上雲。 解決什麼問題?  客戶想要上雲,需要自己評估整體方案,但往往會有一些問題無法考慮到,導致投入多、效率低、同時也可能造成潛在風險; 而阿里雲新

【我的E家】如果一值得去做,那麼也值得做好。

blog入口篇 管理經典blog QA境界:http://blog.csdn.net/huazhongkejidaxuezpp/article/details/78128487 團隊管理:http://blog.csdn.net/huazhongkejidaxuezpp

看懂英文技術文,每天只需要10分鐘做

程式設計師這個行業是很特殊的。之所以說特殊,就是因為它所有的技術大多來自歐美,所以最主流,最新鮮

花椒六間房集團CEO劉巖:把直播做完

花椒直播和六間房合併,原六間房創始人劉巖出任新集團CEO 6月27日,宋城演藝釋出公告,稱旗下全資子公司北京六間房科技有限公司(即六間房的公司主體,下稱:六間房)將與北京密境和風科技有限公司(即花椒直播的公司主體,下稱:密境和風)進行重組。原六間房創始人兼執行長劉巖將出任新集團CEO。 3歲的花椒,或許在

世界上沒有懷才不遇,關鍵是找準你的優勢

轉自:https://blog.csdn.net/harrymeng/article/details/76240455 人才是企業管理中討論最多也是最讓人頭痛的要素,管理者通常都是求賢如渴,愛才如命。他們深知,要想讓企業不斷地發展,不斷往附加價值高的領域定位,這不僅僅需要人才,而且要讓人盡其才,

寫程式碼從模仿開始,聊聊閱讀原始碼

程式設計師在工作過程中,會遇到很多需要閱讀原始碼的場景,比如技術預研、選擇技術框架、接手以前的專案、review他人的程式碼、維護老產品等等。可以說,閱讀原始碼是程式設計師的基本功,這項基本功是否紮實,會在很大程度上影響一個程式設計師在技術上的成長速度。 2014年寫《Qt on Android核心

不論共識大會能否引領幣市暴漲,我們應該著手做了

幣市有個魔咒就是“逢會必跌”,每年逢會當所有人認為行情將起飛時,卻出現了下跌,雖不知是什麼原因造成的。但共識大會除外,每年一次的共識大會就像擁有劈開這魔咒的神斧一般,從會議開始,主流貨幣就會引領一輪暴漲行情。那麼今年共識大會召開在即,是否還會像往年一樣引領行情暴漲呢?下面先來

關於MD5破解

前 幾天在論壇上看到有人在討論MD5的破解,很多人對MD5的理解讓我大跌眼鏡:有人認為MD5是一種加密演算法,有人認為由於無法從MD5 hash回覆出明文,因此對其破解的研究毫無意義,甚至因此置疑王小云教授的成果毫無意義,真是讓人遺憾。 因此今天決定說說MD5的破解,算是義務普及。有關MD5的描述請參考Wi

也談說話--《好好說話》讀後感

溝通技能已經成為一種重要的生存技能,隨著人工智慧的興起,很多專業領域的工作將會慢慢被計算機取代,而與人的溝通和交流相對於專業知識,則相對很難被取代,因為交流和溝通中需要體現人的情緒和感情,計算機在這塊相對於人不具有優勢。在很多領域計算機要取代人可能需要更長的時間