2024年07月20日   码农之路   101 次浏览

首先在讲解openfeign拦截器之前,需要先了解一下feign的请求流程:

图片来源于网络

从上面的流程我们就知道可以从以下几个节点进行数据的拦截:Encoder、RequestInterceptor、Decoder,我们可以看下源码是怎么实现的。

FeignClientsConfiguration默认配置类中的默认Encoder、Decoder配置:

@Bean
@ConditionalOnMissingBean
public Decoder feignDecoder(ObjectProvider<HttpMessageConverterCustomizer> customizers) {
	return new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(messageConverters, customizers)));
}

@Bean
@ConditionalOnMissingBean
@ConditionalOnMissingClass("org.springframework.data.domain.Pageable")
public Encoder feignEncoder(ObjectProvider<AbstractFormWriter> formWriterProvider,
		ObjectProvider<HttpMessageConverterCustomizer> customizers) {
	return springEncoder(formWriterProvider, encoderProperties, customizers);
}

RequestInterceptor的逻辑在FeignClientFactoryBean类中可以看到:

	if (config.getRequestInterceptors() != null && !config.getRequestInterceptors().isEmpty()) {
		// this will add request interceptor to builder, not replace existing
		for (Class<RequestInterceptor> bean : config.getRequestInterceptors()) {
			RequestInterceptor interceptor = getOrInstantiate(bean);
			builder.requestInterceptor(interceptor);
		}
	}

  // 这段代码在SynchronousMethodHandler中
  Request targetRequest(RequestTemplate template) {
    for (RequestInterceptor interceptor : requestInterceptors) {
      interceptor.apply(template);
    }
    return target.apply(template);
  }

好了,了解完源码,我们就可以参照源码来实现自己的需求了。

1、首先实现一个RequestInterceptor对请求进行拦截:

/**
 * feign 请求拦截器
 */
@Component
public class FeignRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        HttpServletRequest httpServletRequest = ServletUtils.getRequest();
        if (httpServletRequest == null) {
            return;
        }

        Map<String, String> headers = ServletUtils.getHeaders(httpServletRequest);
        // 这里可以对请求做任何处理,比如这里对headers进行处理
        String userId = headers.get(SecurityConstants.DETAILS_USER_ID);
        if (StringUtils.isNotEmpty(userId)) {
            requestTemplate.header(SecurityConstants.DETAILS_USER_ID, userId);
        }
    }
}

2、然后实现一个Decoder对结果进行拦截:

/**
 * 对feign的返回结果进行统一处理
 */
@Component
public class FeignResponseDecoder implements Decoder {

    private final SpringDecoder springDecoder;

    public FeignResponseDecoder(SpringDecoder springDecoder) {
        this.springDecoder = springDecoder;
    }

    @Override
    public Object decode(Response response, Type type) throws IOException, FeignException {
        Object decode = springDecoder.decode(response, type);
        // 这里可以对 springDecoder 结果进行处理,下面是判断结果是否正常
        if (decode instanceof R) {
            R r = (R) decode;
            // 判断返回结果是否正常,不正常的抛出异常
            if (r.isError()) {
                throw new DecodeException(r.getCode(), r.getMsg(), response.request());
            }
        }

        return decode;
    }
}

3、定义一个配置类FeignAutoConfiguration覆盖默认的配置:

/**
 * Feign 配置注册
 **/
@Configuration
public class FeignAutoConfiguration {
    @Bean
    public RequestInterceptor requestInterceptor() {
        return new FeignRequestInterceptor();
    }

    @Bean
    public Decoder decoder(ObjectFactory<HttpMessageConverters> msgConverters, ObjectProvider<HttpMessageConverterCustomizer> customizers) {
        // 这里参考的源码,因为SpringDecoder已经帮我们做了很多基础工作,
        // 所以只需要对SpringDecoder进行再次包装即可。
        return new OptionalDecoder((new ResponseEntityDecoder(new FeignResponseDecoder(new SpringDecoder(msgConverters, customizers)))));
    }
}

4、 Encoder的使用就留给你们自己去完成啦^_^

赞 赏
申明:除非注明,本站文章均为原创,转载请以链接形式标明本文地址。 如有问题,请于一周内与本站联系,本站将在第一时间对相关内容进行处理。
本文地址: http://www.yyjjssnn.cn/articles/890.html
相关阅读: Feign, OpenFeign

>>> Hello World <<<

这篇内容是否帮助到你了呢?

如果你有任何疑问或有建议留给其他朋友,都可以给我留言。

:wink: :twisted: :surprised: :smile: :smile9: :smile8: :smile7: :smile6: :smile5: :smile56: :smile55: :smile54: :smile53: :smile52: :smile51: :smile50: :smile4: :smile49: :smile48: :smile47: :smile46: :smile45: :smile44: :smile43: :smile42: :smile41: :smile40: :smile3: :smile39: :smile38: :smile37: :smile36: :smile35: :smile34: :smile33: :smile32: :smile31: :smile30: :smile2: :smile29: :smile28: :smile27: :smile26: :smile25: :smile24: :smile23: :smile22: :smile21: :smile20: :smile1: :smile19: :smile18: :smile17: :smile16: :smile15: :smile14: :smile13: :smile12: :smile11: :smile10: :smile0: :sad: :rolleyes1: :redface: :razz: :question: :neutral: :mrgreen: :mad: :lol: :idea: :exclaim: :evil: :eek: :cry: :cool: :confused: :biggrin: :arrow:

友情链接: 程序员刘杨 刘杨
Copyright 2003~2018 保留所有权利 | 网站地图
备案号:湘ICP备14001005号-2

湘公网安备 43011102001322号