0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Spring AI 第2回】Spring AI から Gemini を呼び出す構成を、GETからPOSTに書き換えてみた

0
Last updated at Posted at 2026-09-15

はじめに

前回の記事

では、Spring AI の ChatClient を使って Gemini と会話する最小構成(GETリクエスト・クエリパラメータ渡し)を作りました。

今回はその発展として、以下の2点を変更した構成を作ってみます。

  • リクエストを GET から POST に変更し、質問をJSONボディで受け取る
  • Controllerが ChatClient を直接扱うのをやめ、Service層(インターフェース+実装) に切り出す

コード量はそこまで増えませんが、実際のアプリケーションに組み込むことを意識した形に一歩近づけます。

前提環境

前回と同様です。

  • Eclipse Version: 2025-12 (4.38.0)(Spring Tools がインストール済み)
  • JDK 21
  • Spring Boot 4.1.1 / Spring AI 2.0.1
  • ビルドツール:Gradle

1. 前回からの変更点

前回はコントローラーが直接 ChatClient を持っていましたが、今回は次のような役割分担にします。

クラス 役割
Question / Answer 質問・回答を表す record
SpringAiService 「質問を受け取って回答を返す」ことを表すインターフェース
SpringAiSample02Service SpringAiService の実装。Gemini とのやり取りを担当
AskController HTTPリクエストの受け口。SpringAiService に処理を委譲するだけ

こうしておくと、たとえば「Geminiではなく別のAIプロバイダーを試したい」「テストのときはモックに差し替えたい」といった場合に、AskController を一切変更せずに済みます。今回はこの構成にしておくことで、将来の拡張の土台を作っておく狙いもあります。

2. 実装

プロジェクトの作り方(Eclipseでの新規プロジェクト作成、application.properties の書き方)は前回と同じなので割愛します。今回は application.properties も前回と同じ内容です。

spring.application.name=SpringAISample02

spring.ai.google.genai.api-key={AIza...から始まるAPIキー}
spring.ai.google.genai.chat.model=gemini-3.1-flash-lite

2.1 Question / Answer

質問と回答を表す、シンプルな record です。

Question.java
package com.example.springaisample;

public record Question(String question) {
}
Answer.java
package com.example.springaisample;

public record Answer(String answer) {
}

@RequestBody / produces="application/json" によって、これらは自動的にJSONへ変換・JSONから変換されます。

2.2 SpringAiService(インターフェース)

「質問を受け取り、回答を返す」という処理内容だけを定義したインターフェースです。

SpringAiService.java
package com.example.springaisample;

public interface SpringAiService {
    Answer askQuestion(Question question);
}

2.3 SpringAiSample02Service(実装)

Gemini とのやり取りを行う実装クラスです。中身は前回のコントローラーにあった処理とほぼ同じで、置き場所がServiceクラスに変わっただけです。

SpringAiSample02Service.java
package com.example.springaisample;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;

@Service
public class SpringAiSample02Service implements SpringAiService {

    private final ChatClient chatClient;

    public SpringAiSample02Service(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    @Override
    public Answer askQuestion(Question question) {
        var answerText = chatClient.prompt()
                .user(question.question())
                .call()
                .content();
        return new Answer(answerText);
    }
}

@Service を付けることで、Spring のDIコンテナに SpringAiService の実装として登録されます。コンストラクタで受け取る ChatClient.Builder は、前回同様 Spring AI が自動構成してくれるものです。

2.4 AskController

前回の @GetMapping の代わりに @PostMapping を使い、クエリパラメータの代わりに @RequestBody でJSONボディを受け取ります。

AskController.java
package com.example.springaisample;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AskController {

    private final SpringAiService springAiService;

    public AskController(SpringAiService springAiService) {
        this.springAiService = springAiService;
    }

    @PostMapping(path = "/ask", produces = "application/json")
    public Answer ask(@RequestBody Question question) {
        return springAiService.askQuestion(question);
    }
}

コントローラーは SpringAiService(インターフェース)にだけ依存しており、Gemini を呼んでいることすら知りません。これがService層に切り出したメリットです。

2.5 SpringAiSample02Application(自動生成)

Spring Initializr / Eclipseのプロジェクト作成時に自動生成されるエントリーポイントです。特に変更はありません。

SpringAiSample02Application.java
package com.example.springaisample;

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

@SpringBootApplication
public class SpringAiSample02Application {

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

ソースコードは下記を参照してください。

3. 実行

Eclipseから「Spring Boot アプリケーション」として実行します。

image.png

起動できたら、ターミナルから curl でPOSTリクエストを送ってみます。

curl localhost:8080/ask \
    -H"Content-type: application/json" \
    -d'{"question":"なぜ、犬はおなかを見せるのでしょうか?"}'

以下のように、JSON形式で回答が返ってきます。

image.png

まとめ

今回は、前回作成した最小構成を以下の2点で書き換えました。

  • GET+クエリパラメータ → POST+JSONボディ
  • コントローラー直書き → インターフェース+実装によるService層への切り出し

ChatClient を扱う部分がServiceクラスに閉じ込められたことで、コントローラー側はGeminiを使っていることすら意識しない、見通しの良い構成になりました。

参考

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?