如何写一个HttpClient[1]——URI的处理

如何写一个HttpClient[1]——URI的处理

在翻阅apache的http client的代码的时候,看到org.apache.http.client.utils.URIBuilder.java的写法,感受甚妙。特地分析一下源码,而且对比几种不一样的URI写法。html

本文目录


Apache的HttpClientjava

做为字符串的URI

假设咱们有一个HttpClient类,这个类用来发起http请求而且作出响应。以下:apache

class HttpClient{

    ...
}

如今要把URI做为参数,传递给HttpClient类,好让它知道对谁发起http请求。URI能够是诸如 https://www.google.com/#q=编程狗的博客 这样一个简单的string,一个简单的实现就是给HttpClient类提供一个设置URL的方法:编程

class HttpClient{
    ...
    public void setURI(String uri){
        ...
    }
    ...
}

这应该是最简单的但倒是最不成熟的作法了。它有不少弊端,但咱们暂时不讲出来,且往下看。安全

做为类对象的URI

如今咱们须要更换URI,但又不是所有更换,什么意思呢?不妨分几个部分来看看URI:函数

Scheme -> https
Host -> www.google.com
Path -> /#q=编程狗的博客

https的可能换成httpwww.google.com可能会换成www.google.com.hk,/#q=编程狗的博客可能换成其余的关键词。咱们暂且把这个过程称为参数的置换。若是咱们仅仅给客户端类HttpClient提供一个setURI(String uri)方法,上面的置换只能经过换掉整个URI实现了。好比把https://www.google.com/#q=编程狗的博客 换成 http://www.google.com/#q=编程狗的博客,而没有办法直接把"https"换成"http"ui

因而,咱们不妨提供再一下几个方法,以使咱们很方便的作出上面的置换this

public void setScheme(String scheme){
    ...
}

public void setHost(String host){
    ...
}

public void setPath(String path){
    ...
}

这三个方法分别用来设置schemehostpath。为了叙述方便,没有对参数进行检查。仅仅提供这三个设置参数的方法是不能过实现置换的,由于对于传入的URI,必须先分割schemehostpath三部分。固然,咱们能够的再添加一个splitURI方法,实现分割;可是,咱们已然发现若是这样作了,HttpClient类就有至少4个方法处理URI了,未来可能还会增长,HttpClient类可能会有数十个方法的做用与http信息收发不相关,这样势必是一种混乱,而且影响扩展性,所以咱们不这样作。咱们应当有一个URI类,专门处理URI的置换分割google

class URI{
    //构造函数,默认把uri分割好。
    public URI(String uri){
    ...
        splitURI();
    ...
    }

    //分割方法
    private void splitURI(){
    ...
    }

    //set方法
    public void setScheme(String scheme){
    ...
    }

    public void setHost(String host){
    ...
    }

    public void setPath(String path){
    ...
    }


    //get方法
    public String getScheme(){
    ...
        return scheme;
    }

    public String setHost(){
    ...
        return host;
    }

    public String setPath(){
    ...
        return path;
    }
}

同时咱们也更新HttpClient类3d

class HttpClient{
    ...
    public void setURI(URI uri){
        ...
    }
    ...
}

咱们能够这样使用它们:

URI uri = new URI("https://www.google.com/#q=编程狗的博客");
uri.getScheme();// https
uri.getHost();// www.google.com
uri.getPath();// /#q=编程狗的博客
...
uri.setScheme();// https(若是你确实须要从新设置)
...
HttpClient client = new HttpClient();
client.setURI(uri);

做为Builder的URI

到如今为止已经能够应付关于URI的不少需求了,可是咱们若是要求URI类是一个不可变的类,为何不可变呢?由于不可变更加安全。但那些set方法就没有用处了。apache把URI的set方法去掉了,若是想设置参数,如今只能经过构造函数:

//重载构造函数
public URI(String str){
...
}
/**
     * @param   scheme    Scheme name
     * @param   userInfo  User name and authorization information
     * @param   host      Host name
     * @param   port      Port number
     * @param   path      Path
     * @param   query     Query
     * @param   fragment  Fragment
*/
public URI(String scheme,
               String userInfo, String host, int port,
               String path, String query, String fragment){
...
}

...
//用法如
URI uri = new URI("http","username:program-dog","program-dog.blogspot.com","/","","");

咱们至少有7个参数,若是要知足各类需求的组合,恐怕总共要提供∑(C^7^~i~)(i=1~7)种构造函数,显然不现实。然而,URIBuilder既能够造出一个不可变的URI,又能够兼顾N种参数。URIBuilder能够这样用:

//  http://www.google.com/search?q=编程狗的博客&btnG=Google+Search&aq=f&oq=
URI uri = new URIBuilder()
    .setScheme("http")
    .setHost("www.google.com")
    .setPath("/search")
    .setParameter("q", "编程狗的博客")
    .setParameter("btnG", "Google Search")
    .setParameter("aq", "f")
    .setParameter("oq", "")
    .build();

URIBuilder正是采用了Builder Pattern(建造者模式)。等号右边其实是一行,先建立一个URIBuilder对象实例,调用实例的setScheme方法,此方法顺便返回URIBuilder对象实例,刚刚返回的这个实例调用setHost方法,...,最后一个返回的URIBuilder对象实例调用build方法,返回URI对象。它是如何实现的呢?

原来的URI类的set方法的基础上,添加一个返回值,返回URIBuilder本身就够了:

class URIBuilder{
    public URIBuilder setScheme(String scheme){
    ...
        return this;
    }

    public URIBuilder setHost(String host){
    ...
        return this;
    }

    public URIBuilder setPath(String path){
    ...
        return this;
    }

    //built 方法,把参数拼接,而后返回一个URI类
    public URI built(){
    ...
        return uri;
    }
}

因为URIBuilder每次都返回它本身,因此能够连续的执行 set方法,最后经过built方法返回URI类。

结束

到此为止,一个简单的URI类的写法已经介绍完毕了。咱们仍是尽可能把URI写成类对象,并使它不可变,而且提供相应的Builder。







知识共享许可协议
本做品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。


本文地址:https://program-dog.blogspot.com/2016/06/HowToWriteAHttpClientAboutURI.html

相关文章
相关标签/搜索