【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硬编码)

相关推荐
eternal__day2 分钟前
Spring Cloud 多机部署与负载均衡实战详解
java·spring boot·后端·spring cloud·负载均衡
哆啦A梦的口袋呀9 分钟前
基于Python学习《Head First设计模式》第七章 适配器和外观模式
python·学习·设计模式
恰薯条的屑海鸥11 分钟前
零基础在实践中学习网络安全-皮卡丘靶场(第十期-Over Permission 模块)
学习·安全·web安全·渗透测试·网络安全学习
程序员秘密基地13 分钟前
基于vscode,idea,java,html,css,vue,echart,maven,springboot,mysql数据库,在线考试系统
java·vue.js·spring boot·spring·web app
吾日三省吾码32 分钟前
Spring 团队详解:AOT 缓存实践、JSpecify 空指针安全与支持策略升级
java·spring·缓存
东京老树根1 小时前
SAP学习笔记 - 开发27 - 前端Fiori开发 Routing and Navigation(路由和导航)
笔记·学习
花月C3 小时前
Mysql-定时删除数据库中的验证码
数据库·后端·mysql·spring
阿阳微客7 小时前
Steam 搬砖项目深度拆解:从抵触到真香的转型之路
前端·笔记·学习·游戏
记得开心一点嘛9 小时前
使用MinIO搭建自己的分布式文件存储
分布式·spring cloud·minio
Chef_Chen12 小时前
从0开始学习R语言--Day18--分类变量关联性检验
学习