SpringCloudFeign-声明性Http请求以及Hystrix-Http请求的熔断配置-@SpringQueryMap注解的使用-《Java笔记》

admin 2025-10-19 05:50:22 编程 来源:ZONE.CI 全球网 0 阅读模式

Java SpringCloudSpringCloud项目使用feign的时候都会发现一个问题,如果是GET方法,需要指定一连串参数,这时候使用对象去封装这些参数,但是get方式无法解析对象参数,如果方法的参数是一个对象,则会被强行转变成Post请求。其实feign是支持对象传递的,但是得是Map形式,而且不能为空,与Spring在机制上不兼容,因此无法使用。在SpringCloud 2.1.x 以上的版本,提供了一个新的注解@SpringQueryMap,这个注解可以实现将JavaBean转为Get请求的参数。

引入依赖

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-openfeign</artifactId>
  4. <version>3.0.4</version>
  5. </dependency>

使用方法

  1. @RequestMapping(value = "/safrv_2meta_id_name/", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
  2. Response verifyIdCardAndNameDTO(@SpringQueryMap AliyunVerifyIdCardAndNameReq app, @RequestHeader("Authorization") String authorization);

源码

可以翻翻feign的源码,相对来说应该是比较简单的。直接拿这个注解全局搜一下,看看有哪些地方使用到了,在每个地方都打上一个断点试试@SpringQueryMap注解的使用 - 图1全局搜下发现使用的地方主要在QueryMapParameterProcessor这个类里面。所以可以在这个类里面打上一个断点试试。

  1. /**
  2. * {@link SpringQueryMap} parameter processor.
  3. *
  4. * @author Aram Peres
  5. * @see AnnotatedParameterProcessor
  6. */
  7. public class QueryMapParameterProcessor implements AnnotatedParameterProcessor {
  8. private static final Class<SpringQueryMap> ANNOTATION = SpringQueryMap.class;
  9. @Override
  10. public Class<? extends Annotation> getAnnotationType() {
  11. return ANNOTATION;
  12. }
  13. @Override
  14. public boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method) {
  15. int paramIndex = context.getParameterIndex();
  16. MethodMetadata metadata = context.getMethodMetadata();
  17. if (metadata.queryMapIndex() == null) {
  18. metadata.queryMapIndex(paramIndex);
  19. metadata.queryMapEncoded(SpringQueryMap.class.cast(annotation).encoded());
  20. }
  21. return true;
  22. }
  23. }

可以发现这个类的话在容器启动的时候会进行加载,并且会执行processArgument方法,接下来来看看 Feign真正发起调用的地方找到SynchronousMethodHandler#invoke方法

  1. public RequestTemplate create(Object[] argv) {
  2. ... 省略部分代码
  3. // metadata.queryMapIndex() 就是QueryMapParameterProcessor #processArgument方法赋值的
  4. if (metadata.queryMapIndex() != null) {
  5. // add query map parameters after initial resolve so that they take
  6. // precedence over any predefined values
  7. // 通过下标获取到需要特殊处理的对象,这里有个问题只会处理方法参数的第一个@SpringQueryMap注解,
  8. // 原因就是QueryMapParameterProcessor #processArgument这个方法只会把第一个下标赋值进去,然后这里也只会取第一个下标,所以只会处理第一个@SpringQueryMap注解
  9. Object value = argv[metadata.queryMapIndex()];
  10. //将对象转换为map 这里需要注意下默认使用解析参数的是FieldQueryMapEncoder类所以它并不会去解析父类的参数,如果需要解析父类的参数我们需要在feign的Config里面指定QueryMapEncoder为FieldQueryMapEncoder
  11. Map<String, Object> queryMap = toQueryMap(value);
  12. //拼接解析完成的对象为URL参数
  13. template = addQueryMapQueryParameters(queryMap, template);
  14. }
  15. ... 省略部分代码
  16. }

上述代码逻辑还是挺好理解的

  • 首先去判断是否需要处理下querymap
  • 通过下标获取到需要特殊处理的对象
  • 将对象转换为map(这里有个坑默认不会去解析父类的字段)
  • 拼接追加mapurl

    总结

  • 上面通过@SpringQueryMap注解实现了get传参,但是如果需要传递多个@SpringQueryMap注解怎么来实现呢?

  • 或者可以自己动手来实现一个SpringQueryMap,该如何实现?
  • @SpringQueryMap注解默认是不会去解析父类的参数,如果需要解析父类的参数需要修改Feignconfig#QueryMapEncoderFieldQueryMapEncoder
  • 如果自己去实现了一个AnnotatedParameterProcessor所有默认的PathVariableParameterProcessorRequestParamParameterProcessorRequestHeaderParameterProcessorQueryMapParameterProcessor都会失效,为啥会失效需要去看SpringMvcContract这个类。所以自定义AnnotatedParameterProcessor需要慎重。
以太坊cppgolang区别 编程

以太坊cppgolang区别

以太坊是一种去中心化的开源平台,它采用智能合约技术,旨在构建和运行不受干扰的分布式应用程序。作为目前最受欢迎的区块链平台之一,以太坊提供了多种编程语言的支持,其
progolang 编程

progolang

Go语言(Golang)是由Google开发的一门静态类型编程语言。作为一名专业的Golang开发者,我深知这门语言的优势和特点。在本文中,我将介绍Golang
golangn个发送者 编程

golangn个发送者

Golang是一种开源的编程语言,由Google团队开发,旨在提高程序的并发性和简化软件开发过程。在Go语言中,有时需要向多个接收者发送信息。本文将介绍如何在G
golang技能图谱 编程

golang技能图谱

从互联网行业的快速发展到人工智能技术的日益成熟,各种编程语言也应运而生。而在这众多的编程语言中,Golang(即Go)作为一门强大且高效的开发语言备受关注。Go
评论:0   参与:  6