[A-00206] Spring Journey(Java)

spring frameworkをジャーニーする記事です。

とりあえずいろんなspringの機能を使って色々作ってみたいと思います。

・RestAPIを設計する

OpenAPI Specificationを作成してRestAPIを設計しましょう

とりあえず下記の内容で作成しました。手始めのAPIなので簡単かつ適当に作りました。

openapi: 3.0.3
info:
  title: "Person Information API"
  version: "1.0.0"
servers:
  - url: http://localhost:8080
paths: 
  /api/person/{id}:
    get:
      summary: Get a person info by ID
      parameters:
        - in: path
          name: id
          schema:
            type: integer
          required: true
          description: Numeric ID of the person to get
      tags:
        - person
      operationId: getPerson

・RestAPIを作成する

とりあえずrest-apiをspringbootで作成してみます。

まずGetメソッドを作ります。Personモデルを返すコントローラを作成します。

package com.example.rest.api.cotroller;

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

import com.example.rest.api.model.Person;

@RestController
@RequestMapping(value="/api/person")
public class RestSvcPersonController {
    
    @GetMapping("/{id}")
    public Person getPerson(@PathVariable int id) {
        // TODO 後ほどcoreサービスを作成する
        Person p = new Person();
        p.setId(1);
        p.setName("Satoshi Tajima");
        p.setAge(14);
        p.setCountry("Japan");
        return p;
    }
}
package com.example.rest.api.model;

import lombok.Data;

@Data
public class Person {
    
    private int id;
    private String name;
    private int age;
    private String country;
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.3.1</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example.rest.api</groupId>
	<artifactId>demo-rest-api</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo-rest-api</name>
	<description>Demo project for Spring Boot</description>
	<url/>
	<licenses>
		<license/>
	</licenses>
	<developers>
		<developer/>
	</developers>
	<scm>
		<connection/>
		<developerConnection/>
		<tag/>
		<url/>
	</scm>
	<properties>
		<java.version>21</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.32</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

ディレクトリ構成は下記のようにしてます。

mavenビルドして起動します。

mvn clean install
java -jar target/demo-rest-api-0.0.1-SNAPSHOT.jar

実行できたらcurlを実行してGetリクエストします。下記のようにJSONが返ってきたら成功です。

$ curl -X GET http://localhost:8080/api/person/1
{"id":1,"name":"Satoshi Tajima","age":14,"country":"Japan"}

・Dockerで動かしてみる

次にデプロイするためのDockerfileを作成します。Dockerを用いて下記のようなイメージでSpringBootを動かします。

FROM openjdk:21

WORKDIR /usr/src/myapp

COPY target/demo-rest-api-0.0.1-SNAPSHOT.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java","-jar","app.jar"]
docker build -t hello-app-java .
docker run -it --rm --publish 8080:8080  --name my-running-app hello-app-java

上記を実行すると、ローカルの8080ポートにフォワードされますので同じようにlocalhost:8080にリクエストを飛ばすと同じ結果が返ってきます。

・Kubernetesで動かしてみる

ローカルからkubernetesのservice,deploymentにアクセスしてrestapiにリクエストしたいので下記のyamlファイルを作成します。kubernetesクラスターのアーキテクチャは下記の通りです

apiVersion: v1
kind: Service
metadata:
  name: hello-java-app-service
spec:
  type: LoadBalancer
  selector:
    app: app
  ports:
  - port: 80
    targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      containers:
      - name: app
        image: hello-app-java
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

下記のコマンドを実行します。

kubectl apply -f k8s-deployment.yml

kubernetesのservice,deploymentを確認します。

$ kubectl get pods,services,deployments
NAME                         READY   STATUS    RESTARTS      AGE
pod/app-5df45cbb69-hwxk7     1/1     Running   0             18m
pod/httpd-58f4986b-sjwjw     1/1     Running   3             56d
pod/nginx-58fdfc99cd-zz9kr   1/1     Running   2 (39m ago)   56d

NAME                             TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/hello-java-app-service   LoadBalancer   10.106.199.164   localhost     80:30713/TCP   18m
service/httpd-svc                ClusterIP      10.111.22.101    <none>        8090/TCP       56d
service/kubernetes               ClusterIP      10.96.0.1        <none>        443/TCP        275d
service/nginx-svc                ClusterIP      10.102.32.169    <none>        8080/TCP       56d

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/app     1/1     1            1           18m
deployment.apps/httpd   1/1     1            1           56d
deployment.apps/nginx   1/1     1            1           56d

localhost:80に対してリクエストを実行すると下記のように動きます。

$ curl localhost:80/api/person/1
{"id":1,"name":"Satoshi Tajima","age":14,"country":"Japan"}

・RestAPI(microservice)を設計する

次にしっかりとしたRestAPI(ちゃんとCRUD機能がある)を作成してみたいと思います。

設計する客体として学生を管理するAPIをイメージして作ります。

//TODO

・API Gatewayを作成する

API Gatewayを作成して各RestAPIへのRoutingを作りたいと思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

*