微服务开发系列 第三篇:OpenFeign

news2025/1/16 9:16:45

总概

A、技术栈

  • 开发语言:Java 1.8
  • 数据库:MySQL、Redis、MongoDB、Elasticsearch
  • 微服务框架:Spring Cloud Alibaba
  • 微服务网关:Spring Cloud Gateway
  • 服务注册和配置中心:Nacos
  • 分布式事务:Seata
  • 链路追踪框架:Sleuth
  • 服务降级与熔断:Sentinel
  • ORM框架:MyBatis-Plus
  • 分布式任务调度平台:XXL-JOB
  • 消息中间件:RocketMQ
  • 分布式锁:Redisson
  • 权限:OAuth2
  • DevOps:Jenkins、Docker、K8S

B、本节实现目标

  • 新建mall-feign服务。
  • 新建mall-order服务。
  • 实现下单接口

一、Spring Cloud OpenFeign简介

Spring Cloud OpenFeign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用OpenFeign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问HTTP请求。

二、新建mall-feign服务

2.1 新建module

新建module

新建mall-feign

2.2 新建.gitignore

.idea
.mvn
target
mvnw
*.iml

2.3 配置pom.xml

参考mall-member服务配置pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>mall-pom</artifactId>
        <groupId>com.ac</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.ac</groupId>
    <artifactId>mall-feign</artifactId>
    <version>${mall.version}</version>
    <name>mall-feign</name>
    <description>OpenFeign服务</description>

    <dependencies>
        <dependency>
            <groupId>com.ac</groupId>
            <artifactId>mall-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2.4 加OpenFeign依赖

在mall-pom的pom.xml里加入mavn依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>${alibaba.cloud.version}</version>
</dependency>

2.5 提供用户查询的Feign接口

package com.ac.feign.member.api;

import com.ac.feign.member.dto.MemberDTO;
import io.swagger.annotations.ApiOperation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient("mall-member")
public interface MemberFeignApi {

    @ApiOperation(value = "获取用户")
    @GetMapping("member/{id}")
    MemberDTO findMember(@PathVariable("id") Long id);

}

2.5.1 说明NO.1

@FeignClient("mall-member")中的"mall-member"是member服务注册在Nacos上的服务名称,

mall-member

2.5.2 说明NO.2

@PathVariable("id") Long id ,@PathVariable括号里的“id”不能少,否则其他依赖mall-feign服务的代码启动会报错,MemberFeignApi注入失败。

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.ac.feign.member.api.MemberFeignApi': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: PathVariable annotation was empty on param 0.

2.6 mall-feign项目结构截图

mall-feign项目结构截图

2.7 关于OpenFeign位置说明

OpenFeign位置一般有两种,

  • 第一种:在各个服务中写需要用的OpenFeign接口。
  • 第二种:将项目中所有的OpenFeign接口抽取出来,放到一个公共的feign服务中,如上面创建的mall-feign服务,然后其他各个服务都依赖这个mall-feign。

很明显,我采用的是第二种,理由是,一个OpenFeign接口可能很多服务都需要用,比如,大部分服务都会通过OpenFeign来取用户数据,如果采用方案一,各个服务都要写一遍MemberFeignApi,如果采用第二种方案,则mall-feign里的MemberFeignApi能被各服务共用。

三、新建mall-order服务

参考mall-feign新建mall-order服务,具体操作步骤省略。

3.1 依赖mall-feign服务

mall-order需要依赖mall-feign服务,因此在pom.xml里配置依赖项

<dependency>
    <groupId>com.ac</groupId>
    <artifactId>mall-feign</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

pom.xml依赖项

3.2 @EnableFeignClients注解

在mall-order的Application类上,加上注解@EnableFeignClients注解,@EnableFeignClients申明该项目是Feign客户端,扫描对应的feign client。

@MapperScan("com.ac.order.mapper")
@ComponentScan("com.ac.*")
@EnableFeignClients(basePackages = {"com.ac.feign.*"})
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

3.2.1 说明NO.1

@EnableFeignClients(basePackages = {"com.ac.feign.*"}) ,中配置了basePackages,让IOC容器去扫描mall-feign服务里的接口。

如果不配置,mall-order服务启动时会报错

A component required a bean of type 'com.ac.feign.member.api.MemberFeignApi' that could not be found.

3.3 调用MemberFeignApi测试

@Api(tags = "订单")
@RestController
@RequestMapping("order")
public class OrderController {

    @Resource
    private MemberFeignApi memberFeignApi;

    @ApiOperation(value = "通过OpenFeign取用户数据")
    @GetMapping("feign/member/{id}")
    public MemberDTO test(@PathVariable Long id) {
        return memberFeignApi.findMember(id);
    }
}

测试结果

项目结构截图

四、下单接口

下单接口需要通过memberId调用mall-member服务的用户信息,通过productId调用mall-product服务的产品信息,代码如下:

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderDao orderDaoImpl;

    @Resource
    private MemberFeignApi memberFeignApi;

    @Resource
    private OrderItemService orderItemServiceImpl;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long createOrder(OrderAddVO addVO) {
        Order order = new Order();
        order.setOrderNo(RandomUtil.randomNumbers(8));
        order.setOrderState(OrderStateEnum.UN_PAY);
        order.setOrderTime(LocalDateTime.now());

        //通过feign取用户信息
        MemberDTO member = memberFeignApi.findMember(addVO.getMemberId());
        order.setMemberId(addVO.getMemberId());
        order.setMemberName(member.getMemberName());
        order.setMobile(member.getMobile());
        orderDaoImpl.save(order);

        BigDecimal discountAmount = new BigDecimal(0.00);
        BigDecimal productAmount = new BigDecimal(0.00);
        //存订单项信息
        for (OrderItemAddVO orderItemAdd : addVO.getOrderItemList()) {
            OrderItem orderItem = orderItemServiceImpl.addOrderItem(order.getId(), orderItemAdd);
            productAmount = productAmount.add(orderItem.getBuyPrice().multiply(new BigDecimal(orderItem.getBuyNum())));
        }

        //更新订单金额信息
        order.setDiscountAmount(discountAmount);
        order.setProductAmount(productAmount);
        BigDecimal payAmount = productAmount.subtract(discountAmount);
        order.setPayAmount(payAmount);
        orderDaoImpl.updateById(order);

        return order.getId();
    }
}
@Slf4j
@Service
public class OrderItemServiceImpl implements OrderItemService {

    @Resource
    private OrderItemDao orderItemDaoImpl;

    @Resource
    private ProductFeignApi productFeignApi;

    @Override
    public OrderItem addOrderItem(Long orderId, OrderItemAddVO orderItemAdd) {
        //通过feign取产品信息
        ProductDTO product = productFeignApi.findProduct(orderItemAdd.getProductId());

        OrderItem entity = new OrderItem();
        entity.setOrderId(orderId);
        entity.setProductId(product.getId());
        entity.setProductName(product.getProductName());
        entity.setImageUrl(product.getImageUrl());
        entity.setBuyNum(orderItemAdd.getBuyNum());
        if (product.getDiscountPrice() != null && product.getDiscountPrice().doubleValue() > 0) {
            entity.setBuyPrice(product.getDiscountPrice());
        } else {
            entity.setBuyPrice(product.getSellPrice());
        }
        orderItemDaoImpl.save(entity);
        return entity;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/557478.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多维时序 | MATLAB实现GA-GRU遗传算法优化门控循环单元多变量时间序列预测

多维时序 | MATLAB实现GA-GRU遗传算法优化门控循环单元多变量时间序列预测 目录 多维时序 | MATLAB实现GA-GRU遗传算法优化门控循环单元多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 多维时序 | MATLAB实现GA-GRU遗传算法优化门控循环单元多变量时间…

OSPF 邻居关系 附实验

实验目的 通过对 OSPF 邻居关系建立进行相关的实验&#xff0c;从中学习到如何调整 OSPF Hello 包间隔&#xff0c;Dead 间隔&#xff0c;以及影响 OSPF 邻居建立的因素&#xff0c;例如 RID&#xff0c;MTU&#xff0c;OSPF 认证。并且将总结 OSPF在不同网络类型上的不同行为…

FPGA纯verilog实现CameraLink视频接收和发送,附带工程源码和技术支持

目录 1、前言2、CameraLink协议基础3、目前我已有的CameraLink收发工程4、设计方案5、CameraLink解码模块详解6、CameraLink编码模块详解7、vivado工程详解8、上板调试验证9、福利&#xff1a;工程代码的获取 1、前言 FPGA实现CameraLink视频编解码目前有两种方案&#xff1a;…

C++基本介绍

文章目录 &#x1f96d;1.C基本介绍&#x1f9c2;1.1 C是什么&#x1f9c2;1.2 C发展史 &#x1f352;2. C的优势&#x1f954;2.1 语言的使用广泛度&#x1f954;2.2 C的应用领域 &#x1fad2;3. C学习计划 &#x1f96d;1.C基本介绍 &#x1f9c2;1.1 C是什么 C是一种通用…

用streamlit,几行代码就可以拥有漂亮图表!

大家注意&#xff1a;因为微信最近又改了推送机制&#xff0c;经常有小伙伴说错过了之前被删的文章&#xff0c;比如前阵子冒着风险写的爬虫&#xff0c;再比如一些限时福利&#xff0c;错过了就是错过了。 所以建议大家加个星标&#xff0c;就能第一时间收到推送。&#x1f44…

FastAPI 和 fastapi-amis-admin:强大而可扩展的后台管理解决方案!

大家好&#xff0c;我是安果&#xff01; 我们都知道 Django 生态丰富&#xff0c;功能强大&#xff0c;适用于中、大型项目&#xff0c;并且自带了后台管理系统&#xff1b;而 FastAPI 更适用于构建高性能的 API&#xff0c;后台管理系统需要另外开发 本篇文章将介绍 FastAPI…

完犊子!原单位的离职证明丢了,下周要入职了,用AI做一个行不行?

弄丢了离职证明怎么办&#xff1f; 一位网友哀叹&#xff1a; 完犊子&#xff01;原单位的离职证明丢了&#xff0c;下周要入职了&#xff0c;现在怎么办&#xff1f;用AI做一个行不行&#xff1f; 有相同经历的网友安慰他&#xff0c;离职证明没了没事&#xff0c;新公司会要求…

打卡智能中国(五):博士都去哪儿了?

《打卡智能中国》系列更新了几期&#xff0c;有读者表示&#xff0c;很爱看这类接地气的真实故事&#xff0c;也有读者反映&#xff0c;不是电工&#xff0c;就是文员、农民、治沙人&#xff0c;人工智能不是高精尖学科吗&#xff1f;那些学历很高的博士都去哪儿了&#xff1f;…

用数据讲故事:十大统计学/机器学习魔法指数

统计学和机器学习为数据分析提供理论基础&#xff0c;入门时我看过很多统计学相关书籍&#xff0c;复杂的公式和推导过程让我一度陷入迷茫。对于数据科学/分析师来说&#xff0c;如何使用统计学知识并应用到我们的分析场景中更为重要。本文主要基于数据分析工作中的实际应用场景…

1000本!计算机经典书籍分享

闲话少说&#xff0c;列表如下。 编程语言类书籍 包含&#xff1a;Java、C、C、Python、Go等语言 Java电子书大全https://www.yingyanshe.cn/5275.htmlC电子书大全https://www.yingyanshe.cn/5284.htmlC语言类电子书https://www.yingyanshe.cn/5293.htmlC#电子书https://www…

chatgpt赋能Python-python_fg

Python FG: 优秀的Python工程师一定要知道的资源 如果你是一名Python工程师&#xff0c;那么你一定会喜欢Python FG资源。Python FG是一个在线平台&#xff0c;提供海量的Python API文档、教程、实例、以及与Python有关的各种工具和资源&#xff0c;让Python工程师轻松学习和使…

盘点!Instruction Tuning 时代的大模型

作者 | Kevin吴嘉文 整理 | NewBeeNLP 公众号 https://zhuanlan.zhihu.com/p/616830127 Alpaca&#xff0c;ChatGLM 等模型的效果可以接受&#xff0c;下文总结部分笔记&#xff0c;为训练自定义小型化&#xff08;7B&#xff09;模型提供点知识储备。包括模型论文 LaMDA, Mup…

纯净版Win10系统重装教程(超详细)

本博客详细讲解纯净版Win10系统重装&#xff0c;步骤齐全&#xff0c;小白可实操。 纯净版Win10系统重装教程 系统安装前准备下载安装工具更新重装 制作U盘为启动盘 重装Win10进入Boot模式选择系统版本分区系统安装中新系统配置 系统安装前准备 ➢ 准备8G或8G以上的空U盘。&a…

POSTGRESQL 10个使用POSTGRESQL 需要避免的错误 (译)

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

EOS网络基金会大战Block.One

微信公众号修改了推送规则&#xff0c;请各位亲爱的读者给刘教链公众号添加星标&#x1f31f;&#xff0c;以便及时收到每日最新文章推送&#xff01; 星标&#x1f31f;添加方法&#xff1a;【1】点击标题下方“刘教链 刘教链”的第二个“刘教链”&#xff0c;打开公众号主页&…

chatgpt赋能Python-python_field

Python在Field上的应用 Python作为一门高级编程语言&#xff0c;在众多领域中扮演着应用广泛、易于学习、使用简便、速度出色的角色。在本文中&#xff0c;我们将重点关注Python在Field上的应用。 Field是什么&#xff1f; Field指的是“领域”&#xff0c;包括科学、工程、…

活动报名|分布式人工智能:可扩展性、效率和泛化性

2023年05月25日&#xff08;星期四&#xff09;14:00-15:30&#xff0c;智源社区「智源Live 第42期」线上活动将在线举办&#xff0c;「阅读原文」报名即可参加。 活动主题&#xff1a;分布式人工智能&#xff1a;可扩展性、效率和泛化性 安波 安波是新加坡南洋理工大学校长委员…

chatgpt赋能Python-python_for_end

Python for End: 介绍 Python是一种高级编程语言&#xff0c;由Guido van Rossum创建于1989年&#xff0c;并在1991年正式发布。Python是一种多范式编程语言&#xff0c;可以用于面向对象、函数式和过程式编程。它拥有简单易懂的语法以及扩展性强的库&#xff0c;从而使得开发…

见证ES6革命:深入学习let、const、var的区别、解构赋值、箭头函数等常用知识点,开创全新开发模式。

let、const、var的区别 使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象。使用let声明的变量,其作用域为该语句所在的代码块内,不存在变量提升。使用const声明的是常量,在后面出现的代码块中,不能在修改改常量的值。 var let const 函数级作用域 块级…

ThingsBoard教程(五十):规则节点解析 创建关系节点Create Relation Node,删除关系节点 Delete Relation Node

创建关系节点 Create Relation Node Since TB Version 2.2.1 根据类型和方向,从所选实体创建到消息发起方的关系。 以下消息发起方类型被允许:资产、设备、实体视图、客户、租、仪表板。 通过元数据键模式查找目标实体,然后在源实体和目标实体之间创建关系。 如果选择的…