一、关于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的更多相关文章

  1. SpringCloud学习之Feign 的使用(五)

     Feign 是一个声明式的伪RPC的REST客户端,它用了基于接口的注解方式,很方便的客户端配置,刚开始使用时还不习惯,感觉是在客户端写服务端的代码,Spring Cloud 给 Feign 添加了 ...

  2. SpringCloud学习(5)——Feign负载均衡

    Feign概述 Feign是声明式的Web服务客户端, 使得编写Web服务客户端变的非常容易, 只需要创建一个接口, 然后在上面添加注解即可. Feign旨在使编写Java Http客户端变的更容易. ...

  3. SpringCloud学习之Ribbon

    一.负载均衡与Ribbon 负载均衡,在集群中是很常见的一个“名词”,顾名思义是根据一定的算法将请求分摊至对应的服务节点上,常见的算法有如下几种: 轮询法:所有请求被依次分发到每台应用服务器上,每台服 ...

  4. SpringCloud学习笔记(3):使用Feign实现声明式服务调用

    简介 Feign是一个声明式的Web Service客户端,它简化了Web服务客户端的编写操作,相对于Ribbon+RestTemplate的方式,开发者只需通过简单的接口和注解来调用HTTP API ...

  5. SpringCloud学习笔记(9)----Spring Cloud Netflix之声明式 REST客户端 -Feign的使用

    1. 什么是Feign? Feign是一种声明式.模板化的HTTP客户端,在SpringCloud中使用Feign.可以做到使用HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完全感知不到 ...

  6. SpringCloud学习笔记(六):Feign+Ribbon负载均衡

    简介 官网解释: http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign Feign是一个声明式WebS ...

  7. SpringCloud学习系列之三----- 断路器(Hystrix)和断路器监控(Dashboard)

    前言 本篇主要介绍的是SpringCloud中的断路器(Hystrix)和断路器指标看板(Dashboard)的相关使用知识. SpringCloud Hystrix Hystrix 介绍 Netfl ...

  8. java框架之SpringCloud(4)-Ribbon&Feign负载均衡

    在上一章节已经学习了 Eureka 的使用,SpringCloud 也提供了基于 Eureka 负载均衡的两种方案:Ribbon 和 Feign. Ribbon负载均衡 介绍 SpringCloud ...

  9. SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理

    前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由 ...

随机推荐

  1. Connect Appium Server Fail.A new session could not be created

    1.由于安卓测试机性能低下,并不能支持测试工作,想安装一个模拟器帮助测试,然后发现群里有朋友发了一个夜神模拟器..下载..安装..美滋滋的准备运行脚本.What..居然报错了..orz..然后百度查找 ...

  2. Linq 透明标识符

    IEnumerable<Person> list = new List<Person> { , Id = }, , Id = }, , Id = }, , Id = }, , ...

  3. 自动化服务部署(二):Linux下安装jenkins

    jenkins是一个Java开发的开源持续集成工具,广泛用于项目开发,具有自动化构建.测试和部署等功能,它的运行需要Java环境. 上篇博客介绍了Linux下安装JDK的步骤,这篇博客,介绍下Linu ...

  4. ### Cause: org.apache.ibatis.binding.BindingException: Parameter 'name' not found. Available parameters are [arg1, arg0, param1, param2]

    org.apache.ibatis.exceptions.PersistenceException: ### Error updating database. Cause: org.apache.ib ...

  5. redis入门(04)redis的数据类型

    Redis 数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). 1.String(字符串) ...

  6. 使用新一代js模板引擎NornJ提升React.js开发体验

    当前的前端世界中有很多著名的开源javascript模板引擎如Handlebars.Nunjucks.EJS等等,相信很多人对它们都并不陌生. js模板引擎的现状 通常来讲,这些js模板引擎项目都有一 ...

  7. DIY一个超简单的画图程序

    编译环境:VS2017+Easy_X 最近笔者一直在翻阅Easy_X的帮助手册,学习到了一些关于获取鼠标状态消息函数的知识,感觉收获颇大,于是想试验一番,将所学知识运用出来.先补充一下在Easy_X中 ...

  8. [论文阅读] Deep Residual Learning for Image Recognition(ResNet)

    ResNet网络,本文获得2016 CVPR best paper,获得了ILSVRC2015的分类任务第一名. 本篇文章解决了深度神经网络中产生的退化问题(degradation problem). ...

  9. flask 操作mysql的两种方式-sqlalchemy操作

    flask 操作mysql的两种方式-sqlalchemy操作 二.ORM sqlalchemy操作 #coding=utf-8 # model.py from app import db class ...

  10. C# 打开文件夹和保存文件夹

    OpenFileDialog sfd = new OpenFileDialog(); sfd.ShowDialog(); this.textBox1.Text = sfd.FileName; Save ...