在SpringCloud系列之Ribbon 一文中我们介绍了使用RestTemplate配合Ribbon实现服务的调用和客户端负载均衡。但是使用RestTemplate调用服务有个弊端,就是参数传递不方便,无论是GET还是POST,都需要对参数进行组装,一旦参数比较多,实际开发时将非常麻烦,而且容易出错。所以,本文将介绍另一种Spring Cloud的服务调用方式——Feign。
Feign Feign也是Netflix开发的,它是一种声明式、模版化的HTTP客户端,相对于RestTemplate更加便捷、优雅。在Spring Cloud中,我们可以使用Feign非常方便的创建服务调用的模版代码,配合相关的注解,完成配置。
实战 修改provider-user服务 增加测试接口 增加新增用户
和设置用户name
接口,其他都不需要修改
package com.huluohu.cloud.user.presentation.web;import com.huluohu.cloud.user.presentation.mode.UserDTO;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.*;import java.util.Random;@Slf4j @RestController @RequestMapping("/user") public class UserController { private Random random = new Random(); @GetMapping("/{id}") public UserDTO findById (@PathVariable Integer id) { return UserDTO.builder() .id(id) .username("root_" + id) .name("huluohu_" + id) .age(random.nextInt(30 ) % (30 - 15 + 1 ) + 15 ) .balance(random.nextLong()) .build(); } @PostMapping() public Integer add (UserDTO user) { return random.nextInt(); } @PutMapping("/{id}") public Boolean setName (@PathVariable Integer id, @RequestParam("name") String name) { log.info("id={}" , id); log.info("name={}" , name); return Boolean.TRUE; } }
创建Feign测试工程 consuer-movie-feign 复制consuer-movie module
,修改名称为consuer-movie-feign
新增依赖 在pom.xml下增加Feign的依赖
<dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-feign</artifactId > </dependency >
修改启动类 package com.huluohu.cloud.movie;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;@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients(basePackages = "com.huluohu.cloud.movie.application.client") public class MovieApplication { public static void main (String[] args) { SpringApplication.run(MovieApplication.class,args); } }
增加服务调用代码 package com.huluohu.cloud.movie.application.client;import com.huluohu.cloud.movie.application.model.User;import org.springframework.cloud.netflix.feign.FeignClient;import org.springframework.web.bind.annotation.*;@FeignClient(serviceId = "provider-user") public interface UserServiceClient { @RequestMapping(value = "/user/{id}", method = RequestMethod.GET) User findById (@PathVariable("id") Integer id) ; @RequestMapping(value = "/user", method = RequestMethod.POST) Integer addUser (@RequestBody User user) ; @RequestMapping(value = "/user/{id}", method = RequestMethod.PUT) Boolean setName (@PathVariable("id") Integer id, @RequestParam("name") String name) ; }
增加测试代码 package com.huluohu.cloud.movie.presentation.web;import com.huluohu.cloud.movie.application.client.UserServiceClient;import com.huluohu.cloud.movie.application.model.User;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;@RestController @RequestMapping("/test") public class TestController { @Resource private UserServiceClient userServiceClient; @GetMapping("/user/{id}") public Object testFindUser (@PathVariable Integer id) { final User user = userServiceClient.findById(id); return ResponseEntity.ok(user); } @PostMapping("/user") public Object testAddUser (User user) { return ResponseEntity.ok(userServiceClient.addUser(user)); } @PutMapping("/user/{id}") public Object testSetName (@PathVariable Integer id, @RequestParam("name") String name) { return ResponseEntity.ok(userServiceClient.setName(id, name)); } }
配置 配置文件和consumer-movie中的一样。
到此,准备工作都已经完成了,下面开始测试。
测试 启动Eureka Server(local profile) 启动Config Server(不需要区分profile) 启动provider-user(local profile) 启动provider-user(local2 profile,模拟多节点) 启动consumer-movie-feign(local profile) 启动应用列表
服务注册情况
测试结果(使用Postman测试)
以上三个测试,分别测试三种参数传递的情况:
查询用户,测试通过GET
方式,使用@PathVariable
注解从请求URL中获取参数 新增用户,测试通过POST
方式,使用@RequestBody
注解传递多个参数的情况 设置用户name,测试通过PUT
方式,使用@RequestParam
传递单个参数的情况 进阶 在Spring Cloud中,支持对Feign进行自定义配置,包括编码器、解码器、契约、拦截器等进行自定义:
Decoder Encoder Logger Contract Feign.Builder Client 还有一些Bean在Spring Cloud中没有提供默认的实现,但是如果在应用上下文中存在这些实现,也会被Feign应用:
Logger.Level Retryer ErrorDecoder Request.Options Collection SetterFactory 如果需要自定义以上Bean,可以创建一个Configuration类,然后设置到FeignClient即可:
配置类
@Configuration public class UserServiceConfiguration { @Bean public Contract feignContract () { return new feign.Contract.Default(); } @Bean public BasicAuthRequestInterceptor basicAuthRequestInterceptor () { return new BasicAuthRequestInterceptor("user" , "password" ); } }
使用配置
@FeignClient(name = "provider-user", configuration = UserServiceConfiguration.class) public interface UserServiceClient { }
“扫一扫接着看”
为正常使用评论功能,请开启浏览器的JavaScript