REST なウェブサービスAPIを試すときによく使っているソースコード。
Rest, GetRequest, XmlResponse の3つのクラスで構成。
Java SE 5.0 以降で使用可能。

(´-`).。oO(他のJavaプログラマってどうやってRESTを扱っているんだろう……いいライブラリとかあるのかな)

ただ、JavaMail API 1.4 が必要なのがちょっと面倒。
ContentType 解析クラスを作れば済む話なんだけど……

Rest.java


import java.io.*;
import java.net.*;
import javax.mail.internet.*; // mailapi.jar from JavaMail API 1.4: http://java.sun.com/products/javamail/
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
 
/**
 * RESTとはアーキテクチャスタイルであって仕様ではない云々みたいな話はとりあえず無視で(^_^;)
 */
public class Rest {
 
  // テスト実行用の main
  public static void main(String[] args) throws Exception {
    
    // Yahoo!デベロッパーネットワーク - Yahoo!検索 - 関連検索ワード
    // http://developer.yahoo.co.jp/search/webunit/V1/webunitSearch.html 
    GetRequest req = new GetRequest("http://api.search.yahoo.co.jp/AssistSearchService/V1/webunitSearch");
    req.set("appid", "hogehoge");
    req.set("query", "猫");
    req.set("results", "10");
    req.set("start", "1");
    
    Rest rest = new Rest();
    XmlResponse res = rest.get(req);
    
    // XPath利用サンプル
    int length = res.getLength("ResultSet/Result");
    for(int i=0; i<length; i++){
      String s = res.getString("ResultSet/Result[" + (i + 1) + "]");
      System.out.println(s);
    }
 
    // もっと複雑な XML 文書になったらヤバげ
    // XPath xpath = res.getXPath();
    // Document doc = res.getXMLDocument();
    // で対処。
    //
    // でも、できれば XPath 使いたくないので、
    // JSON みたいに簡単に扱えないかなぁ……
    //
    // IBM XML から JSON を生成し、Ajax で使う - Japan
    // http://www-06.ibm.com/jp/developerworks/web/library/x-xml2json/index.shtml
    //
    // とか参考になるかも。
    //
  }
  
  public Rest(){
  }
  
  // URL から XML 文書情報を取得
  public XmlResponse get(GetRequest req) throws Exception {
    
    String url = req.getURL();
    
    try{
      // 状況に応じて使い分け?
      
      // パターン1: DocumentBuilder が 直接処理
      //Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(url);
      //return new XmlResponse(doc);
      
      // パターン2: わざわざ URLConnection を使って処理
      String content = getContent(new URL(url));
      //System.out.println(content);
      StringReader sr = new StringReader(content);
      InputSource is = new InputSource(sr);
      Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
      return new XmlResponse(doc, content);
 
    }catch(Exception e){
      throw new Exception("URL=[" + url + "]", e);
    }
  }
 
  // URLからコンテンツ(HTML/XMLページの文字列)を取得
  private static String getContent(URL url) throws Exception{
    
    try{
      HttpURLConnection con = (HttpURLConnection)url.openConnection();
      con.setRequestMethod("GET");
      
      // ex. String ct = "text/xml; charset=\"utf-8\"";
      String ct = con.getContentType();
      String charset = "UTF-8"; // Content Type が無ければ UTF-8 KIMEUCHI
      if(ct != null){
        // JavaMail なクラス ContentType
        // Java SE にあればいいのに……
        String cs = new ContentType(ct).getParameter("charset");
        if(cs != null){
          charset = cs;
        }
        //System.out.println("charset=" + charset);
      }
  
      InputStream is = con.getInputStream();
      InputStreamReader isr = new InputStreamReader(is, charset);
      BufferedReader br = new BufferedReader(isr);
      StringBuffer buf = new StringBuffer();
      String s;
      while ((s = br.readLine()) != null) {
        buf.append(s);
        buf.append("\r\n"); // 改行コードKIMEUCHI
      }
  
      br.close();
      con.disconnect();
      
      return buf.toString();
      
    }catch(Exception e){
      throw new Exception("URL=[" + url + "]", e);
    }
    
  }
  
  public String toString(){
    return super.toString() + ":Rest";
  }
}

GetRequest.java


import java.net.*;
import java.util.*;
 
/**
 * get method for http.
 */
public class GetRequest{
 
  private final String baseurl;
  private final Properties params = new Properties();
 
  private String encoding = "UTF-8";
  
  public GetRequest(String baseurl){
    this.baseurl = baseurl;
  }
  
  public void setEncoding(String encoding){
    this.encoding = encoding;
  }
  
  public void set(Properties params){
    this.params.putAll(params);
  }
  
  public void set(String key, String value){
    params.setProperty(key, value);
  }
  
  // HTTP PATH INFO なパラメータは考慮しない
  public String getURL() throws Exception {
 
    if(params.size() == 0){
      return baseurl;
    }
    
    StringBuffer buf = new StringBuffer();
    buf.append(baseurl);
    if(!baseurl.endsWith("?") && params.size() > 0){
      buf.append("?");
    }    
    for (Enumeration names = params.propertyNames(); names.hasMoreElements();) {
      String key = (String) names.nextElement();
      String val = params.getProperty(key);
      buf.append(key);
      buf.append("=");
      if(encoding != null){
        buf.append(URLEncoder.encode(val, encoding));
      }else{
        buf.append(val);
      }
      buf.append("&");
    }
    if (buf.charAt(buf.length() - 1) == '&') {
      buf.deleteCharAt(buf.length() - 1);
    }
 
    return buf.toString();
  }
}

XmlResponse.java


import javax.xml.xpath.*;
import org.w3c.dom.*;
 
/**
 * xml response for http.
 */
public class XmlResponse{
  
  private final Document doc;
  private final XPath xpath;
  private final String xmlContent;
  
  public XmlResponse(Document doc, String xmlContent){
    this.doc = doc;
    this.xpath = XPathFactory.newInstance().newXPath();
    this.xmlContent = xmlContent;
  }
 
  public String getXMLContent(){
    return xmlContent;
  }
  
  public int getLength(String expression) throws XPathExpressionException{
    // XPath 利用サンプル
    NodeList nodelist = (NodeList)xpath.evaluate(expression, doc, XPathConstants.NODESET);
    if(nodelist != null){
      return nodelist.getLength();
    }else{
      return 0;
    }
  }
 
  public String getString(String expression) throws XPathExpressionException{
    // XPath 利用サンプル
    return xpath.evaluate(expression, doc);
  }
 
  public XPath getXPath(){
    return xpath;
  }
  
  public Document getXMLDocument(){
    return doc;
  }
}

実際にちゃんと使うときには、結果をキャッシュする CachedRest extends Rest クラスを作っておくとか、レスポンスが RSS や Atom の場合は専用のオブジェクトを取得しやすい形にしておくとか、誰が入力したかわからないデータを綺麗にする処理を入れるとかしておくと便利。

# POST とか PUT とかその手のやつには対応してないけど、実際にそういうAPIってどこか提供してたりするのかなぁ。

元になったソースコードはこちら ⇒ Java で XPath を扱ってみる

tags: zlashdot Java Java

Posted by NI-Lab. (@nilab)