LoginSignup
0
1

Spring Securityを使ったWebアプリケーションの基本④ 〜ユーザー情報を一覧と作成〜

Posted at

はじめに

前回の記事では、ユーザー情報をデータベースに登録し、ユーザー情報テーブルから、ログインできるように実装をしていきました。今回はユーザー情報を一覧で表示し、ユーザーと思います。
ファイル構成


.
├── .gradle
├── .idea
├── build
├── gradle
└── src
     ├── main
     │    ├── java
     │    │    └── com
     │    │         └── example
     │    │              └── practice 
     │    │                  ├── config
     │    │                  │    └── SecurityConfig.java
     │    │                  ├── web 
     │    │                  │    ├── user
     │    │                  │    │    ├── UserController.java
     │    │                  │    │    └── userForm.java
     │    │                  │    ├── order
     │    │                  │    │    ├── OrderController.java
     │    │                  │    │    └── OrderForm.java
     │    │                  │    └── IndexController.java
     │    │                  └── domain
     │    │                      ├── authentication
     │    │                      │    ├── CustomUserDetails.java
     │    │                      │    ├── CustomUserDetailsService.java
     │    │                      │    ├── User.java
     │    │                      │    ├── UserService.java
     │    │                      │    └── UserRepository
     │    │                      └── order 
     │    │                           ├── OrderEntity.java
     │    │                           ├── OrderService.java
     │    │                           └── OrderRepository.java
     │    │                        
     │    └── resources
     │         ├── static
     │         ├── templates
     │         │    ├── users
     │         │    │    ├── creationForm.html
     │         │    │    └── list.html
     │         │    ├── order
     │         │    │    ├── delete_confirmation.html
     │         │    │    ├── detail.html 
     │         │    │    ├── form.html 
     │         │    │    └── list.html
     │         │    ├── login.html
     │         │    └── index.html
     │         ├── schema.sql
     │         ├── data.sql 
     │         └── application.properties
     └── test
.gitignore
build.gradle
gradlew.bat
HELP.md
settings.gradle

UserRepository

まずは、ユーザー情報を一覧で表示するために、ユーザー情報をSELECT文で取得します。
UserRepository
package com.example.practice.domain.authentication;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;
import java.util.Optional;

@Mapper
public interface UserRepository {
        @Select("select * from users where username = #{username}")
        Optional<User> findByUsername(String username);

        @Select("select * from users")
        List<User> findAll();
}

UserService

次に、ビジネスロジックの部分であるUserServiceを記載していきます。
UserService
package com.example.practice.domain.authentication;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
public class UserService {

    // UserRepositoryのインスタンスを注入
    private final UserRepository userRepository;

    // ユーザー一覧を取得するメソッド
    public List<User> findAll() {
        // userRepositoryを使ってデータベースからユーザー一覧を取得し、返す
        return userRepository.findAll();
    }
}

VIEWの作成

次に、ユーザー一覧を表示するためのVIEWを作成していきます。 以下がその実装になります。
list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>トップページ | 業務用アプリケーション</title>
    <!-- Bootstrap CSS link -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-4">
    <!-- ヘッダー部分 -->
    <header class="mb-4 bg-light p-3 rounded">
        <div class="d-flex justify-content-between align-items-center">
            <h1 class="mb-0"><a href="../index.html" th:href="@{/}" class="text-dark text-decoration-none">業務管理アプリケーション</a></h1>
            <a href="#" th:href="@{/logout}" th:attr="data-method='post'" class="btn btn-dark" style="font-size: 18px;">ログアウト</a>
        </div>
    </header>
    <div class="d-flex justify-content-center align-items-center flex-column">
        <h1 class="mt-3">ユーザー一覧</h1>
        <table class="table table-striped">
            <thead>
            <tr>
                <th>ユーザー名</th>
            </tr>
            </thead>
            <tbody>
            <tr th:each="user : ${userList}">
                <td th:text="${user.username}"></td>
            </tr>
            </tbody>
        </table>
    </div>
</div>
</body>
</html>

UserController

最後に、Controllerの実装をしていきます。
UserController
package com.example.practice.web.user;

import com.example.practice.domain.authentication.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Collections;

@Controller
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;

    @GetMapping
    public String showList(Model model) {
        model.addAttribute("userList", userService.findAll());
        return "users/list";
    }
}

ユーザー作成

次に、ユーザー情報をデータベースに追加する処理を追加していきたいと思います。 こちらもMVCモデルに従って作成していきましょう。

UserForm

ユーザー情報をフォームとして受け取るために、データベースの定義をしていきます。
UserForm
package com.example.practice.web.user;

import lombok.AllArgsConstructor;
import lombok.Data;
import javax.validation.constraints.NotBlank;

@Data
@AllArgsConstructor
public class UserForm {
    @NotBlank
    private String username;
    @NotBlank
    private String password;

}

UserRepository

ユーザー情報を追加するINSERT文の処理を追加していきます。

UserRepository
package com.example.practice.domain.authentication;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;
import java.util.Optional;

@Mapper
public interface UserRepository {
    // ユーザー名を指定してユーザー情報を取得するクエリ
    @Select("select * from users where username = #{username}")
    Optional<User> findByUsername(String username);

    // ユーザー一覧を取得するクエリ
    @Select("select * from users")
    List<User> findAll();

    // ユーザー情報を挿入するクエリ。#{param1} と #{param2} は引数の順番にバインドされるプレースホルダー
    @Insert("insert into users (username, password) values (#{param1}, #{param2})")
    void insert(String username, String password);
}

UserRepositoryでは、上記のコメントを含むように、データベースからユーザー情報を取得したり、新しいユーザー情報を挿入するクエリ処理を定義しています。

UserService

次にUserServiceに先ほど追加したINSERT文の処理を説明していきます。

UserService
package com.example.practice.domain.authentication;

import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
public class UserService {

    // UserRepositoryのインスタンスを注入
    private final UserRepository userRepository;

    // ユーザー一覧を取得するメソッド
    public List<User> findAll() {
        // userRepositoryを使ってデータベースからユーザー一覧を取得し、返す
        return userRepository.findAll();
    }
    
    // ユーザーを作成するメソッド
    public void create(String username, String password) {
        // ユーザー名とパスワードを引数としてuserRepositoryのinsertメソッドを呼び出し、新しいユーザー情報を挿入する
        userRepository.insert(username, password);
    }
}

VIEW

次に、VIEWの作成をしていきます。

以下がユーザー作成画面になります。

creationForm.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ユーザー作成 |  業務用アプリケーション</title>
    <!-- Bootstrap CSS link -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-4">
    <!-- ヘッダー部分 -->
    <header class="mb-4 bg-light p-3 rounded">
        <div class="d-flex justify-content-between align-items-center">
            <h1 class="mb-0"><a href="../index.html" th:href="@{/}" class="text-dark text-decoration-none">業務管理アプリケーション</a></h1>
            <a href="#" th:href="@{/logout}" th:attr="data-method='post'" class="btn btn-dark" style="font-size: 18px;">ログアウト</a>
        </div>
    </header>
    <form action="#" th:action="@{/users}" method="post" th:object="${userForm}">
    <div class="mt-3">
            <label for="usernameInput" class="form-label">ユーザー名</label>
            <input type="text" id="usernameInput" class="form-control" th:field="*{username}">
        </div>
        <div class="mt-3">
            <label for="passwordInput" class="form-label">パスワード</label>
            <input type="password" id="passwordInput" class="form-control" th:field="*{password}">
        </div>
        <div class="mt-3">
            <button type="submit" class="btn btn-primary">作成</button>
            <a href="./list.html" th:href="@{/users}" class="btn btn-secondary">取消</a>
        </div>
    </form>
</div>
</body>
</html>

ユーザー一覧画面に遷移リンクを追加します。

list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>トップページ | 業務用アプリケーション</title>
    <!-- Bootstrap CSS link -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-4">
    <!-- ヘッダー部分 -->
    <header class="mb-4 bg-light p-3 rounded">
        <div class="d-flex justify-content-between align-items-center">
            <h1 class="mb-0"><a href="../index.html" th:href="@{/}" class="text-dark text-decoration-none">業務管理アプリケーション</a></h1>
            <a href="#" th:href="@{/logout}" th:attr="data-method='post'" class="btn btn-dark" style="font-size: 18px;">ログアウト</a>
        </div>
    </header>
    <!-- ヘッダー部分の最後 -->
    <h2 class="text-center">ユーザー一覧</h2>
        <a href="../index.html" th:href="@{/}" class="btn btn-primary">トップページ</a>
        <a href="../creationForm.html" th:href="@{/users/creationForm}"class="btn btn-success">作成</a>
        <table class="table table-striped">
            <thead>
            <tr>
                <th>ユーザー名</th>
            </tr>
            </thead>
            <tbody>
            <tr th:each="user : ${userList}">
                <td th:text="${user.username}"></td>
            </tr>
            </tbody>
        </table>
    </div>
</div>
</body>
</html>

UserController

最後にControllerの設定をしていきます。

UserController
package com.example.practice.web.user;

import com.example.practice.domain.authentication.UserService;
import com.example.practice.web.order.OrderForm;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Collections;

@Controller
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {

    // UserServiceのインスタンスを注入
    private final UserService userService;

    // ユーザーリストを表示するGETリクエスト
    @GetMapping
    public String showList(Model model) {
        // UserServiceを使って全てのユーザー情報を取得し、"userList"という名前でモデルに追加
        model.addAttribute("userList", userService.findAll());
        return "users/list"; // "users/list" テンプレートを返す
    }

    // ユーザー作成フォームを表示するGETリクエスト
    @GetMapping("/creationForm")
    public String showCreationForm(@ModelAttribute UserForm form) {
        return "users/creationForm"; // "users/creationForm" テンプレートを返す
    }

    // ユーザーを作成するPOSTリクエスト
    @PostMapping
    public String create(@Validated UserForm form, BindingResult bindingResult) {
        // 入力の検証エラーがある場合
        if (bindingResult.hasErrors()) {
            // ユーザー作成フォームを再表示
            return showCreationForm(form);
        }

        // UserServiceを使って新しいユーザー情報を作成
        userService.create(form.getUsername(), form.getPassword());

        // ユーザーリストを表示するページにリダイレクト
        return "redirect:/users";
    }
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1