Spring Bootを紹介してみる
はじめに
この記事は SLP KBIT Advent Calendar 2019 の3日目の記事です。
最後の一枠余っていたので急遽書きました。
今回は、最近自分が一番使っていてるであろうSpring Bootを紹介したいと思います。
Spring Bootってなんぞや?
Spring BootとはJavaやKotlinなどで利用できるWebアプリケーションフレームワークです。 Spring Bootの特徴は調べてもらったらいくらでもでてくるので割愛します。 Spring Bootの良さはたくさんありますが、個人的に良いなと思っているのは以下の点です。
特にライブラリが豊富な点は個人的に良いなと感じており、プロジェクトの規模感に応じてORマッパーを使い分けたりできるのは魅力的です。 また、アーキテクチャ設計の自由度が高い点もプロジェクトの規模感に応じて使い分けれるのでとても良いところだなと感じています。
実際に使ってみる
今回は、Spring Bootでメモ管理システムを作ります。
基本のCRUD機能を実装して完成となります。
使用技術
プロジェクトの立ち上げ
Spring Bootのプロジェクトを立ち上げにはSpring Initializerを使います。
今回は使用技術にあるように、Java11、Spring Boot2.2.1、Gradleを利用していきます。
それぞれ必要なライブラリ群を選択しGenerateするとそれらのライブラリが入った状態のプロジェクトがダウンロードできます。
この時点でライブラリを入れ忘れても、あとでbuild.gradleに書き込めば追加できます。
その後Eclipseを起動し、ファイル -> インポート から 既存のGradleプロジェクトから先程のプロジェクトをインポートします。
実装するエンドポイント
今回実装するエンドポイント一覧です。 Webページは1枚で、メモ一覧表示用にすべてのフォームを実装します。 POST、PUT、DELETEのリクエストが来たときには処理を行った後そのページにリダイレクトするようにしています。
エンドポイント | method | 説明 |
---|---|---|
/memos | GET | メモ一覧表示用 |
/memos | POST | メモ作成用 |
/memos/:id | PUT | メモ更新用 |
/memos/:id | DELETE | メモ削除用 |
テーブル構成
今回はmemoテーブルのみを作成します。カラムの制約はあえてなしにしています。
memo
カラム名 | 型 |
---|---|
id | BIGINT |
body | VARCHAR(256) |
created_at | TIMESTAMP |
updated_at | TIMESTAMP |
アーキテクチャ
Spring Bootでは3層アーキテクチャが使われることが多いです。そこで今回は、そのアーキテクチャを少し改造してcontroller層、service層、repository層、entity層に分けて実装します。 3層アーキテクチャは以下の記事が参考になると思います。
controller層
controllerではリクエストが来た際にどの様な処理を行うのかを実装します。
見慣れないアノテーションがたくさんあったりと複雑そうに見えますが、基本的には来たリクエストをservice層で処理し、その後必要な結果を返すといった実装となっています。
@AutowiredはDependency Injection、いわゆるDIを自動で行ってくれるものです。(DIの説明に関しては今回は省きます)
とりあえず今はmemoService変数には、MemoServiceのインスタンスが入っていると思ってくれれば良いかなと思います。
package work.tomosse.AdventCalendarProject.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; 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.RequestMapping; import org.springframework.web.servlet.ModelAndView; import work.tomosse.AdventCalendarProject.entity.Memo; import work.tomosse.AdventCalendarProject.service.MemoService; @Controller @RequestMapping("/memos") public class MemoController { @Autowired MemoService memoService; /** * メモ一覧表示 * * @param mav * @return */ @GetMapping public ModelAndView index(final ModelAndView mav) { mav.addObject("memoList", memoService.getMemo()); mav.setViewName("index"); return mav; } /** * メモ作成 * * @param memo * @return */ @PostMapping public String create(@ModelAttribute final Memo memo) { memoService.createMemo(memo); return "redirect:/memos"; } /** * メモ更新 * * @param memo * @return * @throws Exception */ @PutMapping("/{id}") public String update(@ModelAttribute final Memo memo) throws Exception { memoService.updateMemo(memo); return "redirect:/memos"; } /** * メモ削除 * * @param id * @return */ @DeleteMapping("/{id}") public String delete(@PathVariable final Long id) { memoService.deleteMemo(id); return "redirect:/memos"; } }
service層
serviceでは、controllerから送られてきたデータをもとに処理を行います。
今回の場合だと、データベースを使った処理を行うことがほとんどになりましたが、複雑なシステムになるとここでの処理が増えることになります。
package work.tomosse.AdventCalendarProject.service; import java.util.Date; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import work.tomosse.AdventCalendarProject.entity.Memo; import work.tomosse.AdventCalendarProject.repository.MemoRepository; @Service public class MemoService { @Autowired MemoRepository memoRepository; /** * memoの一覧を返却する * * @return */ public List<Memo> getMemo() { return memoRepository.findAll(); } /** * memoを作成する * * @param body */ public void createMemo(final Memo memo) { memo.setCreatedAt(new Date()); memo.setUpdatedAt(new Date()); memoRepository.save(memo); } /** * メモを更新する * * @param body * @throws Exception */ public void updateMemo(final Memo memo) throws Exception { memo.setUpdatedAt(new Date()); memoRepository.save(memo); } /** * memoを削除する * * @param id */ public void deleteMemo(final Long id) { memoRepository.deleteById(id); } }
repository層
repository層はDBへのCRUDを自動で実装してくれるインタフェースが集まった層となります。 JpaRepositoryを継承しただけなので説明は省きます。
entity層
entityは今回の場合だとmemoテーブルの構造を表しています。
@Columnでデータベースのカラムとの紐付けを行っています。
本来であれば、Getter/Setterを定義しますが、それをベタに書いてしまうとすごく長いクラスとなるので、Lombokを使って省略します。(@Dataの部分)
LombokはJavaを書く上ですごく便利なライブラリなので積極的に使うと良いと思います。
package work.tomosse.AdventCalendarProject.entity; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import lombok.Data; @Entity @Data public class Memo { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column private Long id; @Column(name="body") private String body; @Column(name="created_at") private Date createdAt; @Column(name="updated_at") private Date updatedAt; }
表示部分
表示部分はThymeleafで実装します。といっても普通のHTMLベースでの書き方なので詰まることは少ないと思います。
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>AdventCalendarProject</title> </head> <body> <h1>AdventCalandarProject</h1> <label>登録</label> <form th:method="POST" th:action="@{/memos}"> <input type="text" name="body" /> <input type="submit" value="登録" /> </form> <table border="1"> <tr> <th>ID</th> <th>内容</th> <th>作成日</th> <th>更新日</th> <th>更新</th> <th>削除</th> </tr> <tr th:each="memo: ${memoList}"> <td th:text="${memo.getId()}"></td> <td th:text="${memo.getBody()}"></td> <td th:text="${memo.getCreatedAt()}"></td> <td th:text="${memo.getUpdatedAt()}"></td> <td> <form th:method="PUT" th:action="@{'/memos/' + ${memo.getId()}}"> <input type="text" name="body" th:value="${memo.getBody()}" /> <input type="submit" value="更新" /> </form> </td> <td> <form th:method="DELETE" th:action="@{'/memos/' + ${memo.getId()}}"> <input type="submit" value="削除" /> </form> </td> </tr> </table> </body> </html>
実際の画面
実際の画面がこちらです。 ちゃんとメモの登録、作成、削除ができるようになっています。
作ったもの
まとめ
かなりざっくりですが、Spring Bootの紹介をしました。
Spring Bootは使えば使うほど良さがわかるフレームワークだと思います。
最初は慣れるまで大変だと思いますが、根気よく使ってみてください。
きっと良さがわかると思います。