前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >通过策略模式提供通用的http接口调用方法

通过策略模式提供通用的http接口调用方法

作者头像
Antony
发布2020-12-02 10:32:27
发布2020-12-02 10:32:27
1.1K00
代码可运行
举报
运行总次数:0
代码可运行

场景

在微服务中,服务可能是部署和运行在不同的区域的。 不同区域的服务,认证方式也不同,接口调用方式不同。

代码语言:javascript
代码运行次数:0
运行
复制
|接入区| ----网关-----|业务区|

另外,随着产品架构的迭代升级,相同的微服务在不同代际版本的上述服务调用方式也会有差异。 这就给了测试开发人员提出了一个需求,希望能在功能测试时尽可能地抹平这些差异,让测试人员能专注于测试层面的测试。 从测试角度看,会有以下几个典型的场景

代码语言:javascript
代码运行次数:0
运行
复制
A:  外部服务接口,提供给外部机构或个人使用,一般位于接入区,涉及业务的应用,认证较为严格,可能需要证书等方式进行认证。
B: 管理类服务接口,提供给业务部门的业务终端或者是前台使用。
C: 内部服务接口,被上述服务调用的接口。

HTTP接口调用基本要素

在接口调用过程中,可能涉及到以下的内容 1)Head : user-agent: 服务间调用时,会对user-agent 进行判断,看客户端是 来自普通浏览器还是内置浏览器,如httpclient X-CSRF-TOKEN, 对于外部服务接口来说,需要在登录后将登录接口返回的CSRF-TOKEN从cookies中取出,存放到head中,以用于后续服务接口的顺利调用。

  1. Cookies: 一般请求都需要带上特定的token 典型的如,token 和过期时间
  2. 传参:params 或者是body 由于产品的升级迭代,不同服务的http接口的传参方式也不一样,有些是通过params在url中传递,有些则使用body进行传递。

策略模式的应用

首先定义一个接口,包括了登录和发请求两个方法

代码语言:javascript
代码运行次数:0
运行
复制
package com.github.http;
public interface Operator {
    public String logon(String logonUrl,String userName, String password);
    public String doPost(String requestUrl,String body);
}

然后写写一个类类实现这个接口,假设这是一个最常见的外部服务接口A的调用类,它的参数通过body进行传输,并且需要登录。

代码语言:javascript
代码运行次数:0
运行
复制
package com.github.http;
public class OperatorA implements Operator {
    @Override
    public String logon(String logonUrl, String userName, String password) {
        return null;//TODO
    }
    @Override
    public String doPost(String requestUrl, String body) {
        return null;//TODO
    }
}

这个时候笔者发现,如果按照一般策略模式进行实现的话,那么如果还需要对服务间接口C编写调用策略时,发现Operator 接口类需要额外增加一个方法

代码语言:javascript
代码运行次数:0
运行
复制
    public String doPost(String requestUrl, Map params)

因为这类接口通过params进行数据传输。如果修改Operator的接口,那么已经写好的OperatorA接口也要做响应的修改来新增这个方法。另外根据之前所述,内部服务调用时不需要登录,因此OperatorB中其实并不需要logon方法,但是采用这种方式,还是需要在OperatorB中实现这个方法。这就不是很友好了。

解决方法 -AbstractOperator 和HttpOperator

新增一个抽象类AbstractOperator 来实现这个接口,然后上述各个Operator来继承并选择性实现各自所需的方法,就可以避免上述麻烦了。最后通过HttpOperator 来提供统一的调用入口。

代码语言:javascript
代码运行次数:0
运行
复制
package com.github.http;
import java.util.Map;
public abstract class AbstractOperator implements Operator {
    public  String logon(String logonUrl, String userName, String password){
        throw new UnsupportedOperationException();
    }
    public  String doPost(String requestUrl, String body) {
        throw new UnsupportedOperationException();
    }
    public  String doPost(String requestUrl, Map params){
        throw new UnsupportedOperationException();
    }
}

package com.github.http;
import java.util.Map;
public interface Operator {
    public String logon(String logonUrl,String userName, String password);
    public String doPost(String requestUrl,String body);
    public String doPost(String requestUrl, Map params);
}

例如在OperatorB中只要实现以下方法即可:

代码语言:javascript
代码运行次数:0
运行
复制
package com.github.http;
public class OperatorB extends AbstractOperator {
    @Override
    public String doPost(String requestUrl, String body) {
        System.out.println("post body on B");
        return null;
    }

}

最终通过一个HttpOperator 来提供统一的调用入口,各个应用的服务调用可以写成类似这样,

代码语言:javascript
代码运行次数:0
运行
复制
        HttpOperator operator= new HttpOperator(OperatorType.A);
        operator.doPost("www.baidu.com","{}");

具体实现如下,

代码语言:javascript
代码运行次数:0
运行
复制
package com.github.http;
import java.util.Map;
public class HttpOperator {
    OperatorType type;
    AbstractOperator operator;
    HttpOperator(OperatorType type){
        this.type=type;
        setOperator(type);
    }
    public  String logon(String logonUrl, String userName, String password){
        return   operator.logon(logonUrl,userName,password);
    }
    public  String doPost(String requestUrl, String body) {
        return  operator.doPost(requestUrl,body);
    }
    public  String doPost(String requestUrl, Map params){
        return  operator.doPost(requestUrl,params);
}
    private void setOperator(OperatorType type) {
            switch (type) {
            case A:
                operator= new OperatorA();
            case B:
                operator= new OperatorB();
            case C:
                operator= new OperatorC();
        }
    }
    public static void main(String argv[]){
        HttpOperator operator= new HttpOperator(OperatorType.A);
        operator.doPost("www.baidu.com","");
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-08-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 软件测试那些事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 场景
    • HTTP接口调用基本要素
    • 策略模式的应用
    • 解决方法 -AbstractOperator 和HttpOperator
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档