spring cloud feign client中 GET方法传输复杂对象的解决方案

spring cloud feign client中 GET方法传输复杂对象的解决方案


在spring cloud feign client中,一般复杂对象只能用Post方法加上@RequestBody来传送。但如果只是读取操作,理应用Get方法。Spring的RestController是支持get方法传递复杂对象的,但用了feign client就发现,如果GET参数为复杂对象,它会自动转成post,这很不友好,也不规范。网上方法比较多,但要么是转成了POST,要么代码侵入性很强,需要修改feign的代码。于是我自己研究了一下spring-cloud-feign,终于找到了优雅的方法,让spring-cloud-feign支持GET方法传递复杂对象。
示例要传输的复杂对象如下:

public class TestGroup {
	private String name;
	private int ver = 1;
	private List<TestItem> items;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public List<TestItem> getItems() {
		return items;
	}
	public void setItems(List<TestItem> items) {
		this.items = items;
	}
	private int getVer() {//这个申明为私有,故意让它不应该传递的
		return ver;
	}
	public void setVer(int ver) {
		this.ver = ver;
	}
}

public class TestItem {
	private String itemCode;

	public String getItemCode() {
		return itemCode;
	}

	public void setItemCode(String itemCode) {
		this.itemCode = itemCode;
	}

}

接口申明:

	@GetMapping(value = "/test/testgroups/sample")
	public List<TestGroup> searchBySample(TestGroup group);

为了要让spring-cloud-openfeign能够支持这个API,下面是支持类。

1. 建立一个Annotation

这个Annotation用于标识这个对象是要在Get请求时,转换成Spring RestController能接收的参数。

@Target({ ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GetParam {
	Class<?> value() default Object.class;
}

然后接口申明改变为:

	@GetMapping(value = "/test/testgroups/sample")
	public List<TestGroup> searchBySample(@GetParam TestGroup group);

2. 实现这个Annotation的处理类

本类处理@GetParam。

/**
 * 用于处理{@link GetParam}
 */
public class GetParamParameterProcessor implements AnnotatedParameterProcessor {
	private static final Class<GetParam> ANNOTATION = GetParam.class;

	@Override
	public Class<? extends Annotation> getAnnotationType() {
		return ANNOTATION;
	}

	@Override
	public boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method) {
		int parameterIndex = context.getParameterIndex();
		// Class<?> parameterType = method.getParameterTypes()[parameterIndex];
		MethodMetadata data = context.getMethodMetadata();
		String paramName = "s";// 用一个假参数骗过feign把本参数当个RequestParameter处理
		context.setParameterName(paramName);
		Map<Integer, Expander> indexToExpander = data.indexToExpander();
		indexToExpander.put(parameterIndex, new GetParameterExpander());
		data.indexToEncoded().put(parameterIndex, Boolean.FALSE);
		RequestTemplate template = data.template();
		Collection<String> query = context.setTemplateParameter(paramName, template.queries().get(paramName));
		template.query(paramName, query);
		return true;
	}
}

下面这个类是让feign处理@GetParam时,把复杂对象转成请求串。

import com.ibm.iisp.common.util.UriUtils;
import feign.Param.Expander;

public class GetParameterExpander implements Expander {

	@Override
	public String expand(Object value) {
		return UriUtils.toQueryString(value, "");
	}

}

假如输入的对象为:

TestGroup group = new TestGroup();
group.setName("Test group1.");
ArrayList<TestItem> items = new ArrayList<>();
group.setItems(items);
TestItem item = new TestItem();
item.setItemCode("Item1");
items.add(item);
item = new TestItem();
item.setItemCode("Item2");
items.add(item);

转换结果如:items[0].itemCode=Item1&items[1].itemCode=Item2&name=Testgroup1

3. 改变Spring-boot的配置,加载处理类

我们在Spring-boot配置类中,改写ParameterProcessor的配置,增加我们的GetParamParameterProcessor:

@Configuration
public class FegnConsumerAppConfig {
	Logger log = LoggerFactory.getLogger(getClass());


	@Bean
	public PathVariableParameterProcessor getPathVariableParameterProcessor() {
		return new PathVariableParameterProcessor();
	}

	@Bean
	public RequestParamParameterProcessor getRequestParamParameterProcessor() {
		return new RequestParamParameterProcessor();
	}

	@Bean
	public RequestHeaderParameterProcessor getRequestHeaderParameterProcessor() {
		return new RequestHeaderParameterProcessor();
	}

	@Bean
	public QueryMapParameterProcessor getQueryMapParameterProcessor() {
		return new QueryMapParameterProcessor();
	}

	@Bean
	public GetParamParameterProcessor getGetParamParameterProcessor() {
		return new GetParamParameterProcessor();
	}
}

最后启动你的Spring-boot用feign client传入一个TestGroup即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值