DWR: サーバーからHTMLファイルを取得する。

前回のログ(「Direct Web Remoting」)に引き続き、dwr.warにあるサンプルをみていく。

今回は、非同期に、ウェブ・アプリケーション・サーバー(以下、サーバー)からHTMLファイルを取得するサンプル(dwr.warにある「Resource Forwarding」Example)。

少しだけ画面を改造した。初期画面は以下。


上の画面で、「HTMLをインクルード」ボタンを押すと、サーバーにあるHTMLファイルを取得して、それをdiv要素に差し込む(下図)。


差し込むHTMLファイルは、dwr.warにあるもの(forward.html)そのままを利用した。
このHTMLから分かるように、HTMLをそのまま読み込んでいるが、IFrameでもないし、エスケープもされていないことがポイント。(DWR Utilで提供されているsetValue()は、クロスサイトスクリプティングを防止するために、デフォルトでは値をエスケープする)
(注意)日本語では文字化けが発生する。

<html>
<body>

<big>
  <span style="color: rgb(153, 153, 153);">An <code>import</code>ed</span>
  <span style="font-weight: bold; font-family: Helvetica,Arial,sans-serif;">
    <span style="color: rgb(204, 102, 204);">JSP</span> Page
  </span>
  <span style="text-decoration: underline;">with </span>
  <span style="font-style: italic; text-decoration: underline;">lots</span>

  <span style="text-decoration: underline;"> of formatting</span>
  .
</big>

</body>
</html>


以下が、これを行うためのJavaクラス(ServletContextDemo.java)。

package test;
import java.io.IOException;
import javax.servlet.ServletException;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;

/**
 * DWRのデモ
 * 
 * ServletContextを取得し、相対参照でファイルを取得して
 * レスポンスする。
 * 
 */


public class ServletContextDemo {
    public String getInclude() throws ServletException, IOException {
        // ServletContextの取得
        // WebContext(if)はServletContext(if)の拡張
        WebContext wctx = WebContextFactory.get();

        // forward先のurlからデータを取得する。
        return wctx.forwardToString("/data/forward.html");
    }
}

コンテキストパス(ドキュメントルート)下にあるディレクトリを相対参照するには、ServletContextへのアクセスとServletConfigの取得が不可欠だが、そのために、DWRではWebContextというインターフェイスが用意されている。

WebContextFactory.get()

で、WebContextを取得(ちょっと語弊があるかな)することができる。

wctx.forwardToString("/data/forward.html")

は、コンテキストパス配下のdataディレクトリにあるforward.htmlというファイルにリクエストをforwardし、forward先からStringを取得するというメソッド。
DWRでは、見た目上、JavaScriptから直接このクラスを呼び出す格好になるので、(PHPなどで実装する場合と違い)このクラス上ではHTTPレスポンスを返す必要はない。
このように、このクラスが「サーバー上で閉じている」、つまり、「リクエスト/レスポンスに依存せず、サーバー上で完結している」というのは(テストを行う上などで)大きなメリットとなる


以下は、画面表示のHtmlファイル(servlet_context_demo.html)。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>DWRのサンプリング</title>
<meta http-equiv="content-type"
      content="text/html; charset=UTF-8">

<style type="text/css" id="defaultstyle">
body {
	margin:0;
	padding:0;
}

#container {
	margin: 2px;
	padding: 3px;
	line-height:1.5em;
	width: 500px;
	height: auto;
	border:1px dashed #999999;
}
</style>
	
<!-- ServletContextDemo.jsはDWRによって自動生成される。 
     dwr/はドキュメントルートとの相対参照。
-->
<script src='dwr/interface/ServletContextDemo.js'></script>
<!-- engine.jsは必須 -->
<script src='dwr/engine.js'></script>
<!-- util.jsは必須 -->
<script src='dwr/util.js'></script>

<script type="text/javascript">
function forward() {
 	  // ServletContextDemoは、dwr.xmlで定義したPOJO名
	  ServletContextDemo.getInclude(
		// Callback関数
		function(data) {
	    	dwr.util.setValue("forward", data, 
    		// escapeしないでセットする(オプション)。
	    	    { escapeHtml:false }
	    	);
	  });
}
</script>
</head>
    
<body>
<div id="container">
	<p>
	簡単なDWRのデモです。<br>
	「HTMLをインクルード」ボタンを押すと、下にHTMLをインクルードします。
	</p>
	<p>
	<input value="HTMLをインクルード" type="button" onclick="forward()"/>
	<br>
  	<br>
  	インクルードされたHTML:  	
  	<br>
	<div id="forward"></div>
	</p>
</div>
</body>
</html>

ここでは、

	    	dwr.util.setValue("forward", data, 
    		// escapeしないでセットする(オプション)。
	    	    { escapeHtml:false }
	    	);

がポイント。DWR UtilのsetValue()に、オブジェクトリテラル型のオプション{ escapeHtml:false }をつけている。
このオプションをつけないと、setValue()によってこのHTML内にセットされる値がエスケープされてしまい、タグがそのまま表示されてしまう(HTML文書としてインクルードできない)。


以下がdwr.xml
これは先の例と同様である。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://directwebremoting.org/schema/dwr20.dtd">

<dwr>
  <allow>

	<!--
	test.ServletContextDemoというクラスのオブジェクトが「new」によって生成され、
	クライアントのJavaScriptプログラムでは「ServletContextDemo」という名前で
	参照できることを意味
	-->

    <create creator="new" javascript="ServletContextDemo">
      <param name="class" value="test.ServletContextDemo"/>
    </create>

  </allow>
</dwr>