URLConnection

1URLConnection

首先URLConnection是一个抽象类,表示指向URL指定资源的活动连接URLConnection有两个不同但相关的用途,首先,与URL类相比,它对服务器(特别是HTTP服务器)的交互提供了更多的控制。URLConnection可以检查服务器发送的首部,并相应地做出响应。它可以设置客户端请求中使用的首部字段。最后,URLConnection可以用POSTPUT和其他HTTP请求方法向服务器发回数据。其次URLConnection类是java的协议处理器机制的一部分,这个机制还包括URLStreamHandler类。协议处理器的思想很简单:它们将处理协议的细节和处理特定数据类型分开,提供相应的用户接口,并完成完整web浏览器所完成的其他操作。基类URLConnection是抽象类,要实现一个特定的协议,就要编写一个子类。这些子类可以在运行时由应用程序加载。

使用步骤(但并不一定执行所有这些步骤):

(1)构造一个URL对象。

(2)调用URL对象的openConnection()获取一个对应该URLURLConnection对象。

(3)配置这个URLConnection

(4)读取首部字段。

(5)获得输入流并读取数据。

(6)获得输出流并写入数据。

(7)关闭连接。

 

2URLConnection 类仅有的一个构造函数为保护类型

protected URLConnection(URL url);

因此,除非派生该类来处理新的URL类型(即编写一个协议处理器),否则要通过调用URL类的openConnection()方法来创建这样一个对象。URLConnection类声明为抽象类。不过,除了一个方法外,其余方法都已经实现。覆盖这个类的其他方法很方便或者可能很有必要。必须由子类实现的这个方法是connect(),它建立与服务器的连接,因而依赖于服务器类型(HTTP,FTP等)。例如,sun.net.www.protocol.file.FileURLConnectionconnect()方法将URL转换为适当目录中的一个文件名,创建该文件的MIME信息,然后打开一个指向该文件的缓冲FileInputStreamsun.net.www.protocol.http.HttpURLConnectionconnect()方法会创建一个sun.net.www.http.HttpClient()对象,由它负责连接服务器。这里采用的是策略模式:URLConnection是一个抽象策略类,包含一个抽象方法connect(),其具体策略实现类主要有FileURLConnection类、HttpURLConnection类。URL为上下文类,保持一个URLConnection类的引用,通过openConnection()得到URLConnection类的对象。

3、读取服务器的数据下面是使用URLConnection 对象从一个URL获取数据所需的最起码的步骤:

(1)构造一个URL对象

(2)调用这个对象的openConnection()方法,获取对应的URLConnection对象

(3)调用这个URLConnection getInputStream()方法

(4)使用通常的流API读取输入数据

import java.io.BufferedInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.Reader;

import java.net.MalformedURLException;

import java.net.URL;

import java.net.URLConnection;

 

//从服务器读取数据

public class SourceViewer2 {

 

public static void main(String[] args) {

// TODO Auto-generated method stub

 

if(args.length > 0){

try{

//打开URLConection进行读取

URL u = new URL(args[0]);

URLConnection uc = u.openConnection();

try(InputStream raw = uc.getInputStream()){//自动关闭

InputStream buffer = new BufferedInputStream(raw);

//InputStreat串联到一个Reader

Reader reader = new InputStreamReader(buffer);

int c;

while((c = reader.read()) != -1){

System.out.println((char)c);

}

}

}catch(MalformedURLException ex){

System.out.println(args[0] + " is not a parseable URL");

}catch(IOException ex){

System.out.println(ex);

}

}

}

}

对于这个例子中这样一个简单的输入流,RULURLConnection之间的区别并不明显。这两个类的最大不同在于:URLConnection提供了对HTTP首部的访问;URLConnection可以配置发送给服务器的请求参数;URLConnection除了读取服务器数据外,还可以向服务器写数据。

 

 

4、读取指定的首部的字段(读取服务器发送给客户端的首部信息)

Content-type: public String getContentType(); 该方法返回响应主题的MIME内容型,egContent-type text/html;charset=UTF-8;

Content-length: public int getContentLength()public int getContentlengthLong()返回一个long类型); 该方法主要表明内容共有多少个字节 ;

http连接读取二进制文件的一般过程:

import java.io.BufferedInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.net.MalformedURLException;

import java.net.URL;

import java.net.URLConnection;

 

public class BinarySaver {

 

public static void main(String[] args) {

for(int i = 0; i < args.length; i++){

try{

URL root = new URL(args[i]);

saveBinaryFile(root);

}catch(MalformedURLException ex){

System.err.println(args[i] + " is not URL I understand.");

}catch (IOException ex) {

System.err.println(ex);

}

}

}

public static void saveBinaryFile(URL u) throws IOException{

URLConnection uc = u.openConnection();

String contentType = uc.getContentType();

int contentLength = uc.getContentLength();

if(contentType.startsWith("text/") || contentLength == -1){

throw new IOException("This is not a binary file.");

}

try(InputStream raw = uc.getInputStream()){

InputStream in = new BufferedInputStream(raw);

byte[] data = new byte[contentLength];

int offset = 0;

while(offset < contentLength){

int bytesRead = in.read(data, offset, data.length - offset);

if(bytesRead == -1){

//读取文件末尾

break;

}

offset += bytesRead;

}

//注意读取文件是否中断

if(offset != contentLength){

throw new IOException("Only read " + offset

 + " bytes; Expected " + contentLength + "bytes");

}

String filename = u.getFile();

filename = filename.substring(filename.lastIndexOf("/") + 1);

try(FileOutputStream fout = new FileOutputStream(filename)){

fout.write(data);

fout.flush();

}

}

}

}

 

Content-encoding: public String getContentEncoding();该方法主要是指出内容是如何编码的,与字符编码不同;

Date: public long getDate(); 放回一个long类型,指出文档何时发送,距197011日子夜后过去了多少毫秒

Expires: public long getExpiration(); 有些文档有基于服务器的过期日期,指示应当何时从缓存中删除文档,并从服务器重新下载。

Last-modified: public long getLastModified(); 返回文档的最后修改日期

5、获取任意首部字段,仅仅对以上方法的封装

String getHeaderField(String name);返回指定首部字段的值,不要假定getHeaderField返回的值一定有效,必须进行检查确保它是否为null.

String getHeaderFieldKey(int n);//返回第n个首部字段的键。请求方法的本身是第0个首部,它的键为null。即第一个首部的编号为1.

String getHeaderField(int n);//返回第n个首部字段的值。在HTTP中,包含请求方法的路径和起始行是第0个首部字段,实际的首部字段编号为1.

long getHeaderFieldDate(String name,long default);//该方法首先获取由name参数指定的首部字段,然后尝试将这个字符串转换为一个long,指示从197011日子夜后经过的毫秒数。

int getHeaderFieldInt(String name,int default);//该方法获取首部name的值,尝试将其转换为int

6、缓存

Web浏览器的缓存默认情况下认为使用GET通过HTTP访问的页面可以缓存,也应当缓存。使用HTTPS或者POST访问的页面通常不缓存。HTTP可以针对首部信息作出如下调整进行缓存:

Expires首部:(主要针对HTTP1.0)指示可以缓存这个资源的表示,直到指定时间为止。

Cache-control首部(HTTP1.1)提供了细粒度的缓存策略:

----max-age=[seconds]:从现在直到缓存项过期之前的秒数。

----s-maxage=[seconds]:从现在起,直到缓存项在共享缓存中过期之前的秒数。私有缓存可以将缓存保存更长时间。

----public:可以缓存一个经过认证的响应。否则已认证的响应不能缓存。

----private:仅单个用户缓存可以保存响应,而共享缓存不应保存。

----no-cahce:这个策略的作用与名字不太一致。缓存项依然可以缓存,不过客户端在每次访问时要用一个EtagLast-Modified首部重新验证响应的状态。

----no-store:无论如何不缓存。

如果Cache-controlExpires首部都出现,Cache-control会覆盖Expires。服务器可以在一个首部中发送多个Cache-control首部,只要它们没有冲突。

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

Etag首部(HTTP1.1)是资源改变时这个资源的唯一标识。客户端可以使用一个HEAD请求来检查这个标识符,只有当本地缓存的副本有一个不同的Etag时,它才会真正的执行GET请求来获取资源。

 

根据这个信息,客户端可以充分加以利用,如果本地缓存中有这个资源的一个表示,而且还没有到它的过期时间,那么可以直接使用这个资源,无需与服务器交互。

如果本地缓存中有这个资源的一个表示,不过已经到它的过期时间,在完成完整的GET之前,可以检查服务器的HEAD首部,查看资源是否已经改变。

7、javaWeb缓存

关于缓存的实现具体看这篇博客:http://blog.youkuaiyun.com/qq_25605779/article/details/70219717

 

8、配置连接

protected URL url;

protected boolean doInput = true;

protected boolean doOutput = false;

protected boolean allowUserInteraction = defaultAllowUserInteraction;

protected boolean useCaches = defaultUseCaches;

protected long ifModifiedSince = 0;

protected boolean connected = flase;

由于以上字段都是保护字段,所以他们的值要通过相应的设置方法和获取方法来访问和修改:get set方法。并且只能在URLConnection连接之前修改这些字段(试图从连接读取内容或首部之前)。对于设置字段的方法,如果调用这些方法时连接已经打开,大多数方法会抛出一个IllegalStateException异常。一般情况下,只能在连接打开前设置URLConnection对象的属性。

还有一些获取方法和设置方法定义了所有URLConnection实例的默认行为。它们包括:

public boolean  getDefaultUseCaches()

public void  setDefaultUseCaches(boolean defaultUseCaches)

public static void setDefaultAllowUserInteraction(boolean defaultAllowUserInteraction)

public static boolean  getDefaultAllowUserInterfaction();

public static FileNameMap getFileNameMap()

public static void setFileNameMap(FileNameMap map)

这些方法可以在任何时候调用,新的默认值只应用于设置这些新默认值之后构造的URLConnection对象。

9、配置客户端请求HTTP首部(向服务器发送首部信息)

在打开服务器与客户端连接之前,使用setRequestProperty()方法为HTTP首部增加首部字段:

public void setRequestRoperty(String name, String value)

增加另外一个属性值,需要使用addRequestProperty()方法

public void  addRequestProperty(String name, String value)

查看URLConnection中的首部

public String getRequestProperty(String name)

获取连接的所有请求的属性并作为一个Map返回:

public Map<String,List<String>> getRequestProperties()

 

10、向服务器写数据

有时需要向URLConnection写入数据,例如,使用postweb服务器提交表单,或者使用put上传文件。getOutputStream()方法返回一个OutputStream,可以用来写入数据给服务器:

public OutputStream getOutputStream()

由于在默认情况下不允许输出,所以在请求输出流之前必须调用setDoOutputtrue)。

11HttpURLConnection

HttpURLConnection类是URLConnection的一个抽象子类,它提供了另外一些方法,在处理http URL时尤其有帮助。具体地,它包含的方法可以获得和设置请求方法、确定是否重定向、获得响应码和消息,以及确定是否使用了代理服务器。等

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值