RSS(RDF Site Summary)とは、サイトのサマリ情報(新着コンテンツやニュース情報など)を配信するためのXMLフォーマットです。最近では、多くのニュースサイトがRSSを導入しています。また、昨今とみに話題にのぼるBlogツールでも、RSS発行に対応するものが増え、その認知度は急速に高まっています。RSSリーダ(アグリゲータ)のような専用のアプリケーションを利用することで、直接サイトにアクセスしなくても各サイトの更新状況が一括で確認できるという点も、注目されている理由の1つでしょう。
RSSの詳細については、「サイトの更新情報を提供する標準言語RSS」(Insider .NET)などを参考にしていただくとして、本TIPSではJSP/サーブレットアプリケーションからRSS文書(RSSフィールド)を動的に配信する方法を紹介することにしましょう。
冒頭で触れたように、RSSはXML構文をベースにしているためJ2SEのコアAPIを利用するだけでもRSS文書を生成/解析することは可能です。しかし、それにはまずRSS独自の構文を理解する必要があります。また、RSSと一口にいっても、実はさまざまなバージョンが乱立しています。0.90、0.91、1.0、2.0……しかも、それぞれのバージョンごとに互換性がないのが、RSS活用における現時点での最大の問題点なのです。これを、開発者が複数のコードを並存させることで対応しなければならないとしたら、大変非効率でしょう。
そこで登場するのが、RSS4jライブラリです。Javaの世界には、RSSを生成/解析するためのライブラリが多く存在しますが、RSS4jはその中でも代表的なものの1つです。RSS4jを利用することで、複数のバージョンに対応したRSSフィールドを簡単に配信することができ、また、開発者がRSSの構文を意識する必要がなくなります。
RSS4jライブラリは、以下のサイトからダウンロードすることが可能です。なお、サイトからダウンロードできるのはRSS4jxxx.jar(xxxはバージョン番号)という名前の「.jar」ファイルですが、サイトの注意書きをご覧いただければお分かりになるように、これはAPIドキュメントやソースコード、バイナリデータなどを含んだアーカイブです。アプリケーションに登録を行うのは、アーカイブ内に含まれるRSS4j.jarになるので注意してください。
・http://www.churchillobjects.com/c/13005.html
RSS4j.jarは、RSS4jxxx.jarを解凍してできたlibフォルダ配下にあるので、これを、アプリケーションルート配下の「/WEB-INF/lib」フォルダにコピーしてください。
環境の準備が整ったところで、RSSフィールドを配信するためのサーブレットクラスを定義してみましょう。まず、サーブレットクラス定義に先立って、サマリ情報の元データとなる情報テーブル(site_info_tbl)をデータベースに用意しておきます。
表 データベースに用意するsite_info_tblテーブルのフィールドレイアウト
|
フィールド名 |
データ型 |
概要 |
|
url |
VARCHAR(255) |
コンテンツのURL(主キー) |
|
title |
VARCHAR(100) |
タイトル |
|
published |
DATE |
公開日 |
|
memo |
TEXT |
サイト概要 |
|
RSSフィールドを配信するためのサーブレットクラスは以下のとおりです。
RssServlet.java
package to.msn.wings.javatips;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import churchillobjects.RSS4j.RssChannel;
import churchillobjects.RSS4j.RssChannelImage;
import churchillobjects.RSS4j.RssChannelItem;
import churchillobjects.RSS4j.RssDocument;
import churchillobjects.RSS4j.generator.RssGenerationException;
import churchillobjects.RSS4j.generator.RssGenerator;
public class RssServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Connection db=null;
PreparedStatement objPs=null;
ResultSet rs=null;
// RSS文書を生成
RssDocument objRss=new RssDocument();
// クエリパラメータversionから生成するRSSのバージョンを特定
// クエリパラエータが無指定の場合は、1.0とする(0.90、0.91、1.0を指定可)
String strVer=request.getParameter("version");
if(strVer==null || strVer.equals("")){strVer="1.0";}
objRss.setVersion(strVer);
// チャネル情報を生成
RssChannel objRc=new RssChannel();
objRc.setChannelTitle("サーバサイド技術の学び舎 - WINGS");
objRc.setChannelLink("http://www.wings.msn.to/");
objRc.setChannelDescription("サーバサイド技術全般に関する情報提供");
objRc.setChannelUri(request.getRequestURL().toString());
objRc.setChannelLanguage("ja");
objRc.setChannelCopyright("YAMADA,Yoshihiro 1998-2004");
// ロゴイメージ情報を生成
RssChannelImage objRci=new RssChannelImage();
objRci.setImageUrl("http://www.wings.msn.to/image/wings.jpg");
objRci.setImageLink("http://www.wings.msn.to/");
objRci.setImageTitle("サーバサイド技術の学び舎 - WINGS");
objRc.setChannelImage(objRci);
try {
// サイト情報テーブルから公開日最新15件のデータを取得
// サマリ情報として、チャネル配下に追加
Class.forName("org.gjt.mm.mysql.Driver");
db=DriverManager.getConnection("
jdbc:mysql://localhost/sample?user=javatips&password=
javatips&useUnicode=true&characterEncoding=Windows-31J");
objPs=db.prepareStatement("
SELECT title,url,memo FROM site_inf_tbl
ORDER BY published DESC LIMIT 15");
rs=objPs.executeQuery();
while(rs.next()){
RssChannelItem objRcii=new RssChannelItem();
objRcii.setItemTitle(rs.getString("title"));
objRcii.setItemLink(rs.getString("url"));
objRcii.setItemDescription(rs.getString("memo"));
objRc.addItem(objRcii);
}
objRss.addChannel(objRc);
// XML文書としてクライアントに出力
response.setContentType("text/xml;charset=UTF-8");
RssGenerator.generateRss(objRss,response.getWriter());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (RssGenerationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(rs!=null){rs.close();}
if(objPs!=null){rs.close();}
if(db!=null){rs.close();}
} catch (SQLException se) {
se.printStackTrace();
}
}
}
} |
このサーブレットクラスを実行するに当たっては、あらかじめデプロイメント・ディスクリプタ(web.xml)に対して、サーブレットの登録を行う必要があります。
<url-pattern>要素に「/rss.xml」と指定しておくことで、サーブレットクラスをあたかも静的なXMLファイルであるかのように見せることができます(「基礎から学ぶサーブレット/JSP 第11回 JSPとサーブレットの違いを明らかにする」(Java Solution)も併せて参照してください)。
web.xml
<?xml version="1.0" encoding="UTF-8" ?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-app_2_4.xsd"
version="2.4">
…中略…
<servlet>
<servlet-name>RssServlet</servlet-name>
<servlet-class>to.msn.wings.javatips.RssServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RssServlet</servlet-name>
<url-pattern>/rss.xml</url-pattern>
</servlet-mapping>
…中略…
</web-app> |
このコードの実行結果は、以下のようになります。クエリパラメータが無指定の場合、あるいは、versionパラメータに0.90、0.91、1.0を指定した場合とで動的に異なるRSS文書が生成される点に注目してください。
以下に、実行結果を示します。
0.90を指定した場合の実行結果 (クリックすると拡大)
0.91を指定した場合の実行結果 (クリックすると拡大)
1.0を指定した場合の実行結果 (クリックすると拡大)
ロジックの詳細な流れについては、ソースコード内のコメントを参照いただくとして、ここで注目していただきたいのは、RSS4jライブラリの構造です。RSS4jライブラリは、RSS文書全体を表すRssDocumentクラスを頂点にして、複数個のチャネル情報(RssChannelクラス)、さらにその配下にはロゴイメージ情報を表すRssChannelImageクラスや個々のサマリアイテムを表すRssChannelItemクラスなどが属するという構造になっています。RSS4jライブラリでは、これらのオブジェクトを生成し、addXxxxxメソッドで階層構造の関連付けを行っていくことで、最終的にRSS文書を生成するという流れになっています。
開発者はRSS4jを利用することで、RSSの構文自体は理解しなくても、極めて直感的にRSS文書を組み立てることができるのです。ただし、RSSのバージョンによっては出力することのできない情報もありますので、注意してください(詳細な出力項目については、RssServletクラスが生成したバージョンごとのRSS文書を概観してみるとよいでしょう)。