Add AbstractApiFactory

This commit is contained in:
2025-09-07 01:41:47 +05:00
parent 413b1293a8
commit 77b8602a0a
3 changed files with 88 additions and 43 deletions

View File

@ -1,9 +1,6 @@
package com.backend.vue.bff.service.config;
import java.util.List;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
@ -13,11 +10,10 @@ import org.springframework.context.annotation.Lazy;
import com.backend.search.kodik.ApiClient;
import com.backend.search.kodik.JSON;
import com.backend.search.kodik.api.SearchControllerApi;
import com.backend.vue.bff.service.exception.ServiceUnavailableException;
import com.backend.vue.bff.service.factory.AbstractApiFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import retrofit2.Retrofit;
import retrofit2.converter.jackson.JacksonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
import retrofit2.Retrofit.Builder;
@Configuration
@EnableDiscoveryClient
@ -32,7 +28,7 @@ public class SearchApiClientConfiguration {
@Bean
@Lazy
public FactoryBean<ApiClient> apiClientFactory() {
return new ApiClientFactoryBean();
return new ApiClientFactoryBean(discoveryClient);
}
@Bean
@ -41,23 +37,9 @@ public class SearchApiClientConfiguration {
return apiClient.createService(SearchControllerApi.class);
}
private class ApiClientFactoryBean implements FactoryBean<ApiClient> {
@Override
public ApiClient getObject() throws Exception {
ApiClient client = new ApiClient();
String baseUrl = resolveServiceUrl("ANYAME-KODIK-SEARCH-BACKEND");
JSON json = new JSON();
Retrofit.Builder adapterBuilder = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(JacksonConverterFactory.create(json.getMapper()));
client.setAdapterBuilder(adapterBuilder);
return client;
private static class ApiClientFactoryBean extends AbstractApiFactory<ApiClient> {
public ApiClientFactoryBean(DiscoveryClient discoveryClient) {
super(discoveryClient, "ANYAME-KODIK-SEARCH-BACKEND");
}
@Override
@ -66,25 +48,19 @@ public class SearchApiClientConfiguration {
}
@Override
public boolean isSingleton() {
return true;
public ObjectMapper createObjectMapper() {
JSON json = new JSON();
return json.getMapper();
}
private String resolveServiceUrl(String serviceName) {
List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
@Override
public ApiClient createApiClient() {
return new ApiClient();
}
if (instances.isEmpty()) {
throw new ServiceUnavailableException();
}
ServiceInstance instance = instances.get(0);
String baseUrl = instance.getUri().toString();
if (!baseUrl.endsWith("/")) {
baseUrl = baseUrl + "/";
}
return baseUrl;
@Override
protected void updateAdapterBuilder(ApiClient instance, Builder adapterBuilder) {
instance.setAdapterBuilder(adapterBuilder);
}
}
}

View File

@ -4,6 +4,7 @@ import java.io.IOException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.backend.search.kodik.api.SearchControllerApi;
@ -17,8 +18,8 @@ public class TestController {
}
@GetMapping("/test")
public String test() throws IOException {
public String test(@RequestParam(name = "title") String title) throws IOException {
SearchControllerApi api = controllerApiFactory.getObject();
return Integer.toString(api.search("Шарлотта").execute().body().getResults().size());
return Integer.toString(api.search(title).execute().body().getResults().size());
}
}

View File

@ -0,0 +1,68 @@
package com.backend.vue.bff.service.factory;
import java.util.List;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import com.backend.vue.bff.service.exception.ServiceUnavailableException;
import com.fasterxml.jackson.databind.ObjectMapper;
import retrofit2.Retrofit;
import retrofit2.converter.jackson.JacksonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
public abstract class AbstractApiFactory<T> implements FactoryBean<T> {
private final DiscoveryClient discoveryClient;
private final String serviceId;
public AbstractApiFactory(DiscoveryClient discoveryClient, String serviceId) {
this.discoveryClient = discoveryClient;
this.serviceId = serviceId;
}
@Override
public T getObject() throws Exception {
T client = createApiClient();
String baseUrl = resolveServiceUrl(serviceId);
Retrofit.Builder adapterBuilder = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(JacksonConverterFactory.create(createObjectMapper()));
updateAdapterBuilder(client, adapterBuilder);
return client;
}
@Override
public boolean isSingleton() {
return true;
}
private String resolveServiceUrl(String serviceName) {
List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
if (instances.isEmpty()) {
throw new ServiceUnavailableException();
}
ServiceInstance instance = instances.get(0);
String baseUrl = instance.getUri().toString();
if (!baseUrl.endsWith("/")) {
baseUrl = baseUrl + "/";
}
return baseUrl;
}
public abstract ObjectMapper createObjectMapper();
public abstract T createApiClient();
protected abstract void updateAdapterBuilder(T instance, Retrofit.Builder adapterBuilder);
}