2014年4月17日木曜日

UUID <-> Base64 変換する Jackson用wrapperクラス

データベースでUUIDを何かと使うのですが、
JSONで出力すると'afb055a0-c18f-11e3-8b27-b1398a321474'みないな
文字列になってちょっと長いですし、
UUIDだというのがバレバレでそこはかとなく心配になります。

なので、JSONマッパーに渡すUUIDをwrapしてBase64としてマップするクラスを作ったので共有
表題にある通りJackson向けです


@JsonValueアノテーションをつけることで
このクラスをシリアライズする際にtoString()が呼ばれBase64化された値を返します

デシリアライズ 時には、
UUIDBase64(String uuidBase64)で初期化されUUIDBase64クラスとしてマップされます。


UUIDBase64.java :

import java.nio.ByteBuffer;
import java.util.UUID;

import org.apache.commons.codec.binary.Base64;
import org.codehaus.jackson.annotate.JsonValue;
import org.codehaus.jackson.annotate.JsonIgnore;

public class UUIDBase64 {
   
    @JsonIgnore
    private final UUID uuid;

    public UUIDBase64(UUID uuid) {
        this.uuid = uuid;
    }

    public UUIDBase64(String uuidBase64) {
        byte[] bytes = Base64.decodeBase64(uuidBase64);
        ByteBuffer bb = ByteBuffer.wrap(bytes);
        this.uuid = new UUID(bb.getLong(), bb.getLong());
    }
   
    @JsonValue
    public String toString(){
        if (uuid == null)
            return null;
       
        ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
        bb.putLong(uuid.getMostSignificantBits());
        bb.putLong(uuid.getLeastSignificantBits());           
        return Base64.encodeBase64URLSafeString(bb.array());
    }
   
    public UUID getUUID() {
        return this.uuid;
    }
   
    public static UUIDBase64 fromUUID(UUID uuid) {
        return new UUIDBase64(uuid);
    }
   
    public static UUIDBase64 fromBase64(String str) {
        return new UUIDBase64(str);
    }

}


次のように変換されます

class User {
    UUIDBase64 id;
}

<-> { "id" : "base64の文字列" }

2014年4月11日金曜日

HttpServletRequestのthread内共有 Spring編

HttpServletRequestを参照しようとした時に
引数で渡さずに、static fieldのthread localに保存して
スレッド内から参照できるようにする方法を昔紹介していましたが、
Spring使用時には標準の機能としてすでにあります。


次のようにRequestContextHolderからHttpServletRequestを取得します。

        RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = 

(HttpServletRequest)attrs.resolveReference(RequestAttributes.REFERENCE_REQUEST);


web.xmlにlistenerを登録する必要があります。

web.xml:

    <listener>
      <listener-class>

     org.springframework.web.context.request.RequestContextListener
   </listener-class>
    </listener>



Spring 2.5以上が必要です
使い道としては、エラー出力にリクエスト情報を出すとか
エラーハンドルのためにいちいち、
リクエストを引数には渡せないのでthreadに保持しているものを参照します。


ThreadLocalに自分で保存する記事よりは
既存のものを使うべきでしょう