如何寫一個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

相關文章
相關標籤/搜索