03 Feign发送Post请求

1 url传递参数

这个和get没有啥区别,就简单介绍

  1. 服务提供者
   /**
     * 测试一个参数
     *
     * @return
     */
    @PostMapping("/post")
    public String test01(@RequestParam String name) {
        return name;
    }

    /**
     * 测试Map
     *
     * @return
     */
    @PostMapping("/post/map")
    public String test02(@RequestParam Map<String,Object> map) {
        return map.toString();
    }
  1. 客户端
 /**
  * 测试一个参数
  *
  * @return
  */
 @RequestLine("POST /feign/provider/post?name={name}")
 String invokeTest01(@Param(value = "name") String name);


 /**
  * 测试map
  *
  * @return
  */
 @RequestLine("POST /feign/provider/post/map")
 String invokeTest02(@QueryMap Map<String,Object> map);
  1. 测试
@Test
public void test01() {
    String response = client.invokeTest01("wade");
    System.out.println(response);
}

@Test
public void test02() {
    Map<String, Object> map = new HashMap<>();
    map.put("name", "wade");
    map.put("age", 28);
    String response = client.invokeTest02(map);
    System.out.println(response);
}
[PostControllerClient#invokeTest01] ---> POST http://localhost:8001/feign/provider/post?name=wade HTTP/1.1
[PostControllerClient#invokeTest01] ---> END HTTP (0-byte body)
[PostControllerClient#invokeTest01] <--- HTTP/1.1 200 (163ms)
[PostControllerClient#invokeTest01] connection: keep-alive
[PostControllerClient#invokeTest01] content-length: 4
[PostControllerClient#invokeTest01] content-type: text/plain;charset=UTF-8
[PostControllerClient#invokeTest01] date: Sat, 20 Mar 2021 11:22:09 GMT
[PostControllerClient#invokeTest01] keep-alive: timeout=60
[PostControllerClient#invokeTest01] 
[PostControllerClient#invokeTest01] wade
[PostControllerClient#invokeTest01] <--- END HTTP (4-byte body)
wade


[PostControllerClient#invokeTest02] ---> POST http://localhost:8001/feign/provider/post/map?name=wade&age=28 HTTP/1.1
[PostControllerClient#invokeTest02] ---> END HTTP (0-byte body)
[PostControllerClient#invokeTest02] <--- HTTP/1.1 200 (3057ms)
[PostControllerClient#invokeTest02] connection: keep-alive
[PostControllerClient#invokeTest02] content-length: 19
[PostControllerClient#invokeTest02] content-type: text/plain;charset=UTF-8
[PostControllerClient#invokeTest02] date: Sat, 20 Mar 2021 11:20:05 GMT
[PostControllerClient#invokeTest02] keep-alive: timeout=60
[PostControllerClient#invokeTest02] 
[PostControllerClient#invokeTest02] {name=wade, age=28}
[PostControllerClient#invokeTest02] <--- END HTTP (19-byte body)
{name=wade, age=28}

2 body参数

先说明一下,不引入其他依赖,feign不支持表单提交。这里先演示json数据提交

2.1 演示

  1. 服务提供者
/**
 * 测试Body:json
 */
@PostMapping("/post/body")
public String test03(@RequestBody User user) {
    return user.toString();
}
package study.wyy.feign.model;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONPObject;
import lombok.Data;
import lombok.ToString;

import java.io.Serializable;

/**
 * @author: wyaoyao
 * @date: 2020-12-17 13:17
 * @description:
 */
@Data
@ToString
public class User implements Serializable {

    private String name;
    /**
     * 年龄
     */
    private Integer age;
}
  1. feign客户端
/**
 * 测试josn
 *
 * @return
 */
@RequestLine("POST /feign/provider/post/body")
@Body("{body}")
@Headers({"content-type:application/json"})
String invokeTest03(@Param("body") User user);
  1. 测试
@Test
public void test03() {
    User user = new User();
    user.setAge(13);
    user.setName("Wade");
    String response = client.invokeTest03(user);
    System.out.println(response);
}

测试报错

[PostControllerClient#invokeTest03] Content-Length: 23
[PostControllerClient#invokeTest03] content-type: application/json
[PostControllerClient#invokeTest03] 
[PostControllerClient#invokeTest03] User(name=Wade, age=13) # 请求数据
[PostControllerClient#invokeTest03] ---> END HTTP (23-byte body)
[PostControllerClient#invokeTest03] <--- HTTP/1.1 400 (59ms)
[PostControllerClient#invokeTest03] connection: close
[PostControllerClient#invokeTest03] content-type: application/json
[PostControllerClient#invokeTest03] date: Sat, 20 Mar 2021 13:13:37 GMT
[PostControllerClient#invokeTest03] transfer-encoding: chunked
[PostControllerClient#invokeTest03] 
[PostControllerClient#invokeTest03] {"timestamp":"2021-03-20T13:13:37.062+0000","status":400,"error":"Bad Request","message":"JSON parse error: Unrecognized token 'User': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'User': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')\n at [Source: (PushbackInputStream); line: 1, column: 6]","path":"/feign/provider/post/body"}
[PostControllerClient#invokeTest03] <--- END HTTP (495-byte body)

feign.FeignException$BadRequest: status 400 reading PostControllerClient#invokeTest03(User)

报了400的错误,JSON parse error;

日志中打印的请求数据是:User(name=Wade, age=13),默认调用的是User的toString方法,但是发现这样数据就不是个json数据了

既然知道了原因了,最简单的解决方法就是重写user的toString方法,返回json格式的数据

@Override
public String toString() {
   String s = JSON.toJSONString(this);
   return s;
}

再测试,发现没有问题:

[PostControllerClient#invokeTest03] ---> POST http://localhost:8001/feign/provider/post/body HTTP/1.1
[PostControllerClient#invokeTest03] Content-Length: 24
[PostControllerClient#invokeTest03] content-type: application/json
[PostControllerClient#invokeTest03] 
[PostControllerClient#invokeTest03] {"age":13,"name":"Wade"} # 此时请求数据就是json格式数据
[PostControllerClient#invokeTest03] ---> END HTTP (24-byte body)
[PostControllerClient#invokeTest03] <--- HTTP/1.1 200 (37ms)
[PostControllerClient#invokeTest03] connection: keep-alive
[PostControllerClient#invokeTest03] content-length: 23
[PostControllerClient#invokeTest03] content-type: text/plain;charset=UTF-8
[PostControllerClient#invokeTest03] date: Sat, 20 Mar 2021 13:18:55 GMT
[PostControllerClient#invokeTest03] keep-alive: timeout=60
[PostControllerClient#invokeTest03] 
[PostControllerClient#invokeTest03] User(name=Wade, age=13)
[PostControllerClient#invokeTest03] <--- END HTTP (23-byte body)
User(name=Wade, age=13)

2.2 API讲解

2.2.1 Body注解

该注解作用于方法上,其定义了一个类似于UriTemplate和HeaderTemplate的Template。其中的表达式也使用了@Param注解中的值进行解析。

Body template遵循以下规则:

  • 无法解析的表达式将会被省略

  • 必须设置Content-Type请求头参数

测试:必须设置Content-Type请求头参数,去掉设置header的代码

@RequestLine("POST /feign/provider/post/body")
@Body("{body}")
String invokeTest03(@Param("body") User user);

在测试,发现出现415错误

feign.FeignException$UnsupportedMediaType: status 415 reading PostControllerClient#invokeTest03(User)
2.2.2 Headers注解
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface Headers {
  String[] value();
}

能标注在类上和方法上。用于传请求头,使用起来比较简单,形如这样即可:

@Headers({"Accept:*/*", "Accept-Language:zh-cn"})

唯一注意的一点:k-v使用的是冒号连接,而不是=。

3 body和url同时参数

  1. 服务提供者
   
@PostMapping("/post/bodyAndUrl")
public String test04(@RequestParam Map<String,Object> map,@RequestBody User user) {
    return map.toString();
}
  1. feign客户端
@RequestLine("POST /feign/provider/post/bodyAndUrl")
@Body("{body}")
@Headers({"content-type:application/json"})
String invokeTest04(@QueryMap Map<String,Object> map,@Param("body") User user);
  1. 测试
@Test
public void test04() {
    User user = new User();
    user.setAge(13);
    user.setName("Wade");
    Map<String, Object> map = new HashMap<>();
    map.put("name", "kobe");
    map.put("age", 28);
    String response = client.invokeTest04(map,user);
    System.out.println(response);
}

在服务提供者的controller 中打个断点
在这里插入图片描述
可以看到数据正确接收到了

当然观察feign的日志输出,也可以看到数据正确封装

[PostControllerClient#invokeTest04] ---> POST http://localhost:8001/feign/provider/post/bodyAndUrl?name=kobe&age=28 HTTP/1.1 # url上正确带有参数
[PostControllerClient#invokeTest04] Content-Length: 24
[PostControllerClient#invokeTest04] content-type: application/json
[PostControllerClient#invokeTest04] 
[PostControllerClient#invokeTest04] {"age":13,"name":"Wade"} # 请求体中也是带有了json格式的数据
[PostControllerClient#invokeTest04] ---> END HTTP (24-byte body)
[PostControllerClient#invokeTest04] <--- HTTP/1.1 200 (34ms)
[PostControllerClient#invokeTest04] connection: keep-alive
[PostControllerClient#invokeTest04] content-length: 19
[PostControllerClient#invokeTest04] content-type: text/plain;charset=UTF-8
[PostControllerClient#invokeTest04] date: Sat, 20 Mar 2021 13:29:35 GMT
[PostControllerClient#invokeTest04] keep-alive: timeout=60
[PostControllerClient#invokeTest04] 
[PostControllerClient#invokeTest04] {name=kobe, age=28}
[PostControllerClient#invokeTest04] <--- END HTTP (19-byte body)
{name=kobe, age=28}
在使用Feign发送POST请求时,可以通过多种方式传递参数,包括请求体、表单参数、路径参数和请求头等。下面是一些常见的示例: 1. 传递请求体参数:可以使用`@RequestBody`注解将参数对象作为请求发送。示例代码如下: ```java @RequestMapping(method = RequestMethod.POST, value = "/api/endpoint") ResponseEntity<String> postWithRequestBody(@RequestBody RequestData requestData); ``` 2. 传递表单参数:可以使用`@RequestParam`注解将参数作为表单参数发送。示例代码如下: ```java @RequestMapping(method = RequestMethod.POST, value = "/api/endpoint") ResponseEntity<String> postWithFormParams(@RequestParam("param1") String param1, @RequestParam("param2") String param2); ``` 3. 传递路径参数:可以使用`@PathVariable`注解将参数作为路径参数发送。示例代码如下: ```java @RequestMapping(method = RequestMethod.POST, value = "/api/endpoint/{id}") ResponseEntity<String> postWithPathParam(@PathVariable("id") String id); ``` 4. 传递请求头:可以使用`@RequestHeader`注解将参数作为请求发送。示例代码如下: ```java @RequestMapping(method = RequestMethod.POST, value = "/api/endpoint") ResponseEntity<String> postWithRequestHeader(@RequestHeader("Authorization") String authorization); ``` 对于返回值,Feign默认使用Spring的`ResponseEntity`作为返回类型。可以根据实际情况设置合适的泛型类型,以便正确处理返回值。示例代码如下: ```java @RequestMapping(method = RequestMethod.POST, value = "/api/endpoint") ResponseEntity<MyResponse> postAndGetResponse(); ``` 在上述示例中,`MyResponse`是自定义的响应对象类型。 以上是一些常见的参数传递和返回值处理的示例,具体的使用方式可以根据实际情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值