转一个基于http协议的访问网络的封装类,使用时只需调用
public static synchronized byte[] connect(String url, byte[] data,String method, String contentType, long lowRange, long highRange, boolean disableProxy, boolean detached)
这个函数就可以了.
------------------------------------------/** * NetConnection.java * * This code is protected under the Apache 2.0 license as mentioned in * the accompanying license.txt file. The license.txt file MUST be located * within the same folder as this NetConnection.java source file. * * The license file may also be viewed online by * visiting http://www.apache.org/licenses/ */
import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;
import javax.microedition.io.Connector;import javax.microedition.io.HttpConnection;
/** * This class provides robust network connectivity and exception handling * over an unreliable MIDP HttpConnection. * * In addition the caller may perform a combination of any of the below * functions. * * - Proxy-server thwarting * - HTTP range requests * - Thread-separated connections * * @author Jason Fuerstenberg (http://www.jay-f.jp) * @version 2004/03/15 */public final class NetConnection implements Runnable { /* * This class is implemented as a singleton since only * a single active connection is allowed. */ private static NetConnection singleton = new NetConnection(); /* * The underlying HttpConnection which is managed by this class. */ private static HttpConnection httpConn; /* * To support multi-threaded network connections a series of * pass-through members are used/shared across the class' threads. */ /* * The requested URL. * * This member serves a second purpose which is to prevent a caller * from directly calling the run() method which is public to adhere to * the Runnable interface. */ private static String url; // The HTTP method used to make the connection. private static String method; // The posted data if any. private static byte[] data; // The content type (if the method is POST) private static String contentType; // The lower bound of the requested range. private static long lowRange; // The higher bound of the requested range. private static long highRange; /* * The flag to indicate that the request should attempt to thwart * any proxy servers by appending a timestamp to the request. */ private static boolean disableProxy; /* * The flag to indicate that the connection should occur in a separate * thread. */ private static boolean detached; // The response's byte array. private static byte[] response; /* * In the event of an exception occuring in the run() method during * synchronous or asynchronous execution the exception needs to be * communicated up the main application thread's call stack. This static * member will be a reference for any exception that may have occured * and will be thrown after run() returns. * */ private static Exception exceptionPipe;
/* * The private constructor to enforce the singleton pattern * which this class implements. */ private NetConnection() { // singleton }
/** * Connects to a target URL. * * @param url The target URL * @param data The data to post (if any) * @param method HttpConnection.GET or HttpConnection.POST * @param contentType The content-type of the posted data (if any) * @param lowRange The byte offset within the requested resource from * which the response will begin. * @param highRange The last byte the response will return or 0 * if requesting the entire resource. * @param disableProxy Attempts to prevent a given server from * offering a cached proxy version of the * requested resource. * @param detached Causes the connection to occur in a thread separate * from the calling thread. This call will block until * the connection has ended. * @return A byte array containing the response from the server. * @throws IOException If a network error occured. */ public static synchronized byte[] connect(String url, byte[] data, String method, String contentType, long lowRange, long highRange, boolean disableProxy, boolean detached) throws Exception {
/* * Set all the pass-through members here. */ exceptionPipe = null; NetConnection.url = url; NetConnection.data = data; NetConnection.method = method; NetConnection.contentType = contentType; NetConnection.lowRange = lowRange; NetConnection.highRange = highRange; NetConnection.disableProxy = disableProxy; NetConnection.detached = detached;
// Preemptively try to disconnect from a previous connection! NetConnection.severConnection();
if (detached) { /* * The caller has specified that the connection should occur * in a separate, detached thread. */ Thread t = new Thread(singleton); t.start(); /* * Enforce a wait here to provide the illusion of synchronous * execution despite having the connection in another thread. */ singleton.forceWait();
} else { /* * Call run() directly without creating a thread to launch it. */ singleton.run(); } /* * Reset the URL to null to prevent direct * calling of the run() method. */ NetConnection.url = null; if (exceptionPipe != null) { /* * During the course of the connection an exception occured * and was communicated here by the exceptionPipe member. * Throw it from this location. */ throw exceptionPipe; } // successful connection, return response! return response; }
/** * Performs the actual connection logic. * The connection may occur in a separate thread from that of the caller. * * @throws IllegalStateException if called directly by any class * other than this one. */ public void run() { if (url == null) { /* * The URL is used as a means to ascertain whether or not the * caller of this method was the connect() method. Since it is * null the caller is directly calling run() so throw an exception. */ throw new IllegalStateException("Cannot invoke this method!"); }
DataOutputStream dos = null; DataInputStream dis = null; StringBuffer buffer = null; /* * IMPLEMENTATION NOTE: * * From this section on, a series of try/catch/finally statements * is used to ensure the proper flow of the connection under a * wide variety of circumstances. This seemingly verbose logic * is important for the proper exception handling and object * reclamation required to make subsequent connections * possible in the future. * * In addition, the catching of exception is not too particular * regarding the type of exception being thrown for a few reasons... * * 1. The handling of each exception type is identical * 2. Implementations may vary in which exceptions they throw * * In the interest of stability it is highly recommended to * leave this as is, even if it goes against orthodox practices. */
try {
int permissions = 0; // Setup the permissions if (HttpConnection.GET.equals(method)) { permissions = Connector.READ; } else if (HttpConnection.POST.equals(method)) { permissions = Connector.READ_WRITE; } if (disableProxy) { /* * To thwart the a given server's proxy cache * the logic will attach a query parameter to the * end of the URL with a millisecond timestamp which * will hopefully force the server to see this request as one * which has never previously occured for this client * and therefore entitled to a fresh copy of the requested * resource. */ boolean hasQueryParams = false; char[] ca = url.toCharArray();
for (int loop = 0; loop < url.length(); loop++) { if (ca[loop] == '?') { hasQueryParams = true; break; } } StringBuffer noProxyUrl = new StringBuffer(); noProxyUrl.append(url);
if (hasQueryParams) { noProxyUrl.append("&"); } else { noProxyUrl.append("?"); } noProxyUrl.append("no-proxy="); noProxyUrl.append(System.currentTimeMillis()); // timestamp /* * Reset the URL to include the "no-proxy" query * parameter. */ url = noProxyUrl.toString(); }
// Open the connection and set the request method. httpConn = (HttpConnection) Connector.open(url, permissions, true); httpConn.setRequestMethod(method);
//if (HttpConnection.GET.equals(method)) { if (permissions == Connector.READ) { // GET request if (lowRange > -1 && lowRange < highRange) { /* * The caller is requesting a specific range within * the resource. * * The logic will insert the appropriate HTTP header to * implement the request. */ StringBuffer range = new StringBuffer(); range.append("bytes="); range.append(lowRange); range.append("-"); range.append(highRange); httpConn.setRequestProperty("Range", range.toString()); } } else if (permissions == Connector.READ_WRITE) { // POST request httpConn.setRequestProperty("Content-Type", contentType); dos = httpConn.openDataOutputStream(); dos.write(data); } } catch (Exception e) { /* * An exception occured either during the opening of the connection * or during the POSTing of data. In either case the logic cannot * continue and will quit here. */ exceptionPipe = e;
if (detached) { forceNotify(); } return; } finally {
try { try { if (dos != null) { // Close the DataOutputStream. dos.close(); } } catch (Exception e) { // Failure to close the DataOutputStream! if (exceptionPipe == null) { exceptionPipe = e; if (detached) { forceNotify(); } return; } } finally { // Force the dereferencing of the DataOutputStream. dos = null; } // Get the response code. int responseCode = httpConn.getResponseCode(); if (responseCode != HttpConnection.HTTP_OK && responseCode != HttpConnection.HTTP_PARTIAL) {
/* * The response code does not match HTTP_OK (200) * or HTTP_PARTIAL (206). The logic cannot proceed to * treat the response as one holding the requested * resource and therefore will report the response code * via an exception to the caller. */ if (exceptionPipe == null) { StringBuffer errorCode = new StringBuffer(); errorCode.append("Response code from server: "); errorCode.append(responseCode); errorCode.append("/nMessage: ["); errorCode.append(httpConn.getResponseMessage()); errorCode.append("]"); exceptionPipe = new IOException(errorCode.toString()); if (detached) { forceNotify(); } return; } }
dis = httpConn.openDataInputStream();
/* * Cycle through all the bytes provided * in the response and append them to a * StringBuffer for later use. */ int ch; buffer = new StringBuffer(); while ((ch = dis.read()) != -1) { buffer.append((char) ch); }
/* * Convert the StringBuffer to an array using * the ISO-8859-1 encoding to preserve the byte * encoding of the characters. */ response = buffer.toString().getBytes("ISO8859_1"); if (detached) { forceNotify(); } /* * All OK, now returning. */ return;
} catch (Exception e) { /* * An exception occured either during the usage of the * connection object (such as a NullPointerException) or during * the reading of the data. In either case the logic cannot * continue. */ if (exceptionPipe == null) { exceptionPipe = e; if (detached) { forceNotify(); } return; } } finally { try { if (dis != null) { // Close the DataInputStream. dis.close(); } } catch (Exception e) { // Failure to close the DataInputStream! if (exceptionPipe == null) { exceptionPipe = e; if (detached) { forceNotify(); } return; } } finally { // force the dereferencing of the DataInputStream. dis = null; } try { if (httpConn != null) { // Close the HttpConnection. httpConn.close(); /* * Only dereference the HttpConnection if the * closing actually succeeded! */ httpConn = null; } } catch (Exception e) { // Failure in closing the HttpConnection! if (exceptionPipe == null) { exceptionPipe = e; if (detached) { forceNotify(); } return; } } } } } /* * Provides the synchronized context against the singleton's instance * for the wait() method call to properly execute. Not all implementations * of the JVM support the concept of synchronized contexts other than * that of an entire method. As such the inner call to wait must be * embedded in this synchronized method. */ private synchronized void forceWait() { try { wait(); } catch (InterruptedException ie) { // Ignore this exception ie = null; } } /* * Provides the synchronized context against the singleton's instance * for the notify() method call to properly execute. Not all * implementations of the JVM support the concept of synchronized * contexts other than that of an entire method. As such the inner * call to notify must be embedded in this synchronized method. */ private synchronized void forceNotify() { notify(); } /* * Severs an ongoing connection. */ private static void severConnection() { try { if (httpConn == null) { /* * No connection is in progress so simply return * to the caller. */ return; } // Close the connection. httpConn.close();
} catch (Exception e) { /* * If the handset's implementation of the HttpConnection * interface is solid it will not be possible for * an exception to occur. */ e = null; } finally { // Force the dereferencing of the connection. httpConn = null; } }}
