Spring Blog
以前の記事では、Spring @MVCバージョン3.0に追加されたREST機能についてブログに書きました。 その後、Alef氏は導入された機能を使って、Pet ClinicアプリケーションにAtomビューを追加したことを書きました。
RestTemplate
RestTemplateは、クライアント側のHTTPアクセスのための中心的なSpringクラスです。 概念的には、JdbcTemplate、JmsTemplate、および Spring Framework や他のポートフォリオ プロジェクトで見られるその他のさまざまなテンプレートに非常によく似ています。 例えば、RestTemplateは一度構築されるとスレッドセーフであり、コールバックを使用してその操作をカスタマイズすることができます。
RestTemplateのメソッド
テンプレートの主要なエントリーポイントは6つの主要なHTTPメソッドにちなんで名付けられています:
HTTP | RestTemplate |
---|---|
DELETE | delete(String, String….) |
GET | getForObject(String, Class, String….) |
HEAD | headForHeaders(String, String …) |
OPTIONS | optionsForAllow(String, String….) |
POST | postForLocation(String, Object, String…) |
PUT | put(String, Object, String…) |
これらのメソッドの名前は、どのHTTPメソッドを呼び出すかを明確に示し、名前の2番目の部分は何が返されるかを示します。 例えば、getForObject()はGETを実行し、HTTPレスポンスを任意のオブジェクトタイプに変換して、そのオブジェクトを返します。postForLocationはPOSTを実行し、指定されたオブジェクトをHTTPリクエストに変換して、新しく作成されたオブジェクトが見つかるHTTP Locationヘッダーをレスポンスとして返します。
URI テンプレート
これらの各メソッドは、第 1 引数として URI を受け取ります。 そのURIはURIテンプレートにすることができ、テンプレートを通常のURIに展開するために変数を使用することができます。 テンプレート変数は2つの形式で渡すことができます: 文字列変数引数の配列として、または Map<String, String>として渡します。 string varargs バリアントは、与えられたテンプレート変数を順に展開していくので、
String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21");
は http://example.com/hotels/42/bookings/21 に対して GET を実行することになります。 map variantは、変数名に基づいてテンプレートを展開するため、多くの変数を使用する場合や、一つの変数を複数回使用する場合などに便利です。 例えば、
Map<String, String> vars = new HashMap<String, String>();vars.put("hotel", "42");vars.put("booking", "21");String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class, vars);
http://example.com/hotels/42/rooms/42に対してもGETを実行します。
HttpMessageConverters
getForObject()、postForLocation()、put()の各メソッドに渡されたオブジェクトや、メソッドから返されたオブジェクトは、HttpMessageConvertersによってHTTPリクエストやHTTPレスポンスに変換されます。 主要なmimeタイプとJavaタイプのコンバーターは、デフォルトで登録されていますが、独自のコンバーターを書いて、RestTemplateにプラグインすることもできます。
Using the RestTemplate to retrieve photos from Flickr
RestTemplateのさまざまな方法を説明するのではなく、Yahoo!sのオンライン写真共有アプリケーションであるFlickrから写真を取得するためにRestTemplateをどのように使用するかを紹介します。 このサンプル・アプリケーションは、指定された検索語に一致する写真をFlickrで検索します。 そして、これらの写真をシンプルなSwing UIを使って表示します。
写真の検索
Flickrは、膨大な写真のライブラリを操作するためのさまざまなAPIを公開しています。 flickr.photos.searchメソッドでは、http://www.flickr.com/services/rest?method=flickr.photos.search&api+key=xxx&tags=penguinsにGETリクエストを発行し、APIキーと検索対象(ここではペンギン)を入力することで、写真を検索できます。 その結果、クエリに適合した写真を記述した XML ドキュメントが返されます。
<photos page="2" pages="89" perpage="10" total="881"><photo owner="" secret="a123456" server="2" title="test_04"ispublic="1" isfriend="0" isfamily="0" /><photo owner=""secret="b123456" server="2" title="test_03"ispublic="0" isfriend="1" isfamily="1" /><photo owner=""secret="c123456" server="2" title="test_01"ispublic="1" isfriend="0" isfamily="0" /><photo owner=""secret="d123456" server="2" title="00_tall"ispublic="1" isfriend="0" isfamily="0" /></photos>
RestTemplateを使用して、このようなドキュメントを取得することは非常に簡単です。
final String photoSearchUrl = "http://www.flickr.com/services/rest?method=flickr.photos.search&api+key={api-key}&tags={tag}&per_page=10";Source photos = restTemplate.getForObject(photoSearchUrl, Source.class, apiKey, searchTerm);
ここで、apiKeyとsearchTermはコマンドラインで指定された2つの文字列です。 このメソッドはSourceHttpMessageConverterを使って、HTTP XMLレスポンスをjavax.xml.transform.Sourceに変換します(なお、SourceHttpMessageConverterはSpring 3.0 M2がリリースされた直後に導入されたものなので、使用するには最新のスナップショット(または次期M3)を入手する必要があります)。
写真の取得
次に、XPath式を使ってドキュメントのすべての写真要素を取得します。 これには、Spring Web ServicesのXPathTemplateを使用します。 XPathTemplateは、Spring Web ServicesのXPathTemplateを使用して、 //photo式を実行し、ドキュメント内の任意の場所で発生するすべてのphoto要素を返します。 NodeMapperはコールバックインターフェースで、そのmapNode()メソッドは、ドキュメント内の各photo要素に対して呼び出されます。 今回の例では、この要素のserver、id、secret属性を取得し、それらを使ってMapを埋めています。 最後に、RestTemplateを使って、写真をjava.awt.image.BufferedImageとして取得しています。
List<BufferedImage> imageList = xpathTemplate.evaluate("//photo", photos, new NodeMapper() { public Object mapNode(Node node, int i) throws DOMException { Element photo = (Element) node; Map<String, String> variables = new HashMap<String, String>(3); variables.put("server", photo.getAttribute("server")); variables.put("id", photo.getAttribute("id")); variables.put("secret", photo.getAttribute("secret")); String photoUrl = "http://static.flickr.com/{server}/{id}_{secret}_m.jpg"; return restTemplate.getForObject(photoUrl, BufferedImage.class, variables); }});
例えば、上記のXMLドキュメントでは、imageListには4つの画像が含まれています。 最初に取得した画像のURLはhttp://static.flickr.com/2/2636_ a123456_m.jpg、2番目はhttp://static.flickr.com/2/2635_ b123456_m.jpgといった具合になります。
画像の変換
このコードを動作させるためには、もうひとつ必要なことがあります。それは、HTTPレスポンスから読み取り、そこからBufferedImageformを作成できるHttpMessageConverterを書くことです。 Java Image I/O APIを使ってこれを行うのは非常に簡単で、HttpMessageConverterインターフェースで定義されているread()メソッドを実装するだけです。
public class BufferedImageHttpMessageConverter implements HttpMessageConverter<BufferedImage> { public List<MediaType> getSupportedMediaTypes() { return Collections.singletonList(new MediaType("image", "jpeg")); } public boolean supports(Class<? extends BufferedImage> clazz) { return BufferedImage.class.equals(clazz); } public BufferedImage read(Class<BufferedImage> clazz, HttpInputMessage inputMessage) throws IOException { return ImageIO.read(inputMessage.getBody()); } public void write(BufferedImage image, HttpOutputMessage message) throws IOException { throw new UnsupportedOperationException("Not implemented"); }}
画像をアップロードするのではなく、ダウンロードするだけなので、write() を実装していないことに注意してください。 あとは、このコンバータをRestTemplateに接続するだけです。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="com.springsource.samples.resttemplate.FlickrClient"> <constructor-arg ref="restTemplate"/> <constructor-arg ref="xpathTemplate"/> </bean> <bean class="org.springframework.web.client.RestTemplate"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/> <bean class="com.springsource.samples.resttemplate.BufferedImageHttpMessageConverter"/> </list> </property> </bean> <bean class="org.springframework.xml.xpath.Jaxp13XPathTemplate"/></beans>
写真を表示する
最終段階として、写真をシンプルなGUIで表示します。
JFrame frame = new JFrame(searchTerm + " photos");frame.setLayout(new GridLayout(2, imageList.size() / 2));for (BufferedImage image : imageList) { frame.add(new JLabel(new ImageIcon(image)));}frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.pack();frame.setVisible(true);
以下のようになります。
全体として、この記事では、HTTPサーバーと対話するためにRestTemplateを使用することがいかに簡単であるかをお見せできたと思います。 たった30行のJavaコードで、みんなの大好きな鳥、ペンギンの写真を表示するGUIを作成しました。
ダウンロード
上記のコードを含む Maven プロジェクトは、ここからダウンロードできます。 このプロジェクトは、Springのナイトリースナップショットビルドをベースにしていることに注意してください。 来るべき Spring の Milestone 3 には、必要なクラスが含まれています。