近期在写商城项目(微服务)的时候遇到一些问题,例如创建订单的情况下,我要知道用户信息、商品信息,为了降低表结构的繁琐性,通常我使用的是一些外联表(join)进行SQL语句的编写,其实完全可以使用Feign来进行各个模块之间的接口调用。但是论SQL性能,三次SQL语句查询创建、与一次查询创建(使用外联表join的SQL语句)是有一定差距的。抛开性能不谈,这也是一种实现方法。
1、首先需要导入Nacos依赖,我们需要将各个服务模块注册成Nacos服务
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2、引入Feign依赖
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
3、在订单模块Order下创建Feign接口
其代码为:
CommodityFeignClient
@FeignClient(name = "commodity-service")
public interface CommodityFeignClient {
@GetMapping("/api/feign/commodity/getCommodityById/{id}")
CommodityDto getCommodityById(@PathVariable("id") Integer id);
}
UserFeignClient
@FeignClient(name = "user-service")
public interface UserFeignClient {
@GetMapping("/api/feign/user/getUserById/{userId}")
User getUserById(@PathVariable("userId") Integer userId);
}
4、创建Commodity商品模块的Feign所调用的API、创建User用户模块的Feign所调用的API(后续查询实现类代码不在添加)
@Slf4j
@RestController
@RequestMapping("/api/feign/commodity")
public class CommodityFeignController {
@Autowired
private CommodityService commodityService;
@GetMapping("/getCommodityById/{id}")
public CommodityDto getCommodityById(@PathVariable("id") Integer id) {
log.info("feign调用commodity-service服务");
CommodityDto commodityDto = commodityService.getCommodityById(id);
return commodityDto;
}
}
@Slf4j
@RestController
@RequestMapping("/api/feign/user")
public class UserFeignController {
@Autowired
private UserService userService;
@RequestMapping("/getUserById/{userId}")
public User getUserById(@PathVariable("userId") Integer userId) {
log.info("feign调用user-service服务");
User user = userService.getUserById(userId);
return user;
}
}
5、Order模块代码(只展示控制层、实现层代码)
控制层:
@Slf4j
@RestController
@RequestMapping("/api/order")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping("/buy")
public OrderDto createOrder(@RequestBody Map<String, Object> payload) {
// 先获取当前用户ID
int userId = Integer.parseInt(payload.get("userId").toString());
// 获取当前的商品ID
int commodityId = Integer.parseInt(payload.get("commodityId").toString());
// 购买的商品数量
int buyNum = (Integer) payload.get("buyNum");
// 生成订单Order
Order order = new Order();
order.setUserId(userId);
order.setCommodityId(commodityId);
order.setCommodityBuyNum(buyNum);
OrderDto orderDto = orderService.createOrder(order);
return orderDto;
}
}
实现层:
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private CommodityFeignClient commodityFeignClient;
@Autowired
private UserFeignClient userFeignClient;
@Override
public OrderDto createOrder(Order order) {
// 获取订单基础信息
String userId = order.getUserId().toString();
String commodityId = order.getCommodityId().toString();
Integer buyNum = order.getCommodityBuyNum();
// 存入订单数据库
int orderId = orderMapper.createOrder(order);
log.info("用户ID:{},商品ID:{},购买数量:{}", userId, commodityId, buyNum);
// 通过Feign调用商品服务获取商品信息
CommodityDto commodityById = commodityFeignClient.getCommodityById(Integer.parseInt(commodityId));
User userById = userFeignClient.getUserById(Integer.parseInt(userId));
// 生成订单信息------这个只是返回的订单信息,没有保存到数据库中
OrderDto orderDto = new OrderDto();
orderDto.setOrderId(orderId);
orderDto.setUserName(userById.getName());
orderDto.setUserId(Integer.parseInt(userId));
orderDto.setCommodityId(Integer.parseInt(commodityId));
orderDto.setCommodityName(commodityById.getCommodityName());
orderDto.setPrice(commodityById.getPrice());
orderDto.setBuyNum(buyNum);
orderDto.setTotalPrice(commodityById.getPrice() * buyNum);
log.info("订单详细信息:{}", JSON.toJSONString(orderDto));
// 返回数据
return orderDto;
}
}
6、修改Commodity、User项目所注册到Nacos的服务名(修改配置文件)
Commodity:
spring:
application:
name: commodity-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
User:
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
7、最后一步,启动类上一定要加注解
Commodity、User启动类上需要加Nacos注解
Order订单模块需要加上Feign的客户端注解
启动三个服务,查看当前的Nacos中是否有User、Commodity服务注册
本地Nacos启动网址:
服务列表下的两个服务已正常启动,使用Postman测试是否可以正常运行,POST方式:
http://localhost:8038/api/order/buy
参数为JSON格式:
{
"userId": "1",
"commodityId": "1",
"buyNum": 5
}
测试结果为:
有其他问题可私聊博主