iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 17
1
Modern Web

站在Web前端人員角度,學習 Spring Boot 後端開發系列 第 17

Day 17 - Spring Boot Todo List RESTful API 實作

  • 分享至 

  • xImage
  •  

生活的秘訣,就是把自己放在適合的光線下。有些人需要百老匯的聚光燈,而有些人只需要一張被小檯燈照亮的桌子。 -- 蘇珊.坎恩 《安靜就是力量》

之前我們利用 Java thymeleaf 模版引擎完成Todo List,是屬於後端渲染(Server-Side Render)到前端 HTML CSS ,而接下來因為想與大家介紹前後端分離與RESTful API,今天要來實作Todo List的 RESTFul API 讓其他軟體(App, Web)介接。

API 端點為

  • [GET] /api/todos 取得所有代辦事項
  • [POST] /api/todos 新增一筆代辦事項
  • [PUT] /api/todos/{id} 修改代辦事項
  • [DELETE] /api/todos/{id} 刪除代辦事項

採取三層式架構

介面層(Controller) 接收前端請求

業務邏輯層(Service):根據請求做資料處理或是處理從DAO回來的資料。

資料訪問層(Dao):對資料庫做增修查改等操作。

之前建立的ToDo Entity

package com.caili.todolist.model.entity;

import lombok.Data;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

import javax.persistence.*;
import java.util.Date;

/**
 * @author cai-li
 */
@Entity
@Table
@Data
public class Todo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer id;

    @Column
    String task = "";

    @Column(insertable = false, columnDefinition = "int default 1")
    Integer status = 1;

    @CreatedDate
    @Column(updatable = false, nullable = false)
    Date createTime = new Date();

    @LastModifiedDate
    @Column(nullable = false)
    Date updateTime = new Date();
}

Dao 層


import com.caili.todolist.model.entity.Todo;
import org.springframework.data.repository.CrudRepository;

public interface TodoDao extends CrudRepository<Todo, Integer> {
}

Service 層

分別實作getTodos()createTodo()updateTodo()deleteTodo() 方法。

getTodos() 純粹透過todoDao取得資料庫的所有代辦事項。

createTodo() 透過todoDao將資料儲存至資料庫,並回傳id。

updateTodo() 一開始會透過findById()判斷id 是否存在資料庫,也會判斷傳進來的值否有無status 這個key,若沒有就會直接回傳false ,再來就會經由todoDao將資料更新至資料庫

deleteTodo() 一開始會透過findById()判斷id 是否存在資料庫,若不存在直接回傳false,再來就會經由todoDao將資料從資料庫中刪除。

package com.caili.todolist.service;

import com.caili.todolist.model.dao.TodoDao;
import com.caili.todolist.model.entity.Todo;
import org.hibernate.service.spi.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Optional;

@Service
public class TodoService {
    @Autowired
    TodoDao todoDao;

    public Iterable<Todo> getTodos() {
        return todoDao.findAll();
    }

    public Integer createTodo(Todo todo) {
        Todo rltTodo = todoDao.save(todo);
        return rltTodo.getId();
    }

    public Boolean updateTodo(Integer id,Todo todo) {
            Optional<Todo> isExistTodo = findById(id);
            if (! isExistTodo.isPresent()) {
                return false;
            }
            Todo newTodo = isExistTodo.get();
            if (todo.getStatus() == null) {
                return false;
            }
            newTodo.setStatus(todo.getStatus());
            todoDao.save(newTodo);
            return true;
    }

    public Optional<Todo> findById(Integer id) {
        Optional<Todo> todo = todoDao.findById(id);
        return todo;
    }

    public Boolean deleteTodo(Integer id) {
            Optional<Todo> findTodo = findById(id);
            if (!findTodo.isPresent()) {
                return false;
            }
            todoDao.deleteById(id);
            return true;
    }
}

Controller層

Controller 一開始會用@RestController Annotation來直接回傳json,並用@RequestMapping("/api") 定義此API的父路徑,也就是說我們呼叫API要/api/xxxx 的呼叫。

Controller實作了CRUD的API呼叫,分別為GET/api/todosPOST/api/todosPUT/api/todos/{id}DELETE /api/todos/{id} 請求,這裡去透過service來操作資料的處理,並回傳相對應的結果。

我們可以使用ResponseEntity 這個類別操作靜態方法status(HttpStatus status) 來設定回傳的status code,與靜態方法body() 來設定要回傳的response body。可以參考Class ResponseEntity 的文件。

GET/api/todos 取得所有資料回傳status code 200 (OK)與所有資料集。

POST/api/todos 建立待辦事項資料,並回傳status code 201(Created),並回傳id。

PUT/api/todos/{id} 修改代辦事項的狀態,成功的話回傳status code 200(OK),失敗則回傳status code 400(Bad Request)

DELETE /api/todos/{id} 刪除待辦事項,成功刪除回傳status code 204(No Content),失敗則回傳status code 400(Bad Request)

package com.caili.todolist.controller;

import com.caili.todolist.model.entity.Todo;
import com.caili.todolist.service.TodoService;
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.Optional;

@RestController
@RequestMapping("/api")
public class TodoController {
    @Autowired
    TodoService todoService;

    @GetMapping("/todos")
    public ResponseEntity getTodos() {
        Iterable<Todo> todoList = todoService.getTodos();
        return ResponseEntity.status(HttpStatus.OK).body(todoList);
    }

    @GetMapping("/todos/{id}")
    public Optional<Todo> getTodo(@PathVariable Integer id) {
        Optional<Todo> todo = todoService.findById(id);
        return todo;
    }

    @PostMapping("/todos")
    public ResponseEntity createTodo(@RequestBody Todo todo) {
        Integer rlt = todoService.createTodo(todo);
        return ResponseEntity.status(HttpStatus.CREATED).body(rlt);
    }

    @PutMapping("/todos/{id}")
    public ResponseEntity upadteTodo(@PathVariable Integer id, @RequestBody Todo todo) {
        Boolean rlt = todoService.updateTodo(id ,todo);
        if (!rlt) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Status 欄位不能為空");
        }
        return ResponseEntity.status(HttpStatus.OK).body("");
    }

    @DeleteMapping("/todos/{id}")
    public ResponseEntity deleteTodo(@PathVariable Integer id) {
        Boolean rlt = todoService.deleteTodo(id);
        if (!rlt) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Id 不存在");
        }
        return ResponseEntity.status(HttpStatus.NO_CONTENT).body("");
    }
}

最後我們使用Postman 來測試API是否成功,Postman 可以用來模擬HTTP request 的工具,快速測試你的api是否運作成功,正常的請求資料。

GET /todost 查詢代辦事項列表
https://ithelp.ithome.com.tw/upload/images/20200926/20118857DQ5jaALI4R.png
POST /todos 新增代辦事項
https://ithelp.ithome.com.tw/upload/images/20200926/201188573HkZcWPYGS.png
PUT /todos/{id} 修改代辦事項狀態
https://ithelp.ithome.com.tw/upload/images/20200926/20118857jtw7PpgFUP.png
DELETE /todos/{id} 刪除代辦事項
https://ithelp.ithome.com.tw/upload/images/20200926/201188578BTZCkmTiK.png


上一篇
Day 16 - Spring Boot 決定就是 RESTful API 了
下一篇
Day 18 - Spring Boot 單元測試 Service層使用Mockito
系列文
站在Web前端人員角度,學習 Spring Boot 後端開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言