spring cloud feign

spring cloud feign

  • Spring Cloud Feign具有可插拔的注解支持,包括Feign注解和JAX-RS注解。

快速入门

  • 创建应用主类FeignApplication,并通过@EnableFeignClients注解开启Spring Cloud Feign的支持功能。
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class FeignApplication {

    public static void main(String[] args) {
        SpringApplication.run(FeignApplication.class, args);
    }
}
  • 定义一个接口,通过@FeignClient注解指定服务名来绑定服务,然后再使用Spring MVC的注解来绑定具体该服务提供的REST接口。
@FeignClient(name = "hello-service")
public interface HelloService {

    @RequestMapping("/hello")
    String hello();
}
  • 接着,创建一个ConsumerController来实现对Feign客户端的调用。使用@Autowired直接注入上面定义的HelloService实例,并在helloConsumer函数中调用这个绑定了hello-service服务接口的客户端来向该服务发起/hello接口的调用。
@RestController
public class CustomerController {

    @Autowired
    private HelloService helloService;
    
    @RequestMapping(value = "/feign-consumer", method = RequestMethod.GET)
    public String helloConsumer() {
        return helloService.hello();
    }
}
  • 最后,同Ribbon实现的服务消费者一样,需要在application.properties中指定服务注册中心,并定义自身的服务名为feign-consumer
server:
  port: 9010
spring:
  application:
    name: feign-consumer
eureka:
  client:
    service-url:
      defaultZone: http://localhost:1111/eureka/

参数绑定

  • Feign中对几种不同形式参数的绑定方法。
@FeignClient(name = "hello-service", configuration = LoggerFeignConfig.class, fallback = HelloServiceFallback.class)
public interface HelloService {

    @RequestMapping("/hello")
    String hello();

    @RequestMapping(value = "/hello1", method = RequestMethod.GET)
    String hello(@RequestParam("name") String name);

    @RequestMapping(value = "/hello2", method = RequestMethod.GET)
    User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age);

    @RequestMapping(value = "/hello3", method = RequestMethod.POST)
    String hello(@RequestBody User user);
}
  • 注意:@RequestParam@RequestHeader等可以指定参数名称的注解,它们的value不能少。在SpringMVC程序中,这些注解会根据参数来作为默认值,但是在Feign中绑定参数必须通过value属性来指明具体的参数名,不然会抛弃IllegalStateException异常,value属性不能为空。

继承特性

创建一个maven工程hello-service-api,里面定义可同时复用于服务端和客户端的接口。

  • 定义一个接口Hello-Service
@RequestMapping("/refactor")
public interface HelloService {

    @RequestMapping(value = "/hello4", method = RequestMethod.GET)
    String hello(@RequestParam("name") String name);

    @RequestMapping(value = "/hello5", method = RequestMethod.GET)
    User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age);

    @RequestMapping(value = "/hello6", method = RequestMethod.POST)
    String hello(@RequestParam User user);
}
  • hello-service服务中的pom.xml文件中导入hello-service-api,定义一个RefactorHelloController来实现HelloService
@RestController
public class RefactorHelloController implements HelloService {

    @Override
    public String hello(@RequestParam("name") String name) {
        return "Hello " + name;
    }

    @Override
    public User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age) {
        return new User(name, age);
    }

    @Override
    public String hello(@RequestBody User user) {
        return "Hello " + user.getName() + ", " + user.getAge();
    }
}
  • 在服务消费方,引入Hello-Service-api,创建RefactorHelloService接口,继承HelloService接口
@FeignClient(value = "hello-service")
public interface RefactorHelloService extends HelloService {
}
  • CustomerController中,注入RefactorHelloService的实例,如下:
@RestController
public class CustomerController {
    
    @Autowired
    private RefactorHelloService refactorHelloService;
    
    @RequestMapping(value = "/feign-consumer3", method = RequestMethod.GET)
    public String helloConsumer3() {
    StringBuilder sb = new StringBuilder();
    sb.append(refactorHelloService.hello("kuraki")).append("\n");
    sb.append(refactorHelloService.hello("kuraki", 26)).append("\n");
    sb.append(refactorHelloService.
              hello(new com.kuraki.feign.dto.User("kuraki", 26))).append("\n");
    return sb.toString();
    }
}

服务降级配置

  • 只需为Feign客户端的定义接口编写一个具体的接口实现类。如下:
@Component
public class HelloServiceFallback implements HelloService {

    @Override
    public String hello() {
        return "error";
    }

    @Override
    public String hello(String name) {
        return "error name";
    }

    @Override
    public User hello(String name, Integer age) {
        return new User("lingbo", 26);
    }

    @Override
    public String hello(User user) {
        return "error user";
    }
}
  • @FeignClient注解的fallback属性来指定对应的服务降级实现类。
@FeignClient(name = "hello-service", fallback = HelloServiceFallback.class)
public interface HelloService {
    @RequestMapping("/hello")
    String hello();

    @RequestMapping(value = "/hello1", method = RequestMethod.GET)
    String hello(@RequestParam("name") String name);

    @RequestMapping(value = "/hello2", method = RequestMethod.GET)
    User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age);

    @RequestMapping(value = "/hello3", method = RequestMethod.POST)
    String hello(@RequestBody User user);
}

日志配置

  • application.properties文件中使用logging.level.的参数配置格式来开启指定Feign客户端的DEBUG日志,其中Feign客户端定义接口的完整路径。
  • 其次,Feign客户端默认的Logger.Level对象定义为NONE级别,该级别不会记录任何Feign调用过程中的信息,可在启动类或者自定义一个配置类中修改级别,如下:
@Configuration
public class LoggerFeignConfig {

    @Bean
    public Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}
  • 对于FeignLogger级别主要有下面4类:
    • NONE:不记录任何信息。
    • BASIC:仅记录请求方法,url以及响应状态码和执行时间。
    • HEADERS:除了记录BASIC级别的信息之外,还会记录请求和响应的头信息。
    • FULL:记录所有请求与响应的明细,包括头信息、请求体、元数据等。

你可能感兴趣的:(Java,微服务)