【springcloud学习(dalston.sr1)】使用Feign实现接口调用(八)

该系列项目整体介绍及源代码请参照前面写的一篇文章【springcloud学习(dalston.sr1)】项目整体介绍(含源代码)(一)

(一)Feign的理解

前面文章【springcloud学习(dalston.sr1)】服务消费者通过restTemplate来访问服务提供者(含源代码)(五)里提到了通过restTemplate进行接口调用,这里有个不好的地方,就是不同的接口,都需要手写restTemplate来调用,且需要自己实现返回结果的处理,自己转换json数据到实体类,且需要手工指定不同的请求类型(post、get、delete、put),极为不方便。

我们知道像mybaitis,我们直接声明一个DAO接口,结合mapper.xml文件,就能访问数据库了。那么访问http的URL,能否也声明一个接口,就能实现http请求的访问呢?答案是肯定的,feign就可以用来实现这个需求。

(二)通过Feign来实现http请求的访问

(1)首先我们在microservicecloud-api项目中,新建一个接口GoodsClientService,注意这个接口我们加了注解FeignClient,并且这个注解里,我们指定了服务名称为MICROSERVICECLOUD-GOODS。然后在其getGoods方法里,我们也加入了熟悉的GetMapping注解,并设置了请求的url为/goods/list

java 复制代码
package com.company.api.service;

import com.company.api.entity.Goods;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;

@FeignClient(value = "MICROSERVICECLOUD-GOODS", fallbackFactory = GoodsClientServiceFallbackFactory.class)
public interface GoodsClientService {

    @GetMapping("/goods/list")
    List<Goods> getGoods();
}

因为在前面microservicecloud-provider-8001项目中,我们有在controller提供这个http接口

(2)新建一个microservicecloud-consumer-feign模块,类似于microservicecloud-consumer-80项目,同样作为消费者,其整体结构如下:

(4)修改POM文件,增加其相关依赖(注意这个项目依赖于前面提到的microservicecloud-api的接口,所以需要引入microservicecloud-api项目)

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">
    <parent>
        <artifactId>springcloud2025</artifactId>
        <groupId>com.company</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>microservicecloud-consumer-feign</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.company</groupId>
            <artifactId>microservicecloud-api</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Feign相关支持 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
        <!-- ribbon相关 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

    </dependencies>
</project>

(5)新增application.yml配置文件

java 复制代码
server:
  port: 80

eureka:
  client:
    register-with-eureka: false #false表示不向注册中心注册自己
    service-url:
      defaultZone: http://localhost:7001/eureka/ #http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

#启用服务降级
feign:
  hystrix:
    enabled: true

(7)新增启动类和配置类

启动类

java 复制代码
package com.company.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;

//这里需要手动制定包扫描路径,否则识别不到API项目中的GoodsClientServiceFallbackFactory,导致项目无法启动
@SpringBootApplication(scanBasePackages = {"com.company.consumer","com.company.api.service"})
@EnableEurekaClient
@EnableFeignClients(basePackages = "com.company.api.service")
//因为Feign接口在另一个API项目中,且API项目的包和当前项目有点不一样,所以需要加上扫描包的范围,确保能扫描到
public class Consumer80FeignApplication {

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

这里需要注意的是启动类上面@EnableFeignClients(basePackages = "com.company.api.service"),需要能扫描到前面提到的microservicecloud-api项目中的接口GoodsClientService

配置类

java 复制代码
package com.company.consumer.config;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RetryRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ConfigBean {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    /**
     * 设置ribbon负载均衡的算法,默认是轮询算法,也即每个都轮询一次。
     * @return
     */
    @Bean
    public IRule myRule() {
         return new RoundRobinRule(); //默认是轮询算法,也即每个都轮询一次。
        // return new RandomRule(); //现在采用随机的算法
        // return new RetryRule(); //如果provider都是正常的话,则轮询。如果有1个不可用的话,则在尝试几次失败后,会自动轮询能正常使用的服务
    }
}

然后在控制器controller

java 复制代码
package com.company.consumer.controller;

import com.company.api.entity.Goods;
import com.company.api.service.GoodsClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
@RequestMapping("/consumer")
public class GoodsConsumerContrller {

    //private static final String REST_URL_PREFIX = "http://localhost:8001";
    private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-GOODS";

    @Autowired
    private GoodsClientService goodsClientService;

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/goods/list")
    public List<Goods> getGoods() {
        return restTemplate.exchange(REST_URL_PREFIX + "/goods/list", HttpMethod.GET,
             null,   new ParameterizedTypeReference<List<Goods>>(){}).getBody();
    }

    @GetMapping("/goods/list/feign")
    public List<Goods> getGoodsByFeign() {
        return goodsClientService.getGoods();
    }
}

注意:我们前面在microservicecloud-api项目中定义了一个接口GoodsClientService,需要注入到controller中,然后就可以使用该接口,调用getGoods方法,来实现对microservicecloud-provider-8001项目的对应接口的调用。

(三)前面准备工作做好后,我们可以启动相关服务了,按照如下顺序,依次启动服务microservicecloud-eureka-7001 作为eureka注册服务端

microservicecloud-provider-8001 作为eureka 客户端,同时作为服务提供者

microservicecloud-consumer-feign 作为eureka 客户端,同时作为服务消费者

(四)启动正常后,我们在浏览器地址栏输入localhost/consumer/goods/list/feign

通过打断点,确认调用的是GoodsClientService接口,如图

然后放行该断点,在浏览器看到响应即为正常。如下图。这说明我们可以通过GoodsClientService接口来完成相关接口的调用(直接声明个接口,避免了通过restTemplate硬编码)

相关推荐
郜太素26 分钟前
PyTorch 中神经网络相关要点(损失函数,学习率)及优化方法总结
人工智能·pytorch·python·深度学习·神经网络·学习
threelab1 小时前
05.three官方示例+编辑器+AI快速学习three.js webgl - animation - skinning - ik
人工智能·学习·编辑器
threelab1 小时前
04.three官方示例+编辑器+AI快速学习webgl_animation_skinning_additive_blending
人工智能·学习·编辑器
深度学习机器学习1 小时前
计算机视觉最不卷的方向:三维重建学习路线梳理
人工智能·深度学习·学习·yolo·目标检测·机器学习·计算机视觉
带刺的坐椅1 小时前
SpringBoot2 可以使用 SolonMCP 开发 MCP(江湖救急)
java·spring·ai·solon·mcp
jimsten2 小时前
苍穹外卖 - Day02 学习笔记
java·笔记·学习
人类恶.2 小时前
C 语言学习笔记(6)
c语言·笔记·学习
LJianK12 小时前
Spring Boot、Spring MVC 和 Spring 有什么区别
spring boot·spring·mvc
困了又困zZ2 小时前
系统单元测试和项目打包
spring
LuckyLay3 小时前
React百日学习计划-Grok3
前端·学习·react.js