声明式的 HTTP 客户端Feign的应用

        近期在写商城项目(微服务)的时候遇到一些问题,例如创建订单的情况下,我要知道用户信息、商品信息,为了降低表结构的繁琐性,通常我使用的是一些外联表(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启动网址:

http://localhost:8848/nacos

服务列表下的两个服务已正常启动,使用Postman测试是否可以正常运行,POST方式:

http://localhost:8038/api/order/buy

参数为JSON格式:

{
    "userId": "1",
    "commodityId": "1",
    "buyNum": 5
}

测试结果为:

有其他问题可私聊博主

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值