SpringCloud学习之feign
一、关于feigin
feigin是一种模板化,声明式的http客户端,feign可以通过注解绑定到接口上来简化Http请求访问。当然我们也可以在创建Feign对象时定制自定义解码器(xml或者json等格式解析)和错误处理。
二、添加SpringCloud对feign的支持
gradle配置:
compile('org.springframework.cloud:spring-cloud-starter-feign')
feigin最基本使用方法:
interface GitHub {
@RequestLine("GET /repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);
}
static class Contributor {
String login;
int contributions;
}
public static void main(String... args) {
GitHub github = Feign.builder()
.decoder(new GsonDecoder())
.target(GitHub.class, "https://api.github.com");
// Fetch and print a list of the contributors to this library.
List<Contributor> contributors = github.contributors("OpenFeign", "feign");
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
}
feign发送json与xml的格式的http请求:
interface LoginClient {
@RequestLine("POST /")
@Headers("Content-Type: application/xml")
@Body("<login \"user_name\"=\"{user_name}\" \"password\"=\"{password}\"/>")
void xml(@Param("user_name") String user, @Param("password") String password);
@RequestLine("POST /")
@Headers("Content-Type: application/json")
// json curly braces must be escaped!
@Body("%7B\"user_name\": \"{user_name}\", \"password\": \"{password}\"%7D")
void json(@Param("user_name") String user, @Param("password") String password);
}
注意示例中需要添加对gson的支持
feign发送https信任所有证书的代码:
final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] chain,
String authType) {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] chain,
String authType) {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
}};
final SSLContext sslContext = SSLContext.getInstance("TLSv1");
sslContext.init(null, trustAllCerts,
new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext
.getSocketFactory();
Feign.builder().client(new Client.Default(sslSocketFactory, (s, sslSession) -> true));
三、在SpringCloud中使用Feign
比如说注册中心有如下服务:

1)application.yml的配置:
spring:
application:
name: demo-consumer
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka,http://localhost:8081/eureka
server:
port: 8090
2)创建接口
package com.bdqn.lyrk.consumer.demo.api; import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping; @FeignClient("demo")
public interface DemoConfigService { @RequestMapping("/demo.do")
String demoService();
}
注意在接口上加上注解:@FeignClient("demo") 注解里的参数是在eureka注册的服务名
3)编写启动类:
package com.bdqn.lyrk.consumer.demo; import com.bdqn.lyrk.consumer.demo.api.DemoConfigService;
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;
import org.springframework.context.ConfigurableApplicationContext; @EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class DemoConsumerProvider { public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoConsumerProvider.class, args);
DemoConfigService demoConfigService = applicationContext.getBean(DemoConfigService.class);
System.out.println(demoConfigService.demoService());
}
}
注意在启动类上加上@EnableFeignClients来开启Feign功能
运行后输出:

此时我们可以发现使用feign客户端我们访问服务的代码简洁了好多
4) feign多参数设置方法
service-api模块的接口定义:
public interface IBillService {
@PostMapping("/queryBill")
List<BillDTO> queryOrders(@RequestBody BillsVO billsVO);
}
相关服务实现类:
@RestController
public class BillServiceImpl implements IBillService {
@Autowired
private BillMapper billMapper;
@PostMapping("/queryBill")
@Override
public List<BillDTO> queryOrders(@RequestBody BillsVO billsVO) {
return billMapper.query(BeanMap.create(billsVO));
}
}
注意 需要在接口定义与实现类的参数上加@RequestBody注解
四、feign中的使用Hystrix
1) 在@FeignClient中有两个属性我们值得关注一下,它们分别是fallBack和fallBackFactory,当然我们系统里要添加Hystrix支持并且在属性文件里设置:
feign.hystrix.enabled=true
同样我们要在启动类里加上@EnableCircuitBreaker注解打开Hystrix保护
2) fallBack属性很简单,用来设置降级方法,当feign请求服务失败时所调用的方法, 这里我给出接口的例子:
首先定义一个接口:IOrderService
package com.bdqn.lyrk.service.api; import com.bdqn.lyrk.service.dto.OrderDTO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; public interface IOrderService { @GetMapping("/orderId/{orderId}")
OrderDTO getOrderById(@PathVariable("orderId") Integer orderId); @GetMapping("/errorOrder")
OrderDTO getErrorOrder();
}
其次定义Feign的接口OrderServiceClient继承IOrderService
package com.bdqn.lyrk.order.service.consumer.feign; import com.bdqn.lyrk.service.api.IOrderService;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Primary; @Primary
@FeignClient(value = "ORDER-SERVER", fallBack="FailedOrderServiceClientImpl.class")
public interface OrderServiceClient extends IOrderService { }
由于IOrderService不在同一个项目里,而且SpringCloud不推荐服务端和客户端使用同一个接口,所以我采用继承的方式,注意加上@Primary注解以免使用@Autowired时注入失败
在定义实现类:
package com.bdqn.lyrk.order.service.consumer.feign; import com.bdqn.lyrk.service.dto.OrderDTO;
import org.springframework.stereotype.Component; @Component
public class FailedOrderServiceClientImpl implements OrderServiceClient {
@Override
public OrderDTO getOrderById(Integer orderId) {
OrderDTO orderDTO = new OrderDTO();
orderDTO.setId(orderId);
orderDTO.setOrderName("服务中失败的订单,id为:" + orderId);
return null;
} @Override
public OrderDTO getErrorOrder() {
OrderDTO orderDTO = new OrderDTO();
orderDTO.setOrderName("服务中失败的订单");
orderDTO.setId(-1);
return orderDTO;
}
}
最后@FeignClient中设置属性fallBack="FailedOrderServiceClientImpl.class" 就可以了
3) 当我们需要封装服务端的异常信息时,可以指定fallbackFactory属性,请看下面的例子:
package com.bdqn.lyrk.order.service.consumer.feign; import com.bdqn.lyrk.service.dto.OrderDTO;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component; @Component
public class OrderServiceFallbackFactoryImpl implements FallbackFactory<OrderServiceClient> {
@Override
public OrderServiceClient create(Throwable cause) {
return new OrderServiceClient() {
@Override
public OrderDTO getOrderById(Integer orderId) {
OrderDTO orderDTO = new OrderDTO();
orderDTO.setOrderName(cause.getMessage());
return orderDTO;
} @Override
public OrderDTO getErrorOrder() {
OrderDTO orderDTO = new OrderDTO();
orderDTO.setOrderName(cause.getMessage());
return orderDTO;
}
};
}
}
注意:FallbackFactory的泛型参数一定要指定为@FeignClient修饰的接口,同时不建议fallback与fallbackFactory同时使用
最后 我贴一下服务端的实现代码:
package com.bdqn.lyrk.springcloud.order.service; import com.bdqn.lyrk.service.api.IOrderService;
import com.bdqn.lyrk.service.dto.OrderDTO;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.TimeUnit; @RestController
public class OrderServiceImpl implements IOrderService { @HystrixCommand(fallbackMethod = "errorDTO",
commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")} )
@GetMapping("/orderId/{orderId}")
@Override
public OrderDTO getOrderById(@PathVariable("orderId") Integer orderId) {
OrderDTO orderDTO = new OrderDTO();
orderDTO.setId(orderId);
orderDTO.setOrderName("订单ID为" + orderId + "的订单");
try {
TimeUnit.SECONDS.sleep(orderId);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} return orderDTO;
} @Override
public OrderDTO getErrorOrder() {
System.out.println(1 / 0);
return null;
} public OrderDTO errorDTO(Integer orderId) {
OrderDTO orderDTO = new OrderDTO();
orderDTO.setId(-1);
orderDTO.setOrderName("错误的订单,请重试");
return orderDTO;
}
}
对于Hystrix可以参考:SpringCloud学习之Hystrix
SpringCloud学习之feign的更多相关文章
- SpringCloud学习之Feign 的使用(五)
Feign 是一个声明式的伪RPC的REST客户端,它用了基于接口的注解方式,很方便的客户端配置,刚开始使用时还不习惯,感觉是在客户端写服务端的代码,Spring Cloud 给 Feign 添加了 ...
- SpringCloud学习(5)——Feign负载均衡
Feign概述 Feign是声明式的Web服务客户端, 使得编写Web服务客户端变的非常容易, 只需要创建一个接口, 然后在上面添加注解即可. Feign旨在使编写Java Http客户端变的更容易. ...
- SpringCloud学习之Ribbon
一.负载均衡与Ribbon 负载均衡,在集群中是很常见的一个“名词”,顾名思义是根据一定的算法将请求分摊至对应的服务节点上,常见的算法有如下几种: 轮询法:所有请求被依次分发到每台应用服务器上,每台服 ...
- SpringCloud学习笔记(3):使用Feign实现声明式服务调用
简介 Feign是一个声明式的Web Service客户端,它简化了Web服务客户端的编写操作,相对于Ribbon+RestTemplate的方式,开发者只需通过简单的接口和注解来调用HTTP API ...
- SpringCloud学习笔记(9)----Spring Cloud Netflix之声明式 REST客户端 -Feign的使用
1. 什么是Feign? Feign是一种声明式.模板化的HTTP客户端,在SpringCloud中使用Feign.可以做到使用HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完全感知不到 ...
- SpringCloud学习笔记(六):Feign+Ribbon负载均衡
简介 官网解释: http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign Feign是一个声明式WebS ...
- SpringCloud学习系列之三----- 断路器(Hystrix)和断路器监控(Dashboard)
前言 本篇主要介绍的是SpringCloud中的断路器(Hystrix)和断路器指标看板(Dashboard)的相关使用知识. SpringCloud Hystrix Hystrix 介绍 Netfl ...
- java框架之SpringCloud(4)-Ribbon&Feign负载均衡
在上一章节已经学习了 Eureka 的使用,SpringCloud 也提供了基于 Eureka 负载均衡的两种方案:Ribbon 和 Feign. Ribbon负载均衡 介绍 SpringCloud ...
- SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理
前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由 ...
随机推荐
- 2017 清北济南考前刷题Day 4 afternoon
期望得分:30+50+30=110 实际得分:40+0+0=40 并查集合并再次写炸... 模拟更相减损术的过程 更相减损术,差一定比被减数小,当被减数=减数时,停止 对于同一个减数来说,会被减 第1 ...
- nyoj 公约数和公倍数
公约数和公倍数 时间限制:1000 ms | 内存限制:65535 KB 难度:1 描述 小明被一个问题给难住了,现在需要你帮帮忙.问题是:给出两个正整数,求出它们的最大公约数和最小公倍数. ...
- Java8-如何构建一个Stream
Stream的创建方式有很多种,除了最常见的集合创建,还有其他几种方式. List转Stream List继承自Collection接口,而Collection提供了stream()方法. List& ...
- HTML事件处理程序
事件处理程序中的代码执行时,有权访问全局作用域中任何代码. //为按钮btn_event添加了两个个事件处理程序,而且该事件会在冒泡阶段触发(最后一个参数是false). var btn_event ...
- SSO的全方位解决方案 - Kerberos协议(RFC 1510)
一.桌面SSO和WEB-SSO的局限性 前面我们的解决方案(桌面SSO和WEB-SSO)都有一个共性:要想将一个应用集成到我们的SSO解决方案中,或多或少的需要修改应用程序. Web应用需要配置一个我 ...
- 新概念英语(1-17)How do you do ?
Is there a problem wtih the Customers officer? What are Michael Baker and Jeremy Short's jobs? A:Com ...
- zabbix配置微信报警
首先我们先目睹下微信报警的效果 接下来我们正式开始操作. 一:注册企业微信. 打开企业微信注册:http://work.weixin.qq.com 根据以上提示填入相应的内容,然后注册即可. 二:登录 ...
- 前端开发必备之Chrome开发者工具(一)
本文介绍的 Chrome 开发者工具基于 Chrome 65版本,如果你的 Chrome 开发者工具没有下文提到的那些内容,请检查下 Chrome 的版本 简介 Chrome 开发者工具是一套内置于 ...
- 高级控件之Scrollview ( 滑动屏幕 ) 与 Imageview (滑动屏幕 切换图片)
ScrollView 的xml布局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayo ...
- 工作笔记 | Visual Studio 调用 Web Service
引言 最近笔者负责ERP财务系统跟中粮集团财务公司的财务系统做对接,鉴于ERP系统中应付结算单结算量比较大,而且管理相对集中,ERP系统与中粮财务公司的支付平台系统对接,实现银企直联,将网银录入的环节 ...