微服务(十)—— Feign的使用

上一篇:微服务(九)—— 日志管理.

目录

      • 1.介绍
      • 2. 使用
        • 2.1 提供服务方
        • 2.2 调用方

1.介绍

微服务就是将一个应用拆分成多个小的系统,每个系统有独立的功能,但是如果是系统间的调用该怎么办呢?这时候就可以使用Feign来进行服务间的通信,Feign是一个声明式RESTful HTTP请求客户端,调用方也就是消费服务的模块可以通过Feign提供的接口进行访问提供服务的模块。

2. 使用

因为是通过Feign对外提供接口进行调用的,所以可以将Feign接口独立出来。
类似于Maven父子工程一样新建一个Maven工程backend-service-api,删除src文件,只留pom.xml文件即可;然后创建需要提供服务的接口。
我这里只有产品模块和收货地址模块会对外提供服务,所以创建两个Maven工程,里面只有Feign接口和对应的实体类。项目目录结构如下:
微服务(十)—— Feign的使用_第1张图片

以产品接口为例:
看一下ProductFeign接口:

package com.aiun.product.feign;
@FeignClient(value="backend-product", path="backend-product")
@RequestMapping("/product/")
public interface ProductFeign {
    @GetMapping("{id}")
    Product findById(@PathVariable(name="id") Integer id);

    @RequestMapping(value = "update",method = RequestMethod.GET)
    void updateStockById(@RequestParam("id") Integer id, @RequestParam("stock") int stock);
}

产品模块提供两个服务接口。
下面从提供服务模块和调用服务模块两方面介绍。

2.1 提供服务方

提供服务方比较简单,只需要在Controller增加和Feign接口对应的接口就可以了,如下:

@Api(tags = "产品相关接口")
@RestController
@RequestMapping("/product/")
public class ProductController {
    @Value("${image.localhost}")
    private String mageHost;
    @Autowired
    private IProductService iProductService;
    @Autowired
    private IFileService iFileService;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
 /**
     * 对外提供的服务
     * 根据ID查询Sku数据
     * @param id 产品 id
     * @return 产品信息类
     */
    @GetMapping("{id}")
    public Product findById(@PathVariable(name="id") Integer id){
        return iProductService.findById(id);
    }

    /**
     * 对外提供的服务
     * 更新产品库存数量信息
     * @param id 产品 id
     * @param stock 产品库存
     * @return 操作影响行数
     */
    @PostMapping("update")
    public void updateStockById(@RequestParam("id") Integer id, @RequestParam("stock") int stock){
        iProductService.updateStockById(id, stock);
    }
}

然后Controller调用Service,然后访问Dao取到数据返回即可。
除此之外提供服务方不需要做任何改动,不需要Feign依赖,不需要配置,不需要注解等。

2.2 调用方

调用方需要引入Feign的依赖,还需要引入提供接口的Maven依赖,使用对应的实体类。如下:


<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-openfeignartifactId>
    <version>2.1.0.RELEASEversion>
dependency>


<dependency>
    <groupId>com.aiungroupId>
    <artifactId>backend-service-user-apiartifactId>
    <version>1.0-SNAPSHOTversion>
dependency>

<dependency>
    <groupId>com.aiungroupId>
    <artifactId>backend-service-product-apiartifactId>
    <version>1.0-SNAPSHOTversion>
dependency>

<dependency>
    <groupId>com.aiungroupId>
    <artifactId>backend-service-shipping-apiartifactId>
    <version>1.0-SNAPSHOTversion>
dependency>

然后需要在启动类加@EnableFeignClients注解,如下:

package com.aiun.order;
/**
 * 后台启动类
 * @author lenovo
 */
@EnableSwagger2
@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients(basePackages = {"com.aiun.product.feign", "com.aiun.shipping.feign"})
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

@EnableFeignClients注解的basePackages属性表示Feign接口所在的包。
然后在需要使用产品和收货地址模块的地方调用对外提供Feign接口。
我在Service层的实现类OrderServiceImpl调用ProductFeign和ShippingFeign接口,如下:

@Service("iOrderService")
public class OrderServiceImpl implements IOrderService {
    @Autowired
    private ProductFeign productFeign;
    @Autowired
    private ShippingFeign shippingFeign;
	
	/**
     * 减少商品库存
     * @param orderItemList 订单详情列表
     */
    private void reduceProductStock(List<OrderItem> orderItemList) {
        orderItemList.forEach(e->{
            Product product = productFeign.findById(e.getProductId());
            productFeign.updateStockById(e.getProductId(), product.getStock() - e.getQuantity());
        });
    }
	//......

然后像调用Dao层一样调用Feign接口就可以了。
Feign注意点:
SpringCloud对Feign进行了增强兼容了SpringMVC的注解 ,我们在使用SpringMVC的注解时需要注意:

  • 1、feignClient接口 有参数在参数必须加@PathVariable(“XXX”)或者@RequestParam(“XXX”)
  • 2、feignClient返回值为复杂对象时其类型必须有无参构造函数。

下一篇: 微服务(十一)—— 单点登录.

你可能感兴趣的:(#,SpringCloud,微服务,spring,cloud)