54
59

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Spring Boot / Thymeleafの基礎を学ぶ【初心者向け】

Last updated at Posted at 2019-06-04

はじめに

この記事は社内でSpring Boot(実質的にはSpring?)の勉強会を行うにあたり作成した資料となります。
1時間程度で済む簡単なものになっています。
「Spring Bootってこんな感じなんだ」ということが少しでも伝われば幸いです。
なお、私自身Spring並びにSpring Boot初心者なため、記事に誤っている点があるかもしれません。
その際はご指摘いただけますと幸いです。

環境

  • Mac
  • Spring 2.0.2
  • Dokcer for Mac
  • Gradle 5.2.1
  • VSCode

※Eclipseでええやん!って人はDockerじゃなくても○。
※Gradleについては以下の記事が分かり易かったです。
→  [多分わかりやすいGradle入門] (https://tech-lab.sios.jp/archives/9500)
  [Gradle入門] (https://qiita.com/vvakame/items/83366fbfa47562fafbf4)

Springについて

強み

  • 変更に強い
    • DI(Dependency Injection)という仕組みが導入されている。
      • それぞれが独立しているため依存度が低く、変更に強い。
  • 拡張性が高い
    • 基本的な機能の大部分が インターフェース として提供されている。
    • 必要な部分は簡単に追加できる。
  • 保守性が高い
    • AOP(アスペクト指向プログラミング) を用いることができる。
      • 共通のプログラムを再利用することでコーディング量減・修正も簡単
  • テストが簡単
    • Spring MVC Test という専用のテストプログラムで結合テストが簡単にできる。
  • 大規模データベース NoSQL に対応

弱み

  • フレームワークの規模が大きく、全体を把握するのが難しい。
  • DIコンテナの正しい使い方が難しい
  • 日本語のドキュメントが乏しい

じゃあSpring Bootって何?

WEBアプリケーションに特化した「Spring MVC」というフレームワークの完成形として、Spring MVCやその他のSpring Frameworkのライブラリ類をいい感じに組み合わせたWebアプリケーション環境を簡単に構築するライブラリです。

【参考: [[Java] Spring BootでHello World!(入門編)] (https://www.marineroad.com/staff-blog/16785.html)】

その特徴を簡単にまとめると、

1.アノテーションを記述するだけで実装できる機能が多数あり、コード量を削減できる
2.Webコンテナをjarに内蔵することで、jar単体でWebアプリケーションが実行できる
3.今までのSpringフレームワークでは必須だった、XML設定ファイルが不要になった
4.Spring Initializrというプロジェクト雛形生成サービスがあり、一から開発する必要がない

などなど様々な高速システム開発のための機能が提供されています。

【[[Java] Spring Bootで簡単・高速にWebAPI開発] (http://www.xn--springboot-mh5yz04y.tokyo/01-introduction-spring-boot/)】

下準備

  • Docker for Macをインストールし、 docker コマンドが打てることを確認する。
  • 以下のコマンドを実行する。
$ git clone https://github.com/miwa0519/spring-boot.git
$ cd spring-boot/spring_boot_docker/
  • 以下のコマンドを実行。
  • Tomcatが8080ポートで動く。
  • 3000番ポートは人気者だから別ポートがいい、という場合は docker-compose.yml 内の3000部分を別の番号に変えるといい。
  • Springが上手く動いていればコンソールに Spring>>> みたいな例のAAが出る。出ると少しテンションが上がる。
$ docker build -t spring-docker ./
$ docker run -p 3000:8080 spring-docker

今回のサンプルだと、ソースコードを編集する度に上記コマンドを実行する必要があります。
今後改善予定です。面倒臭くてすみません:bow_tone1:

とりあえずHello Worldしてみる

src/main/java/com/example/demo 直下に HelloController.java を作成します。
HelloController.java 内に以下のソースを記述します。

src/main/java/com/example/demo/HelloController.java
package com.example.demo;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
  @RequestMapping("/hello")
  public String hello() {
    return "Hello World!";
  }
}

http://localhost:3000/hello
にアクセスすると Hello World! と表示されていると思います。

スクリーンショット 2019-05-29 12.52.38.png

アノテーションが二つ出てきました。これらが何をしているかを簡単に説明します。

  1. @RestController :RestControllerアノテーションをつけると、このコントローラーが Webアプリケーション のリクエストを受け付ける Restコントローラー になる。
  2. @RequestMapping :RequestMappingアノテーションをつけると、ルーティングを行なってくれる。今回でいうと、 http://localhost:3000/hello にアクセスすると Hello メソッドを実行する、という紐付けが行われる。

これらが使えるように、それぞれのクラスをインポートしてます。インポート出来ていないとコンパイルエラーになるので気をつけてください。

もう少しWebアプリらしく Hello World! したいので、今度はテンプレートを作ってみたいと思います。

Viewの部分を実装する

Spring Bootでは1.2以降はJSPが非推奨とされています。
なので今回は Thymeleaf というテンプレートエンジンを使います。
Spring Bootでは Thymeleafを使うのが無難らしいです。

Thymeleafを使えるように設定する

設定をしないとThymeleafは使えません。

build.gradle を以下のように書き換えてください。

build.gradle
// 中略

dependencies {
+	compile('org.springframework.boot:spring-boot-starter-thymeleaf')
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

実際にHTMLを書いてみる

Thymeleafの設定ができたので、実際にHTMLを書いてViewを実装していきます。
src/resources 直下に templates ディレクトリを用意し、 hello.html ファイルを作成します。

src/main/resources/templates/hello.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>Thymeleaf</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  </head>
  <body>
    <p th:text="'Hello Wonderful World!'" />
  </body>
</html>

th:textThymeleaf の属性。Thymeleafの記述については以下が分かりやすかったです。
[[Java] Spring BootでThymeleafを使ってみよう!(応用編)] (https://www.marineroad.com/staff-blog/17761.html)

HelloControllerを修正する

テンプレートを用意したので、今度はコントローラーがそのテンプレートを呼び出してくれるように修正します。

HelloController.java
package com.example.demo;

  import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
+ import org.springframework.stereotype.Controller;
+ import org.springframework.web.bind.annotation.RequestMethod;

- @RestController
+ @Controller
  public class HelloController {
    @RequestMapping("/hello")
    public String hello() {
-     return "Hello World!"
+     return "hello";
    }
  }

@RestController@Controller に変更しました。
これにより、WebAPIとして機能していた HelloControllerMVCC として振る舞うようになります。
それにより、 return の部分に記載した helloViewResolver がView名として認識し、実際のファイル名に変換し、クライアントに返却します。

最初のコマンドを再度実行した後に
http://localhost:3000/hello
をリロードします。テンプレートが呼び出されて、表示される文言が変わっていることが確認できると思います。

スクリーンショット 2019-05-29 12.56.17.png

簡単な計算アプリを作ってみる

MVCのVとCについてはここまでで学ぶことが出来ました。
最後にModelについての説明を加えながら、与えた数字を元に足し算を行ってくれる簡単なアプリを作成したいと思います。

Model作ってみる

まず、フォームの値を受け取って計算するためのモデルを作成します。
Controllerを作成したディレクトリの中に model ディレクトリを作成し、その中に Form.java を作成します。

src/main/java/com/example/demo/model/Form.java
package com.example.demo.model;

public class Form {

  private int num1 = 0;
  private int num2 = 0;
  private int total = 0;

  public int getNum1(){
    return num1;
  }

  public void setNum1(int num){
    this.num1 = num;
  }

  public int getNum2(){
    return num2;
  }

  public void setNum2(int num){
    this.num2 = num;
  }

  public int getTotal(){
    return total;
  }

  public void setTotal(int total){
    this.total = total;
  }
  public void sumTotal(){
    total = this.num1 + this.num2;
    setTotal(total);    
  }
}

入力値を保持する num1num2 と合計値を保持する total フィールドを作成し、それぞれに gettersetter を定義します。
また、 num1num2 の合計を算出する sumTotal メソッドを定義しておきます。

入力フォームを表示する

modelを定義したので、次は入力フォームを表示してみます。
まず、入力フォームを表示するためのコントローラーを定義します。

src/main/java/com/example/demo/CalculateController.java
package com.example.demo;
import com.example.demo.model.Form;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;

@Controller
public class CalculateController {
  @RequestMapping("/calculate")
  public String form(Model model){
    model.addAttribute("form", new Form());
    return "index";
  }
}

今までの Controller と違うところは、メソッドに Model 型のオブジェクトを引数に取っているところです。
この Model に値をセットすることでHTMLに値を渡す事が出来ます。(Springが用意してくれているクラス)
model.addAttribute("form", new Form()) の部分で、 model に対し、Formインスタンスを渡しています。

model.addAttribute("変数名", オブジェクト)

※ちなみに、第2引数に Form form と記述しても同じ意味になります。(裏で
addAttribute と同じことが実行されるイメージ)

【参考:[【Spring Boot】ModelクラスとModel And Viewクラス] (https://pointsandlines.jp/java/model-and-view)】

form メソッドでは index というテンプレートを最後に返しています。
今度は index テンプレートを作成し、入力画面を作成します。

入力画面を作る

src/main/resources/templates/index.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>Index</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  </head>
  <body>
    <h1>Form</h1>
    <form action="#" th:action="@{/result}" th:object="${form}" method="post">
      <p>first number: <input type="number" th:field="*{num1}" /></p>
      <p>Second number: <input type="number" th:field="*{num2}" /></p>
      <p><input type="submit" value="calculate" /></p>
    </form>
  </body>
</html>

最初に作った hello.html と異なるところは、 th:actionth:objectth:field という属性が出てきている点です。
なんとなく見た目で伝わるかと思いますが、簡単に使い方だけご紹介します。

th:action   th:object th:field="*{フィールド名}"
フォームのアクションを指定する ${}で指定したオブジェクトにフォームで入力した値が入る。 th:objectで指定しているオブジェクトのフィールドに対して入力された値を入れる。

【参考: [Spring Boot でフォームの値を取得して操作] 】(https://qiita.com/NariseT/items/172ca093364aa9391989)

各テキストエリアに入力された値は、先ほどコントローラーで Model オブジェクトに追加した Form インスタンスの各フィールドに値がセットされます。

http://localhost:3000/calculate
にアクセスすると入力フォームが表示されるはずです。

スクリーンショット 2019-05-29 13.54.42.png

Controllerを修正する

今度はフォームで入力した値を受け取り、計算を行い、その結果を画面に表示できるようにします。
まずはコントローラーに新しいメソッドを追加します。

src/main/java/com/example/demo/CalculateController.java
package com.example.demo;
import com.example.demo.model.Form;

// 中略
  import org.springframework.ui.Model;
+ import org.springframework.web.bind.annotation.RequestMethod;
+ import org.springframework.web.bind.annotation.ModelAttribute;

  @Controller
  public class CalculateController {
    @RequestMapping("/calculate")
    public String form(Model model){
      model.addAttribute("form", new Form());
      return "index";
  }

+   @RequestMapping(value="/result", method = RequestMethod.POST)
+   public String result(@ModelAttribute Form form, Model model){
+     form.sumTotal();
+     model.addAttribute("form", form);
+     return "result";
+   }
  }

@RequsetMapping は今回パラメータを受け取るので、HTTPメソッドを指定します。
method = RequestMethod.post と記載することでこれはPOSTだよ!と指定できます。
また今回はメソッドの引数に @ModelAttribute というアノテーションがついています。このアノテーションをつけると input の値を受け取ることが出来ます。

form の各フィールドには入力フォームで入力された値がセットされている状態なので、 Form クラスで定義した sumTotal メソッドを呼び出し、 formtotal フィールドに合計値を保持させます。

その結果を result テンプレートに表示させたいので、今度は result テンプレートを作成します。

計算結果を画面に表示する

templates ディレクトリ直下に以下のファイルを作成してください。

src/main/resources/templates/result.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>Result</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  </head>
  <body>
    <h1>Result</h1>
    <p th:text="'Answer: ' + ${form.getTotal()}" />
    <a href="/calculate">Calculate Another number</a>
  </body>
</html>

${} で式展開を行なってくれるので、getterを使っての合計値を取得し、表示します。

計算実行結果は以下です。

スクリーンショット 2019-05-29 13.59.03.png スクリーンショット 2019-05-29 13.28.57.png

最後に

私自身がSpring Bootについて初歩的な部分を学んで感じたのは以下の三点です。

  • 面倒な設定が少なく、すぐに開発に取りかかれた。(Dockerで動かすのが大変だったくらい)
  • ソースコードが割と直感的に書ける
  • 自分の求めているドキュメントに辿り着くまでの時間が壮大(自分の調べ方が下手なだけかも)

とはいえ私自身、初歩的な部分しかまだ分からない状況なので、今後も少しずつ学んでいけたらと思っております。
この記事がSpring Boot、Spring初心者の何かの皆さんの役に立てば幸いです。

参考

54
59
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
54
59

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?