上一篇:微服务(九)—— 日志管理.
微服务就是将一个应用拆分成多个小的系统,每个系统有独立的功能,但是如果是系统间的调用该怎么办呢?这时候就可以使用Feign来进行服务间的通信,Feign是一个声明式RESTful HTTP请求客户端,调用方也就是消费服务的模块可以通过Feign提供的接口进行访问提供服务的模块。
因为是通过Feign对外提供接口进行调用的,所以可以将Feign接口独立出来。
类似于Maven父子工程一样新建一个Maven工程backend-service-api,删除src文件,只留pom.xml文件即可;然后创建需要提供服务的接口。
我这里只有产品模块和收货地址模块会对外提供服务,所以创建两个Maven工程,里面只有Feign接口和对应的实体类。项目目录结构如下:
以产品接口为例:
看一下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);
}
产品模块提供两个服务接口。
下面从提供服务模块和调用服务模块两方面介绍。
提供服务方比较简单,只需要在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依赖,不需要配置,不需要注解等。
调用方需要引入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的注解时需要注意:
下一篇: 微服务(十一)—— 单点登录.