spring cloud feign , 它基于netflix feign实现,整合了spring cloud ribbon 与 spring cloud hystrix。
在我们实际开发中,由于对服务依赖的调用可能不止于一处,往往一个接口会被多处调用,所以我们通常都会针对各个微服务自行封装一些客户端类包装这些依赖服务的调用,但大多数的编码都是模板化的内容。spring cloud
feign在此基础上做了进一步封装,我们只需要创建一个接口并用注解的方式配置它,即可完成对服务提供方的接口绑定
版本 spring boot 15.14
简单实现
注册中心
启动类 |
package springcloud.eurekaserver;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer // 注解启动一个服务注册中心 @SpringBootApplication public class EurekaServerApplication {
public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } |
配置文件 |
server.port=1111 eureka.instance.hostname=localhost #由于该应用为注册中心,所有设置为false,代表不向注册中心注册自己 eureka.client.register-with-eureka=false #由于注册中心的职责就是维护服务实例,它并不需要去检索服务,所以也设置为false eureka.client.fetch-registry=false eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/ |
创建一个 api 模块,专门放通用的接口与实体,使用spring boot web 项目
实体 |
package springcloud.helloserviceapi;
import java.io.Serializable;
public class User implements Serializable{ private String name; private Integer age;
@Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; }
public User(){
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; } } |
接口 在定义各参数绑定时,@RequestParam,@RequestHeader等可以指定参数名称的注解, 它们的value 不能少。在spring mvc中,这些注解会根据参数名作为默认值,但是在feign中绑定参数必须 通过value属性来指明具体的参数名 |
package springcloud.helloserviceapi; import org.springframework.web.bind.annotation.*;
@RequestMapping("helloController") public interface HelloService {
@RequestMapping(value = "/hello",method = RequestMethod.GET) String hello();
@RequestMapping(value = "/hello1",method = RequestMethod.GET) String hello(@RequestParam("name") String name);
@RequestMapping(value = "/hello2",method = RequestMethod.GET) User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age);
@RequestMapping(value = "/hello3",method = RequestMethod.POST) String hello(@RequestBody User user);
} |
maven 依赖 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> |
服务提供端
启动类 |
package springcloud.eureka_provider_pt;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient @SpringBootApplication public class EurekaProviderPtApplication {
public static void main(String[] args) { SpringApplication.run(EurekaProviderPtApplication.class, args); } } |
controller @RequestParam @RequestHeader 注解不能省 |
package springcloud.eureka_provider_pt;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.*; import springcloud.helloserviceapi.HelloService;
@RestController public class HelloController implements HelloService{
@Override public String hello() { return "Hello World eueka_provider gz1"; }
@Override public String hello(@RequestParam("name") String name) { return "hello "+name; }
@Override public springcloud.helloserviceapi.User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age) { springcloud.helloserviceapi.User user=new springcloud.helloserviceapi.User(); user.setAge(age); user.setName(name); return user; }
@Override public String hello(@RequestBody springcloud.helloserviceapi.User user) { return "hello "+user.getName()+", "+user.getAge(); } }
|
配置文件 |
spring.application.name=hello-service
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/ |
服务消费端
service 接口,通过@FeignClient注解指定服务名来绑定服务,然后再使用spring mvc 的注解来绑定具体该服务提供的REST接口 |
package springcloud.feign;
import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.*; import springcloud.helloserviceapi.HelloService;
@FeignClient("hello-service") public interface HelloServiceExtends extends HelloService{
} |
controller |
package springcloud.feign; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import springcloud.helloserviceapi.User;
@RestController public class HelloController { @Autowired protected HelloServiceExtends helloService;
@RequestMapping(value = "/feign-consumer",method = RequestMethod.GET) public String helloConsumer(){ return helloService.hello(); }
@RequestMapping(value = "/feign-consumer2",method = RequestMethod.GET) public void helloConsumer2(){ User user = new User(); user.setAge(24); user.setName("shendu"); System.out.println(helloService.hello(user)); System.out.println(helloService.hello("shendu")); System.out.println(helloService.hello("shendu",24)); } } |
启动类用 @EnableFeignClients 打开对feign 的支持 |
package springcloud.feign;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.feign.EnableFeignClients;
@EnableDiscoveryClient @EnableFeignClients @SpringBootApplication public class FeignApplication {
public static void main(String[] args) { SpringApplication.run(FeignApplication.class, args); } } |
配置文件 |
spring.application.name=feign-consumer server.port=9001 eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/ |
maven pom文件 |
<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> |
结果
参考 spring cloud 微服务实战 (程序员DD)