はじめに
今回は,前回に続きタスクの取得、特定のIDのタスクを取得、タスクの新規作成、更新、削除機能を実装していきます。
※動作確認にpgAdminとPostmanを使います。
リポジトリの実装
このコードは、タスク情報を扱うためのリポジトリインターフェースと、そのインターフェースを実装する具体的なリポジトリ構造体を定義しています。package repository
import (
"fmt"
"go-rest-api/model"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type ITaskRepository interface {
//ユーザーのすべてのタスクを取得するメソッドです。
GetAllTasks(tasks *[]model.Task, userId uint) error
// 特定のIDのタスクを取得するメソッドです。
GetTaskById(task *model.Task, userId uint, taskId uint) error
// 新しいタスクを作成するメソッドです。
CreateTask(task *model.Task) error
//タスクを更新するメソッドです。
UpdateTask(task *model.Task, userId uint, taskId uint) error
//タスクを削除するメソッドです。
DeleteTask(userId uint, taskId uint) error
}
type taskRepository struct {
//このフィールドは、データベース接続 (`gorm.DB` オブジェクト) を保持します。
db *gorm.DB
}
func NewTaskRepository(db *gorm.DB) ITaskRepository {
//`taskRepository` インスタンスを作成し、データベース接続を `db` フィールドに設定して返します。
return &taskRepository{db}
}
func (tr *taskRepository) GetAllTasks(tasks *[]model.Task, userId uint) error {
//gorm.DB の Joins、Where、Order、Find、Error メソッドを使って、指定されたユーザーIDのタスクをデータベースから取得します。
//Joins("User"): ユーザーとタスクの関係を定義します。
//Where("user_id=?", userId): ユーザーIDを指定してタスクを絞り込みます。
//Order("created_at"): 作成日時順にソートします。
//Find(tasks): 取得したタスクを tasks スライスに格納します。
if err := tr.db.Joins("User").Where("user_id=?", userId).Order("created_at").Find(tasks).Error; err != nil {
return err
}
return nil
}
func (tr *taskRepository) GetTaskById(task *model.Task, userId uint, taskId uint) error {
//gorm.DB の Joins、Where、First、Errorメソッドを使って、指定されたユーザーIDとタスクIDのタスクをデータベースから取得します。
//First(task, taskId): 取得したタスクをtask構造体に格納します。
if err := tr.db.Joins("User").Where("user_id=?", userId).First(task, taskId).Error; err != nil {
return err
}
return nil
}
func (tr *taskRepository) CreateTask(task *model.Task) error {
//新しいタスクを作成するメソッドの実装です。
//gorm.DBのCreate メソッドを使って、新しいタスクレコードを作成します。
if err := tr.db.Create(task).Error; err != nil {
return err
}
return nil
}
func (tr *taskRepository) UpdateTask(task *model.Task, userId uint, taskId uint) error {
//gorm.DBのModel、Clauses、Where、Update、Error メソッドを使って、指定されたIDとユーザーIDのタスクを更新します
//Model(task): 更新対象のタスクを指定します。
//Clauses(clause.Returning{}): 更新されたレコードの情報を取得します。
//Where("id=? AND user_id=?", taskId, userId): 更新対象のタスクレコードを、taskIdとuserIdで絞り込みます。
//Update("title", task.Title): task 構造体のTitleフィールドの値を、データベースのタスクレコードのtitle列に更新します。
result := tr.db.Model(task).Clauses(clause.Returning{}).Where("id=? AND user_id=?", taskId, userId).Update("title", task.Title)
//if result.Error != nil { return result.Error }: データベース更新処理中にエラーが発生した場合、エラーオブジェクトresult.Errorを返します。
if result.Error != nil {
return result.Error
}
//更新されたレコードがなかった場合、更新対象のレコードが存在しないことを示すエラーオブジェクトを返します。
if result.RowsAffected < 1 {
return fmt.Errorf("object does not exist")
}
return nil
}
func (tr *taskRepository) DeleteTask(userId uint, taskId uint) error {
//データベースからタスクレコードを削除する処理を実行します。
//gorm.DB の Where、Delete、Error メソッドを使って、指定されたIDとユーザーIDのタスクを削除します。
//Where("id=? AND user_id=?", taskId, userId): 削除対象のタスクレコードを、taskIdとuserIdで絞り込みます。
//Delete(&model.Task{}): gorm.DBのDeleteメソッドを使って、指定された条件に合致するタスクレコードを削除します。
result := tr.db.Where("id=? AND user_id=?", taskId, userId).Delete(&model.Task{})
//if result.Error != nil { return result.Error }: データベース削除処理中にエラーが発生した場合、エラーオブジェクト result.Error を返します。
if result.Error != nil {
return result.Error
}
//更新されたレコードがなかった場合、更新対象のレコードが存在しないことを示すエラーオブジェクトを返します。
if result.RowsAffected < 1 {
return fmt.Errorf("object does not exist")
}
return nil
}
ユースケースの実装
次はユースケースを作成していきます。タスクの取得、特定のIDのタスクを取得、タスクの新規作成、更新、削除を行うユースケースを実装したものです。
package usecase
import (
"go-rest-api/model"
"go-rest-api/repository"
)
//タスクユースケースが実装すべきメソッドを定義するインターフェースです。
type ITaskUsecase interface {
//ユーザーのすべてのタスクを取得するメソッドです。
GetAllTasks(userId uint) ([]model.TaskResponse, error)
//特定のIDのタスクを取得するメソッドです。
GetTaskById(userId uint, taskId uint) (model.TaskResponse, error)
//新しいタスクを作成するメソッドです。
CreateTask(task model.Task) (model.TaskResponse, error)
//タスクを更新するメソッドです。
UpdateTask(task model.Task, userId uint, taskId uint) (model.TaskResponse, error)
//タスクを削除するメソッドです。
DeleteTask(userId uint, taskId uint) error
}
//タスクリポジトリへの依存関係を保持するフィールドです。
type taskUsecase struct {
tr repository.ITaskRepository
}
//taskUsecase構造体のインスタンスを生成する関数です。
func NewTaskUsecase(tr repository.ITaskRepository) ITaskUsecase {
return &taskUsecase{tr}
}
func (tu *taskUsecase) GetAllTasks(userId uint) ([]model.TaskResponse, error) {
//tasks := []model.Task{} は、データベースから取得したタスクのリストを格納する model.Task 型のスライスtasksを空で初期化します。
tasks := []model.Task{}
//タスクリポジトリのGetAllTasksメソッドを呼び出して、ユーザーのすべてのタスクを取得します。
//GetAllTasks(&tasks, userId): タスクリポジトリのGetAllTasksメソッドは、データベースからユーザーのすべてのタスクを取得し、tasksスライスに格納します。
if err := tu.tr.GetAllTasks(&tasks, userId); err != nil {
return nil, err
}
//resTasks を空で初期化。
resTasks := []model.TaskResponse{}
//取得したタスクのリストtasksをループ処理し、model.TaskResponse型のオブジェクトに変換します。
for _, v := range tasks {
//model.TaskResponse 型の新しいオブジェクトを作成し、取得したタスクの情報 (v.ID, v.Title, v.CreatedAt, v.UpdatedAt) を設定します。
t := model.TaskResponse{
ID: v.ID,
Title: v.Title,
CreatedAt: v.CreatedAt,
UpdatedAt: v.UpdatedAt,
}
//resTasks = append(resTasks, t) は、変換されたmodel.TaskResponseオブジェクトを resTasks スライスに追加します。
resTasks = append(resTasks, t)
}
//取得したタスクのリストresTasksとエラーオブジェクトnilを返します。
return resTasks, nil
}
func (tu *taskUsecase) GetTaskById(userId uint, taskId uint) (model.TaskResponse, error) {
//データベースから取得したタスクの情報を格納するmodel.Task型の変数taskを空で初期化します。
task := model.Task{}
//タスクリポジトリのGetTaskByIdメソッドを呼び出して、特定のユーザーの特定のタスクを取得します。
//タスクリポジトリのGetTaskByIdメソッドは、データベースから指定されたユーザーIDとタスクIDのタスクを取得し、task変数に格納します。
if err := tu.tr.GetTaskById(&task, userId, taskId); err != nil {
return model.TaskResponse{}, err
}
//model.TaskResponse型の新しいオブジェクトを作成し、取得したタスクの情報 (task.ID, task.Title, task.CreatedAt, task.UpdatedAt) を設定します。
resTask := model.TaskResponse{
ID: task.ID,
Title: task.Title,
CreatedAt: task.CreatedAt,
UpdatedAt: task.UpdatedAt,
}
//取得したタスクの情報を含むmodel.TaskResponseオブジェクトとエラーオブジェクトnilを返します。
return resTask, nil
}
func (tu *taskUsecase) CreateTask(task model.Task) (model.TaskResponse, error) {
//タスクリポジトリのCreateTaskメソッドを呼び出して、新しいタスクを作成します。
//タスクリポジトリのCreateTaskメソッドは、データベースに新しいタスクレコードを作成します。
//タスク作成処理中にエラーが発生した場合、エラーを返します。
if err := tu.tr.CreateTask(&task); err != nil {
return model.TaskResponse{}, err
}
//作成されたタスクの情報を格納するmodel.TaskResponse型の新しいオブジェクトを作成し、作成されたタスクの情報 (task.ID, task.Title, task.CreatedAt, task.UpdatedAt) を設定します。
resTask := model.TaskResponse{
ID: task.ID,
Title: task.Title,
CreatedAt: task.CreatedAt,
UpdatedAt: task.UpdatedAt,
}
/作成されたタスクの情報を含むmodel.TaskResponseオブジェクトとエラーオブジェクトnilを返します。
return resTask, nil
}
func (tu *taskUsecase) UpdateTask(task model.Task, userId uint, taskId uint) (model.TaskResponse, error) {
//タスクリポジトリのUpdateTaskメソッドは、データベースのタスクレコードを更新します。
//タスク更新処理中にエラーが発生した場合、エラーを返します。
if err := tu.tr.UpdateTask(&task, userId, taskId); err != nil {
return model.TaskResponse{}, err
}
//更新されたタスクの情報を格納するmodel.TaskResponse型の新しいオブジェクトを作成し、更新されたタスクの情報 (task.ID, task.Title, task.CreatedAt, task.UpdatedAt) を設定します。
resTask := model.TaskResponse{
ID: task.ID,
Title: task.Title,
CreatedAt: task.CreatedAt,
UpdatedAt: task.UpdatedAt,
}
//更新されたタスクの情報を含むmodel.TaskResponseオブジェクトとエラーオブジェクト nil を返します。
return resTask, nil
}
func (tu *taskUsecase) DeleteTask(userId uint, taskId uint) error {
//eleteTask(userId, taskId): タスクリポジトリのDeleteTaskメソッドは、データベースのタスクレコードを削除します。
//タスク削除処理中にエラーが発生した場合、エラーを返します。
if err := tu.tr.DeleteTask(userId, taskId); err != nil {
return err
}
//エラーが発生しなかった場合、return nilで、エラーオブジェクトnilを返します。これは、正常に処理が完了したことを示します。
return nil
}
コントローラの実装
下記のコードは、タスクの取得、特定のIDのタスクを取得、タスクの新規作成、更新、削除を処理を行うためのコントローラを定義しています。package controller
import (
"go-rest-api/model"
"go-rest-api/usecase"
"net/http"
"strconv"
"github.com/golang-jwt/jwt/v4"
"github.com/labstack/echo/v4"
)
type ITaskController interface {
//ユーザーのすべてのタスクを取得するメソッドです。
GetAllTasks(c echo.Context) error
//特定のIDのタスクを取得するメソッドです。
GetTaskById(c echo.Context) error
//新しいタスクを作成するメソッドです。
CreateTask(c echo.Context) error
//タスクを更新するメソッドです。
UpdateTask(c echo.Context) error
//タスクを削除するメソッドです。
DeleteTask(c echo.Context) error
}
type taskController struct {
//タスクユースケースへの依存関係を保持するフィールドです。
tu usecase.ITaskUsecase
}
//タスクユースケースオブジェクトを受け取り、userController構造体のインスタンスを生成して返します。
func NewTaskController(tu usecase.ITaskUsecase) ITaskController {
return &taskController{tu}
}
func (tc *taskController) GetAllTasks(c echo.Context) error {
//echo.Contextオブジェクトcからuserキーで格納された認証情報を取得します。
user := c.Get("user").(*jwt.Token)
//取得した認証情報userから、jwt.MapClaims型のペイロードデータを取得します。
claims := user.Claims.(jwt.MapClaims)
//ペイロードデータから user_id の値を取得します。
userId := claims["user_id"]
//タスクユースケースの GetAllTasks メソッドは、ユーザーIDを受け取り、そのユーザーのすべてのタスクを[]model.TaskResponse型のリストとして返します。
tasksRes, err := tc.tu.GetAllTasks(uint(userId.(float64)))
//エラーが発生した場合、HTTP ステータスコード 500 (Internal Server Error)と、エラーメッセージをJSON形式で返します。
if err != nil {
return c.JSON(http.StatusInternalServerError, err.Error())
}
//タスクの取得が成功した場合、HTTP ステータスコード 200 (OK) と、取得したタスクのリスト (tasksRes) をJSON形式で返します。
return c.JSON(http.StatusOK, tasksRes)
}
func (tc *taskController) GetTaskById(c echo.Context) error {
//echo.Contextオブジェクトcからuserキーで格納された認証情報を取得します。
user := c.Get("user").(*jwt.Token)
//取得した認証情報userから、jwt.MapClaims型のペイロードデータを取得します。
claims := user.Claims.(jwt.MapClaims)
//ペイロードデータからuser_idの値を取得します。
userId := claims["user_id"]
//リクエストパスからtaskIdパラメータを取得します。これは、echo.ContextのParam メソッドを使って取得します。
id := c.Param("taskId")
//taskIdパラメータを整数型に変換します。
taskId, _ := strconv.Atoi(id)
//タスクユースケースの GetTaskByIdメソッドは、ユーザーIDとタスクIDを受け取り、そのタスクの情報をmodel.TaskResponse型のオブジェクトとして返します。
taskRes, err := tc.tu.GetTaskById(uint(userId.(float64)), uint(taskId))
//タスクの取得処理中にエラーが発生した場合、エラーを返します。
if err != nil {
//エラーが発生した場合、HTTP ステータスコード 500 (Internal Server Error) と、エラーメッセージをJSON形式で返します。
return c.JSON(http.StatusInternalServerError, err.Error)
}
//タスクの取得が成功した場合、HTTP ステータスコード 200 (OK) と、取得したタスクの情報をJSON形式で返します。
return c.JSON(http.StatusOK, taskRes)
}
func (tc *taskController) CreateTask(c echo.Context) error {
//echo.Context オブジェクトcからuserキーで格納された認証情報を取得します。
user := c.Get("user").(*jwt.Token)
//取得した認証情報userから、jwt.MapClaims型のペイロードデータを取得します。
claims := user.Claims.(jwt.MapClaims)
//ペイロードデータからuser_idの値を取得します。
userId := claims["user_id"]
//新しいタスクの情報を格納するmodel.Task構造体を空で作成します。
task := model.Task{}
//c.Bind(&task) は、EchoフレームワークのコンテキストオブジェクトcのBindメソッドを呼び出し、リクエストボディからデータを取得して、task構造体にバインドします。
//バインド処理中にエラーが発生した場合、エラーを返します。この場合、ステータスコード 400 Bad RequestとともにエラーメッセージをJSON形式で返します。
if err := c.Bind(&task); err != nil {
return c.JSON(http.StatusBadRequest, err.Error())
}
// 取得したユーザーIDを、task構造体のUserIdフィールドに設定します。
//タスクユースケースのCreateTaskメソッドは、新しいタスクを作成します。
task.UserId = uint(userId.(float64))
//タスクの作成処理が成功した場合、taskRes変数には、作成されたタスクの情報を格納するmodel.TaskResponse構造体が格納されます。
//タスクの作成処理中にエラーが発生した場合、err変数には、エラーオブジェクトが格納されます。
taskRes, err := tc.tu.CreateTask(task)
//タスクの作成処理中にエラーが発生した場合、HTTPステータスコード 500 (Internal Server Error) を返します。
if err != nil {
return c.JSON(http.StatusInternalServerError, err.Error())
}
//タスクの作成が成功した場合、HTTPステータスコード 201 (Created) と、作成されたタスクの情報をJSON形式で返します。
return c.JSON(http.StatusCreated, taskRes)
}
func (tc *taskController) UpdateTask(c echo.Context) error {
//c.Get("user").(*jwt.Token): echo.Contextオブジェクトcからuserキーで格納された認証情報を取得します。
user := c.Get("user").(*jwt.Token)
//取得した認証情報 user から、jwt.MapClaims型のペイロードデータを取得します。
claims := user.Claims.(jwt.MapClaims)
//ペイロードデータからuser_idの値を取得します。
userId := claims["user_id"]
//リクエストパスからtaskIdパラメータを取得します。これは、echo.ContextのParamメソッドを使って取得します。
id := c.Param("taskId")
//taskId パラメータを整数型に変換します。これは、strconv.Atoi 関数を使って行います。
taskId, _ := strconv.Atoi(id)
//更新するタスクの情報を格納するmodel.Task構造体を空で作成します。
task := model.Task{}
//c.Bind(&task) は、EchoフレームワークのコンテキストオブジェクトcのBindメソッドを呼び出し、リクエストボディからデータを取得して、task構造体にバインドします。
//バインド処理中にエラーが発生した場合、エラーを返します。この場合、ステータスコード 400 Bad Request とともにエラーメッセージをJSON形式で返します。
if err := c.Bind(&task); err != nil {
return c.JSON(http.StatusBadRequest, err.Error())
}
//タスクユースケースの UpdateTask メソッドは、ユーザーID、タスクID、更新するタスク情報を渡して、タスクの更新処理を実行します。
//更新処理が成功した場合、taskRes変数には、更新されたタスクの情報を格納する model.TaskResponse 構造体が格納されます。
//更新処理中にエラーが発生した場合、err 変数には、エラーオブジェクトが格納されます。
taskRes, err := tc.tu.UpdateTask(task, uint(userId.(float64)), uint(taskId))
//更新処理中にエラーが発生した場合、HTTPステータスコード 500 (Internal Server Error) を返します。
if err != nil {
return c.JSON(http.StatusInternalServerError, err.Error())
}
//タスクの更新が成功した場合、HTTP ステータスコード 200 (OK) と、更新されたタスクの情報をJSON形式で返します。
return c.JSON(http.StatusOK, taskRes)
}
func (tc *taskController) DeleteTask(c echo.Context) error {
//echo.Context オブジェクトcからuserキーで格納された認証情報を取得します。
user := c.Get("user").(*jwt.Token)
//取得した認証情報userから、jwt.MapClaims型のペイロードデータを取得します。
claims := user.Claims.(jwt.MapClaims)
//ペイロードデータから user_idの値を取得します。
userId := claims["user_id"]
//リクエストパスからtaskIdパラメータを取得します。
id := c.Param("taskId")
//taskId パラメータを整数型に変換します。
taskId, _ := strconv.Atoi(id)
//タスクユースケースのDeleteTaskメソッドは、ユーザーIDとタスクIDを受け取り、タスクの削除処理を実行します。
//削除処理中にエラーが発生した場合、err変数には、エラーオブジェクトが格納されます。
err := tc.tu.DeleteTask(uint(userId.(float64)), uint(taskId))
//削除処理中にエラーが発生した場合、HTTPステータスコード 500 (Internal Server Error) を返します。
if err != nil {
return c.JSON(http.StatusInternalServerError, err.Error())
}
//タスクの削除が成功した場合、HTTP ステータスコード 204 (No Content) を返します。これは、削除が成功したことを示しますが、レスポンスボディに何も含めないことを意味します。
return c.NoContent(http.StatusNoContent)
}
routerの実装
以前作成したrouterにタスク関連のエンドポイントを追加していきます。
package router
import (
"go-rest-api/controller"
"os"
echojwt "github.com/labstack/echo-jwt/v4"
"github.com/labstack/echo/v4"
)
func NewRouter(uc controller.IUserController, tc controller.ITaskController) *echo.Echo {
e := echo.New()
e.POST("/signup", uc.SignUp)
e.POST("/login", uc.Login)
e.POST("/logout", uc.LogOut)
//echo.Echo オブジェクトeに対して、/tasksというプレフィックスを持つグループを作成します。これにより、/tasksの下に複数のエンドポイントを定義することができます。
t := e.Group("/tasks")
//echo-jwtミドルウェアを使って、tasksグループのすべてのエンドポイントに対して、JWTトークンによる認証を適用します。
//echojwt.Config: echo-jwtミドルウェアの設定オプションを定義します。
t.Use(echojwt.WithConfig(echojwt.Config{
////JWTトークンを署名するために使用される秘密鍵です。環境変数 SECRET から取得されます。
SigningKey: []byte(os.Getenv("SECRET")),
//JWTトークンを取得する場所を指定します。この場合、クッキーのtokenという名前で取得します。
TokenLookup: "cookie:token",
}))
//GETメソッドで/tasksエンドポイントにアクセスしたときに、tc.GetAllTasks関数を呼び出すように設定します。
t.GET("", tc.GetAllTasks)
//GET メソッドで/tasks/:taskId エンドポイントにアクセスしたときに、tc.GetTaskById 関数を呼び出すように設定します。
t.GET("/:taskId", tc.GetTaskById)
///tasksエンドポイントにアクセスしたときに、tc.CreateTask関数を呼び出すように設定します。
t.POST("", tc.CreateTask)
//PUTメソッドで/tasks/:taskIdエンドポイントにアクセスしたときに、tc.UpdateTask 関数を呼び出すように設定します。
t.PUT("/:taskId", tc.UpdateTask)
//DELETEメソッドで/tasks/:taskIdエンドポイントにアクセスしたときに、tc.DeleteTask関数を呼び出すように設定します。
t.DELETE("/:taskId", tc.DeleteTask)
return e
}
mainの実装
以前作成したmain.goにタスクリポジトリ、タスクユースケース、タスクコントローラーを追加していきます。package main
import (
"go-rest-api/controller"
"go-rest-api/db"
"go-rest-api/repository"
"go-rest-api/router"
"go-rest-api/usecase"
)
func main() {
db := db.NewDB()
userRepository := repository.NewUserRepository(db)
//dbを使って、タスクリポジトリの新しいインスタンスを作成します。
taskRepository := repository.NewTaskRepository(db)
userUsecase := usecase.NewUserUsecase(userRepository)
//taskRepositoryを使って、タスクユースケースの新しいインスタンスを作成します。
taskUsecase := usecase.NewTaskUsecase(taskRepository)
userController := controller.NewUserController(userUsecase)
//taskUsecaseを使って、タスクコントローラーの新しいインスタンスを作成します。
taskController := controller.NewTaskController(taskUsecase)
e := router.NewRouter(userController, taskController)
e.Logger.Fatal(e.Start(":8080"))
}
プログラムを起動
下記のコマンドでプログラムを起動していきます。 `GO_ENV=dev go run main.go`次はPostmanを使って動作確認します。
http://localhost:8080/tasks
のエンドポイントにGETメソッドでアクセスします。
タスクのエンドポイントはJWTでプロテクションされているので、JWTトークンがない場合は401 Unauthorized
のエラーが発生します。
JWTトークンを付与するためにログインを行います。
エンドポイントをhttp://localhost:8080/login
に変更してPOSTメソッドでアクセスしていきます。
Bodyのrawを選択し、前回作成したユーザーでログインしていきます。
Cookiesタブを確認するとJWTトークンが出来ます。
JWTトークンが出来たので、再度http://localhost:8080/tasks
のエンドポイントにGETメソッドでアクセスします。
今度はJWTの認証が通って、ステータスがOKで空の配列が返ってきます。
それでは、タスクの新規作成を行ってみたいと思います。
titleがhelloというタスクを作ります。
http://localhost:8080/tasks
に変更してPOSTメソッドでアクセスしていきます。
ステータス201 Createdが返ってきて新しく作成されたタスクのオブジェクトがJSONで返ってきます。
pdAdminでも確認していきます。
DBにも新規作成したタスクが追加されたのを確認できました。
GetTaskByIdでID12のタスクを1つだけ取得していきたいと思います。
まずは、http://localhost:8080/tasks
に変更してPOSTメソッドでアクセスしてもう一つタスクを作成しておきます。
http://localhost:8080/tasks/12
のエンドポイントにGETメソッドでアクセスします。
そうするとIDが12のタスクを1つ取得できました。
それでは、次は更新を試していきたいと思います。
PUTメソッドに変更して、そしてエンドポイントhttp://localhost:8080/tasks/
の末尾に変更したいタスクのIDを追加します。
ここではID12のtitleをupdateに更新していこうと思います。
titleが更新されて、更新した日時も変更されました。
pgAdminを確認するとデータベースの方にも更新内容が反映されました。
次はID12のタスクを削除していきたいと思います。
DELETEメソッドに変更してhttp://localhost:8080/tasks/12
のエンドポイントにアクセスします。
そうすると204 No Contentが返ってきました。
pgAdminを確認するとデータベースの方もIDが12のタスクが削除されているのを確認できました。
(Executeボタンを押下)
そして、POSTメソッドでログアウトのエンドポイントにアクセスすると、Cookieが削除されますので、この状態で、DELETEメソッドhttp://localhost:8080/tasks/11
のエンドポイントにアクセスしても,JWTトークンがありませんということで、401 Unauthorizedが返ってきます。
まとめ
今回はタスクの新規作成、更新、削除機能を実装しました。次回は、バリデーションの機能を実装していきます。