Spring Cloud : feign 客户端使用FORM形式POST数据
本文基于 Spring boot 2.1.2 RELEASE + Spring Cloud Greenwich.RELEASE
feign
客户端缺省的参数传递行为
缺省情况下,feign
支持GET
和POST
方式往服务端提交数据,feign
客户端的定义也很方便和直观,如下所示 :
@FeignClient(name = "test-service", path = "/test")
public interface TestService {
@GetMapping(value = "/echo")
TestModel echoGet(@RequestParam("parameter") String parameter);
@PostMapping(value = "/echo/post")
TestModel echoPost(@RequestParam("parameter") String parameter);
}
这种方式的特点是基于基本的注解@GetMapping
,@PostMapping
,@RequestParam
就可以清楚明了地定义出面向服务端API
的一个本地方法。
但上述方式中,无论是GET
还是POST
,所传递的参数都会作为QueryString
的一部分出现在URL
中。但这种URL
传参的方式存在一定的风险:
-
URL
的最大允许长度较小,如果传递的参数数据量比较大,很可能超过此限制,这种情况下程序运行可能会出现错误; - 对于加号
+
,如果开发人员不做特殊处理,而使用以上缺省feign
缺省传参方式,加号会被被错误处理成空格;
错误示例 :
- 针对
GET
DispatcherServlet
看到的URL
:GET "/test/echo?parameter=GET%20%3A%20++%20plus%20sign%20contained%2C%20but%20it's%20gone%20unexpectedly."
通过
request.getParameterMap()
获取到的参数 :{"parameter":["GET : plus sign contained, but it's gone unexpectedly."]}
- 针对
POST
DispatcherServlet
看到的URL
:POST "/test/echo/post?parameter=POST%20%3A%20++%20plus%20sign%20contained%2C%20but%20it's%20gone%20unexpectedly."
通过
request.getParameterMap()
获取到的参数 :{"parameter":["POST : plus sign contained, but it's gone unexpectedly."]}
feign
客户端使用FORM
表单形式提交(POST
)参数
针对以上URL
传参风险的考虑,我们考虑POST FORM
方式传递参数来解决这些问题。
1. 提供一个FormEncoder
如果要使用FORM
方式提交参数,首先需要确保feign
客户端使用的Encoder
是一个FormEncoder
,因此,我们要提供一个FormEncoder
给feign
客户端使用。具体通过如**册一个feignFormEncoder
bean
组件的方式到应用上下文:
@Configuration
public class FeignClientFormPostConfig {
// 这里会由容器自动注入HttpMessageConverters的对象工厂
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
// new一个form编码器,实现支持form表单提交
// 注意这里方法名称,也就是bean的名称是什么不重要,
// 重要的是返回类型要是 Encoder 并且实现类必须是 FormEncoder 或者其子类
@Bean
public Encoder feignFormEncoder() {
return new FormEncoder(new SpringEncoder(messageConverters));
}
}
2. 定义feign
客户端方法使用FORM
方式提交POST
参数
将某个feign
客户端方法定义如下 :
@PostMapping(value = "/echo/post",consumes = {"application/x-www-form-urlencoded"})
TestModel echoPostForm(Map<String, ?> formParams);
这里有几个要点需要指出 :
- 使用注解
@PostMapping
表明要使用HTTP POST
方法; -
@PostMapping
注解使用属性consumes = {"application/x-www-form-urlencoded"}
, - 参数使用
Map<String, ?>
形式 (不再是@RequestParam("parameter")
这种形式);
注意 : 这里参数
Map<String, ?>
中key
要和服务器端要求的参数名称一致,value
的类型要和服务器端要求的类型一致,否则会出现HTTP 400 BAD_REQUEST
错误。
使用如此方式,我们就可以通过POST FORM
方式传递参数了 , 例子如下 :
针对
POST FORM
, 所传递的参数和上面GET/POST例子中类似, 都是一个名为parameter
的参数,参数值含有加号 :DispatcherServlet
看到的URL
:POST "/test/echo/post"
通过
request.getParameterMap()
获取到的参数 :{"parameter":["POST FORM : plus sign contained and it's handled correctly."]}
通过这种方式,我们可以看到,加号问题被正确处理,另外基于POST FORM
方式通过request body
传递参数,我们就不用太担心参数数据量的大小了。
参考资料
上一篇: 使用Feign做远程调用的注意点
下一篇: OpenFeign 简介
推荐阅读
-
使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的方法(推荐)
-
使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的方法(推荐)
-
Spring Cloud使用Feign实现Form表单提交的示例
-
Spring Cloud下使用Feign Form实现微服务之间的文件上传
-
Spring Cloud使用Feign实现Form表单提交的示例
-
Spring Cloud : feign 客户端使用FORM形式POST数据
-
Spring Cloud下使用Feign Form实现微服务之间的文件上传
-
Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的使用