微服务最重要的一个功能是服务间调用,各个服务互相依赖。比如电商系统有订单服务,有库存服务。在我们购买一件商品的时候,需要生成订单和减库存。这里我们就要用到服务间调用Feign。
Feign是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。
接下来我们新建两个module,一个app-order,一个app-storage;app-order作为调用方,app-storage作为被调用方。使用mybatis-plus作为数据处理框架。使用lombok简化代码(idea需要按照lombok插件,否则会报错)
1.8
Hoxton.SR1
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-openfeign
com.baomidou
mybatis-plus-boot-starter
3.3.1.tmp
mysql
mysql-connector-java
runtime
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
# 设置端口号
server.port=9920
# 设置服务名称
spring.application.name=app-storage
# 设置eureka
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
eureka.instance.instance-id=${spring.application.name}:${server.port}
# 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/storage?allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
CREATE TABLE `tb_storage` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`commodity_code` varchar(255) DEFAULT NULL,
`count` int(11) DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY (`commodity_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
预制数据
INSERT INTO `storage`(`id`, `commodity_code`, `count`) VALUES (1, 'product-1', 9999999);
@SpringBootApplication
@EnableEurekaClient // 开启eureka客户端模式
@MapperScan("com.ipp.springcloud.appstorage.mapper") // mybatis扫描
public class AppOrderApplication {
public static void main(String[] args) {
SpringApplication.run(AppOrderApplication.class, args);
}
}
可以用mybatis-plus代码生成插件去生成以上代码,篇幅问题不在此处做详细展示,详细内容请查看git仓库。
controller
/**
* 减库存
* @param commodityCode 商品代码
* @param count 数量
* @return
*/
@RequestMapping(path = "/deduct")
public Boolean deduct(String commodityCode, Integer count) {
storageService.deduct(commodityCode, count);
return true;
}
service
@Override
public void deduct(String commodityCode, int count) {
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.setEntity(new Storage().setCommodityCode(commodityCode));
Storage storage = baseMapper.selectOne(wrapper);
storage.setCount(storage.getCount() - count);
baseMapper.updateById(storage);
}
内容与app-storage一致
# 设置端口号
server.port=9910
# 设置服务名称
spring.application.name=app-order
# 设置eureka
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
eureka.instance.instance-id=${spring.application.name}:${server.port}
# 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/order?allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
CREATE TABLE `tb_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` varchar(255) DEFAULT NULL,
`commodity_code` varchar(255) DEFAULT NULL,
`count` int(11) DEFAULT 0,
`money` int(11) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@SpringBootApplication
@EnableEurekaClient // 开启eureka客户端模式
@EnableFeignClients //开启feign请求
@MapperScan("com.ipp.springcloud.apporder.mapper") // mybatis扫描
public class AppOrderApplication {
public static void main(String[] args) {
SpringApplication.run(AppOrderApplication.class, args);
}
}
可以用mybatis-plus代码生成插件去生成以上代码,篇幅问题不在此处做详细展示,详细内容请查看git仓库。
@FeignClient(name = "APP-STORAGE")
public interface StorageFeignService {
/**
* 减库存
* @param commodityCode
* @param count
* @return
*/
@GetMapping("storage/deduct")
Boolean deduct(@RequestParam("commodityCode") String commodityCode, @RequestParam("count") Integer count);
}
这里的@FeignClient 中的name写的是app-storage服务的服务名称(也就是注册到eureka中的服务名称)
下面声明的deduct方法对应app-storage服务中的deduct接口
controller
@RequestMapping("/placeOrder/commit")
public Boolean placeOrderCommit() {
orderServiceImpl.placeOrder("1", "product-1", 1);
return true;
}
service
@Autowired
private StorageFeignService storageFeignService;
@Override
public void placeOrder(String userId, String commodityCode, Integer count) {
BigDecimal orderMoney = new BigDecimal(count).multiply(new BigDecimal(5));
Order order = new Order()
.setUserId(userId)
.setCommodityCode(commodityCode)
.setCount(count)
.setMoney(orderMoney);
baseMapper.insert(order);
storageFeignService.deduct(commodityCode, count);
}
依次启动server-eureka,app-storage,app-order
在浏览器中访问 http://127.0.0.1:9910/order/placeOrder/commit , 分别查看order表和storage表。是否生成了订单和减了库存