导读:通过前面两篇文章我们准备好了微服务的基础环境并让accout-service 和 product-service对外提供了增删改查的能力,本篇我们的内容是让order-service作为消费者远程调用accout-service和product-service的服务接口。

  • <dependency>
    <groupId>com.jianzh5.cloud</groupId>
    <artifactId>cloud-common</artifactId>
    <version>1.0-SNAPSHOT</version>
    </dependency>
    @Data
    public class ResultData<T> {
    /** 结果状态 ,正常响应200,其他状态码都为失败*/
    private int status;
    private String message;
    private T data;
    private boolean success;
    private long timestamp ;

    ... 提供一些静态方法 ...
    }
    @RestController
    @Log4j2
    public class AccountController {
    @Autowired
    private AccountService accountService;
    @PostMapping("/account/insert")
    public ResultData<String> insert(@RequestBody AccountDTO accountDTO){
    log.info("insert account:{}",accountDTO);
    accountService.insertAccount(accountDTO);
    return ResultData.success("insert account succeed");
    }
    @PostMapping("/account/delete")
    public ResultData<String> delete(@RequestParam String accountCode){
    log.info("delete account,accountCode is {}",accountCode);
    accountService.deleteAccount(accountCode);
    return ResultData.success("delete account succeed");
    }
    @PostMapping("/account/update")
    public ResultData<String> update(@RequestBody AccountDTO accountDTO){
    log.info("update account:{}",accountDTO);
    accountService.updateAccount(accountDTO);
    return ResultData.success("update account succeed");
    }
    @GetMapping("/account/getByCode/{accountCode}")
    public ResultData<AccountDTO> getByCode(@PathVariable(value = "accountCode") String accountCode){
    log.info("get account detail,accountCode is :{}",accountCode);
    AccountDTO accountDTO = accountService.selectByCode(accountCode);
    return ResultData.success(accountDTO);
    }
    }

    服务调用

    SpringCloud体系中,所有微服务间的通信都是通过Feign进行调用,Feign是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,而不用像使用HttpClientOKHttp3等组件通过封装HTTP请求报文的方式调用。Feign通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求,这种请求相对而言比较直观。而且Feign默认集成了负载均衡器Ribbon,不需要自己实现负载均衡逻辑。

    FeignSpringCloud的组件,在引入Feign之前我们先看看Spring BootSpring CloudSpring Cloud Alibaba 三者之间的关系,防止在业务中引入了错误的版本。

    2.1.x Greenwich 0.9.x
    2.0.x Finchley 0.2.x
    1.5.x Edgware 0.1.x
    1.5.x Dalston 0.1.x

    很显然,我们引用的是SpringCloud Alibab 0.9.0,所以我们需要引入SpringCloud Greenwich

    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>Greenwich.SR2</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    @FeignClient(name = "account-service")
    public interface AccountFeign {
    @PostMapping("/account/insert")
    ResultData<String> insert(@RequestBody AccountDTO accountDTO);

    @PostMapping("/account/delete")
    ResultData<String> delete(@RequestParam("accountCode") String accountCode);

    @PostMapping("/account/update")
    ResultData<String> update(@RequestBody AccountDTO accountDTO);

    @GetMapping("/account/getByCode/{accountCode}")
    ResultData<AccountDTO> getByCode(@PathVariable(value = "accountCode") String accountCode);
    }

    在接口上添加注解@FeignClient(name = "account-service"),表明这是一个Feign客户端,name属性的配置表示我这个接口最终会转发到accout-service上。

    正如回字有多种写法,这里Feign也有多种使用方式。第一种就是我们这里介绍的,Feign和生产者的RequestMapping保持一致,大家可以看看上面改造后的AccountControllerAccountFeign一模一样有米有。

    第二种方式就是让我们的Controller直接实现Feign接口,不再需要写RequestMapping,如:

    @RestController
    @Log4j2
    public class ProductController implements ProductFeign {
    @Autowired
    private ProductService productService;

    @Override
    public ResultData<String> insert(@RequestBody ProductDTO productDTO){
    log.info("insert product:{}",productDTO);
    productService.insertProduct(productDTO);
    return ResultData.success("insert product succeed");
    }
    }
    <dependency>
    <groupId>com.jianzh5.cloud</groupId>
    <artifactId>account-feign</artifactId>
    <version>1.0-SNAPSHOT</version>
    </dependency>
    @SpringBootApplication
    @RestController
    @EnableDiscoveryClient
    @EnableFeignClients(basePackages = "com.javadaily.feign.*")
    public class OrderServiceApplication {
    public static void main(String[] args) {
    SpringApplication.run(OrderServiceApplication.class, args);
    }
    }
    @RestController
    public class OrderController {
    @Autowired
    private AccountFeign accountFeign;

    @Autowired
    private ProductFeign productFeign;

    @PostMapping("/order/getAccount/{accountCode}")
    public ResultData<AccountDTO> getAccount(@PathVariable String accountCode){
    return accountFeign.getByCode(accountCode);
    }

    @PostMapping("/order/insertAccount")
    public ResultData<String> insertAccount(AccountDTO accountDTO){
    return accountFeign.insert(accountDTO);
    }

    @PostMapping("/order/updateAccount")
    public ResultData<String> updateAccount(AccountDTO accountDTO){
    return accountFeign.update(accountDTO);
    }

    @PostMapping("/order/deleteAccount/{accountCode}")
    public ResultData<String> deleteAccount(@PathVariable String accountCode){
    return accountFeign.delete(accountCode);
    }
    }

    血与泪

    使用feign过程中有以下几点需要注意,否则一不小心你就会掉进坑里。(我不会告诉你我当时在坑里踩了多久才爬上来)SpringCloud Alibaba微服务实战三 - 服务调用-LMLPHP

    @PostMapping("/account/insert")ResultData<String> insert(@RequestBody AccountDTO accountDTO);
    feign:
    client:
    config:
    default:
    connectTimeout: 5000
    readTimeout: 5000

    否则你会经常看到如下所示的错误:

    java.net.SocketTimeoutException: Read timed out
    at java.net.SocketInputStream.socketRead0(Native Method) ~[?:1.8.0_112]

    至此我们已经完成了项目公共返回接口的统一并且成功使用Feign调用远程生产者的服务,那么本期的“SpringCloud Alibaba微服务实战三 - 服务调用”篇也就该结束啦,咱们下期有缘再见!



    点击下方“阅读原文”查看更多


    本文分享自微信公众号 - JAVA日知录(javadaily)。
    如有侵权,请联系 support@oschina.cn 删除。
    本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

    09-13 13:45
    查看更多