第3回

REST API

ToDo管理アプリにWeb-APIを実装する

やりたいこと

API仕様

操作API呼び出し戻り値
ToDo作成POST /api/{uid}/todos {"title": "タイトル"}作成されたToDoオブジェクト
ToDo取得GET /api/{uid}/todos/{seq}指定したToDoオブジェクト
ToDo取得GET /api/{uid}/todosそのユーザのToDoリスト
ToDo取得GET /api/{uid}/donesそのユーザのDoneリスト
ToDo更新PUT /api/{uid}/todos/{seq}/done完了したToDoオブジェクト
ToDo更新PUT /api/{uid}/todos/{seq} {"title":"変更するタイトル"}更新されたToDoオブジェクト
ToDo削除DELETE /api/{uid}/todos/{seq}true

RESTController - RESTコントローラ

package jp.ac.kobe_u.cs.itspecialist.todoapp.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import jp.ac.kobe_u.cs.itspecialist.todoapp.dto.ToDoForm;
import jp.ac.kobe_u.cs.itspecialist.todoapp.entity.ToDo;
import jp.ac.kobe_u.cs.itspecialist.todoapp.exception.ToDoAppException;
import jp.ac.kobe_u.cs.itspecialist.todoapp.service.MemberService;
import jp.ac.kobe_u.cs.itspecialist.todoapp.service.ToDoService;

/**
 * ToDoの操作,CRUDを行うAPI
 */
@RestController
@RequestMapping("/api")
public class ToDoRestController {
    @Autowired
    ToDoService todoService;
    @Autowired
    MemberService memberService;

    /* --- C: ToDoを作成する --- */
    @PostMapping("/{mid}/todos")
    ToDo createToDo(@PathVariable String mid, @Validated @RequestBody ToDoForm form) {
        return todoService.createToDo(mid, form);
    }

    /* --- R: ToDoを取得する (1件) --- */
    @GetMapping("/{mid}/todos/{seq}")
    ToDo getToDoList(@PathVariable String mid, @PathVariable Long seq) {
        return todoService.getToDo(seq);
    }

    /* --- R: ToDoを取得する (リスト) --- */
    @GetMapping("/{mid}/todos")
    List<ToDo> getToDoList(@PathVariable String mid) {
        return todoService.getToDoList(mid);
    }

    /* --- R: Doneを取得する (リスト) --- */
    @GetMapping("/{mid}/dones")
    List<ToDo> getDoneList(@PathVariable String mid) {
        return todoService.getDoneList(mid);
    }

    /* --- U: ToDoを完了する --- */
    @PutMapping("/{mid}/todos/{seq}/done")
    ToDo done(@PathVariable String mid, @PathVariable Long seq) {
        return todoService.done(mid, seq);
    }

    /* --- U: ToDoを更新する --- */
    @PutMapping("/{mid}/todos/{seq}")
    ToDo updateToDo(@PathVariable String mid, @PathVariable Long seq, @Validated @RequestBody ToDoForm form) {
        return todoService.updateToDo(mid, seq, form);
    }

    /* --- D: ToDoを削除する --- */
    @DeleteMapping("/{mid}/todos/{seq}")
    boolean deleteToDo(@PathVariable String mid, @PathVariable Long seq) {
        todoService.deleteToDo(mid, seq);
        return true;
    }

    /*--------------------- エラーハンドラー -----------------------------*/
    /*
     * 本当は@RestControllerAdviceにまとめて書きたいが,@ControllerAdviceと競合するので,
     * Controllerに書いている.
     */
    @ExceptionHandler(ToDoAppException.class)
    public ResponseEntity<Object> handleToDoException(ToDoAppException ex) {
        HttpStatus status;
        switch (ex.getCode()) {
            // 存在しない系例外
            case ToDoAppException.NO_SUCH_MEMBER_EXISTS:
            case ToDoAppException.NO_SUCH_TODO_EXISTS:
                status = HttpStatus.NOT_FOUND;
                break;
            // パラメタ異常系例外
            case ToDoAppException.MEMBER_ALREADY_EXISTS:
            case ToDoAppException.INVALID_MEMBER_INFO:
            case ToDoAppException.INVALID_TODO_INFO:
                status = HttpStatus.BAD_REQUEST;
                break;
            // 認可失敗系例外
            case ToDoAppException.INVALID_MEMBER_OPERATION:
            case ToDoAppException.INVALID_TODO_OPERATION:
                status = HttpStatus.FORBIDDEN;
                break;
            default:
                status = HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return new ResponseEntity<>(ex, status);
    }

    /* -- バリデーション失敗 -- */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex) {
        return new ResponseEntity<>(ex, HttpStatus.BAD_REQUEST);
    }

    /* -- その他の例外 -- */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<Object> handleException(Exception ex) {
        return new ResponseEntity<>(ex, HttpStatus.BAD_REQUEST);
    }

}

解説

POSTMANで試す

ToDoの取得

GETでエンドポイントにリクエストする

ToDoの作成

POSTでエンドポイントにリクエストする

ToDoの更新

自分で試してみよう

ToDoの削除

自分で試してみよう


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS