SpringCloud学习(七)----- 使用Feign调用别的微服务的方法

发布于:2022-12-23 ⋅ 阅读:(203) ⋅ 点赞:(0)

SpringCloud版本:2021.0.1     SpringBoot版本:2.6.3

系列文章

SpringCloud学习(一)----- Eureka搭建

SpringCloud学习(二)----- SpringBoot Admin搭建(与Eureka整合)

SpringCloud学习(三)----- Gatewayw网关搭建

SpringCloud学习(四)----- Gatewayw网关完善(限流)

SpringCloud学习(五)----- Gatewayw网关完善(Resilience4j断路器)

SpringCloud学习(六)----- Gatewayw网关完善(防止SQL注入)

SpringCloud学习(七)----- 使用Feign调用别的微服务的方法

SpringCloud学习(八)----- Gateway网关及其他微服务接入Swagger接口文档

参考文章:

Spring Cloud微服务之间的调用

今日教学:RestTemplate 结合 Ribbon 使用

FEIGN调用出现权限问题 FEIGN.FEIGNEXCEPTION$UNAUTHORIZED: [401] DURING [GET] TO[....]

因为在微服务的框架中,已经把所有的服务的功能区分的很细了,所以有可能会出现一种问题,就是比如某个微服务需要用到某个功能,但这个功能已经划分在别的服务并已经开发完成了,那么这个时候就可以用到Feign这个来调用别的服务的方法了。

一、微服务之间一般用什么方法来进行互相的方法调用 ?

        一般常用的有两种方法,即Ribbon + RestTemplate进行微服务调用或者使用Feign进行微服务调用。当然,也有一个最原始的方法,那就是http接口,这个也可以实现微服务之间的方法的调用的功能,但就是比较麻烦,头铁的可以试试。那么,Ribbon + RestTemplateFeign这两种方法有什么区别吗?那当然是有的,但也没有那么大的区别。

1、它们的启动类注解不同,Ribbon是@RibbonClient,Feign的是@EnableFeignClients。

2、服务指定的位置不同,Ribbon是在@RibbonClient注解上声明,Feign则是在定义抽象方法的接口中使用@FeignClient声明。

3、调用方式不同,Ribbon需要自己构建http请求,先模拟http请求然后再使用RestTemplate发送给其他服务,步骤比较繁琐。但Feign只需要将调用的方法定义成抽象方法即可,当然,前提是得已经把服务注册到注册中心。

那么,它们之间对比下来,那个更好呢?

1、Ribbon弊端:代码里会充斥着大量的url,在小型项目中还好,但在大型项目里,维护成本就会很高了。

2、Feign弊端:如果微服务调用的方法入参发生了变化,那么对应的Feign方法也得进行相应的更改,但这个我觉得还是可以接受的。

不过呢,一般开发人员都会选用Feign来进行微服务之间的调用,因为如果真的使用Ribbon + RestTemplate的话,那么维护成本就太高了,相比较下,Feign还是比较好的。

那么,回归主题,首先简单介绍一下Ribbon + RestTemplate的使用。

1、Ribbon + RestTemplate

首先,是Ribbon的pom依赖导入,不过如果用的是Eurker作为注册中心的话,也不用导入,因为Eureka 中已经引用了Ribbon。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

然后我们需要在启动类里面的方法创建一个负载均衡的RestTemplate Bean

@SpringBootApplication
@EnableDiscoveryClient
public class TestApplicaton {
    //创建一个负载均衡的RestTemplate Bean
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    public static void main(String[] args) {
        SpringApplication.run(TestApplicaton.class, args);
    }
}

再然后,在要使用的方法里进行引入就可以了。


	@Autowired
	private RestTemplate restTemp;
	

	public String test(){
	    //与Eurka集成,将服务注册到Eurka,url中使用注册到Eurka中服务名来进行调用
		ResponseEntity<String> rest = restTemp.getForEntity("http://test-service/test/hello" , String.class);
		if (rest != null){
			return rest.getBody();
		}		
		return null;
		
	}

2、Feign

(1)引入pom依赖

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

(2)在启动类上加上 @EnableFeignClients注解

@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class TestApplicaton {
    public static void main(String[] args) {
        SpringApplication.run(TestApplicaton.class, args);
    }
}

(3)新建访问其他微服务的接口

@FeignClient("test-service")
public interface ServiceApi {
    @PostMapping("/test/hello")
    String hello();
}
  • @FeignClient("test-service")中的“test-service”是spring:application:name,即注册中心中配的应用名,即注册到注册中心里的服务名
  • @PostMapping("/test/hello") 是要调用的微服务的url

在使用Feign中,我还出现过401的问题,这种情况为没有认证就请求了资源服务器的资源,解决办法为使用Feign的时候把请求的认证信息传递过去,或者资源服务那边开放一些接口。不过开放接口的话情况有点多,所以就选择把token携带过去了。feign提供了一个名为RequestInterceptor得拦截器,可以在请求的时候指定请求头。 

解决方法就是加一个配置文件, 在请求的时候指定请求头,就可以了。

@Configuration
public class FeignConfig implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        requestTemplate.header("Authorization", request.getHeader("Authorization"));
    }
}

本文含有隐藏内容,请 开通VIP 后查看