一、简述
Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单。Feign是对Ribbon的包装,Feign集成了Ribbon。
前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模版化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它,即可完成对服务提供方的接口绑定,简化了使用Spring cloud Ribbon时,自动封装服务调用客户端的开发量。
个人理解:feign也是客户端的负载均衡,它包装了ribbon。ribbon负载均衡是面向整个服务的,而feign是面向服务的接口,这样更利于我们这些面向接口编程的人。它的原理就是写一个调用服务提供者的接口,然后客户端访问时在controller中调用这个接口。就是在服务端、消费端中间又加了一层接口,这个接口通过feign来访问服务端并实现接口的负载均衡。
二、配置feign负载均衡
1.创建module
在父项目中新建module:microservice-consumer-feign8080
2.添加依赖
pom:
<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.syr.springcloud</groupId>
<artifactId>microservice</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>microservice-consumer-feign8080</artifactId>
<dependencies>
<dependency>
<groupId>com.syr.springcloud</groupId>
<artifactId>microservice-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 修改后立即生效,热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- Ribbon相关 -->
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
</project>
3.配置信息
server:
port: 8080
eureka:
register-with-eureka: false
client:
service-url:
defaultZone: http://eureka2001.com:2001/eureka/,http://eureka2002.com:2002/eureka/,http://eureka2003.com:2003/eureka/
4.创建接口
注意:接口上要标注@FeignClient(value = “microservicecloud-provider”)
其中value值为需要访问的服务名称(eureka上注册的服务名称)
package com.syr.consumer.service;
import java.util.List;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import com.syr.api.entity.User;
@RequestMapping("users")
@FeignClient(value = "microservicecloud-provider")
public interface UserService {
@GetMapping(value = "{id}")
public User get(@PathVariable("id") int id) ;
@GetMapping
public List<User> get() ;
@PostMapping
public boolean post(@RequestBody User user) ;
@DeleteMapping("{id}")
public boolean delete(@PathVariable("id") int id);
@PutMapping
public boolean put(@RequestBody User user);
}
5.创建controller
注意:该controller中,访问路径不应该与service接口中的路径一样,会报错。所有我在@RequestMapping("/consumer/users")
中添加了一层consumer
package com.syr.consumer.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.syr.api.entity.User;
import com.syr.consumer.service.UserService;
@RestController
@RequestMapping("/consumer/users")
public class UserController {
@Autowired
private UserService service;
@GetMapping(value = "{id}")
public User get(@PathVariable("id")int id) {
User user=service.get(id);
return user;
}
@GetMapping
public List<User> get() {
List<User> users=service.get();
return users;
}
@PostMapping
public boolean post(@RequestBody User user) {
boolean b = service.post(user);
return b;
}
@DeleteMapping("{id}")
public boolean delete(@PathVariable("id") int id) {
boolean b = service.delete(id);
return b;
}
@PutMapping
public boolean put(@RequestBody User user) {
boolean b = service.put(user);
return b;
}
}
6.开启feign
basePackages是feign接口所在包
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = "com.syr.consumer.service")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
7.测试
测试成功
8.通用
一些需要共用的服务,它的fiegn接口应放在通用项目中如:microservice-api
9.与ribbon的对比
ribbon是面向整个服务,而feign面向服务的接口
ribbon中,由于restTemplate的 delete、put方法是没有返回值的,所以执行后也不知道是否成功。而feign是feign查找服务controller中的方法,也就是对应的是方法,是可以有返回值的。