feign常见问题总结 feignclient接口如使用@pathvariable ,必须指定value属性
//在一些早期版本中, @pathvariable(id) 中的 id ,也就是value属性,必须指定,不能省略。@feignclient(microservice-provider-user)public interface userfeignclient { @requestmapping(value = /simple/{id}, method = requestmethod.get) public user findbyid(@pathvariable(id) long id); ...} java代码自定义feign client的注意点与坑
@feignclient(name = microservice-provider-user, configuration = userfeignconfig.class)public interface userfeignclient { @getmapping(/users/{id}) user findbyid(@pathvariable(id) long id);}/** * 该feign client的配置类,注意: * 1. 该类可以独立出去; * 2. 该类上也可添加@configuration声明是一个配置类; * 配置类上也可添加@configuration注解,声明这是一个配置类; * 但此时千万别将该放置在主应用程序上下文@componentscan所扫描的包中, * 否则,该配置将会被所有feign client共享,无法实现细粒度配置! * 个人建议:像我一样,不加@configuration注解 * * @author zhouli */class userfeignconfig { @bean public logger.level logger() { return logger.level.full; }} 配置类上也可添加@configuraiton 注解,声明这是一个配置类;但此时千万别将该放置在主应用程序上下文@componentscan 所扫描的包中,否则,该配置将会被所有feign client共享(相当于变成了通用配置,其实本质还是spring父子上下文扫描包重叠导致的问题),无法实现细粒度配置! 个人建议:像我一样,不加@configuration注解,省得进坑。 最佳实践:尽量用配置属性自定义feign的配置!!! @feignclient 注解属性
//@feignclient(name = microservice-provider-user)//在早期的spring cloud版本中,无需提供name属性,从brixton版开始,@feignclient必须提供name属性,否则应用将无法正常启动!//另外,name、url等属性支持占位符。例如:@feignclient(name = ${feign.name}, url = ${feign.url}) 类级别的@requestmapping会被spring mvc加载
@requestmapping(/users)@feignclient(name = microservice-user)public class testfeignclient { // ...} 类上的@requestmapping 注解也会被spring mvc加载。该问题现已经被解决,早期的版本有两种解决方案:
方案1:不在类上加@requestmapping 注解;
方案2:添加如下代码:
@configuration@conditionalonclass({ feign.class })public class feignmappingdefaultconfiguration { @bean public webmvcregistrations feignwebregistrations() { return new webmvcregistrationsadapter() { @override public requestmappinghandlermapping getrequestmappinghandlermapping() { return new feignfilterrequestmappinghandlermapping(); } }; } private static class feignfilterrequestmappinghandlermapping extends requestmappinghandlermapping { @override protected boolean ishandler(class beantype) { return super.ishandler(beantype) && !beantype.isinterface(); } }} 首次请求失败
ribbon的饥饿加载(eager-load)模式
如需产生hystrix stream监控信息,需要做一些额外操作
feign本身已经整合了hystrix,可直接使用@feignclient(value = microservice-provider-user, fallback = xxx.class) 来指定fallback类,fallback类继承@feignclient所标注的接口即可。
但是假设如需使用hystrix stream进行监控,默认情况下,访问http://ip:port/actuator/hystrix.stream 是会返回404,这是因为feign虽然整合了hystrix,但并没有整合hystrix的监控。如何添加监控支持呢?需要以下几步:
第一步:添加依赖,示例:
org.springframework.cloudspring-cloud-starter-hystrix 第二步:在启动类上添加@enablecircuitbreaker 注解,示例:
@springbootapplication@enablefeignclients@enablediscoveryclient@enablecircuitbreakerpublic class moviefeignhystrixapplication { public static void main(string[] args) { springapplication.run(moviefeignhystrixapplication.class, args); }} 第三步:在application.yml中添加如下内容,暴露hystrix.stream端点:
management: endpoints: web: exposure: include: 'hystrix.stream' 这样,访问任意feign client接口的api后,再访问http://ip:port/actuator/hystrix.stream ,就会展示一大堆hystrix监控数据了。
原文链接:http://www.itmuch.com/spring-...
feign 上传文件 加依赖
io.github.openfeign.formfeign-form3.0.3io.github.openfeign.formfeign-form-spring3.0.3 编写feign client
@feignclient(name = ms-content-sample, configuration = uploadfeignclient.multipartsupportconfig.class)public interface uploadfeignclient { @requestmapping(value = /upload, method = requestmethod.post, produces = {mediatype.application_json_utf8_value}, consumes = mediatype.multipart_form_data_value) @responsebody string handlefileupload(@requestpart(value = file) multipartfile file); class multipartsupportconfig { @bean public encoder feignformencoder() { return new springformencoder(); } }} 如代码所示,在这个feign client中,我们引用了配置类multipartsupportconfig ,在multipartsupportconfig 中,我们实例化了springformencoder 。这样这个feign client就能够上传啦。
注意点
//requestmapping注解中的produeces 、consumes 不能少;@requestmapping(value = /upload, method = requestmethod.post, produces = {mediatype.application_json_utf8_value}, consumes = mediatype.multipart_form_data_value) 接口定义中的注解@requestpart(value = file) 不能写成@requestparam(value = file) 。 最好将hystrix的超时时间设长一点,例如5秒,否则可能文件还没上传完,hystrix就超时了,从而导致客户端侧的报错。 原文链接:http://www.itmuch.com/spring-...
feign实现form表单提交 添加依赖:
io.github.openfeign.formfeign-form3.2.2io.github.openfeign.formfeign-form-spring3.2.2 feign client示例:
@feignclient(name = xxx, url = http://www.itmuch.com/, configuration = testfeignclient.formsupportconfig.class)public interface testfeignclient { @postmapping(value = /test, consumes = {mediatype.application_form_urlencoded_value}, produces = {mediatype.application_json_utf8_value} ) void post(map queryparam); class formsupportconfig { @autowired private objectfactory messageconverters; // new一个form编码器,实现支持form表单提交 @bean public encoder feignformencoder() { return new springformencoder(new springencoder(messageconverters)); } // 开启feign的日志 @bean public logger.level logger() { return logger.level.full; } }},> 调用示例:
@getmapping(/user/{id})public user findbyid(@pathvariable long id) { hashmap param = maps.newhashmap(); param.put(username,zhangsan); param.put(password,pwd); this.testfeignclient.post(param); return new user();},> 日志:
...[testfeignclient#post] ---> post http://www.baidu.com/test http/1.1...[testfeignclient#post] accept: application/json;charset=utf-8...[testfeignclient#post] content-type: application/x-www-form-urlencoded; charset=utf-8...[testfeignclient#post] content-length: 30...[testfeignclient#post] ...[testfeignclient#post] password=pwd&username=zhangsan...[testfeignclient#post] ---> end http (30-byte body) 由日志可知,此时feign已能使用form表单方式提交数据。
原文链接:http://www.itmuch.com/spring-...
feign get请求如何构造多参数 假设需请求的url包含多个参数,例如http://microservice-provider-... ,该如何使用feign构造呢?
我们知道,spring cloud为feign添加了spring mvc的注解支持,那么我们不妨按照spring mvc的写法尝试一下:
@feignclient(microservice-provider-user)public interface userfeignclient { @requestmapping(value = /get, method = requestmethod.get) public user get0(user user);} 然而,这种写法并不正确,控制台会输出类似如下的异常。
feign.feignexception: status 405 reading userfeignclient#get0(user); content:{timestamp:1482676142940,status:405,error:method not allowed,exception:org.springframework.web.httprequestmethodnotsupportedexception,message:request method 'post' not supported,path:/get} 由异常可知,尽管我们指定了get方法,feign依然会使用post方法发送请求。于是导致了异常。正确写法如下
方法一[推荐]
注意:使用该方法无法使用fegin的继承模式
@feignclient(microservice-provider-user)public interface userfeignclient { @getmapping(/get) public user get0(@springquerymap user user);} 方法二[推荐]
@feignclient(name = microservice-provider-user)public interface userfeignclient { @requestmapping(value = /get, method = requestmethod.get) public user get1(@requestparam(id) long id, @requestparam(username) string username);} 这是最为直观的方式,url有几个参数,feign接口中的方法就有几个参数。使用@requestparam注解指定请求的参数是什么。
方法三[不推荐]
多参数的url也可使用map来构建。当目标url参数非常多的时候,可使用这种方式简化feign接口的编写。
@feignclient(name = microservice-provider-user)public interface userfeignclient { @requestmapping(value = /get, method = requestmethod.get) public user get2(@requestparam map map);},> 在调用时,可使用类似以下的代码。
public user get(string username, string password) { hashmap map = maps.newhashmap(); map.put(id, 1); map.put(username, 张三); return this.userfeignclient.get2(map);},> 注意:这种方式不建议使用。主要是因为可读性不好,而且如果参数为空的时候会有一些问题,例如map.put(username, null); 会导致服务调用方(消费者服务)接收到的username是 ,而不是null。
原文链接:http://www.itmuch.com/spring-...
切换为 okhttp3 提升 qps 性能优化 加依赖引入okhttp3
io.github.openfeignfeign-okhttp${version} 写配置
feign: # feign启用hystrix,才能熔断、降级 # hystrix: # enabled: true # 启用 okhttp 关闭默认 httpclient httpclient: enabled: false #关闭httpclient # 配置连接池 max-connections: 200 #feign的最大连接数 max-connections-per-route: 50 #fegin单个路径的最大连接数 okhttp: enabled: true # 请求与响应的压缩以提高通信效率 compression: request: enabled: true min-request-size: 2048 mime-types: text/xml,application/xml,application/json response: enabled: true 参数配置
/** * 配置 okhttp 与连接池 * connectionpool 默认创建5个线程,保持5分钟长连接 */@configuration@conditionalonclass(feign.class)@autoconfigurebefore(feignautoconfiguration.class) //springboot自动配置public class okhttpconfig { // 默认老外留给你彩蛋中文乱码,加上它就 ok @bean public encoder encoder() { return new formencoder(); } @bean public okhttp3.okhttpclient okhttpclient() { return new okhttp3.okhttpclient.builder() //设置连接超时 .connecttimeout(10, timeunit.seconds) //设置读超时 .readtimeout(10, timeunit.seconds) //设置写超时 .writetimeout(10, timeunit.seconds) //是否自动重连 .retryonconnectionfailure(true) .connectionpool(new connectionpool(10, 5l, timeunit.minutes)) .build(); }} 来源:赵小胖个人博客
LED台灯也分男女?适合颜控的家居风格
黄奇帆:《5G背景下金融科技的特征和发展路径》
中国5G建设速度有多快?
分享PCB布线设计规则检查分析
首届中南大学新能源科技大会在长沙开幕
Spring Cloud Feign总结问题,注意点,性能调优,切换okhttp3
芯片封装烧结银工艺
惊帆科技凭什么占据可穿戴设备的上游位置
智能家居WIFI温控器如何解决
恶性竞争及外销订单骤减 大陆LED厂掀倒闭潮
EMC检测所需资料和步骤
【RA2L1开发实践】-触摸按键控制舵机
苹果A14处理器采用台积电5nm将于2020年亮相
CEEASIA亚洲消费电子展:科技引领未来
Intel 10代酷睿桌面处理器偷跑 3、4月份上市有戏
智慧医疗车开进村里可以带来什么福利
Mini/Micro LED高清显示技术迎来更大发展
气体质量流量传感器的应用
工业物联网助力流程工业数字化转型有序推进
诺基亚8什么时候上市?诺基亚8、诺基亚9最新消息:诺基亚回来了,是诺基亚8还是诺基亚9,用这款S8能夺回市