mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-08 04:39:00 +08:00
fix(feign): 修复 HttpMessageConverterCustomizer 的 UnsupportedOperationException
This commit is contained in:
1 parent
e88b2818fd
commit
e80b4f0b28
3 files changed
+312
-193
No files matched your search
+93
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2026, lengleng All rights reserved.
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@@ -17,8 +17,10 @@
|
||||
|
||||
package com.pig4cloud.pigx.common.feign;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.pig4cloud.pigx.common.feign.endpoint.FeignClientEndpoint;
|
||||
import com.pig4cloud.pigx.common.feign.interceptor.PigxFeignInnerRequestInterceptor;
|
||||
import com.pig4cloud.pigx.common.feign.interceptor.PigxFeignLanguageInterceptor;
|
||||
import com.pig4cloud.pigx.common.feign.interceptor.PigxFeignRequestCloseInterceptor;
|
||||
import feign.Feign;
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
|
||||
@@ -27,27 +29,49 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.cloud.openfeign.PigxFeignClientsRegistrar;
|
||||
import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
||||
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* Feign 客户端自动化配置
|
||||
* <p>
|
||||
* 提供 Feign 客户端的核心配置,包括:
|
||||
* <ul>
|
||||
* <li>Jackson 2 消息转换器配置 - 确保与 Spring MVC 使用相同的序列化机制</li>
|
||||
* <li>请求拦截器 - 添加内部调用标识、语言标头、连接关闭标头</li>
|
||||
* <li>Actuator 端点 - 提供 Feign 客户端监控能力</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* <b>重要说明</b>:本项目使用 Jackson 2.x 而非 Spring Boot 4 默认的 Jackson 3.x,
|
||||
* 因此必须显式配置 Feign 使用 Jackson 2 的 ObjectMapper,否则会导致服务间调用时的序列化/反序列化错误。
|
||||
*
|
||||
* @author lengleng
|
||||
* @date 2020/2/8
|
||||
* <p>
|
||||
* feign 自动化配置
|
||||
* @see HttpMessageConverterCustomizer
|
||||
* @see PigxFeignInnerRequestInterceptor
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(Feign.class)
|
||||
@Import(PigxFeignClientsRegistrar.class)
|
||||
@AutoConfigureAfter(EnableFeignClients.class)
|
||||
@SuppressWarnings("removal")
|
||||
public class PigxFeignAutoConfiguration {
|
||||
|
||||
/**
|
||||
* feign actuator endpoint
|
||||
* @param context
|
||||
* @return FeignClientEndpoint
|
||||
* Feign 客户端监控端点
|
||||
* <p>
|
||||
* 提供 Actuator 端点用于监控和管理 Feign 客户端,可以查看已注册的 Feign 客户端列表及其配置信息。
|
||||
* 仅在 Actuator 可用且端点启用时才会创建此 Bean。
|
||||
*
|
||||
* @param context Spring 应用上下文
|
||||
* @return FeignClientEndpoint 实例
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@@ -56,6 +80,59 @@ public class PigxFeignAutoConfiguration {
|
||||
return new FeignClientEndpoint(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置 Feign 使用 Jackson 2 消息转换器
|
||||
* <p>
|
||||
* <b>问题背景</b>:Spring Boot 4 默认使用 Jackson 3.x,但本项目为了兼容性使用 Jackson 2.x。
|
||||
* 如果不显式配置,Feign 客户端会使用默认的 Jackson 3 进行序列化/反序列化,
|
||||
* 导致与使用 Jackson 2 的 Spring MVC 之间出现数据格式不一致的问题。
|
||||
* <p>
|
||||
* <b>典型错误</b>:
|
||||
* <pre>
|
||||
* Cannot deserialize value of type `java.time.LocalDateTime` from String "2019-05-15 00:00:00"
|
||||
* </pre>
|
||||
* <p>
|
||||
* <b>解决方案</b>:通过 {@link HttpMessageConverterCustomizer} 在 Feign 初始化时:
|
||||
* <ol>
|
||||
* <li>原地把 Jackson 3 的 {@link JacksonJsonHttpMessageConverter} 替换成
|
||||
* 使用 Spring 装配好的 ObjectMapper 的 Jackson 2 转换器</li>
|
||||
* <li>找不到 Jackson 3 转换器时把 Jackson 2 转换器插入队首作为兜底</li>
|
||||
* <li>保留 byte[]、String、multipart 等其它默认转换器,避免破坏文件下载/上传等非 JSON 调用</li>
|
||||
* <li>注入的 ObjectMapper 已被所有 {@code Jackson2ObjectMapperBuilderCustomizer}
|
||||
* (包括 pigx-common-xss 的反序列化清洗)处理过,Feign 与 Spring MVC 序列化行为完全一致</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* <b>注意</b>:此配置使用了已标记为 removal 的 API({@code MappingJackson2HttpMessageConverter}),
|
||||
* 这是有意为之,因为项目需要使用 Jackson 2 而非 Jackson 3。
|
||||
* <p>
|
||||
* <b>不使用 {@link ConditionalOnMissingBean}</b>:{@code HttpMessageConverterCustomizer}
|
||||
* 是可叠加的扩展点,OpenFeign 等模块可能已注册其它 customizer;如果加上 missing-bean 条件,
|
||||
* 本 Bean 会被静默跳过,Jackson 2 修复消失。
|
||||
*
|
||||
* @param objectMapper Spring 装配好的 Jackson 2 ObjectMapper(来自 JacksonConfiguration 的 customizer 链)
|
||||
* @return HttpMessageConverterCustomizer 实例
|
||||
* @see com.pig4cloud.pigx.common.core.config.JacksonConfiguration
|
||||
* @see com.pig4cloud.pigx.common.core.jackson.PigxJavaTimeModule
|
||||
*/
|
||||
@Bean
|
||||
public HttpMessageConverterCustomizer pigxFeignJackson2Customizer(ObjectMapper objectMapper) {
|
||||
return converters -> {
|
||||
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter jackson2Converter =
|
||||
new org.springframework.http.converter.json.MappingJackson2HttpMessageConverter(objectMapper);
|
||||
ListIterator<HttpMessageConverter<?>> it = converters.listIterator();
|
||||
boolean replaced = false;
|
||||
while (it.hasNext()) {
|
||||
if (it.next() instanceof JacksonJsonHttpMessageConverter) {
|
||||
it.set(jackson2Converter);
|
||||
replaced = true;
|
||||
}
|
||||
}
|
||||
if (!replaced) {
|
||||
converters.add(0, jackson2Converter);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* add http connection close header
|
||||
*
|
||||
@@ -75,4 +152,14 @@ public class PigxFeignAutoConfiguration {
|
||||
public PigxFeignInnerRequestInterceptor pigFeignInnerRequestInterceptor() {
|
||||
return new PigxFeignInnerRequestInterceptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* add accept-language header
|
||||
*
|
||||
* @return PigxFeignLanguageInterceptor
|
||||
*/
|
||||
@Bean
|
||||
public PigxFeignLanguageInterceptor pigxFeignLanguageInterceptor() {
|
||||
return new PigxFeignLanguageInterceptor();
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.pig4cloud.pigx.common.feign.interceptor;
|
||||
|
||||
import com.pig4cloud.pigx.common.core.util.WebUtils;
|
||||
import feign.RequestInterceptor;
|
||||
import feign.RequestTemplate;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2025/3/26
|
||||
* <p>
|
||||
* feign 语言环境透传拦截器
|
||||
*/
|
||||
public class PigxFeignLanguageInterceptor implements RequestInterceptor {
|
||||
|
||||
@Override
|
||||
public void apply(RequestTemplate template) {
|
||||
HttpServletRequest request = WebUtils.getRequest();
|
||||
if (request == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String language = request.getHeader(HttpHeaders.ACCEPT_LANGUAGE);
|
||||
if (StringUtils.hasText(language)) {
|
||||
template.header(HttpHeaders.ACCEPT_LANGUAGE, language);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+188
-187
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2026, lengleng All rights reserved.
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@@ -46,229 +46,230 @@ import java.util.Map;
|
||||
* feign 自动配置功能 from mica
|
||||
*/
|
||||
public class PigxFeignClientsRegistrar
|
||||
implements ImportBeanDefinitionRegistrar, BeanClassLoaderAware, EnvironmentAware {
|
||||
implements ImportBeanDefinitionRegistrar, BeanClassLoaderAware, EnvironmentAware {
|
||||
|
||||
private final static String BASE_URL = "http://127.0.0.1:${server.port}${server.servlet.context-path}";
|
||||
private final static String BASE_URL = "http://127.0.0.1:${server.port}${server.servlet.context-path}";
|
||||
|
||||
@Getter
|
||||
private ClassLoader beanClassLoader;
|
||||
@Getter
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
@Getter
|
||||
private Environment environment;
|
||||
@Getter
|
||||
private Environment environment;
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
|
||||
registerFeignClients(registry);
|
||||
}
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
|
||||
registerFeignClients(registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
private void registerFeignClients(BeanDefinitionRegistry registry) {
|
||||
List<String> feignClients = new ArrayList<>();
|
||||
private void registerFeignClients(BeanDefinitionRegistry registry) {
|
||||
List<String> feignClients = new ArrayList<>();
|
||||
|
||||
// 支持 springboot 2.7 + 最新版本的配置方式
|
||||
ImportCandidates.load(FeignClient.class, getBeanClassLoader()).forEach(feignClients::add);
|
||||
// 支持 springboot 2.7 + 最新版本的配置方式
|
||||
ImportCandidates.load(FeignClient.class, getBeanClassLoader()).forEach(feignClients::add);
|
||||
|
||||
// 如果 spring.factories 里为空
|
||||
if (feignClients.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (String className : feignClients) {
|
||||
try {
|
||||
Class<?> clazz = beanClassLoader.loadClass(className);
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(clazz,
|
||||
FeignClient.class);
|
||||
if (attributes == null) {
|
||||
continue;
|
||||
}
|
||||
// 如果 spring.factories 里为空
|
||||
if (feignClients.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (String className : feignClients) {
|
||||
try {
|
||||
Class<?> clazz = beanClassLoader.loadClass(className);
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(clazz,
|
||||
FeignClient.class);
|
||||
if (attributes == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 如果是单体项目自动注入 & url 为空
|
||||
Boolean isMicro = environment.getProperty("spring.cloud.nacos.discovery.enabled", Boolean.class, true);
|
||||
// 如果已经存在该 bean,支持原生的 Feign
|
||||
if (registry.containsBeanDefinition(className) && isMicro) {
|
||||
continue;
|
||||
}
|
||||
// 如果是单体项目自动注入 & url 为空
|
||||
Boolean isMicro = environment.getProperty("spring.cloud.nacos.discovery.enabled", Boolean.class, true);
|
||||
// 如果已经存在该 bean,支持原生的 Feign
|
||||
if (registry.containsBeanDefinition(className) && isMicro) {
|
||||
continue;
|
||||
}
|
||||
|
||||
registerClientConfiguration(registry, getClientName(attributes), className,
|
||||
attributes.get("configuration"));
|
||||
registerClientConfiguration(registry, getClientName(attributes), className,
|
||||
attributes.get("configuration"));
|
||||
|
||||
validate(attributes);
|
||||
BeanDefinitionBuilder definition = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(FeignClientFactoryBean.class);
|
||||
definition.addPropertyValue("url", getUrl(attributes));
|
||||
definition.addPropertyValue("path", getPath(attributes));
|
||||
String name = getName(attributes);
|
||||
definition.addPropertyValue("name", name);
|
||||
validate(attributes);
|
||||
BeanDefinitionBuilder definition = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(FeignClientFactoryBean.class);
|
||||
definition.addPropertyValue("url", getUrl(attributes));
|
||||
definition.addPropertyValue("path", getPath(attributes));
|
||||
String name = getName(attributes);
|
||||
definition.addPropertyValue("name", name);
|
||||
|
||||
// 兼容最新版本的 spring-cloud-openfeign,尚未发布
|
||||
StringBuilder aliasBuilder = new StringBuilder(18);
|
||||
if (attributes.containsKey("contextId")) {
|
||||
String contextId = getContextId(attributes);
|
||||
aliasBuilder.append(contextId);
|
||||
definition.addPropertyValue("contextId", contextId);
|
||||
} else {
|
||||
aliasBuilder.append(name);
|
||||
}
|
||||
// 兼容最新版本的 spring-cloud-openfeign,尚未发布
|
||||
StringBuilder aliasBuilder = new StringBuilder(18);
|
||||
if (attributes.containsKey("contextId")) {
|
||||
String contextId = getContextId(attributes);
|
||||
aliasBuilder.append(contextId);
|
||||
definition.addPropertyValue("contextId", contextId);
|
||||
}
|
||||
else {
|
||||
aliasBuilder.append(name);
|
||||
}
|
||||
|
||||
definition.addPropertyValue("type", className);
|
||||
definition.addPropertyValue("dismiss404",
|
||||
Boolean.parseBoolean(String.valueOf(attributes.get("dismiss404"))));
|
||||
Object fallbackFactory = attributes.get("fallbackFactory");
|
||||
if (fallbackFactory != null) {
|
||||
definition.addPropertyValue("fallbackFactory", fallbackFactory instanceof Class ? fallbackFactory
|
||||
: ClassUtils.resolveClassName(fallbackFactory.toString(), null));
|
||||
}
|
||||
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
|
||||
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
|
||||
definition.addPropertyValue("type", className);
|
||||
definition.addPropertyValue("dismiss404",
|
||||
Boolean.parseBoolean(String.valueOf(attributes.get("dismiss404"))));
|
||||
Object fallbackFactory = attributes.get("fallbackFactory");
|
||||
if (fallbackFactory != null) {
|
||||
definition.addPropertyValue("fallbackFactory", fallbackFactory instanceof Class ? fallbackFactory
|
||||
: ClassUtils.resolveClassName(fallbackFactory.toString(), null));
|
||||
}
|
||||
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
|
||||
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
|
||||
|
||||
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
|
||||
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
|
||||
|
||||
// alias
|
||||
String alias = aliasBuilder.append("FeignClient").toString();
|
||||
// alias
|
||||
String alias = aliasBuilder.append("FeignClient").toString();
|
||||
|
||||
// has a default, won't be null
|
||||
boolean primary = (Boolean) attributes.get("primary");
|
||||
// has a default, won't be null
|
||||
boolean primary = (Boolean) attributes.get("primary");
|
||||
|
||||
beanDefinition.setPrimary(primary);
|
||||
beanDefinition.setPrimary(primary);
|
||||
|
||||
String qualifier = getQualifier(attributes);
|
||||
if (StringUtils.hasText(qualifier)) {
|
||||
alias = qualifier;
|
||||
}
|
||||
String qualifier = getQualifier(attributes);
|
||||
if (StringUtils.hasText(qualifier)) {
|
||||
alias = qualifier;
|
||||
}
|
||||
|
||||
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className,
|
||||
new String[]{alias});
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
|
||||
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className,
|
||||
new String[] { alias });
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validate(Map<String, Object> attributes) {
|
||||
AnnotationAttributes annotation = AnnotationAttributes.fromMap(attributes);
|
||||
// This blows up if an aliased property is overspecified
|
||||
FeignClientsRegistrar.validateFallback(annotation.getClass("fallback"));
|
||||
FeignClientsRegistrar.validateFallbackFactory(annotation.getClass("fallbackFactory"));
|
||||
}
|
||||
|
||||
private void validate(Map<String, Object> attributes) {
|
||||
AnnotationAttributes annotation = AnnotationAttributes.fromMap(attributes);
|
||||
// This blows up if an aliased property is overspecified
|
||||
FeignClientsRegistrar.validateFallback(annotation.getClass("fallback"));
|
||||
FeignClientsRegistrar.validateFallbackFactory(annotation.getClass("fallbackFactory"));
|
||||
}
|
||||
private String getName(Map<String, Object> attributes) {
|
||||
String name = (String) attributes.get("serviceId");
|
||||
if (!StringUtils.hasText(name)) {
|
||||
name = (String) attributes.get("name");
|
||||
}
|
||||
if (!StringUtils.hasText(name)) {
|
||||
name = (String) attributes.get("value");
|
||||
}
|
||||
name = resolve(name);
|
||||
return FeignClientsRegistrar.getName(name);
|
||||
}
|
||||
|
||||
private String getName(Map<String, Object> attributes) {
|
||||
String name = (String) attributes.get("serviceId");
|
||||
if (!StringUtils.hasText(name)) {
|
||||
name = (String) attributes.get("name");
|
||||
}
|
||||
if (!StringUtils.hasText(name)) {
|
||||
name = (String) attributes.get("value");
|
||||
}
|
||||
name = resolve(name);
|
||||
return FeignClientsRegistrar.getName(name);
|
||||
}
|
||||
private String getContextId(Map<String, Object> attributes) {
|
||||
String contextId = (String) attributes.get("contextId");
|
||||
if (!StringUtils.hasText(contextId)) {
|
||||
return getName(attributes);
|
||||
}
|
||||
|
||||
private String getContextId(Map<String, Object> attributes) {
|
||||
String contextId = (String) attributes.get("contextId");
|
||||
if (!StringUtils.hasText(contextId)) {
|
||||
return getName(attributes);
|
||||
}
|
||||
contextId = resolve(contextId);
|
||||
return FeignClientsRegistrar.getName(contextId);
|
||||
}
|
||||
|
||||
contextId = resolve(contextId);
|
||||
return FeignClientsRegistrar.getName(contextId);
|
||||
}
|
||||
private String resolve(String value) {
|
||||
if (StringUtils.hasText(value)) {
|
||||
return this.environment.resolvePlaceholders(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private String resolve(String value) {
|
||||
if (StringUtils.hasText(value)) {
|
||||
return this.environment.resolvePlaceholders(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
private String getUrl(Map<String, Object> attributes) {
|
||||
|
||||
// 如果是单体项目自动注入 & url 为空
|
||||
Boolean isMicro = environment.getProperty("spring.cloud.nacos.discovery.enabled", Boolean.class, true);
|
||||
|
||||
private String getUrl(Map<String, Object> attributes) {
|
||||
if (isMicro) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 如果是单体项目自动注入 & url 为空
|
||||
Boolean isMicro = environment.getProperty("spring.cloud.nacos.discovery.enabled", Boolean.class, true);
|
||||
Object objUrl = attributes.get("url");
|
||||
|
||||
if (isMicro) {
|
||||
return null;
|
||||
}
|
||||
String url = "";
|
||||
if (StringUtils.hasText(objUrl.toString())) {
|
||||
url = resolve(objUrl.toString());
|
||||
}
|
||||
else {
|
||||
url = resolve(BASE_URL);
|
||||
}
|
||||
|
||||
Object objUrl = attributes.get("url");
|
||||
return FeignClientsRegistrar.getUrl(url);
|
||||
}
|
||||
|
||||
String url = "";
|
||||
if (StringUtils.hasText(objUrl.toString())) {
|
||||
url = resolve(objUrl.toString());
|
||||
} else {
|
||||
url = resolve(BASE_URL);
|
||||
}
|
||||
private String getPath(Map<String, Object> attributes) {
|
||||
String path = resolve((String) attributes.get("path"));
|
||||
return FeignClientsRegistrar.getPath(path);
|
||||
}
|
||||
|
||||
return FeignClientsRegistrar.getUrl(url);
|
||||
}
|
||||
@Nullable
|
||||
private String getQualifier(@Nullable Map<String, Object> client) {
|
||||
if (client == null) {
|
||||
return null;
|
||||
}
|
||||
String qualifier = (String) client.get("qualifier");
|
||||
if (StringUtils.hasText(qualifier)) {
|
||||
return qualifier;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getPath(Map<String, Object> attributes) {
|
||||
String path = resolve((String) attributes.get("path"));
|
||||
return FeignClientsRegistrar.getPath(path);
|
||||
}
|
||||
@Nullable
|
||||
private String getClientName(@Nullable Map<String, Object> client) {
|
||||
if (client == null) {
|
||||
return null;
|
||||
}
|
||||
String value = (String) client.get("contextId");
|
||||
if (!StringUtils.hasText(value)) {
|
||||
value = (String) client.get("value");
|
||||
}
|
||||
if (!StringUtils.hasText(value)) {
|
||||
value = (String) client.get("name");
|
||||
}
|
||||
if (!StringUtils.hasText(value)) {
|
||||
value = (String) client.get("serviceId");
|
||||
}
|
||||
if (StringUtils.hasText(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getQualifier(@Nullable Map<String, Object> client) {
|
||||
if (client == null) {
|
||||
return null;
|
||||
}
|
||||
String qualifier = (String) client.get("qualifier");
|
||||
if (StringUtils.hasText(qualifier)) {
|
||||
return qualifier;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
"Either 'name' or 'value' must be provided in @" + FeignClient.class.getSimpleName());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getClientName(@Nullable Map<String, Object> client) {
|
||||
if (client == null) {
|
||||
return null;
|
||||
}
|
||||
String value = (String) client.get("contextId");
|
||||
if (!StringUtils.hasText(value)) {
|
||||
value = (String) client.get("value");
|
||||
}
|
||||
if (!StringUtils.hasText(value)) {
|
||||
value = (String) client.get("name");
|
||||
}
|
||||
if (!StringUtils.hasText(value)) {
|
||||
value = (String) client.get("serviceId");
|
||||
}
|
||||
if (StringUtils.hasText(value)) {
|
||||
return value;
|
||||
}
|
||||
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class);
|
||||
builder.addConstructorArgValue(name);
|
||||
builder.addConstructorArgValue(configuration);
|
||||
registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(),
|
||||
builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
throw new IllegalStateException(
|
||||
"Either 'name' or 'value' must be provided in @" + FeignClient.class.getSimpleName());
|
||||
}
|
||||
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object className,
|
||||
Object configuration) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class);
|
||||
builder.addConstructorArgValue(name);
|
||||
builder.addConstructorArgValue(className);
|
||||
builder.addConstructorArgValue(configuration);
|
||||
registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(),
|
||||
builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class);
|
||||
builder.addConstructorArgValue(name);
|
||||
builder.addConstructorArgValue(configuration);
|
||||
registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(),
|
||||
builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object className,
|
||||
Object configuration) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class);
|
||||
builder.addConstructorArgValue(name);
|
||||
builder.addConstructorArgValue(className);
|
||||
builder.addConstructorArgValue(configuration);
|
||||
registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(),
|
||||
builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user