SpringCloud-Feign声明式客户端(Rest调用)

Feign客户端-声明式REST调用

1.0分析

之前是通过RestTemplate调用Rest服务,代码是这样写的

@HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod")
    public Item queryItemById3(Long id) {

        Item result = itemFeignClient.queryItemById(id);
        System.out.println("===========HystrixCommand queryItemById-线程池名称:" + Thread.currentThread().getName() + "订单系统调用商品服务,result:" + result);
        return result;
    }
}

虽然使用了Ribbon和Hystrix可以实现负载均衡和容错处理,但是这个编码在实现大量业务时会显得太过于冗余(如,多参数的URL拼接)。
思考:有没有更加优雅的实现呢?

2.0.Feign的简介

在这里插入图片描述
2.1.快速入门
在订单微服务microservice order中增加对Feign的支持。

2.1.1导入maven坐标

<!--springboot 整合fegnin客户端-->
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2.1.2创建一个ItemFeignClient接口

package com.mr.feignclient;

import com.mr.entity.Item;
import com.mr.servicefallback.ItemServiceFallback;
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;
/**
 * 申明这是一个Feign客户端,并且指明服务id
 * @author Evan
 */
@FeignClient(value = "gigest-commodity" ,fallback = ItemServiceFallback.class)
public interface ItemFeignClient {
    /**
     * 这里定义了类似于SpringMVC用法的方法,就可以进行RESTful方式的调用了
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "/item/{id}", method = RequestMethod.GET)
    Item queryItemById(@PathVariable("id") Long id);

    
}

2.2.3 改变ItemService

package com.mr.order.service.impl;


import com.mr.entity.Item;
import com.mr.feignclient.ItemFeignClient;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class ItemService {

    // Spring框架对RESTful方式的http请求做了封装,来简化操作
    @Autowired
    private ItemFeignClient itemFeignClient;

    /*@HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod")*/
    public Item queryItemById3(Long id) {

        Item result = itemFeignClient.queryItemById(id);
        System.out.println("===========HystrixCommand queryItemById-线程池名称:" + Thread.currentThread().getName() + "订单系统调用商品服务,result:" + result);
        return result;
    }


    /**
     * 请求失败执行的方法
     * fallbackMethod的方法参数个数类型要和原方法一致
     *
     * @param id
     * @return
     */
    /*public Item queryItemByIdFallbackMethod(Long id) {
        return new Item(id, "查询商品信息出错!", null, null, null);
    }*/


}

2.2.4.在启动类行添加 @EnableFeignClients 注解

package com.mr;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.client.RestTemplate;

/**
 * @author Evan
 */
@SpringBootApplication//申明这是一个Spring Boot项目
@EnableHystrix
@EnableFeignClients(basePackages="com.mr.feignclient")
@ComponentScan(basePackages = {"com.mr.order.controller", "com.mr.order.service.impl","com.mr.servicefallback"})//手动指定bean扫描范围
public class OrderApp {
    public static void main(String[] args) {
        SpringApplication.run(OrderApp.class, args);
    }

    /**
     * 向Spring容器中定义RestTemplate对象
     * @return
     */
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

2.2.5启动测试

测试正常
在这里插入图片描述

2.2.6到底发生了什么?

@Autowired
private ItemFeignClient itemFeignClient;

@HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod")
public Item queryItemById3(Long id) {
    String itemUrl = "http://app-item/item/{id}";
    //Item result = restTemplate.getForObject(itemUrl, Item.class, id);
    Item result = itemFeignClient.queryItemById(id);
    return result;
}

写这样的代码,就可以访问RESTful服务啦?

流程分析:
1、由于我们在入口程序使用了@EnableFeignClients注解,Spring启动后会扫描标注了@FeignClient注解的接口,然后生成代理类。
2、我们在@FeignClient接口中指定了value,其实就是指定了在Eureka中的服务名称。
3、在FeignClient中的定义方法以及使用了SpringMVC的注解,Feign就会根据注解中的内容生成对应的URL,然后基于Ribbon的负载均衡去调用REST服务。
为什么使用的是SpringMVC的注解?

i.其实,Feign是有自己的注解的@RequestLine,是因为Spring Cloud对Feign做了增强,兼容了SpringMVC的注解,使我们的学习成本更低

在这里插入图片描述
ii.专业的解释是这样的:
org.springframework.cloud.netflix.feign.FeignClientsConfiguration
在这里插入图片描述
设置的默认契约是SpringMVC契约。

2.2.7.Feign的多参数构造

服务方参数列表使用注解@RequestParam、@PathVariable修饰
在这里插入图片描述

2.2.8设置统一的hystrix fallback接口

一般在实际开发中fallback 方法不会直接写在接口方法所在类里,那样太杂乱,例如之前订单工程中的写法:

@HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod")
public Item queryItemById3(Long id) {
    Item result = itemFeignClient.queryItemById(id);
    System.out.println("===========HystrixCommand queryItemById-线程池名称:" + Thread.currentThread().getName() + "订单系统调用商品服务,result:" + result);
    return result;
}

public Item queryItemByIdFallbackMethod(Long id) {
    return new Item(id, "查询商品信息出错!", null, null, null);
}

Order工程改进(将fallback方法放到类中):
1.不在方法上使用@HystrixCommand注解

//@HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod")
public Item queryItemById3(Long id) {
    Item result = itemFeignClient.queryItemById(id);
    System.out.println("===========HystrixCommand queryItemById-线程池名称:" + Thread.currentThread().getName() + "订单系统调用商品服务,result:" + result);
    return result;
}

2.创建回调类

package com.mr.servicefallback;

import com.mr.entity.Item;
import com.mr.feignclient.ItemFeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
/**
 * 此类中的方法专门用于服务降级,该类一般要实现调用远程服务的接口(这样保证方法名一致)
 */
@Component
public class ItemServiceFallback  implements ItemFeignClient {
    /**
     * 服务降级的方法要和原方法一致(名称、参数列表)
     * @param id
     * @return
     */
    @Override
    public Item queryItemById(@PathVariable("id") Long id) {
        return new Item(00, "服务降级方法queryItemById", null, "服务降级方法queryItemById", null);
    }
}

3.在Feign客户端中添加fallback属性

package com.mr.feignclient;

import com.mr.entity.Item;
import com.mr.servicefallback.ItemServiceFallback;
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;
/**
 * 申明这是一个Feign客户端,并且指明服务id
 * @author Evan
 */
@FeignClient(value = "gigest-commodity" ,fallback = ItemServiceFallback.class)
public interface ItemFeignClient {
    /**
     * 这里定义了类似于SpringMVC用法的方法,就可以进行RESTful方式的调用了
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "/item/{id}", method = RequestMethod.GET)
    Item queryItemById(@PathVariable("id") Long id);

    
}

4.配置文件中开启hystrix

#开启hystrix断路器
feign:
  hystrix:
    enabled: true

5.修改启动类,增加包扫描

@ComponentScan(basePackages = {"com.mr.order.controller", "com.mr.order.service.impl","com.mr.servicefallback"})//手动指定bean扫描范围

6.重新启动应用测试
服务都正常的情况:
在这里插入图片描述
在这里插入图片描述
停止Item服务,访问Order服务没有配置hystrix熔断的普通方法:
在这里插入图片描述
配置fallback类OK!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值