赞
踩
openFeign是一种声明式、模板化的HTTP客户端。在SpringCloud中使用openFeign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问HTTP请求。
其用法就是编写一个接口,在接口上添加注解,如此就能轻而易举的调用远程服务
有如此强大的东西,我们肯定不能放过使用的机会,就像有时你有特殊的要求必须拉别的女孩的手,而此时有个中间人能帮你实现这个愿望,你拉别的女孩子的手就像拉自己女朋友的手一样方便
openFeign在微服务中的作用就像中间方一样,当你需要调用另一个微服务的接口时,使用openFeign就像调用本服务的接口一样丝滑
既然是远程调用,那肯定至少得有2个微服务,consumer and provider。下面我们在consumer中记录以下使用步骤
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> <version>2.2.1.RELEASE</version> </dependency> <!-- 对JAXRS支持 --> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-jaxrs</artifactId> <version>10.0.0</version> </dependency> <!-- 调用soap webservice支持 --> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-soap</artifactId> <version>10.2.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency>
在启动类上添加@EnableFeignClients注解
@SpringBootApplication
@EnableFeignClients
public class OpenFeignServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OpenFeignServiceApplication.class, args);
}
}
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(FeignClientsRegistrar.class) public @interface EnableFeignClients { String[] value() default {}; String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; Class<?>[] defaultConfiguration() default {}; Class<?>[] clients() default {}; }
注解@EnableFeignClients告诉框架扫描所有使用注解@FeignClient定义的Feign客户端。它又通过注解@Import导入了类FeignClientRegistrar(feign客户端注册器)
分别写三个接口:GET请求、POST请求、SOAP请求
@FeignClient(name = "dynamicFeignClient", configuration = FeignClientsConfiguration.class) public interface DynamicFeignClient { // 发送GET请求 @RequestLine("GET") @GetMapping("/product/{id}") String getProductById(@PathVariable("id") Long id); // 发送POST请求 @RequestLine("POST") @Headers(value = "Content-Type: application/json;charset=UTF-8") String requestPOST(URI baseUri, @RequestBody JSONObject args); // 发送webservice-SOAP请求 @RequestLine("POST") @Headers(value = "Content-Type: text/xml;charset=UTF-8") String requestSOAP(URI baseUri, @RequestBody String params); }
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FeignClient { @AliasFor("name") String value() default ""; String serviceId() default ""; String contextId() default ""; String name() default ""; String qualifier() default ""; String url() default ""; boolean decode404() default false; Class<?>[] configuration() default {}; Class<?> fallback() default void.class; Class<?> fallbackFactory() default void.class; String path() default ""; boolean primary() default true;
@FeignClient注解解析
- name: 是一个任意得客户端名称,用于创SpringCloud LoadBalancer 客户端
- url: url一般用于调试,可以手动指定@FeignClient调用的地址
- configuration: Feign配置类,可自定义Feign的Encode,Decode,LogLevel,Contract
- fallback: 定义容错的类,当远程调用的接口失败或者超时的时候,会调用对应接口的容错逻辑,fallback执行的类必须实现@FeignClient标记的接口
- fallbackFactory: 工厂类,用于生成fallback类实例,通过此属性可以实现每个接口通用的容错逻辑,以达到减少重复的代码
- path: 定义当前FeignClient的统一前缀
public interface RequestClient {
String sendPost(String url, JSONObject request);
}
@Service @Slf4j @Import(FeignClientsConfiguration.class) public class RequestClientImpl implements RequestClient { private DynamicFeignClient client; @Autowired public RequestClientImpl(Decoder decoder, Encoder encoder) { client = Feign.builder() .decoder(decoder) .encoder(encoder) .options(new Request.Options(1000, 1000)) .target(Target.EmptyTarget.create(DynamicFeignClient.class)); } @Override public String sendPost(String url, JSONObject request) { log.info("url:{},入参:{}", url, request); String response; try { response = client.requestPOST(new URI(url), request); } catch (FeignException feignException) { throw new BusinessException("调用接口异常!地址:" + url); } catch (URISyntaxException uriSyntaxException) { throw new BusinessException("调用地址异常!地址:" + url); } log.info("url:{},出参:{}", url, response); return response; } }
@SneakyThrows
@PostMapping("/getOtherServiceData")
public JSONObject getOtherServiceData(@RequestBody JSONObject jsonObject) {
String responseString = client.sendPost("http://localhost:9907/remindMedication/getRemindMedication", jsonObject);
return JSONObject.parseObject(responseString);
}
可以看到调用了远程服务的接口
openFeign提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解openFeign中Http请求的细节。通过设置日志,可以对Feign接口的调用情况进行监控和输出
openFeign的日志级别主要有以下几种
使用方式
@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel() {
// 开启详细日志
return Logger.Level.FULL;
}
}
设置什么级别,根据情况而定
@Autowired
public RequestClientImpl(Decoder decoder, Encoder encoder) {
client = Feign.builder()
.decoder(decoder)
.encoder(encoder)
.options(new Request.Options(5000, 5000))
.logLevel(Logger.Level.FULL)
.target(Target.EmptyTarget.create(DynamicFeignClient.class));
}
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
在@FeignClient注解中,当设定了客户端名称后,便默认使用了Spring Cloud LoadBalancer进行负载均衡访问,在老版本中,集成的是Ribbon,它默认的响应时间是1s,可以通过ribbon.ReadTimeout和ribbon.ConnectTimeout来设置客户端超时时间
在新版本中,我们可以在options设置,例如,我们设置为1s
@Autowired
public RequestClientImpl(Decoder decoder, Encoder encoder) {
client = Feign.builder()
.decoder(decoder)
.encoder(encoder)
.options(new Request.Options(1000, 1000))
.logLevel(Logger.Level.FULL)
.target(Target.EmptyTarget.create(DynamicFeignClient.class));
}
并且在服务提供方延迟3s
然后再进行测试
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。