学习
Spring Cloud
之路,文中Spring Boot
版本为2.1.3.RELEASE
,Spring Cloud
版本为Greenwich.SR1
。因能力有限,难免会有不足或者错误之处,还望不吝指正,谢!
之前 Spring Cloud 学习 | - 03 - 服务消费(Rest + Ribbon实现负载均衡),我们使用Rest+Ribbon方式实现消费的负载均衡。如果只是这样,那么以后我们可能需要编写大量重复代码,而且格式基本相同,只是参数不同罢了,能不能有一种更优雅简洁的方式实现呢?我们可以用Feign方式实现。
Feign是Netflix开发的声明式、模块化的HTTP客户端。Feign可以帮助我们更加便捷、优雅的调用HTTP API, 可以做到使用HTTP请求远程服务时能与调用本地方法一样的编码体验,完全感知不到这是远程方法,更感知不到这是个HTTP请求。
在Spring Cloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解,代码便完成了。Feign支持多种注解,礼服Feign自带的注解或JAX-RS注解等。
Spring Cloud对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了RIbbon和Eureka,从而让Feign的使用更加方便。
详细请查阅Spring Cloud 学习 | - 01 - Eureka服务注册与发现一文。
Service接口:
public interface UserService {
/**
* 查询所有用户
* @return
*/
List findAll();
/**
* hello,${name}
* @param name
* @return
*/
String hello(String name);
}
实现类:
@Service
public class UserServiceImpl implements UserService {
/**
* 查询所有用户
* @return
*/
@Override
public List findAll() {
List list = Arrays.asList("Cindy","Pony","Marry");
return list;
}
@Override
public String hello(String name) {
return "Hello, " + name;
}
}
代码如下:
@RestController
@RequestMapping("/user")
public class UserController {
@Value("${server.port}")
private String port;
@Autowired
private UserService userService;
private Map<String, Object> data = null;
@GetMapping("/{name}")
public Map<String, Object> hello(@PathVariable String name) {
String hello = userService.hello(name);
data = new HashMap<>(4);
data.put("port", port);
data.put("msg", hello);
return data;
}
}
启动2个user-provider服务,端口分别为8090和8091,详细步骤请参阅https://blog.csdn.net/xudc0521/article/details/88878904#31_2_181。
利用Spring Initializr快速创建一个Spring Boot项目,主要依赖如下:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
在XxxApplication主启动类上加上注解@EnableFeignClients
,同时也要加上服务发现的注解@EnableDiscoveryClient
,完整代码如下:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients // 启用Feign功能
public class UserConsumerFeignApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerFeignApplication.class, args);
}
}
新建一个接口UserService
,修改代码如下:
@FeignClient("user-provider")
public interface UserService {
/**
* hello,${name}
* @param name
* @return
*/
@GetMapping("/user/{name}")
Map<String, Object> hello(@PathVariable String name);
}
- 首先这是一个接口,Feign会通过动态代理,帮我们生成实现类
- @FeignClient()声明这是一个Feign客户端,value值指定服务提供者名称,即调用哪个服务
- 接口中的定义方法,完全采用SpringMVC的注解,Feign会根据注解帮我们生成URL,并访问获取结果
添加一个Junit方法测试,代码如下:
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserConsumerFeignApplicationTests {
@Autowired
private UserService userService;
@Test
public void contextLoads() {
for (int i = 0; i < 10; i++) {
Map<String, Object> map = userService.hello("Cindy" + i);
System.err.println(map);
}
}
}
Feign中本身已经集成了Ribbon依赖和自动配置,默认实现了负载均衡。
因此我们不需要额外引入依赖,也不需要再注册RestTemplate
对象。