Spring Cloud OpenFeign @SpringQueryMap注解

概述

我们在使用@GetMapping方法是,对于多个参数都是通过@RequestParam参数一个一个接取的,多个参数时会比较麻烦,能像@RequestBody那样接取@PostMapping的参数么?答案是可以的。

@SpringQueryMap介绍

@SpringQueryMap 注解是 spring-cloud-openfeign-core:2.1.0.RELEASE 开始引入的一个新注解。
在这里插入图片描述
它被包含在 spring-cloud-starter-openfeign:2.1.0.RELEASE 中

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.1.0.RELEASE</version>
</dependency>

虽然 OpenFeign 的 @QueryMap注解支持将 POJO 映射到 GET 方法的参数上。但由于缺少value属性而与 Spring 不兼容,为此 Spring Cloud OpenFeign 提供了等效的@SpringQueryMap注解,用于将 POJO 或 Map ,映射为 GET 方法的参数。

@SpringQueryMap使用

@SpringQueryMap 注解用法也很简单,假设有一个叫 StudentDTO的类。

public class StudentDTO {
    private String name;
    private String age;

    // get、set 方法
}

spring-cloud-openfeign-core:2.1.0.RELEASE 之前,你不能直接传递对象,只能将它手动拆分成多个字段进行传参.

@FeignClient("demo")
public interface DemoTemplate {
    @GetMapping(path = "/demo")
    String demoEndpoint(@RequestParam String name, @RequestParam String age);
}

spring-cloud-openfeign-core:2.1.0.RELEASE 开始 @SpringQueryMap注解可以自动帮你完成参数映射。

// 等效于上面的写法
@FeignClient("demo")
public interface DemoTemplate {

    @GetMapping(path = "/demo")
    String demoEndpoint(@SpringQueryMap StudentDTO studentDTO);
}

@SpringQueryMap 注解不解析父类字段

这句话是啥意思了?
我们来看一个例子,还是刚刚那个 StudentDTO,但是现在它继承了 PageDTO。

public class PageDTO {
    private Integer page;
    private Integer siez;
    // get、set 方法
}

public class StudentDTO exdents PageDTO {
    private String name;
    private String age;
    // get、set 方法
}

然后同样使用 @SpringQueryMap 来映射。

@FeignClient("demo")
public interface DemoTemplate {

    @GetMapping(path = "/demo")
    String demoEndpoint(@SpringQueryMap StudentDTO studentDTO);
    // 等效于 String demoEndpoint(@RequestParam String name,@RequestParam String age);
}

但实际结果可能跟你想的不太一样,上面的写法等效于。

String demoEndpoint(@RequestParam String name, @RequestParam String age);

可以看到 StudentDTO exdents PageDTO 中的参数并没有映射上去。

原因

其实,准确来说,“@SpringQueryMap 注解不解析父类字段” 这种说法并不准确,因为这并不是 @SpringQueryMap 的问题。
原生的 OpenFeign 在使用原生的 @QueryMap 注解时,也会出现这个问题。
问题的重点不在于 @QueryMap 注解而是在于 OpenFeign 的 encode 上。
在这里插入图片描述
@QueryMap 对应的 encode 为 QueryMapEncoder, 而从 QueryMapEncoder 源码注释中可以看出,FieldQueryMapEncoder 虽然是 QueryMapEncoder 的默认实现,但是已经不推荐使用了,其中一个原因就是因为它不会去映射 POJO 的父类属性。

public interface QueryMapEncoder {

  /**
   * ...
   */
  Map<String, Object> encode(Object object);

  /**
   * @deprecated use {@link BeanQueryMapEncoder} instead. default encoder uses reflection to inspect
   *             provided objects Fields to expand the objects values into a query string. If you
   *             prefer that the query string be built using getter and setter methods, as defined
   *             in the Java Beans API, please use the {@link BeanQueryMapEncoder}
   */
  class Default extends FieldQueryMapEncoder {
  }
}

解决方案

知道了原因,解决方案就很简单了,跟换为 @QueryMap 的 QueryMapEncoder 为推荐的 BeanQueryMapEncoder 就行了。

@Configuration
public class FeignClientCustomizerConfig {

	/**
	 * 替换解析 queryMap 的类,实现父类中变量的映射
	 * @return
	 */
	@Bean
	public Feign.Builder feignBuilder() {
		return Feign.builder()
			.queryMapEncoder(new BeanQueryMapEncoder());
	}
}

然后使用上面自定义的配置,如果想让它全局生效,就在 Spting boot 启动类上。

@EnableFeignClients(defaultConfiguration = FeignClientCustomizerConfig.class)
@SpringBootApplication
public class TestApplication {
    public static void main(String[] args) {
    }
}

如果只想让它在单个 FeignClient 上生效,就加上 configuration 属性。

@FeignClient(value = "xxx", configuration = FeignClientCustomizerConfig.class)
@RequestMapping("/xxx")
@Service
public interface XxxFeignClient {
}

参考

Spring Cloud OpenFeign @SpringQueryMap

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

融极

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值