R e i - D r e a m
for Laravel
Guest
login

最終投稿日:2026年09月20日

APIの基本(クライアント)

接続設定

APIクライアントの場合は、他サーバに対してリクエストを送る仕組みとなります。
よって『api-config.properties』を作り、そこに各種接続設定を記述します。
作成する場所は『resources』以降であれば任意ですが『META-INF』直下に作成します。
src/main/resources/META-INF/api-config.properties

# APIclient各種設定
# タイムアウト設定
CONNECT_TIMEOUT=5
READ_TIMEOUT=10

# 接続先 URL
KEIYAKU_BASE_URI_DEVELOP=http://localhost/laravel_12/api/v1/
KEIYAKU_BASE_URI=https://reidream.net/laravel_12/api/v1/

# 各種APIエンドポイント
KEIYAKU_INFO_END-POINT_DEVELOP=keiyaku_info
KEIYAKU_INFO_END-POINT=keiyaku_info

○ 設定内容
● CONNECT_TIMEOUT
他サーバに接続するために待機できる最大の時間(秒)
● READ_TIMEOUT
他サーバに接続後に待機できる最大の時間(秒)
● KEIYAKU_BASE_URI_XXXXX
他サーバに接続するためのベースのURLとなります。
2種類あるのは『開発』『本番』用を分けるためです。
● KEIYAKU_INFO_END-POINT_XXXXX
他サーバに接続するための個別のエンドポイントとなります。
2種類あるのは『開発』『本番』用を分けるためです。

接続設定ファイル読込み

先ほど作成した『api-config.properties』を読込む必要があります。
ただ、個々のAPIクライアントクラスで読込むのは非効率となります。
そこで基底クラス『BaseApiClient』を作成します。
src\main\java\api\client\BaseApiClient.java

package api.client;

import java.util.ResourceBundle;
import java.util.concurrent.TimeUnit;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;

public class BaseApiClient {
    protected ResourceBundle apiConf;
    protected Client client;
    
    @PostConstruct
    public void init() {
        // [api-config.properties]ファイルを読込む
        apiConf = ResourceBundle.getBundle("META-INF.api-config");
        // clientインスタンスをタイムアウト設定込みで生成する
        client = ClientBuilder.newBuilder()
            .connectTimeout(Long.parseLong(apiConf.getString("CONNECT_TIMEOUT")), TimeUnit.SECONDS)
            .readTimeout(Long.parseLong(apiConf.getString("READ_TIMEOUT")), TimeUnit.SECONDS)
            .build();
    }
    @PreDestroy
    public void destroy() {
        // クラス全体が破棄されたタイミングで、clientインスタンスをクローズする
        if (this.client != null) {
            this.client.close();
            // デバッグ確認用ログ(不要になれば削除してください)
        }
    }
}

『api-config.properties』を読込む基底クラスとなります。
また、ついでに『タイムアウト設定を含んだclientインスタンス』『自動インスタンスクローズ』の設定もしています。
では作成した『APIクライアント』を呼び出すメソッドを任意のクラスに書いてみましょう。
まぁ画面から操作するのが簡単なので『SampleBean.java』に作成します。
SampleBean.java

@Inject
private KeiyakuClient keiyakuClient;
~ 省略 ~
public void submit() {
    keiyakuClient.apiKeiyakuInfo();
}

作成した内容はエラー状態ですが、今は問題ありません。

APIクライアント作成

それでは先ほどの『SampleBean.java』のエラーを解消するためにもクライアントクラスを作成しましょう。
src/main/java/api/client/KeiyakuClient.java

package api.client;

import java.net.SocketTimeoutException;
import config.AppConfig;
import jakarta.enterprise.context.RequestScoped;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

@RequestScoped
public class KeiyakuClient extends BaseApiClient {
    public void apiKeiyakuInfo() {
        String baseUri = AppConfig.get("KEIYAKU_BASE_URI");
        String ePoint = AppConfig.get("KEIYAKU_INFO_END-POINT");
        String fullUrl = apiConf.getString(baseUri) + apiConf.getString(ePoint);
        try {
            Response response = client.target(fullUrl).request(MediaType.APPLICATION_JSON).get();
            switch (response.getStatus()) {
            case 200:
                break;
            case 400:
                break;
            case 404:
                break;
            default:
                System.err.println("それ以外のコード");
            }
        } catch (ProcessingException e) {
            if (e.getCause() instanceof SocketTimeoutException) {
                System.err.println("タイムアウトが発生しました: " + e.getMessage());
            } else {
                System.err.println("通信時のその他の処理エラー: " + e.getMessage());
            }
        } catch (Exception e) {
            System.err.println("不明なエラー: " + e.getMessage());
        }
    }
}

まず大抵『String baseUri = AppConfig.get("KEIYAKU_BASE_URI");』でエラーになると思います。
『AppConfig』なんてクラスありませんよね。
実は【 動的環境設定】で解説しています。
この設定は『開発』『本番』環境を動的に振り分ける事ができるので、是非参考にしてください。
それでは『AppConfig』設定の通り『KEIYAKU_BASE_URI』『KEIYAKU_INFO_END-POINT』を設定する必要があります。
以下の様に設定してみましょう。
src/main/resources/META-INF/production/appinfo.properties

# API設定
KEIYAKU_BASE_URI=KEIYAKU_BASE_URI
KEIYAKU_INFO_END-POINT=KEIYAKU_INFO_END-POINT

※ 一見同じ値を設定してる様に見えますが『開発』用ファイルでは「KEIYAKU_BASE_URI_DEVELOP」の様な値を設定します
※ 動的環境設定をされていない場合は『AppConfig』から取得する内容を直接固定値に書き換えて下さい
○ この設定で以下の様に値が取得できます。
● String baseUri = AppConfig.get("KEIYAKU_BASE_URI");
『appinfo.properties』のKEY『KEIYAKU_BASE_URI』の値が取得できます。
● String ePoint = AppConfig.get("KEIYAKU_INFO_END-POINT");
『appinfo.properties』のKEY『KEIYAKU_INFO_END-POINT』の値が取得できます。
● String fullUrl = apiConf.getString(baseUri) + apiConf.getString(ePoint);
『api-config.properties』のKEY『KEIYAKU_BASE_URI』『KEIYAKU_INFO_END-POINT』の値を文字列結合して取得できます。
つまり、以下サーバにリクエストするための『URL』を作成しています。
    https://reidream.net/laravel_12/api/v1/keiyaku_info
● Response response = client.target(fullUrl).request(MediaType.APPLICATION_JSON).get();
JSON形式で他サーバにGET送信します。

API送信でパラメータを渡す方法

○ GET送信
『client.target(fullUrl).request(MediaType.APPLICATION_JSON).get();』に対し、メソッドチェーンを追加します。
例)
client.target(fullUrl)
    .queryParam("param1", "ほげ")
    .queryParam("param2", "ふ~")
    .request(MediaType.APPLICATION_JSON).get();
○ POST送信
『client.target(fullUrl).request(MediaType.APPLICATION_JSON).post(★);』の★にデータを格納します。
基本的にはJSONで送信し、渡し方は以下3種類あります。
① DTO
② Map型
③ JSON文字列
例)
Map mapData = new HashMap<>();
mapData.put("param1", "ほげ");
mapData.put("param2", "ふ~");
Response response = client.target(fullUrl)
    .request(MediaType.APPLICATION_JSON)
    .post(Entity.entity(mapData, MediaType.APPLICATION_JSON));
○ Headerにパラメータを渡す方法(GET,POST共通)
通常のパラメータ付与と同じ様にメソッドチェーンで繋げます。
例)
client.target(fullUrl)
    .queryParam("param1", "ほげ")
    .request(MediaType.APPLICATION_JSON)
    .header("Authorization", "Bearer your_token_here")
    .header("X-Custom-Header", "custom_value").get();
○ rawデータにJSON文字列を格納する
Postmanなどで見る『raw』データをしてAPI送信する方法です。
『.post(★)』引数★に直接JSON文字列を渡します。
例)
client.target(fullUrl)
    .request(MediaType.APPLICATION_JSON)
    .header("X-Custom-Header", "custom_value")
    .post(Entity.json("{\"raw_data\":\"ロウデータ\"}"));

API返却データを取得する方法

『Response response = client.target(fullUrl)...』でAPIリクエストしているので、当然『response』で取得します。
しかし色々と加工しないと参照できる状態にはなりません。
○ 文字列として参照する
JSONで返却される場合は、以下コードの様に『response』インスタンスからJSON文字列を取得できます。
    String body = response.readEntity(String.class);
ただし、APIサービス側の返却方法次第では日本語は『Unicode』になる場合があります。
その場合『JSON-B』を利用している場合は、簡単に変換できます。
《JSON-B》の場合

String body = response.readEntity(String.class);
Jsonb jsonb = JsonbBuilder.create();
Object result = jsonb.fromJson(body, Object.class);
System.out.println(result);

『Jackson』を利用している場合はもっと簡単に変換できます。
《Jackson》の場合

String body = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
System.out.println(span class="p">mapper.readValue(body, Object.class));

○ レスポンスHeader情報を参照する
● ステータスコードの取得([200]等)
int status = response.getStatus();
● ステータス情報の詳細取得([OK]等)
response.getStatusInfo().getReasonPhrase();
● レスポンスヘッダーの取得
String contentType = response.getHeaderString("Content-Type");
○ API返却データをDTOに詰替える方法
先ずは以下DTOを作成します。
ApiKeiyakuInfoDto

package dto;

import lombok.Data;
@Data
public class ApiKeiyakuInfoDto {
    private String message;
    private int id;
}

この場合、単純に以下1行でマッピングできます。
    ApiKeiyakuInfoDto result = response.readEntity(ApiKeiyakuInfoDto.class);
問題は、今回の様に返却値のKEY名とDTOのプロパティ名が合わない場合です。
例えば返却されるJSONの内容が以下とします。
    {"message":"成功", "id_no":123}
この場合DTOのプロパティ『private int id;』にマッピングされません。
ただしマッピングの場合、以下強力なアノテーションがあります。
ただしマッピングの場合、以下強力なアノテーションがあります。
【JSON-B】                       @JsonbProperty("id_no")
【Jackson】                      @JsonProperty("id_no")
このアノテーションは『JSON-B』モジュールを『pom.xml』で設定してる場合は問題ありません。
しかし『Jackson』を設定している場合は、マッピングされないのです。
原因はJAX-RS(Jakarta EE)の標準仕様が『JSON-B』である事に起因しています。
コード【response.readEntity(...)】が実行される際、内部では『JSON-B』の機能をコッソリ使っています。
そのためアノテーション『@JsonProperty』は無視されるのです。
ただし解決方法はあります! 少し行数は増えますが、以下の様に『Jackson』のマッピング機能を明示的に使用します。
String rawJson = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
ApiKeiyakuInfoDto result = mapper.readValue(rawJson, ApiKeiyakuInfoDto.class);
ログインしてコメントを残そう!!


きっぷる
きっぷる