本文基于 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传递参数,我们就不用太担心参数数据量的大小了。
本文探讨了在Spring Cloud环境中,Feign客户端如何通过POST FORM方式安全传递参数,避免URL长度限制及加号解析错误等问题,提供了配置FormEncoder及定义feign客户端方法的具体步骤。
168万+

被折叠的 条评论
为什么被折叠?



