Spring Cloud学习系列第四篇声明式服务调用

Posted yipaihushuo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Cloud学习系列第四篇声明式服务调用相关的知识,希望对你有一定的参考价值。

  之前的随笔我们访问其它微服务方式都是通过Ribbon组件提供的一些模板方法去访问的,使用过程中会发现一个问题就是对某服务接口调用往往不是一处的,于是我们需要这个服务接口进行一个封装,其它地方统一调用这个封装,而每个封装其实也就是对用RestTemplate的模板方法对目标服务接口的调用,这样代码里就会有很多冗余的RestTemplate方法了,代码很不优雅,而使用了Spring Cloud Feign就不一样了,它是Spring Cloud Hystrix和Spring Cloud Ribbon整合,有了它在框架层面Spring Cloud就帮我们封装好这些东西了,我们只需要定义一个需要访问目标服务方法的接口,就可以直接通过依赖注入直接使用了,省去了我们自己封装那一步,代码也更加优雅了。

  下面改写一下之前的例子,体验一下吧。我们新增一个Feign项目作为采用声明式服务调用这种方式去访问ServiceA的服务。由于Feign需要定义访问ServiceA方法的接口,然后ServiceA需要提供对应的HTTP服务,于是我们在新增一个FeignApi项目把公共的接口定义在这,然后Feign和ServiceA依赖FeignApi,达到代码共用的效果。结合下代码来理解下。

 

 一、 新增FeignApi项目

 

  再次说明FeigApi作用了抽取共用代码给Feign和ServiceA使用的,哪里会有共用代码?这就是需要Feign需要访问的ServiceA的几个接口信息 。

  技术分享图片

  FeignService接口定义需要访问的URL路径。

package com.pumpkin.service;

import com.pumpkin.dto.User;
import org.springframework.web.bind.annotation.*;

@RequestMapping("/user")
public interface FeignService {

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

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

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

}

 

二、Feign项目使用声明式调用

  写个controller作为等下我们调用ServcieA的入口,URL为:127.0.0.1:7000/feign/hello.do

spring.application.name=feign

#eureka.instance.instance-id=${spring.application.name}:${random.int}
server.port=7000

eureka.client.serviceUrl.defaultZone=http://localhost:5001/eureka/,http://localhost:5002/eureka/

 

package com.pumpkin.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.pumpkin.dto.User;
import com.pumpkin.service.FeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/feign")
public class FeignController {

    @Autowired
    private FeignService feignService;

    @RequestMapping(value = "/hello.do", method = RequestMethod.GET)
    public String feignHello() {
        StringBuilder sb = new StringBuilder();
        sb.append(feignService.hello("MIMI")).append("
");
        sb.append(feignService.hello("MIMI", 20)).append("
");
        sb.append(feignService.hello(new User("MIMI", 20))).append("
");
        return sb.toString();
    }
    
}

 

 

  编写FeignServiceImpl接口,因为FeignService在FeignApi项目,所以我们要先依赖FeignApi项目。然后FeignServiceImpl只需要继承FeignService,并添加@FeignClient(value = "SERVICE-A")注解后就可以通过依赖注入给Controller层的入口使用了。

package com.pumpkin.service.impl;

import com.pumpkin.service.FeignService;
import org.springframework.cloud.netflix.feign.FeignClient;

@FeignClient(value = "SERVICE-A")
public interface FeignServiceImp extends FeignService {
}

 

 

三、改造ServiceA项目

  新增一个FeignController提供对外服务。可以看到FeignController是通过实现FeignService接口,这样ServiceA项目就不需要冗余那个几个方法的代码了,直接依赖FeignApi即可。

package com.pumpkin.controller;

import com.pumpkin.dto.User;
import com.pumpkin.service.FeignService;
import org.apache.log4j.Logger;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FeignController implements FeignService {
    private final Logger LOGGER = Logger.getLogger(getClass());

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

    @Override
    public User hello(@RequestParam("name")String name, @RequestParam("sex")Integer sex) {
        LOGGER.info("name=" +name+ " ,sex=" +sex);
        return new User("pumpkin", 0);
    }

    @Override
    public String hello(@RequestBody User user) {
        return "hello user=" +user.toString();
    }
}

 

 

四、启动看看效果

技术分享图片

五、总结

  Spring Cloud Feign是对Spring Cloud Ribbon和Spring Hystrix封装整合。这篇随笔主要介绍了Spring Cloud Feign的简单使用,对于如何进行服务熔断和降级并没有涉及,但从使用层面来讲也就是几个注解的问题,只要对Hystrix机制有一定的理解,使用起来是非常容易的,另外Feign并没有对Hysrix的请求合并和请求缓存进行封装,所以需要这些功能的话,只能使用回Ribbon了。

 

六、参考资料

Spring Cloud微服务实战-翟永超。本系列的学习都是参考该书籍学习的,同时源码使用的Spring Boot和Spring Cloud的版本也与该书保持一致。

七、源码

码云地址:[email protected]:pumpkingg/Spring-Cloud-Study.git 该篇随笔对应的代码是master分支下命名为blog3的Tag

 

 
 

 



以上是关于Spring Cloud学习系列第四篇声明式服务调用的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA系列4:Spring声明式事务处理与多数据源支持

Spring Cloud Eureka 分布式开发之服务注册中心负载均衡声明式服务调用实现

Spring Cloud学习笔记-007

[第四篇]——Windows Docker 安装之Spring Cloud直播商城 b2b2c电子商务技术总结

Spring Cloud Gateway面试攻略,微服务网关的作用以及案例

Spring Boot Serverless 实战系列 | 性能调优