SpringCloud开发cloud具有巨大的灵活性。

在调用其它服务的时候有多种方式,虽然本质一样,但是细节还是有所差异。

一、概述

当a服务调用b服务的时候有多种方式进行:

1.通过openFeign接口方式

优点:我们一般会使用这种方式,因为代码量相对少一些,安全可以通过openFeign拦截器来实现。

缺点:无法在请求的时候直接设置请求头,请求体等(当然可以通过拦截器或者属性配置解决这个。但在运行时,动态修改并不方便)

总结:总体而言,还是推荐的。

2.通过RestTemplate的方式指定服务名调用

优点:灵活度较高,可以自定义处理请求(头+参数等)和返回的操作,不需要定义openFeign接口

确定:如果类似的请求比较多,则工作量还是有一些的。

总结: 如果是最求灵活性,可以考虑。如果不做cloud开发,那么RestTemplate是非常不错的选择。

3.通过RestTemplate的方式指定ip方式调用

第二种方式的变体,一般不那么做,因为这失去了cloud的优势-集群+负载均衡等等。所以在后文的例子中,有关此部分略。

做工程,自然要兼顾效率和可维护性,所以一般我们都推荐使用第1种方式。技术总是要服务于工程和需求。

下面我使用例子来说明。

二、例子

2.1 概述

为了测试,我们构建了四个服务:

a.base(ConfigService) -负责认证 ,返回token

b.McService --管理中心,负责一些管理信息处理

c.CustomerService-负责客户有关信息

d.ConfigServiceTest-配置测试服务

测试的脚本写在服务ConfigServiceTest中。

为了解决篇幅,下文例子只是贴出了各个service的接口以及ConfigServiceTest的cloud有关配置。

 2.2 配置代码

a服务的接口-/api/services/app/Users/Login

    @RequestMapping(value="/api/services/app/Users/Login",method= {RequestMethod.POST,RequestMethod.GET})
@ResponseBody
public PublicReturn login(HttpServletRequest request,@RequestBody AuthParam input) {
AuthParam auth=jwtUtil.parseAuthToken(request, "Authorization"); if (auth!=null) {
LOG.debug("token Value From header is:"+JSON.toJSONString(auth));
}
LOG.debug(JSON.toJSONString(input));
LOG.debug(input.getCustomerSystemCode());
try {
PublicReturn result= this.authService.login(input);
LOG.debug("result is:"+JSON.toJSONString(result));
return result;
}
catch(Exception e) {
return PublicReturn.getUnSuccessful("获取认证信息失败");
} }

b 服务的接口-/api/services/app/test


/**
* 仅用于测试
* @param name
* @return
*/
@RequestMapping("/app/test")
@ResponseBody
public PublicReturn test(@RequestParam(value="name",required = true) String name){
return PublicReturn.getSuccessful(name);
}

c服务的接口-/customer/list

@Controller
@RequestMapping(value="/customer")
public class TestController {
/**
* 返回list
* @return
*/
@RequestMapping(value = "/list")
@ResponseBody
public Object list() { // TODO:
Map<String,Object> customer=new HashMap<String,Object>();
customer.put("name","lzf");
customer.put("sex","男");
customer.put("age","99");
customer.put("address","中华");
return customer;
} }

以上三个服务的代码不用特别关注。

d服务(ConfigServiceTest)的测试代码,分两大部分:配置和接口

  • 配置-OpenFeign接口和相关配置
  • 用于测试的接口

配置代码:

1.异常处理-ErrorHandler(ErrorDecoder)

2.openFeign拦截器等配置-ConfigServiceFeignInter,McServiceFeignInter

3.Spring-Mvc配置-CustomWebMvcConfigurer(WebMvcConfigurationSupport),负责定义RestTemplate bean等等

4.openFeign接口-ConfigServiceOpenFeignInterface、McServiceOpenFeignInterface

测试代码:

1.TestController

--------------------

下面逐一贴出以上代码(注:为了节约篇幅,部分代码只选择紧要部分)

d的两个拦截器代码

public class ConfigServiceFeignInter {
@Bean
public RequestInterceptor currentUserRequestInterceptor() {
return (RequestTemplate template) -> {
//Map<String, Collection<String>> header=template.request().headers();
//System.out.println(JSON.toJSONString(header, true));
};
} } public class McServiceFeignInter { @Bean
public ErrorDecoder feignErrorDecoder() {
return new ErrorHandler();
} @Bean
public RequestInterceptor currentUserRequestInterceptor() {
return (RequestTemplate template) -> {
//Map<String, Collection<String>> header=template.request().headers();
//System.out.println(JSON.toJSONString(header, true));
String token = LoginCache.get();
System.out.println(token);
template.header("Authorization", token);
};
} }

d的两个openFeign接口

@FeignClient(value = "ConfigService",configuration= ConfigServiceFeignInter.class)
@Component
public interface ConfigServiceOpenFeignInterface {
@PostMapping("/api/services/app/Users/Login")
@ResponseBody
PublicReturn login(@RequestBody AuthParam input);
} @FeignClient(value = "McService",configuration= McServiceFeignInter.class)
@Component
public interface McServiceOpenFeignInterface {
@RequestMapping(value = "/api/services/app/test")
public PublicReturn test(@RequestParam(value="name",required = true) String name);
}

d的mvc配置(局部)

@LoadBalanced
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
// 把自定义的ClientHttpRequestInterceptor添加到RestTemplate,可添加多个
//restTemplate.setInterceptors(Collections.singletonList(actionTrackInterceptor));
return restTemplate;
}

注意:

1.springMvc的RestTemplate功能还是很强大的,可以设定拦截器等等。

2.我们并没有为服务c(CustomerService)定义标准的OpenFeign接口

2.3 测试代码

@RequestMapping(value = "/login_and_request")
@ResponseBody
public Object loginAndRequest() { // TODO:
AuthParam authParam=new AuthParam();
//此处略
PublicReturn loginResult=configService.login(authParam);
if (loginResult.isSuccessful()){
String token=loginResult.getDateItem("token").toString();
LoginCache.set(token);
try{
PublicReturn result=mcService.test("this is luzhifei");
return result;
}
catch(Exception e){
return PublicReturn.getUnSuccessful(e.getMessage());
}
}
else{
return PublicReturn.getUnSuccessful("登录失败");
}
} /**
* 使用RestTemplate来调用
* @return
*/
@RequestMapping(value = "/request3srv")
@ResponseBody
public Object request3srv() { // TODO:
AuthParam authParam=new AuthParam();
//此处略...
PublicReturn loginResult=configService.login(authParam);
if (loginResult.isSuccessful()){
String token=loginResult.getDateItem("token").toString();
String url="http://McService/api/services/app/test";
MultiValueMap<String, String> header=new LinkedMultiValueMap<>();
header.add("Authorization",token);
MultiValueMap<String, String> param = new LinkedMultiValueMap<>();
param.add("name","lzf");
HttpEntity<MultiValueMap<String, String>> requst=new HttpEntity<>(param,header);
try{
PublicReturn result=restTemplate.postForObject(url,requst,PublicReturn.class);
return result;
}
catch(Exception e){
return PublicReturn.getUnSuccessful(e.getMessage());
} }
else{
return PublicReturn.getUnSuccessful("登录失败");
}
} @RequestMapping(value = "/list-customer")
@ResponseBody
public Object listCustomer() { // TODO:
String url="http://CustomerService/customer/list";
MultiValueMap<String, String> header=new LinkedMultiValueMap<>();
header.add("Authorization","青山遮不住,毕竟东流去!");
MultiValueMap<String, String> param = new LinkedMultiValueMap<>();
param.add("name","lzf");
HttpEntity<MultiValueMap<String, String>> requst=new HttpEntity<>(param,header);
Object result=restTemplate.postForObject(url,requst,Object.class);
return result;
}

2.4测试

编写完成后,启动a,b,c,d服务。

之后通过浏览器执行:

#通过原生openFeign接口调用
http://localhost:9081/test/login_and_request

#混合调用(原生openFeign+无openFeign方式调用)
http://localhost:9081/test/request3srv

#不需要定义OpenFeign接口的测试
http://localhost:9081/test/list-customer

通过上文list-customer的例子可以看到:不需要专门定义OpenFeign接口,也可以直接调用(通过服务名称而不是ip+url)来实现对其它

服务的调用。

测试的时候发现,如果故意停止服务b.McService,那么会等待比较长一段时间才能返回。

如果觉得这个TimeOut时间太长,那么可以设置OpenFeign调用的TimeOut参数

feign:
  client:
    config:
      default:
        connectTimeout: 30000

注意:这影响所有的Client

---

关于Timeout可以参阅:SpringCloud开发之OpenFeign timeout和压缩等问题

Springcloud开发之OpenFeign调用和认证的更多相关文章

  1. Android NDK开发之C调用Java及原生代码断点调试(二)

    上一篇中,我们主要学习了Java调用本地方法,并列举了两大特殊实例来例证我们的论据,还没学习的伙伴必须先去阅读下,本次的学习是直接在上一篇的基础上进行了.点击:Android NDK开发之从Java与 ...

  2. android webView开发之js调用java代码示例

    1.webView设置 webView.getSettings().setJavaScriptEnabled(true);//设置支持js webView.addJavascriptInterface ...

  3. Android NDK开发之Jni调用Java对象

    https://my.oschina.net/zhiweiofli/blog/114064 通过使用合适的JNI函数,你可以创建Java对象,get.set 静态(static)和 实例(instan ...

  4. Liferay7 BPM门户开发之32: 实现自定义认证登陆(定制Authentication Hook)

    第一步:修改liferay-hook.xml <?xml version="1.0"?> <!DOCTYPE hook PUBLIC "-//Lifer ...

  5. 微信程序开发之-WeixinJSBridge调用

    微信的WeixinJSBridge还是很厉害的,虽然官方文档只公布了3个功能,但是还内置的很多功能没公布,但是存在.今天就好好和大家聊聊 功能1------发送给好友     代码如下: functi ...

  6. web 开发之js---js 调用视频播放

    var popWindow;var videoWindow;var videoWindowF;var currentVideo=null;var currentVideoTitle="&qu ...

  7. Liferay7 BPM门户开发之37: Liferay7下的OSGi Hook集成开发

    hook开发是Liferay客制扩展的一种方式,比插件灵活,即可以扩展liferay门户,也能对原有特性进行更改,Liferay有许多内置的服务,比如用hook甚至可以覆盖Liferay服务. 可作为 ...

  8. 新浪微博客户端开发之OAuth认证篇

    新浪微博客户端开发之OAuth认证篇 2013年7月29日新浪微博客户端开发 OAuth2.0授权机制我在这里就不浪费口舌了,有很多大牛都发表过相关的文章解释OAuth2.0认证的流程,我就随便找了一 ...

  9. Liferay7 BPM门户开发之10: 通用流程实现从Servlet到Portlet(Part1)

    开发目的: 实现通用流程自动化处理(即实现不需要hardcode代码的bpm统一处理后台,仅需要写少量前端html form代码和拖拽设计BPM定义) 既可独立运行或可依托于Liferay或依托其它门 ...

  10. Android混合开发之WebViewJavascriptBridge实现JS与java安全交互

    前言: 为了加快开发效率,目前公司一些功能使用H5开发,这里难免会用到Js与Java函数互相调用的问题,这个Android是提供了原生支持的,不过存在安全隐患,今天我们来学习一种安全方式来满足Js与j ...

随机推荐

  1. WPF 通过 WindowsAppSDK 使用 WinRT 的手写识别功能

    本文告诉大家如何在基于 .NET 6 的 WPF 使用 WinRT 的手写识别功能 在开始之前需要先创建 WPF 项目,创建完成之后,可替换 csproj 项目文件为以下代码,用来安装初始化环境 &l ...

  2. WPF 列表控件数据源绑定多个数据集合方法

    在 WPF 用的多的列表控件如 ListBox 或 ListView 等,本文告诉大家在这些列表控件上进行绑定多个数据集合来源的多个实现方法.如有一个显示动物列表的控件,需要绑定的数据来源是阿猫和阿狗 ...

  3. DE10-Lite锁相环使用教程

    DE10-Lite锁相环使用教程 目标:本文讲述如何在Quartus里设置和例化一个锁相环. 引言 锁相环(PLL)是一种闭环频率控制电路,用于比较压控振荡器的输入信号和输出信号之间的相位差. 负反馈 ...

  4. 第3讲-Cadence分裂元件的制作方法

    笔记3-Cadence分裂元件的制作方法 1.Homogeneous和heterogeneous的区别: 2.创建homogeneous类型元件: 3.创建heterogeneous类型元件. 把元件 ...

  5. vue项目hbuilder打包-微信登录调取手机微信登录权限

    这个笔记得做好. 1.vue页面的点击事件 import {login,loginy,wxLog,wxLogin,logout} from '../network/login' wxloginBtn( ...

  6. 一种光电容积波PPG 转换到心电图ECG进行房颤检测的神经网络模型

    具体的软硬件实现点击 http://mcu-ai.com/ MCU-AI技术网页_MCU-AI人工智能 光电体积描记法(PPG)是一种经济有效的非侵入性技术,利用光学方法测量心脏生理学. PPG 在健 ...

  7. Go-Zero自定义goctl实战:定制化模板,加速你的微服务开发效率(四)

    前言 上一篇文章带你实现了Go-Zero和goctl:解锁微服务开发的神器,快速上手指南,本文将继续深入探讨Go-Zero的强大之处,并介绍如何使用goctl工具实现模板定制化,并根据实际项目业务需求 ...

  8. vueJs开发音乐播放器第二篇(点击歌单跳出详情页)

    继上一篇开发音乐播放器歌单列表页 (1.使用router定义跳转链接,2. 使用axios得到音乐第三方数据,并渲染到页面上,3.组件之间传值(props)) 1.接下来使用了vue-router路由 ...

  9. 远程协助软件哪个好,IT远程支持用什么软件

    软件行业做售后支持,有时候需要远程控制客户电脑以实现远程协助,远程解决客户问题. IT远程支持用什么软件比较好?这个我们可以逐个分析下. 一.QQ远程 一看就不专业,的确也不专业.QQ远程协助可以实现 ...

  10. AIRIOT答疑第4期|如何使用数据分析引擎?

    灵活报表曲线,满足各类分析需求! AIRIOT物联网低代码平台的数据分析引擎满足各类型数据分类及分析需求,毫秒级数据反馈速度,快速响应客户分析条件变换查询需求.通过机器学习.融合各种计算模型.人工智能 ...