SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Spring Bootで作るマイクロサービス

Spring Bootで始める簡単Webプロジェクト~ひな型の作成からWeb APIの実装まで

Spring Bootで作るマイクロサービス 第2回


Spring Bootで簡単なWeb APIを作成する

 続いて、先ほど作成したプロジェクトを使い、図6に示す簡単なWeb APIのエンドポイントを追加しつつSpring Bootでの開発の流れを紹介します。

図6:サンプルの仕様
図6:サンプルの仕様

 サンプルの仕様は、(1)のように設定ファイルがあり、その設定ファイルで変数の初期値を指定します。次に、(2)のようにその変数の値を保持するアプリケーションで1つの共有インスタンス(シングルトンインスタンス)を保持します。

 そして、(3)のようにそのインスタンスをJSON形式でGETできるAPIエンドポイントと、POSTで変更できるAPIエンドポイントがあります。リスト3はこれらのAPIを利用したときの実行例です。

[リスト3]サンプルコードに対してAPIを実行したときの例(出力は整形済み)
$curl -s http://127.0.0.1:8080/hello/world
{
  "value": "Hello sample"
}
$curl -s -H 'Content-Type:application/json' -d '{ "value" : "こんにちは" }' http://127.0.0.1:8080/hello/world
{
  "value": "こんにちは"
}
$curl -s http://127.0.0.1:8080/hello/world
{
  "value": "こんにちは"
}

 また、これらのソースが図7のようなパッケージ、もしくはフォルダ構造になっています。

図7:サンプルソースのディレクトリ構造
図7:サンプルソースのディレクトリ構造

 ここでは、必ずメインプログラムであるSampleApplicationクラスのパッケージ以下に関連クラスを作成するように気を付けてください。

 SpringBootではそれぞれのクラスに付与されたアノテーションから自動的に管理できるようにしていますが、そのためにはプロジェクトのメインパッケージ配下に置く必要があります。

 ただし、これらの制限はあくまでデフォルトの設定ではあり、これらの変更方法は次回以降説明します。現時点ではSpring Bootで特別な設定が必要ないように、こういったルールでコードを記述するようにしてください。

アプリケーションでの設定(DI)を制御する

 Springでの設定では、設定ファイルから値を取得するといった単純なものだけではなく、DIを実現するためのコードの記述もすることになります。

 前回、DIを実現する方法として、XMLを使う以外にJavaのコードでDIの設定ができると紹介しました。リスト4がSpring FrameworkのDI設定例です。

[リスト4]JavaベースでのDIの設定方法(src/main/java/com/coltware/spring/sample/config/SampleConfiguration.java)
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// (1) Javaベースの設定を示すアノテーション
@Configuration
public class SampleConfiguration {

    // (2) 設定ファイルから"sample.world"の値で設定する
    @Value("${sample.world:World}")
    String world;

    // (3) オブジェクトの作成方法を指定する
    @Bean
    public WorldModel worldModel(){
        WorldModel model =  new WorldModel();
        model.setValue(world);
        return model;
    }
}

 クラス宣言の前に(1)のように@Cofigurationアノテーションを指定します。この指定がDIのためのコードであることを指定します。続いて、(2)では設定ファイルの"sample.world"という項目の値を取得し、変数に設定しています。

 また、設定がない場合のデフォルト値の指定は、:(コロン)以降に記述します。(3)ではこのアプリケーション内でのWorldModelの共有インスタンスを示す@Beanアノテーションを指定します。

 このような流れでDIの定義をしていきます。DIの指定方法がJavaのコードになってしまったことで後から柔軟に実装を入れ替えることができなくなり、DIを使わない頃のJavaに先祖返りしてしまった印象を受けるかもしれません。

 しかし、実際にはXMLでの柔軟すぎる変更の可能性やそれに伴う複雑なXML記述というのはデメリットも多々ありました。

 そのため、Javaにすることでもう一度、開発者にコントロールを戻しています。ただし、開発者はあくまで設定という視点でわかりやすいコードを記述するように心がける必要があります。

Web APIのエンドポイントを定義する

 Web APIのサンプルコードがリスト5です。同様のことを実現する際には、一般的にはServlet APIを使いますが、Springでは特定の親クラスを継承する必要がありません。

 そのため、他のコードからの依存性を低く保ちつつ、また、テストが行いやすいコードとして記述しやすくなっています。

[リスト5]JavaベースでのDIの定義方法(src/main/java/com/coltware/spring/sample/api/HelloController.java)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

// (1) Rest用のコントローラクラスであることを宣言する
@RestController
// (2) /hello 以下のリクエストに対する処理
@RequestMapping(value = "/hello")
public class HelloController {
    private static final Logger log = LoggerFactory.getLogger(HelloController.class);

    // (3) 自動的にWorldModelオブジェクトを設定する
    @Autowired
    WorldModel model;

    // (4) GET /hello/world  に対する処理
    @GetMapping(value = "/world")
    public WorldModel world(){
        return model;
    }
    //  (5) POST /hello/world  に対する処理
    @PostMapping(value = "/world")
    public WorldModel setWorld(@RequestBody WorldModel world){
        model.setValue(world.getValue());
        log.info("set value : {}",model.getValue());
        return world;
    }
}

 (1)ではRest用のコントローラであることを宣言しています。ここでのRestとはRESTFulという意味ではなく、単純にWebアプリケーションのコントローラである、といった程度の指定です。この指定によりWebコンテナが指定のURLで、どのコントローラを起動すればよいかを管理しています。

 Springのプロジェクトの経験がある方であれば、Web用のコントローラクラスに@Controllerというアノテーションを使っていたと思いますが、Web APIのようにJSON形式のコントローラの場合には@RestControllerというアノテーションをつけることでリターン値をJSON形式のレスポンスデータとして扱うことができます。

 また、(2)ではこのコントローラが/helloというエンドポイント配下に対する処理であることを定義しています。

 続いて、(3)の@AutowiredというアノテーションはDIを実現するための指定でWorldModelのインスタンスが自動的に設定されます。

 (4)では、/hello/worldに対してGETリクエストがあったときの処理を定義し、(5)ではPOSTリクエストがあったときの処理を定義しています。@RequestBodyというアノテーションは、リクエストデータとしてWorldModelのJSONフォーマットを利用することを宣言しています。

 また、リクエストやレスポンスがJSONからJavaのオブジェクトに自動的に変換されていますが、JSONフォーマットへの変換方法にはデフォルトではJacksonを使っています。

 そのため、必ずしも自分で指定したオブジェクトが正しくJSONにならなかった場合や、希望するフォーマットにカスタマイズする際には、Jacksonの仕様について知る必要があります。

最後に

 Spring Bootを使えば、TomcatなどのWebコンテナの設定、起動、停止の方法、そして、開発したコードの設定方法などにわずらわされることなく、すぐにコードの記述、実行まで確認できます。

 これらの簡略化は、Springが提供しているさまざまなアノテーションと、それらの設定やルールをまとめたSpring BootのStarterによって実現しています。

 アノテーションの使い方やSpring特有の注意点などを覚える必要はありますが、Spring Bootはそれらを考慮しても十分使いやすくなっています。

 また、利用する開発者が非常に多いために、ドキュメントやノウハウなども十分に蓄積されていることも安心できる大きな要因です。次回からは、もう少し本格的なサンプルを作成しながら各機能の紹介をしていきます。

参考資料

 

本連載の書籍が発売されました!

Javaによる高速Webアプリケーション開発のためのSpring Boot入門

Amazon(POD) Amazon(電子書籍) その他

Javaによる高速Webアプリケーション開発のためのSpring Boot入門

著者:WINGSプロジェクト 小林昌弘
発売日:2020年5月31日(水)
価格(POD):2,200円(税込)
価格(電書):1,760円(税込)

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
Spring Bootで作るマイクロサービス連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

WINGSプロジェクト について> 有限会社 WINGSプロジェクト が運営する、テクニカル執筆コミュニティ(代表 ...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/11380 2020/06/01 18:46

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー