如何写一个HttpClient[1]——URI的处理
如何写一个HttpClient[1]——URI的处理
在翻阅apache的http client的代码的时候,看到org.apache.http.client.utils.URIBuilder.java的写法,感觉甚妙。特意分析一下源码,并且对比几种不同的URI写法。
本文目录

Apache的HttpClient
作为字符串的URI
假设我们有一个HttpClient类,这个类用来发起http请求并且做出响应。如下:
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的可能换成http,www.google.com可能会换成www.google.com.hk,/#q=编程狗的博客可能换成其他的关键词。我们暂且把这个过程称为参数的置换。如果我们仅仅给客户端类HttpClient提供一个setURI(String uri)方法,上面的置换只能通过换掉整个URI实现了。比如把https://www.google.com/#q=编程狗的博客 换成 http://www.google.com/#q=编程狗的博客,而没有办法直接把"https"换成"http"。
于是,我们不妨提供再一下几个方法,以使我们很方便的做出上面的置换:
public void setScheme(String scheme){
...
}
public void setHost(String host){
...
}
public void setPath(String path){
...
}
这三个方法分别用来设置scheme,host和path。为了叙述方便,没有对参数进行检查。仅仅提供这三个设置参数的方法是不能过实现置换的,因为对于传入的URI,必须先分割成scheme,host和path三部分。当然,我们可以的再添加一个splitURI方法,实现分割;但是,我们已然发现如果这样做了,HttpClient类就有至少4个方法处理URI了,将来可能还会增加,HttpClient类可能会有数十个方法的作用与http信息收发不相关,这样势必是一种混乱,并且影响扩展性,因此我们不这样做。我们应当有一个URI类,专门处理URI的置换和分割。
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类:
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个参数,如果要满足各种需求的组合,恐怕总共要提供∑(C7i)(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
如何写一个HttpClient[1]——URI的处理的更多相关文章
- 如何写一个简单的http服务器
最近几天用C++写了一个简单的HTTP服务器,作为学习网络编程和Linux环境编程的练手项目,这篇文章记录我在写一个HTTP服务器过程中遇到的问题和学习到的知识. 服务器的源代码放在Github. H ...
- Java Web 开发利用Struts2+Spring+mybatis写一个用户登录界面以及简单的数据交互
框架的东西太复杂也难以讲通,直接上代码: 一.首先得配置环境 和导入必要的jar包 有一些重要的如下: Filter文件夹下的SafetyFilter.java model文件夹下的 Global ...
- 【Filter 不登陆无法访问】web项目中写一个过滤器实现用户不登陆,直接给链接,无法进入页面的功能
在web项目中写一个过滤器实现用户不登陆,直接给链接,无法进入页面,而重定向到登陆界面的功能. 项目是用springMVC+spring+hibernate实现 (和这个没有多大关系) 第一步: 首先 ...
- 【Filter 页面重定向循环】写一个过滤器造成的页面重定向循环的问题
今天做一个过滤器,碰上页面重定向循环的情况: 浏览器的访问路径是:http://192.168.16.104:8080/biologyInfo/login/login/login/login/logi ...
- 与众不同 windows phone (38) - 8.0 关联启动: 使用外部程序打开一个文件或URI, 关联指定的文件类型或协议
[源码下载] 与众不同 windows phone (38) - 8.0 关联启动: 使用外部程序打开一个文件或URI, 关联指定的文件类型或协议 作者:webabcd 介绍与众不同 windows ...
- (2)自己写一个简单的servle容器
自己写一个简单的servlet,能够跑一个简单的servlet,说明一下逻辑. 首先是写一个简单的servlet,这就关联到javax.servlet和javax.servlet.http这两个包的类 ...
- 用c++写一个 “hello,world” 的 FastCGI程序
原文:http://chriswu.me/blog/writing-hello-world-in-fcgi-with-c-plus-plus/ 上面的连接地址给出的是作者的原文地址. 另外一个作者稍微 ...
- 手动的写一个structs
为了更好的学习框架的运行机制,这里开始学习框架之前,介绍一个简单的自定义的框架. 需求: 登录:id:aaa,pwd:888登录成功之后,跳转到,index.jsp页面并显示,欢迎你,aaa 注册,页 ...
- 爬虫入门 手写一个Java爬虫
本文内容 涞源于 罗刚 老师的 书籍 << 自己动手写网络爬虫一书 >> ; 本文将介绍 1: 网络爬虫的是做什么的? 2: 手动写一个简单的网络爬虫; 1: 网络爬虫是做 ...
随机推荐
- Tomcat服务器中配置多个域名,访问不同的web项目
先说一下在本地电脑怎么实现: 想要在一个tomcat下访问两个web项目时,可以通过添加虚拟host的方式来解决. 详细步骤如下: 1.将两个项目打包放入tomcat的webapps目录下: 2.修改 ...
- shFlags简介
看到有脚本中使用了shFlags,于是google了一下,发现还是个挺方便的东西. https://github.com/kward/shflags/wiki/Documentation12x sha ...
- MySQL Replication需要注意的问题
MySQL Replication 大家都非常熟悉了,我也不会写怎么搭建以及复制的原理,网上相关文章非常多,大家可以自己去搜寻.我在这里就是想总结一下mysql主从复制需要注意的地方.有人说主从复制很 ...
- 响应式Web设计 - 布局
可扩展的布局 有一种流体布局的概念在早起web兴起的时,就开始盛行了.它的概念是说页面会根据浏览器窗口的变化进行更改,网站可以通过维护一套代码,保质一致性的设计.我这里强调的可扩展的布局也是基于这个概 ...
- .net core 1.0 中的asp.net identity 的基本使用 序言
2016年6月底,微软发不了vs2015 up3,在这个版本中,微软做了一些改变,本人目前也尚在学习使用之中,现把学习和使用的心得写出来,错误之处请大家指正. 开发环境:vs2015 UP3 项目 ...
- Spring 000 框架简介 (转载)
转载自:https://my.oschina.net/myriads/blog/37922 1.使用框架的意义与Spring的主要内容 随着软件结构的日益庞大,软件模块化趋势出现,软件开发也需要多人合 ...
- Unity5和WebGL移植指南的一些总结
对于手游开发者来说,更新版本往往意味着非常复杂的过程,你需要根据反馈做更新.测试.提交然后等待审核,而由于不需要客户端依赖,页游往往是快速测试游戏版本的最佳途径,很多人可能都知道Unity 5可以再不 ...
- float导致父级元素塌陷的问题
利用float进行页面布局时常常会出现父级元素没有高度的塌陷问题,如以下代码: <!DOCTYPE html> <html> <head lang="en&qu ...
- node静态资源管理变迁之路
使用express自带的,express.static,如:app.use(express.static('hehe')),就可以用localhost/hua.png,访问项目根目录下,hehe文件夹 ...
- 点击input时,里面默认字体消失显示
点击input时,点击input里面默认字体消失显示: <input type="" name="" id="" value=&quo ...
