SpringCloud原理-OpenFeign篇(一、Hello OpenFeign项目示例)

本文详细介绍了使用SpringCloudOpenFeign构建的简单服务调用链路,包括FeignClient的使用、服务间的RPC调用过程以及代码实现。重点展示了如何通过OpenFeign封装远程调用,简化开发过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

本篇是SpringCloud原理系列的 OpenFeign 模块的第一篇。主要内容是搭建一个极简的Spring Cloud OpenFeign 调用链路。

项目代码仓库地址:https://gitee.com/fengsoshuai/springcloud-openfeign-demo

正文

本次项目使用java 17,spring cloud 4.0.4,springboot 3.1.4。
maven 环境编译,idea开发。

一、项目结构

本次项目分为3个模块。
在这里插入图片描述
在这里插入图片描述

二、服务调用链路说明

在这里插入图片描述

  1. 使用IDEA/Postman/Apifox等工具进行触发client服务的接口
  2. client内部通过feign调用server接口
  3. server执行业务逻辑
  4. server返回执行结果到client
  5. client返回调用结果到触发方

三、Rpc调用链路说明

两个服务之间,使用远程调用。
基本都是需要URL,请求头,请求报文,请求方式(Get\Post 等)等基本信息的。
下图简单说明rpc调用时的链路。
在这里插入图片描述
其中,调用方,相当于发起远程调用的一方,对比本项目的话,相当于使用postman等工具触发后,client模块的操作。

只是特殊的一点在于,调用方中的红色虚线框内的部分,被openFeign 封装了,不再是我们手动去处理他们。而这也正是本系列研究的重点。

中间部分,就是形如 RestTemplate,WebClient的功能,只是发出请求,接受响应。

服务方,就是一个提供rest接口的普通应用。

四、项目代码

本文全部代码托管在gitte仓库中,地址已经在文章开头给出。
这里只粘贴出比较重要的几个文件。

4.1 client 模块中的feign接口

package org.feng.feigns;

import org.feng.common.dto.HelloRequest;
import org.feng.common.dto.HelloResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

/**
 * hello-feign客户端接口
 *
 * @version v1.0
 * @author: fengjinsong
 * @date: 2023年11月20日 21时25分
 */
@FeignClient(name = "helloFeignClient", url = "http://localhost:10080")
public interface HelloFeignClient {

    @PostMapping("/hello/post")
    HelloResponse postHello(@RequestBody HelloRequest helloRequest);
}

4.2 client 中的rest接口

package org.feng.controller;

import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.feng.common.dto.HelloRequest;
import org.feng.common.dto.HelloResponse;
import org.feng.feigns.HelloFeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * HelloFeignClientController
 *
 * @version v1.0
 * @author: fengjinsong
 * @date: 2023年11月20日 21时45分
 */
@Slf4j
@RestController
@RequestMapping("/helloclient")
public class HelloFeignClientController {

    @Resource
    private HelloFeignClient helloFeignClient;

    @PostMapping("/postHello")
    public HelloResponse postHello(@RequestBody HelloRequest helloRequest) {
        if(Objects.isNull(helloRequest.getLocalDateTime())){
            helloRequest.setLocalDateTime(LocalDateTime.now());
        }

        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        String localAddr = request.getLocalAddr();
        int serverPort = request.getServerPort();
        helloRequest.setHost(localAddr);
        helloRequest.setPort(serverPort);

        log.info("helloRequest  {}", helloRequest);
        return helloFeignClient.postHello(helloRequest);
    }
}

4.3 client 中的启动类

指定扫描包为 org.feng.feigns

package org.feng;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableFeignClients(basePackages = "org.feng.feigns")
@SpringBootApplication
public class ClientApplication {

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

}

4.4 server中的rest接口

package org.feng.controller;

import lombok.extern.slf4j.Slf4j;
import org.feng.common.dto.HelloRequest;
import org.feng.common.dto.HelloResponse;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * openfeign 控制器
 *
 * @author feng
 */
@Slf4j
@RequestMapping("/hello")
@RestController
public class HelloOpenFeignController {

    @PostMapping("/post")
    public HelloResponse postHello(@RequestBody HelloRequest helloRequest) {
        log.info("request:{}", helloRequest);

        HelloResponse response = new HelloResponse();
        response.setTitle(helloRequest.getTitle());
        response.setLocalDateTime(helloRequest.getLocalDateTime());
        response.setFromHost(helloRequest.getHost());
        response.setFromPort(helloRequest.getPort());

        log.info("response: {}", response);
        return response;
    }
}


4.5 server中的配置文件

spring.application.name=openserver
server.port=10080

五、调试

启动server 和 client 服务。
在idea中触发client 的服务:

POST http://localhost:8080/helloclient/postHello
Content-Type: application/json

{
  "title": "托尔斯泰"
}

响应报文如下:

{
  "fromHost": "127.0.0.1",
  "fromPort": 8080,
  "title": "托尔斯泰",
  "localDateTime": "2023-11-21T14:07:18.537384"
}

server中的服务,打印出来的日志如下:
在这里插入图片描述
以上就是通过onepfeign 进行rpc 调用的完整示例了。

可以看到,我们只在client中定义了接口,并没有实现。但是在调用时,没有报错,同时也调用到了server服务。而这,就是spring cloud 中的 openfeign 封装了远程调用,帮我们处理的部分,也是我们后续研究其原理的核心部分。

附录

附1:本系列文章链接

SpringCloud系列文章目录(总纲篇)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你家宝宝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值