Spring Cloud中聲明式服務調用Feign

前面幾篇文章咱們詳細的介紹了Ribbon、RestTemplate、Hystrix組件,這些組件是咱們Spring Cloud中很是基礎的組件,小夥伴們在使用的過程當中可能也發現了這些東西都是同時出現的,並且配置也都很是類似,每次開發都有不少相同的代碼,所以,Spring Cloud基於Netflix Feign整合了Ribbon和Hystrix,讓咱們的開發工做變得更加簡單,就像Spring Boot是對Spring+SpringMVC的簡化同樣。Spring Cloud Feign不只在配置上大大簡化了開發工做,同時還提供了一種聲明式的Web服務客戶端定義方式。
在前面幾篇文章中,咱們爲了簡化RestTemplate操做,將之封裝在一個BookService中,但同時咱們也發現BookService中的方法幾乎都是模板式的,寫起來很枯燥,Spring Cloud Feign對此進行了進一步的封裝,簡化了咱們的封裝操做。接下來咱們就來看看Spring Cloud Feign的使用。spring


本文是Spring Cloud系列的第十六篇文章,瞭解前十五篇文章內容有助於更好的理解本文: 緩存

1.使用Spring Cloud搭建服務註冊中心
2.使用Spring Cloud搭建高可用服務註冊中心
3.Spring Cloud中服務的發現與消費
4.Eureka中的核心概念
5.什麼是客戶端負載均衡
6.Spring RestTemplate中幾種常見的請求方式
7.RestTemplate的逆襲之路,從發送請求到負載均衡
8.Spring Cloud中負載均衡器概覽
9.Spring Cloud中的負載均衡策略
10.Spring Cloud中的斷路器Hystrix
11.Spring Cloud自定義Hystrix請求命令
12.Spring Cloud中Hystrix的服務降級與異常處理
13.Spring Cloud中Hystrix的請求緩存
14.Spring Cloud中Hystrix的請求合併
15.Spring Cloud中Hystrix儀表盤與Turbine集羣監控app


Spring Cloud Feign入門

環境搭建

OK,首先咱們經過下面六步來建立一個Spring Cloud Feign工程,先來體驗下Spring Cloud Feign帶給咱們的便利。負載均衡

第一步:建立普通Spring Boot工程

首先咱們來建立一個普通的Spring Boot工程,取名爲feign-consumer。ide

第二步:添加依賴

這裏要添加的依賴主要是spring-cloud-starter-eureka和spring-cloud-starter-feign,以下:spring-boot

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.7.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
    <spring-cloud.version>Dalston.SR3</spring-cloud.version>
</properties>
<dependencies>
    <!-- 其餘依賴 -->
    <!-- 本身添加的依賴 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
    </dependency>
</dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

第三步:添加註解

而後在工程的入口類上添加@EnableFeignClients註解表示開啓Spring Cloud Feign的支持功能,以下:測試

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class FeignConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(FeignConsumerApplication.class, args);
    }
}

第四步:聲明服務

定義一個HelloService接口,經過@FeignClient註解來指定服務名進而綁定服務,而後再經過SpringMVC中提供的註解來綁定服務提供者提供的接口,以下:編碼

@FeignClient("hello-service")
public interface HelloService {
    @RequestMapping("/hello")
    String hello();
}

這至關於綁定了一個名叫hello-service(這裏hello-service大小寫無所謂)的服務提供者提供的/hello接口。咱們來看一下我服務提供者提供的接口,以下:url

@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello() {
    return "hello";
}

第五步:Controller中調用服務

接着來建立一個Controller來調用上面的服務,以下:spa

@RestController
public class FeignConsumerController {
    @Autowired
    HelloService helloService;

    @RequestMapping("/hello")
    public String hello() {
        return helloService.hello();
    }
}

第六步:屬性配置

最後,咱們須要在application.properties中指定服務註冊中心,並配置端口號等,以下:

spring.application.name=feign-consumer
server.port=2005
eureka.client.service-url.defaultZone=http://localhost:1111/eureka/

測試

作完上面的操做以後,依次啓動eureka-server、provider和feign-consumer,而後訪問以下地址:http://localhost:2005/hello,訪問結果以下:

圖片描述

Ribbon和Hystrix的功能都有,只是咱們使用Feign實現起來更簡單,Feign使用了一種更加優雅的方式來調用服務提供者的接口,避免了咱們寫模板式的RestTemplate代碼。

參數傳遞

上面咱們看了一個簡單的調用案例,這個例子中沒有涉及到參數的傳遞,那麼接下來咱們就來看看參數的傳遞要如何實現。

首先我先給個人服務提供者添加三個測試接口,以下:

@RequestMapping(value = "/hello1", method = RequestMethod.GET)
public String hello1(@RequestParam String name) {
    return "hello " + name + "!";
}

@RequestMapping(value = "/hello2", method = RequestMethod.GET)
public Book hello2(@RequestHeader String name, @RequestHeader String author, @RequestHeader Integer price) throws UnsupportedEncodingException {
    Book book = new Book();
    book.setName(URLDecoder.decode(name,"UTF-8"));
    book.setAuthor(URLDecoder.decode(author,"UTF-8"));
    book.setPrice(price);
    System.out.println(book);
    return book;
}

@RequestMapping(value = "/hello3", method = RequestMethod.POST)
public String hello3(@RequestBody Book book) {
    return "書名爲:" + book.getName() + ";做者爲:" + book.getAuthor();
}

hello1接口主要是接收一個String類型的參數,參數經過key-value的形式傳來,而後返回一個String類型的數據;hello2接口接收到參數攜帶在請求頭中,請求頭中傳遞中文會亂碼,因此要先編碼,再解碼(固然若是傳遞的是英文就不用這麼麻煩),而後返回一個Book對象;hello3則接收一個Book對象,返回一個字符串。

測試接口寫好以後,咱們再來看看feign-consumer工程中的HelloService接口要怎麼寫,以下:

@FeignClient("hello-service")
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)
    Book hello(@RequestHeader("name") String name, @RequestHeader("author") String author, @RequestHeader("price") Integer price);

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

這裏有一個細節須要小夥伴們注意,在SpringMVC中,@RequestParam和@RequestHeader註解,若是咱們不指定value,則默認採用參數的名字做爲其value,可是在Feign中,這個value必須明確指定,不然會報錯。

最後添加測試接口,以下:

@RestController
public class FeignConsumerController {
    @Autowired
    HelloService helloService;

    @RequestMapping("/hello")
    public String hello() {
        return helloService.hello();
    }

    @RequestMapping("/hello1")
    public String hello1() {
        return helloService.hello("張三");
    }

    @RequestMapping(value = "/hello2")
    public Book hello2() throws UnsupportedEncodingException {
        Book book = helloService.hello(URLEncoder.encode("三國演義","UTF-8"), URLEncoder.encode("羅貫中","UTF-8"), 33);
        System.out.println(book);
        return book;
    }

    @RequestMapping("/hello3")
    public String hello3() {
        Book book = new Book();
        book.setName("紅樓夢");
        book.setPrice(44);
        book.setAuthor("曹雪芹");
        return helloService.hello(book);
    }
}

運行結果以下:

http://localhost:2005/hello1

圖片描述

http://localhost:2005/hello2

圖片描述

http://localhost:2005/hello3

圖片描述

OK,關於Feign入門咱們就先說到這裏,有問題歡迎留言討論。

更多JavaEE資料請關注公衆號:

圖片描述

相關文章
相關標籤/搜索