OpenFeign

Tips

@QueryMap

feign.QueryMap#encoded encoded=true时,表明参数值已经编码过了,不需要feign去编码;encoded=false,默认值,需要feign对参数进行urlencode

当我们不希望对查询参数进行urlencode编码时可使用该注解

发送content-type为application/x-www-form-urlencoded的请求

设置org.springframework.web.bind.annotation.PostMapping#consumes属性

    @PostMapping(value = "xxxx/xxxx", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    String getOpenId(@RequestParam String accessToken, @RequestBody OpenIdRequest request);

feignclient请求流程

  • feign.ReflectiveFeign.FeignInvocationHandler#invoke
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    	  if ("equals".equals(method.getName())) {
    	      // ...
    	  }
    	  // ...
    	  
    	  return dispatch.get(method).invoke(args);
    	}
    
  • feign.SynchronousMethodHandler#invoke
    构建请求模板对象RequestTemplate,然后发送请求并对响应解码
    在这里插入图片描述

编码Encoder/Decoder

feign.codec.Encoder
在上述构建RequestTemplate的过程中,涉及对参数编码的逻辑

  @Override
  public RequestTemplate create(Object[] argv) {
    RequestTemplate mutable = RequestTemplate.from(metadata.template());
    // ...省略部分代码
    
    RequestTemplate template = resolve(argv, mutable, varBuilder);
    
    // ...
    return template;

使用编码器Encoder对参数进行编码

  @Override
  protected RequestTemplate resolve(Object[] argv,
                                    RequestTemplate mutable,
                                    Map<String, Object> variables) {
    // ...
      if (alwaysEncodeBody) {
        body = argv == null ? new Object[0] : argv;
        // 使用编码器
        encoder.encode(body, Object[].class, mutable);
      } else {
        encoder.encode(body, metadata.bodyType(), mutable);
      }
    // ...
    return super.resolve(argv, mutable, variables);
  }

Encoder实现类的来源:①在feignclient的自动配置类中向容器中注入了Encoder的实现类SpringEncoder的实例。②也可以利用@FeignClient的configuration属性指定局部配置类,在局部配置类中自定义Encoder的实现类。③在配置文件中为某个feignclient指定使用的encoder
在这里插入图片描述
在这里插入图片描述
进入SpringEncoder#encode,如果content-type是表单数据(multipart/form-dataapplication/x-www-form-urlencoded等)则使用SpringFormEncoder进行编码,否则使用消息转换器HttpMessageConverter对参数进行处理
在这里插入图片描述
例:content-type是application/x-www-form-urlencoded,则使用SpringFormEncoder编码器去编码,最终调用其父类FormEncoder的encode方法,该方法会使用UrlencodedFormContentProcessor来处理

	public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
	    String contentTypeValue = this.getContentTypeValue(template.headers());
	    ContentType contentType = ContentType.of(contentTypeValue);
	    if (!this.processors.containsKey(contentType)) {
	        this.delegate.encode(object, bodyType, template);
	    } else {
	        // ...省略部分代码
	        
	        Charset charset = this.getCharset(contentTypeValue);
	        // 交给ContentProcessor处理
	        ((ContentProcessor)this.processors.get(contentType)).process(template, charset, data);
	    }
	}

在这里插入图片描述

feign.codec.Decoder
Encoder类似

容错fallback

拦截器RequestInterceptor

扩展

x-www-form-urlencoded

传输表单数据,这种编码方式的请求数据会放置在请求体发送。
例如使用这种content-type提交以下内容:

name: Susan
password: 666777

会被编码成以下内容在请求体中进行传输

name=Susan&password=666777

multipart/form-data

这种格式会把表单内容分成多个部分,这也是为什么叫multipart,而且每个part都支持不同的内容类型,当然请求头中的content-type肯定是multipart/form-data
例如可以通过表单在一次请求中传输文本类型的参数和文件类型的参数
在这里插入图片描述

注意:并不是必须要用request.getInputStream()方法才能读取请求体中的数据,如果是表单数据,也可以用request.getParameter()方法获取参数,就是说request.getParameter()方法除了能获取请求地址上的参数,还能获取表单中的参数(x-www-form-urlencode和form-data),这些表单数据是放在请求体中传输的。但是使用form-data上传文件时,无法使用request.getParameter()获取

对于x-www-form-urlencode和form-data这两种格式,request.getParameter()方法会从请求体中读取数据,底层也是通过获取InputStream实现的

动态URL(未验证)

@feignclient修饰的接口中,方法参数使用java.net.URI
在这里插入图片描述
@FeignClient的url属性不能为空,可使用任意字符串作为占位避免报错

  • 18
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值