OpenFeign 基础使用

微服务之间方便优雅的远程调用

Feign ,何许人也

Feign是Netflix开发的声明式、模板化的HTTP客户端,Feign可帮助我们更加便捷、优雅地调用HTTP API。

Feign可以做到使用HTTP请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个 HTTP请求。它像Dubbo一样,consumer直接调用接口方法来调用provider,而不需要通过常规的Http Client构造请求再解析返回数据。它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。

Spring Cloud openfeign对Feign进行了增强,使其支持Spring MVC注解,另外还整合了Ribbon和Eureka,从而使得Feign的使用更加方便。

架构设计

1740705788464.jpg

SpringBoot ,SpringCloud 快速整合Feign

【Spring Cloud Alibaba 同理】

引入openfeign 的起步依赖

<!-- openfeign 远程调用 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

编写调用接口+@FeignClient注解

package com.xx.user.client;

import com.morris.user.entity.Order;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@FeignClient(value = "order-service", path = "/order")
public interface OrderClient {

    @GetMapping("findOrderByUserId")
    List<Order> findOrderByUserId(@RequestParam("userId") Long userId);

}

在启动类上添加@EnableFeignClients注解

package com.xx.user.client;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableFeignClients // 开启OpenFeign
@SpringBootApplication
public class UserServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }

}

发起调用,像调用本地方式一样调用远程服务

package com.xx.user.controller;

import com.xx.user.client.OrderClient;
import com.xx.user.entity.Order;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("testuser")
public class OpenFeignController {

    @Resource
    private OrderClient orderClient;

    @GetMapping("findOrderByUserId")
    public List<Order> findOrderByUserId1(Long userId) {
        return orderClient.findOrderByUserId(userId);
    }

}

接口定义

GET 请求

无参数

无参和正常无参的本地方法类似

@GetMapping("getOrder")
Order getOrder();

多个基础参数

注:Get请求多个参数时,需要使用@RequestParam或者@PathVariable注解,这是因为在加载方法元数据的时候,如果该形参没有注解,默认会直接将其放在请求体中,这样GET请求时就会报错。

路径参数 @PathVariable
@GetMapping("findOrderByUserId/{userId}")
List<Order> findOrderByUserId2(@PathVariable("userId") Long userId);
查询参数 @RequestParam
  • 单个数据
@GetMapping("findOrderByUserId")
List<Order> findOrderByUserId(@RequestParam("userId") Long userId);
  • 集合数据
@GetMapping("getOrders")
    List<Order> getOrders(@RequestParam("idList") List<Long> idList);

请求时,会自动用逗号拼接

  http://localhost:8030/user3/getOrders=1,2
多个参数合并为对象 @SpringQueryMap
@GetMapping("getOrderUser")
Order getOrderUser(@SpringQueryMap Order order)

注:SpringQueryMap 只能存一个,不能同时给两个对象参数

  • 非对象参数追加@SpringQueryMap + @RequestParam 也是支持的,注意保持参数不要同名,同名会覆盖对象内属性
@GetMapping("getOrderName")
Order getOrderName(@SpringQueryMap Order order, @RequestParam("name") String name);
下载文件

下载文件需要注意的是,应该返回二进制数据,还有GET请求时,需要对URL进行编码

@GetMapping("/download")
byte[] download(@RequestParam("filePath") String filePath);

POST 请求

传递单个对象

@PostMapping("saveOrder")
Long saveOrder(@RequestBody Order order);
  • @RequestBody 可以省略
  • 会使用编码器,将对象编码 Content-Type: application/json
  • 只能传递一个对象,多对象需要自已转化为一个对象,或用map转化一下
上传文件

上传文件时,需要注意的是需要使用@RequestPart注解,Fiegn会解析这个注解,标记为上传文件请求,还需要指定consumes为MULTIPART_FORM_DATA_VALUE,编码器会根据这个配置,将文件对象进行编码。

@PostMapping(value = "upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
String upload(@RequestPart("file") MultipartFile file);

在调用方,上传文件时,则需要将文件对象转为MultipartFile。

@GetMapping("upload")
public String upload() throws URISyntaxException {
    File file = new File(OpenFeignController.class.getResource("/application.yml").toURI());
    MultipartFile multipartFile =fileToMultipartFile(file);
    return orderClient.upload(multipartFile);
}

private MultipartFile fileToMultipartFile(File file) {
    String fieldName = "file";
    FileItemFactory factory = new DiskFileItemFactory(16, null);
    FileItem item = factory.createItem(fieldName, "multipart/form-data", true, file.getName());
    int bytesRead = 0;
    byte[] buffer = new byte[8192];
    try {
        FileInputStream fis = new FileInputStream(file);
        OutputStream os = item.getOutputStream();
        while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        fis.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return new CommonsMultipartFile(item);
}

header中加参数

有时候接口验签的场景header中需要追加一些参数,可以通过@RequestHeader注解实现

@GetMapping("header1")
String header1(@RequestHeader(name = "authorization")String authorization);

固定参数,可以通过@Headers 指定

@PostMapping("header2")
@Headers({"Content-Type:application/json","Authorization:{authorization}"})
String header2(@RequestHeader(name = "authorization")String authorization, User user);

参考文章

【openfeign】OpenFeign的使用、GET请求和POST请求_51CTO博客_openfeign get请求

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容