Spring-Cloud: SpringMVC + Feign 对象传递和注解使用

使用到的工具:Interlij IDEA、Postman

一、SpringMVC

在使用spring-cloud的过程中,server端提供 api接口的时候 接受的请求类型有(POST、GET、PUT 等)

1、关于提交参数的 http  Cotent-Type:

 application/x-www-form-urlencoded: 表单提交,浏览器url等 都是通过这种方式

 application/json:ajax 提交,指定Content-Type

2、参数注解的使用

SpringMVC中常用的请求参数注解有(@RequestParam, @RequestBody, @PathVariable)等。

2.1 @RequestParam

@RestController
public class TestController {
    @RequestMapping(value = "/hello")     // <1>
    public String hello (String name) {   // <2>
        return "hello " + name;
    }
}

name 被默认当做 @RequestParam。 形参String name 由框架使用字节码技术获取name这个名称,自动检测请求参数中key值为name的参数,也可以使用@RequestParam(“name”)覆盖变量本身的名称。当我们在url中携带name参数或者form表单中携带name参数时,会被获取到。

2.2 @PathVariable

@RestController
public class BookController {
    @RequestMapping(value = "/hello/{name}") // <1>
    public String hello(@PathVariable("name") String name) { // <2>
        return "hello " + name;
    }
}

name 参数被指定在url 的 /hello/{name} 后边,随着请求。@PathVariable 会获取到这个参数。

 

以上方式,在url 中都能直接指定参数,在 controller中能获取到参数。这两种方式比较适用于单个参数或者少量的参数提交,如果参数较多 建议使用对象封装。

2.3 @RequestBody

@RestController
public class BookController {
    @RequestMapping(value = "/hello")               // <1>
    public String hello(@RequestBody String name) { // <2>
        return "hello " + name;
    }
}

这种方式,请求时需要将参数放在请求的body中,在 headers中指定 Content-Type:application/json

Spring-Cloud: SpringMVC + Feign 对象传递和注解使用_第1张图片

body 中的参数必须符合 json格式,Controller 才能获取到

 

二、Feign 中的接口写法

 

在 FeignClient 的接口中,如果入参不指定参数注解(@RequestParam,@RequestBody,@PathVariable)其中一种。Feign会默认为 @RequestBody  且 Content-Type为:application/json

当参数注解为 @RequestBody 时,Feign 会将参数封装到请求的body中 类似于上图。

body中存在参数,这时候会通过 post 提交,无论你在RequestMapping 指定的为何种提交方式。

如果不加默认的注解,Feign则会对参数默认加上@RequestBody注解,而RequestBody一定是包含在请求体中的,GET方式无法包含。所以上述两个现象得到了解释。Feign在GET请求包含RequestBody时强制转成了POST请求,而不是报错

而在controller的方法上 如果不用 @RequestBody 注解入参,将获取不到参数。

Feign绑定复合参数

指定请求参数的类型与请求方式,上述问题的出现实际上是由于在没有理清楚Feign内部机制的前提下想当然的和SpringMVC进行了类比。同样,在使用对象作为参数时,也需要注意这样的问题。

对于这样的接口

@FeignClient("book")
public interface BookApi {

    @RequestMapping(value = "/book",method = RequestMethod.POST)
    Book book(@RequestBody Book book); // <1>
  
    @RequestMapping(value = "/book",method = RequestMethod.POST)
    Book book(@RequestParam("id") String id,@RequestParam("name") String name); // <2>
  
    @RequestMapping(value = "/book",method = RequestMethod.POST)
    Book book(@RequestParam Map map); // <3>
  
    // 错误的写法
    @RequestMapping(value = "/book",method = RequestMethod.POST)
    Book book(@RequestParam Book book); // <4>
}

<1> 使用@RequestBody传递对象是最常用的方式。

<2> 如果参数并不是很多,可以平铺开使用@RequestParam

<3> 使用Map,这也是完全可以的,但不太符合面向对象的思想,不能从代码立刻看出该接口需要什么样的参数。

<4> 错误的用法,Feign没有提供这样的机制自动转换实体为Map。

你可能感兴趣的:(Spring,Cloud)