feign-使用最佳实践

     Spring Cloud提供的微服务都是基于http,那么在请求的时候如果用spring提供的RestTemplate再加一个Ribbon提供的@LoadBalanced注解也是可以比较方便的发起微服务的调用,并且也能做到负载均衡。但是如果服务提供者参数较多也较复杂,那么使用这种方式需要拼接url或者使用Map的形式,但总归是不便于开发的。
     Spring Cloud全家桶提供了feign这样的一个组件,feign是Netflix开发的声明式、模板化的HTTP客户端,feign的使用非常简单,创建一个接口,在接口上加入一些注解,这样就完成了代码开发。
     Spring Cloud在Netflix的基础上对feign进行了进一步的增强,添加了对Spring MVC注解的支持,并整合了Ribbon和Eureka,从而让feign的使用更加简单了。接下去介绍使用feign的最佳实践。
  • Api/Client
    我们在写dubbo服务的时候,会定义一个接口Interface,然后提供者实现该接口完成具体的服务逻辑并将服务接口export出去,消费者注入该接口(需要有相应的配置)然后就能调用该服务。对于提供者的输入和输出同样可以定义在一个同一个包里面,然后提供者和消费者都来依赖,这样可以减少代码开发量。
    那么同样在feign的使用中,我们也来这么做:
    • 依赖
compile ("org.springframework.cloud:spring-cloud-netflix-core:1.3.1.RELEASE") {
  exclude group: 'org.springframework.boot', module: 'spring-boot'
  exclude group: 'org.springframework.boot', module: 'spring-boot-autoconfigure'
}
compile ("org.springframework:spring-web:4.3.8.RELEASE")
               这里使用的是Dalston.SR1版本,去掉spring-boot相关的包,因为只需要@FeignClient这样的注解,加入spring-web包是为了要Spring MVC相关的注解
    • 接口
@FeignClient("eureka-client-test")
@RequestMapping("spring-cloud")
public interface HelloService {

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

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

  @RequestMapping(value = "hello3", method = RequestMethod.POST)
  MatchMessage hello(@RequestBody(required = false) UserDto userDto);
}
               @FeignClient表示的是哪个服务(注册到Eureka server的服务名),@RequestMapping就是传统我们熟悉的Spring MVC相关的注解
  • 输入输出
    MatchMessage和UserDto的定义比较简单,不再贴代码了,MatchMessage主要是服务返回的数据,UserDto是服务需要的参数
  • 服务提供者
    • 加入依赖
compile ("spring-cloud-demo:feign-client:0.0.1") {
  exclude group: 'org.springframework', module: 'spring-web'
  exclude group: 'org.springframework.cloud', module: 'spring-cloud-netflix-core'
}
               这里服务的实现仅仅需要的是输入和输出的定义和实现那个Interface,所以无需其他相关的包,可以exclude掉
    • 服务实现
@RestController
public class HelloController implements HelloService {

  private static final Logger LOGGER = LoggerFactory.getLogger(HelloController.class);

  @Override
  public String hello(@RequestParam(value = "name", required = false) String name) {
  LOGGER.info("call hello, simple");
  return "Hello " + name;
  }

  @Override
  public MatchMessage hello(@RequestHeader(value = "name", required = false) String name,
  @RequestHeader(value = "age", required = false) Integer age) {
  UserDto userDto = new UserDto(name, age);
  LOGGER.info("call hello, GET");
  return new MatchMessage(userDto, MatchMessage.RESULT_MATCHED);
  }

  @Override
  public MatchMessage hello(@RequestBody(required = false) UserDto userDto) {
  LOGGER.info("call hello, POST");
  return new MatchMessage(userDto, MatchMessage.RESULT_MATCHED);
  }
}
               代码比较简单,实现HelloService接口,一些接口的定义如@RequestMapping就不再需要了,已经在client中定义了,这个其实就是feign对继承的支持。
    • 调用
@RestController
public class HelloController {

  private static final Logger LOGGER = LoggerFactory.getLogger(HelloController.class);

  @Autowired
  private HelloService helloService;

  @RequestMapping(value = "feign-consumer", method = RequestMethod.GET)
  public MatchMessage consume1() {
  LOGGER.info(this.helloService.hello("levi.qian"));
  MatchMessage message = this.helloService.hello("levi.qian", 20);
  LOGGER.info(message.getResult() + "");
  return this.helloService.hello(new UserDto("levi.qian", 27));
  }
}
               注入HelloService,直接调方法即可,底层会使用Ribbon的负载均衡来调具体的服务。
     这样做的方式将提供者和消费者的代码耦合了,但是这种方式能够减少很多的代码,如果在前期对接口定义得足够好,这种方式还是可以接受的。
     具体的Feign的原理会在以后讲到(为啥加了@Feign就可以调用了?)

     分享一个项目:https://github.com/JThink/SkyEye对java、scala等运行于jvm的程序进行实时日志采集、索引和可视化,对系统进行进程级别的监控,对系统内部的操作进行策略性的报警、对分布式的rpc调用进行trace跟踪以便于进行性能分析。欢迎对分布式跟踪感兴趣的交流~~,交流群:624054633
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值