Spring Cloud中使用Feign(十二)

首先还是需要去们的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名称:类名):

  • Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecoder)
  • Encoder feignEncoder: SpringEncoder
  • Logger feignLogger: Slf4jLogger
  • Contract feignContract: SpringMvcContract
  • Feign.Builder feignBuilder: HystrixFeign.Builder
  • 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

源码点击这里

猜你喜欢

转载自blog.csdn.net/mrspirit/article/details/80388108