JSP/Servlet | サーブレットとJSP/HTML | Ajaxでサーブレットにアクセスする

先ほど説明した「フォームを送信して値を渡す」方式は、あまり便利とは言えない。サーブレットでPrintWriterを使ってページを出力するのは非常に面倒である。やはり画面表示にはHTMLやJSPを利用し、サーバー側の処理部分だけをサーブレットで行う方式のほうが効率がよい。

一つの方法として考えられるのがAjaxを使うことである。HTML内のAjaxからサーブレットへアクセスし、その結果を取得して表示する。こうすればサーブレット側は結果値だけを出力し、表示はHTML側で行うため、開発が楽になる。

それではサンプルを作り、それを見ながら説明しよう。以下に簡単な例を示す。

index.html

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>Hello App Engine</title>
    <style>
    h1 {
        font-size: 16pt;
        background: #AAFFAA;
        padding: 5px;
    }
    </style>
    <script type="text/javascript">
    function doAction() {
        var req =  createRequest();
        if (req == null) {
            alert("実行できません!");
            return;
        }
        var s = document.getElementById('text1').value;
        req.open("post", "/mygaeapp", true);
        req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.onreadystatechange = function(){
            if (this.readyState == 4 && this.status == 200){
                var msg = document.getElementById('msg');
                msg.innerHTML = this.responseText;
            }
        }
        req.send("text1=" + encodeURIComponent(s));
        msg.innerHTML = "<<< please wait... >>>";
    }
         
       function createRequest(){
        var httplist = [
            function(){ return new XMLHttpRequest(); },
            function(){ return new ActiveXObjct("Msxml2.XMLHTTP"); },
            function(){ return new ActiveXObject("Microsoft.XMLHTTP"); }
        ];
        for(var i = 0;i < httplist.length;i++){
            try {
                var http = httplist[i]();
                if (http != null) return http;
            } catch(e){
                continue;
            }
        }
        return null;
    }
    </script>
</head>
<body>
    <h1>Hello App Engine!</h1>
    <p id="msg">整数を入力</p>
    <p name="msg"></p>
    <table>
        <tr>
            <td>入力</td>
            <td><input type="text" id="text1"></td>
        </tr>
        <tr>
            <td></td>
            <td><button onclick="doAction();">送信</button></td>
        </tr>
    </table>
</body>
</html>

MyGaeAppServlet.java

package com.devkuma.mygaeapp;
 
import java.io.*;
import java.net.*;
 
import javax.servlet.http.*;
 
@SuppressWarnings("serial")
public class MyGaeAppServlet extends HttpServlet {
     
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/plain");
        request.setCharacterEncoding("utf8");
        response.setCharacterEncoding("utf8");
        PrintWriter out = response.getWriter();
        out.println("Hello, world!");
    }
 
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/plain");
        request.setCharacterEncoding("utf8");
        response.setCharacterEncoding("utf8");
        String param = URLDecoder.decode(request.getParameter("text1"),"utf8");
        int result = 0;
        try {
            int n = Integer.parseInt(param);
            for(int i = 1;i <= n;i++){
                result += i;
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        PrintWriter out = response.getWriter();
        out.println(result);
    }
}

index.htmlとMyGaeAppServletを使ったサンプルである。HTML内のAjaxからMyGaeAppServletにアクセスし、結果を受け取って表示するようになっている。

今回のサンプルでは、入力フォームに整数を入力するとAjaxでサーブレットへアクセスし、0からその数までの合計を計算して受け取り、表示する。いろいろな数値を入力して動作を確認してみよう。

流れを見てみよう。まずAjax通信で利用するXMLHttpRequestオブジェクトの生成はcreateRequestという関数にまとめられている。これを呼び出してXMLHttpRequestオブジェクトを取得し、openでアクセス先を指定してリクエストを開き、sendで必要な値を設定してアクセスを開始する。この部分の処理はJavaScriptのAjax通信の話になるため、ここでは省略する。

一方、サーブレット側の処理は、実は前回のサンプルとほとんど違いがない。唯一の違いは次の点である。

  1. response.setContentType("text/plain");となっている。HTMLではなく通常のテキストを書き出している。
  2. out.printlnする内容が単純なテキストだけになっている。HTMLタグは一切ない。

この程度である。もちろん数値を計算する処理は新しく増えているが、Ajaxの利用はサーブレット側ではほとんど意識するものではない。基本的にはJavaScript側の問題だと考えてよい。