Spring Cloud OpenFeign 是一个声明式的 Web 服务客户端,它使得编写 Web 服务客户端变得更加容易。
OpenFeign 通过接口和注解的方式来定义和调用 RESTful 服务,在这个过程中,需要正确地映射 HTTP 请求方法来与服务端的接口进行交互。
OpenFeign 提供了多种注解来映射不同的 HTTP 请求方法,例如:
(1)@RequestMapping 是一个比较通用的注解,它可以用于定义多种 HTTP 请求方法。通过修改 method 属性的值来改变请求方法,如 RequestMethod.GET、RequestMethod.PUT、RequestMethod.DELETE 等。下面将请求映射为 GET 请求:
@RequestMapping(value = "/simple/hello", method = RequestMethod.GET) String demo();
(2)@GetMapping 映射请求为 HTTP GET 请求
@GetMapping ("/simple/hello") String demo();
(3)@PostMapping 映射请求为 HTTP POST 请求
@PostMapping ("/simple/hello") String demo();
(4)@PutMapping 映射请求为 HTTP PUT 请求
@PutMapping ("/simple/hello") String demo();
(5)@DeleteMapping 映射请求为 HTTP DELETE 请求
@DeleteMapping ("/simple/hello") String demo();
上述这些注解的使用方式和在 Spring MVC 中的使用方式类似。
如果没有指定请求方法注解(如 @GetMapping 等),OpenFeign 会根据方法签名的一些特征来尝试默认映射。
例如:默认请求方法映射到 GET 请求,映射失败
// 1.服务端方法 // GET 请求,根据用户 ID 获取用户信息 @GetMapping("/getUserById") public CommonReturn<User> getUserById(@RequestParam("id") Long id) { log.info("getUserById() id={}", id); return USERS.stream() .filter(user -> user.getId().equals(id)) .findFirst() .map(u -> CommonReturn.success(u).ext(appName, appPort)) .orElse(CommonReturn.fail("用户不存在")); // 2.Feign客户端定义,没有明确定义请求方法,由 OpenFeign 尝试映射 @RequestMapping("/user/getUserById") CommonReturn<User> demo2(Long id); // 3.调用Feign客户端 @GetMapping("/demo2") public CommonReturn<User> demo2(@RequestParam("id") Long id) { return simpleFeign.demo2(id); }
使用 http://localhost:8080/demo2?id=2 地址访问上面服务,服务抛出错误:
查看详细日志:
[SimpleFeign#demo2] ---> GET http://SERVICE-DEMO/user/getUserById HTTP/1.1 [SimpleFeign#demo2] Content-Length: 1 [SimpleFeign#demo2] Content-Type: application/json [SimpleFeign#demo2] [SimpleFeign#demo2] 2 [SimpleFeign#demo2] ---> END HTTP (1-byte body) [SimpleFeign#demo2] <--- HTTP/1.1 200 (11ms) [SimpleFeign#demo2] connection: keep-alive [SimpleFeign#demo2] content-type: application/json [SimpleFeign#demo2] date: Fri, 08 Nov 2024 23:48:27 GMT [SimpleFeign#demo2] keep-alive: timeout=60 [SimpleFeign#demo2] transfer-encoding: chunked [SimpleFeign#demo2] [SimpleFeign#demo2] {"code":0,"message":"服务异常,稍后再试","data":null,"appName":null,"port":null} [SimpleFeign#demo2] <--- END HTTP (89-byte body)
服务端异常信息:2024-11-09T07:48:27.204+08:00 WARN 15764 --- [service-demo] [nio-8090-exec-6] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' is not supported]
例如:如果方法参数中包含 @RequestBody 注解,OpenFeign 会默认将其映射为一个 HTTP POST 请求。
// 1.服务端方法 // POST 请求,创建新用户 @PostMapping("/createUser") public CommonReturn<User> createUser(@RequestBody User user) { log.info("createUser() user={}", user); USERS.add(user); return CommonReturn.success(user).ext(appName, appPort); } // 2.Feign客户端定义,没有明确定义请求方法,由 OpenFeign 尝试映射 @RequestMapping("/user/createUser") CommonReturn<User> demo3(User user); // 3.调用Feign客户端 @GetMapping("/demo3") public CommonReturn<User> demo3(@RequestParam("id") Long id, @RequestParam("name") String name, @RequestParam("age") Integer age) { User user = User.builder().id(id).name(name).age(age).build(); return simpleFeign.demo3(user); }
使用 http://localhost:8080/demo3?id=2&name=Admin&age=43 地址访问上面服务,请求成功:
查看详细日志:
[SimpleFeign#demo3] ---> GET http://SERVICE-DEMO/user/createUser HTTP/1.1 [SimpleFeign#demo3] Content-Length: 32 [SimpleFeign#demo3] Content-Type: application/json [SimpleFeign#demo3] [SimpleFeign#demo3] {"id":2,"name":"Admin","age":43} [SimpleFeign#demo3] ---> END HTTP (32-byte body) [SimpleFeign#demo3] <--- HTTP/1.1 200 (9ms) [SimpleFeign#demo3] connection: keep-alive [SimpleFeign#demo3] content-type: application/json [SimpleFeign#demo3] date: Fri, 08 Nov 2024 23:55:54 GMT [SimpleFeign#demo3] keep-alive: timeout=60 [SimpleFeign#demo3] transfer-encoding: chunked [SimpleFeign#demo3] [SimpleFeign#demo3] {"code":1,"message":null,"data":{"id":2,"name":"Admin","age":43},"appName":"service-demo","port":"8090"} [SimpleFeign#demo3] <--- END HTTP (104-byte body)
💥注意:
(1)这种默认行为可能会因为具体的配置和使用场景而有所不同,所以为了代码的清晰和准确,最好还是显式地使用请求方法注解。
(2)在 Spring Boot 应用中使用 OpenFeign 时,它会自动利用 Spring MVC 的很多特性,如消息转换器、请求拦截器等。这意味着在映射 HTTP 请求方法时,所使用的注解和 Spring MVC 中的行为是高度一致的,开发人员可以很方便地根据 Spring MVC 的知识来编写 OpenFeign 客户端接口。例如,在处理请求参数绑定、请求头设置等方面,可以直接参考 Spring MVC 的规则。
(3)在映射 HTTP 请求方法时,要注意请求路径的匹配。确保 OpenFeign 客户端接口中定义的路径与服务端接口的路径完全一致,包括路径参数的名称和位置。如果路径不匹配,可能会导致无法正确调用服务端接口。
(4)对于不同的 HTTP 请求方法,请求参数和请求体的处理方式也有所不同。例如,在 GET 请求中,参数通常是通过查询字符串传递的,而在 POST 请求中,可以通过请求体传递复杂的数据结构。在使用 OpenFeign 时,要根据实际情况正确地处理请求参数和请求体,比如使用@RequestParam注解来处理查询参数,使用@RequestBody注解来处理请求体中的数据。