🐥

docker-compose 下で Java + Spring Boot + 簡単なWeb API を作ってみる

7 min read 1

TL;DR

docker-compose.yml を用意する

cd your_project
mkdir server
touch docker-compose.yml
docker-compose.yml
docker-compose.yml
version: '3.6'
services:
  app:
    image: openjdk:15
    ports:
      - 8080:8080
    tty: true
    volumes:
      - ./server:/srv:cached
    working_dir: /srv

Gradleプロジェクト作成

今回も Spring Initializr というサイトで作ってしまいます。

前回の記事との違いは特にないです。

入力が終わったら GENERATE してダウンロードします。
ダウンロードしたら展開したものを
your_project/server 配下に配置します。

server/src/main/java/com/example/api/ApiApplication.java はダウンロードしてきたままでOK.

server/src/main/java/com/example/api/ApiApplication.java
package com.example.api;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ApiApplication {
	public static void main(String[] args) {
		SpringApplication.run(ApiApplication.class, args);
	}
}

簡単な GETリクエストを受けつけてみる

mkdir server/src/main/java/com/example/api/controllers
touch server/src/main/java/com/example/api/controllers/TestController.java

こんな感じのファイルを用意する

server/src/main/java/com/example/api/controllers/TestController.java
package com.example.api.controllers;

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

@RestController
public class TestController {
    @RequestMapping(path = "/test", method = RequestMethod.GET)
    public String test() {
      return "ok from test.";
    }
}

用意したら、Docker コンテナを起動してGradleビルド, アプリケーション起動

docker-compose up -d
docker-compose exec app bash
bash-4.4# pwd
/srv
bash-4.4# sh gradlew build
bash-4.4# java -jar build/libs/api-0.0.1-SNAPSHOT.jar

起動したら http://localhost:8080/test へcURLでリクエストを投げてみます。

$ curl http://localhost:8080/test -X GET
ok from test.

いい感じですね。
参考にした記事には org.springframework.boot:spring-boot-starter-data-rest が必要との記述がありましたが、単純な RestController を作る分にはこのパッケージは不要です。
(RestController を使っていますが RESTfull なAPIは今回は作ってないです)
Spring Data REST は Entity と Repository を用意するだけで
RESTful な Endpoint が全部生える便利なパッケージですね。

JSON をレスポンスしてみる

POJO(Plain Old Java Object) をreturnしてやるとJSONシリアライズしてレスポンスできる。

server/src/main/java/com/example/api/controllers/TestController.java
package com.example.api.controllers;

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

@RestController
public class TestController {
    @RequestMapping(path = "/test", method = RequestMethod.GET)
    public String test() {
      return "ok from test.";
    }

    @RequestMapping(path = "/test/json", method = RequestMethod.GET)
    public Example testJson() {
      var examplePOJO = new Example();
      examplePOJO.value1 = "foo";
      examplePOJO.value2 = "bar";
      return examplePOJO;
    }

    public class Example {
  		public String value1;
	  	public String value2;
	  }
}

コンパイルしてサーバー起動し直し

bash-4.4# sh gradlew build
bash-4.4# java -jar build/libs/api-0.0.1-SNAPSHOT.jar

起動したら http://localhost:8080/test/json へcURLでリクエストを投げてみます。

$ curl http://localhost:8080/test/json -X GET
{"value1":"foo","value2":"bar"}

いい感じですね。
内部では Jackson がよしなにシリアライズしてくれてるみたいです。

簡単な POSTリクエストを受けつけてみる

server/src/main/java/com/example/api/controllers/TestController.java
package com.example.api.controllers;

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

@RestController
public class TestController {
    @RequestMapping(path = "/test", method = RequestMethod.GET)
    public String test() {
      return "ok from test.";
    }

    @RequestMapping(path = "/test/json", method = RequestMethod.GET)
    public Example testJson() {
      var examplePOJO = new Example();
      examplePOJO.value1 = "foo";
      examplePOJO.value2 = "bar";
      return examplePOJO;
    }

    @RequestMapping(path = "/test/post", method = RequestMethod.POST)
    public Example testPost(@RequestBody Example requestPOJO) {
      requestPOJO.value1 = requestPOJO.value1 + ":AddServer";
      requestPOJO.value2 = requestPOJO.value2 + ":AddServer";
      return requestPOJO;
    }

    // static class で宣言しないと @RequestBody で受け取れない……?
    public static class Example {
  		public String value1;
	  	public String value2;
	  }
}

import org.springframework.web.bind.annotation.RequestBody; を追加していますが
ワイルドカード指定で
import org.springframework.web.bind.annotation.*; でもいいかもしれませんね。

コンパイルしてサーバー起動し直し

bash-4.4# sh gradlew build
bash-4.4# java -jar build/libs/api-0.0.1-SNAPSHOT.jar

起動したら http://localhost:8080/test/post へcURLでリクエストを投げてみます。

$ curl http://localhost:8080/test/post -X POST -H 'Content-Type: application/json' -d '{"value1":"hoge","value2":"fuga"}'
{"value1":"hoge:AddServer","value2":"fuga:AddServer"}

いい感じですね!

今回のリポジトリはこちら

https://github.com/JUNKI555/java_spring_boot_practice01

Discussion

記事拝見させていただきました。
最近SpringBootの勉強をし始めたばかりだったので、大変参考になりました。
ありがとうございました。

1点もしお分かりであれば教えていただきたいことがあるのですが、よろしいでしょうか?

// static class で宣言しないと @RequestBody で受け取れない……?

とコード中に記載されており、試したところ確かにstatic修飾子をつけないとエラーになりました。

調べたところ、これといった情報を得ることができませんでした。
staticをつけるつけないでどのように変わるか既に解決済みでしたらお教えいただけませんでしょうか?

ログインするとコメントできます