Android网络编程HttpURLConnection
大部分andriod应用需要与服务器进行数据交互,HTTP、FTP、SMTP或者是直接基于SOCKET编程都可以进行数据交互,但是HTTP必然是使用最广泛的协议。
本文并不针对HTTP协议的具体内容,仅探讨android开发中使用HTTP协议访问网络的两种方式——HttpURLConnection和HttpClient。
1、标准Java接口(java.NET) ----HttpURLConnection,可以实现简单的基于URL请求、响应功能;
2、Apache接口(org.appache.http)----HttpClient,使用起来更方面更强大。一般来说,用这种接口。但它它是基于第一种底层实现的。
URL请求的类别
分为二类,GET与POST请求。二者的区别在于:
1、 get请求可以获取静态页面,也可以把参数放在URL字串后面,传递给servlet,
2、post与get的不同之处在于post的参数不是放在URL字串里面,而是放在http请求的正文内。
HttpURLConnection
HttpURLConnection继承自URLConnection类,用它可以发送和接口任何类型和长度的数据,且预先不用知道数据流的长度,可以设置请求方式get或post、超时时间。
1、获得HttpURLConnection对象
Java中可以使用HttpURLConnection来请求WEB资源。
HttpURLConnection对象不能直接构造,需要通过URL.openConnection()来获得HttpURLConnection对象,示例代码如下:
String szUrl = "http://my.csdn.net/ljheee";
URL url = new URL(szUrl);
HttpURLConnection httpUrlConnection = (HttpURLConnection)url.openConnection();
HttpURLConnection是基于HTTP协议的,其底层通过socket通信实现。如果不设置超时(timeout),在网络异常的情况下,可能会导致程序僵死而不继续往下执行。可以通过以下两个语句来设置相应的超时:
httpUrlConnection.setConnectTimeout(30000);
httpUrlConnection.setReadTimeout(30000);
2、HttpURLConnection对象设置参数
// 设定请求的方法为"POST",默认是GET
httpUrlConnection.setRequestMethod("POST");
// 设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在
// http正文内,因此需要设为true, 默认情况下是false;
httpUrlConnection.setDoOutput(true); // 设置是否从httpUrlConnection读入,默认情况下是true;
httpUrlConnection.setDoInput(true); // Post 请求不能使用缓存
httpUrlConnection.setUseCaches(false); // 设定传送的内容类型是可序列化的java对象
// (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)
httpUrlConnection.setRequestProperty("Content-type", "application/x-java-serialized-object");
// 连接,从上述url.openConnection()至此的配置必须要在connect之前完成,
httpUrlConnection.connect();
3、HttpURLConnection连接
// 此处getOutputStream会隐含的进行connect(即:如同调用上面的connect()方法,
// 所以在开发中不调用上述的connect()也可以)。
OutputStream outStrm = httpUrlConnection.getOutputStream();
4、HttpURLConnection携带数据与发送数据到服务器
// 通过outStrm构建对象输出流,以实现输出可序列化的对象,作为请求的参数
ObjectOutputStream objOutputStrm = new ObjectOutputStream(outStrm); // 向对象输出流写出数据,这些数据将存到内存缓冲区中
objOutputStrm.writeObject(new String("请求携带的数据")); //序列化对象作为请求的参数// 刷新对象输出流,将任何字节都写入潜在的流中(些处为ObjectOutputStream)
objOutputStm.flush(); // 关闭流对象。此时,不能再向对象输出流写入任何数据,先前写入的数据存在于内存缓冲区中,
// 在调用下边的getInputStream()函数时才把准备好的http请求正式发送到服务器
objOutputStm.close(); // 调用HttpURLConnection连接对象的getInputStream()函数,
// 将内存缓冲区中封装好的完整的HTTP请求电文发送到服务端。
InputStream inStrm &#61; httpUrlConnection.getInputStream(); // <&#61;&#61;&#61;注意&#xff0c;实际发送请求的代码段就在这里
5、Servlet端的开发注意点
(1) 客户端发送的POST类型的HTTP请求&#xff0c;Servlet必须实现doPost方法&#xff0c;而不能用doGet方法。
(2) 用HttpServletRequest的getInputStream()方法取得InputStream的对象&#xff0c;比如&#xff1a;
InputStream inStream &#61;httpRequest.getInputStream(); ObjectInputStreamobjInStream &#61; new ObjectInputStream(inStream); Object obj &#61;objInStream.readObject(); //获得请求携带的参数// 做后续的处理......
小结:
1、 使用HttpURLConnection的步骤是先实例化一个URL对象&#xff0c;通过URL的openConnection实例化HttpURLConnection对象。然后设置参数&#xff0c;注意此时并没有发生连接。真正发生连接是在获得流时即httpUrlConnection.getInputStream这一句时&#xff0c;这点跟TCP Socket是一样的。并非阻塞在ServerSocket.accept()而是阻塞在获取流。所以在获取流之前应该设置好所有的参数。getInputStream从Http连接中获取输入流&#xff0c;即获取服务器响应请求后&#xff0c;返回给客户端的内容都在此流中可以获得。
2、 HttpURLConnection的connect()函数&#xff0c;实际上只是建立了一个与服务器的tcp连接&#xff0c;并没有实际发送http请求。
无论是post还是get&#xff0c;http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。
3、 connect()函数会根据HttpURLConnection对象的配置值生成http头部信息&#xff0c;因此在调用connect函数之前&#xff0c; 就必须把所有的配置准备好。 在http头后面紧跟着的是http请求的正文&#xff0c;正文的内容是通过outputStream流写入的&#xff0c; 实际上outputStream不是一个网络流&#xff0c;充其量是个字符串流&#xff0c;往里面写入的东西不会立即发送到网络&#xff0c;而是存在于内存缓冲区中&#xff0c;待outputStream流关闭时&#xff0c;根据输入的内容生成http正文。 至此&#xff0c;http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候&#xff0c;就会把准备好的http请求 正式发送到服务器了&#xff0c;然后返回一个输入流&#xff0c;用于读取服务器对于此次http请求的返回信息。由于http 请求在getInputStream的时候已经发送出去了&#xff08;包括http头和正文&#xff09;&#xff0c;因此在getInputStream()函数 之后对connection对象进行设置&#xff08;对http头的信息进行修改&#xff09;或者写入outputStream&#xff08;对正文进行修改&#xff09; 都是没有意义的了&#xff0c;执行这些操作会导致异常的发生。
4、 [Android4.0后所有网络方面的操作都不能再主线程&#xff01;&#xff01;&#xff01;]在获取网页响应字符串时本文代码使用了Thread&#xff0c;在下载图片时使用了AsyncTask,可以对比其使用的异同。很明显&#xff0c;AsyncTask更加方面。在onPreExecute和onPostExecute里可以很方面的做主线程UI的事。