前回までで、作成したアプリをWEBアプリとして公開しました。
その後、少し機能を追加してみたのでまとめます。
トップ画面
ユーザの登録機能を作成しました。
最初はログイン画面に設置していましたが
ログイン後の画面に設置しなおしました。
トップページにはまだ何も置いていません。
お知らせ機能とか、カレンダーとか置きたいなと思っていますが
これから徐々に機能を増やしていきたいなと思っています。
前回までの記事でも記載しましたがログイン機能はSpringSecurityを使用しました。
手を動かしてコーディングをするのが数年ぶりなのと
SpringBootでアプリを作成するのが初めてなので
色々探り探りで躓きながらですが作成を進めています。
右上の「山田 太郎」はcontrollerから受け取ったログインユーザの名前が出るようにしています。
以下の記事の後ろのほうに記載したcssが適用されない件ですが解決しました。
当初は以下のような階層にしていたのですが
└── src
└── main
├── java
└── resources
└── static
└── templates
└── index.html // cssを適用させたいhtml
└── css
└── style.html
このようにしたら読み込めるようになりました。
└── src
└── main
├── java
└── resources
└── static
├── templates
| └── index.html // cssを適用させたいhtml
└── css
└── style.html
Thymeleafを使用しているので、記述方式がThymeleaf式です。
ちなみに
th:src … HTML 文書中に埋め込む画像やスクリプトなどのリソース
th:href … HTML 文書にリンクするリソース
という区別だそうです。
画面側はあまりやってこなかったので勉強になりました。
同じように右上のアイコン画像も読み込めたので
ログアウト用のアイコンとして設置しています。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<link th:href="@{/css/style.css}" rel="stylesheet">
<script th:src="@{https://code.jquery.com/jquery-3.4.1.min.js}"></script>
</head>
<body class="in-body">
<!-- 以下略 -->
ヘッダー部分を共通化したかったのですが、こちらはうまくいきませんでした。
どうにもHTMLがうまく読み込まれない...
またしばらくしたらトライしたいです。
ユーザ検索画面
登録したユーザ情報が検索できる画面を作成しました。
メニューの「ユーザ管理」から遷移する先がこちらです。
テーブルはjQuaryで作成するか迷いましたが
Thymeleafの機能で作成しました。便利です。
ソースコードはこんな感じ。
/**
* ユーザ検索画面の処理(GET)
* @return
*/
@GetMapping("/userSearch")
public ModelAndView userSearchForm(@ModelAttribute UserSearchDto userSearchDto) {
// 画面に返却するオブジェクトを生成
ModelAndView mav = new ModelAndView();
// ログイン情報を取得
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UserPrincipal userInfo = (UserPrincipal) authentication.getPrincipal();
if (userInfo != null) {
// ユーザ情報が取得できた場合は名前をセット
mav.addObject("name", userInfo.getUser().getLastName() + " " + userInfo.getUser().getFirstName());
}
if (userSearchDto.getViewType() == null) {
// 初期表示処理
mav.addObject("userSearchDto", new UserSearchDto());
mav.setViewName("userSearch");
return mav;
}
// 検索実行時処理
List<User> users = null;
if (userSearchDto.getUserId().isBlank() &&
userSearchDto.getFirstName().isBlank() &&
userSearchDto.getFirstNameKana().isBlank() &&
userSearchDto.getLastName().isBlank() &&
userSearchDto.getLastNameKana().isBlank() &&
userSearchDto.getRoleAdmin() == 0 &&
userSearchDto.getRoleEmployee() == 0 &&
userSearchDto.getRoleContract() == 0 &&
userSearchDto.getValid() == 0) {
// 全件検索
users = userService.findAll();
} else {
// 部分検索
users = userDaoImpl.search(userSearchDto);
}
mav.addObject("userSearchDto", new UserSearchDto()); // 次の検索実行用の入れ物
if (users.isEmpty()) {
// ユーザ情報が1件も取得できなかった場合
mav.addObject("msg", CommonVariable.MSG_02);
} else {
mav.addObject("users", users);
}
mav.setViewName("userSearch");
return mav;
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<link th:href="@{/css/style.css}" rel="stylesheet">
<script th:src="@{https://code.jquery.com/jquery-3.4.1.min.js}"></script>
</head>
<body class="in-body">
<!--ヘッダー共通部分(略) -->
<main>
<p class="view-title">ユーザ検索</p>
<div class="search-form">
<form th:action="@{/userSearch}" th:object="${userSearchDto}" method="get">
<label class="search-label">ユーザID</label>
<input type="text" id="userId" name="userId"><br>
<label class="search-label">ユーザ名</label>
<input type="text" id="lastName" name="lastName" placeholder="姓">
<input type="text" id="firstName" name="firstName" placeholder="名"><br>
<label class="search-label">ユーザ名(カナ)</label>
<input type="text" id="lastNameKana" name="lastNameKana" placeholder="セイ">
<input type="text" id="firstNameKana" name="firstNameKana" placeholder="メイ"><br>
<label for="email" class="search-label">メールアドレス</label>
<input type="text" id="email" name="email"><br>
<label class="search-label">権限</label>
<input type="checkbox" name="roleAdmin" value="1" /><label>管理者</label>
<input type="checkbox" name="roleEmployee" value="1" /><label>社員</label>
<input type="checkbox" name="roleContract" value="1" /><label>契約社員</label><br>
<label class="search-label">有効/無効</label>
<input type="checkbox" id="valid" name="valid" value="1" /><label for="valid">無効を含む</label><br>
<input type="hidden" name="viewType" value="search" />
<button class="submit" type="submit" value="Submit">検索</button>
<button class="reset" type="reset" value="Reset">リセット</button>
<button class="register" type="register" value="Register"><a th:href="@{/userRegister}">新規登録</a></button>
</form>
</div>
<a class="search-msg" th:if="${msg}" th:text="${msg}"></a>
<table>
<tr th:if="${users}">
<th>ユーザID</th>
<th id="fix">名</th>
<th id="fix">姓</th>
<th id="fix">メールアドレス</th>
<th id="fix">権限</th>
<th id="fix">有効/無効</th>
<th></th>
</tr>
<tr class="data-table" th:each="item: ${users}">
<td class="fix" th:text="${item.userId}"></td>
<td class="fix" th:text="${item.lastName}"></td>
<td class="fix" th:text="${item.firstName}"></td>
<td class="fix" th:text="${item.email}"></td>
<td class="fix" th:if="${item.roleCode} eq 0">システム管理者</td>
<td class="fix" th:if="${item.roleCode} eq 1">管理者</td>
<td class="fix" th:if="${item.roleCode} eq 2">社員</td>
<td class="fix" th:if="${item.roleCode} eq 3">契約社員</td>
<td class="fix" th:if="${item.validFlag} eq true">有効</td>
<td class="fix" th:if="${item.validFlag} eq false">無効</td>
<td>
<a th:href="@{/userRef(userId=${item.userId})}"><img class="edit" th:src="@{/img/edit.png}" height="20px"></a>
</td>
</tr>
</table>
</main>
<footer></footer>
</body>
<script th:src="@{/js/common.js}"></script>
</html>
th:each="item: ${users}"
これが便利です。
usersにはControllerから渡されたUserのリストが格納されており
これが存在した場合はリストの数だけ次のコードの生成を行ってくれます。
ログイン情報の取得方法についてや初期表示の判定方法は
他にもっと効率的な処理の仕方があるような気がしますが
技術不足があるので勉強しつつでアップデートしていけたらなと思います。
HTMLは基本的にノリで書いているので
フロントエンジニアから見るとダメダメかもしれません。
idとclassの使い分けとか、divタグ aタグ pタグの使い分けとかあんまりよくわかってません...
classはグループ名でidは項目単位の名前ってくらいの認識。
検索ボタンからは検索画面に、
新規登録ボタンからは新規登録画面に
テーブルの行の一番右のアイコンからは編集画面に遷移します。
リセットの処理はjQuaryで実装したいですがまだできていません。
組みながら最善を模索していますので
javaでもhtmlでも、こんな方法があるよ!こうしたらもっといいよ!
など、アドバイス等あればコメントいただけるとと思います。
思ったより長くなってしまったので今回は一旦ここまで、
次回、検索処理の詳細と、新規登録・編集の処理について書いていきたいと思います。