一、Feign是什么?
Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单,它的使用方法就是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可插拔式的编码器和解码器。SpringCloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。在Spring Cloud feign的实现下,只需要创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon时自行封装服务调用客户端的开发量。
二、工程的搭建
2.1、eureka搭建(spring-cloud-eureka-server)
- Maven
4.0.0
com.yk
cloud-parent
0.0.1-SNAPSHOT
springcloud-eureka-server
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
- application.yml
spring:
application:
name: spring-cloud-eureka-server
server:
#使用启动命令覆盖默认的801
port: 1234
eureka:
client:
##让自己不需要注册在上面禁止客户端注册,表明自己是一个eureka server
register-with-eureka: false
fetch-registry: false
service-url:
#服务注册
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
instance:
hostname: localhost
- 入口类
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
2.2、公共接口搭建(springcloud-api)
- Maven
4.0.0
com.yk
cloud-parent
0.0.1-SNAPSHOT
springcloud-api
org.springframework.cloud
spring-cloud-starter-openfeign
- entity
@Data
public class User {
/**
* ID
*/
private Long id;
/**
* 用户名称
*/
private String name;
}
- service
//声明Feign客户端,使用占位符方式防止硬编码,如果没有使用eureka需要指定url=ip地址+端口,fallback回调地址
@FeignClient(name="${user.service.name}",fallback = UserFallback.class)
public interface UserService {
/**
* 保存用户
* @param user
*/
@PostMapping("/user/save")
boolean saveUser( User user);
/**
* 查询所有的用户列表
*/
@GetMapping("/user/find/all")
List findAll();
}
- fallback
/**
* @description: 熔断的回调
* @create: 2019年06月19日 21时16分
**/
public class UserFallback implements UserService {
@Override
public boolean saveUser(User user) {
return false;
}
@Override
public List findAll() {
return Collections.emptyList();
}
}
2.3、服务提供者工程(spring-cloud-api-provider)
- Maven
4.0.0
com.yk
cloud-parent
0.0.1-SNAPSHOT
springcloud-api-provider
com.yk
springcloud-api
0.0.1-SNAPSHOT
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
- application.properties
## 用户服务提供方应用信息
spring.application.name = spring-cloud-api-provider
## 服务端口
server.port = 801
#配置eureka
eureka.client.serviceUrl.defaultZone = http://localhost:1234/eureka/
eureka.instance.hostname = localhost
eureka.instance.prefer-ip-address = true
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
- 启动入口类
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableHystrix //熔断器
@EnableDiscoveryClient //eureka
public class ApiProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ApiProviderApplication.class, args);
}
}
- ServiceImpl
@Service
public class UserServiceImpl implements UserService {
private Map repository = new ConcurrentHashMap<>();
@Override
public boolean saveUser(User user) {
return repository.put(user.getId(), user) == null;
}
@Override
public List findAll() {
return new ArrayList(repository.values());
}
}
- Controller
@RestController
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/user/save")
public boolean saveUser(@RequestBody User user) {
return userService.saveUser(user);
}
@HystrixCommand(
// Command 配置,设置操作时间为 100 毫秒
commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "100")},
// 设置 fallback 方法
fallbackMethod = "fallbackForGetUsers"
)
@GetMapping("/user/find/all")
public List findAll() {
return userService.findAll();
}
/**
* 超过100毫秒就返回空集合
* @return
*/
public List fallbackForGetUsers() {
return Collections.emptyList();
}
}
2.3、服务调用者工程(spring-cloud-api-client)
- Maven
4.0.0
com.yk
cloud-parent
0.0.1-SNAPSHOT
springcloud-api-client
com.yk
springcloud-api
0.0.1-SNAPSHOT
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
- application.properties
## 用户 Ribbon 客户端应用
spring.application.name = spring-cloud-api-client
## 服务端口
server.port = 802
## 提供方服务名称
provider.service.name = spring-cloud-api-provider
#配置@FeignClient(name="${user.service.name}")中的占位符
#user.service.name实际需要指定UserService接口的提供方,也就是spring-cloud-api-provider
user.service.name = ${provider.service.name}
#配置eureka
eureka.client.serviceUrl.defaultZone = http://localhost:1234/eureka/
eureka.instance.hostname = localhost
eureka.instance.prefer-ip-address = true
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
- 启动入口类
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
// 使用客户端短路
@EnableCircuitBreaker
//声明 UserService接口作为Feign Client 调用
@EnableFeignClients(clients = UserService.class)
@EnableDiscoveryClient
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
- Controller
@RestController
public class FeignUserController implements UserService {
//UserService@FeignClient注解默认primary是true,相当于代理
@Autowired
private UserService userService;
//这里使用Feign的继承特性,会将UserService里面的@RequestMapping继承过来但是@RequestBoday是不会继承过来的
@Override
public boolean saveUser(@RequestBody User user) {
return userService.saveUser(user);
}
@Override
public List findAll() {
return userService.findAll();
}
}
这里就不提供演示图了,如果想测试Feign的负载均衡只需要将服务提供者开启多个实例就OK了。后续学习的技术点也是在此工程的基础上的