OpenFeign簡單介紹和基本使用
簡介
Feign是一個聲明式WebService客戶端,使用Feign能讓編寫Web Service客戶端更簡單
它的使用方法是定義一個服務接口然后在上面添加注解,Feign也支持可拔插式的編碼器和解碼器。Spring Cloud對Feign進行了封裝,使其支持了Spring MVC標准注解和HttpMessageConverters。Feign可以與Eureka和Ribbon組合使用以支持負載均衡
Feign能干什么
Feign旨在使編寫Java Http客戶端變得更容易
前面在使用Ribbon+RestTemplate時,利用RestTemplate對http請求的封裝處理,形成了一套模板化的調用方法。但是在實際開發中,由於對服務依賴的調用可能不止一處,往往一個接口會被多處調用,所以通常都會針對每個微服務自行封裝一些客戶端類來包裝這些依賴服務的調用。所以,Feign在此基礎上做了進一步封裝,由它來幫助我們定義和實現依賴服務接口的定義。在Feign的實現下,我們只需要創建一個接口並使用注解的方式來配置它(以前是Dao接口上面標注Mapper注解,現在是一個微服務接口上面標注一個Feign即可),即可完成對服務提供方的接口綁定,簡化了使用Spring Cloud Ribbon時,自動封裝服務調用客戶端的開發量
Feign集成了Ribbon,通過feign只需要定義服務綁定接口並且以聲明式的方法,優雅而簡單的實現了服務調用
Feign和OpenFeign的區別
Feign是Spring Cloud組件中的一個輕量級RESTful的HTTP服務客戶端,Feign內置了Ribbon,用來做客戶端負載均衡,去調用服務注冊中心的服務。Feign的使用方式是:使用Feign的注解定義接口,調用這個接口,就可以調用服務注冊中心的服務
OpenFeign是Spring Cloud在Feign的基礎上支持了SpringMVC的注解,如@RequestMaping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMaping注解下的接口,並通過動態代理的方式產生實現類,實現類中做負載均衡並調用其他服務
基本使用
引入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
編寫service接口調用遠程服務,添加@FeignClient注解(value:調用的服務名)
package com.yl.openfeign.order.service;
import com.yl.common.entity.CommonResult;
import com.yl.common.entity.Payment;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* 支付
*
* @auther Y-wee
*/
@Component
@FeignClient(value = "PAYMENT")
public interface PaymentFeignService {
/**
* 根據id查詢數據
*
* @param id
* @return
*/
@GetMapping(value = "/payment/get/{id}")
CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
}
編寫controller
package com.yl.openfeign.order.controller;
import com.yl.common.entity.CommonResult;
import com.yl.common.entity.Payment;
import com.yl.openfeign.order.service.PaymentFeignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 支付
*
* @auther Y-wee
*/
@RequestMapping("/order")
@RestController
@Slf4j
public class OrderFeignController {
@Resource
private PaymentFeignService paymentFeignService;
/**
* 根據id查詢數據
*
* @param id id
* @return 查詢結果
*/
@GetMapping(value = "/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
return paymentFeignService.getPaymentById(id);
}
}
feign相關配置
ribbon:
# 默認feign客戶端只等待1s,但是服務端處理需要超過1s,導致feign客戶端不想等待了,直接返回報錯
# 為了避免這樣的情況,我們需要設置feign客戶端超時時間
# 設置建立連接后調用服務超時時間
ReadTimeout: 5000
# 設置連接超時時間
ConnectTimeout: 5000
主啟動類添加@EnableFeignClients
package com.yl.openfeign.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OpenFeignOrder80Application {
public static void main(String[] args) {
SpringApplication.run(OpenFeignOrder80Application.class,args);
}
}
被調用的服務controller
package com.yl.payment.controller;
import com.yl.common.entity.CommonResult;
import com.yl.common.entity.Payment;
import com.yl.payment.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* 支付
*
* @auther Y-wee
*/
@RestController
@Slf4j
@RequestMapping("/payment")
public class PaymentController {
@Resource
private PaymentService paymentService;
@Value("${server.port}")
private String serverPort;
/**
* 查詢數據
*
* @param id id
* @return 查詢結果
*/
@GetMapping(value = "/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
Payment payment = paymentService.getPaymentById(id);
if (payment != null) {
return new CommonResult(200, "查詢成功:" + serverPort, payment);
}
return new CommonResult(444, "沒有對應記錄,查詢ID: " + id, null);
}
}
OpenFeign日志
feign提供了日志打印功能,我們可以通過配置來調整日志級別,從而了解Feign中http請求的細節,說白了就是對feign接口的調用情況進行監控和輸出
新建feign配置類
package com.yl.openfeign.order.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* feign配置類
*
* @auther Y-wee
*/
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel() {
/**
* NONE:默認的,不顯示任何日志
* BASIC:僅記錄請求方法、URL、響應狀態碼及執行時間
* HEADERS:除了BASIC中定義的信息外,還有請求和響應頭的信息
* FULL:除了HEADERS中定義的信息外,還有請求和響應的正文及元數據
*/
return Logger.Level.FULL;
}
}
修改配置文件
logging:
level:
# feign日志以什么級別監控哪個接口(注意接口名和包名不要寫錯)
com.yl.openfeign.order.service.PaymentFeignService: debug
通過feign調用服務,控制台顯示日志,eg: