Java网络编程之URLConnection协议处理器

简介:

   URLConnection是一个协议处理器中的一个类,它是表示指向URL所指定的资源的活动连接。主要用于两个方面,一个是与服务器(特别是HTTP服务器)的交互,可以用来查看服务器发送的首部,设置连接的属性,设置客户端的请求的首部等。利用它也可以实现POST和PUT方法来发送数据。另一个方面是Java的协议处理器机制的一部分。所谓的协议处理器就是将处理协议的细节从处理特定数据类型中分离出,会涉及到客户端与服务器端的交互,如生成正确的请求格式,解释与数据一起返回的首部等。


获取URLConnection
   根据一个已经创建的URL来通过openConnection来打开生成一个URLConnection,虽然利用url来获取,其实内部调用的是URLStreamHandler的openConnection,该方法是一个抽象方法,它返回的URLConnection会根据协议的类型返回,倘若是一个http url则就会返回一个HTTPURLConnection。
   URL url=new URL("http://www.baidu.com");
   URLConnection uc=url.openConnection();
   此时该uc并没有连接,本地与远程主机是无法进行收发数据的,需要调用uc.connect()方法来建立连接。不过在使用getInputStream(),getHeaderField()等其它要求的时候会首先自动调用这个方法。
   利用此URLConnection可以很容易读取来自服务器端的数据,只要其getInputStream。

URL和URLConnection的区别
URLConnection提供了对于HTTP首部的访问
URLConnection可以配置客户端向服务器端发送的请求参数即首部

URLConnection可以利用POST,PUT等请求方法与服务器进行交互

利用URL与URLConnection都可以向服务器发送HTTP请求。

1,创建一个URL,传递一个字符串形式的HTTP请求,可以加上查询字符串,此时默认动作类型是get,也就是查询,从服务器返回一个资源,再通过getInputStream正式建立客户端与服务器之间的连接,将该HTTP请求发送到服务器端,建立必要的握手,由于HTTP是全双工的,此时就可以在这里面获取服务器的返回输出流。

2,通过url的opentConnection获取一个指向url地址的活动连接,初次获取的时候是没有连接的,本地和远程根本不能收发数据,也就是没有socket来连接这台主机。要利用connect()方法来在本地和远程主机之间建立一个TCP socket连接,不过一般都是在使用getInputstream自动调用这个方法,使用getInputStream才是真正的进行发送HTTP的请求消息。
读取服务器响应的首部
对于服务器响应的首部,当然这里都是以HTTP服务器响应为准,可以来获取响应中的首部字段。
Content-type,Content-length,Content-encoding,Date,Last-modified,Expires
可以利用getContentType()来获取数据的MIME类型,判断字符编码,并且以正常的格式显示出,如
 String encoding= "ISO-8859-1";//HTTP默认的编码方式
 URL u= new URL(url);
 URLConnection uc=u.openConnection();
  String type=uc.getContentType();
//获取字符编码方式
int star=type.indexOf( "charset=");
if(star!=-1)
          encoding=type.substring(star+8);
   System.out.println( "CharSet:"+encoding);
   InputStream raw=uc.getInputStream();
    Reader r= new InputStreamReader( new BufferedInputStream(raw),encoding);
利用getContentLength来获取二进制文件大小,从而来下载文件
URLConnection uc=url.openConnection();
   String contentType=uc.getContentType();
int contentLength=uc.getContentLength();
if(contentType.startsWith( "text/")||contentLength==-1)
   {
throw new IOException( "This is not a binary file");
   }

   InputStream raw= new BufferedInputStream(uc.getInputStream());
byte[] data= new byte[contentLength];

int bytesRead=0;
int offset=0;
while(offset<contentLength)
   {
     bytesRead=raw.read(data, offset, contentLength);
if(bytesRead==-1) break;
     offset+=bytesRead;
   }

   raw.close();

if(offset!=contentLength)
   {
throw new IOException( "Only read "+offset+  "bytes;Expected "+contentLength+ " bytes");
   }

//根据URL中获取文件路径的名,将获取的流写入到本地
   String file=url.getFile();
int start=file.lastIndexOf( "/");
   String filename=file.substring(start+1);

   FileOutputStream fout= new FileOutputStream(filename);
   fout.write(data);
   fout.flush();
   fout.close();
getHeaderField(String name);可以根据指定首部名来不区分大小写获取该名对应的值
getHeaderFieldKey(int n)和getHeaderField(int n)依此返回首部中的名和值,很有用
     URL u= new URL(url);
     URLConnection uc=u.openConnection();

for( int j=1;;j++)
     {
       String header=uc.getHeaderField(j);
if(header== null) break; //skip the loop
       System.out.println(uc.getHeaderFieldKey(j)+ ":"+header);
     }

配置连接
所谓的配置主要就是定义了客户端如何向服务器做出请求。
一般客户端在默认情况下doInput为true,表示可以接受来自服务器端发送的数据,这些必须在URLConnection连接之前设置。如果想要利用POST和PUT进行交互就必须要设置doOutpu为true,默认是false

配置客户端发送的HTPP首部
客户端进行服务器访问的时候,有些协议需要加上首部,配置一些名值对,可以通过setRequestProperty(name,value)设置,多个值之间利用逗号隔开。

客户端利用POST来发送数据
package com.urlconnection;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.net.URLConnection;

//模拟表单提交处理
public class FormPoster {

private URL url;
private QueryString query= new QueryString();

//必须要保证是http协议
public FormPoster(URL url)
 {
if(!url.getProtocol().toUpperCase().startsWith( "HTTP"))  
           {
throw new IllegalArgumentException( "Posting only works for http urls");
           }
this.url=url;
 }

public void add(String name,String value)
 {
   query.add(name, value);
 }

public URL getURL()
 {
return this.url;
 }

public InputStream post() throws IOException
 {
   URLConnection uc=url.openConnection();
   uc.setDoOutput( true);
   Writer out= new OutputStreamWriter(uc.getOutputStream(), "ASCII");
//POST行,Content-type和Content-length是由URLConnection发送的
//只需要发送数据即可
   out.write(query.toString());
   out.write( "\r\n\r\n");
   out.flush();
   out.close();

return uc.getInputStream();
 }

public static void main(String[] args) {
// TODO Auto-generated method stub
   String u= "http://www.baidu.com";
   URL url=null;
try{
       url=new URL(u);
   }catch(IOException e)
   {
   }
                FormPoster poster=new FormPoster(url);
                poster.add("hawk""fdafda");
                poster.add("good morning""fdafa");

try{
                   InputStream in=poster.post();

//读取响应
                   InputStreamReader r=new InputStreamReader(in);
int c;
while((c=r.read())!=-1)
                   {
                    System.out.print((char)c);
                   }
                   in.close();
                }catch(IOException ex)
                {
                   System.err.println(ex);
                }
 }

}

HTTPURLConnection
这个是一个专门操作http URL的类,继承子URLConnection,主要有7个请求的方法
利用setRequestMethod(String method)设置不同的请求方法,默认是get,区分大小写
GET 从服务器端获取数据
POST 向服务器端提交表单
PUT 上传文件至服务器
HEAD , 获取服务器端响应的头部
OPTIONS , 查询服务器支持哪些请求方法
DELETE , 删除服务器中的文件
TRACE 服务器返回客户端发送的HTTP首部,用于检测代理服务器对HTTP首部进行怎样修改
服务器响应的格式如下:
HTTP/1.1 200 OK
...
这个类添加了两个方法
getResponseMessage()获取响应码对应的消息,如OK
getResponseCode()获取响应码,如200

协议处理器
   协议处理器主要就是根据URL中的协议来找到合适的协议处理器来进行客户端与服务器端的交互。主要涉及四个类,具体类URL,抽象类URLConnection和URLStreamHandler,以及接口URLStreamHandlerFactory。协议处理器的流处理器总是根据指定的协议找到最适合的URLConnection
   要想自己建立协议处理器,需要编写两个 URLConnection和URLStreamHandler的子类,然后创建一个 URLStreamHandlerFactory。
URLConnection子类主要处理与服务器交互,将服务器发送的数据转换为InputStream,将客户端发送的所有数据转换为OutputStream。 URLStreamHandler子类主要将URL的字符串表示解析为各个部分,用这些部分来设置URL对象的各个部分,并且创建一个理解次URL协议的URLConnection。

协议处理器的基本流程如下
1 程序先利用字符串构建某一个协议的URL对象,在创建URL模式中,只会验证是否识别URL模式,而不会对其格式的正确性进行检查
2 构造函数利用所传递的参数来确定URL的协议部分,如http
3 URL()构造函数以如下方式尝试进行找到给定的 URLStreamHandler
  a 如果以前使用过此协议,从缓存中获取 URLStreamHandler
  b 否则,若设置了 URLStreamHandlerFactory,将此字符串传递给工厂
  c 若两个都没有,则尝试实例化一个位于java.protocol.handler.pkgs属性列出的                  protocol.Handler的 URLStreamHandler
  d 如果实例化失败,就尝试实例化一个位于sun.net.www.protocol中的 protocol.Handler            的 URLStreamHandler
  e 如果其中一个成功了,则设置属性字段handler字段。如果都不成功,则抛                        出 MalformedURLException异常
4 程序调用URL对象的openConnection方法
5 URL会根据协议让 URLStreamHandler返回一个适合于此URL的URLConnection
6 使用 URLConnection进行与远程资源的交互

URLStreamHandler解析URL中字段的过程
URL(String)-->URL(URL,String)-->URL(URL,String,String)--> URLStreamHandler.parseURL()
--> URLStreamHandler.setURL()--> URL.set();
要新建立一个 URLStreamHandler一般只需要修改openConnection方法即可,根据需要来修改parseURL
为每一个URLConnection子类重写一个connect方法,该方法包含了Socket的具体建立步骤。
再利用URLStreamHandlerFactory来注册这些流处理器



本文转自 zhao_xiao_long 51CTO博客,原文链接:http://blog.51cto.com/computerdragon/1195689
相关文章
|
2月前
|
存储 监控 安全
单位网络监控软件:Java 技术驱动的高效网络监管体系构建
在数字化办公时代,构建基于Java技术的单位网络监控软件至关重要。该软件能精准监管单位网络活动,保障信息安全,提升工作效率。通过网络流量监测、访问控制及连接状态监控等模块,实现高效网络监管,确保网络稳定、安全、高效运行。
78 11
|
3月前
|
Java 程序员
JAVA程序员的进阶之路:掌握URL与URLConnection,轻松玩转网络资源!
在Java编程中,网络资源的获取与处理至关重要。本文介绍了如何使用URL与URLConnection高效、准确地获取网络资源。首先,通过`java.net.URL`类定位网络资源;其次,利用`URLConnection`类实现资源的读取与写入。文章还提供了最佳实践,包括异常处理、连接池、超时设置和请求头与响应头的合理配置,帮助Java程序员提升技能,应对复杂网络编程场景。
93 9
|
5天前
|
安全 网络协议 Java
Java网络编程封装
Java网络编程封装原理旨在隐藏底层通信细节,提供简洁、安全的高层接口。通过简化开发、提高安全性和增强可维护性,封装使开发者能更高效地进行网络应用开发。常见的封装层次包括套接字层(如Socket和ServerSocket类),以及更高层次的HTTP请求封装(如RestTemplate)。示例代码展示了如何使用RestTemplate简化HTTP请求的发送与处理,确保代码清晰易维护。
|
3月前
|
网络协议 Java 物联网
Java网络编程知识点
Java网络编程知识点
75 13
|
3月前
|
网络协议 安全 Go
Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
【10月更文挑战第28天】Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
90 13
|
3月前
|
安全 Java API
深入探索Java网络编程中的HttpURLConnection:从基础到进阶
本文介绍了Java网络编程中HttpURLConnection的高级特性,包括灵活使用不同HTTP方法、处理重定向、管理Cookie、优化安全性以及处理大文件上传和下载。通过解答五个常见问题,帮助开发者提升网络编程的效率和安全性。
214 9
|
3月前
|
数据采集 Java API
java怎么设置代理ip:简单步骤,实现高效网络请求
本文介绍了在Java中设置代理IP的方法,包括使用系统属性设置HTTP和HTTPS代理、在URL连接中设置代理、设置身份验证代理,以及使用第三方库如Apache HttpClient进行更复杂的代理配置。这些方法有助于提高网络请求的安全性和灵活性。
110 0
|
7月前
|
网络协议 安全 Java
Java中的网络编程:Socket编程详解
Java中的网络编程:Socket编程详解
|
7月前
|
Java API 网络安全
Java网络编程入门
Java网络编程入门
|
7月前
|
网络协议 安全 Java
Java中的网络编程:Socket编程详解
Java中的网络编程:Socket编程详解

热门文章

最新文章