[TOC]

前面的文章中,服务消费者调用服务提供者的接口我们是使用RestTemplate实现的REST API调用的。但这种方式在参数比较多时会变得低效,难以维护。

Feign

Feign是Netflix开发的声明式,模板化的HTTP客户端。它可以让我们更加便捷,优雅的调用HTTP API。Feign有自己的注解,在Spring Cloud中对Feign进行了增强,使其可以支持Spring MVC注解,并整合Ribbon与Eureka。

整合Feign

前面的服务消费都使用RestTemplate来调用服务提供者,这里更改成使用Feign,使用声明式的RestFul API。

添加依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

配置

配置其实无需修改

1
2
3
4
5
6
7
8
9
10
11
server:
port: 8011
spring:
application:
name: microservice-consumer-movie
eureka:
client:
service-url:
defaultZone: http://user:admin@localhost:8761/eureka/
instance:
prefer-ip-address: true

创建Feign接口

1
2
3
4
5
6
@FeignClient(name = "microservice-provider-user")
public interface UserFeignClient {

@GetMapping(value = "/{id}")
public User findById(@PathVariable("id") Long id);
}

@FeignClient 注解中的microservice-provider-user 是服务提供者的主机名,用于创建Ribbon负载均衡器,与上篇文章中使用主机名是一样的。也可以使用URL属性指定请求的URL:

@FeignClient(name = "microservice-provider-user",url="http://localhost:8000/")

Controller

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
public class UserController {

@Autowired
private UserFeignClient userFeignClient;


@GetMapping("/user/{id}")
public User findById(@PathVariable Long id){
return this.userFeignClient.findById(id);
}
}

Controller 中去掉RestTemplate,定义 UserFeignClient 。我在测试中定义的 UserFeignClient 会提示 Could not autowire. No beans of 'UserFeignClient' type found. 但运行并不影响。

添加注解

在启动类上注解 @EnableFeignClients

1
2
3
4
5
6
7
8
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class MicroserviceSimpleConsumerMovieApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceSimpleConsumerMovieApplication.class, args);
}
}

测试

完成上述修改后,就可以像之前一样去调用服务提供者了。
与上篇Ribbon一样,启动一个Eureka,一个或多个服务提供者(Feign自己集成了Ribbon),启动修改完成后的服务消费者。
访问http://localhost:8011/user/1
测试

自定义Feign配置

按上一节整合Feign很简单,但有时候我们想自定义Feign的配置,如更改Feign使用的编码器,解码器,契约,拦截器等。
如服务提供者是需要Http Basic的认证才能调用的,那么服务消费者可以在Feign中自定义配置拦截器,添加 Http Basic 认证。

编写配置类

1
2
3
4
5
6
7
8
@Configuration
public class FooConfiguration {

@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){
return new BasicAuthRequestInterceptor("user","123456");
}
}

使用这个配置,只需要在Feign接口类UserFeignClient @FeignClient注解中添加configuration 属性

@FeignClient(name = "microservice-provider-user",configuration="FooConfiguration.class")

另外还需要把服务提供者加上Http Basic认证。
在服务提供都项目中添加security

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

在其配置文件中添加用户名与密码:

1
2
3
4
5
6
security:
basic:
enabled: true
user:
name: user
password: 123456

测试

重新启动服务提供者与服务消费者
这里我们直接去访问服务提供者是需要进行认证的:
测试
访问服务消费者,通过服务消费者去调用服务提供者,不会弹出认证窗口,因为服务消费者在Feign中已经配置了用户名与密码了。
这里写图片描述

Feign服务间传送文件

转 :Spring Cloud微服务【Finchley.RELEASE版本】(四)使用feign服务间传送文件

Feign构造多参数请求

GET

对于GET请求可以使用Map来构建。接口修改如下 :

1
2
3
4
5
@FeignClient(name = "microservice-provider-user",configuration = FooConfiguration.class)
public interface UserFeignClient {
@GetMapping(value = "/get")
public User get(@RequestParam Map<String,Object> map);
}

调用时构建一个Map传递到接口中

POST

post请求则简单得多,可以直接使用 User 实体类

1
2
3
4
5
@FeignClient(name = "microservice-provider-user",configuration = FooConfiguration.class)
public interface UserFeignClient {
@PostMapping(value = "/get")
public User get(@RequestBody User user);
}