Spring BootのWEB画面上では、Ajax通信も行うことができる。今回は、jQueryを利用しない形で、Ajax通信を含むサンプルプログラムを作成してみたので、共有する。
前提条件
下記記事のSpring BootでのOracle接続処理の実装が完了していること。
また、以下の記事の「hibernate_sequence」シーケンスの作成が完了していること。
サンプルプログラムの作成
まず、HTMLは以下の内容になっていて、検索ボタンを押下した場合に、後述のdemo.jsの関数「getUserData」を呼び出すようになっている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <!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オブジェクトの値を、画面上に表示するようになっている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | '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文字列に変換して返却している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | 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
サンプルプログラムの実行結果
user_dataテーブルのデータの内容は以下の通りで、ID=1のデータは存在し、ID=2のデータは存在しないものとする。
また、Spring Bootアプリケーションを起動し、「http:// (ホスト名):(ポート番号)」とアクセスすると、以下の画面が表示される。
次に、以下のように、検索IDに1を指定し「検索」ボタンを押下すると、検索されたデータが表示される。
さらに、以下のように、検索IDに2を指定し「検索」ボタンを押下すると、該当するデータがない旨のダイアログが表示される。
要点まとめ
- Spring Bootのコントローラメソッド上でJSON文字列を返却するには、メソッドに@ResponseBodyアノテーションを付与し、戻り値はJSON文字列とする。
- Javaソース内でオブジェクトをJSON文字列に変換するには、ObjectMapperクラスのwriteValueAsStringメソッドを利用する。
- JavaScriptソース内でJSON文字列をオブジェクトに変換するには、JSON.parseメソッドを利用する。