安庆大理运城常德铜陵江西
投稿投诉
江西南阳
嘉兴昆明
铜陵滨州
广东西昌
常德梅州
兰州阳江
运城金华
广西萍乡
大理重庆
诸暨泉州
安庆南充
武汉辽宁

SpringCloud系列Feign服务调用

5月5日 相见欢投稿
  前言
  前面我们已经实现了服务的注册与发现(请戳:SpringCloud系列Eureka服务注册与发现),并且在注册中心注册了一个服务myspringboot,本文记录多个服务之间使用Feign调用。
  Feign是一个声明性web服务客户端。它使编写web服务客户机变得更容易,本质上就是一个http,内部进行了封装而已。
  GitHub地址:https:github。comOpenFeignfeign
  官方文档:https:cloud。spring。iospringcloudstaticspringcloudopenfeign2。1。0。RC2singlespringcloudopenfeign。html服务提供者
  提供者除了要在注册中心注册之外,不需要引入其他东西,注意以下几点即可:
  1、经测试,默认情况下,feign只能通过RequestBody传对象参数
  2、接参只能出现一个复杂对象,例:publicResultListUserVolist(RequestBodyUserVoentityVo){。。。}
  3、提供者如果又要向其他消费者提供服务,又要向浏览器提供服务,建议保持原先的Controller,新建一个专门给消费者的Controller
  测试Controller接口RestControllerRequestMapping(user)publicclassUserController{AutowiredprivateUserServiceuserSRequestMapping(list)publicResultListUserVolist(RequestBodyUserVoentityVo){returnuserService。list(entityVo);}RequestMapping(get{id})publicResultUserVoget(PathVariable(id)Integerid){returnuserService。get(id);}}服务消费者
  消费者maven引入jar!feigndependencygroupIdorg。springframework。cloudgroupIdspringcloudstarteropenfeignartifactIddependency
  配置文件
  对日期的解析,消费者要跟提供者一致,不然会报json解析错误超时时间feign。httpclient。connectiontimeout30000mvc接收参数时对日期进行格式化spring。mvc。dateformatyyyyMMddHH:mm:ssjackson对响应回去的日期参数进行格式化spring。jackson。dateformatyyyyMMddHH:mm:ssspring。jackson。timezoneGMT8
  服务调用
  1、springdatejpa应用名称,是服务提供者在eureka注册的名字,Feign会从注册中心获取实例
  2、如果不想启动eureka服务,直连本地开发:FeignClient(namespringdatejpa,pathuser,urlhttp:localhost:10086),或者无eureka,调用第三方服务,关闭eureka客户端(eureka。client。enabledfalse),url直接指定第三方服务地址,path指定路径,接口的方法指定接口
  3、如果使用RequestMapping,最好指定调用方式
  4、消费者的返回值必须与提供者的返回值一致,参数对象也要一致
  5、20190521补充:如需进行容错处理(服务提供者发生异常),则需要配置fallback,如果需要获取到报错信息,则要配置fallbackFactory,例:fallbackMyspringbootFeignFallback。class,fallbackFactoryMyspringbootFeignFallbackFactory。class容错处理(服务提供者发生异常,将会进入这里)ComponentpublicclassMyspringbootFeignFallbackimplementsMyspringbootFeign{OverridepublicResultUserVoget(Integerid){returnResult。of(null,false,糟糕,系统出现了点小状况,请稍后再试);}OverridepublicResultListUserVolist(UserVoentityVo){returnResult。of(null,false,糟糕,系统出现了点小状况,请稍后再试);}}只打印异常,容错处理仍交给MyspringbootFeignFallbackComponentpublicclassMyspringbootFeignFallbackFactoryimplementsFallbackFactoryMyspringbootFeign{privatefinalMyspringbootFeignFallbackmyspringbootFeignFpublicMyspringbootFeignFallbackFactory(MyspringbootFeignFallbackmyspringbootFeignFallback){this。myspringbootFeignFallbackmyspringbootFeignF}OverridepublicMyspringbootFeigncreate(Throwablecause){cause。printStackTrace();returnmyspringbootFeignF}}
  Feign接口
  更多FeignClient注解参数配置,请参阅官方文档FeignClient(namespringdatejpa,pathuser)publicinterfaceMyspringbootFeign{RequestMapping(valueget{id})ResultUserVoget(PathVariable(id)Integerid);RequestMapping(valuelist,methodRequestMethod。GET)ResultListUserVolist(RequestBodyUserVoentityVo);}
  Controller层feign调用GetMapping(feignget{id})ResultUserVoget(PathVariable(id)Integerid){returnmyspringbootFeign。get(id);}feign调用GetMapping(feignlist)ResultListUserVolist(UserVouserVo){returnmyspringbootFeign。list(userVo);}
  启动类
  启动类加入注解:EnableFeignClientsEnableEurekaClientEnableFeignClientsSpringBootApplicationpublicclassMyspringbootApplication{publicstaticvoidmain(String〔〕args){SpringApplication。run(MyspringbootApplication。class,args);}}效果
  成功注册两个服务
  成功调用
  报错记录
  1、启动时报了个SQL错误
  解决:配置文件连接数据时指定serverTimezoneGMT2B8
  2、当我将之前搭好的一个springbootspringdatajpa整合项目在eureka注册时出现了一个报错
  然后在网上查了下说是因为springboot版本问题(请戳:http:www。cnblogs。comhbbbsarticles8444013。html),之前这个项目用的是2。0。1。RELEASE,现在要在eureka注册,pom引入了就出现了上面的报错!eurekaclientdependencygroupIdorg。springframework。cloudgroupIdspringcloudstarternetflixeurekaclientartifactIddependency!actuatordependencygroupIdorg。springframework。bootgroupIdspringbootstarteractuatorartifactIddependencydependencyManagementdependenciesdependencygroupIdorg。springframework。cloudgroupIdspringclouddependenciesartifactIdversionGreenwich。RC1versiontypepomtypescopeimportscopedependencydependenciesdependencyManagementrepositoriesrepositoryidspringmilestonesidnameSpringMilestonesnameurlhttps:repo。spring。iomilestoneurlrepositoryrepositories
  解决:升级了springboot版本,2。1。0,项目正常启动parentgroupIdorg。springframework。bootgroupIdspringbootstarterparentartifactIdversion2。1。0。RELEASEversion!version2。0。1。RELEASEversionrelativePath!lookupparentfromrepositoryparent补充
  20191017补充:Feign设置header请求头
  方法1,mapping的headers属性,单一设置FeignClient(namesvc,pathmodulesuser,url{feign。url})publicinterfaceUserFeignextendsBaseFeignUserVo{PostMapping(valuexxx,headers{Cookie,JSESSIONIDxxx})ResultModelListUserVoxxx(UserVoentity);}
  方法2,自定义FeignInterceptor,全局设置feign请求设置header参数这里比如浏览器调用A服务,A服务Feign调用B服务,为了传递一致的sessionIdComponentpublicclassFeignInterceptorimplementsRequestInterceptor{publicvoidapply(RequestTemplaterequestTemplate){StringsessionIdRequestContextHolder。currentRequestAttributes()。getSessionId();requestTemplate。header(Cookie,JSESSIONIDsessionId);}}
  这样就可以设置cookie,传递token等自定义值
  常见场景1
  通常我们一个服务web层、svc层、dao层,但有时候也会将拆分成两个服务:
  web服务提供静态资源、页面以及controller控制器控制跳转,数据通过java调用svc服务获取;
  svc服务,进行操作数据库以及业务逻辑处理,同时提供接口给web服务调用;
  特殊情况下我们想svc服务的接口也做登录校验,所有接口(除了登录请求接口)都有做登录校验判断,未登录的无权访问,这时候就需要做sessionId传递,将web服务的sessionId通过Feign调用时传递到svc服务
  web服务
  注:登录成功后用sessionId作为key,登录用户的id作为value,保存到redis缓存中
  登录拦截器web登录拦截器ComponentpublicclassLoginFilterimplementsFilter{AutowiredprivateStringRedisTOverridepublicvoidinit(FilterConfigfilterConfig){}OverridepublicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{HttpServletRequestrequest(HttpServletRequest)servletRHttpServletResponseresponse(HttpServletResponse)servletRStringrequestURIrequest。getRequestURI();除了访问首页、登录页面、登录请求,其他的都要查看Redis缓存StringsessionIdrequest。getSession()。getId();Stringredistemplate。opsForValue()。get(sessionId);if(!无需登录即可访问的接口(requestURI。contains(index)requestURI。contains(loginindex)requestURI。contains(loginlogin)静态资源requestURI。contains(。js)requestURI。contains(。css)requestURI。contains(。json)requestURI。contains(。ico)requestURI。contains(。png)requestURI。contains(。jpg))StringUtils。isEmpty(redis)){重定向登录页面response。sendRedirect(loginindex?urlrequestURI);}else{正常处理请求filterChain。doFilter(servletRequest,servletResponse);}}Overridepublicvoiddestroy(){}}
  自定义FeignInterceptorfeign请求设置header参数这里比如浏览器调用A服务,A服务Feign调用B服务,为了传递一致的sessionIdComponentpublicclassFeignInterceptorimplementsRequestInterceptor{publicvoidapply(RequestTemplaterequestTemplate){StringsessionIdRequestContextHolder。currentRequestAttributes()。getSessionId();requestTemplate。header(Cookie,JSESSIONIDsessionId);}}
  svc服务svc登录拦截器ComponentpublicclassLoginFilterimplementsFilter{AutowiredprivateStringRedisTOverridepublicvoidinit(FilterConfigfilterConfig){}OverridepublicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{HttpServletRequestrequest(HttpServletRequest)servletRHttpServletResponseresponse(HttpServletResponse)servletRStringrequestURIrequest。getRequestURI();service服务,查看Redis缓存,登录后才允许访问(除了checkByAccountNameAndPassword)StringsessionIdrequest。getRequestedSessionId();if(!(requestURI。contains(modulesusercheckByAccountNameAndPassword))StringUtils。isEmpty(template。opsForValue()。get(sessionId))){提示无权访问response。setCharacterEncoding(UTF8);response。setContentType(charsetutf8);PrintWriteroutresponse。getWriter();out。print(对不起,你无权访问!);out。flush();out。close();}else{正常处理请求filterChain。doFilter(servletRequest,servletResponse);}}Overridepublicvoiddestroy(){}}七天免登陆
  会话期的sessionId,关闭浏览器后就失效了,所以就会退出浏览器后就需要重新登陆,有些情况我们并不想这样,我们想实现七天免登陆,这时候就需要自定义token,并且存放在cookie
  登陆拦截器web登录拦截器ComponentpublicclassLoginFilterimplementsFilter{静态资源为防止缓存,加上时间戳标志privatestaticfinalStringSTATICTAILAutowiredprivateStringRedisTOverridepublicvoidinit(FilterConfigfilterConfig){}OverridepublicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{HttpServletRequestrequest(HttpServletRequest)servletRHttpServletResponseresponse(HttpServletResponse)servletRStringrequestURIrequest。getRequestURI();无需登录即可访问的接口,登陆页面、登陆请求if(requestURI。contains(loginindex)requestURI。contains(loginlogin)){正常处理请求filterChain。doFilter(servletRequest,servletResponse);}静态资源if(requestURI。contains(。js)requestURI。contains(。css)requestURI。contains(。json)requestURI。contains(。woff2)requestURI。contains(。ttf)requestURI。contains(。ico)requestURI。contains(。png)requestURI。contains(。jpg)requestURI。contains(。gif)){检查是否有防缓存时间戳StringqueryStrrequest。getQueryString();if(StringUtils。isEmpty(queryStr)!queryStr。trim()。contains(STATICTAIL)){response。sendRedirect(requestURI?STATICTAILSystem。currentTimeMillis());}正常处理请求filterChain。doFilter(servletRequest,servletResponse);}剩下的要检查redis缓存Sfor(Cookiecookie:request。getCookies()){if(TOKEN。equals(cookie。getName())){tokencookie。getValue();}}Stringredistemplate。opsForValue()。get(token);if(StringUtils。isEmpty(redis)){重定向登录页面response。sendRedirect(loginindex?urlrequestURI);}如果都不符合,正常处理请求filterChain。doFilter(servletRequest,servletResponse);}Overridepublicvoiddestroy(){}}
  登陆成功,设置cookiepublicResultModelUserVologin(UserVouserVo){此处省略查询操作。。。if(true){HttpServletResponseresponse((ServletRequestAttributes)RequestContextHolder。currentRequestAttributes())。getResponse();设置Redis,有效时长:7天StringuuidUUID。randomUUID()。toString();template。opsForValue()。set(uuid,userVo。getAccountNo());template。expire(uuid,76060,TimeUnit。SECONDS);设置cookie,有效时长:7天CookiecookienewCookie(TOKEN,uuid);cookie。setPath();cookie。setMaxAge(7246060);response。addCookie(cookie);returnResultModel。of(userVo,true,登录成功);}returnResultModel。of(null,false,用户名或密码错误);}
  推出登陆,销毁cookiepublicResultModelUserVologout(){HttpServletRequestrequest((ServletRequestAttributes)RequestContextHolder。currentRequestAttributes())。getRequest();HttpServletResponseresponse((ServletRequestAttributes)RequestContextHolder。currentRequestAttributes())。getResponse();Sfor(Cookiecookie:request。getCookies()){if(TOKEN。equals(cookie。getName())){tokencookie。getValue();cookie。setValue(null);cookie。setPath();cookie。setMaxAge(0);立即销毁cookieresponse。addCookie(cookie);}}template。delete(token);returnResultModel。of(null,true,操作成功!);}代码开源
  代码已经开源、托管到我的GitHub、码云:
  GitHub:https:github。comhuanziqchspringCloud
  码云:https:gitee。comhuanziqchspringCloud版权声明
  作者:huanziqch
  出处:https:www。cnblogs。comhuanziqch
  若标题中有转载字样,则本文版权归原作者所有。若无转载字样,本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。
投诉 评论 转载

SpringCloud系列Feign服务调用前言前面我们已经实现了服务的注册与发现(请戳:SpringCloud系列Eureka服务注册与发现),并且在注册中心注册了一个服务myspringboot,本文记录多个服……蔚来事件后续理想小鹏相继修改辅助驾驶描述词汇删除高级自动字眼每经记者:李硕每经编辑:孙磊近日一起知名企业家驾驶蔚来ES8在沈海高速公路发生的交通事故,让有关自动驾驶的功能和宣传一跃成为行业热议的话题。事件发生后不久,理想汽车……除了SAP,宁德时代数字生态圈还有哪些伙伴?一向低调的宁德时代,在数字化领域的布局鲜少被提及,直到今年9月,宁德时代宁德工厂被世界经济论坛(WEF)评选为灯塔工厂,我们才得以窥见其在智能制造和数字化领域的冰山一角。……免费看还能挣钱片多多撬得动下沉市场吗面对下沉市场,腾讯上线了一款长视频App片多多。5月11日,北京商报记者发现,目前这款应用仅在安卓应用商店上线,用户可在片多多上免费观看长视频,且可以看剧换金币提现,每天最多赚……闲鱼上有很多非常高配非常低价的外星人笔记本,谁知道这是什么套作为一个有着多年电脑网络维修经验的电脑爱好者来说,我可以推心置腹的跟你分享我的经验,希望我的解答能给你带来帮助。对于你的这个提问,来听听我的一点看法吧!现如今闲鱼这……256GB后置三摄,现已跌至4059元,经典iPhone二手苹果公司在发布iPhone13系列新机之前,就已经是开始有意加速清空下架iPhone12Pro系列手机了,所以如今想要在正规销售渠道中买到iPhone12Pro系列手机反而不容……任正非从来不卖各种鸡汤,也没有加入各种圈子,把华为做成了中国人人都可以有鸡汤,但鸡汤的味道总是因人而异。任正非的从容与包容,特别是包容,确实是超越了我们的想象。面对巨大的困难,既能从容,又能包容,这就一种难能可贵的定力与自信。……最薄5G手机?小米11青春版入网首发骁龙775G近日一款型号为M2101K9C的小米新机入网工信部,电池容量为4150mAh,机身厚度为6。81mm。新机应该就是小米11青春版,主打轻薄机身,可能是目前最薄的5G手机。……有哪些极简的iPhone壁纸推荐?关于iPhone的原生壁纸,不少人都为之着迷。随着iPhoneX的上市,看过其系统自带壁纸的小伙伴都应该有这样一种感觉:色彩艳丽,但又不失简洁大气。那么,大家有没有想过,……红米K40为啥稳定版不能上DC调光?垃圾手机。买了肠子都悔青了小米官方工程师回复过这个问题,意思是,经过测试,红米k40这块屏幕开启dc调光后显示效果很不理想,所以该功能不会加入稳定版,只会加入开发版让会折……手把手教你四步彻底删除右下角弹窗电脑中有的弹窗可以直接关闭,但有的弹窗却十分流氓,因为他根本没有关闭键,如上图所示一样,遇到这种情况,不禁让小伙伴们非常气愤。那我们应该如何处理这种现象呢?这类弹窗确实不会显示……装Windows11了!这三个常规操作,你会了吗?Window11系统已经正式推出,相信很多小伙伴和小编一样已经跃跃欲试下载尝鲜了,但是由于win11系统相比之前的系统做了一下改动,使用起来还不是很习惯的。小编就在一些常……
GN2超大底5000mAh,低价高配的集大成之作,300万销北方稀土预计一季度净利同比增96。78润建股份(002929。SZ)取得1。02亿元能源网络管维业5直播摄像头与电脑的连接专业虚拟直播间搭建打击传销当心这40个互联网投资项目骗局,有的即将崩盘跑路!速GO语言(十三)使用Go和Gin开发RESTfulAPI(下美国星链又有变化了?马斯克要价36000元,一年期的500兆我,华为员工,揭秘华为的高级工程师退休后有多少退休金三星S21U有何能耐?市场的统治者名副其实现在有5000千个比特币的人是一种什么样的体验?新买的二手房,首付款是用支付宝和微信转给房东的,银行不承认,3月22日晚A股新能源上市公司利好消息医圣是指谁麦玲玲年属马运程肖马者丁酉鸡年喜获众多吉星拱照等咱中国强大了汽车减震器漏油故障处理方法介绍中国古代榫卯结构体现工匠的极致匠心婆媳相处不做母女做朋友感恩朋友的话语句子肖像面向对象设计原则接口隔离原则春天来了春色混合皮肤冬天怎么补水混合性肌肤冬季护肤秘籍为什么有些女人生完孩子还像个少女,有些女人就变成了大妈?

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找七猫云易事利