springcloud(七)-Feign声明式REST调用

前言

前面我们使用的RestTemplate实现REST API调用,代码大致如下:

public User findById(@PathVariable Long id) {
        return restTemplate.getForObject("http://localhost:8084/" + id, User.class);
    }

由代码可知,我们是使用拼接字符串的方式构造URL的,该URL只有一个参数。但是,在现实中,URL中往往含有多个参数。这时候我们如果还用这种方式构造URL,那么就会非常痛苦。举个例子:

http://localhost:8010/search?name=zhangsan&username=account1&age=20

这里是有三个参数,要是有10个参数,那么代码会变得难以维护。

怎么解决?

Feign简介

Feign是Netflix开发的声明式,模板化的HTTP客户端,其灵感来自Retrofit,JAXRS-2.0以及WebSocket.Feign可帮助我们更加便捷,优雅的调用HTTP API。

在spring cloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解,代码就完成了。Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。

spring cloud对Feign进行了增强,使Feign支持了springmvc注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。

代码编写

1.我们复制前面的microservice-consumer-movie,将ArtifactId修改为microservice-consumer-movie-feign.

2.添加Feign的依赖。

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

3.创建一个Feign接口,并添加@FeignClient注解。

@FeignClient("microservice-provider-user")
public interface UserFeignClient {
    @RequestMapping(value="/{id}",method = RequestMethod.GET)
    public User findById(@PathVariable("id") Long id);
}

这里解释一下:@FeignClient注解中的microservice-provider-user是一个任意的客户端名称,用于创建Ribbon负载均衡器。在本例中,使用了Eureka,所以Ribbon会把microservice-provider-user解析成Eureka Server服务注册表中的服务。

当然,你也可以使用url属性指定请求URL(URL可以是完整的URL或者主机名),例如:

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

4.修改Controller代码,让其调用Feign接口。

@RestController
public class MovieController {
//    @Autowired
//    private RestTemplate restTemplate;
    
    @Autowired
    private UserFeignClient userFeignClient;

    @GetMapping("/user/{id}")
    public User findById(@PathVariable Long id) {
//        return restTemplate.getForObject("http://localhost:8081/" + id, User.class);
        return userFeignClient.findById(id);
    }
}

5.修改启动类,为其添加@EnableFeignClients注解,如下:

@SpringBootApplication
@EnableFeignClients
public class ConsumerMovieApplication {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

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

这样,我们的电影微服务就可以用Feign去调用用户微服务的API了。

测试

启动microservice-discovery-eureka.

启动2个或更多microservice-provider-user实例。

启动microservice-consumer-movie-feign.

多次访问http://localhost:8082/user/1,返回结果。

{"id":1,"username":"account1","name":"张三","age":20,"balance":98.23}

两个用户微服务实例都会打印如下日志:

Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.balance as balance3_0_0_, user0_.name as name4_0_0_, user0_.username as username5_0_0_ from user user0_ where user0_.id=?
2019-04-19 19:23:42.249 TRACE 7464 --- [nio-8084-exec-7] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [1]
2019-04-19 19:23:42.251 TRACE 7464 --- [nio-8084-exec-7] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([age2_0_0_] : [INTEGER]) - [20]
2019-04-19 19:23:42.251 TRACE 7464 --- [nio-8084-exec-7] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([balance3_0_0_] : [NUMERIC]) - [98.23]
2019-04-19 19:23:42.251 TRACE 7464 --- [nio-8084-exec-7] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([name4_0_0_] : [VARCHAR]) - [张三]
2019-04-19 19:23:42.251 TRACE 7464 --- [nio-8084-exec-7] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([username5_0_0_] : [VARCHAR]) - [account1]

以上结果说明,我们不但实现了声明式REST API调用,同时还实现了客户端侧的负载均衡。


代码下载地址:https://gitee.com/fengyuduke/my_open_resources/blob/master/microservice-consumer-movie-feign.zip

猜你喜欢

转载自www.cnblogs.com/fengyuduke/p/10738342.html