SpringCloud學習筆記(3):使用Feign實現聲明式服務調用

簡介

Feign是一個聲明式的Web Service客戶端,它簡化了Web服務客戶端的編寫操做,相對於Ribbon+RestTemplate的方式,開發者只需經過簡單的接口和註解來調用HTTP API。它支持Spring MVC註解和JAX-RS註解,還支持可插拔式的編碼器和解碼器。整合了Eureka,Ribbon和Hystrix,具備可插拔、基於註解、負載均衡、服務熔斷等一系列便捷功能。html

項目介紹

  1. sc-parent,父模塊(請參照SpringCloud學習筆記(1):Eureka註冊中心)
  2. sc-eureka,註冊中心(請參照SpringCloud學習筆記(1):Eureka註冊中心)
  3. sc-provider,提供者(請參照SpringCloud學習筆記(1):Eureka註冊中心)
  4. sc-consumer-feign,基於Feign聲明式調用的消費者

基於Feign聲明式調用的消費者

1.在父模塊下建立子模塊項目sc-consumer-feign,pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.cf</groupId>
    <artifactId>sc-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>sc-consumer-feign</artifactId>
  
  <dependencies>
  	<dependency>
	    <groupId>org.springframework.cloud</groupId>
	    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>
	<dependency>
	    <groupId>org.springframework.cloud</groupId>
	    <artifactId>spring-cloud-starter-openfeign</artifactId>
	</dependency>
  </dependencies>
</project>

2.建立啓動類feign.FeignApplication:

package feign;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
public class FeignApplication {
	public static void main(String[] args) {
		SpringApplication.run(FeignApplication.class, args);
	}
}

3.建立Feign聲明式接口:feign.inter.BookService

package feign.inter;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient("sc-provider")
public interface BookService {
	
	@GetMapping("/book/list")
	public String getBookList();
}

4.建立調用提供者服務的Controller:

package feign.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import feign.inter.BookService;

@RequestMapping("/feign")
@RestController
public class FeignController {
	@Autowired
	private BookService bookService;
	
	@GetMapping("/getBookList")
	public String getBookList(){
		return bookService.getBookList();
	}
}

5.建立application.yml:

server:
  port: 8084

spring:
  application:
    name: sc-consumer-feign
    
eureka:
  client:
    registerWithEureka: false
    serviceUrl:
      defaultZone: http://localhost:8080/eureka/

6.依次啓動註冊中心sc-eureka、提供者sc-provider、消費者sc-consumer-feign,並訪問http://localhost:8084/feign/getBookList:

Feign基於Ribbon實現,也具備Ribbon負載均衡的特性,能夠將調用的提供者服務換成sc-provider-random(請參照SpringCloud學習筆記(2):使用Ribbon負載均衡)來測試。java

帶參數的請求

上面例子沒有涉及到參數的傳遞,接下來測試下如何使用Feign構造帶參數的請求,首先對提供者和消費者作以下更改:web

//提供者Controller添加了兩個參數,並打印到控制檯。
@RequestMapping("/book")
@RestController
public class BookController {
	@GetMapping("/list")
	public String getBookList(String param1, Integer param2){
		System.out.println(param1 + ":" + param2);
		return "[\"Java入門到放棄\",\"C++入門到放棄\",\"Python入門到放棄\",\"C入門到放棄\"]";
	}
}


//消費者Feign接口和Controller添加參數
@FeignClient("sc-provider")
public interface BookService {
	@GetMapping("/book/list")
	public String getBookList(String param1, Integer param2);
}

@RequestMapping("/feign")
@RestController
public class FeignController {
	@Autowired
	private BookService bookService;
	
	@GetMapping("/getBookList")
	public String getBookList(){
		return bookService.getBookList("Java", 520);
	}
}

依次啓動註冊中心sc-eureka、提供者sc-provider、消費者sc-consumer-feign,啓動消費者sc-consumer-feign時會啓動失敗: <font color="red">java.lang.IllegalStateException: Method has too many Body parameters: public abstract java.lang.String feign.inter.BookService.getBookList(java.lang.String,java.lang.Integer)</font>spring

解決方法1

更改Feign接口,爲參數添加@RequestParam註解:apache

@FeignClient("sc-provider")
public interface BookService {
	@GetMapping("/book/list")	
	public String getBookList(@RequestParam("param1") String param1, @RequestParam("param2") Integer param2);
}

解決方法2

將參數封裝到Map裏,更改消費者Feign接口和Controller:app

@FeignClient("sc-provider")
public interface BookService {
	@GetMapping("/book/list")
	public String getBookList(@RequestParam Map<String, Object> paramMap);
}

@RequestMapping("/feign")
@RestController
public class FeignController {
	@Autowired
	private BookService bookService;
	
	@GetMapping("/getBookList")
	public String getBookList(){
		Map<String,Object> paramMap = new HashMap<String, Object>();
		paramMap.put("param1", "Java");
		paramMap.put("param2", 520);
		return bookService.getBookList(paramMap);
	}
}

在參數較多的狀況下,該方式能夠簡化Feign接口的編寫。負載均衡

自定義類型的參數

OpenFeign的@QueryMap註解支持將自定義類型用於GET參數映射,因爲@QueryMap和Spring不兼容,Spring Cloud OpenFeign提供了一個等價的@SpringQueryMap註解,能夠用於自定義類型和Map類型的參數映射。下面將使用自定義類型Params做爲參數,使用@SpringQueryMap註解來處理自定義類型的參數映射。dom

1.分別在提供者和消費者中建立類Params(能夠建一個公共模塊,而後在提供者和消費者中添加依賴):

public class Params {
	private String param1;
	
	private Integer param2;

	public String getParam1() {
		return param1;
	}

	public void setParam1(String param1) {
		this.param1 = param1;
	}

	public Integer getParam2() {
		return param2;
	}

	public void setParam2(Integer param2) {
		this.param2 = param2;
	}
	
	@Override
	public String toString() {
		return "Params [param1=" + param1 + ", param2=" + param2 + "]";
	}

	public Params(String param1, Integer param2) {
		this.param1 = param1;
		this.param2 = param2;
	}

	public Params() {}
}

2.更改提供者和消費者相關類

//提供者
@RequestMapping("/book")
@RestController
public class BookController {
	@GetMapping("/list")
	public String getBookList(Params params){
		System.out.println(params.toString());
		return "[\"Java入門到放棄\",\"C++入門到放棄\",\"Python入門到放棄\",\"C入門到放棄\"]";
	}
}

//消費者
@FeignClient("sc-provider")
public interface BookService {
	@GetMapping("/book/list")
	public String getBookList(@SpringQueryMap Params params);
}

@RequestMapping("/feign")
@RestController
public class FeignController {
	@Autowired
	private BookService bookService;
	
	@GetMapping("/getBookList")
	public String getBookList(){	
		Params params = new Params("Java", 520);
		return bookService.getBookList(params);
	}
}

3.依次啓動註冊中心sc-eureka、提供者sc-provider、消費者sc-consumer-feign,並訪問http://localhost:8084/feign/getBookList,提供者控制檯輸出:

Params [param1=Java, param2=520]

原文出處:https://www.cnblogs.com/seve/p/11512249.htmlmaven

相關文章
相關標籤/搜索