FeignClient 数据请求方式小结

文章目录

  • 前言
  • 一、GET方式
    • 参数字段直接ENCODE拼接
    • Map对象ENCODED拼接
    • POJO对象ENCODED拼接
    • Map对象可配ENCODE拼接
  • 二、POST方式
    • 1. application/json
    • 2. application/x-www-form-urlencoded
    • 3. application/x-www-form-urlencoded但body不做encode
  • 总结


前言

基于SB/SC做微服务化改造,服务之间的HTTP请求大多是基于FeignClient来完成。本文对个人工作中遇到的使用方式做一个小结。

相关maven配置
io.github.openfeign: feign-core :11.8
io.github.openfeign: feign-form :3.8.0
org.springframework.springcloud:spring-cloud-starter-openfeign:3.1.3


一、GET方式

参数字段直接ENCODE拼接

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name= "testSpi")
public interface TestSpi {
    @GetMapping(path = "/api/v0/user")
	public User getUser(@RequestParam("username") String username,
	@RequestParam("md5") String md5);
}

举例:
username=“Good Morning”
md5=“md 5”
实际请求url如下,参数做了URLEncode处理
GET /api/v0/user?username=Good%20Morning&md5=md%205

Map对象ENCODED拼接

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name= "testSpi")
public interface TestSpi {
    @GetMapping(path = "/api/v0/user")
	public User getUser(@RequestParam Map<String,Object> paramMap);
}

// 其中 paramMap的内容
/**
{
   "username": "Good Morning",
   "md5": "md 5"
}
*/

实际效果
GET /api/v0/user?username=Good%20Morning&md5=md%205

POJO对象ENCODED拼接

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name= "testSpi")
public interface TestSpi {
    @GetMapping(path = "/api/v0/user")
	public User getUser(@RequestParam UserVo userVo);
}

/**
其中
userVo = new UserVo("Good Morning", "md 5");
*/

实际效果
GET /api/v0/user?username=Good%20Morning&md5=md%205

Map对象可配ENCODE拼接

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.cloud.openfeign.SpringQueryMap;

@FeignClient(name= "testSpi")
public interface TestSpi {
    @GetMapping(path = "/api/v0/user")
	public User getUser(@SpringQueryMap(encoded = true) Map<String,Object> paramMap);
}

// 其中 paramMap的内容
/**
{
   "username": "Good Morning",
   "md5": "md 5"
}
*/

实际效果
GET /api/v0/user?username=Good Morning&md5=md 5
encoded=true,告诉Feign字段值已做urlencode 不需要再encode;
encoded=false, 默认值,告诉Feign字段值未做urlencode, 需要由Feign做urlencode;

二、POST方式

1. application/json

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name= "testSpi")
public interface TestSpi {
    @PostMapping(path = "/api/v0/user")
	public User getUser(@RequestBody UserVo userVo);
}
/**
其中
userVo = new UserVo("Good Morning", "md 5");
*/

实际效果
POST /api/v0/user

CONTENT-TYPE: application/json

body:
{
“username”: “Good Morning”,
“md5”: “md 5”
}

2. application/x-www-form-urlencoded

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name= "testSpi")
public interface TestSpi {
    @PostMapping(path = "/api/v0/user", consumer=MediaType.APPLICATION_FORM_URLENCODED_VALUE)
	public User getUser(@RequestParam UserVo userVo);
}
/**
其中
userVo = new UserVo("Good Morning", "md 5");
*/

实际效果
POST /api/v0/user

CONTENT-TYPE: application/x-www-form-urlencoded

body:
username=Good%20Morning&md5=md%205

3. application/x-www-form-urlencoded但body不做encode

有时候服务端提供的接口要求body不做encode,比如server端基于Apache+CGI开发。预期的效果如下

POST /api/v0/user

CONTENT-TYPE: application/x-www-form-urlencoded

body:
username=Good Morning&md5=md 5

我们知道FeignClient是通过Encode来对参数做加工,Encoder内部则是依赖不同的ContentProcessor,对于UrlencodedFormContentProcessor来说默认都是做了encode处理的。因此需要自定义ContentProcessor,进而自定义encoder。

原始的UrlencodedFormContentProcessor

public class UrlencodedFormContentProcessor implements ContentProcessor {

  private static final char QUERY_DELIMITER = '&';

  private static final char EQUAL_SIGN = '=';

  @SneakyThrows
  private static String encode (Object string, Charset charset) {
    return URLEncoder.encode(string.toString(), charset.name());
  }
}

自定义的MyUrlencodedFormContentProcessor

public class MyUrlencodedFormContentProcessor implements ContentProcessor {

    private static final char QUERY_DELIMITER = '&';

    private static final char EQUAL_SIGN = '=';

    @SneakyThrows
    private static String encode (Object string, Charset charset) {
        return string.toString();
    }
}

自定义的MyFormEncoder

public class MyFormEncoder {
 public MyFormEncoder(Encoder delegate) {
        this.delegate = delegate;

        val list = asList(
                new MultipartFormContentProcessor(delegate),
                // 此处写入自己的Processor
                new MyUrlencodedFormContentProcessor()
        );

        processors = new HashMap<ContentType, ContentProcessor>(list.size(), 1.F);
        for (ContentProcessor processor : list) {
            processors.put(processor.getSupportedContentType(), processor);
        }
    }
}

定义configuration

public class TestSpiConfiguration {
    @Bean
    public Encoder encoder() {
        return new MyFormEncoder();
    }
}

@FeignClient(name= "testSpi", configuration = TestSpiConfiguration.class)
public interface TestSpi {
    @PostMapping(path = "/api/v0/user", consumer=MediaType.APPLICATION_FORM_URLENCODED_VALUE)
	public User getUser(@RequestParam UserVo userVo);
}

最终效果达成。


总结

本文对FeignClient在使用过程中遇到几种方式做了小结,期待对你有所帮助。

你可能感兴趣的:(SpringCloud,java,spring,spring,boot)