こんにちは。今回はJavaでTODOアプリの投稿機能の部分をやってみたいと思います。
ちなみに今回はバリデーションについては触れませんでしたが、後の記事で登場するので正常処理だけのやり方を紹介します。
TODOアプリ作成リンク集
1: MVCの簡単な説明
2: Spring Initializrで雛形を作ってHello worldしたい
3: MySQLに仮のデータを保存 -> 全取得 -> topに表示する
4: 投稿機能の実装 (今ここ)
TodoFormクラスを作成する
まずはユーザーがTODOを登録する際のデータの入れ物を用意したいと思います。今回はそれをTodoFormクラスに実装していきたいと思います。
クラスを作る階層はTodoContorollerと同じで良いかと思います。
@Data
public class TodoForm {
private long Id;
@NotNull
@Size(min = 1, max =30)
private String title;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate deadline;
private boolean status;
}
↑こんな感じで良いでしょう。
アノテーションが使えない場合は・・・
Spring2.3から仕様が変わったみたいでvalidation系のアノテーションを使う為には手動で追加してやる必要があります。
dependencies {
compile group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'
}
dependenciesに上記を追加すれば@Sizeとかが使える様になります!
TodoServiceにTODOを保存するロジックを追加する
お次はServiceの編集になります。
@Service
@RequiredArgsConstructor
public class TodoService {
private final TodoRepository todoRepository;
// 〜略〜
public void setTodo(TodoForm formData) {
TodoEntity todo = new TodoEntity();
todo.setTitle(formData.getTitle());
todo.setDeadline(formData.getDeadline());
todoRepository.save(todo);
}
}
今回は登録するだけなので戻り値はvoidにしています。
引数で渡ってきたTodoForm型のformDataを新しく作成したTodoEntityにセットして保存します。
set~~とかget~~はそれぞれのクラス内で@Dataとつけている為、LomBokが自動的にセッターとゲッターを作り、使用することが出来ています。
ここら辺はいきなりLombokを使うと理解しづらいかもしれないので、より深く理解したい方はゲッター・セッターという概念について調べてみると良いでしょう。
最後にRepositoryクラスの関数saveで保存してDBへ保存します!
TodoContorollerからServiceクラスの関数を呼び出す
Serviceクラスの実装が終わったので今度はコントローラから呼び出してみましょう!
@Controller
@RequiredArgsConstructor
public class TodoController {
// ~略~
@PostMapping("/register")
public String register(@ModelAttribute TodoForm formData) {
todoService.setTodo(formData);
return "redirect:/top";
}
}
ここで注目したいのが@ModelAttributeアノテーションですね!
このアノテーションは引数に使う時とメソッドの直前で使う時とで用途が違います!
今回の使用方法はフロント側から送られてきたデータをTodoForm型にして関数内で使える様にする、というものです。
こちらのサイトに分かりやすい説明があるので参考にしてみてください。
formDataを先ほど作成したsetTodoに送ってやる事でTODOをDBに登録します。
また処理が終わったら/topへ遷移するようになっています。
TOPページの編集
最後にフロント側を編集しましょう!
~略
<body>
<!-- 投稿フォーム -->
<div class=" w-75 h-auto my-1 mx-auto pt-5">
<p class="pl-5">新しいToDoを作成する</p>
<form th:action="@{/register}" th:object="${ToDoForm}" method="POST" class="container d-flex w-auto my-0 mx-auto">
<div class="w-100">
<label class="row">
<span class="col-2 text-center">ToDo名</span>
<input type="text" name="title" placeholder="ToDoを30字以内で入力" class="col-9">
</label>
<label class="row my-0">
<span class="col-2 text-center">期日</span>
<input type="date" id="date" name="deadline" class="col-9 my-0">
</label>
</div>
<button class="btn btn-primary w-25 col-2 mr-3" type="submit">ToDoの追加</button>
</form>
</div>
</body>
th:actionで/registerとマッピングされたコントローラの関数へ登録内容を飛ばすようにしています。
またmethod="POST"となっているのでPOSTかつ/registerな関数という細かい指定をしています。
この考え方はHTTPメソッドの性質を理解する上で非常に重要なのでこちらのサイトを参照すると良いかもしれません。
th:objectは送信されたデータの入れ物を指定するのに使っています。
今回の記事で一番最初につくったTodoFormオブジェクトに送信データをぶち込んでいるわけです。
登録ボタンが押された際に
<input type="text" name="title" placeholder="ToDoを30字以内で入力" class="col-9">
name="title"に入力された内容がFormDataクラスの同名の変数(当然 title)に格納されます。
簡単なまとめ
どうでしたでしょうか?簡単なまとめをすると・・・
- フロントからTODOに必要なデータが送信される
- 送信先はth:action~~とmesod=~~によって特定される。送信されたデータは特定のオブジェクトに格納される(今回はFormDataと命名した)
- コントローラからビジネスロジックを記述しているサービスクラスへそのオブジェクトが送られる。
- サービスクラスでTODO登録用のEnitty(データの入れ物)を作成してその中にコントローラから来たオブジェクトの中身を詰める
- Repositoryの関数でそれを保存する。
こんな感じです!
MVCの流れが徐々に理解できたのではないでしょうか?
次回は完了⇄未完了の表示切り替えについて触れていきたいと思います。それではまた!