blog

JavaWebユーザーの追加、削除、変更、取得の実装の超詳細な要約

この記事は、役割の追加、削除、変更、チェックの機能を実現するためのモノリシックアーキテクチャに基づいています。フロントエンドの使用Bootstrap + Ajaxの+ Jspは、Springのバックエ...

Nov 25, 2020 · 18 min. read
シェア

序文

この記事は、追加、削除、変更、および役割を確認する機能を実現するためにモノリシックアーキテクチャに基づいています。フロントエンドの使用Bootstrap + Ajaxの+ Jspは、Springのバックエンドの使用+ SpringMvcの+ MyBatis開発は、私はこれらの技術の使用は、次の内容をよく理解する必要があると信じているだけでなく、この記事のパートナーが得ていることを確認することを願っています。

準備

バックエンドテクニック

フロントエンドのテクニック

ブートストラップ シンプルで直感的かつ堅牢なフロントエンド開発フレームワーク https://www.bootcss.com/
エイジャックス フロントエンドとバックエンドの相互作用
ジェイエスピー テンプレートエンジン
レイヤー メッセージアラート http://www.h-ui.net/lib/layer.js.shtml
モーダルプラグイン モーダルボックスは、親フォームに重なる子フォームです。

役割のメンテナンス - ページングの実装

ページング・フロントエンド機能の実装

外部JavaScriptソースファイルの作成,role.js

role-page.jspページにrole.jsファイルを導入します。

<script type="text/javascript" src="script/my-role.js"></script>

グローバル関数の初期化

ページネーションの実装では、グローバル関数、ページあたりのエントリ数、ページ番号、あいまい検索のキーワードを初期化します。

//グローバル変数の初期化
function initGlobalVariable() {
 window.pageSize = 5; //ページあたりのエントリー数
 window.pageNum = 1; // 
 window.keyword = ""; // 
}

ページング関数の宣言

//サーバーにリクエストを送り、ページング・データを取得し、ページング効果をページに表示する。
function showPage() {
 // ページング・データのリクエストをサーバーに送る: PageInfo
 var pageInfo = getPageInfo();
 // tbodyタグ内のページネーションの本文データをページ上のテーブルに表示する。
 generateTableBody(pageInfo);
 // ページのテーブルのtfootタグの中にページ番号ナビゲーションバーを表示する
 initPagination(pageInfo);
}

ページングデータの取得

function getPageInfo() {
 // 同期リクエストとして呼び出される$.ajax()関数の戻り値を取得する
 var ajaxResult = $.ajax({
 "url": "role/search/by/keyword.action",
 "type": "post",
 "data": {
 "pageNum": (window.pageNum == undefined) ? 1 : window.pageNum,
 "pageSize": (window.pageSize == undefined) ? 5 : window.pageSize,
 "keyword": (window.keyword == undefined) ? "" : window.keyword
 },
 "dataType": "json",
 "async": false // getPageInfo()関数が、Ajaxリクエストがレスポンスを取得した後にPageInfoを取得できるようにするためには、同期的に動作するように設定する必要がある。
 });
 
 // 完全なレスポンスデータからJSON形式のレスポンスボディデータを取得する
 var resultEntity = ajaxResult.responseJSON;
 // レスポンス・ボディのデータから結果を取得し、現在のリクエストが成功したかどうかを判断する
 var result = resultEntity.result;
 // PageInfoの取得に成功した場合
 if (result == "SUCCESS") {
 return resultEntity.data;
 }
 if (result == "FAILED") {
 layer.msg(resultEntity.message);
 }
 return null;
}

ページング・データを tbody タグ内に表示するための PageInfo データの使用

function generateTableBody(pageInfo) {
 // すべての操作を実行する前にクリアする
 $("#roleTableBody").empty(); //これはページの<tbody id="roleTableBody"> </tbody>
 // データのコレクションを取得する
 var list = pageInfo.list;
 // リストが有効かどうかを判断する
 if (list == null || list.length == 0) {
 $("#roleTableBody").append("<tr><td colspan='4' style='text-align:center;'>データは照会されなかった!</td></tr>");
 return;
 }
 for (var i = 0; i < list.length; i++) {
 var role = list[i];
 var checkBtn = "<button type='button' class='btn btn-success btn-xs'><i class=' glyphicon glyphicon-check'></i></button>";
 var pencilBtn = "<button type='button' id='roleTableBody' roleid='" + role.id + "' class='btn btn-primary btn-xs editBtn'><i class=' glyphicon glyphicon-pencil'></i></button>";
 var removeBtn = "<button type='button' roleid='" + role.id + "' class='btn btn-danger btn-xs removeBtn'><i class=' glyphicon glyphicon-remove'></i></button>";
 var numberTd = "<td>" + (i + 1) + "</td>";
 var checkBoxTd = "<td><input class='itemBox' roleid='" + role.id + "' type='checkbox'></td>";
 var roleNameTd = "<td>" + role.name + "</td>";
 var btnTd = "<td>" + checkBtn + " " + pencilBtn + " " + removeBtn + "</td>";
 var tr = "<tr>" + numberTd + checkBoxTd + roleNameTd + btnTd + "</tr>";
 // 先ほど説明したHTMLコードを#roleTableBody 
 $("#roleTableBody").append(tr);
 }
}

ナビゲーションバーの初期化操作をカプセル化する関数を宣言します。

function initPagination(pageInfo) {
 // ページング・ナビゲーション・バー表示時のプロパティ設定を格納する変数を宣言する
 var paginationProperties = {
 num_edge_entries: 3, //エッジページ数
 num_display_entries: 5, //メインページ数
 callback: pageselectCallback, //コールバック関数
 items_per_page: window.pageSize, //1ページに表示されるデータ数はpageSizeである。
 current_page: (window.pageNum - 1),//現在のページ番号
 prev_text: "前のページ", //前のページのテキスト
 next_text: "次へ" //次のテキスト
 };
 // ページング・ナビゲーション・バーを表示する<div id="Pagination" class="pagination"> <!-- ここにページングを表示する> </div>
 $("#Pagination").pagination(pageInfo.total, paginationProperties);
}

各クリックで "前"、"次"、"ページ番号 "この関数の実装は、ページにジャンプする場合

function pageselectCallback(pageIndex, jq) {
 // グローバル変数のpageNumを最新の値に変更する
 // pageIndex0から始まり、pageNumは1から始まる。
 window.pageNum = pageIndex + 1;
 // ページング関数を呼び出してページングを再実行する
 showPage();
 return false;
}

ページの初期化は、役割メンテナンスページをクリックしたときに読み込まれます。

$(function(){
 
 // ページングパラメータ初期化メソッドを呼び出す
 initGlobalVariable();
 // ページングを実行する
 showPage();
});

キーワード検索機能

Query "ボタンをクリックした後、テキストボックスに入力されたキーワード値を取得し、グローバル変数keywordに代入し、showPage()関数を呼び出します。

//キーワードクエリの実装
 $("#searchBtn").click(function () {
 //キーワードクエリの値を取得する
 var keywordInput = $.trim($("#keywordInput").val());
 /*if (keywordInput==null || keywordInput==""){
 layer.msg("キーワード") "を入力する;
 return;
 }*/
 window.keyword = keywordInput;
 //クエリー操作を行う
 showPage();
 });

ページネーションのバックエンド実装

役割をクリックすると、両方のアイデアのページデータがロードされたままになります:

1つ目は、モデルへのデータのクエリをバックグラウンドに要求し、表示されたデータのトラバースをフォアグラウンドに要求することです。

もうひとつは、PageInfoのときにバックグラウンドにデータを照会するように要求し、次にダイナミック・スプライシングでデータをページに表示することです。

Controllerメソッドの実装

@ResponseBody
 @RequestMapping("/role/search/by/keyword")
 public ResultEntity<PageInfo<Role>> search(
 @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
 @RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize,
 @RequestParam(value = "keyword", defaultValue = "") String keyword) {
 // 1.PageInfoオブジェクトを取得するクエリー
 PageInfo<Role> pageInfo = roleService.queryForKeywordWithPage(pageNum, pageSize, keyword);
 // 2.結果オブジェクトをカプセル化して返す
 return ResultEntity.successWithData(pageInfo);
 }

Serviceメソッドの実装

public PageInfo<Role> queryForKeywordWithPage(Integer pageNum, Integer pageSize, String keyword) {
 // 1.ページングをオンにする
 PageHelper.startPage(pageNum, pageSize);
 // 2.クエリーを実行する
 List<Role> list = roleMapper.selectForKeywordSearch(keyword);
 // 3.PageInfoオブジェクトとしてカプセル化される
 return new PageInfo<Role>(list);
 }

Mapperメソッドの実装

List<Role> selectForKeywordSearch(String keyword);

マッパー.xml

<select id="selectForKeywordSearch" resultMap="BaseResultMap">
 SELECT
 id,
 `name`
 FROM
 t_role
 WHERE
 `name` LIKE CONCAT('%', #{keyword}, '%')
</select>

役割メンテナンス - すべての機能を選択

ページ上の関数の位置

の具体的な実装は

マーカー

ロールページ.jsp

<thead>
 <tr>
 <th width="30">#</th>
 <th width="30"><input id="summaryBox" type="checkbox"></th>
 <th>名称</th>
 <th width="100">操作</th>
 </tr>
</thead>

マイロール

for (var i = 0; i < list.length; i++) {
 //省略
 var checkBoxTd = "<td><input class='itemBox' roleid='" + role.id + "' type='checkbox'></td>";
 //省略
}

summaryBoxにシングルクリック応答関数をバインドします。

 //全選択/全選択解除機能の実装
 $("#summaryBox").click(function () {
 //現在の選択状態を取得する
 var currentStatus = this.checked;
 $(".itemBox").prop("checked", currentStatus);
 });

役割のメンテナンス - 一括削除

モーダルボックスの準備

最初にモーダルボックスの HTML タグを用意します。

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<div id="confirmModal" class="modal fade" tabindex="-1" role="dialog">
 <div class="modal-dialog" role="document">
 <div class="modal-content">
 <div class="modal-header">
 <button type="button" class="close" data-dismiss="modal"
 aria-label="Close">
 <span aria-hidden="true">&times;</span>
 </button>
 <h4 class="modal-title">役割メンテナンス削除</h4>
 </div>
 <div class="modal-body">
 <p>下に表示されているものを本当に削除していいのか?</p>
 <table class="table table-bordered">
 <thead>
 <tr>
 <th width="30">#</th>
 <th>名称</th>
 </tr>
 </thead>
 <tbody id="confirmModalTableBody"></tbody>
 </table>
 </div>
 <div class="modal-footer">
 <button id="confirmModalBtn" type="button" class="btn btn-primary">OK</button>
 </div>
 </div>
 </div>
</div>

getRoleListByRoleIdArray()

//id役割情報を照会る
function getRoleListByRoleIdArray(roleIdArray) {
 //roleIdArrayJSON文字列に変換する
 var roleIds = JSON.stringify(roleIdArray);
 var ajaxResult = $.ajax({
 "url": "role/get/list/by/id/list.action",
 "type": "post",
 "data": roleIds,
 "contentType": "application/json;charset=UTF-8",
 "dataType": "json",
 "async": false
 });
 // 3.JSONオブジェクト型のレスポンスボディを取得する
 var resultEntity = ajaxResult.responseJSON;
 var result = resultEntity.result;
 if (result == "SUCCESS") {
 // 5.成功すればroleListが返される
 return resultEntity.data;
 }
 if (result == "FAILED") {
 layer.msg(resultEntity.message);
 return null;
 }
 return null;
}

対応するバックエンドのコード:

 @ResponseBody
 @RequestMapping("role/get/list/by/id/list")
 public ResultEntity<List<Role>> getRoleListByIdList(@RequestBody List<Integer> roleIds) {
 List<Role> roleList = roleService.findRoleListByIdList(roleIds);
 return ResultEntity.successWithData(roleList);
 }
public List<Role> findRoleListByIdList(List<Integer> roleIds) {
 return roleMapper.findRoleListByIdList(roleIds);
 }

showRemoveConfirmModal()

// 削除確認モーダルボックスを開く
function showRemoveConfirmModal() {
 // 1.モーダルボックスを
 $("#confirmModal").modal("show");
 //文字データを取得する
 var roleList = getRoleListByRoleIdArray(window.roleIdArray);
 //テーブルデータをクリアする
 $("#confirmModalTableBody").empty();
 //confirmModalTableBodyにデータを入れる
 for (var i = 0; i < roleList.length; i++) {
 // 5.文字関連データの取得
 var role = roleList[i];
 var id = role.id;
 var name = role.name;
 var trHTML = "<tr><td>" + (i+1) + "</td><td>" + name + "</td></tr>";
 // 6.フィルを実行する
 $("#confirmModalTableBody").append(trHTML);
 }
}

一括削除ボタンクリック時のシングルクリック応答機能のバインド

一括削除ボタンをマーク

 <button type="button" class="btn btn-danger" id="batchRemoveBtn"
 style="float: right; margin-left: 10px;">
 <i class=" glyphicon glyphicon-remove"></i>  
 </button>

itemBoxが選択されているかどうかをチェックします。

 // 一括削除ボタンにクリック応答関数をバインドする
 $("#batchRemoveBtn").click(function () {
 //選択されたitemBox配列の長さを取得する
 var length = $(".itemBox:checked").length;
 if (length == 0) {
 layer.msg("削除するレコードを選択してください!");
 return;
 }
 // 未完成のビジネス...
 });

ポップアップモーダルボックスに確認メッセージを表示します。

 // 一括削除ボタンにクリック応答関数をバインドする
 $("#batchRemoveBtn").click(function () {
 //選択されたitemBox配列の長さを取得する
 var length = $(".itemBox:checked").length;
 if (length == 0) {
 layer.msg("削除するレコードを選択してください!");
 return;
 }
 window.roleIdArray = new Array();
 //チェックボックスを繰り返し処理する
 $(".itemBox:checked").each(function () {
 //チェックボックスのroleidプロパティでroleId値を取得する
 var roleId = $(this).attr("roleid");
 //配列に格納される
 window.roleIdArray.push(roleId);
 });
 // モーダルボックスを開く関数を呼び出す
 showRemoveConfirmModal();
 });

モーダルボックスのOKボタンをクリックして削除を実行します。

OKマークを押してください

 <button **id="confirmModalBtn"** type="button" class="btn btn-primary">OK</button> 

クリックレスポンス機能のバインド

$("#confirmModalBtn").click(function () {
 //配列からJsonへ
 var roleIds = JSON.stringify(window.roleIdArray);
 var ajaxResult = $.ajax({
 "url": "role/batch/remove.action",
 "type": "post",
 "data": roleIds,
 "contentType": "application/json;charset=UTF-8",
 "dataType": "json",
 "async": false,
 "success": function (response) {
 var result = response.result;
 if (result == "SUCCESS") {
 layer.msg("操作成功!");
 // 削除に成功すると、ページング・メソッドが再び呼び出される。
 showPage();
 }
 if (result == "FAILED") {
 layer.msg(response.message);
 }
 // 成功しても失敗しても、モーダルボックスをオフにする必要がある
 $("#confirmModal").modal("hide");
 },
 "error": function (response) {
 if (result == "FAILED") {
 layer.msg(response.message);
 }
 }
 });
 }); 

バックエンドコード

 @ResponseBody
 @RequestMapping(value = "role/batch/remove")
 public ResultEntity<String> batchAdminList(@RequestBody List<Integer> roleIds) {
 try {
 roleService.batchRoleList(roleIds);
 return ResultEntity.successWithoutData();
 } catch (Exception e) {
 return ResultEntity.failed(null, e.getMessage());
 }
 }
public void batchRoleList(List<Integer> roleIds) {
 roleMapper.batchRoleList(roleIds);
 }
<delete id="batchRoleList" parameterType="java.util.List">
 delete from t_role where id in
 <foreach collection="list" item="item" open="(" separator="," close=")" >
 #{item}
 </foreach>
</delete>

役割のメンテナンス - 新規

一般的な手順

  • 追加」ボタンにクリック応答関数をバインドします。

  • モーダルボックスを開く

  • 保存ボタンへのクリック応答関数のバインド

  • テキストボックスの内容を収集

  • リクエスト送信

  • リクエスト処理完了 モーダルボックス、リページ、フォームのクリーンアップを閉じます。

クリック・レスポンス関数を新しいボタンにバインドします。

追加ボタンのフラグ

 <button type="button" class="btn btn-primary" id="addBtn"
 style="float: right;">
 <i class="glyphicon glyphicon-plus"></i>  
 </button>

クリックレスポンス機能のバインド

 $("#addBtn").click(function(){ alert("aaa..."); }); 

モーダルボックスの準備

まず、モーダルボックスの HTML コード include-modal-role-add.jsp を用意します。

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<div id="addModal" class="modal fade" tabindex="-1" role="dialog">
 <div class="modal-dialog" role="document">
 <div class="modal-content">
 <form role="form">
 <div class="modal-header">
 <button type="button" class="close" data-dismiss="modal"
 aria-label="Close">
 <span aria-hidden="true">&times;</span>
 </button>
 <h4 class="modal-title">役割が追加された</h4>
 </div>
 <div class="modal-body">
 <input type="text" id="roleNameInput" class="form-control" placeholder="ロール名を入力する>
 </div>
 <div class="modal-footer">
 <button type="button" id="addModalBtn" class="btn btn-default"><i class="glyphicon glyphicon-plus"></i>  </button>
 <button type="reset" class="btn btn-primary"><i class="glyphicon glyphicon-refresh"></i>  </button>
 </div>
 </form>
 </div>
 </div>
</div>

モーダルボックスを開く

 $("#addBtn").click(function(){ $("#addModal").modal("show"); }); 

保存ボタンへのクリック応答関数のバインド

保存」ボタンをマークします。

 <button id="addModalBtn" type="button" class="btn btn-success"> <i class="glyphicon glyphicon-plus"></i> </button> 

クリックレスポンス機能のバインド

$("#addModalBtn").click(function () {
 // 1.テキストボックスの内容を収集する
 var roleName = $.trim($("#roleNameInput").val());
 if (roleName == null || roleName == "") {
 layer.msg("有効なロール名を入力してください!");
 return;
 }
 // 2.リクエストを送信する
 $.ajax({
 "url": "role/save/role.action",
 "type": "post",
 "data": {
 "roleName": roleName
 },
 "dataType": "json",
 "success": function (response) {
 var result = response.result;
 if (result == "SUCCESS") {
 layer.msg("操作成功!");
 // 3.リパジションに成功
 // 最後のページへ
 window.pageNum = 999999;
 showPage();
 }
 if (result == "FAILED") {
 layer.msg(response.message);
 }
 // 4.成功しても失敗しても、モーダルボックスを閉じる
 $("#addModal").modal("hide");
 // 5.今回テキストボックスに記入されたデータを消去する
 $("#roleNameInput").val("");
 },
 "error": function (response) {
 layer.msg(response.message);
 }
 });
 });

バックエンドコードの一部

 @ResponseBody
 @RequestMapping("role/save/role")
 public ResultEntity<String> saveRole(@RequestParam("roleName") String roleName) {
 try {
 roleService.saveRole(roleName);
 return ResultEntity.successWithoutData();
 } catch (Exception e) {
 return ResultEntity.failed(null, e.getMessage());
 }
 }

公開リターンコード

public class ResultEntity<T> {
 public static final String SUCCESS = "SUCCESS";
 public static final String FAILED = "FAILED";
 public static final String NO_MESSAGE = "NO_MESSAGE";
 public static final String NO_DATA = "NO_DATA";
 // 成功した結果を返しやすくする
 public static ResultEntity<String> successWithoutData() {
 return new ResultEntity<String>(SUCCESS, NO_MESSAGE, NO_DATA);
 }
 // 成功した結果を返しやすくする
 public static <E> ResultEntity<E> successWithData(E data) {
 return new ResultEntity<E>(SUCCESS, NO_MESSAGE, data);
 }
 // 失敗結果を返すのに便利
 public static <E> ResultEntity<E> failed(E data, String message) {
 return new ResultEntity<E>(FAILED, message, data);
 }
 private String result;
 private String message;
 private T data;
 public ResultEntity() {
 }
 public ResultEntity(String result, String message, T data) {
 super();
 this.result = result;
 this.message = message;
 this.data = data;
 }
 @Override
 public String toString() {
 return "ResultEntity [result=" + result + ", message=" + message + ", data=" + data + "]";
 }
 public String getResult() {
 return result;
 }
 public void setResult(String result) {
 this.result = result;
 }
 public String getMessage() {
 return message;
 }
 public void setMessage(String message) {
 this.message = message;
 }
 public T getData() {
 return data;
 }
 public void setData(T data) {
 this.data = data;
 }
}

役割のメンテナンス - 更新

一般的な手順

編集ボタンへのクリック応答関数のバインド

モーダルボックスを開く

  • モーダルボックスの準備
  • roleIdをグローバル変数に保存
  • 現在のボタンが配置されている行のroleNameを取得します。
  • モーダルボックスにフォームを表示するには、roleName を使用します。
  • 更新ボタンへのクリック応答関数のバインド
  • テキストボックスの内容の収集
  • リクエスト送信
  • リクエスト処理が完了したら、モーダルボックスを閉じてリページします。

編集ボタンへのクリック応答関数のバインド

マーカー編集ボタン

my-role.jsファイル

function generateTableBody(pageInfo) {
 //省略
 var pencilBtn = "<button type='button' roleid='" + role.id + "' class='btn btn-primary btn-xs editBtn'><i class=' glyphicon glyphicon-pencil'></i></button>";
 //省略
 }
}

モーダルボックスの準備

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8" %>
<div id="editModal" class="modal fade" tabindex="-1" role="dialog">
 <div class="modal-dialog" role="document">
 <div class="modal-content">
 <form role="form">
 <div class="modal-header">
 <button type="button" class="close" data-dismiss="modal"
 aria-label="Close">
 <span aria-hidden="true">&times;</span>
 </button>
 <h4 class="modal-title">Sunchip.comシステムポップアップ</h4>
 </div>
 <div class="modal-body">
 <input type="text" id="roleNameInputEdit" class="form-control"
 placeholder="ロール名を入力する>
 </div>
 <div class="modal-footer">
 <button id="editModalBtn" type="button" class="btn btn-warning">
 <i class="glyphicon glyphicon-edit"></i> 更新
 </button>
 <button type="reset" class="btn btn-primary">
 <i class="glyphicon glyphicon-refresh"></i>  
 </button> </div>
 </form>
 </div>
 </div>
</div>

クリックレスポンス機能のバインド

 $("#roleTableBody").on("click", ".editBtn", function () {
 // 1.現在のボタンのroleIdを取得する
 window.roleId = $(this).attr("roleId");
 // 2.現在のボタンが配置されている行のroleNameを取得する
 var roleName = $(this).parents("tr").children("td:eq(2)").text();
 // 3.にroleNameを表示する目的で、モーダルボックスのこのボックスの値を変更する。
 $("#roleNameInputEdit").val(roleName);
 // 4.モーダルボックスを開く
 $("#editModal").modal("show");
 });

更新ボタンへのクリック応答関数のバインド

$("#editModalBtn").click(function () {
 // 1.テキストボックスの値を取得する
 var roleName = $.trim($("#roleNameInputEdit").val());
 if (roleName == null || roleName == "") {
 layer.msg("有効なロール名を入力してください!");
 return;
 }
 // 2.リクエストを送信する
 $.ajax({
 "url": "role/update.action",
 "type": "post",
 "data": {
 "id": window.roleId,
 "name": roleName
 },
 "dataType": "json",
 "success": function (response) {
 var result = response.result;
 if (result == "SUCCESS") {
 layer.msg("操作成功!");
 // 3.操作の再拡張に成功
 showPage();
 }
 if (result == "FAILED") {
 layer.msg(response.message);
 }
 // 4.成功しても失敗しても、モーダルボックスを閉じる
 $("#editModal").modal("hide");
 }
 });
 });

バックエンドコードの一部

 @ResponseBody
 @RequestMapping("role/update")
 public ResultEntity<String> updateRole(@RequestParam("id") Integer id,
 @RequestParam("name") String name) {
 Role role = new Role();
 role.setId(id);
 role.setName(name);
 try {
 roleService.updateRole(role);
 return ResultEntity.successWithoutData();
 } catch (Exception e) {
 return ResultEntity.failed(null, e.getMessage());
 }
 }

例外マッピングは非同期リクエストと互換性があります。

問題の表現

Ajaxリクエストはサーバーサイドの処理中に例外をスローし、例外ハンドラを通過します:

@ControllerAdvice
public class CrowdFundingExceptionResolever {
 
 @ExceptionHandler(value=Exception.class)
 public ModelAndView catchException(Exception exception) {
 
 ModelAndView mav = new ModelAndView();
 
 mav.addObject("exception", exception);
 
 mav.setViewName("system-error");
 
 return mav;
 }
}

現在、この例外処理メカニズムはページのみを返すことができますが、JSONレスポンスデータを返すAjaxリクエストに対してはできません。そのため、Ajaxリクエスト処理中に例外がスローされ、例外情報ページが返された場合、Ajaxプログラムはそれを適切に解析することができず、その結果、ページが正しく表示されず、正しく動作せず、フレンドリーなエラーメッセージが表示されません。

問題解決のアイデア

非同期リクエスト機能

非同期リクエストを識別するためのツールアプローチ

 /**
 * リクエストが非同期かどうかを判断するために使われる
 * @param request
 * @return
 */
 public static boolean checkAsyncRequest(HttpServletRequest request) {
 
 // 1.対応するリクエストメッセージヘッダを取得する
 String accept = request.getHeader("Accept");
 String xRequested = request.getHeader("X-Requested-With");
 
 // 2.リクエストメッセージヘッダデータにターゲット機能が含まれているかどうかを判定する
 if(
 (stringEffective(accept) && accept.contains("application/json")) 
 || 
 (stringEffective(xRequested) && xRequested.contains("XMLHttpRequest")) ) {
 return true;
 }
 
 return false;
 }
 /**
 * 文字列が有効かどうかを判定する
 * @param source 検証される文字列
 * @return trueは有効、偽は無効を意味する
 */
 public static boolean stringEffective(String source) {
 
 return source != null && source.length() > 0;
 }

例外処理プロセッサーのアップグレード

最初に紹介:

<dependency>
 <groupId>com.google.code.gson</groupId>
 <artifactId>gson</artifactId>
 <version>2.8.5</version>
</dependency>
@ControllerAdvice
public class CrowdFundingExceptionResolever {
 @ExceptionHandler(value = Exception.class)
 public ModelAndView catchException(
 Exception exception,
 HttpServletRequest request,
 HttpServletResponse response) throws IOException {
 // 1.現在のリクエストのチェックを行う
 boolean checkAsyncRequestResult = CrowdFundingUtils.checkAsyncRequest(request);
 // 2.リクエストが非同期の場合
 if(checkAsyncRequestResult) {
 // 例外の型と定数の対応によって、エラーメッセージがより親しみやすいテキストで表示される。
 String exceptionClassName = exception.getClass().getName();
 String message = CrowdFundingConstant.EXCEPTION_MESSAGE_MAP.get(exceptionClassName);
 if(message == null) {
 message = "システム不明エラー ";
 }
 // 3.ResultEntityオブジェクトを作成する
 ResultEntity<String> resultEntity = ResultEntity.failed(ResultEntity.NO_DATA, message);
 // 4.resultEntityをJSON形式に変換する
 Gson gson = new Gson();
 String json = gson.toJson(resultEntity);
 // 5.レスポンスデータとしてjsonをブラウザに返す
 response.setContentType("application/json;charset=UTF-8");
 response.getWriter().write(json);
 return null;
 }
 ModelAndView mav = new ModelAndView();
 mav.addObject("exception", exception);
 mav.setViewName("system-error");
 return mav;
 }
}

定数クラス

public class CrowdFundingConstant {
 
 public static final Map<String, String> EXCEPTION_MESSAGE_MAP = new HashMap<String, String>();
 static {
 EXCEPTION_MESSAGE_MAP.put("java.lang.ArithmeticException", "システムが数学演算を実行中にエラーが発生した");
 EXCEPTION_MESSAGE_MAP.put("java.lang.RuntimeException", "システムの実行中にエラーが発生した");
 EXCEPTION_MESSAGE_MAP.put("com.atguigu.crowd.funding.exception.LoginException", "ログイン中の実行エラー");
 }
}
Read next

JVMチューニングのまとめ -Xms -Xmx -Xmn -Xss

JVMの最大ヒープ・サイズには3つの制限があります:関連するオペレーティング・システムのデータ・モデルの制限、システムの利用可能な仮想メモリーの制限、システムの利用可能な物理メモリーの制限。私は物理メモリが3.5GのWindows Server 2003システムを使用しています。

Nov 25, 2020 · 4 min read