Spring BootとJPAでREST APIを実装する(アプリケーション層編)

[Spring Boot + MySQLでシンプルなWeb REST APIサーバを実装する - Qiita](https://qiita.com/YutaKase6/items/007f6b7d12d342c1330c)

# Outline
以下の設計に従って、アプリケーション層を実装する。
[Spring Boot + MySQLでシンプルなWeb REST APIサーバを実装する - Qiita](https://qiita.com/YutaKase6/items/007f6b7d12d342c1330c)

以下の2クラスを実装する。

```
├── application
│   ├── controller
│   │   └── UserController.java
│   └── resource
│       └── UserBody.java
```

# UserBody.java
ユーザ登録のPOSTリクエスト時のbodyをマッピングするクラス。
バリデーションと、ドメインオブジェクトへの変換処理をもたせる。

```UserBody.java
package com.example.springapi.application.resource;

import com.example.springapi.domain.object.User;
import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

/**
 * リクエストボディのマッピング用クラス
 */
@Data
public class UserBody {

    @NotBlank
    @Size(max = 18)
    private String id;

    @NotBlank
    private String value;

    /**
     * ドメインオブジェクトへ変換
     *
     * @return ドメインオブジェクト
     */
    public User toDomainUser() {
        return User.builder()
                .id(this.id)
                .value(this.value)
                .build();
    }
}
```

# UserController.java

```UserController.java
package com.example.springapi.application.controller;

import com.example.springapi.application.exception.NotFoundException;
import com.example.springapi.application.resource.ErrorResponse;
import com.example.springapi.application.resource.UserBody;
import com.example.springapi.domain.object.User;
import com.example.springapi.domain.service.UserService;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * ユーザ操作のコントローラ
 */
@RestController
@RequiredArgsConstructor
@RequestMapping(path = "/v1/users")
public class UserController {

    @NonNull
    private final UserService userService;

    /**
     * ユーザ検索
     *
     * @param id 検索したいユーザID
     * @return ユーザ
     */
    @GetMapping("{id}")
    @ResponseStatus(HttpStatus.OK)
    public User findById(@PathVariable("id") String id) {
        return this.userService.findById(id).orElseThrow(RuntimeException::new);
    }

    /**
     * ユーザ作成、更新
     *
     * @param userBody リクエストボディ
     * @return 更新後のユーザ
     */
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public User save(@RequestBody @Validated UserBody userBody) {
        return this.userService.save(userBody.toDomainUser());
    }

    /**
     * ユーザ削除
     *
     * @param id 削除したいユーザID
     */
    @DeleteMapping("{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteById(@PathVariable("id") String id) {
            this.userService.deleteById(id);
    }
}

```

## ※ 利用したアノテーション
### @RestController
@Controllerの拡張アノテーション。
@Controllerは@Serviceや@Repository同様、@Compornentのエイリアス。
@RestControllerでは加えて、各メソッドに@ResponseBodyを付与する。

### @ResponseBody
メソッドに付与することで、返り値のjavaオブジェクトをjsonへ変換する。

## @RequestMapping
引数methodに指定したHttpメソッドで、引数pathに指定したパスをメソッドにマッピングするアノテーション。
クラスに付与することで、引数のパスが、クラスに所属するメソッドのベースパスとなる。

### @***Mappring
@RequestMappingの拡張アノテーション。
methodを省略できるアノテーション。

### @ResponseStatus
ステータスコードを指定できるアノテーション。

### @PathVariable
パスパラメータを引数にマッピングするアノテーション。

### @RequestBody
リクエストのbodyを引数にマッピングするアノテーション。

### @Validated
@RequestBodyと同時に付与することで、マッピングされたクラスに付与されているバリデーションアノテーションを有効化するアノテーション。