当前位置:首页 > 服务端 > feign拦截器和解码器

feign拦截器和解码器

2022年11月09日 09:01:13服务端8

Feign拦截器和解码器

业务需求

在Spring Cloud的项目中,A服务使用Feign调用B服务的某个接口,如果需要传递全局认证token或参数,在方法参数里面加相应字段的方式显然是不可取的。

首先想到的是AOP方式,使用切面拦截Feign方法,在AOP切面里面向方法参数里面添加数据,Feign方法执行完成之后,从响应对象里面获取返回的数据,这样的方式可以解决数据的传递和接收,但也必将需要方法参数和响应对象的支持,与业务耦合,并不是合理的架构实现方案。

如果有某种机制可以拦截到Feign的请求对象和响应对象,便可以获取到请求头和响应头,就可以使用请求头和响应头来传递数据。

经过一番调查,了解到Feign的RequestInterceptor可以拦截到Feign请求,可以获取到请求对象和请求头,但是RequestInterceptor无法处理响应。

于是又进行调查,得知解码器Decoder是对响应进行解码的组件,可以获取到响应对象和响应头。

在调查过程中,还有另外的收获:FeignClientsConfiguration类。

FeignClientsConfiguration类

Feign默认配置类是FeignClientsConfiguration类,该类定义了Feign默认的编码器、解码器、所使用的契约等。

Spring Cloud允许通过注解@FeignClient的configuration属性自定义Feign配置,自定义配置的优先级比FeignClientsConfiguration要高。

这个类的核心代码如下:

@Configuration
public class FeignClientsConfiguration {
     

	@Autowired
	private ObjectFactory<HttpMessageConverters> messageConverters;

	@Autowired(required = false)
	private List<AnnotatedParameterProcessor> parameterProcessors = new ArrayList<>();

	@Autowired(required = false)
	private List<FeignFormatterRegistrar> feignFormatterRegistrars = new ArrayList<>();

	@Autowired(required = false)
	private Logger logger;

	@Bean
	@ConditionalOnMissingBean
	public Decoder feignDecoder() {
     
		return new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
	}

	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnMissingClass("org.springframework.data.domain.Pageable")
	public Encoder feignEncoder() {
     
		return new SpringEncoder(this.messageConverters);
	}

	@Bean
	@ConditionalOnMissingBean
	public Contract feignContract(ConversionService feignConversionService) {
     
		return new SpringMvcContract(this.parameterProcessors, feignConversionService);
	}

	@Bean
	@Scope("prototype")
	@ConditionalOnMissingBean
	public Feign.Builder feignBuilder(Retryer retryer) {
     
		return Feign.builder().retryer(retryer);
	}
}

Feign请求拦截器

参考FeignClientsConfiguration类,我们可以编写一个configuration类,注入自定义的RequestInterceptor实现类对象,在apply(RequestTemplate requestTemplate)方法中获取到请求RestTemplate对象,使用RequestTemplate对象设置请求参数、添加请求头。

示例如下:

@Configuration
public class MyConfig {
     
	@Bean("myInterceptor")
	public RequestInterceptor getRequestInterceptor() {
     
		return new MyClientInterceptor();
	}
}

MyClientInterceptor类:

class MyClientInterceptor implements RequestInterceptor {
     
	@Override
	public void apply(RequestTemplate requestTemplate) {
     
		requestTemplate.query("name", "Allen");
		requestTemplate
              .header("token", "token")
              .header("id", id);
	}
}

Feign解码器

解码器概述

Feign解码器负责对响应进行解码,返回符合Feign接口需求的对象。

我们可以参考FeignClientsConfiguration类中的方式编写和注入自定义的解码器。

@Bean
@ConditionalOnMissingBean
public Decoder feignDecoder() {
     
	return new OptionalDecoder(
			new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
}

继承SpringDecoder自定义解码器

class TraceDecoder extends SpringDecoder {
     

	TraceDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {
     
		super(messageConverters);
	}

	@Override
	public Object decode(Response response, Type type) throws IOException, FeignException {
     

		// 这里可以从response对象里面获取响应头和响应体

        // 获取响应头
		Map<String, Collection<String>> headers = response.headers();

		return super.decode(response, type);
	}
}

注入自定义解码器

feignDecoder()方法完全参考了FeignClientsConfiguration类的写法。

@Slf4j
@Configuration
@ConditionalOnClass({
     Feign.class})
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class CommonLogFeignConfig {
     

	@Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;

	@Bean
	public Decoder feignDecoder() {
     
		return new OptionalDecoder(new ResponseEntityDecoder(new TraceDecoder(this.messageConverters)));
	}
}

作者:xuguofeng2016
来源链接:https://blog.csdn.net/xuguofeng2016/article/details/122598807

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/server/68780.html

标签: Feign
分享给朋友:

“feign拦截器和解码器” 的相关文章

SpringCloud:Feign模块引用版本问题

java.io.FileNotFoundException: class path resource [org/springframework/boot/autoconfigure/web/ServerPropertiesAutoConfiguration.class] cannot...

SpringCloud笔记五:Feign

SpringCloud笔记五:Feign

目录 什么是Feign? 有了Ribbon我还要Feign干嘛? 新建consumer-feign 修改api项目 引入Maven文件 新建feign...

SpringCloud组件:Feign之日志输出

目录 Feign之日志输出 Feign日志输出说明 前期准备 构建项目 tairan-spring-cloud-feign-logger配置 源码位置 Feign之日志输出...

SpringCloud和Dubbo的区别及Dubbo和Feign远程调用的差异

SpringCloud和Dubbo的区别 SpringCloud和Dubbo有什么区别? 两者都是现在主流的微服务框架,但却存在不少差异: 初始定位不同:SpringCloud定位为微服务架构下的一站式解决方案;Dubbo 是...

SpringCloud Feign重试详解

SpringCloud Feign重试详解

摘要: 今天在生产环境发生了数据库进程卡死的现象,除了sql因为全量更新,没加索引的原因,最主要还是我们的接口的服务器端接口出现问题了。忽视了更新接口的幂等性,以及调用方feign client的重试,导致接口重复执行。万幸的是数据已经修复,花了几个小时跟踪feign和ribbon的源...

Feign服务之间的鉴权问题

Feign服务调服务传递数据的时候,需要带token验证的,而调用那个用户服务的时候被用户服务方拦截然后没有token进不去接口,很明显的是因为没有token导致,那么Feign里面有提供一个接口叫做RequestInterceptor,只要实...

feign 启用gzip压缩

feign 启用gzip压缩

目录 1.项目中启用gzip压缩 2.在feign 服务提供方开启http压缩(很重要) 3.启用httpclient 4.还有一点很容易忽略的,引入httpclient jar包,同时注意和openfeign的版本一致。 一.最近项目要在f...

声明式服务消费Feign——4(使用Feign实现消费者服务熔断)

声明式服务消费Feign——4(使用Feign实现消费者服务熔断)

使用Feign实现消费者服务熔断 服务熔断 1.在yml文件开启 hystrix功能 2.指定熔断回调逻辑 3.测试...

Spring cloud alibaba--Feign微服务调用组件

Spring cloud alibaba--Feign微服务调用组件

目录 1.1Feign优势 2.spring cloud alibaba整合Feign 3.Spring Cloud Feign日志配置  4.Feign契约配置  5.Feign超时时间配置 6.Open Feign自定义...

Feign的使用(与Ribbon的异同)

Feign:伪RPC客户端(本质还是http) 选择Feign:   1.Feignn和Ribbo两个的区别和选择   默认集成了Ribbon(包含关系)   写起来更加思路清晰和方便   采用注解方式进行配置,配置熔断等方式方便 &nbs...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。