JAVA开发常用类库--HTTP库

我不是很喜欢JDK的一个重要原因就包括他们缺乏对HTTP的支持。虽然可以使用java.net包类,但是这和直接使用像 Apache HttpClient 和 HttpCore 等开源类库比起来麻烦太多了。

尽管JDK 9将开始HTTP 2.0,也对HTTP的支持做了优化,但是我还是强烈建议所有的Java开发人员熟悉流行的HTTP处理类库,例如HttpClient和HttpCore HTTP等库。

传统的java.net包类

InetAddress类:表示互联网协议 (IP) 地址

URL类:代表一个统一资源定位符,它是指向互联网“资源”的指针。

资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。

URLConnection类:用于读取和写入此 URL 引用的资源。

使用步骤:
通过在 URL 上调用 openConnection 方法创建连接对象。
处理设置参数和一般请求属性。
使用 connect 方法建立到远程对象的实际连接。
远程对象变为可用。远程对象的头字段和内容变为可访问。

DatagramPacket类:此类表示数据报包。

数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。

DatagramSocket类:此类表示用来发送和接收数据报包的套接字。

数据报套接字是包投递服务的发送或接收点。每个在数据报套接字上发送或接收的包都是单独编址和路由的。从一台机
器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。

  • ServerSocket类:此类实现服务器套接字。

ServerSocket类主要用在服务器端程序的开发上,用于接收客户端的连接请求

logo

服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。

  • Socket类:此类实现客户端套接字(也可以就叫“套接字”)。

则是在客户端上运行的,在服务器每次运行时都要使用accept()方法来获取客户端连接,此方法执行之后服务器端将进入阻塞状态,
直到客户端连接之后才可以继续向下执行,此方法的返回值类型是Socket,每一个Socket都表示一个客户端对象

本包中的主线应该是Socket和ServalSocket两个类。将围绕socket和serverSocket的通信而展开。

首先,如何建立一个客户端和服务器端的通信?

一、客户端

1.首先new一个socket(有连接的socket和未连接的socket两种:指定服务器端的ip地址(或主机名)与port号的为连接的,没指定或使用socket(Proxy proxy)的为未连接的)。

2.设置socket的各项参数:时间?(连接之后还能设置么?)

3.通过getInputputStream()和getOutputStream()方法得到InputStream和OutputStream流。

4.操作InputStream和OutputStream流读取或写入数据。

5.close

二、服务器端

1.首先new一个serverSocket(有绑定的serverSocket和未绑定的serverSocket两种:指定服务器端的Port号为绑定的,未指定的为未绑定的)。

2.设置serverSocket的各项参数:buffersize?

3.调用accept()方法获得一个和客户端连接的Socket。

4.通过getInputputStream()和getOutputStream()方法得到InputStream和OutputStream流。

5.close

通过以上步骤我们基本上就建立起了客户端和服务器端的通信链路。然后我们讲讲关于Socket和ServerSocket参数设置的问题。

本文的第二个主线是DatagramSocket和DatagramPacket两个类。

首先,如何通过UDP协议建立一个客户端和服务器端的通信?

一、客户端

1.首先new 一个DatagramSocket(有绑定的DatagramSocket和未绑定的DatagramSocket两种:需指定本地的ip地址和port号,DatagramSocket(SocketAddress localAddr)如果localAddr未null,则为未绑定)。

2,new一个DatagramPacket实例(需指定主机地址和端口号),填充数据,将其传递给DatagramSocket的send方法。

3.接收数据时将DatagramPacket实例传递给DatagramSocket的receive方法。

3,close

二、服务器端

其实本质和客户端一样的。

示例:

import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStreamReader;  
import java.io.PrintWriter;  
import java.net.URL;  
import java.net.URLConnection;  
import java.util.List;  
import java.util.Map;  

/** 
 * @Title   SendRequestUtils.java 
 * @Package com.pro.huanbao.common.utils 
 * @author  wanpu_ly 
 * @dade    2017年10月13日 上午8:43:42 
 * @version V1.0 
 * 类说明:  
 */  
public class SendRequestUtils {  

    /** 
     * 向指定URL发送GET方法的请求 
     *  
     * @param url 
     *            发送请求的URL 
     * @param param 
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 
     * @return URL 所代表远程资源的响应结果 
     */  
    public static String sendGet(String url, String param) {  
        String result = "";  
        BufferedReader in = null;  
        try {  
            String urlNameString = url + "?" + param;  
            if (param == null) {  
                urlNameString = url;  
            }  
            URL realUrl = new URL(urlNameString);  
            // 打开和URL之间的连接  
            URLConnection connection = realUrl.openConnection();  
            // 设置通用的请求属性  
            connection.setRequestProperty("accept", "*/*");  
            connection.setRequestProperty("connection", "Keep-Alive");  
            connection.setRequestProperty("user-agent",  
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");  
            // 建立实际的连接  
            connection.connect();  
            // 获取所有响应头字段  
            Map<String, List<String>> map = connection.getHeaderFields();  
            // 遍历所有的响应头字段  
            for (String key : map.keySet()) {  
                System.out.println(key + "--->" + map.get(key));  
            }  
            // 定义 BufferedReader输入流来读取URL的响应  
            in = new BufferedReader(new InputStreamReader(  
                    connection.getInputStream()));  
            String line;  
            while ((line = in.readLine()) != null) {  
                result += line;  
            }  
        } catch (Exception e) {  
            System.out.println("发送GET请求出现异常!" + e);  
            e.printStackTrace();  
        }  
        // 使用finally块来关闭输入流  
        finally {  
            try {  
                if (in != null) {  
                    in.close();  
                }  
            } catch (Exception e2) {  
                e2.printStackTrace();  
            }  
        }  
        return result;  
    }  

    /**  
     * 向指定 URL 发送POST方法的请求  
     *   
     * @param url  
     *            发送请求的 URL  
     * @param param  
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。  
     * @return 所代表远程资源的响应结果  
     */  
    public static String sendPost(String url, String param) {  
        PrintWriter out = null;  
        BufferedReader in = null;  
        String result = "";  
        try {  
            URL realUrl = new URL(url);  
            // 打开和URL之间的连接  
            URLConnection conn = realUrl.openConnection();  
            // 设置通用的请求属性  
            conn.setRequestProperty("accept", "*/*");  
            conn.setRequestProperty("connection", "Keep-Alive");  
            conn.setRequestProperty("user-agent",  
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");  
            // 发送POST请求必须设置如下两行  
            conn.setDoOutput(true);  
            conn.setDoInput(true);  
            // 获取URLConnection对象对应的输出流  
            out = new PrintWriter(conn.getOutputStream());  
            // 发送请求参数  
            out.print(param);  
            // flush输出流的缓冲  
            out.flush();  
            // 定义BufferedReader输入流来读取URL的响应  
            in = new BufferedReader(  
                    new InputStreamReader(conn.getInputStream()));  
            String line;  
            while ((line = in.readLine()) != null) {  
                result += line;  
            }  
        } catch (Exception e) {  
            System.out.println("发送 POST 请求出现异常!"+e);  
            e.printStackTrace();  
        }  
        //使用finally块来关闭输出流、输入流  
        finally{  
            try{  
                if(out!=null){  
                    out.close();  
                }  
                if(in!=null){  
                    in.close();  
                }  
            }  
            catch(IOException ex){  
                ex.printStackTrace();  
            }  
        }  
        return result;  
    }    
}  

不过由于java.net的局限性和性能上的不足,基本上开发互联网产品的时候不会用到

接下来介绍一些第三方流行的Http库

apache的httpclient工具类

示例:

package org.egg.utils;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

/**
 * @author dataochen
 * @Description
 * @date: 2017/11/7 17:49
 */
public class HttpRequestUtil {
    private static CloseableHttpClient httpClient;

    static {
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(100);
        cm.setDefaultMaxPerRoute(20);
        cm.setDefaultMaxPerRoute(50);
        httpClient = HttpClients.custom().setConnectionManager(cm).build();
    }

    public static String get(String url) {
        CloseableHttpResponse response = null;
        BufferedReader in = null;
        String result = "";
        try {
            HttpGet httpGet = new HttpGet(url);
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
            httpGet.setConfig(requestConfig);
            httpGet.setConfig(requestConfig);
            httpGet.addHeader("Content-type", "application/json; charset=utf-8");
            httpGet.setHeader("Accept", "application/json");
            response = httpClient.execute(httpGet);
            in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            StringBuffer sb = new StringBuffer("");
            String line = "";
            String NL = System.getProperty("line.separator");
            while ((line = in.readLine()) != null) {
                sb.append(line + NL);
            }
            in.close();
            result = sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != response) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    public static String post(String url, String jsonString) {
        CloseableHttpResponse response = null;
        BufferedReader in = null;
        String result = "";
        try {
            HttpPost httpPost = new HttpPost(url);
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
            httpPost.setConfig(requestConfig);
            httpPost.setConfig(requestConfig);
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");
            httpPost.setHeader("Accept", "application/json");
            httpPost.setEntity(new StringEntity(jsonString, Charset.forName("UTF-8")));
            response = httpClient.execute(httpPost);
            in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            StringBuffer sb = new StringBuffer("");
            String line = "";
            String NL = System.getProperty("line.separator");
            while ((line = in.readLine()) != null) {
                sb.append(line + NL);
            }
            in.close();
            result = sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != response) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

}

代码所用jar包maven坐标:


org.apache.httpcomponents
httpclient
4.5.3



org.apache.httpcomponents
httpcore
4.4.8

Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会更加深入。

一、简介
HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。

二、特性

  1. 基于标准、纯净的java语言。实现了Http1.0和Http1.1
  2. 以可扩展的面向对象的结构实现了Http全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。
  3. 支持HTTPS协议。
  4. 通过Http代理建立透明的连接。
  5. 利用CONNECT方法通过Http代理建立隧道的https连接。
  6. Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。
  7. 插件式的自定义认证方案。
  8. 便携可靠的套接字工厂使它更容易的使用第三方解决方案。
  9. 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。
  10. 自动处理Set-Cookie中的Cookie。
  11. 插件式的自定义Cookie策略。
  12. Request的输出流可以避免流中内容直接缓冲到socket服务器。
  13. Response的输入流可以有效的从socket服务器直接读取相应内容。
  14. 在http1.0和http1.1中利用KeepAlive保持持久连接。
  15. 直接获取服务器发送的response code和 headers。
  16. 设置连接超时的能力。
  17. 实验性的支持http1.1 response caching。
  18. 源代码基于Apache License 可免费获取

三、使用方法
Mavn坐标
Java代码 收藏代码

org.apache.httpcomponents
httpclient
4.3.4

使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。

  1. 创建HttpClient对象。
  2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
  3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
  4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。
  5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
  6. 释放连接。无论执行方法是否成功,都必须释放连接

四.post跟get请求示例
Java代码 收藏代码
package com.ickes;

import java.util.ArrayList;  
import java.util.List;  
import org.apache.http.HttpEntity;  
import org.apache.http.NameValuePair;  
import org.apache.http.client.entity.UrlEncodedFormEntity;  
import org.apache.http.client.methods.CloseableHttpResponse;  
import org.apache.http.client.methods.HttpGet;  
import org.apache.http.client.methods.HttpPost;  
import org.apache.http.entity.StringEntity;  
import org.apache.http.impl.client.CloseableHttpClient;  
import org.apache.http.impl.client.HttpClients;  
import org.apache.http.message.BasicNameValuePair;  
import org.apache.http.protocol.HTTP;  
import org.apache.http.util.EntityUtils;  

public class HttpClientDemo {  

    public static void main(String[] args) throws Exception  {   
        get();  
    }  

    /** 
     * post方式提交json代码 
     * @throws Exception  
     */  
    public static void postJson() throws Exception{  
        //创建默认的httpClient实例.   
        CloseableHttpClient httpclient = null;  
        //接收响应结果  
        CloseableHttpResponse response = null;  
        try {  
            //创建httppost  
            httpclient = HttpClients.createDefault();    
            String url ="http://192.168.16.36:8081/goSearch/gosuncn/deleteDocs.htm";  
            HttpPost httpPost = new HttpPost(url);  
            httpPost.addHeader(HTTP.CONTENT_TYPE,"application/x-www-form-urlencoded");  
            //参数  
            String json ="{'ids':['html1','html2']}";  
            StringEntity se = new StringEntity(json);  
            se.setContentEncoding("UTF-8");  
            se.setContentType("application/json");//发送json需要设置contentType  
            httpPost.setEntity(se);  
            response = httpclient.execute(httpPost);  
            //解析返结果  
            HttpEntity entity = response.getEntity();   
            if(entity != null){  
                String resStr = EntityUtils.toString(entity, "UTF-8");      
                System.out.println(resStr);  
            }  
        } catch (Exception e) {  
            throw e;  
        }finally{  
            httpclient.close();  
            response.close();  
        }  
    }  

     /**  
     * post方式提交表单(模拟用户登录请求)  
     * @throws Exception  
     */    
    public static void postForm() throws Exception  {    
        // 创建默认的httpClient实例.      
        CloseableHttpClient httpclient = null;  
        //发送请求  
        CloseableHttpResponse response = null;  
        try {  
            httpclient = HttpClients.createDefault();    
            // 创建httppost      
            String url= "http://localhost:8080/search/ajx/user.htm";  
            HttpPost httppost = new HttpPost(url);    
            // 创建参数队列      
            List<NameValuePair> formparams = new ArrayList<NameValuePair>();    
            formparams.add(new BasicNameValuePair("username", "admin"));    
            formparams.add(new BasicNameValuePair("password", "123456"));  
            //参数转码  
            UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");    
            httppost.setEntity(uefEntity);   
            response = httpclient.execute(httppost);    
            HttpEntity entity = response.getEntity();    
            if (entity != null) {    
                  System.out.println(EntityUtils.toString(entity, "UTF-8"));    
            }    
            //释放连接  
        } catch (Exception e) {  
            throw e;  
        }finally{  
             httpclient.close();  
             response.close();  
        }  
    }    

    /**  
     * 发送 get请求  
     * @throws Exception  
     */    
    public static void get() throws Exception {    
        CloseableHttpClient httpclient = null;  
        CloseableHttpResponse response = null;  
        try {  
            httpclient = HttpClients.createDefault();    
            // 创建httpget.      
            HttpGet httpget = new HttpGet("http://www.baidu.com/");    
            // 执行get请求.      
            response = httpclient.execute(httpget);    
            // 获取响应实体      
            HttpEntity entity = response.getEntity();    

            // 打印响应状态      
            System.out.println(response.getStatusLine().getStatusCode());    
            if (entity != null) {    
                // 打印响应内容      
                System.out.println("Response content: " + EntityUtils.toString(entity));    
            }  
        } catch (Exception e) {  
            throw e;  
        }finally{  
            httpclient.close();  
            response.close();  
        }  
    }  
}  

五、SSL跟上传文件实例

Java代码 收藏代码
package com.test;

import java.io.File;  
import java.io.FileInputStream;  
import java.io.IOException;  
import java.io.UnsupportedEncodingException;  
import java.security.KeyManagementException;  
import java.security.KeyStore;  
import java.security.KeyStoreException;  
import java.security.NoSuchAlgorithmException;  
import java.security.cert.CertificateException;  
import java.util.ArrayList;  
import java.util.List;  
import javax.net.ssl.SSLContext;  
import org.apache.http.HttpEntity;  
import org.apache.http.NameValuePair;  
import org.apache.http.ParseException;  
import org.apache.http.client.ClientProtocolException;  
import org.apache.http.client.entity.UrlEncodedFormEntity;  
import org.apache.http.client.methods.CloseableHttpResponse;  
import org.apache.http.client.methods.HttpGet;  
import org.apache.http.client.methods.HttpPost;  
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;  
import org.apache.http.conn.ssl.SSLContexts;  
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;  
import org.apache.http.entity.ContentType;  
import org.apache.http.entity.mime.MultipartEntityBuilder;  
import org.apache.http.entity.mime.content.FileBody;  
import org.apache.http.entity.mime.content.StringBody;  
import org.apache.http.impl.client.CloseableHttpClient;  
import org.apache.http.impl.client.HttpClients;  
import org.apache.http.message.BasicNameValuePair;  
import org.apache.http.util.EntityUtils;  
import org.junit.Test;  

public class HttpClientTest {  

    @Test  
    public void jUnitTest() {  
        ssl();  
    }  

    /** 
     * HttpClient连接SSL 
     */  
    public void ssl() {  
        CloseableHttpClient httpclient = null;  
        try {  
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());  
            FileInputStream instream = new FileInputStream(new File("d:\\tomcat.keystore"));  
            try {  
                // 加载keyStore d:\\tomcat.keystore    
                trustStore.load(instream, "123456".toCharArray());  
            } catch (CertificateException e) {  
                e.printStackTrace();  
            } finally {  
                try {  
                    instream.close();  
                } catch (Exception ignore) {  
                }  
            }  
            // 相信自己的CA和所有自签名的证书  
            SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build();  
            // 只允许使用TLSv1协议  
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,  
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);  
            httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();  
            // 创建http请求(get方式)  
            HttpGet httpget = new HttpGet("https://localhost:8443/myDemo/Ajax/serivceJ.action");  
            System.out.println("executing request" + httpget.getRequestLine());  
            CloseableHttpResponse response = httpclient.execute(httpget);  
            try {  
                HttpEntity entity = response.getEntity();  
                System.out.println("----------------------------------------");  
                System.out.println(response.getStatusLine());  
                if (entity != null) {  
                    System.out.println("Response content length: " + entity.getContentLength());  
                    System.out.println(EntityUtils.toString(entity));  
                    EntityUtils.consume(entity);  
                }  
            } finally {  
                response.close();  
            }  
        } catch (ParseException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        } catch (KeyManagementException e) {  
            e.printStackTrace();  
        } catch (NoSuchAlgorithmException e) {  
            e.printStackTrace();  
        } catch (KeyStoreException e) {  
            e.printStackTrace();  
        } finally {  
            if (httpclient != null) {  
                try {  
                    httpclient.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  

    /** 
     * 上传文件 
     */  
    public void upload() {  
        CloseableHttpClient httpclient = HttpClients.createDefault();  
        try {  
            HttpPost httppost = new HttpPost("http://localhost:8080/myDemo/Ajax/serivceFile.action");  

            FileBody bin = new FileBody(new File("F:\\image\\sendpix0.jpg"));  
            StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN);  

            HttpEntity reqEntity = MultipartEntityBuilder.create().addPart("bin", bin).addPart("comment", comment).build();  

            httppost.setEntity(reqEntity);  

            System.out.println("executing request " + httppost.getRequestLine());  
            CloseableHttpResponse response = httpclient.execute(httppost);  
            try {  
                System.out.println("----------------------------------------");  
                System.out.println(response.getStatusLine());  
                HttpEntity resEntity = response.getEntity();  
                if (resEntity != null) {  
                    System.out.println("Response content length: " + resEntity.getContentLength());  
                }  
                EntityUtils.consume(resEntity);  
            } finally {  
                response.close();  
            }  
        } catch (ClientProtocolException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                httpclient.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
}  

本实例是采用HttpClient4.3最新版本。该版本与之前的代码写法风格相差较大,大家多留意下。

参考:http://blog.csdn.net/wangpeng047/article/details/19624529

坚持原创技术分享,您的支持将鼓励我继续创作!
+