Spring Cloud中使用Feign(十二)

個人博客請訪問 http://www.x0100.top     

首先還是需要去們的Spring Cloud服務管理框架Eureka簡單示例(三)這篇博客底部拿到源碼,這是一個最微型的集羣。爲了符合後面的測試,先把eureka-provider項目com.init.springCloud包下的ProviderApp類修改成按照端口啓動:

package com.init.springCloud;
 
import java.util.Scanner;
 
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 
@SpringBootApplication
@EnableEurekaClient
public class ProviderApp {
 
	public static void main(String[] args) {
		@SuppressWarnings("resource")  
        Scanner scan = new Scanner(System.in);  
        String port = scan.nextLine();  
        new SpringApplicationBuilder(ProviderApp.class).properties("server.port=" + port).run(args);  
	}
 
}

接着爲ProviderController控制器添加一個方法,用於返回簡單的JSON字符串:

@RequestMapping(value = "/hello/{name}", method = RequestMethod.GET)
public String sayHello(@PathVariable String name){
	return "hello "+name+", I'm glad to see you.";
}

然後修改eureka-consumer項目的application.yml配置文件,將啓動端口號修改爲9090:

server:
  port: 9090

之後依次運行三個項目的**App類裏面的main方法,啓動三個項目。注意,eureka-provider項目需要在控制檯輸入端口號之後回車。之後訪問:http://localhost:8761,http://localhost:8080/search/1,http://localhost:9090/router,看看是否都能正常調用。

引入Spring Cloud中的Feign

因爲feign是用於服務調用端,做服務調用的,我們在eureka-consumer項目中引入它的依賴:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

然後開啓feign,讓eureka-consumer能夠使用到feign提供的能力。找到ConsumerApp啓動類,增加@EnableFeignClients的註解:

package com.init.springCloud;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
 
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class ConsumerApp {
 
	public static void main(String[] args) {
		SpringApplication.run(ConsumerApp.class, args);
	}
 
}

 然後,我們需要定義一個接口PersonClient,用做Feign處理請求調用:

package com.init.springCloud;
 
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@FeignClient("eureka-provider")
public interface PersonClient {
 
	@RequestMapping(method = RequestMethod.GET, value = "/hello/{name}")
	String sayHello(@PathVariable("name") String name);
	
}

 

在接口上,我們使用了@FeignClient註解,表明需要請求的服務提供者的服務ID(ServiceId),然後在抽象方法上面用Spring提供的註解@RequestMapping,註明請求的方式和路徑,參數也用Spring註解@PathVariable修飾(注意需要把參數名稱填進去),Feign內部有專門的SpringMvcContract註解解釋器(這個註解解釋器可以查看OpenFeign之feign使用簡介(十一))來理解Spring的@RequestMapping註解,所以在這裏使用Spring的註解來替代feign提供的@RequestLine,讓我們迴歸到了熟悉的配置上,簡化了開發難度。

接下來就是重新編寫ConsumerController控制器,注入我們剛剛編寫的PersonClient接口:

package com.init.springCloud;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
 
@RestController
public class ConsumerController {
	
	@Autowired PersonClient PersonClient;
	
	@RequestMapping(method = RequestMethod.GET, value = "/router/{name}", 
			produces = MediaType.APPLICATION_JSON_VALUE)
	public String router(@PathVariable String name){
		return PersonClient.sayHello(name);
	}
	
}

重新啓動eureka-consumer項目,訪問:http://localhost:9090/router/spirit,瀏覽器能正常返回我們的字符串,就說明我們編寫的Feign客戶端運行正常

Feign的負載均衡效果

基於Ribbon,Feign也擁有負載均衡的效果(不用再引入Ribbon依賴)。

修改eureka-provider的Person實體類,新增一個屬性,用端口來確認訪問的哪一個服務:

package com.init.springCloud;
 
import lombok.Data;
 
@Data
public class Person {
 
	private Integer id;			//主鍵ID
	private String name;		//姓名
	private String info;		//url路徑信息
	
}

然後修改ProviderController控制器,通過請求獲取這個url信息:

@RequestMapping(value = "/search/{id}", method = RequestMethod.GET, 
		produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Person searchPerson(@PathVariable Integer id, HttpServletRequest request){
	Person person = new Person();
	person.setId(id);
	person.setName("Spirit");
	person.setInfo(request.getRequestURL().toString());  
	return person;
}

 

啓動兩個eureka-provider項目,端口分別是8080和8081。

然後拷貝eureka-provider項目的Person實體到eureka-consumer中(lombok需要引入相關依賴,也可以改寫成自己生成getter、setter方法),在PersonClient接口中新增方法,用於返回這個實體:

@RequestMapping(method = RequestMethod.GET, value = "/search/{id}")
Person getPersonById(@PathVariable("id") Integer id);

然後在ConsumerController項目中新增方法,返回Person實體類的JSON字符串:

@RequestMapping(method = RequestMethod.GET, value = "/find/{id}", 
		produces = MediaType.APPLICATION_JSON_VALUE)
public Person getPersonById(@PathVariable Integer id){
	return PersonClient.getPersonById(id);
}

 重啓eureka-consumer項目,瀏覽器多次訪問:http://localhost:9090/find/1,我們可以看到Feign實現了負載均衡的效果:

Feign提供的Bean組件

Spring Cloud Netflix在默認情況下提供了以下bean(Bean類型  Bean名稱:類名):

  1. Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecoder)
  2. Encoder feignEncoder: SpringEncoder
  3. Logger feignLogger: Slf4jLogger
  4. Contract feignContract: SpringMvcContract
  5. Feign.Builder feignBuilder: HystrixFeign.Builder
  6. Client feignClient: if Ribbon is enabled it is a LoadBalancerFeignClient, otherwise the default feign client is used.

我們可以通過設置feign.okhttp.enabled或者feign.httpclient.enabled屬性爲true來分別啓用OkHttpClient和ApacheHttpClient的Feign客戶端,然後分別在類路徑中使用它們。

Spring Cloud Netflix在默認情況下不提供以下bean,但仍然從應用程序上下文中查找這些類型的bean,以創建feign客戶端:

  • Logger.Level
  • Retryer
  • ErrorDecoder
  • Request.Options
  • Collection<RequestInterceptor>
  • SetterFactory
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章