LoginSignup
6
6

More than 3 years have passed since last update.

【初心者】SpringBootでTodoアプリのREST APIを書いてみる

Last updated at Posted at 2019-09-25

追記

  • Controllerのコードの一部が切れていたので修正
  • Controllerのアノテーション周りの話が抜けていたので追記

内容

  • Java初心者が夏休み中にSpringの勉強をする
  • Spring Frameworkはハードルが高そうだったので一先ずSpringBootから
  • お題は初心者がよくやるTodoアプリのREST API

詳しく触れないこと

  • gradle周辺
  • Database周辺
    • JPA
    • H2 Database

本編

  • 開発はIntelliJ IDEAを使用
    • ビルドとかアプリケーションの起動はお任せ

雛形作成

  • https://start.spring.io/ で作成
    • Project: Gradle Project
    • Language: Java
    • Spring Boot: 2.1.8
    • Project Metadaba:
      • Group: com.example
      • Artifact: todoapp
      • Options: そのまま
    • Dependencies:
      • Spring Web
      • Spring Data JPA
      • H2 Database
      • Lombok
  • ダウンロードされたzipファイルをunzipしてIntelliJでopenしたところから開始

パッケージ構成

  • com.example.todoapp直下に以下を並べる
    • controllers
    • repositories
    • models
  • servicesとかもあるべきかもしれないけど今回は割愛

コード

models

  • Task.java
package com.example.todoapp.models;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Data
@Entity
public class Task {

    @Id
    @GeneratedValue
    private Long id;
    private String summary;
    private Boolean done = false;

    public Task(){}
}

  • 各アノテーションについて
    • @Data
      • 各フィールドのsetterとgetterを定義してくれる
      • toString()メソッドやhashCode()メソッドを定義してくれる
    • @Entity
      • エンティティであることを示す。
      • このクラスのフィールドを持つテーブルがDBに作られる
    • @Id
      • エンティティの主キーのフィールドを指定する
    • @GeneratedValue
      • 主キーの値の生成方法を指定する
      • strategygeneratorを指定して挙動を変えられそう(試してない)

repositories

  • TaskRepository.java
package com.example.todoapp.repositories;

import com.example.todoapp.models.Task;
import org.springframework.data.jpa.repository.JpaRepository;

public interface TaskRepository extends JpaRepository<Task, Long> {
}
  • JpaRepositoryを継承したinterfaceを定義
    • JpaRepositoryの祖先にいるCrudRepositoryインターフェースがfindByIdなどのインターフェースを定義している
    • 実装はSimpleJpaRepositoryなのかな?
  • JpaRepositoryは対象のエンティティクラスとその主キーの型を指定する
    • ここで指定した主キーの型は、findByIddeleteByIdの引数の型として使われる
    • 今回作成したTaskエンティティの主キーはLong型なのでここではLongを指定

controllers

  • ApiController.java
package com.example.todoapp.controllers;

import com.example.todoapp.models.Task;
import com.example.todoapp.repositories.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

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

@RestController
@RequestMapping(value = "/api")
public class ApiController {

    @Autowired
    TaskRepository taskrepo;

    @GetMapping(value = "/todos")
    public List<Task> tasklist(){
        return taskrepo.findAll();
    }

    @GetMapping(value = "todo/{id}")
    public Optional<Task> retrieve(@PathVariable Long id){
        return taskrepo.findById(id);
    }

    @PostMapping(value = "/todo")
    public ResponseEntity<Task> newTask(@RequestBody Task task){
        Task result = taskrepo.save(task);
        return new ResponseEntity<Task> (result, HttpStatus.CREATED);
    }

    @PutMapping(value = "/todo/{id}")
    public Task update(@PathVariable Long id, @RequestBody Task task){
        task.setId(id);
        return taskrepo.save(task);
    }

    @DeleteMapping(value = "/todo/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void delete(@PathVariable Long id){
        taskrepo.deleteById(id);
    }
}
  • 各アノテーションについて
    • @RestController
      • 各メソッドの戻り値がそのままレスポンスボディになる
      • @Controllerを使う場合、メソッドの戻り値はStringにしてテンプレートに埋め込む形で使うらしい
    • @RequestMapping
      • このコントローラが受け付けるリクエストのパスやメソッドやクエリパラメータを指定できる
    • @Autowired
      • @Componentアノテーションをつけて登録されているBeanとの紐付けを行う
      • @Repository@Serviceをつけたクラスも、内部では@Componentが付加されている
      • ここではTaskRepositoryインターフェースを満たすクラスが自動的にtaskrepoに格納される
    • @GetMapping, @PostMapping, @PutMapping, @DeleteMapping
      • @RequestMappingのメソッドを固定したもの
      • @GetMappingの場合、@RequestMapping(method=RequestMethod.GET)と同等
    • @ResponseStatus
      • デフォルトのステータスコードを指定する
      • 200以外を返したい時に使う?

動作確認

新規登録

$ curl http://localhost:8080/api/todo -XPOST -H 'Content-Type: application/json' -d '{"summary": "my first task"}' | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    75    0    47  100    28    170    101 --:--:-- --:--:-- --:--:--   170
{
  "id": 1,
  "summary": "my first task",
  "done": false
}

リスト取得

$ curl http://localhost:8080/api/todos | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    49    0    49    0     0    285      0 --:--:-- --:--:-- --:--:--   286
[
  {
    "id": 1,
    "summary": "my first task",
    "done": false
  }
]

1件取得

$ curl http://localhost:8080/api/todo/1 | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    47    0    47    0     0   2045      0 --:--:-- --:--:-- --:--:--  2136
{
  "id": 1,
  "summary": "my first task",
  "done": false
}

更新

$ curl http://localhost:8080/api/todo/1 -XPUT -H 'Content-Type: application/json' -d '{"summary": "updated my task", "done": true}' | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    92    0    48  100    44   2632   2412 --:--:-- --:--:-- --:--:--  2666
{
  "id": 1,
  "summary": "updated my task",
  "done": true
}

削除(レスポンスボディがないのでStatusCodeで確認)

$ curl http://localhost:8080/api/todo/1 -XDELETE -v
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> DELETE /api/todo/1 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 204
< Date: Wed, 25 Sep 2019 15:29:37 GMT
<
* Connection #0 to host localhost left intact

まとめ

  • 動かしたいもの自体はめっちゃ簡単に動かせた
  • アノテーション種類多すぎて何使えばいいのかわからん
    • とりあえず今回使ったものくらいは最低限おさえておきたい
    • あとは何かするときに都度調べられればよさそう
6
6
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
6
6