Spring Boot Ajax/JavaScript連携

Spring BootでAjaxを利用してみた

Spring BootのWEB画面上では、Ajax通信も行うことができる。今回は、jQueryを利用しない形で、Ajax通信を含むサンプルプログラムを作成してみたので、共有する。

前提条件

下記記事のSpring BootでのOracle接続処理の実装が完了していること。

Spring BootでOracle接続処理を実装してみたSpring BootのWEBアプリケーションを開発する際、なんらかのデータベースにアクセスすることが多いが、SpringのJPAライブ...

また、以下の記事の「hibernate_sequence」シーケンスの作成が完了していること。

Spring BootのWEB画面上でCRUDを含むOracleアクセス処理を実装してみた(完成イメージ編)今回は、C(Create)・R(Read)・U(Update)・D(Delete)を一通り含むOracle接続処理をSpring Boo...



サンプルプログラムの作成

作成したサンプルプログラムの構成は以下の通り。
サンプルプログラムの構成

まず、HTMLは以下の内容になっていて、検索ボタンを押下した場合に、後述のdemo.jsの関数「getUserData」を呼び出すようになっている。

<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" th:src="@{/demo.js}"></script>
    <title>index page</title>
</head>
<body>
    検索IDを指定し、「検索」ボタンを押下してください。<br/>
    検索ID: <input type="text" id="searchId" name="searchId" size="12" maxlength="4" />
    <input type="button" value="検索" onclick="getUserData();" />
    <br/><br/><br/>
    ★以下に検索されたデータが表示されます
    <table border="0">
        <tr>
            <td align="left" valign="top">名前:</td>
            <td>
                <span id="name"></span>
            </td>
        </tr>
        <tr>
            <td align="left" valign="top">生年月日:</td>
            <td>
                <span id="birthDay"></span>
            </td>
        </tr>
        <tr>
            <td align="left" valign="top">性別:</td>
            <td>
                <span id="sex"></span>
            </td>
        </tr>
        <tr>
            <td align="left" valign="top">メモ:</td>
            <td>
                <span id="memo"></span>
            </td>
        </tr>
    </table>
</body>
</html>

また、demo.jsの内容は以下の通りで、検索IDの値を引数に、Ajax通信でsearchメソッドを呼び出し、その処理が正常終了した場合は、取得したUserDataオブジェクトの値を、画面上に表示するようになっている。

'use strict';

function getUserData(){
    // index.htmlの検索IDの値を取得
    const id = document.getElementById('searchId').value;

    // AjaxにてDemoControllerクラスのsearchメソッドを呼び出す
    let request = new XMLHttpRequest();
    request.open("get", "/search?id=" + id, true);
    request.send(null);
    request.onload = function (event) {
       // Ajaxが正常終了した場合
       if (request.readyState === 4 && request.status === 200) {
          // 該当するデータが無かった場合
          if(!request.responseText){
              alert("該当するデータはありませんでした");
              return;
          }
          // 該当するデータがあった場合は、取得したUserDataオブジェクトの内容を画面に
          // 表示する。その際、名前・性別・メモはデコードする
          const userData = JSON.parse(request.responseText);
          document.getElementById('name').textContent = decodeURI(userData.name);
          document.getElementById('birthDay').textContent
            = userData.birthY + '年' + userData.birthM + '月' + userData.birthD + '日';
          document.getElementById('sex').textContent = decodeURI(userData.sex);
          document.getElementById('memo').textContent = decodeURI(userData.memo);
       // Ajaxが異常終了した場合
       }else{
          alert("エラーが発生し、データが取得できませんでした");
       }
    };
    // Ajaxが異常終了した場合
    request.onerror = function (event) {
       alert("エラーが発生し、データが取得できませんでした");
    }
}



さらに、コントローラクラスの内容は以下の通りで、Ajax通信で呼ばれるsearchメソッドは、@ResponseBodyアノテーションを付与し、取得したUserDataオブジェクトをJSON文字列に変換して返却している。

package com.example.demo;

import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.thymeleaf.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

@Controller
public class DemoController {

    /**
     * ユーザーデータテーブル(user_data)へアクセスするリポジトリ
     */
    @Autowired
    private UserDataRepository repository;

    /**
     * 初期表示画面に遷移する
     * @return 初期表示画面へのパス
     */
    @GetMapping("/")
    public String index(){
        return "index";
    }

    /**
     * 引数の検索IDに対応するDemoFormデータを取得する
     * @param id 検索ID
     * @return DemoFormデータ(JSON形式)
     */
    //JSON文字列を返却するために、@ResponseBodyアノテーションを付与
    @GetMapping("/search")
    @ResponseBody
    public String search(@RequestParam("id") String id){
        // ユーザーデータを取得し、取得できなければそのまま返す
        UserData userData = repository.findUserDataById(Long.valueOf(id));
        // ユーザーデータが取得できなかった場合は、null値を返す
        if(userData == null){
            return null;
        }
        // 性別を表示用(男,女)に変換
        userData.setSex("1".equals(userData.getSex()) ? "男" : "女");
        // 名前・メモ・性別をエンコード
        userData.setName(encode(userData.getName()));
        userData.setMemo(encode(userData.getMemo()));
        userData.setSex(encode(userData.getSex()));
        // 取得したユーザーデータをJSON文字列に変換し返却
        return getJson(userData);
    }

    /**
     * 引数の文字列をエンコードする
     * @param data 任意の文字列
     * @return エンコード後の文字列
     */
    private String encode(String data){
        // 引数がnullまたは空文字の場合は、その値を返す
        if(StringUtils.isEmpty(data)){
            return data;
        }
        String retVal = null;
        try{
            retVal = URLEncoder.encode(data, "UTF-8");
        }catch (UnsupportedEncodingException e) {
            System.err.println(e);
        }
        return retVal;
    }

    /**
     * 引数のUserDataオブジェクトをJSON文字列に変換する
     * @param userData UserDataオブジェクト
     * @return 変換後JSON文字列
     */
    private String getJson(UserData userData){
        String retVal = null;
        ObjectMapper objectMapper = new ObjectMapper();
        try{
            retVal = objectMapper.writeValueAsString(userData);
        } catch (JsonProcessingException e) {
            System.err.println(e);
        }
        return retVal;
    }
}

その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-web-ajax/demo



サラリーマン型フリーランスSEという働き方でお金の不安を解消しよう先日、「サラリーマン型フリーランスSE」という働き方を紹介するYouTube動画を視聴しましたので、その内容をご紹介します。 「サ...

サンプルプログラムの実行結果

user_dataテーブルのデータの内容は以下の通りで、ID=1のデータは存在し、ID=2のデータは存在しないものとする。
user_dataテーブルの値

また、Spring Bootアプリケーションを起動し、「http:// (ホスト名):(ポート番号)」とアクセスすると、以下の画面が表示される。
実行結果1

次に、以下のように、検索IDに1を指定し「検索」ボタンを押下すると、検索されたデータが表示される。
実行結果2_1

実行結果2_2

さらに、以下のように、検索IDに2を指定し「検索」ボタンを押下すると、該当するデータがない旨のダイアログが表示される。
実行結果3_1

実行結果3_2

要点まとめ

  • Spring Bootのコントローラメソッド上でJSON文字列を返却するには、メソッドに@ResponseBodyアノテーションを付与し、戻り値はJSON文字列とする。
  • Javaソース内でオブジェクトをJSON文字列に変換するには、ObjectMapperクラスのwriteValueAsStringメソッドを利用する。
  • JavaScriptソース内でJSON文字列をオブジェクトに変換するには、JSON.parseメソッドを利用する。