当前位置: 首页> 游戏> 攻略 > SpringCLoud OpenFeign的使用介绍

SpringCLoud OpenFeign的使用介绍

时间:2025/7/15 15:16:35来源:https://blog.csdn.net/Mwt258/article/details/140646556 浏览次数:0次

Spring Cloud OpenFeign使用介绍

文章目录

  • Spring Cloud OpenFeign使用介绍
    • 导引
    • 1. 简单介绍
    • 2. 操作方式
    • 3. 参数传递
      • 3.1 传递单个参数
      • 3.2 传递多个参数
      • 3.3 传递对象
      • 3.4 传递JSON类型参数
    • 4. 最佳实践

导引

在之前的文章中,我们使用过RestTemplate来进行远程调用:

@Service
public class OrderServiceImpl implements OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;@Overridepublic OrderInfo selectOrderById(Integer orderId) {OrderInfo orderInfo = orderMapper.selectOrderById(orderId);String url = "http://product-service/product/" + orderInfo.getProductId();ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);orderInfo.setProductInfo(productInfo);return orderInfo;}
}

虽说RestTemplate对HTTP封装后已经比直接使用HTTPClient简单方便很多,但还是存在这一些问题:

  • 需要拼接URL,灵活性高,但是封装臃肿,当URL复杂时则容易出错
  • 代码可读性差,风格不统一

于是,我们可以使用OpenFeign来更”优雅“的实现远程通信!

1. 简单介绍

OpenFeign是一个声明式的Web Service 客户端,它让微服务之间的调用变得更加简单,类似于controller调用service,只需要创建一个接口,然后添加注解即可使用OpenFeign

OpenFeign 官方文档:GitHub - OpenFeign/feign: Feign makes writing java http clients easier

2. 操作方式

当前代码基于Nacos配置完成的基础上进行编写【代码获取】:

  1. 先给order-service(哪个实例需要进行远程调用就给谁加)引入依赖

    <!--feign-->
    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  2. order-service的启动类上添加注解@EnableFeignClients,开启OpenFeign功能

    package com.order;import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.openfeign.EnableFeignClients;@EnableFeignClients
    @SpringBootApplication
    public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class, args);}
    }
    
  3. 编写OpenFeign的客户端(接口),且只需进行方法声明,基于SpringMVC的注解来声明远程调用的信息

    package com.order.api;import com.order.model.ProductInfo;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.cloud.openfeign.SpringQueryMap;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;import java.util.Date;@FeignClient(value = "product-service" , path = "/product")
    public interface ProductApi {@RequestMapping("/{productId}")ProductInfo getProductById(@PathVariable("productId") Integer productId);}
    

    • value:指定FeignClient的名称,也就是微服务的名称,用于服务发现
    • path:定义当前FeignClient的统一前缀
  4. 修改远程调用的方法

    package com.order.service.Impl;import com.order.api.ProductApi;
    import com.order.mapper.OrderMapper;
    import com.order.model.OrderInfo;
    import com.order.model.ProductInfo;
    import com.order.service.OrderService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;@Service
    public class OrderServiceImpl implements OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate ProductApi productApi;@Overridepublic OrderInfo selectOrderById(Integer orderId) {OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
    //        String url = "http://product-service/product/" + orderInfo.getProductId();
    //        ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);ProductInfo productInfo = productApi.getProductById(orderInfo.getProductId());orderInfo.setProductInfo(productInfo);return orderInfo;}
    }
    

完成上述配置后,启动服务,访问接口测试远程调用:

在这里插入图片描述

远程调用测试成功,同时远程调用的代码也变的更加简洁了!

3. 参数传递

在上述例子中,介绍了从Feign从URL中获取参数,接下来介绍Feign参数传递的其它方式.

3.1 传递单个参数

服务提供方 product-service (ProductController)

package com.product.controller;import com.product.service.model.ProductInfo;
import com.product.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Date;@Slf4j
@RequestMapping("/product")
@RestController
public class ProductController {@RequestMapping("p1")public String p1(Integer id) {return "p1接受单个参数Id = " + id;}
}

Feign客户端

package com.order.api;import com.order.model.ProductInfo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.SpringQueryMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;import java.util.Date;@FeignClient(value = "product-service" , path = "/product")
public interface ProductApi {@RequestMapping("/p1")String p1(@RequestParam("id") Integer id);}

@RequestParam作参数绑定,不能省略

服务消费方 order-service (FeignController)

package com.order.controller;import com.order.api.ProductApi;
import com.order.model.ProductInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@Slf4j
@RequestMapping("/feign")
@RestController
public class FeignController {@Autowiredprivate ProductApi productApi;@RequestMapping("/o1")public String o1(Integer id) {log.info("调用o1");return productApi.p1(id);}
}

测试远程调用:http://127.0.0.1:8080/feign/o1?id=5

在这里插入图片描述

3.2 传递多个参数

使用多个@RequestParam进行参数绑定即可

服务提供方 product-service (ProductController)

@RequestMapping("p2")
public String p2(Integer id, String productName) {return "p2接收多个参数:id = " + id + " productName = " + productName;
}

Feign客户端

@RequestMapping("p2")
String p2(@RequestParam("id") Integer id, @RequestParam("productName") String productName);

服务消费方 order-service (FeignController)

@RequestMapping("/o2")
public String o2(Integer id, String productName) {log.info("调用o2");return productApi.p2(id, productName);
}

这里我们使用Postman进行远程调用测试:

在这里插入图片描述

3.3 传递对象

服务提供方 product-service (ProductController)

@RequestMapping("/p3")
public String p3(ProductInfo productInfo) {// 这里我们只给对象传入 id 和 productName,剩下的由内部封装如下productInfo.setProductPrice(99);productInfo.setState(0);productInfo.setCreateTime(new Date(System.currentTimeMillis()));productInfo.setUpdateTime(new Date(System.currentTimeMillis()));return productInfo.toString();
}

Feign客户端

@RequestMapping("/p3")
String p3(@SpringQueryMap ProductInfo productInfo);

:传入对象参数的话需要加上注解 @SpringQueryMap

服务消费方 order-service (FeignController)

@RequestMapping("/o3")
public String o3(ProductInfo productInfo) {log.info("调用o3");return productApi.p3(productInfo);
}

进行远程调用测试:

在这里插入图片描述

3.4 传递JSON类型参数

服务提供方 product-service (ProductController)

@RequestMapping("/p4")
public String p4(@RequestBody ProductInfo productInfo) {productInfo.setProductPrice(99);productInfo.setState(0);productInfo.setCreateTime(new Date(System.currentTimeMillis()));productInfo.setUpdateTime(new Date(System.currentTimeMillis()));return productInfo.toString();
}

Feign客户端

@RequestMapping("/p4")
String p4(@RequestBody ProductInfo productInfo);

服务消费方 order-service (FeignController)

@RequestMapping("/o4")public String o4(@RequestBody ProductInfo productInfo) {log.info("调用o4");return productApi.p4(productInfo);}
}

进行远程调用测试:

在这里插入图片描述

4. 最佳实践

最佳实践,其实就是经过历史的迭代,在项目的实际过程中总结出来的最好的使用方式。

在上文配置Feign客户端时也能看出,它与服务提供方的代码非常相似:

在这里插入图片描述

如果需要在每个模块中都配置重复的代码,一旦数量上来则会造成一定的代码冗余!

对此我们可以对其做出简化,将Feign的客户端抽取为一个独立的模块,并把涉及到的实体类等都放在这个模块中,打成一个jar包,消费方只需要依赖该jar包即可(jar包通常由服务提供方来实现)

具体操作如下:

  1. 先创建一个模块 product-api

    在这里插入图片描述

  2. 给刚创建的模块product-api引入依赖

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  3. 复制ProductApiProductInfoproduct-api模块中

    在这里插入图片描述

  4. 通过Maven将该模块打包到本地Maven仓库

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

  5. 删除 order-service 中的ProductApi与ProductInfo

  6. 为服务消费方 order-service引入依赖

    <dependency><groupId>org.example</groupId><artifactId>product-api</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope>
    </dependency>
    

    会出现报错信息,此时需要修改项目中ProductApi与ProductInfod 路径product-api中的路径

  7. 给服务消费方 order-service启动类添加扫描路径

    @EnableFeignClients(basePackages = {“com.api”}, clients = {ProductApi.class})

    其中basePackages为扫描路径,clients为需要加载的Feign客户端

    package com.order;import com.api.ProductApi;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.openfeign.EnableFeignClients;@EnableFeignClients(basePackages = {"com.api"}, clients = {ProductApi.class})
    @SpringBootApplication
    public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class, args);}
    }
    

完成上述配置后即可进行远程测试调用:

在这里插入图片描述

:若需要将服务部署到服务器上,需要修改服务消费方的pom文件,因为其使用了部署在本地Maven仓库的jar包:

<dependency><groupId>org.example</groupId><artifactId>product-api</artifactId><version>1.0-SNAPSHOT</version>
<!--  <scope>compile</scope>--><scope>system</scope><systemPath>D:/maven_test/.m2/repository/org/example/product-api/1.0-SNAPSHOT/product-api-1.0-SNAPSHOT.jar</systemPath>
</dependency><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><includeSystemScope>true</includeSystemScope></configuration></plugin>
</plugins>

以上便是对OpenFeign的使用介绍了!!如果内容对大家有帮助的话请给这篇文章一个三连关注吧💕( •̀ ω •́ )✧( •̀ ω •́ )✧✨

关键字:SpringCLoud OpenFeign的使用介绍

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: