1
0

VSCodeでSpring Bootアプリケーション作成 とDB連携

Last updated at Posted at 2024-03-19

概要

VSCodeでSpring Bootアプリケーション作成と
PostgreSQLに登録されているユーザでログインを行う

全体像

スクリーンショット 2024-03-18 14.48.46.png

前提知識

SpringBoot, Thymeleaf を利用したアプリケーションの基本的な理解

環境情報

  • Java SE 17
  • PostgreSQL 16.2

拡張機能

拡張機能名 備考
Java Extension Pack Java開発のための機能が含まれた一連のパッケージ
Spring Boot Extension Pack Spring Bootアプリケーション開発のための機能が含まれた一連のパッケージ
Maven for Java Mavenプロジェクトの管理用

Spring Boot アプリケーションの作成

  1. VScodeの左下歯車マークを選択し、コマンドパレットを選択
    スクリーンショット 2024-03-17 19.07.12.png

  2. Create a Maven Project を選択
    スクリーンショット 2024-03-17 23.55.06.png

  3. プロジェクトの選択内容

    選択項目 選択内容
    Spring Boot Version 3.2.3
    Project Language Java
    パッケージ名 com.example (任意のパッケージ名)
    プロジェクト名 demo  (任意のプロジェクト名)
    Packaging Type jar
    Java Version 17

  4. 依存関係の追加内容
    下記依存関係を選択したらEnterを押し、任意のフォルダに保存する

    dependencies 備考
    Spring Web 自己完結型の HTTP サーバーを作成できる
    Spring Boot Devtools 再起動なしにソースコードの修正を反映させることができる (無くても問題ないがあると便利)
    Thymeleaf Javaのウェブ開発用テンプレートエンジン
    JDBC API JavaとDBを接続するためのAPI
    PostgreSQL Driver PostgreSQLと通信するためのドライバー

    スクリーンショット 2024-03-18 0.42.22.png

  5. 保存したプロジェクトの確認
    プロジェクトを開き以下のように作成されていればOK
    スクリーンショット 2024-03-18 9.47.29.png

ここで一旦起動したいところですが、DB接続エラーが発生してしまうため
PostgreSQLとの接続情報を追加します

Consider the following:
    If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
    If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

PostgreSQLとの連携

  1. アプリケーションプロファイルの設定
    src/main/resources配下の「application.properties」を「application.yml」にリネームし、以下の内容を記載

    appliation.yml
    spring:
      datasource:
        url: jdbc:postgresql://localhost:5432/test   # 接続先URL
        username: postgres    # ユーザー名
        password: postgres    # パスワード
    

  2. 簡易的なhtmlの作成
    ログインページ「src/main/resources/tmplates/login.html」
    ログイン成功ページ「src/main/resources/tmplates/home.html」

    login.html
    <!DOCTYPE html>
    <html lang="ja" xmlns:th="https://www.thymeleaf.org">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>ログインページ</title>
    </head>
    
    <body>
      <h1>ログイン</h1>
      <div style="color: red;" th:text="${message}"></div>
      <form action="/login" method="post">
        <div>
          <label for="username">ユーザ名</label>
          <input type="text" id="name" name="name" th:value="${name}">
        </div>
        <div>
          <label for="password">パスワード</label>
          <input type="password" id="password" name="password">
        </div>
        <button type="submit">ログイン</button>
      </form>
    </body>
    
    </html>
    
    home.html
    <!DOCTYPE html>
    <html lang="ja" xmlns:th="https://www.thymeleaf.org">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>ログインページ</title>
    </head>
    
    <body>
      <h1>ログイン成功</h1>
    </body>
    
    </html>
    

  3. usersテーブルの作成
    本来であればパスワードは暗号化して格納するべきだが、今回は暗号化処理未実装

    カラム名
    name admin
    password admin
    sql.txt
    -- usersテーブルがあれば削除
    DROP TABLE IF EXISTS users CASCADE;
    
    -- usersテーブル作成
    CREATE TABLE users(
     name varchar(20) PRIMARY KEY
     , password varchar(20) NOT NULL
    );
    
    -- データ挿入
    INSERT INTO users(name, password) VALUES('admin', 'admin');
    

  4. Repositoryの作成
    DBからの情報を取得するためのRepositoryクラスを作成する
    「 src/main/java/com/example/demo/repository/UserRepository.java 」

    • 依存関係で追加したJdbcTemplate(NamedParameterJdbcTemplate)を利用
    • ユーザーが見つかればユーザー情報を、見つからなければ空を返す
    UserRepository.java
    package com.example.demo.repository;
    
    //〜〜〜〜import文は省略〜〜〜〜〜
    
    @Repository
    public class UserRepository {
    
      @Autowired
      private NamedParameterJdbcTemplate jdbcTemplate;
    
      // RowMapperの実装
      private static final RowMapper<User> ROW_MAPPER = (rs, i) -> {
        String name = rs.getString("name");
        String password = rs.getString("password");
        return new User(name, password);
      };
    
      /**
       * ユーザー名とパスワードからユーザーを取得する.
       * 
       * @param name     ユーザー名
       * @param password パスワード
       * @return ユーザー情報、存在しない場合は空のOptional
       */
      public Optional<User> findByUser(String name, String password) {
        SqlParameterSource param = new MapSqlParameterSource().addValue("name", name).addValue("password", password);
        String sql = "SELECT * FROM users WHERE name = :name AND password = :password";
        List<User> userList = jdbcTemplate.query(sql, param, ROW_MAPPER);
        return userList.stream().findFirst();
      }
    }
    

  5. Domainの作成

    User.java
    package com.example.demo.domain;
    
    public record User(String name, String password) {}
    

  6. Serviceの作成

    UserService.java
    package com.example.demo.service;
    
    //〜〜〜〜import文は省略〜〜〜〜〜
    
    @Service
    public class UserService {
    
      @Autowired
      private UserRepository userRepository;
    
      public Optional<User> findByUser(String name, String password) {
        Optional<User> user = userRepository.findByUser(name, password);
        System.out.println(user);
        return user;
      }
    
    }
    
    

  7. Controllerの作成

    LoginController.java
    package com.example.demo.controller;
    
    //〜〜〜〜import文は省略〜〜〜〜〜
    
    @Controller
    @RequestMapping("")
    public class LoginController {
    
      @Autowired
      private UserService userService;
    
      @Autowired
      private HttpSession session;
    
      @GetMapping("")
      public String login() {
        return "/login";
      }
    
      @GetMapping("/login")
      public String loginPage(Model model) {
        return "/login";
      }
    
      /**
       * ログイン処理を行う
       * 
       * @param name     ユーザー名
       * @param password パスワード
       * @param model    モデル
       * @return ログイン成功時は/home、失敗時は/loginに遷移
       */
      @PostMapping("/login")
      public String login(String name, String password, Model model) {
        return userService.findByUser(name, password)
            .map(user -> {
              session.setAttribute("user", user);
              return "/home";
            })
            .orElseGet(() -> {
              model.addAttribute("name", name);
              model.addAttribute("message", "ユーザー名またはパスワードが違います");
              return "/login";
            });
    
      }
    
      @GetMapping("/home")
      public String home() {
        if (session.getAttribute("user") == null) {
          return "redirect:/login";
        }
        return "/home";
      }
    }
        
    

    参考資料

    NamedParameterJdbcTemplate
    SpringBootのO/Rマッパー
    streamインターフェース リファレンス
    Optional リファレンス
    Optional
    recordクラス

1
0
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
1
0