URLConnection是一个抽象类,表示指向URL指定资源的活动连接。URLConnection有两个不同但相关的用途:
直接使用URLConnection类的程序遵循以下基本步骤:
并不一定执行所有这些步骤。看你需不需要!
URLConnection类仅有的一个构造函数为保护类型:
protected URLConnection(URL url)
try {
URL url = new URL("http://www.baidu.com");
URLConnection connection = url.openConnection();
//从URL读取。。。
} catch (Exception e) {
// TODO: handle exception
}
下面是使用URLConnection对象从一个URL获取数据所需的最起码的步骤:
getInputStream()方法返回一个通用InputStream,可以读取和解析服务器发送的数据:
public class Test {
public static void main(String[] args) {
try {
//打开URLConnection进行读取
URL url = new URL("http://www.baidu.com");
URLConnection connection = url.openConnection();
try (InputStream in = connection.getInputStream()){ //带资源的try-catch语句。自动关闭
InputStream buffer = new BufferedInputStream(in);
//将InputStream串链到一个Reader
Reader reader = new InputStreamReader(buffer);
int c;
while ((c = reader.read())!= -1) {
System.out.print((char)c);
}
} catch (MalformedURLException e) {
}
} catch (IOException e) {
}
}
}
运行:
URL和URLConnection这两个类最大的不同在于:
前6个方法可以请求首部中特定的常用字段:
public String getContentType()
getContentType()方法返回响应主体的MIME内容类型。如果没有提供内容类型,它不会抛出异常,而是返回null;
public int getContentLength()
getContentLength()方法告诉你内容中有多少字节。如果没有Content-Length首部,getContentLength()就返回-1;
public long getContentLengthLong()--------Java7增加的
与getContentLength()类似,只不过它会返回一个long而不是int,这样就可以处理更大的资源;
public String getContentEncoding()
getContentEncoding()方法返回一个String,指出内容是如何编码的。如果发送的内容没有编码,这个方法就返回null;
public long getDate()
getDate()方法返回一个long,指出文档何时发送;
public long getExpiration()
有些文档有基于服务器的过期日期,指示应当何时从缓存中删除文档,并从服务器重新下载。如果HTTP首部没有包括Expiration字段,getExpiration()就返回0,这表示文档不会过期,将永远保留在缓存中;
public long getLastModified()
返回文档的最后修改日期;
Test .java
public class Test {
public static void main(String[] args) {
try {
URL url = new URL("http://www.baidu.com");
URLConnection connection = url.openConnection();
System.out.println("Content-Type: " + connection.getContentType());
System.out.println("Content-Length: " + connection.getContentLength());
System.out.println("Content-LengthLong: " + connection.getContentLengthLong());
System.out.println("Content-encoding: " + connection.getContentEncoding());
System.out.println("Date: " + connection.getDate());
System.out.println("Expires: " + connection.getExpiration());
System.out.println("Last-modified: " + connection.getLastModified());
} catch (IOException e) {
}
}
}
public String getHeaderField(String name)
getHeaderField()方法返回指定首部字段的值。首部的名不区分大小写,也不包含结束冒号;
URL url = new URL("http://www.baidu.com");
URLConnection connection = url.openConnection();
System.out.println(connection.getHeaderField("Content-Type"));
System.out.println(connection.getHeaderField("last-modified"));
//输出
text/html
Mon, 23 Jan 2017 13:27:36 GMT
public String getHeaderFieldKey(int n)
返回第n个首部字段的键(即字段名)。请求方法本身是第0个首部,它的键为null。第一个首部即编号为1:
System.out.println(connection.getHeaderFieldKey(5)); //输出Content-Type
public String getHeaderField(int n)
返回第n个首部字段的值,包含请求方法和路径的起始行是第0个首部字段,实际的第一个首部编号为1:
Test.java–循环显示整个HTTP首部
public class Test {
public static void main(String[] args) {
try {
URL url = new URL("http://www.baidu.com");
URLConnection connection = url.openConnection();
for (int i = 1; ; i++) {
String header = connection.getHeaderField(i);
if (header == null) {
break;
}
System.out.println(connection.getHeaderFieldKey(i)+": "+header);
}
} catch (IOException e) {
}
}
}
//输出
Accept-Ranges: bytes
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Connection: Keep-Alive
Content-Length: 2381
Content-Type: text/html
Date: Thu, 04 Oct 2018 13:14:20 GMT
Etag: "588604ec-94d"
Last-Modified: Mon, 23 Jan 2017 13:28:12 GMT
Pragma: no-cache
Server: bfe/1.0.8.18
Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
public long getHeaderFieldDate(String name, long Default)
这个方法首先获取由name参数指定的首部字段,然后尝试将这个字符串转换为一个long;
public long getHeaderFieldInt(String name, int Default)
这个方法获取首部字段name的值,尝试将其转换为int;
默认情况下,一般认为使用GET通过HTTP访问的页面可以缓存,也应当缓存。使用HTTPS或POST访问的页面通常不应缓存。不过,HTTP首部可以对此做出调整:
。。。用到再写;
URLConnection类有7个保护的实例字段,定义了客户端如何向服务器做出请求:
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 = false;
例如,如果doOutput为true,那么除了通过这个URLConnection读取数据外,还可以将数据写入到服务器。如果useCaches为false,连接会绕过所有本地缓存,重新从服务器下载文件;
由于这些字段都是保护字段,所以它们的值要通过相应的set方法和get方法来访问和修改!
只能在URLConnection连接之前修改这些字段,对于设置字段的方法,如果调用这些方法时连接已经打开,大多数方法会抛出一个IllegalStateException异常!
protected URL url
url字段指定了这个URLConnection连接的URL。可以通过getURL()方法获取这个字段的值
public class Test {
public static void main(String[] args) {
try {
URL url = new URL("http://www.baidu.com");
URLConnection connection = url.openConnection();
System.out.println(connection.getURL()); //输出http://www.baidu.com
} catch (IOException e) {
}
}
}
protected boolean connected
如果连接已经打开,boolean字段connected为true,如果连接关闭,这个字段则为false。由于创建一个新的URLConnection对象时连接尚未打开,所以其初始值为false。没有直接读取或改变connected值的方法。不过,任何导致URLConnection连接的方法都会将这个变量设置为true;
protected boolean allowUserInteraction
有些URLConnection需要与用户交互。allowUserInteraction字段指示了是否允许用户交互。默认值为false;
protected boolean doInput
URLConnection可以用于读取服务器、写入服务器,或者同时用于读/写服务器。如果URLConnection可以用来读取,保护类型boolen字段doInput就为true,否则为false;默认为true!
protected boolean doOutput
如果URLConnection可以用于写入,保护类型boolen字段doOutput就为true,否则为false;默认为false!
protected long ifModifiedSince
protected boolean useCaches
useCaches变量确定了是否可以使用缓存。默认值为true,表示将使用缓存;false表示不使用缓存 !!
有4个方法可以查询和修改连接的超时值。也就是说,底层socket等待远程服务器的响应时,等待多长时间后会抛出SocketTimeoutException异常:
//控制socket等待建立连接的时间
public void setConnectTimeout(int timeout)
public int getConnectTimeout()
//控制输入流等待数据到达的时间
public void setReadTimeout(int timeout)
public int getReadTimeout()
都以毫秒为单位。都将0解释为永远不超时。如果超时值为负数,两个设置方法都会抛出IllegalArgumentException异常;
每个URLConnection会在首部默认设置一些不同的名–值对。打开连接前,可以使用setRequestProperty()方法为HTTP首部增加首部字段:
//只能在连接打开之前使用。如果连接已经打开,它将抛出一个IllegalArgumentException异常;getRequestProperty()方法返回这个
//URLConnection所用HTTP首部中指定字段的值
public void setRequestProperty(String key, String value)
HTTP允许一个指定名字的属性有多个值。在这种情况下,各个值用逗号隔开;
要增加另外一个属性值,需要使用addRequestProperty()方法:
public void addRequestProperty(String key, String value)
如果出于某种原因需要查看URLConnection中的首部,有一个标准的获取方法:
public String getRequestProperty(String key)
Java还提供了一个方法,可以获得连接的所有请求属性并作为一个Map返回:
public Map> getRequestProperties() //键是首部名,值是属性值列表
有时你需要向URLConnection写入数据,例如,使用POST向Web服务器提交表单,或者使用PUT上传文件。
getOutputStream()方法返回一个OutputStream,可以用来写入数据传送给服务器:
public OutputStream getOutputStream()
由于URLConnection在默认的情况下不允许输出,所以在请求输出流之前必须调用setDoOutput(true)。为一个HTTP URL将doOutput设置为true时,请求方法将由GET变为POST;
public static void main(String[] args) {
try {
URL url = new URL("http://www.baidu.com");
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
OutputStream out = connection.getOutputStream();
OutputStream buff = new BufferedOutputStream(out);
OutputStreamWriter writer = new OutputStreamWriter(buff);
writer.write("name=yd&sex=man");
writer.flush();
writer.close();
} catch (IOException e) {
}
}
java.net.HttpURLConnection类是URLConnection的抽象子类。它提供了另外一些方法,在处理http URL时尤其有帮助;
由于这个类是抽象类,唯一的构造函数是保护类型的,所以不能直接创建HttpURLConnection的实例:
URL url = new URL("http://www.baidu.com");
URLConnection connection = url.openConnection();
HttpURLConnection http = (HttpURLConnection) connection;
或者可以跳过一个步骤:
URL url = new URL("http://www.baidu.com");
HttpURLConnection http = (HttpURLConnection) url.openConnection();
默认情况下,HttpURLConnection会使用GET方法。不过,可以用setRequestMethod()来改变请求方法:
public void setRequestMethod(String method) throws ProtocolException
这个方法的参数应当是以下7个字符之一:
如果使用其他方法,就会抛出java.net.ProtocolException异常,这是IOException的一个子类;
HTTP1.1支持持久连接,允许通过一个TCP socket发送多个请求和响应。HttpURLConnection类透明地支持HTTP Keep-Alive,除非显式将其关闭。一旦知道与一个特定主机的会话结束,disconnect()方法允许客户端断开连接:
public abstract void disconnect()
如果这个连接上还有打开的流,disconnect()将关闭这些流。不过,反过来并不成立。关闭一个持久连接上的流时,并不会关闭这个socket并断开连接;
通常响应消息中我们只需要数字响应码。HttpURLConnection有一个getResponseCode()方法,会以int返回这个响应码:
public int getResponseCode() throws IOException
响应码后面的文本字符串称为响应信息。可以由一个getResponseMessage()方法返回:
public String getResponseMessage() throws IOException
重定向
默认情况下,HttpURLConnection会跟随重定向。不过,HttpURLConnection有两个静态方法,允许你确定是否跟随重定向:
public static boolean getFollowRedirects()
public static void setFollowRedirects(boolean set)
如果跟随重定向,getFollowRedirects()方法就会返回true,否则返回false。当参数为true时,setFollowRedirects()会让HttpURLConnection对象跟随重定向。当参数为false,则会阻止HttpURLConnection对象跟随重定向。
代理
usingProxy()方法可以指定某个HttpURLConnection是否通过代理服务器:
public abstract boolean usingProxy()
如果使用了代理,返回true,否则返回false;
以上只是学习所做的笔记!!!
书籍:Java网络编程