首页 > 经验记录 > 分布式微服务项目如何使用 Feign 实现声明式 REST 调用,以及自定义 Feign 配置

分布式微服务项目如何使用 Feign 实现声明式 REST 调用,以及自定义 Feign 配置

上个文章使用了Eureka搭建了集群服务注册中心,但是最后实现 RPC 的方式还是  从代码中获得服务对应地址->字符串拼接->请求获得响应  的这样一种方式。
这种方式弊端还是有不少的。如果可以像调用自己的服务一样调用别人提供的服务那该多舒适啊。
 
而 Feign 就可以实现这种需求,Feign也是网飞开发的,SpringCloud 使用 Feign 非常简单,我下边演示一下:
首先 服务消费者这边肯定需要一个对应的依赖:

compile("org.springframework.cloud:spring-cloud-starter-openfeign")

需要启用Feign的话,也得在启动类上面加个注解 @EnableFeignClients
然后,创建一个 Feign 的接口,像这样子

package com.skypyb.sc.feign;
import com.skypyb.sc.entity.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient("sc-demo-microservice-user")
public interface UserFeignClient {
    @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    public User getUser(@PathVariable("id") Long id);
}

@FeignClient 注解里边的默认属性,也就是name属性是一个客户端的名字,如果使用了Eureka的话,会给他自动解析为 Eureka Server 服务注册表中的服务。
要是配了Ribbon,也会使用默认的负载均衡策略来执行请求。
Feign默认使用SpringMVC的注解声明请求,当然也可以用Feign自带的注解。不过没啥必要,还需要配置东西。
 
我上边这个例子写完了,实际使用的话只需要注入该类然后调用对应的方法就完事了。非常简便。

package com.skypyb.sc.controller;
import com.skypyb.sc.entity.User;
import com.skypyb.sc.feign.UserFeignClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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("/movie")
public class MovieController {
    private Logger logger = LoggerFactory.getLogger(MovieController.class);
    @Autowired
    private UserFeignClient userFeignClient;
    @GetMapping("/user/{id}")
    public User getUser(@PathVariable("id") Long id) {
        return userFeignClient.getUser(id);
    }
}

不过有几个点需要注意
在使用@FeignClient 声明的Feign伪装类中:
使用 @PathVariable 注解,必须加上参数!
GET请求无法使用对象作为入参! 要不有多少参数写多少参数(每个都要加@RequestParam(“参数名”) 注解),要不就用接受一个Map对象,也得加@RequestParam
POST请求可以接收对象,需要加上@RequestBody注解
 
 
Feign论使用的话,其实已经差不多了。
但是还有一些相关的操作也比较重要。
 
Feign 的请求都是使用的默认配置,我们其实可以实现自己的配置供 Feign 使用以实现编码、解码、日志记录、验证 等等等等。
比如我可以这么定义一个配置类:

package com.skypyb.sc.config;
import feign.Logger;
import feign.auth.BasicAuthRequestInterceptor;
import org.springframework.context.annotation.Bean;
public class FeignConfiguration {
    @Bean
    public Logger.Level feignLog() {
        return Logger.Level.FULL;
    }
    /**
     * 使用指定的用户名和密码验证所有请求
     * @return
     */
    @Bean
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){
        return new BasicAuthRequestInterceptor("user","614");
    }
}

该类配置了对应的日志记录器,和一个简单的效验,以应对请求的验证。
在对应的Feign伪装类中,上边的@FeignClient注解改一下,就可以使用自己写的配置:

@FeignClient(name = "sc-demo-microservice-user", configuration = FeignConfiguration.class)

之所以在 @FeignClient 注解中指定配置,是因为我的配置类是没有加 @Configuration 注解的,我想要实现细粒度的控制。 推荐这样做。
如果加了@Configuration 注解,则 Spring 会将其自动解析自动应用到全局,这样子就不方便为每个请求进行细粒度调整。
 
 

           


CAPTCHAis initialing...
EA PLAYER &

历史记录 [ 注意:部分数据仅限于当前浏览器 ]清空

      00:00/00:00