在java中"模拟" XMLHttpRequest

这里所说的"模拟" 是指 : 在java中,使用类似 XMLHttpRequest 的方式来实现"同步/异步的HttpRequest"功能.


  用 java 实现一个HTTPRequest 并不难. 通过 java.net 包内提供的东东 可以很容易的实现.
  而且我们还有 apache 的 HttpClient 一类的组件可供我们使用 .
  实现 异步的HTTPRequest 当然同样简单 , 再使用一个 Thread就ok了.
  但是 使用上面的 方法 , 实现的往往只是一个 "异步的HTTPRequest"的功能而已,
  使用方式上 还是 很 java的.
 
我在这里所要介绍的 则是使用很"ajax"的方式来实现"异步的HTTPRequest"的功能.
这个 AjaxHttpRequest 类  模仿了 XMLHttpRequest 的实现,
从属性 方法 使用方式上 都尽量的和 XMLHttpRequest 接近.

利用 AjaxHttpRequest 类 可以更自然的实现 ajax请求的服务端代理 等工作.

=============================

当然 本文的技术研究的价值 也许远远大于 实用的价值. :P .


我先来举一个例子 ,  AjaxHttpRequest 类的代码&注释 在后面附上 附件中也会提供该java文件.

大家注意看代码注释 ,我要说的东西更多的都在注释里呢.

一个 用 java 来调用 google 翻译服务的例子 (利用了后面附上的 AjaxHttpRequest 类) :

Java代码

  1. /** 
  2.  * 利用这个AjaxHttpReuqest类来实现 对google translate服务的访问 . 
  3.  * 只演示了 "英-->汉"的翻译. 
  4.  * 返回的是JSON字符串,需要使用Json工具类进行转换,这个不难 就不详细举例了. 
  5.  */
  6. public static void testGoogleTranslate(String words,boolean async) throws IOException {  
  7.     Map params=new HashMap();  
  8.     params.put("q",words);  
  9.     params.put("v","1.0");  
  10.     params.put("langpair","en|zh-CN");  
  11.     String url="http://ajax.googleapis.com/ajax/services/language/translate";  
  12.     // 以上为 调用google翻译服务所需要的参数.
  13.     // 下面 是用java 来调用这个 翻译服务.
  14.     // 在 AjaxHttpRequest 类的 帮助下 我们可以使用 类似操作浏览器XHR对象的方式来 实现该功能.
  15.     // 创建 AjaxHttpRequest对象 相当于 创建 XHR对象.
  16.     // 这里的final 主要是为了"使监听器内部能够调用ajax对象"而加的.
  17.     final AjaxHttpRequest ajax=new AjaxHttpRequest();  
  18.     // 设置状态监听器,类似 XHR对象的 onreadystatechange 属性.
  19.     // 由于js 和java的本质区别 导致这里可能和 xhr有点不一样,但是应该不难理解.
  20.     ajax.setReadyStateChangeListener(  
  21.             // 监听器, 根据需求 实现onReadyStateChange方法即可.
  22.             new AjaxHttpRequest.ReadyStateChangeListener(){  
  23.                     public void onReadyStateChange() {  
  24.                         int readyState = ajax.getReadyState();  
  25.                         //判断状态 然后做出相应处理.
  26.                         if (readyState==AjaxHttpRequest.STATE_COMPLETE){  
  27.                             System.out.println( ajax.getResponseText() );  
  28.                         }  
  29.                     }             
  30.             }  
  31.     );  
  32.     // 这里就和 xhr 几乎完全一样了
  33.     ajax.open("POST", url, true);  
  34.     //这里这个send方法接受的参数是一个map ,当然AjaxHttpRequest类也提供了string的方法
  35.     ajax.send(params);  
  36. }  

    /**     * 利用这个AjaxHttpReuqest类来实现 对google translate服务的访问 .     * 只演示了 "英-->汉"的翻译.     * 返回的是JSON字符串,需要使用Json工具类进行转换,这个不难 就不详细举例了.     */    public static void testGoogleTranslate(String words,boolean async) throws IOException {        Map params=new HashMap();        params.put("q",words);        params.put("v","1.0");        params.put("langpair","en|zh-CN");        String url="http://ajax.googleapis.com/ajax/services/language/translate";                // 以上为 调用google翻译服务所需要的参数.        // 下面 是用java 来调用这个 翻译服务.        // 在 AjaxHttpRequest 类的 帮助下 我们可以使用 类似操作浏览器XHR对象的方式来 实现该功能.                    // 创建 AjaxHttpRequest对象 相当于 创建 XHR对象.        // 这里的final 主要是为了"使监听器内部能够调用ajax对象"而加的.        final AjaxHttpRequest ajax=new AjaxHttpRequest();                // 设置状态监听器,类似 XHR对象的 onreadystatechange 属性.        // 由于js 和java的本质区别 导致这里可能和 xhr有点不一样,但是应该不难理 解.        ajax.setReadyStateChangeListener(                // 监听器, 根据需求 实现onReadyStateChange方法即可.                new AjaxHttpRequest.ReadyStateChangeListener(){                        public void onReadyStateChange() {                            int readyState = ajax.getReadyState();                            //判断状态 然后做出相应处理.                            if (readyState==AjaxHttpRequest.STATE_COMPLETE){                                System.out.println( ajax.getResponseText() );                            }                        }                            }        );                // 这里就和 xhr 几乎完全一样了        ajax.open("POST", url, true);                //这里这个send方法接受的参数是一个map ,当然AjaxHttpRequest类也提供了string的方法        ajax.send(params);    }[/pre]

有了上面的功能 当页面中要使用google的翻译服务时 就不用在引入google的那些js了.
也不用担心 客户端无法访问google的情况了.



下面附上 AjaxHttpRequest类 的完整代码 ( 附件中有下载 )

Java代码

  1. package com.fins.gt.server;  
  2. import java.io.IOException;  
  3. import java.io.InputStream;  
  4. import java.io.OutputStream;  
  5. import java.io.UnsupportedEncodingException;  
  6. import java.net.HttpURLConnection;  
  7. import java.net.MalformedURLException;  
  8. import java.net.Proxy;  
  9. import java.net.URL;  
  10. import java.net.URLConnection;  
  11. import java.net.URLEncoder;  
  12. import java.util.HashMap;  
  13. import java.util.Iterator;  
  14. import java.util.LinkedHashMap;  
  15. import java.util.Map;  
  16. import java.util.StringTokenizer;  
  17. import java.util.logging.Level;  
  18. /** 
  19.  * AjaxHttpRequest ,用java 模拟 浏览器的 XMLHttpRequest 对象. 
  20.  * 目的是 用 操作浏览器中的XHR对象的 方式来处理java端的 http请求. 
  21.  *  
  22.  * @author fins 
  23.  *  
  24.  * 本类的实现借鉴了 cobra 组件的 org.lobobrowser.html.test.SimpleHttpRequest 类. 
  25.  * 可以看作是对 SimpleHttpRequest 类的一个完善和补充. 
  26.  *  
  27.  * cobra 组件是一个 Java HTML Renderer & Parser, 
  28.  * 官方网站 : http://lobobrowser.org/cobra.jsp  
  29.  */
  30. public class AjaxHttpRequest {  
  31.     // 对应 XMLHttpRequest 的5种状态.
  32.     public static final int STATE_UNINITIALIZED = 0;  
  33.     public static final int STATE_LOADING = 1;  
  34.     public static final int STATE_LOADED = 2;  
  35.     public static final int STATE_INTERACTIVE = 3;  
  36.     public static final int STATE_COMPLETE = 4;  
  37.     // 默认的 userAgent 
  38.     public static final String DEFAULT_USERAGENT = "Mozilla/4.0 (compatible; MSIE 6.0;) JavaAjax/1.0";  
  39.     // 默认的 编码 
  40.     public static final String DEFAULT_AJAX_CHARSET = "UTF-8";  
  41.     public static final String DEFAULT_HTTP_CHARSET = "ISO-8859-1";  
  42.     // 默认的 HTTP method
  43.     public static final String DEFAULT_REQUEST_METHOD = "POST";  
  44.     private int readyState;  
  45.     private int status;  
  46.     private String statusText;  
  47.     private String responseHeaders;  
  48.     private byte[] responseBytes;  
  49.     private Map responseHeadersMap;  
  50.     private Map requestHeadersMap;  
  51.     private ReadyStateChangeListener readyStateChangeListener;  
  52.     private boolean async;  
  53.     private boolean sent;  
  54.     private URLConnection connection;  
  55.     private String userAgent = DEFAULT_USERAGENT;  
  56.     private String postCharset = DEFAULT_AJAX_CHARSET;  
  57.     private Proxy proxy;  
  58.     private URL requestURL;  
  59.     protected String requestMethod;  
  60.     protected String requestUserName;  
  61.     protected String requestPassword;  
  62. /
  63. /
  64.     /** 
  65.      * 构造方法. 自动添加 XMLHttpRequest 的一些缺省头信息. 
  66.      * 如果不需要这些头信息,可在创建 AjaxHttpRequest 实例后, 
  67.      * 通过 setRequestHeader/removeRequestHeader/removeAllRequestHeaders 方法 
  68.      * 进行修改或移除.  
  69.      */
  70.     public AjaxHttpRequest() {  
  71.         requestHeadersMap = new LinkedHashMap();  
  72.         setRequestHeader("X-Requested-With", "XMLHttpRequest");  
  73.         setRequestHeader("Accept",  
  74.                 "text/javascript, text/html, application/xml, application/json, text/xml, */*");  
  75.     }  
  76.     /**  
  77.      * 类似 XMLHttpRequest 中的 readyState 属性.  
  78.      */  
  79.     public synchronized int getReadyState() {  
  80.         return this.readyState;  
  81.     }  
  82.     /** 
  83.      * 类似 XMLHttpRequest 中的 status 属性. 
  84.      */
  85.     public synchronized int getStatus() {  
  86.         return this.status;  
  87.     }  
  88.     /** 
  89.      * 类似 XMLHttpRequest 中的 statusText 属性. 
  90.      */
  91.     public synchronized String getStatusText() {  
  92.         return this.statusText;  
  93.     }  
  94.     /** 
  95.      * 类似 XMLHttpRequest 中的 setRequestHeader 方法. 
  96.      */
  97.     public void setRequestHeader(String key, String value) {  
  98.         this.requestHeadersMap.put(key, value);  
  99.     }  
  100.     /** 
  101.      * 类似 XMLHttpRequest 中的 open 方法. 
  102.      */
  103.     public void open(String method, String url, boolean async, String userName, String password)  
  104.             throws IOException {  
  105.         URL urlObj = createURL(null, url);  
  106.         open(method, urlObj, async, userName, password);  
  107.     }  
  108.     /** 
  109.      * 类似 XMLHttpRequest 中的 open 方法. 
  110.      */
  111.     public void open(final String method, final URL url, boolean async, final String userName,  
  112.             final String password) throws IOException {  
  113.         this.abort();  
  114.         Proxy proxy = this.proxy;  
  115.         URLConnection c = proxy == null || proxy == Proxy.NO_PROXY ? url.openConnection() : url  
  116.                 .openConnection(proxy);  
  117.         synchronized (this) {  
  118.             this.connection = c;  
  119.             this.async = async;  
  120.             this.requestMethod = method;  
  121.             this.requestURL = url;  
  122.             this.requestUserName = userName;  
  123.             this.requestPassword = password;  
  124.         }  
  125.         this.changeState(AjaxHttpRequest.STATE_LOADING, 0, null, null);  
  126.     }  
  127.     /** 
  128.      * 类似 XMLHttpRequest 中的 open 方法. 
  129.      * 省略部分参数的形式. 
  130.      */
  131.     public void open(String url, boolean async) throws IOException {  
  132.         open(DEFAULT_REQUEST_METHOD, url, async, null, null);  
  133.     }  
  134.     /** 
  135.      * 类似 XMLHttpRequest 中的 open 方法. 
  136.      * 省略部分参数的形式. 
  137.      */
  138.     public void open(String method, String url, boolean async) throws IOException {  
  139.         open(method, url, async, null, null);  
  140.     }  
  141.     /** 
  142.      * 类似 XMLHttpRequest 中的 send 方法. 
  143.      * 支持发送 key-value 形式的数据集合(Map). 
  144.      * 传入map参数, 自动转换成string形式 并调用 send(String) 方法发送. 
  145.      */
  146.     public void send(Map parameters) throws IOException {  
  147.         Iterator keyItr=parameters.keySet().iterator();  
  148.         StringBuffer strb=new StringBuffer();  
  149.         while (keyItr.hasNext()){  
  150.             Object key = keyItr.next();  
  151.             String keyStr = encode(key);  
  152.             String valueStr = encode(parameters.get(key));  
  153.             strb.append(keyStr).append("=").append(valueStr);  
  154.             strb.append("&");  
  155.         }  
  156.         send(strb.toString());  
  157.     }  
  158.     /** 
  159.      * 类似 XMLHttpRequest 中的 send 方法. 
  160.      */
  161.     public void send(final String content) throws IOException {  
  162.         final URL url = this.requestURL;  
  163.         if (url == null) {  
  164.             throw new IOException("No URL has been provided.");  
  165.         }  
  166.         if (this.isAsync()) {  
  167.             new Thread("AjaxHttpRequest-" + url.getHost()) {  
  168.                 public void run() {  
  169.                     try {  
  170.                         sendSync(content);  
  171.                     } catch (Throwable thrown) {  
  172.                         log(Level.WARNING, "send(): Error in asynchronous request on " + url, thrown);  
  173.                     }  
  174.                 }  
  175.             }.start();  
  176.         } else {  
  177.             sendSync(content);  
  178.         }  
  179.     }  
  180.     /** 
  181.      * 类似 XMLHttpRequest 中的 getResponseHeader 方法. 
  182.      */
  183.     public synchronized String getResponseHeader(String headerName) {  
  184.         return this.responseHeadersMap == null ? null : (String) this.responseHeadersMap.get(headerName);  
  185.     }  
  186.     /** 
  187.      * 类似 XMLHttpRequest 中的 getAllResponseHeaders 方法. 
  188.      */
  189.     public synchronized String getAllResponseHeaders() {  
  190.         return this.responseHeaders;  
  191.     }  
  192.     /** 
  193.      * 类似 XMLHttpRequest 中的 responseText 属性. 
  194.      */
  195.     public synchronized String getResponseText() {  
  196.         byte[] bytes = this.responseBytes;  
  197.         String encoding = getCharset(this.connection);  
  198.         if (encoding==null){  
  199.             encoding=getPostCharset();  
  200.         }  
  201.         if (encoding == null) {  
  202.             encoding = DEFAULT_HTTP_CHARSET;  
  203.         }  
  204.         try {  
  205.             return bytes == null ? null : new String(bytes, encoding);  
  206.         } catch (UnsupportedEncodingException uee) {  
  207.             log(Level.WARNING, "getResponseText(): Charset '" + encoding + "' did not work. Retrying with "
  208.                     + DEFAULT_HTTP_CHARSET + ".", uee);  
  209.             try {  
  210.                 return new String(bytes, DEFAULT_HTTP_CHARSET);  
  211.             } catch (UnsupportedEncodingException uee2) {  
  212.                 // Ignore this time
  213.                 return null;  
  214.             }  
  215.         }  
  216.     }  
  217.     /** 
  218.      * 类似 XMLHttpRequest 中的 responseXML 属性. 
  219.      * TODO : 此方法在java中 并不常使用, 而且需要两个额外的包,两个包不是所有的java环境都有的. 
  220.      *   所以我(fins)把此方法注释条了.  
  221.      *   如果确实需要此方法 请自行取消该方法的注释,并引入下面列出的类/接口. 
  222.      *     javax.xml.parsers.DocumentBuilderFactory; 
  223.      *     org.w3c.dom.Document; 
  224.      */
  225. //        public synchronized Document getResponseXML() { 
  226. //            byte[] bytes =  this.responseBytes; 
  227. //            if (bytes == null) { 
  228. //                return null; 
  229. //            } 
  230. //            InputStream in =  new ByteArrayInputStream(bytes); 
  231. //            try { 
  232. //                return DocumentBuilderFactory.newInstance().newDocumentBuilder() .parse(in); 
  233. //            }catch (Exception err) { 
  234. //                log(Level.WARNING,  "Unable to parse response as XML.", err); return null;
  235. //            }
  236. //       }
  237.     /** 
  238.      * 类似 XMLHttpRequest 中的 responseBody 属性. 
  239.      * @deprecated 这个方法命名源自XMLHttpRequest中的responseBody属性. 
  240.      * 不过这个名字并不是好名字.建议使用 getResponseBytes 方法代替之. 
  241.      */
  242.     public synchronized byte[] getResponseBody() {  
  243.         return this.getResponseBytes();  
  244.     }  
  245.     /** 
  246.      * 类似 XMLHttpRequest 中的 responseBody 属性. 
  247.      * 建议使用此方法代替 getResponseBody 方法. 
  248.      */
  249.     public synchronized byte[] getResponseBytes() {  
  250.         return this.responseBytes;  
  251.     }     
  252.     /** 
  253.      * 与 XMLHttpRequest 中的 responseStream 属性对应的方法 暂不提供. 
  254.      * 因为1 不常用 2 通常可用 getResponseBytes 方法代替  
  255.      */
  256.     /** 
  257.      * 类似 XMLHttpRequest 中的 onreadystatechange 属性. 
  258.      * 设置一个监听器,用来跟踪HttpRequest状态变化. 
  259.      * 参数是一个 ReadyStateChangeListener 对象. 
  260.      * ReadyStateChangeListener 是一个抽象类. 只需 实现 onReadyStateChange方法即可. 
  261.      */
  262.     public void setReadyStateChangeListener(ReadyStateChangeListener listener) {  
  263.         this.readyStateChangeListener = listener;  
  264.     }  
  265.     /** 
  266.      * 中断 Request 请求. 类似 XMLHttpRequest 中的 abort. 
  267.      */
  268.     public void abort() {  
  269.         URLConnection c = null;  
  270.         synchronized (this) {  
  271.             c = this.getConnection();  
  272.         }  
  273.         if (c instanceof HttpURLConnection) {  
  274.             ((HttpURLConnection) c).disconnect();  
  275.         } else if (c != null) {  
  276.             try {  
  277.                 c.getInputStream().close();  
  278.             } catch (IOException ioe) {  
  279.                 ioe.printStackTrace();  
  280.             }  
  281.         }  
  282.     }  
  283. ///
  284.  以上 为 模拟 XMLHttpRequest 对象 相关的方法 
  285. ///
  286. ///
  287.     /** 
  288.      * 返回 此次HttpRequest是否是"异步"的. 
  289.      */
  290.     public boolean isAsync() {  
  291.         return async;  
  292.     }  
  293.     /** 
  294.      * 返回 此次HttpRequest是否已经发送. 
  295.      * 已经发送 且还没有完全处理完此次发送的返回信息时,是不能再次发送的. 
  296.      * 如果需要联系发送请求, 请再另行创建一个 AjaxHttpRequest对象. 
  297.      */
  298.     public boolean hasSent() {  
  299.         return sent;  
  300.     }  
  301.     protected void setSent(boolean sent) {  
  302.         this.sent=sent;  
  303.     }  
  304.     /** 
  305.      * 设置/取得 伪造的  userAgent 信息.通常不用理会. 
  306.      * 很少有http服务会对此做严格的判断. 
  307.      */
  308.     public void setUserAgent(String userAgent) {  
  309.         this.userAgent = userAgent;  
  310.     }  
  311.     public String getUserAgent() {  
  312.         return this.userAgent;  
  313.     }  
  314.     /** 
  315.      * 取得/设置 默认的 AJAX编码.AJAX请求都是UTF-8编码 此属性通常无需改变. 
  316.      */
  317.     public String getPostCharset() {  
  318.         return this.postCharset;  
  319.     }  
  320.     public void setPostCharset(String postCharset) {  
  321.         this.postCharset = postCharset;  
  322.     }  
  323.     /** 
  324.      * 实现发送数据功能的方法,是整个类的核心.  
  325.      * 我(fins)借鉴了 cobra 组件的 org.lobobrowser.html.test.SimpleHttpRequest 类中的同名方法. 
  326.      * 略作改动. 
  327.      */
  328.     protected void sendSync(String content) throws IOException {  
  329.         if (hasSent()){  
  330.             log(Level.WARNING, "This AjaxHttpRequest Object has sent", null);  
  331.             return ;  
  332.         }  
  333.         try {  
  334.             URLConnection c;  
  335.             synchronized (this) {  
  336.                 c = this.connection;  
  337.             }  
  338.             if (c==null){  
  339.                 log(Level.WARNING, "Please open AjaxHttpRequest first.", null);  
  340.                 return ;  
  341.             }  
  342.             setSent(true);  
  343.             initConnectionRequestHeader(c);  
  344.             int istatus;  
  345.             String istatusText;  
  346.             InputStream err;  
  347.             if (c instanceof HttpURLConnection) {  
  348.                 HttpURLConnection hc = (HttpURLConnection) c;  
  349.                 String method = this.requestMethod==null?DEFAULT_REQUEST_METHOD:this.requestMethod;  
  350.                 method = method.toUpperCase();  
  351.                 hc.setRequestMethod(method);  
  352.                 if ("POST".equals(method) && content != null) {  
  353.                     hc.setDoOutput(true);  
  354.                     byte[] contentBytes = content.getBytes(this.getPostCharset());  
  355.                     hc.setFixedLengthStreamingMode(contentBytes.length);  
  356.                     OutputStream out = hc.getOutputStream();  
  357.                     try {  
  358.                         out.write(contentBytes);  
  359.                     } finally {  
  360.                         out.flush();  
  361.                     }  
  362.                 }  
  363.                 istatus = hc.getResponseCode();  
  364.                 istatusText = hc.getResponseMessage();  
  365.                 err = hc.getErrorStream();  
  366.             } else {  
  367.                 istatus = 0;  
  368.                 istatusText = "";  
  369.                 err = null;  
  370.             }  
  371.             synchronized (this) {  
  372.                 this.responseHeaders = getConnectionResponseHeaders(c);  
  373.                 this.responseHeadersMap = c.getHeaderFields();  
  374.             }  
  375.             this.changeState(AjaxHttpRequest.STATE_LOADED, istatus, istatusText, null);  
  376.             InputStream in = err == null ? c.getInputStream() : err;  
  377.             int contentLength = c.getContentLength();  
  378.             this.changeState(AjaxHttpRequest.STATE_INTERACTIVE, istatus, istatusText, null);  
  379.             byte[] bytes = loadStream(in, contentLength == -1 ? 4096 : contentLength);  
  380.             this.changeState(AjaxHttpRequest.STATE_COMPLETE, istatus, istatusText, bytes);  
  381.         } finally {  
  382.             synchronized (this) {  
  383.                 this.connection = null;  
  384.                 setSent(false);  
  385.             }  
  386.         }  
  387.     }  
  388.     /** 
  389.      * 当状态变化时 重新设置各种状态值,并触发状态变化监听器. 
  390.      */
  391.     protected void changeState(int readyState, int status, String statusMessage, byte[] bytes) {  
  392.         synchronized (this) {  
  393.             this.readyState = readyState;  
  394.             this.status = status;  
  395.             this.statusText = statusMessage;  
  396.             this.responseBytes = bytes;  
  397.         }  
  398.         if (this.readyStateChangeListener!=null){  
  399.             this.readyStateChangeListener.onReadyStateChange();  
  400.         }  
  401.     }  
  402.     /** 
  403.      * 对字符串进行 URLEncoder 编码. 
  404.      */
  405.     protected String encode(Object str){  
  406.         try {  
  407.             return URLEncoder.encode(String.valueOf(str), getPostCharset());  
  408.         } catch (UnsupportedEncodingException e) {  
  409.             return String.valueOf(str);  
  410.         }  
  411.     }  
  412.     /** 
  413.      * 将设置的 RequestHeader 真正的设置到链接请求中. 
  414.      */
  415.     protected void initConnectionRequestHeader(URLConnection c) {  
  416.         c.setRequestProperty("User-Agent", this.getUserAgent());  
  417.         Iterator keyItor = this.requestHeadersMap.keySet().iterator();  
  418.         while (keyItor.hasNext()) {  
  419.             String key = (String) keyItor.next();  
  420.             String value = (String) this.requestHeadersMap.get(key);  
  421.             c.setRequestProperty(key, value);  
  422.         }  
  423.     }  
  424.     /** 
  425.      * 以下 4个 方法 负责处理 requestHeader信息.  
  426.      */
  427.     public String getRequestHeader(String key) {  
  428.         return (String) this.requestHeadersMap.get(key);  
  429.     }  
  430.     public String removeRequestHeader(String key) {  
  431.         return (String)this.requestHeadersMap.remove(key);  
  432.     }  
  433.     public void removeAllRequestHeaders() {  
  434.         this.requestHeadersMap.clear();  
  435.     }  
  436.     public Map getAllRequestHeaders() {  
  437.         return this.requestHeadersMap;  
  438.     }  
  439.     public URLConnection getConnection() {  
  440.         return connection;  
  441.     }  
  442.     public void setConnection(URLConnection connection) {  
  443.         this.connection = connection;  
  444.     }  
  445.     public Proxy getProxy() {  
  446.         return proxy;  
  447.     }  
  448.     public void setProxy(Proxy proxy) {  
  449.         this.proxy = proxy;  
  450.     }  
  451.     /
  452.     // 以下是 Static Method //
  453.     // 这些静态方法其实可以(应该)单独提取出去的, ///
  454.     // 不过为了让这个程序结构简单些 , 我(fins)就全部 all in one 了.///
  455.     // 这些方法也不都是我(fins)自己写的 很多是copy 借鉴来的 功能都挺简单的 就不详细说明了 //
  456.     /
  457.     public static void log(Level level, String msg, Throwable thrown) {  
  458.         System.out.println(level.getName() + " : " + thrown.getMessage() + " ----- " + msg);  
  459.     }  
  460.     public static String getConnectionResponseHeaders(URLConnection c) {  
  461.         int idx = 0;  
  462.         String value;  
  463.         StringBuffer buf = new StringBuffer();  
  464.         while ((value = c.getHeaderField(idx)) != null) {  
  465.             String key = c.getHeaderFieldKey(idx);  
  466.             buf.append(key);  
  467.             buf.append(": ");  
  468.             buf.append(value);  
  469.             idx++;  
  470.         }  
  471.         return buf.toString();  
  472.     }  
  473.     public static String getCharset(URLConnection connection) {  
  474.         String contentType = connection==null?null:connection.getContentType();  
  475.         if (contentType != null) {  
  476.             StringTokenizer tok = new StringTokenizer(contentType, ";");  
  477.             if (tok.hasMoreTokens()) {  
  478.                 tok.nextToken();  
  479.                 while (tok.hasMoreTokens()) {  
  480.                     String assignment = tok.nextToken().trim();  
  481.                     int eqIdx = assignment.indexOf('=');  
  482.                     if (eqIdx != -1) {  
  483.                         String varName = assignment.substring(0, eqIdx).trim();  
  484.                         if ("charset".equalsIgnoreCase(varName)) {  
  485.                             String varValue = assignment.substring(eqIdx + 1);  
  486.                             return unquote(varValue.trim());  
  487.                         }  
  488.                     }  
  489.                 }  
  490.             }  
  491.         }  
  492.         return null;  
  493.     }  
  494.     public static String unquote(String text) {  
  495.         if (text.startsWith("/"") && text.endsWith("/"")) {  
  496.             return text.substring(1, text.length() - 2);  
  497.         }  
  498.         return text;  
  499.     }  
  500.     protected static URL createURL(URL baseUrl, String relativeUrl) throws MalformedURLException {  
  501.         return new URL(baseUrl, relativeUrl);  
  502.     }  
  503.     protected static byte[] loadStream(InputStream in, int initialBufferSize) throws IOException {  
  504.         if (initialBufferSize == 0) {  
  505.             initialBufferSize = 1;  
  506.         }  
  507.         byte[] buffer = new byte[initialBufferSize];  
  508.         int offset = 0;  
  509.         for (;;) {  
  510.             int remain = buffer.length - offset;  
  511.             if (remain <= 0) {  
  512.                 int newSize = buffer.length * 2;  
  513.                 byte[] newBuffer = new byte[newSize];  
  514.                 System.arraycopy(buffer, 0, newBuffer, 0, offset);  
  515.                 buffer = newBuffer;  
  516.                 remain = buffer.length - offset;  
  517.             }  
  518.             int numRead = in.read(buffer, offset, remain);  
  519.             if (numRead == -1) {  
  520.                 break;  
  521.             }  
  522.             offset += numRead;  
  523.         }  
  524.         if (offset < buffer.length) {  
  525.             byte[] newBuffer = new byte[offset];  
  526.             System.arraycopy(buffer, 0, newBuffer, 0, offset);  
  527.             buffer = newBuffer;  
  528.         }  
  529.         return buffer;  
  530.     }  
  531.     /// 
  532.     // Listener Class /
  533.     ///
  534.     /** 
  535.      * 一个用来监听 HttpRequest状态 的监听器. 是一个内部静态抽象类. 
  536.      * 可以根据实际情况来自行重构(如 增加方法、变为独立的外部类等). 
  537.      */
  538.     public static abstract class ReadyStateChangeListener {  
  539.         public abstract void onReadyStateChange();  
  540.     }  
  541.     /// 
  542.     // Test Method 
  543.     ///
  544.     /** 
  545.      * 利用这个AjaxHttpReuqest类来实现 对google translate服务的访问 . 
  546.      * 只演示了 "英-->汉"的翻译. 
  547.      * 返回的是JSON字符串,需要使用Json工具类进行转换,这个不难 就不详细举例了. 
  548.      */
  549.     public static void testGoogleTranslate(String words,boolean async) throws IOException {  
  550.         Map params=new HashMap();  
  551.         params.put("q",words);  
  552.         params.put("v","1.0");  
  553.         params.put("langpair","en|zh-CN");  
  554.         String url="http://ajax.googleapis.com/ajax/services/language/translate";  
  555.         // 以上为 调用google翻译服务所需要的参数.
  556.         // 下面 是用java 来调用这个 翻译服务.
  557.         // 在 AjaxHttpRequest 类的 帮助下 我们可以使用 类似操作浏览器XHR对象的方式来 实现该功能.
  558.         // 创建 AjaxHttpRequest对象 相当于 创建 XHR对象.
  559.         // 这里的final 主要是为了"使监听器内部能够调用ajax对象"而加的.
  560.         final AjaxHttpRequest ajax=new AjaxHttpRequest();  
  561.         // 设置状态监听器,类似 XHR对象的 onreadystatechange 属性.
  562.         // 由于js 和java的本质区别 导致这里可能和 xhr有点不一样,但是应该不难理解.
  563.         ajax.setReadyStateChangeListener(  
  564.                 // 监听器, 根据需求 实现onReadyStateChange方法即可.
  565.                 new AjaxHttpRequest.ReadyStateChangeListener(){  
  566.                         public void onReadyStateChange() {  
  567.                             int readyState = ajax.getReadyState();  
  568.                             //判断状态 然后做出相应处理.
  569.                             if (readyState==AjaxHttpRequest.STATE_COMPLETE){  
  570.                                 System.out.println( ajax.getResponseText() );  
  571.                             }  
  572.                         }             
  573.                 }  
  574.         );  
  575.         // 这里就和 xhr 几乎完全一样了
  576.         ajax.open("POST", url, true);  
  577.         //这里这个send方法接受的参数是一个map ,当然AjaxHttpRequest类也提供了string的方法
  578.         ajax.send(params);  
  579.     }  
  580.     public static void main(String[] args) throws IOException {  
  581.         testGoogleTranslate("Hello world!",false);  
  582.     }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值