1 url传递参数
这个和get没有啥区别,就简单介绍
- 服务提供者
/**
* 测试一个参数
*
* @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();
}
- 客户端
/**
* 测试一个参数
*
* @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);
- 测试
@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 演示
- 服务提供者
/**
* 测试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;
}
- feign客户端
/**
* 测试josn
*
* @return
*/
@RequestLine("POST /feign/provider/post/body")
@Body("{body}")
@Headers({"content-type:application/json"})
String invokeTest03(@Param("body") User user);
- 测试
@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同时参数
- 服务提供者
@PostMapping("/post/bodyAndUrl")
public String test04(@RequestParam Map<String,Object> map,@RequestBody User user) {
return map.toString();
}
- 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);
- 测试
@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}