SpringCloud组件OpenFeign之拦截器解读
SpringCloud组件OpenFeign之拦截器
OpenFeign组件中有这么一个接口——RequestInterceptor 。
我们来看一下源码中关于这个接口的介绍。
package feign; /** * 可以配置零个或多个请求拦截器,可以用于例如给所有请求添加请求头信息.但是不能保证拦截器的应用顺 * 序。一旦拦截器被应用,就会调用Target类中的apply(RequestTemplate)方法去创建不可变的http请 * 求,该请求通过Client类中的execute(Request, feign.Request.Options)发送。 * * 拦截器是在设置rest模板参数后才被应用的,因此不能再拦截器中添加参数,比如不能再 * apply(RequestTemplate)方法中给/path/{foo}/bar中的foo设置参数。 * 这个类类似于RequestInterceptor.intercept()方法,可以实现读取、删除或以其他方式改变请求模板 * 的任何部分。 */ public interface RequestInterceptor { /** * 可以被每个请求调用。使用RequestTemplate提供的这个方法可以添加数据。 */ void apply(RequestTemplate template); }
通过对该类及方法的注释可以了解到RequestInterceptor接口的apply方法可以对请求进行拦截,可以在该方法中添加请求头信息。
实践一下。
一、创建一个拦截器在请求头中添加traceId信息
场景如下,使用拦截器在请求头中添加traceId属性,服务端可以获取到该traceId,用于日志追踪。
方式一:创建自定义拦截器+@Configuration
package com.example.rtbootconsumer.config.interceptor; import com.example.rtbootconsumer.common.utils.TraceIdUtil; import feign.Request; import feign.RequestInterceptor; import feign.RequestTemplate; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Configuration; /** * @Description Feign接口请求拦截器 **/ @Configuration public class FeignRequestInterceptor implements RequestInterceptor { /** * @description: 将traceId设置到请求头 */ @Override public void apply(RequestTemplate template) { String traceId = TraceIdUtil.getTraceId(); if (StringUtils.isNotEmpty(traceId)) { template.header("traceId", traceId); } } }
方式二:创建自定义拦截器+配置@FeignClient注解的configuration属性
package com.example.rtbootconsumer.config.interceptor; import com.example.rtbootconsumer.common.utils.TraceIdUtil; import feign.Request; import feign.RequestInterceptor; import feign.RequestTemplate; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Configuration; /** * @Description Feign接口请求拦截器 **/ public class FeignRequestInterceptor implements RequestInterceptor { /** * @description: 将traceId设置到请求头 */ @Override public void apply(RequestTemplate template) { String traceId = TraceIdUtil.getTraceId(); if (StringUtils.isNotEmpty(traceId)) { template.header("traceId", traceId); } } }
package com.example.rtbootconsumer.feignservice; import com.example.rtbootconsumer.pojo.User; import com.example.rtbootconsumer.vo.ResultBody; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; import java.util.List; @FeignClient(name = "service-provider", path = "/testComm", url = "${addr.url}",configuration = FeignRequestInterceptor.class) public interface UserFeignService { @PostMapping(value = "/getUser") public ResultBody<User> getUser(@RequestBody User user); }
二、创建两个拦截器
也可以同时创建多个拦截器实现拦截器链的功能。
此时再创建一个拦截器FeignRequestInterceptor2,用于在请求头中设置属性名为test,值为lalala信息。
方式一:同上
package com.example.rtbootconsumer.config.interceptor; import com.example.rtbootconsumer.common.utils.TraceIdUtil; import feign.Request; import feign.RequestInterceptor; import feign.RequestTemplate; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Configuration; /** * @Description Feign接口请求拦截器 **/ @Configuration public class FeignRequestInterceptor2 implements RequestInterceptor { /** * @description: 将test设置到请求头 */ @Override public void apply(RequestTemplate template) { String traceId = TraceIdUtil.getTraceId(); if (StringUtils.isNotEmpty(traceId)) { template.header("test", "lalala"); } } }
方式二:同上,注意这里设置的@FeignClient注解的configuration属性值是两个拦截器的class数组。
package com.example.rtbootconsumer.feignservice; import com.example.rtbootconsumer.pojo.User; import com.example.rtbootconsumer.vo.ResultBody; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; import java.util.List; @FeignClient(name = "service-provider", path = "/testComm", url = "${addr.url}",configuration = {FeignRequestInterceptor.class,FeignRequestInterceptor2.class}) public interface UserFeignService { @PostMapping(value = "/getUser") public ResultBody<User> getUser(@RequestBody User user); @PostMapping(value = "/testList") public ResultBody<List<User>> testList(@RequestBody List<User> list); }
三、注意
在创建并配置拦截器时有两点需要特别注意。
1.在使用方式一去创建拦截器时
会拦截所有请求。用方式二时若@FeignClient注解的configuration属性未设置拦截器,那么并不会拦截该接口下所有方法的请求。拦截器只会拦截所有configuration属性值设置了拦截器的接口下所有方法的请求。因此使用方式二更灵活。
2.拦截器执行顺序
若使用方式一去创建多个拦截器时,正如前面注释所讲,不能保证拦截器的执行顺序。
但是使用方式二则可以控制拦截器的执行顺序,拦截器的执行顺序和@FeignClient注解中configuration属性中拦截器的配置顺序有关。
若配置为 {FeignRequestInterceptor.class,FeignRequestInterceptor2.class}),则会先执行FeignRequestInterceptor中的拦截,再执行FeignRequestInterceptor2中的拦截。
若配置为 {FeignRequestInterceptor2.class,FeignRequestInterceptor.class}),则会先执行FeignRequestInterceptor2中的拦截,再执行FeignRequestInterceptor中的拦截。有兴趣的可以试一下。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
Spring中@PropertySource和@Value注解详解
这篇文章主要介绍了Spring中@PropertySource和@Value注解详解,@PropertySource注解可以方便和灵活的向Spring的环境容器(org.springframework.core.env.Environment Environment)中注入一些属性,这些属性可以在Bean中使用,需要的朋友可以参考下2023-11-11java使用RandomAccessFile类基于指针读写文件实例代码
这篇文章主要介绍了java使用RandomAccessFile类基于指针读写文件实例代码,具有一定参考价值,需要的朋友可以了解下。2017-10-10
最新评论