「はじめての Django アプリ作成」をSpring WebFluxでやってみた、その 1

# はじめに
この記事はDjangoの公式チュートリアル[「はじめての Django アプリ作成」](https://docs.djangoproject.com/ja/4.0/intro/tutorial01/)と同じものをSpring WebFluxで作成することでDjangoとSpring WebFluxの違いを理解することを目的としています。

# 違い一覧
DjangoとSpringでは同じコンセプトでも用語が結構違います。

|Django|Spring|
|:-----------|:------------|
|Model(モデル)|Model(モデル)|
|Template(テンプレート)|View(ビュー)|
|View(ビュー)|Controller(コントローラ)|

# はじめてのアプリ作成、その 1

## プロジェクトを作成する

### Django
Djangoでは`django-admin`を使ってプロジェクトを作成できます。

```bash
django-admin startproject mysite
```

### Spring WebFlux
Springでは[Spring Initializr](https://start.spring.io/)を使ってプロジェクトを作成できます。Spring Initializrの場合はプロジェクト名以外のいくつかの設定を与えることができます。
今回はSpring WebFluxを使うため、dependenciesに`Spring Reactive Web`を追加します。

![fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286572/b5287138-8a98-8457-dd24-e395d09c9285.png)

下の`GENERATE`を押すとプロジェクトをzipファイルでダウンロードできます。

## サーバーを立ち上げる
Djangoの`runserver`の場合、ただの開発用サーバーに過ぎませんがgradleを使ってWebFluxのサーバーを立ち上げるとNettyという実際のプロダクション環境で使えるサーバーが立ち上がります。ログで確認できるように両方ともデフォルトで`8080`ポートを使います。

### Django

```bash
python manage.py runserver
```

### Spring WebFlux

```bash
./gradlew bootRun
```

## Polls アプリケーションをつくる

### Django
Djangoでは`manage.py`を使ってアプリケーションを作成できます。

```bash
python manage.py startapp polls
```

### Spring WebFlux
Spring WebFluxでは`startapp`のような機能はありません。`mysite/src/main/java/com/example/mysite`の中に`polls`というディレクトリーを直接作ります。

```bash
cd mysite
mkdir -p src/main/java/com/example/mysite/polls
```

## はじめてのビュー作成
Djangoでのビューを意味するものでSpringではコントローラに該当します。
"Hello, world. You're at the polls index."というHTTPレスポンスは返すコントローラを作ります。

### Django
Djangoでは`views.py`でファンクションを定義し、Rootからpollsアプリ、pollsアプリからviewに向かうパスを繋げます。

まず、`HttpResponse`を返す`index(request)`を定義し、

```python:polls/views.py
from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
```
`polls`アプリの`''`URLに`index(request)`を紐づけます。

```python:polls/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
]
```
あとプロジェクトルートから`polls/`に`polls`アプリを紐づけます。

```python:mysite/urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
    path('admin/', admin.site.urls),
]
```

### Spring WebFlux
先に作った`mysite/src/main/java/com/example/mysite/polls`に`MyController.java`というJavaクラスファイルを生成します。

```bash
cd mysite
touch src/main/java/com/example/mysite/polls/MyController.java
```

`MyController.java`の中身は以下のようになります。

```java:MyController.java
package com.example.mysite.polls;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("polls")
public class MyController {

    @GetMapping(value = "")
    Mono<ResponseEntity<String>> index() {
        return Mono.just(ResponseEntity.status(HttpStatus.OK)
                         .body("Hello, world. You're at the polls index.")
        );
    }
}
```

* `@RestController` : Springに`MyController`クラスをアプリとして登録するような効果を持ちます。
* `@RequestMapping("polls")` : `mysite/urls.py`に`polls`アプリを登録するような効果を持ちます。クラスの中のURLマッピングは`polls/`URLをベースに持つようになります。
* `@GetMapping(value = "")` : Djangoで`index(request)`を`polls/urls.py`に登録するような効果を持ちます。`value = ""`なので`http://127.0.0.1:8080/polls`で接続すると`index()`が呼ばれます。
* `Mono<ResponseEntity<String>>` : Spring WebFluxで使うオブジェクトの箱のようなものです。`0..1`個のオブジェクトを入れることができます。`Mono.just()`関数でMonoのオブジェクトを生成できます。
* `ResponseEntity.status(HttpStatus.OK).body("Hello, world. You're at the polls index.")` : Djangoの`HttpResponse("Hello, world. You're at the polls index.")`に該当します。