取り組みの背景: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開発