简介: 本文档介绍如何在微服务架构中使用Spring Cloud的OpenFeign进行服务间的远程调用。首先,需在项目中引入OpenFeign及其负载均衡器依赖。接着,通过@EnableFeignClients启用Feign客户端功能,并定义客户端接口以声明远程服务调用逻辑。为确保启动类能正确扫描到这些接口,需指定basePackages属性。最后,演示了如何在购物车服务中利用Feign客户端接口调用商品服务,以实现跨服务的数据整合和查询。Feign通过动态代理机制简化了HTTP请求的发起过程,使服务间交互更为直观和便捷。
1.引入OpenFeign依赖:
<!--openFeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--负载均衡器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
2.开启OpenFeign客户端功能并创建client接口:
package com.wcl.api.client;
import com.wcl.common.utils.general.CommonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(value = "cart-service")
public interface CartClient {
/**
* 购物车移除商品
*
* @param cartId 购物车商品编号
*/
@RequestMapping(value = "/shoppingCart/deleteById")
public CommonResult deleteShoppingCart(Integer cartId);
}
@SpringBootApplication
@EnableFeignClients(basePackages = "com.wcl.api.client",defaultConfiguration = DefaultFigenConfig.class)
public class CartApplication {
public static void main(String[] args) {
SpringApplication.run(CartApplication.class, args);
}
}
需要通过@EnableFeignClients来启动Feign的客户端功能,同时由于我的所有服务的client由于方便管理所以统一放在了一个模块中,然后服务引入该模块依赖,但是这样的话启动类将无法扫描到client接口,所以我使用@EnableFeignClients注解的basePackages属性来指定feign的接口让spring来扫描注册(若是没有添加该注解,或者没有扫描到client接口,那么会报404错误,所以请大家谨记!)
3.使用client接口:
列如:一个购物车查询接口,他需要通过购物车表与商品表进行连接查询获取数据,但是在微服务中购物车表与商品表被分别拆分在了购物车服务与商品服务中(两个不同的数据库中),那么以往的连接查询将不再适用,这是需要通过在购物车服务中通过OpenFeign接口运行去调用商品服务获取相应数据然后进行数据合并如下
/**
* 查询用户购物车商品信息
* @param accountNumber 账号信息
* @return
*/
@Override
public List<ShoppingCartAllVo> selectAll(String accountNumber) {
// 查询用户购物车商品信息
List<ShoppingCart> shoppingCarts = shoppingCartDao.selectAll(accountNumber);
ArrayList<Integer> productIds = new ArrayList<>();
for (ShoppingCart shoppingCart : shoppingCarts) {
productIds.add(shoppingCart.getProductId());
}
// 查询商品详细信息
List<Map<String, Object>> productsMaps = (List<Map<String, Object>>) productClient.findByIds(productIds).getData();
//进行数据转换
List<Product> products = convertToProductList(productsMaps);
//将商品信息封装到map中
HashMap<Integer, Product> productHashMap = new HashMap<>();
for (Product product : products) {
productHashMap.put(product.getProductId(), product);
}
ArrayList<ShoppingCartAllVo> shoppingCartAllVos=null;
//将购物车信息和商品信息封装到vo中
shoppingCartAllVos = getShoppingCartAllVos(shoppingCarts, productHashMap, shoppingCartAllVos);
return shoppingCartAllVos;
}
/**
* 数据转换
* @param productsMaps
* @return
*/
private List<Product> convertToProductList(List<Map<String, Object>> productsMaps) {
List<Product> products = new ArrayList<>();
for (Map<String, Object> productMap : productsMaps) {
Product product = new Product();
product.setProductId((Integer) productMap.get("productId"));
product.setProductName((String) productMap.get("productName"));
product.setProductStock((Integer) productMap.get("productStock"));
product.setProductUrl((String) productMap.get("productUrl"));
product.setOutPrice((Double) productMap.get("outPrice")); // 假设outPrice是Double类型
product.setProductNo((String) productMap.get("productNo"));
products.add(product);
}
return products;
}
/**
* 将购物车信息和商品信息封装到vo中
* @param shoppingCarts
* @param productHashMap
* @param shoppingCartAllVos
* @return
*/
private ArrayList<ShoppingCartAllVo> getShoppingCartAllVos(List<ShoppingCart> shoppingCarts, HashMap<Integer, Product> productHashMap, ArrayList<ShoppingCartAllVo> shoppingCartAllVos) {
//将购物车信息和商品信息封装到vo中
if (shoppingCarts !=null){
shoppingCartAllVos =new ArrayList<>();
for (ShoppingCart shoppingCart : shoppingCarts) {
ShoppingCartAllVo shoppingCartAllVo = new ShoppingCartAllVo();
shoppingCartAllVo.setCartId(shoppingCart.getCartId());
shoppingCartAllVo.setAccountNumber(shoppingCart.getAccountNumber());
shoppingCartAllVo.setProductId(shoppingCart.getProductId());
shoppingCartAllVo.setPayAmount(shoppingCart.getPayAmount());
shoppingCartAllVo.setProductSpecs(shoppingCart.getProductSpecs());
shoppingCartAllVo.setProductStock(productHashMap.get(shoppingCart.getProductId()).getProductStock());
shoppingCartAllVo.setProductUrl(productHashMap.get(shoppingCart.getProductId()).getProductUrl());
shoppingCartAllVo.setProductName(productHashMap.get(shoppingCart.getProductId()).getProductName());
shoppingCartAllVo.setProductPrice(productHashMap.get(shoppingCart.getProductId()).getOutPrice());
shoppingCartAllVo.setProductNo(productHashMap.get(shoppingCart.getProductId()).getProductNo());
shoppingCartAllVos.add(shoppingCartAllVo);
}
}
return shoppingCartAllVos;
}
在其中我们主要通过使用client接口的方法就可以实现服务调用:
// 查询商品详细信息
List<Map<String, Object>> productsMaps = (List<Map<String, Object>>) productClient.findByIds(productIds).getData();
使用了这个方法后,OpenFeign就会通过动态代理的方式自动的通过相应的接口方法配置去帮我们发送请求到相应的服务接口进行处理