#目的
Spring Quickstart Guideを取り組み終えた方、SpringBootを学び始めた方、復習をしたい方に向けて、
公式が人気ガイドだからやってみて!と勧めてくれている、Building a RESTful Web Serviceを実際に取り組み学んだことを共有します。
OS: macOS Mojave バージョン10.14.6
テキストエディタ: Visual Studio Code(以下VSCode)
Java: 11.0.2
#1.SpringBoot projectを始めよう!
まずは、spring initializrにアクセスします。
web
と入力して、Spring Web
を選択します。
Artifact, Nameは、restserviceに変更しました。
Javaのversionは11なので、11を選択します。
GENERATE
ボタンをクリックします。
Zipファイルがダウンロードされるので、
そのZipファイルを展開してください。
準備完了です。
#2.コードを追加しよう!
先ほどのフォルダをVSCodeで開きます。
拡張機能のJava Extension Packのインストールの推奨します。と言われるのでインストールしておきましょう。
##Greeting.javaを作成しよう!
src/main/java/com/example/restservice/
にGreeting.javaファイルを作成します。
Greeting.javaファイル内にコードを追加していきます。
package com.example.restservice;
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
Greeting.javaファイルに追加したコードを深掘りしていきます。
###①定数の宣言
private final long id;
private final String content;
long型のid、string型のcontentという定数をそれぞれ宣言しています。
アクセス修飾子はprivate
、そして、final修飾子を用いている
ので、同一クラス内からしかアクセス出来ない定数となります。
定数なので、値の再代入は不可能となります。
###②コンストラクタの定義
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
インスタンス化された時に同時に行っておきたい処理
を記述しておきます。
今回は、インスタンス定数であるid、contentに初期値を代入しています。
###③ゲッターメソッドの定義
public long getId() {
return id;
}
public String getContent() {
return content;
}
id、contentの値を呼び出すためのメソッドです。
Greeting.javaはこれで完成です!
##GreetingController.javaを作成しよう!
src/main/java/com/example/restservice/
にGreetingController.javaファイルを作成します。
GreetingController.javaファイル内にコードを追加していきます。
package com.example.restservice;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@GetMapping("/greeting")
public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
GreetingController.javaファイルに追加したコードを深掘りしていきます。
###①@RestController
@RestController
public class GreetingController {
}
このアノテーションを記述する事により、SpringBootはControllerとして認識してくれます。Viewには遷移せずにメソッドの戻り値がそのままレスポンスのコンテンツとなります。
後述のgreetingメソッドはGreetingオブジェクトを戻り値にしていますが、SpringBootがJSONに自動変換してくれているのでJSONが画面に表示される事になります。
###②定数の宣言
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
string型のtemplate、long型のcounterという定数をそれぞれ宣言しています。
アクセス修飾子はprivate
、そして、final修飾子を用いている
ので、同一クラス内からしかアクセス出来ない定数となります。
定数なので、値の再代入は不可能となります。
templateの方は、static修飾子を用いているので、クラスに対して1つしか存在しない定数となります。
そして%s
は、String.formatというメソッドを使用する際に、第一引数に決められた書式を指定しなければいけないため、記載されています。
counterの方は、AtomicLongクラスを用いています。
なぜこのクラスを用いているのかは後ほど記述します。
###③greetingメソッドの定義
@GetMapping("/greeting")
public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
@GetMapping("/greeting")
は、URLで〇〇/greeting
とアクセスされた時(GETリクエストがあった時)、greetingメソッドの処理が行われるためのアノテーションです。
http://localhost8080/greeting とアクセスがあった時にgreetingメソッドが呼ばれるという事です。
greetingメソッドの引数の@RequestParam
は、URLのクエリパラメータを受け取る事が出来ます。
String nameにどのような値を格納するのかを指定しており、
http://localhost8080/greeting とアクセスがあった場合は、nameにはWorldが格納され
、
http://localhost8080/greeting?name=tanaka とアクセスがあった場合は、nameにはtanakaが格納されます
。
最後にreturnの部分を深掘りします。
return new Greeting(counter.incrementAndGet(), String.format(template, name));
http://localhost8080/greeting とアクセスされる毎にGreetingクラスをインスタンス化したJavaオブジェクトを返しています。
new Greetingのコンストラクタの第一引数にcounter.incrementAndGet()
、第二引数に String.format(template, name)
を渡しています。
Greetingクラスのインスタンス化、counterのインクリメント、書式を指定して文字列を返す、と複数処理を同時に行っています。
インクリメントはcounter++;
と記述も出来ますが、複数の処理が実行された場合に正しく処理されない場合があるため、
上述のAtomicLongクラスでcounterを定義して、同クラスのメソッドであるincrementAndGet()
を使用し、現在の値(counter)をインクリメントして、インクリメントした値を返しています。
アトミックは不可分操作と言われており、加算が終わるまで他の処理の割り込みをさせないためにAtomicLongクラスを用いてcounterを定義した、と解釈しました。
#3.実行してみよう!
アプリケーション実行の準備が出来たので確認しましょう。
ターミナルで以下のコマンドを入力してEnterしてください。
$ ./mvnw spring-boot:run
2秒ぐらい待った後、http://localhost:8080/greeting にアクセスすると、
次に、http://localhost:8080/greeting?name=tanaka でアクセスすると、
次に、http://localhost:8080/greeting?name=suzuki でアクセスすると、
アクセスする毎にidが増えていき、/greeting?name=任意の文字列
でアクセスすると入力した値が表示されていますね!
#参考サイト
SpringBoot入門ガイド
OracleのAtomicLong
アトミックであるとはどういうことか
マルチスレッド
Java並行処理の基本