Java: Simple HTTPUrlConnection example

Java: Simple HTTPUrlConnection example

 

package ChinaCache;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

import java.net.HttpURLConnection;

 

import java.net.MalformedURLException;

import java.net.ProtocolException;

import java.net.URL;

 

public class SimpleHTTPRequest {

/**                                                                                                                                                     */

public static void main(String[] args) {

       HttpURLConnection connection = null ;

       OutputStreamWriter wr = null ;

       BufferedReader rd = null ;

       StringBuilder sb = new StringBuilder ();;

       String line = null ;

       URL serverAddress = null ;

 

       try {

            serverAddress = new URL("http://www.globalsources.com/");

            //1) open connection

            connection = (HttpURLConnection) serverAddress.openConnection();

            //2) connection settings

            connection.setRequestMethod("GET");

            connection.setDoOutput(true);

            connection.setReadTimeout(10000);

//3)connect

            connection.connect();

            //4)write data

            // get the output stream writer and write the output to the server

            // not needed in this example

            // wr = new OutputStreamWriter(connection.getOutputStream());

           // wr.write("....");

            // wr.flush();

           

            //5)read the result from the server

            rd  = new BufferedReader( new InputStreamReader(connection.getInputStream()));

            while ((line = rd.readLine()) != null ) {

                 sb.append(line + '/n' );

            }

            System. out .println(sb.toString());

            //6)close

            rd.close();

           

       } catch (MalformedURLException e) {

            e.printStackTrace();

       } catch (ProtocolException e) {

            e.printStackTrace();

       } catch (IOException e) {

            e.printStackTrace();

       } finally {

       }

}

}

 

Notes:

1.StringBuilder:

A mutable sequence of characters. This class provides an API compatible with StringBuffer , but with no guarantee of synchronization . This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.

2. HttpURLConnection 对象参数问题

1) 设置是否向 httpUrlConnection 输出,因为这个是 post 请求,参数要放在 http 正文内,因此需要设为 true, 默认情况下是 false;
httpUrlConnection.setDoOutput(true);

 

2) 设置是否从 httpUrlConnection 读入,默认情况下是 true;
httpUrlConnection.setDoInput(true);

 

3) Post 请求不能使用缓存
httpUrlConnection.setUseCaches(false);

 

4) 设定传送的内容类型是可序列化的 java 对象 ( 如果不设此项 , 在传送序列化对象时 , WEB 服务默认的不是这种类型时可能抛 java.io.EOFException)
httpUrlConnection.setRequestProperty("Content-type", "application/x-java-serialized-object");

 

5) 设定请求的方法为 "POST" ,默认是 GET
httpUrlConnection.setRequestMethod("POST");

 

6) 1)-5) 必须在 url.openConnection() 之后和 httpUrlConnection.connect() 之前完成

 

3. HttpURLConnection 写数据与发送数据问题:

1) 现在通过输出流对象构建对象输出流对象,以实现输出可序列化的对象。
   ObjectOutputStream objOutputStrm = new ObjectOutputStream(outStrm);

 

2) 向对象输出流写出数据,这些数据将存到内存缓冲区中
   objOutputStrm.writeObject(new String("
我是测试数据 "));

 

3) 刷新对象输出流,将任何字节都写入潜在的流中(些处为 ObjectOutputStream
   objOutputStm.flush();

 

4) 关闭流对象。此时,不能再向对象输出流写入任何数据,先前写入的数据存在于内存缓冲区中 , 在调用下边的 getInputStream() 函数时才把准备好的 http 请求正式发送到服务器
   objOutputStm.close();

5) 调用 HttpURLConnection 连接对象的 getInputStream() 函数 , 将内存缓冲区中封装好的完整的 HTTP 请求电文发送到服务端。
  InputStream inStrm = httpConn.getInputStream(); // <===
注意,实际发送请求的代码段就在这里

  上边的 httpConn.getInputStream() 方法已调用 , 本次 HTTP 请求已结束 , 下边向对象输出流的输出已无意义 , 既使对象输出流没有调用 close() 方法,下边的操作也不会向对象输出流写入任何数据 . 因此,要重新发送数据时需要重新创建连接、重新设参数、重新创建流对象、重新写数据、
6)
重新发送数据 ( 至于是否不用重新这些操作需要再研究 )
   objOutputStm.writeObject(new String(""));
   httpConn.getInputStream();

 

4 URL 请求的类别 : 分为二类 ,GET POST 请求。二者的区别在于:
      a:) get
请求可以获取静态页面,也可以把参数放在 URL 字串后面,传递给 servlet
      b:) post
get 的不同之处在于 post 的参数不是放在 URL 字串里面,而是放在 http 请求的正文内。

5 .其他:

   a:) HttpURLConnection connect() 函数,实际上只是建立了一个与服务器的 tcp 连接,并没有实际发送 http 请求
   
无论是 post 还是 get http 请求实际上直到 HttpURLConnection getInputStream() 这个函数里面才正式发送出去


   b:)
在用 POST 方式发送 URL 请求时, URL 请求参数的设定顺序是重中之重,对 connection 对象的一切配置(那一堆 set 函数)都必须要在 connect() 函数执行之前完成。而对 outputStream 的写操作,又必须要在 inputStream 的读操作之前。
   
这些顺序实际上是由 http 请求的格式决定的。
   
如果 inputStream 读操作在 outputStream 的写操作之前,会抛出例外:
    java.net.ProtocolException: Cannot write output after reading input.......
      
   c:) http
请求实际上由两部分组成,一个是 http 头,所有关于此次 http 请求的配置都在 http 头里面定义,一个是正文 content
    connect()
函数会根据 HttpURLConnection 对象的配置值生成 http 头部信息,因此在调用 connect 函数之前,
   
就必须把所有的配置准备好。


   d:)
http 头后面紧跟着的是 http 请求的正文,正文的内容是通过 outputStream 流写入的,
   
实际上 outputStream 不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,
   
而是存在于内存缓冲区中,待 outputStream 流关闭时,根据输入的内容生成 http 正文。
   
至此, http 请求的东西已经全部准备就绪。在 getInputStream() 函数调用的时候,就会把准备好的 http 请求
   
正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次 http 请求的返回信息。由于 http
   
请求在 getInputStream 的时候已经发送出去了(包括 http 头和正文),因此在 getInputStream() 函数
   
之后对 connection 对象进行设置(对 http 头的信息进行修改)或者写入 outputStream (对正文进行修改)
   
都是没有意义的了,执行这些操作会导致异常的发生。

4 Servlet 端的开发注意点:
a:)
对于客户端发送的 POST 类型的 HTTP 请求, Servlet 必须实现 doPost 方法,而不能用 doGet 方法。
b:)
HttpServletRequest getInputStream() 方法取得 InputStream 的对象,比如:
     InputStream inStream = httpRequest.getInputStream();
    
现在调用 inStream.available() (该方法用于 返回此输入流下一个方法调用可以不受阻塞地
    
从此输入流读取(或跳过)的估计字节数 )时,永远都反回 0 。试图使用此方法的返回值分配缓冲区,
    
以保存此流所有数据的做法是不正确的。那么,现在的解决办法是
     Servlet
这一端用如下实现:
     InputStream inStream = httpRequest.getInputStream();
     ObjectInputStream objInStream = new ObjectInputStream(inStream);
     Object obj = objInStream.readObject();
     //
做后续的处理
     //
。。。。。。
     //
。。。 。。。
    
而客户端,无论是否发送实际数据都要写入一个对象(那怕这个对象不用),如:
     ObjectOutputStream objOutputStrm = new ObjectOutputStream(outStrm);
     objOutputStrm.writeObject(new String("")); //
这里发送一个空数据
     //
甚至可以发一个 null 对象,服务端取到后再做判断处理。
     objOutputStrm.writeObject(null);
     objOutputStrm.flush();
     objOutputStrm.close();

注意 : 上述在创建对象输出流 ObjectOutputStream , 如果将从 HttpServletRequest 取得的输入流
      (
:new ObjectOutputStream(outStrm) 中的 outStrm) 包装在 BufferedOutputStream 流里面 ,
     
则必须有 objOutputStrm.flush(); 这一句 , 以便将流信息刷入缓冲输出流 . 如下 :
      ObjectOutputStream objOutputStrm = new ObjectOutputStream(new BufferedOutputStream(outStrm));
      objOutputStrm.writeObject(null);
      objOutputStrm.flush(); // <======
此处必须要有 .
      objOutputStrm.close();

 


       

========= Another article about  URLConnection ==========

Reading from and Writing to a URLConnection

The URLConnection class contains many methods that let you communicate with the URL over the network. URLConnection is an HTTP-centric class; that is, many of its methods are useful only when you are working with HTTP URLs. However, most URL protocols allow you to read from and write to the connection. This section describes both functions.

Reading from a URLConnection

The following program performs the same function as the URLReader program shown in Reading Directly from a URL .

However, rather than getting an input stream directly from the URL, this program explicitly retrieves a URLConnection object and gets an input stream from the connection. The connection is opened implicitly by calling getInputStream . Then, like URLReader , this program creates a BufferedReader on the input stream and reads from it. The bold statements highlight the differences between this example and the previous

import java.net.*;
import java.io.*;

public class URLConnectionReader {
    public static void main(String[] args) throws Exception {
        URL yahoo = new URL("http://www.yahoo.com/ ");

        

URLConnection yc = yahoo.openConnection();




        BufferedReader in = new BufferedReader(
                                new InputStreamReader(
                                 yc.getInputStream() ));

        

String inputLine;

        while ((inputLine = in.readLine()) != null)
            System.out.println(inputLine);
        in.close();
    }
}

The output from this program is identical to the output from the program that opens a stream directly from the URL. You can use either way to read from a URL. However, reading from a URLConnection instead of reading directly from a URL might be more useful. This is because you can use the URLConnection object for other tasks (like writing to the URL) at the same time.

Again, if the program hangs or you see an error message, you may have to set the proxy host so that the program can find the Yahoo server.

Writing to a URLConnection

Many HTML pages contain forms -- text fields and other GUI objects that let you enter data to send to the server. After you type in the required information and initiate the query by clicking a button, your Web browser writes the data to the URL over the network. At the other end the server receives the data, processes it, and then sends you a response, usually in the form of a new HTML page.

Many of these HTML forms use the HTTP POST METHOD to send data to the server. Thus writing to a URL is often called posting to a URL . The server recognizes the POST request and reads the data sent from the client.

For a Java program to interact with a server-side process it simply must be able to write to a URL, thus providing data to the server. It can do this by following these steps:

  1. Create a URL .
  2. Retrieve the URLConnection object.
  3. Set output capability on the URLConnection .
  4. Open a connection to the resource.
  5. Get an output stream from the connection.
  6. Write to the output stream.
  7. Close the output stream.

Here is a small servlet named ReverseServlet ( or if you prefer a cgi-bin script ). You can use this servlet to test the following example program.

The servlet running in a container reads from its InputStream, reverses the string, and writes it to its OutputStream. The servlet requires input of the form string=string_to_reverse , where string_to_reverse is the string whose characters you want displayed in reverse order.

Here's an example program that runs the ReverseServlet over the network through a URLConnection :

import java.io.*;
import java.net.*;

public class Reverse {
    public static void main(String[] args) throws Exception {

        if (args.length != 2) {
            System.err.println("Usage:  java Reverse " +

                               

"http://<location of your servlet/script>" + 
                               " string_to_reverse");
            System.exit(1);
        }

        String stringToReverse = URLEncoder.encode(args[1], "UTF-8");


        URL url = new URL(args[0]);
        URLConnection connection = url.openConnection();
        connection.setDoOutput(true);

        OutputStreamWriter out = new OutputStreamWriter(
                              connection.getOutputStream());

        

out.write("string=" + stringToReverse);
        out.close();

        BufferedReader in = new BufferedReader(
                               new InputStreamReader(
                               connection.getInputStream()));
                              
        String decodedString;


        while ((decodedString = in.readLine()) != null) {
            System.out.println(decodedString);
        }
        in.close();
    }
}

Let's examine the program and see how it works. First, the program processes its command-line arguments:

if (args.length != 2) {
    System.err.println("Usage:  java Reverse " +
                        "http://<location of your servlet/script>" +
                        " string_to_reverse");

    

System.exit(1);
}      

String stringToReverse = URLEncoder.encode(args[1], "UTF-8");

These statements ensure that the user provides two and only two command-line arguments to the program. The command-line arguments are the location of the ReverseServlet and the string that will be reversed. It may contain spaces or other non-alphanumeric characters. These characters must be encoded because the string is processed on its way to the server. The URLEncoder class methods encode the characters.

Next, the program creates the URL object, and sets the connection so that it can write to it:

URL url = new URL(args[0]);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);

The program then creates an output stream on the connection and opens an OutputStreamWriter on it:

OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());

If the URL does not support output, getOutputStream method throws an UnknownServiceException . If the URL does support output, then this method returns an output stream that is connected to the input stream of the URL on the server side--the client's output is the server's input.

Next, the program writes the required information to the output stream and closes the stream:

out.write("string=" + stringToReverse);
out.close();

This code writes to the output stream using the write method. So you can see that writing data to a URL is as easy as writing data to a stream. The data written to the output stream on the client side is the input for the servlet on the server side. The Reverse program constructs the input in the form required by the script by prepending string= to the encoded string to be reversed.

The serlvet reads the information you write, performs a reverse operation on the string value, and then sends this back to you. You now need to read the string the server has sent back. The Reverse program does it like this:

BufferedReader in = new BufferedReader(
                    new InputStreamReader(
                    connection.getInputStream()));
                              
String decodedString;

while ((decodedString = in.readLine()) != null) {

    

System.out.println(decodedString);
}
in.close();

If your ReverseServlet is located at http://foobar.com/servlet/ReverseServlet , then when you run the Reverse program using

http://foobar.com/servlet/ReverseServlet

 "Reverse Me"

as the argument (including the double quote marks), you should see this output:

Reverse Me
  reversed is:
eM esreveR

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值