1) はじめに
「Ajaxとの連携1」では、String型の文字列をそのままクライアントに返すサンプルを紹介しました。
ただし、この例だとサーバの処理結果を文字列で返す分には問題ありませんが、
String型以外の複雑な情報を返す場合、その都度文字列に変換してクライアント
に返す必要があります。
サーバで処理した結果は、特別な処理を行うことなくクライアントに返したいですよね?
Ajaxでは、サーバとのHTTP通信にXMLのDOMツリーを使った情報のやり取りを行うことが
できます。
Weberフレームワークはこの特性を利用して、サーバで処理されたオブジェクトを
XMLのDOMツリーに変換するAPIを提供しています。
このAPIを利用すれば、サーバで処理した結果をわずかな手順で
クライアントに返すことができます。
ここでは、サーバで生成されたオブジェクトをXMLのDOMツリーに変換してから
クライアントに返す方法について解説します。
ここで紹介するWebアプリケーションの構成は以下のとおりです
2) 入力画面の作成 (sample2.html)
まず入力となる画面を作成します。
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
<title>従業員番号から氏名表示</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<style type="text/css">
#title {font-size:18px; font-weight:600; color:#aa0000}
</style>
<script type="text/javascript" src="./../../js/xmlhttp.js"></script>
<script type="text/javascript">
//<![CDATA[
var httpObj; //XMLHttpObject変数
/**
* XMLHttpObjectを使って,指定されたコンポーネントにセットされている
* 条件に合致する従業員名を取得します
*/
function getEmpName(e){
var emp_no = document.getElementById("emp_no").value;
var emp_name;
httpObj = createXMLHttpRequest(displayData);
httpObj.open("GET", "./html_4_0/ajax/sample2.wb?empNo=" + emp_no);
httpObj.send(null);
}
/**
* サーバから受け取った結果を画面に出力する
*/
function displayData(){
if(httpObj.readyState == 4){
if(httpObj.status == 200){
//結果をXMLで取得
var resXml = httpObj.responseXML;
//受け取った結果がエラーかどうか判定
var errList = resXml.getElementsByTagName("errorList");
if( errList != null && errList.length > 0 ){ //入力エラーの場合
var err = resXml.getElementsByTagName("message");
var errMsg = err[0].firstChild.nodeValue;
document.getElementById("err_msg").innerHTML = errMsg;
document.getElementById("emp_name").innerHTML = "検索失敗";
}else{ //正常応答の場合
var empNameElems = resXml.getElementsByTagName("empName");
emp_name = empNameElems[0].firstChild.nodeValue;
emp_name = ' 検索結果=' + emp_name + 'がヒットしました';
document.getElementById("emp_name").innerHTML = emp_name;
}
}
}
}
//]]>
</script>
</head>
<body>
<center><span id="title">従業員番号から氏名表示2(XML版)</span></center>
<p>0000〜0002までの従業員番号を入力し、タブキーを押下してください</p>
<font id="err_msg" color="red">
<!-- 入力エラー時はここにメッセージが出力されます -->
</font>
<form>
<table align="center">
<tr>
<td>
従業員番号:<input id="emp_no" type="text" name="emp_no" onblur="getEmpName();"/>
</td>
<td>
<div id="emp_name">
<!-- 従業員番号に該当する従業員が見つかった場合はここに結果が出力されます -->
</div>
</td>
</tr>
</table>
</form>
</body>
</html>
「Ajaxとの連携1」で作成した画面をXML版に修正しています。
funcs.jsは「Ajaxとの連携1」で作成したものを利用してください。
太字の箇所が前回からの修正点になります。
まず、httpObj.responseXMLを使って、サーバから受け取った結果をXMLデータとして
取得しています。
又、このサンプルでは受け取ったXMLの種類によって表示内容を変えるようにしています。
具体的には、XMLデータの中に"errList"要素が存在する場合は、エラーメッセージを表示し、
無ければ、検索結果を表示するようにしています。
そして取得したXMLドキュメントをgetElementsByTagName()で表示しています。
XMLデータの表示方法はいくつかありますが、
今回はJavaスクリプトでDOMツリーを展開し、HTMLタグに変換して
表示するようにしています。
4) バリュークラスの作成
ここではエラー表示用と検索結果表示用の2つのバリュークラスを作成します。
(1) 検索結果表示用クラス(Ajax.java)
package weber_4_0_sample.org.itscool.ajax;
public class Ajax {
private String empNo;
private String empName;
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
}
(2) エラー表示用クラス(AjaxError.java)
package weber_4_0_sample.org.itscool.ajax;
public class AjaxError {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
5) アクションクラスの作成(AjaxXmlSampleAction.java)
このサンプルのアクションクラスです。
package weber_4_0_sample.org.itscool.ajax;
import org.itscool.commons.document.BeanToXmlDocument;
import org.itscool.commons.util.InputCheckUtil;
import org.itscool.weber.action.Action;
import org.itscool.weber.action.ActionBucket;
import org.itscool.weber.controller.Globals;
import org.w3c.dom.Document;
/**
* サンプル1の場合は検索結果をテキストで返していたが
* 本サンプルでは、XMLを返している。
*/
public class AjaxSample2Action extends Action {
/**
* 入力チェックを行います。
* 入力内容が不正な場合は、エラーオブジェクト(AjaxError)を生成し、
* そのオブジェクトからXMLに変換した結果をクライアントに返します
* @param bucket ActionBucketインスタンス
* @return 入力成功時はGlobals.RET_SUCCESSを返します。
* 入力エラーの場合はGlobals.RET_NOFORWARDを返します
* (XmlHttpRequestで非同期通信、同期通信を行う場合は画面遷移は行いません)
*/
public String doValidate(ActionBucket bucket) throws Exception{
String emp_no = (String)bucket.getParameter("empNo");
if( !InputCheckUtil.checkDigit(emp_no) ){
AjaxError error = new AjaxError();
error.setMessage("従業員番号は数値を入力してください");
//オブジェクトをXMLにマッピングします
BeanToXmlDocument beanToXml = new BeanToXmlDocument("errorList");
beanToXml.addElement(error, "error");
bucket.printXml(beanToXml);
//XML変換後のデバッグ
System.out.println(beanToXml.parseText("utf-8"));
return Globals.RET_NOFORWARD;
}
//入力に誤りが無ければdoExecuteを実行します。
return Globals.RET_SUCCESS;
}
/**
* アクションを実行し、結果をXMLで出力します。
* このアクションの実行結果はGlobals.RET_NOFORWARDを返巣必要があります。
* XmlHttpRequestで非同期通信、同期通信を行う場合は、RequestDispatcher.forwardで
* 画面を飛ばすと、XmlHttpRequestが画面の表示内容を受け取ってしまうため、
* 結果がうまく表示されません。
* 又、bucket.printXml系のメソッドを実行すると、出力内容が確定し待っているため、
* RequestDispatcher.forwardを呼び出すと、ServletExceptionがスローされます。
* @param bucket ActionBucketインスタンス
* @return Globals.RET_NOFORWARDを返します
*/
public String doExecute(ActionBucket bucket)throws Exception{
//クライアントからの入力パラメータをオブジェクトで取得します
Ajax bean = (Ajax)bucket.getForm();
String emp_no = bean.getEmpNo();
String emp_name = "該当なし";
if( emp_no.equals("0000")){
emp_name="太郎";
}else if( emp_no.equals("0001")){
emp_name="加納";
}else if( emp_no.equals("0002")){
emp_name="hanako";
}
bean.setEmpName(emp_name);
//オブジェクトをXMLにマッピングします
BeanToXmlDocument beanToXml = new BeanToXmlDocument("result");
beanToXml.addElement(bean, "bean");
bucket.printXml(beanToXml);
//XML変換後のデバッグ
System.out.println(beanToXml.parseText("utf-8"));
return Globals.RET_NOFORWARD;
}
}
まずdoValidateメソッドで、フォームの入力チェックを行っています。
入力エラーの場合はActionErrorインスタンスを生成し、
BeanToXmlDocumentインスタンスにセットしています。
BeanToXmlDocumentクラスは、オブジェクトをXMLにマッピングするためのクラスで、
コンストラクタの第1引数が、XMLのルート要素名になります。
次にBeanToXmlDocument.addElementメソッドで、このXMLに追加するオブジェクトと
要素名をセットしています。
bucket.printXml(beanToXml)メソッドでBeanToXmlDocumentインスタンスのXMLデータを
クライアントに返しています。
このサンプルでは、入力エラーが発生した場合、以下のようなXMLデータを返すように
なっています。
入力エラー時のXMLデータ
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<result>
<bean>
<message>従業員番号は数値を入力してください</message>
</bean>
</result>
doExecuteメソッドで、従業員番号に合致する従業員名を検索し、結果をXMLで
返しています。
具体的には、検索結果用のインスタンス(Ajax)を生成し、Ajaxインスタンスを
BeanToXmlDocumentにセットしてから、bucket.printXml(beanToXml)メソッドで、
XMLデータをクライアントに返しています。
検索結果を返すXMLデータは以下のような感じになります。
検索結果用のXMLデータ
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<result>
<bean>
<empNo>0000</empNo>
<empName>太郎</empName>
</bean>
</result>
6) 実行
ここまでの作業が完了したら、コンパイル・デプロイを行い、動作を確認してみましょう。