6.Spring3.0から追加された新しい部品の紹介
概要
ここではSpring3.0から追加された新しい部品を少し紹介していこうと思います。
追加された部品はいろいろありますが、面白そうなものを一部だけピックアップしようと思います。
1つのキーに複数の値を設定できるMap(org.springframework.util.MultiValueMap)
WEBなどでは、1つのキーに複数の値を紐付けたくなります。
そんなときに使用できるMultiValueMapという部品を紹介します。
【MultiValueMapのサンプル】
MultiValueMap<String, String> params1 = new LinkedMultiValueMap<String, String>();
//同じキーに2つ追加する。
params1.add("a", "あ");
params1.add("a", "い");
//1つ目の値だけ取得する
String val = params1.getFirst("a"); //⇒"あ"
//あるキーの値をすべて取得する
List<String> list = params1.get("a"); //⇒"あ", "い"
//複数の値を一気に設定する
params1.put("b", Arrays.asList(new String[]{"う", "え"}));
//1つ目の値だけのMapを取得する
Map m = params1.toSingleValueMap();
//値を1つだけ設定する
params1.set("a", "お"); //⇒キー"a" の値が"お"だけになる
まず、MultiValueMapはインターフェースになっていて、以下のMapの派生インターフェースになっています。
Map<K, List<V>>
ですので、put()や、get()での値は、Listになります。
そして実体のクラスは、LinkedMultiValueMapになります。
Mapへの登録の仕方や、取得の仕方は上記サンプルを見るとおおよそ分かるかとおもいます。
Mapインターフェースで提供するメソッドの他に、add(), getFirst(), set(), toSingleValueMap() などが追加されています。
少し直感と違うかもしれないので、上記のサンプルをよく確認していただければと思います。
【補足】
実は、MultiValueMapは、apache commonsライブラリの中にも同名のクラス名で存在します。
apacheのMultiValueMapは、Springのものと動作がかなり違いますので既にそちらをお使いの方は気をつけてください。
また、apacheのものはgenericに対応していませんので、genericで型を指定したい場合はSpringの方が有利です。
【注意点】
Springの設定ファイル上でDIしたとき、mapタグはデフォルトでは自動的にMultiValueMapには変換できません。
自作で変換方法を作らなければなりません。
変換方法のカスタマイズは別の記事で記述予定ですので、それをご覧いただければと思います。
(参考:7.型変換のカスタマイズ (Spring3.0から追加された機能))
POJOの設定コピーなどを行うユーティリティ(org.springframework.beans.BeanUtils)
これもそもそもはapache commonsのライブラリのPropertyUtilsやBeanUtilsにあるものですが、少し機能が違ったりしますので面白いかと思います。
とりあえずは使用サンプルを見ていただいた方が分かりやすいと思います。
【BeanUtilsのサンプル】
//プロパティ値のコピー
Pojo p1 = new Pojo();
Pojo p2 = new Pojo();
p1.setEncode("ff");
p1.setPath("gg");
BeanUtils.copyProperties(p1, p2);
//インスタンスの生成
Pojo a = BeanUtils.instantiate(Pojo.class);
1つ目のプロパティのコピーはapacheライブラリのPropertyUtilsにもあるものです。
ただし、引数の順番が逆になっていて、copyProperties(コピー元, コピー先) というようになっていますので注意してください。
次のインスタンスの生成はSpringオリジナルです。
通常であればコンストラクタクラスを取得してnewInstance()メソッドを呼び出さないといけないのでそこそこ面倒ですが、メソッド1つで可能になります。
【補足】
BeanUtilsには他にも、beanのプロパティの型のチェックを行ったり、PropertyDescriptorなどを取得するメソッドが用意されています。
WEB通信の結果を表す部品(HttpHeaders、ResponseEntity<T>)
あまり使うことはないかも知れませんが面白かったので紹介します。
Spring3.0からはREST(WEBサービスのようなもの)を扱う機能が追加されました。
そのためHTTPのヘッダを扱う部品HttpHeadersクラスも導入されています。
ここでは、それを紹介します。
【HttpHeadersのサンプル】
HttpHeaders h = new HttpHeaders();
h.add("Location", "http://localhost:8080/soracane/sec/homeAction.do");
h.add("Content-Type", "text/html;charset=utf-8");
h.add("Content-Length", "1106");
//URLを取得(リダイレクトの場合はリダイレクト先)
URI uri = h.getLocation(); //⇒"http://localhost:8080/soracane-batch-viewer/sec/homeAction.do"
//コンテントタイプの取得
String type = h.getContentType().getType(); //⇒"text"
//コンテントの長さ
long len = h.getContentLength(); //⇒1106
HttpHeadersは、MultiValueMapを継承しています。
ですので、add()メソッドで値を追加していきます。
しかし、単純に値を保管するだけでなく、getXxxx()で各種のヘッダ情報を取得できます。
SpringのRESTの部品を使う限り、レスポンスのヘッダなどは自動的に作られるため、あまり自分でnewして値を設定することはないかもしれません。
しかし、普通のHTTP通信をしたい場合などはapacheライブラリの、org.apache.http.client.HttpClient を使用することになるかと思います。
このクライアントをラップして使いやすくするときに、ヘッダを返す場合などはHttpHeadersを使用すると、使う側は便利になると思います。
【補足】
また、この他にもResponseEntity<T>というクラスも用意されていて、ヘッダ、ボディー、ステータスを持つクラスになっています。
型 T は、ボディ(通常HTML部分)を表すものです。
RESTの場合、ボディはHTML以外にも、JSONなどの場合もあります。JSONの場合、JSONがJavaのPOJOを表すこともできます。
型 T は、ボディの文字列⇒POJO の変換をした結果(例: ResponseEntity<Member> )でもよいですし、
元の文字列のままResponseEntity<String>でもよいです。
このEntityをHTTPの通信の結果として返してあげればとても便利です。
通信結果のステータスがリダイレクトかどうかなどを簡単に確認することもできます。
【ResponseEntityの使用サンプル】
ResponseEntity<String> response = sendPost(); //何かHTTP通信後に結果を返す自作メソッド
Series series = response.getStatusCode().series();
if(series.equals(HttpStatus.Series.REDIRECTION)){
System.out.println("リダイレクト要求が返ってきました。URI=" + response.getHeaders().getLocation());
}
ステータスの確認は意外と面倒で、HTTPヘッダの仕様を確認しながらプログラムしなければなりません。
ResponseEntityがそのあたりを分かりやすくしてくれているので、かなり楽になり、間違いも少なくなります。
上記のようにステータスを確認することも、getBody()でHTMLを取得することもできます。
必要な情報がそろっていて使う側は便利です。
Created Date: 2011/11/01