一、使用Feign
Feign 提供声明式REST调用。一开始我们还在懊恼,dubbo都已经提供了配置式的服务调用了,为什么SpringCloud没有相应的解决方案?有SpringCloud提供了Feign声明式事务,使用Feign有个非常大的好处就是,只要你属性SpringMVC的annotation配置,Feign就没有什么学习成本。
事不宜迟,我们首先将Feign整合到我们的微服务当中:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
之前的笔记中,用户服务系统提供了二个接口,第一个接口是查询用户、第二个是添加用户。以下我们就在商品服务中通过Feign整合两个API
首先我们需要在配置类当中打上@EnableFeignClients
@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class ProductsystemApplication {
然后我们创建一个UserFeignClient接口:
@FeignClient(name = "tony-mall-provider-user") public interface UserFeignClient { @GetMapping("/user/getUserById/{id}") User getUserById(@PathVariable("id") int id); @PutMapping("/user/add") User addUser(@RequestParam("username") String username, @RequestParam("password")String password,@RequestParam("balance") long balance); }
接口上面使用了@FeignClient annotation 标记目标的微服务,然后创建相关的方法声明。
或许你已经注意到,所有的操作跟我们SpringMVC中的annotation一模一样。不过需要注意的是,方法的参数默认是使用@RequestBody进行交换的,所以如果我们希望使用普通的参数传参,还需要打上SpringMVC的@RequestParam annotation。
之后在我们调用的service层或者是controller层 直接注入UserFeignClient。由于演示我就不划分业务层和服务层了。
@RestController public class ProductController { @Autowired private ProductRepository productRepository; @Autowired private UserFeignClient userFeignClient; @GetMapping("/getProductByFeign/{productId}/userId/{userId}") public Map<String, Object> getProductByFeign(@PathVariable int productId, @PathVariable int userId) { Map<String, Object> map = new HashMap<>(); User user = this.userFeignClient.getUserById(userId); Product product = this.productRepository.getByProductId(productId); map.put("user", user); map.put("product", product); return map; } }
事实上Feign提供了自己的annotation配置,但是如果习惯使用SpringMVC的你,一定会和笔者一样选择如上的配置。
二、Feign压缩
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2024
mime-types 指定压缩的类型,min-reqest-size指定压缩的阈值。
三、Feign日志
在配置类中配置Feign的日志级别:
@Bean public Logger.Level feignLoggerLevel(){ return Logger.Level.FULL; }
使用application.properties指定某个接口的日志级别:
logging.level.com.tony.mall.rest.UserFeignClient=DEBUG
输出的Feign请求日志如下:
2017-07-14 15:58:34.044 DEBUG 12184 --- [nio-8802-exec-4] com.tony.mall.rest.UserFeignClient : [UserFeignClient#getUserById] ---> GET http://tony-mall-provider-user/user/getUserById/1 HTTP/1.1
2017-07-14 15:58:34.047 DEBUG 12184 --- [nio-8802-exec-4] com.tony.mall.rest.UserFeignClient : [UserFeignClient#getUserById] ---> END HTTP (0-byte body)
2017-07-14 15:58:34.173 DEBUG 12184 --- [nio-8802-exec-4] com.tony.mall.rest.UserFeignClient : [UserFeignClient#getUserById] <--- HTTP/1.1 200 (125ms)
2017-07-14 15:58:34.174 DEBUG 12184 --- [nio-8802-exec-4] com.tony.mall.rest.UserFeignClient : [UserFeignClient#getUserById] content-type: application/json;charset=UTF-8
2017-07-14 15:58:34.174 DEBUG 12184 --- [nio-8802-exec-4] com.tony.mall.rest.UserFeignClient : [UserFeignClient#getUserById] date: Fri, 14 Jul 2017 07:58:34 GMT
2017-07-14 15:58:34.174 DEBUG 12184 --- [nio-8802-exec-4] com.tony.mall.rest.UserFeignClient : [UserFeignClient#getUserById] transfer-encoding: chunked
2017-07-14 15:58:34.174 DEBUG 12184 --- [nio-8802-exec-4] com.tony.mall.rest.UserFeignClient : [UserFeignClient#getUserById] x-application-context: tony-mall-provider-user:8803
2017-07-14 15:58:34.174 DEBUG 12184 --- [nio-8802-exec-4] com.tony.mall.rest.UserFeignClient : [UserFeignClient#getUserById]
2017-07-14 15:58:34.176 DEBUG 12184 --- [nio-8802-exec-4] com.tony.mall.rest.UserFeignClient : [UserFeignClient#getUserById] {"userId":1,"username":"TONY","userpwd":"TONYPWD","balance":1000000}
2017-07-14 15:58:34.176 DEBUG 12184 --- [nio-8802-exec-4] com.tony.mall.rest.UserFeignClient : [UserFeignClient#getUserById] <--- END HTTP (68-byte body)