Spring bootで簡単なWebアプリを作ってみる(プロジェクト作成)

こんにちは。船井総研デジタルのいっちーです。

前回の記事では、Docker環境を構築して、疎通確認をするところまで行いました。

https://qiita.com/fsd_itchy/items/368d0424ba4de12eed61

今回は、プロジェクトの初期構築を行っていきたいと思います。

# Spring Initializrでプロジェクトのスケルトンを作る

[Spring Snitializr](https://start.spring.io/)にアクセスして、プロジェクトの初期設定を入力します。今回は、下記のような入力内容で良いでしょう。

![プロジェクト初期化.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3280429/2e3ee48f-7e9f-9ec2-f5ef-77709d81c9b1.png)

| 入力項目 | 入力値 | 備考 |
| ---- | ---- | ---- |
| Project | Maven | - |
| Language | Java | - |
| Spring Boot | 3.0.5 (SNAPSHOT) | Dependenciesの項でMyBatisを選択する際に「3.1.0(M1)以前のバージョン」を要求されるので、こちらを使います。 |
| Project Metadata | Packagingは「War」、Javaは「19」あとはお好みで | - |
| Dependencies | 「Lombok」「Thymeleaf」「Spring Web」「MySQL Driver」「MyBatis Framework」の5つを選択 | 必要に応じて、追加していくかも知れません。 |

入力が終わったら、「GENERATE」を押下すると、プロジェクトのスケルトンがzipファイルでダウンロードできます。

ダウンロードしたzipファイルを、`C:\work\negitter\app`配下に展開します。

![プロジェクト展開.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3280429/467b8134-af5a-afe5-72bf-5ad5f373dd88.png)

VSCodeからも見てみましょう。

![展開確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3280429/93b751ec-db70-4595-8e8a-bfb164f1dedf.png)

これで、VSCodeでプロジェクトを作成する準備が整いました。

# 画面モックアップを追加する

## モックアップの追加と調整

`src\main\resources\static`配下に、要件定義のときに作成した画面のモックアップを格納します。ついでに、良い感じの背景画像、CSS、Javascriptのスケルトンも追加しておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3280429/120e141b-d845-42d3-aa20-61ffa68f4d43.png)


<details><summary>メイン画面</summary>

```html:src/main/resources/templates/negitter.html
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <link href="../static/css/negitter.css" rel="stylesheet">
    <link rel="icon" href="../static/img/favicon.ico" />
    <script type="text/javascript" src="../static/js/negitter.js"></script>
    <title>Negitter</title>
</head>

<body style="padding-top: 50px; padding-bottom: 50px;">
    <nav class="navbar navbar-expand-lg navbar-light fixed-top" style=" background: #2ce45a;">
        <div class="container">
            <a class="navbar-brand" href="#"><span>Negitter</span></a>
            <a id="registerNegiBtn" class="btn btn-light" href="#">ねぎを登録</a>
        </div>
    </nav>
    <div class="container">
        <!-- posted message start -->
        <div class="row mt-3">
            <div class="col">
                <h6>○○○○さん</h6>
            </div>
            <div class="col">
                <span class="text-right">投稿日時: 2023年01月01日 00時00分00秒</span>
            </div>
        </div>
        <div class="row mt-3">
            <div class="col">
                ○○ねぎって美味しいね！
            </div>
        </div>
        <hr>
        <!-- posted message end -->
    </div>

    <div class="container">
        <div class="row mt-3 justfy-content-between">
            <div class="col-3 text-start">
                <a class="btn btn-light">前のページへ</a>
            </div>
            <div class="col-3"><!-- nothing --></div>
            <div class="col-3 text-end">
                <a class="btn btn-light">次のページへ</a>
            </div>
        </div>
        <hr>
    </div>

    <form method="POST" action="#">
        <div class="container">
            <p class="alert alert-danger">ねぎでつぶやいてください！</p>
            <div class="row mt-3">
                <div class="col">
                    おなまえ: <input type="text" name="username" class="form-control" placeholder="おなまえ"
                        required="required">
                </div>
            </div>
            <div class="row mt-3">
                <div class="col">
                    メッセージ: <input type="text" name="message" class="form-control" placeholder="メッセージ"
                        required="required"><br>
                </div>
            </div>
            <div class="row">
                <div class="col">
                    <button type="submit" class="btn btn-primary btn-block">つぶやく</button>
                </div>
            </div>
        </div>
        </div>
    </form>

    <div class="container fixed-bottom">
        <p style="text-align: center; background: #2ce45a;">&copy; 2023 fsd_itchy </p>
    </div>
</body>

</html>
```

</details>

<details><summary>ねぎ登録画面</summary>

```html:src/main/resources/templates/register.html
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <link href="../static/css/negitter.css" rel="stylesheet">
    <link rel="icon" href="../static/img/favicon.ico" />
    <script type="text/javascript" src="../static/js/negitter.js"></script>
    <title>Negitter</title>
</head>

<body style="padding-top: 50px; padding-bottom: 50px;">
    <nav class="navbar navbar-expand-lg navbar-light fixed-top" style=" background: #2ce45a;">
        <div class="container">
            <a class="navbar-brand" href="#"><span>Negitter</span></a>
            <a id="backToNegiitsBtn" class="btn btn-light" href="#">戻る</a>
        </div>
    </nav>
    <form method="POST" action="#">
        <div class="container">
            <div class="row mt-3">
                <div class="col">
                    <h3>ねぎを登録する</h3>
                </div>
            </div>
            <p class="alert alert-danger">そのねぎは登録済みです！</p>
            <div class="row mt-3">
                <div class="col">
                    <input type="text" name="neginame" placeholder="○○ねぎ" required maxlength="128" size="110">
                </div>
                <div class="col"></div>
                <div class="col">
                    <button type="submit" class="btn btn-primary btn-block">登録</button>
                </div>
            </div>
        </div>
        </div>
    </form>
    <form method="POST" action="#">
        <div class="container">
            <div class="row mt-3">
                <div class="col">
                    <h3>登録済みねぎ一覧</h3>
                </div>
            </div>
            <div class="row mt-3">
                <table class="table table-light table-striped table-borderd table-condensed">
                    <tr>
                        <th>
                            No
                        </th>
                        <th>
                            名称
                        </th>
                        <th>
                            編集
                        </th>
                    </tr>
                    <!-- negi info start -->
                    <tr>
                        <td>
                            1
                        </td>
                        <td>
                            <input type="text" id="negi" name="negi" required maxlength="128" size="100" value="○○ねぎ">
                        </td>
                        <td>
                            <a class="btn btn-warning">修正</a>
                            <a class="btn btn-secondary">削除</a>
                        </td>
                    </tr>
                    <!-- negi info end -->
                </table>
            </div>
        </div>
    </form>

    <div class="container fixed-bottom">
        <p style="text-align: center; background: #2ce45a;">&copy; 2023 fsd_itchy </p>
    </div>
</body>

</html>
```

</details>

<details><summary>CSS</summary>

```css:src/main/resources/static/css/negitter.css
body {
    background: #FFF url(../img/parts/bg.png) fixed ;
};
```

</details>

<details><summary>JS</summary>

```css:src/main/resources/static/js/negitter.js
// nothing
```

::: note info
まだ何も書いてないので、「nothing」とコメントしています。
:::

</details>

モックアップ作成時には繰り返し項目をベタ書きしていましたが、今後はプログラムから繰り返し項目を作ることになるため、ここで削除しておきます。

::: note warn
最初の記事で作ったモックアップからちょこちょこ変えていますが、本来であれば画面設計はモックアップの段階でクライアントの合意を取るため、あとから変えるには再度クライアントとの調整が必要になったり、色々と面倒なことになると思います。
あくまで個人学習のための開発、ということでお読みいただければ幸いです。
:::

## モックアップの表示確認

ブラウザでモックアップを表示して、正しく表示されるか確認します。

### メイン画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3280429/619f366e-ace9-d92f-90a0-e900d8c4b411.png)

### ねぎ登録画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3280429/1ff0b031-7130-17bb-1ec2-4d4ad749824b.png)


:::note info
この素敵な背景画像は、船井総研デジタルの同僚@fsd-jume氏より提供いただきました。@fsd-jume氏は、Microsoft Azureに関する記事を多数執筆しています。氏の記事もどうぞご覧ください。
:::

# まとめ
今回の記事では、プロジェクトのスケルトンを作成し、画面のモックアップを追加しました。次回は、このモックアップに画面遷移を組み込んでいこうと思います。

# おまけ
Spring Initializr、ずっとSpring Initiali**zer**かと思ってましたが、よく見るとInitiali**zr**なんですね。気になったのでChatGPT先生に聞いてみました。

![initializr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3280429/56114535-709d-1411-f64a-9d691578e845.png)


…ほんまかいな？

それではまた。