URLConnection是一个功能强大的抽象类,它表示指向URL指定资源的活动连接。

  • 与URL类相比,它与服务器的交互提供了更多的控制机制。尤其服务器是HTTP服务器,可以使用URLConnection对HTTP首部的访问,可以配置发送给服务器的请求参数。当然也可以通过它读取服务器的数据以及向服务器写入数据
  • URLConnection是Java的协议处理器机制的一部分。协议处理器机制是将处理协议的细节与特定数据类型分开。如果要实现一个特定的协议,则实现URLConnection的子类即可。程序运行时可以将该子类作为一个具体的协议处理器来使用。

使用URLConnection类的步骤

  1. 构造一个URL对象
  2. 调用该URL的openConnection()获取一个URLConnection
  3. 配置这个URLConnection
  4. 读取首部字段
  5. 获得输入流并读取数据
  6. 获得输出流并写入数据
  7. 关闭连接

打开URLConnection

通过URL类来打开一个URLConnection

当我们拿到一个URLConnection对象后,并不代表客户端已经和服务器建立了连接。只有主动调用其connect()方法才去和服务器建立连接。不过当我们调用getInputStream(),getContent(),getHeaderField()和其他要求打开连接的方法时,如果连接尚未打开,它们就会调用connect()。所以,在实际开发中我们主动调用connect()方法的机会很少。

读取服务器的数据

这里从HTTP服务器读取数据。

获取首部


HTTP响应的首部中包含了许多有用的信息,比如消息体的类型,长度,采用的压缩格式的。只有通过解析首部中的元数据,我们才能正确的解读消息体中的信息。

获取Content-Type属性

Content-Type指定了消息体的类型(text,image,video),如果是文本类型还会指定编码方式。

public String getContentType()

程序中查找charset的值来获取编码方式,并使用指定的编码方式从流中读取数据。

下面是服务器端代码,通过header方法来指定文本编码方式。并通过iconv函数将“这个一个中文测试”以gb2312编码的方式输出。

获Content-Length长度

我们可以使用URL的openStream()方法从HTTP服务器下载文本文件。但是在实际中会产生问题,即HTTP服务器并不总是会在数据发送完后就立即关闭连接。因此,客户端不知道何时停止读取。最好的做法就是读取HTTP头中的Content-Lenght来确定文件的长度,然后根据这个长度来读取相应的字节数。

public int getContentLength()

下面的代码中我们从http://www.xdysite.cn/download.php下载一个20M大小的文件。通过解析HTTP头可以获取文件具体的大小以及文件名。然后在本地创建一个同名文件,并将获取的数据写的该文件中。因为下载的是图片,我们直接使用字符流即可。

服务器端代码

其他方法

public String getContentEncoding()   获取消息体的压缩方式,一般情况下会对消息体压缩后再传输

public long getDate()                          获取文档发送时间,该时间为自1970年1月1号0点到目前为止过去的毫秒数

public long getLastModified()             获取文档的最后修改日期

public String getHeaderField(String name)  获取任意首部字段

缓存


下面的几个首部会影响客户端的缓存(针对HTTP1.1)

Cache-control

---max-age=[seconds]     从现在起数据在缓存中待的时间

---s-maxage=[seconds]   从现在起数据在共享缓存(http代理)中待的时间,会将max-age设置覆盖

---public                         该响应可以被缓存,主要是针对HTTP代理

---private                        该响应只能被浏览器缓存,不能被代理缓存

---no-cache                     该响应可以被缓存,但是客户端再次从缓存中加载该页面时,需要用ETag或Last-modified首部去验证这个页面在服务器是否发生改变

---no-store                     不能被缓存

Lost-modified                   指示资源最后一次修改的日期。客户端可以使用HEAD请求来检查这个日期。只有当本地缓存的副本早于Last-modified日期时,它才会真正执行GET来获取资源

Etag                                 对资源的唯一标识,当资源发生改变时该表示也应做出改变。客户端可以使用HEAD请求来检查这个标识,只有当本地缓存的副本的ETag与请求到的不同时,才会真正的执行GET获取资源

JAVA本身是并没有实现缓存,只是对外提供了接口。至于缓存具体的实现方式需要用户自己去实现。与缓存有关的类是ResponseCache

通过该类可以安装系统级缓存。系统级缓存是一个共享缓存,且是唯一的一个。即所有请求过的URL都放在这个缓存管理器中被统一管理。当通过该类安装了缓存后,只要系统尝试加载一个新的URL时,它首先会在这个缓存中查找。如果缓存中返回了所要的内容,URLConnection就不需要与远程服务器连接了。如果没有找到,则会连接服务器下载数据。完成之后,它会把这个响应放到缓存中,使得下一次加载这个URL时,可以很快从缓存中得到这个内容。

public abstract class ResponseCache

ResponseCache是一个抽象类,它有两个抽象方法需要用户去实现。

public abstract CacheResponse get(URI uri, String rqstMethod, Map<String,List<String>> rqstHeaders)

public abstract CacheRequest put(URI uri, URLConnection conn)

get方法是从缓存取数据,它返回一个CacheResponde对象。该对象中包含了一个InputStream流,这样系统可以从该流中读取数据,然后返回给用户。put方法是往缓存中放入数据,它返回的是一个CacheRequest。该对象中包含了一个OutputStream,系统可以将从服务器获得的数据通过该流写到一个具体的地方(可以是文件可以是内存,这个需要通过我们自己实现的CacheRequest类来制定)

为了实现这两个方法需要实现CacheRequest类和CacheResponse类。下面是一个具体的例子来实现HTTP缓存。我们将会在内存中开辟一块地方作为缓存使用。

实现自己的CacheRequest类

该类用于缓存数据,将来的从服务器获取的数据都会放到该类中

实现自己的CacheResponsel类

该类主要是记录响应头和缓冲区的引用

实现MemoryCache类

class MemoryCache extends ResponseCache {
//创建容器来管理缓冲区
private final Map<URI, SimpleCacheResponse> responses
= new ConcurrentHashMap<>();
//缓冲区最大缓存URL的数量
private final int maxEntries;
</span><span style="color: #0000ff">public</span><span style="color: #000000"> MemoryCache(){
</span><span style="color: #0000ff">this</span>(100<span style="color: #000000">);
} </span><span style="color: #0000ff">public</span> MemoryCache(<span style="color: #0000ff">int</span><span style="color: #000000"> i) {
maxEntries </span>=<span style="color: #000000"> i;
} </span><span style="color: #008000">//</span><span style="color: #008000">从缓冲区读数据</span>

@Override

public CacheResponse get(URI uri, String rqstMethod,

Map<String, List<String>> rqstHeaders) throws IOException {

//如果是GET方法则去检查缓存

if ("GET".equals(rqstMethod)) {

//根据URI来获取response对象

SimpleCacheResponse response = responses.get(uri);

//有缓存对象但是已经过期,则将其从缓冲区删除并返回NULL

if (response != null && response.isExpired()) {

responses.remove(response);

response = null;

}

return response;

} else

return null;

}

</span><span style="color: #008000">//</span><span style="color: #008000">往缓冲区放数据</span>

@Override

public CacheRequest put(URI uri, URLConnection conn) throws IOException {

//检查缓存区是否达到上限

if(responses.size() >= maxEntries)

return null;

//检查是否可以缓存

CacheControl control = new CacheControl(conn.getHeaderField("Cache-Control"));

if(control.isNoCache())

return null;

else if (conn.getDoOutput()) //POST方法不缓存

return null;

//创建request对象来作为缓存

SimpleCacheRequest request = new SimpleCacheRequest();

//创建response对象并将其与request对象绑定

SimpleCacheResponse response = new SimpleCacheResponse(request, conn, control);

//将URI与response绑定

responses.put(uri, response);

//返回request对象,因为要将服务器数据写到缓存中

return request;

}

}

测试类

在测试类中,我们设置了缓存策略,然后向服务器发起了两次请求。下面是服务器的日志记录

在日志记录中我们看出只有一条请求,这是因为第一次缓存中没有数据,所以需要去服务器拿数据。而第二次请求发现同样的资源已经被缓存过了,所以只需要从缓存中直接获取即可。

URLConnection类中的setDefaultUseCaches方法可以设置对于当前的URL是否使用缓存。

URLConnection类介绍的更多相关文章

  1. URLConnection类详解-转

    转-http://www.cnblogs.com/shijiaqi1066/p/3753224.html 1. URLConnection概述 URLConnection是一个抽象类,表示指向URL指 ...

  2. CYQ.Data.Orm.DBFast 新增类介绍(含类的源码及新版本配置工具源码)

    前言: 以下功能在国庆期就完成并提前发布了,但到今天才有时间写文介绍,主要是国庆后还是选择就职了,悲催的是上班的地方全公司都能上网,唯独开发部竟不让上网,是个局域网. 也不是全不能上,房间里有三台能上 ...

  3. MediaRecorder类介绍

    audiocallbackvideojavadescriptorencoding 目录(?)[+] 找到个MediaRecorder类介绍和大家分享一下. Mediarecorder类在官网的介绍和在 ...

  4. Object类介绍

    一.Object类介绍

  5. istringstream、ostringstream、stringstream 类介绍 .

    istringstream.ostringstream.stringstream 类介绍 . 转自:http://www.cnblogs.com/gamesky/archive/2013/01/09/ ...

  6. URLConnection类详解

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/SJQ. http://www.cnblogs.com/shijiaqi1066/p/3753224.html ...

  7. C#中的Dictionary字典类介绍

      Dictionary字典类介绍 必须包含名空间System.Collection.Generic    Dictionary里面的每一个元素都是一个键值对(由二个元素组成:键和值)    键必须是 ...

  8. POI 导出导入工具类介绍

    介绍: Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. .NET的开发人员则可以利用NPOI (POI ...

  9. Android Paint类介绍以及浮雕和阴影效果的设置

    Paint类介绍 Paint即画笔,在绘制文本和图形用它来设置图形颜色, 样式等绘制信息. 1.图形绘制 setARGB(int a,int r,int g,int b); 设置绘制的颜色,a代表透明 ...

随机推荐

  1. HTML5移动端图片左右切换动画

    插件描述:HTML5移动端图片左右切换动画 小海今天要给大家分享一款很不错的图片左右切换焦点图动画,并且支持移动端触摸滑动.功能上,这款HTML5图片播放器支持鼠标滑动.手机端触摸滑动以及自动播放.外 ...

  2. iOS 修改状态栏字体的颜色

    在实际开发中,状态栏有时,需要我们自己设置: 比如: 默认状态栏 假如我们开发的view是黑色的,那么效果如图: 状态栏是白底黑字,下面的view是黑底? 这样子真的好吗?说好的和谐社会呢?说好的开发 ...

  3. SharePoint 2013 激活标题字段外的Menu菜单

    前言 SharePoint 有个很特别的字段,就是标题(Title)字段,无论想要链接到项目,还是弹出操作项目的菜单,都是通过标题字段,一直以来需要的时候,都是通过将标题字段改名进行的. 其实,Sha ...

  4. Android 手机卫士--设置密码对话框

    本文实现初次设置密码验证过程,首先实现如下效果 本文地址:http://www.cnblogs.com/wuyudong/p/5939823.html,转载请注明出处. 布局如下: <?xml ...

  5. 我的Android第五章:通过Intent实现活动与活动之间的交互

    Intent在活动的操作 作用: Itent是Android程序中各个组件直接交换的一个重要方式可以指定当前组件要执行任务同时也可以给各个组件直接进行数据交互              同时Inten ...

  6. Cucumber测试驱动开发

     Cucumber是一种BDD实践开发工具,属于敏捷开发的组成部分.      在敏捷开发中,对用户进行需求分析时,不是像传统的P&D的开发方式,首先编写大量的用户需求分析文档,而是通过一个个 ...

  7. 课程上线 -“新手入门 : Windows Phone 8.1 开发”

    经过近1个月的准备和录制,“新手入门 : Windows Phone 8.1 开发”系列课程已经在Microsoft 虚拟学院上线,链接地址为:http://www.microsoftvirtuala ...

  8. MySQL ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)的真正原因

    在博客Linux mysql 5.6: ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: N ...

  9. Python基础之面向对象

    一.面向对象概述 面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 面向过程 ...

  10. OpenStack 通用设计思路 - 每天5分钟玩转 OpenStack(25)

    API 前端服务 每个 OpenStack 组件可能包含若干子服务,其中必定有一个 API 服务负责接收客户请求. 以 Nova 为例,nova-api 作为 Nova 组件对外的唯一窗口,向客户暴露 ...