APIの基本(クライアント)
接続設定
よって『api-config.properties』を作り、そこに各種接続設定を記述します。
作成する場所は『resources』以降であれば任意ですが『META-INF』直下に作成します。
# 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
2種類あるのは『開発』『本番』用を分けるためです。
2種類あるのは『開発』『本番』用を分けるためです。
接続設定ファイル読込み
ただ、個々のAPIクライアントクラスで読込むのは非効率となります。
そこで基底クラス『BaseApiClient』を作成します。
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();
// デバッグ確認用ログ(不要になれば削除してください)
}
}
}
また、ついでに『タイムアウト設定を含んだclientインスタンス』『自動インスタンスクローズ』の設定もしています。 では作成した『APIクライアント』を呼び出すメソッドを任意のクラスに書いてみましょう。
まぁ画面から操作するのが簡単なので『SampleBean.java』に作成します。
@Inject
private KeiyakuClient keiyakuClient;
~ 省略 ~
public void submit() {
keiyakuClient.apiKeiyakuInfo();
}
APIクライアント作成
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());
}
}
}
『AppConfig』なんてクラスありませんよね。 実は【 動的環境設定】で解説しています。
この設定は『開発』『本番』環境を動的に振り分ける事ができるので、是非参考にしてください。 それでは『AppConfig』設定の通り『KEIYAKU_BASE_URI』『KEIYAKU_INFO_END-POINT』を設定する必要があります。
以下の様に設定してみましょう。
# API設定
KEIYAKU_BASE_URI=KEIYAKU_BASE_URI
KEIYAKU_INFO_END-POINT=KEIYAKU_INFO_END-POINT
※ 動的環境設定をされていない場合は『AppConfig』から取得する内容を直接固定値に書き換えて下さい
つまり、以下サーバにリクエストするための『URL』を作成しています。
https://reidream.net/laravel_12/api/v1/keiyaku_info
API送信でパラメータを渡す方法
例)
.queryParam("param1", "ほげ")
.queryParam("param2", "ふ~")
.request(MediaType.APPLICATION_JSON).get();
基本的にはJSONで送信し、渡し方は以下3種類あります。
② Map型
③ JSON文字列
mapData.put("param1", "ほげ");
mapData.put("param2", "ふ~");
Response response = client.target(fullUrl)
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(mapData, MediaType.APPLICATION_JSON));
例)
.queryParam("param1", "ほげ")
.request(MediaType.APPLICATION_JSON)
.header("Authorization", "Bearer your_token_here")
.header("X-Custom-Header", "custom_value").get();
『.post(★)』引数★に直接JSON文字列を渡します。
例)
.request(MediaType.APPLICATION_JSON)
.header("X-Custom-Header", "custom_value")
.post(Entity.json("{\"raw_data\":\"ロウデータ\"}"));
API返却データを取得する方法
しかし色々と加工しないと参照できる状態にはなりません。
String body = response.readEntity(String.class); ただし、APIサービス側の返却方法次第では日本語は『Unicode』になる場合があります。
その場合『JSON-B』を利用している場合は、簡単に変換できます。
String body = response.readEntity(String.class);
Jsonb jsonb = JsonbBuilder.create();
Object result = jsonb.fromJson(body, Object.class);
System.out.println(result);
String body = response.readEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
System.out.println(span class="p">mapper.readValue(body, Object.class));
package dto;
import lombok.Data;
@Data
public class ApiKeiyakuInfoDto {
private String message;
private int id;
}
ApiKeiyakuInfoDto result = response.readEntity(ApiKeiyakuInfoDto.class); 問題は、今回の様に返却値のKEY名とDTOのプロパティ名が合わない場合です。
例えば返却されるJSONの内容が以下とします。
{"message":"成功", "id_no":123} この場合DTOのプロパティ『private int id;』にマッピングされません。
ただしマッピングの場合、以下強力なアノテーションがあります。
【Jackson】 @JsonProperty("id_no")
しかし『Jackson』を設定している場合は、マッピングされないのです。 原因はJAX-RS(Jakarta EE)の標準仕様が『JSON-B』である事に起因しています。
コード【response.readEntity(...)】が実行される際、内部では『JSON-B』の機能をコッソリ使っています。
そのためアノテーション『@JsonProperty』は無視されるのです。 ただし解決方法はあります! 少し行数は増えますが、以下の様に『Jackson』のマッピング機能を明示的に使用します。
ObjectMapper mapper = new ObjectMapper();
ApiKeiyakuInfoDto result = mapper.readValue(rawJson, ApiKeiyakuInfoDto.class);




