◉GEMINI LABEN
●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — deep-research-pro-preview-12-2025 は 10/23 に停止しました(本日)。移行先は deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●MCP — ツール結果が 8.5万トークンに膨らんだ事例を、ADK で 310 トークンに包んで抑えた報告が出ています●FLASH — gemini-3.7-flash と 3.5-flash は新しい Flash モデルに自動で回されます(10/08)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…●ARGON — gemini-4-argon が 10/13 に GA。複雑なコーディング・エージェント・数学・科学向けです●DEEP RES — deep-research-pro-preview-12-2025 は 10/23 に停止しました(本日)。移行先は deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 が GA(10/06)。gemini-3.1-flash-image は非推奨で停止日は未発表です●MCP — ツール結果が 8.5万トークンに膨らんだ事例を、ADK で 310 トークンに包んで抑えた報告が出ています●FLASH — gemini-3.7-flash と 3.5-flash は新しい Flash モデルに自動で回されます(10/08)●NEW — クラッシュ報告を毎回ゼロから読ませない — 既知バグ早見表を先に grep し…
記事一覧/API / SDK
◈ API / SDK/2026-04-01初級

Gemini APIをSpring Bootで活用する:JavaエンジニアのためのAIチャットアプリ開発入門

Spring BootとGemini APIを組み合わせてAIチャットAPIを構築する実践ガイド。Javaエンジニアがゼロからセットアップし、REST APIエンドポイントとしてGemini AIを統合する手順を丁寧に解説します。

gemini-api291spring-bootjavatutorial5rest-api

取り組みの背景:JavaエンジニアにこそGemini APIがおすすめな理由

AI機能をアプリケーションに組み込む際、Python一択というイメージをお持ちの方も多いかもしれません。しかし、企業の基幹システムやバックエンドサービスにはJavaとSpring Bootが今も広く採用されており、既存のJavaプロジェクトにGemini APIをシームレスに統合できれば、新たな言語を習得することなくAI機能を実現できます。

まずはGemini APIのキー取得から始める方は、Gemini API クイックスタート — Python/TypeScriptで始めるもあわせてご参照ください。


前提条件と環境準備

作業を始める前に、以下が準備できているか確認してください。

  • Java 17以上(LTS推奨)
  • Maven 3.8以上 または Gradle 8以上
  • Google AI Studio のアカウントとAPIキー
  • Spring Boot 3.2以上(本記事での確認バージョン)

Gemini APIキーの取得

Google AI Studio にアクセスし、「Get API Key」から新しいAPIキーを発行してください。キーは後ほどapplication.propertiesに設定します。


Spring Bootプロジェクトの作成と依存関係の設定

pom.xml の設定

Spring Initializr(start.spring.io)でプロジェクトを生成し、以下の依存関係を追加します。Gemini APIとの通信にはspring-boot-starter-webfluxのWebClientを使用します。

<!-- pom.xml (抜粋) -->
<dependencies>
  <!-- Spring Web MVC(REST APIの公開) -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
 
  <!-- WebClient(Gemini APIへのHTTP通信) -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
  </dependency>
 
  <!-- JSON処理 -->
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
  </dependency>
</dependencies>

application.properties の設定

APIキーを直接コードに埋め込まないよう、設定ファイルで管理します。

# src/main/resources/application.properties
 
# Gemini API設定
gemini.api.key=YOUR_GEMINI_API_KEY
gemini.api.url=https://generativelanguage.googleapis.com/v1beta
gemini.model=gemini-2.5-flash
 
# アプリケーション設定
spring.application.name=gemini-chat-api
server.port=8080

注意: YOUR_GEMINI_API_KEY の部分は実際のAPIキーに置き換えてください。本番環境では環境変数や Secret Manager を使用することを強く推奨します。


Gemini API クライアントの実装

設定クラス(GeminiConfig.java)

package com.example.geminichat.config;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
 
@Configuration
public class GeminiConfig {
 
    @Value("${gemini.api.url}")
    private String apiUrl;
 
    // WebClientをBeanとして登録
    @Bean
    public WebClient geminiWebClient() {
        return WebClient.builder()
                .baseUrl(apiUrl)
                .defaultHeader("Content-Type", "application/json")
                .build();
    }
}

リクエスト/レスポンスのデータクラス

Gemini APIが期待するJSONリクエスト形式に合わせてデータクラスを定義します。

package com.example.geminichat.model;
 
import java.util.List;
 
// チャットリクエスト(クライアントから受け取るJSON)
public record ChatRequest(String message) {}
 
// Gemini APIへ送信するリクエストボディ
public record GeminiRequest(List<Content> contents) {
    public record Content(List<Part> parts) {}
    public record Part(String text) {}
}
 
// Gemini APIからのレスポンス(簡略版)
public record GeminiResponse(List<Candidate> candidates) {
    public record Candidate(Content content) {}
    public record Content(List<Part> parts) {}
    public record Part(String text) {}
}
 
// クライアントへ返すレスポンス
public record ChatResponse(String reply, boolean success) {}

サービスクラス(GeminiService.java)

Gemini APIとの通信ロジックをサービス層に集約します。

package com.example.geminichat.service;
 
import com.example.geminichat.model.ChatResponse;
import com.example.geminichat.model.GeminiRequest;
import com.example.geminichat.model.GeminiResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
 
import java.util.List;
 
@Service
public class GeminiService {
 
    private final WebClient webClient;
 
    @Value("${gemini.api.key}")
    private String apiKey;
 
    @Value("${gemini.model}")
    private String model;
 
    public GeminiService(WebClient geminiWebClient) {
        this.webClient = geminiWebClient;
    }
 
    public ChatResponse chat(String userMessage) {
        // リクエストボディを構築
        var request = new GeminiRequest(
            List.of(new GeminiRequest.Content(
                List.of(new GeminiRequest.Part(userMessage))
            ))
        );
 
        try {
            // Gemini APIへPOSTリクエスト
            GeminiResponse response = webClient.post()
                    .uri("/models/{model}:generateContent?key={key}", model, apiKey)
                    .bodyValue(request)
                    .retrieve()
                    .bodyToMono(GeminiResponse.class)
                    .block(); // 同期呼び出し(本番ではreactive化推奨)
 
            // レスポンスからテキストを抽出
            if (response != null && !response.candidates().isEmpty()) {
                String text = response.candidates().get(0)
                        .content().parts().get(0).text();
                return new ChatResponse(text, true);
            }
            return new ChatResponse("応答が取得できませんでした", false);
 
        } catch (Exception e) {
            // エラーハンドリング(詳細は後述)
            return new ChatResponse("エラーが発生しました: " + e.getMessage(), false);
        }
    }
}

REST APIコントローラーの実装

package com.example.geminichat.controller;
 
import com.example.geminichat.model.ChatRequest;
import com.example.geminichat.model.ChatResponse;
import com.example.geminichat.service.GeminiService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
 
@RestController
@RequestMapping("/api/chat")
public class ChatController {
 
    private final GeminiService geminiService;
 
    public ChatController(GeminiService geminiService) {
        this.geminiService = geminiService;
    }
 
    // POST /api/chat
    @PostMapping
    public ResponseEntity<ChatResponse> chat(@RequestBody ChatRequest request) {
        if (request.message() == null || request.message().isBlank()) {
            return ResponseEntity.badRequest()
                    .body(new ChatResponse("メッセージを入力してください", false));
        }
 
        ChatResponse response = geminiService.chat(request.message());
        return ResponseEntity.ok(response);
    }
 
    // ヘルスチェック用
    @GetMapping("/health")
    public ResponseEntity<String> health() {
        return ResponseEntity.ok("Gemini Chat API is running!");
    }
}

動作確認

アプリケーションを起動し、curl で動作確認をしてみましょう。

# アプリケーション起動
./mvnw spring-boot:run
 
# チャットAPIへリクエスト送信
curl -X POST http://localhost:8080/api/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "Javaの特徴を3つ教えてください"}'

期待されるレスポンス例:

{
  "reply": "Javaの主な特徴は以下の3つです:\n1. **プラットフォーム非依存**: JVM(Java Virtual Machine)上で動作するため、一度書いたコードをOSに関わらず実行できます。\n2. **オブジェクト指向**: クラスと継承を中心とした設計で、大規模アプリケーションの保守性が高まります。\n3. **強力なエコシステム**: Spring BootやMavenなど、豊富なライブラリとフレームワークが利用できます。",
  "success": true
}

エラーハンドリングのベストプラクティスについては、Gemini API エラーハンドリング完全ガイドを参考にしてください。


本番環境へのステップアップ

1. System Instructionsで振る舞いをカスタマイズ

Gemini APIのリクエストにsystemInstructionを追加することで、AIの役割や回答スタイルを固定できます。

// GeminiRequestにsystemInstructionを追加する場合
public record GeminiRequest(
    List<Content> contents,
    SystemInstruction systemInstruction
) {
    public record SystemInstruction(List<Part> parts) {}
    // ... (他フィールドは同様)
}
 
// サービス側での利用例
var systemInstruction = new GeminiRequest.SystemInstruction(
    List.of(new GeminiRequest.Part(
        "あなたはJava開発の専門家です。質問に対して簡潔かつ正確に答えてください。"
    ))
);

プロダクション品質のシステムインストラクション設計については、Gemini 2.5 Pro システムインストラクション完全マスターでさらに詳しく解説しています。

2. コスト管理の設定

APIの利用コストを抑えるため、maxOutputTokensでレスポンスの最大トークン数を制限することを推奨します。詳細はGemini API コスト最適化 完全ガイドをご覧ください。

3. 非同期処理への移行


まとめ

ここではSpring BootとGemini APIを組み合わせてAIチャットRESTエンドポイントを構築する手順をご紹介しました。

  • spring-boot-starter-webfluxのWebClientでGemini APIに接続
  • application.propertiesでAPIキーとモデルを一元管理
  • Record型を活用したシンプルなデータモデル設計
  • サービス層にビジネスロジックを集約した保守しやすい設計

これをベースにマルチターン会話、RAGパターン、Function Callingと組み合わせることで、実用的な業務AIアシスタントへと発展させることができます。ぜひご自身のプロジェクトに取り入れてみてください。

Javaでの本格的なAI開発

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

◈ API / SDK2026-10-22
gemini-4-argon へ model を替える前に、自分のコードから消すものを探します
gemini-4-argon への移行で、明示キャッシュ・temperature 系・小さな max_output_tokens・短いタイムアウトの 4 つが問題になりうることを、公式の移行チェックリストから整理しました。自分のリポジトリから該当行を探す標準ライブラリだけの小さなスクリプトと、替えた後の確認点、Flash を据え置く判断も添えています。
◈ API / SDK2026-10-19
404 と 429 が同じログに並んだら、上限より先にモデル名を確かめます
Gemini API のログに 404 NOT_FOUND と 429 RESOURCE_EXHAUSTED が混ざって出たとき、どちらから疑うかの順番と、生成を伴わずに切り分ける最小の Python スクリプトをまとめます。
◈ API / SDK2026-10-16
models は 200 なのに generateContent だけ 403 になる日 — 切り分けの順番を先に決めておく
モデル一覧の取得は 200 で通るのに、生成リクエストだけが 403 permission_denied で止まるときの切り分け手順です。キー・プロジェクト・請求の順に確かめる小さな診断スクリプトと、リトライしてはいけない理由、サポートへ渡す材料の揃え方をまとめました。