Visual Studio CodeによるSpring5 MVC Webアプリ開発　Spring Security使用編 3/3【ページ作成編 2/2】

#はじめに
[こちら](https://qiita.com/t_skri/items/77b90fc31daf2689c5a3)からの続きです。
今回は一般ユーザー作成ページを作成していきます。

##controller作成
一般ユーザー作成ページのcontrollerを作成します。

```
D:\JAVA\Project\securitySample\src\main\java\com\example
└─controller
  └─UserRegController.java
```

###UserRegController.java

```java:UserRegController.java
package com.example.web.controller;

import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.example.persistence.entity.UserInfo;
import com.example.service.AuthService;
import com.example.web.form.AuthForm;

@Controller
@RequestMapping("/userReg")
public class UserRegController {
	@Autowired
	AuthService authService;

	final static Map<String, String> CHECK_ITEMS =
			Collections.unmodifiableMap(new LinkedHashMap<String, String>() {
				private static final long serialVersionUID = 1L;

				{
					put("ロール1", 		"ROLE_Role1");
					put("ロール2", 		"ROLE_Role2");
					put("ロール3", 		"ROLE_Role3");
				}
			});

	@GetMapping("/index")
	public String index(Model model) {
		List<UserInfo> userInfoList = authService.findUserAll();
		model.addAttribute("userInfoList", userInfoList);
		return "userReg/index";
	}

	@GetMapping("/registered")
	public String registeredGet() {
		return "userReg/registered";
	}

	@GetMapping("/insert")
	public String insertGet(Model model) {
		model.addAttribute("authForm", new AuthForm());
		model.addAttribute("checkItems", CHECK_ITEMS);
		return "userReg/insert";
	}

	@PostMapping("/insert")
	public String insertPost(Model model, RedirectAttributes attributes,
			@Valid AuthForm authForm, BindingResult bindingResult, HttpServletRequest request) {
		if (bindingResult.hasErrors()) {
			model.addAttribute("checkItems", CHECK_ITEMS);
			model.addAttribute("signupError", true);
			return "userReg/insert";
		}
		try {
			authService.insertUser(authForm);
		} catch (DataIntegrityViolationException e) {
			model.addAttribute("checkItems", CHECK_ITEMS);
			model.addAttribute("signupError", true);
			return "userReg/insert";
		}

		attributes.addFlashAttribute("message", "登録しました。");
		return "redirect:/userReg/registered";
	}

	@GetMapping("/{id}/update")
	public String updateGet(Model model, @PathVariable("id") String id) {
		AuthForm authForm = authService.userRegById(id);

		model.addAttribute("authForm", authForm);
		model.addAttribute("checkItems", CHECK_ITEMS);
		return "userReg/update";
	}

	@PostMapping("/{id}/update")
	public String updatePost(Model model,
			RedirectAttributes attributes,
			@Valid AuthForm authForm, BindingResult bindingResult, HttpServletRequest request) {

		if (bindingResult.hasErrors()) {
			model.addAttribute("checkItems", CHECK_ITEMS);
			model.addAttribute("signupError", true);
			return "userReg/update";
		}
		try {
			authService.updateUser(authForm);
		} catch (DataIntegrityViolationException e) {
			model.addAttribute("checkItems", CHECK_ITEMS);
			model.addAttribute("signupError", true);
			return "userReg/update";
		}

		attributes.addFlashAttribute("message", "変更しました。");
		return "redirect:/userReg/registered";
	}

	@GetMapping("/{id}/delete")
	public String deleteGet(Model model, @PathVariable("id") String id) {
		AuthForm authForm = authService.userRegById(id);

		model.addAttribute("authForm", authForm);
		model.addAttribute("checkItems", Arrays.asList(authForm.getAuthority()));
		return "userReg/delete";
	}

	@PostMapping("/{id}/delete")
	public String deletePost(Model model, @PathVariable("id") String id,
			RedirectAttributes attributes,
			@Valid AuthForm authForm, BindingResult bindingResult, HttpServletRequest request) {

		try {
			authService.deleteUser(authForm.getUserId());
		} catch (DataIntegrityViolationException e) {
			model.addAttribute("signupError", true);
			return "userReg/delete";
		}

		attributes.addFlashAttribute("message", "削除しました。");
		return "redirect:/userReg/registered";
	}
}
```

##view作成
一般ユーザー作成ページのviewを作成します。

```
D:\JAVA\Project\securitySample\src\main\webapp\WEB-INF\templates
└─userReg
  ├─delete.html
  ├─index.html
  ├─insert.html
  ├─register.html
  ├─registered.html
  └─update.html
```

```html:delete.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
	<head th:insert="fragment/frag01 :: htmlhead"></head>
	<title>ユーザー削除画面</title>
</head>
<body>
	<h1>ユーザー削除</h1>

	<form method="post" action="#" th:action="@{delete}" th:object="${authForm}">
		<div>
			<label for="userId">ログインID</label>
			<span th:text="*{userId}"></span>
			<input type="hidden" th:field="*{userId}">
		</div>

		<div>
			<label for="userNameJP">ユーザー名（日本語）</label>
			<span th:text="*{userNameJP}"></span>
			<input type="hidden" th:field="*{userNameJP}">
		</div>

		<div>
			<button type="submit">削除</button>
			&nbsp;&nbsp;&nbsp;
			<a th:href="@{/userReg/index}">キャンセル</a>
		</div>
	</form>

</body>
</html>
```

```html:index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
	<head th:insert="fragment/frag01 :: htmlhead"></head>
	<title>登録ユーザー一覧画面</title>
</head>

<body>
	<h1>登録ユーザー一覧</h1>
	<a href="insert.html" th:href="@{insert}">新規登録</a>
	<div>
   		<table border="1">
    		<thead>
        		<tr>
            		<th>ユーザーID</th>
            		<th>ユーザー名</th>
            		<th>部署名</th>
            		<th>ステータス</th>
            		<th>ロール</th>
            		<th>コマンド</th>
        		</tr>
       		</thead>
       		<tr th:each="userInfo : ${userInfoList}" th:object="${userInfo}">
           		<td th:text="*{userId}"></td>
           		<td th:text="*{userNameJP}"></td>
           		<td th:text="*{sectionNameJP}"></td>
           		<td th:if="*{enabled}">使用可</td>
				<td th:unless="*{enabled}">使用不可</td>
				<td>
					<th:block th:each="userRoles : *{userRolesList}" th:object="${userRoles}">
						<th:block th:utext="*{authority} + '<br />'"></th:block>
					</th:block>
				</td>
           		<td>
           			<a th:href="@{*{userId} + '/update'}">編集</a>
           			&nbsp;&nbsp;&nbsp;
           			<a th:href="@{*{userId} + '/delete'}">削除</a>
           		</td>
       		</tr>
	    </table>
   	</div>
</body>
</html>
```

```html:insert.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
	<head th:insert="fragment/frag01 :: htmlhead"></head>
	<title>ユーザー登録画面</title>
</head>
<body>
	<h1>ユーザー登録</h1>

	<form method="post" action="#" th:action="@{insert}" th:object="${authForm}">
		<div th:if="${signupError}">
			<em>登録出来ませんでした。</em>
		</div>

		<div>
			<label for="userId">ログインID</label>
			<input type="text" autofocus="autofocus" th:field="*{userId}">
		</div>

		<div th:insert="userReg/register :: register"></div>
	</form>

</body>
</html>
```

```html:register.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">

	<div th:fragment="register" th:remove="tag">
		<div>
			<label for="password">パスワード</label>:
			<input type="password" th:field="*{password}">
			<em th:if="${#fields.hasErrors('password')}" th:errors="*{password}">Password Error</em>
		</div>

		<div>
			<label for="userNameJP">ユーザー名（日本語）</label>
			<input type="text" th:field="*{userNameJP}">
		</div>

		<div>
			<label for="userId">部署名（日本語）</label>
			<input type="text" th:field="*{sectionNameJP}">
		</div>

		<div>
			<label>
				<input type="checkbox" id="enabled" th:field="*{enabled}">有効化
			</label>
		</div>

		<div>
			<label class="control-label col-sm-2">ロール</label>
				<div th:each="item : ${checkItems}">
					<label>
						<input type="checkbox" name="authority" th:value="${item.value}" th:text="${item.key}" th:field="*{authority}">
					</label>
				</div>
			<span th:if="${#fields.hasErrors('authority')}" th:errors="*{authority}" class="help-block">error!</span>
		</div>

		<div>
			<button type="submit">登録</button>
			&nbsp;&nbsp;&nbsp;
			<a th:href="@{/userReg/index}">キャンセル</a>
		</div>
	</div>
</html>
```
```html:registered.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
	<head th:insert="fragment/frag01 :: htmlhead"></head>
	<title>ユーザー登録メッセージ</title>
</head>
<body>
	<h1><span th:text="${message}">メッセージ</span></h1>
	<a th:href="@{index}">ユーザー一覧へ戻る</a>
</body>
</html>
```

```html:update.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org"
	xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
	<head th:insert="fragment/frag01 :: htmlhead"></head>
	<title>ユーザー編集画面</title>
</head>
<body>
	<h1>ユーザー編集</h1>

	<form method="post" action="#" th:action="@{update}" th:object="${authForm}">
	<div th:if="${signupError}">
			<em>更新出来ませんでした。</em>
		</div>
		<div>
			<label for="userId">ログインID</label>
			<span th:text="*{userId}"></span>
			<input type="hidden" th:field="*{userId}">
		</div>

		<div th:insert="userReg/register :: register"></div>
	</form>

</body>
</html>
```

#今回のサンプルソース
GitHubにアップしました。
https://github.com/t-skri1/SpringSample03

#まとめ
以上で一般ユーザー作成ページは完成です。
プロジェクトもこれで完成です。
コンパイルして動かしてみて下さい。
ロールによる挙動の違いも試して見て下さい。

#Visual Studio CodeによるSpring5 MVC Webアプリ開発を実践してみて
hot deployされないのが、とにかくしんどかったです。
慣れもありますが、Eclipseの方が自分にはしっくりくるなと言う感じでした。
今はあまり需要の無い？非BootのSpringだからやりにくいのでしょうか。
次回はBootでのWebアプリ開発をVisual Studio Codeにて行ってみます。