Http请求-HttpURLConnection、HttpClient

本章介绍Java开发中,常见的Http请求方式:

  1. JAVA的标准类Java.net.HttpURLConnection
  2. org.apache.commons.httpclient 封装好的HttpClient
  3. Springboot 中RestTemplate

1. HttpURLConnection

JDK提供的包java.net.HttpURLConnection,HttpURLConnection是JAVA的标准类,是JAVA比较原生的一种实现方式。

POST请求:

public class HttpURLConnectionDemo {
    /**
     * Http post请求
     */
    public static String doPost(String httpUrl, String param) {
        HttpURLConnection connection = null;
        OutputStream os = null;
        InputStream is = null;
        BufferedReader br = null;
        StringBuffer result = new StringBuffer();

        try {
            //1.1、创建连接对象
            URL url = new URL(httpUrl);
            //1.2、创建连接
            connection = (HttpURLConnection) url.openConnection();

            //2.1、设置请求方法
            connection.setRequestMethod("POST");
            //2.2、设置连接超时时间 单位:毫秒
            connection.setConnectTimeout(15000);
            //2.3、设置读取超时时间 单位:毫秒
            connection.setReadTimeout(60000);
            //2.4、默认值为:false,当向远程服务器传送数据/写数据时,需要设置为true
            connection.setDoOutput(true);
            // 默认值为:true,当前向远程服务读取数据时,设置为true,该参数可有可无
            connection.setDoInput(true);
            //2.5、设置通用的请求属性
            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.setRequestProperty("Content-Type", "application/json;charset=utf-8");

            //3、写需要发送的请求
            if (null != param && !param.equals("")) {
                //设置参数
                os = connection.getOutputStream();
                //拼装参数
                os.write(param.getBytes("UTF-8"));
            }

            //4、读取响应
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                is = connection.getInputStream();
                if (null != is) {
                    br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    String temp = null;
                    while (null != (temp = br.readLine())) {
                        result.append(temp);
                        result.append("\r\n");
                    }
                }
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //关闭连接
            connection.disconnect();
        }
        return result.toString();
    }
    
    public static void main(String[] args) throws IOException {
        String post = doPost("http://127.0.0.1:8080/postHttp", "{\"id\":\"1001\",\"name\":\"丽丽\"}");
        System.out.println(post);
    }
}

在这里插入图片描述

get请求:

public class HttpURLConnectionDemo {
    /**
     * Http get请求
     */
    public static String doGet(String httpUrl){
        HttpURLConnection connection = null;
        InputStream is = null;
        BufferedReader br = null;
        StringBuffer result = new StringBuffer();

        try {
            //1、创建连接对象
            URL url = new URL(httpUrl);
            connection = (HttpURLConnection) url.openConnection();

            //2.1、设置请求方法
            connection.setRequestMethod("GET");
            //2.2、设置连接超时时间 单位:毫秒
            connection.setReadTimeout(15000);

            //3、开始连接
            connection.connect();

            //4、获取响应数据
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                //获取返回的数据
                is = connection.getInputStream();
                if (null != is) {
                    br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    String temp = null;
                    while (null != (temp = br.readLine())) {
                        result.append(temp);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //关闭远程连接
            connection.disconnect();
        }
        return result.toString();
    }

    public static void main(String[] args) throws IOException {
        String get = doGet("http://127.0.0.1:8080/getHttp?id=1001");
        System.out.println(get);
    }
}

在这里插入图片描述

get请求下载图片:
和上面的get请求一样,只是响应数据用字节流接收,保存到指定目录。

public class HttpURLConnectionDemo {
    /**
     * Http get请求下载图片
     */
    public static void downLoad(String httpUrl){
        HttpURLConnection connection = null;
        InputStream is = null;
        BufferedInputStream fis = null;
        BufferedOutputStream fio = null;

        try {
            //1、创建连接对象
            URL url = new URL(httpUrl);
            connection = (HttpURLConnection) url.openConnection();

            //2.1、设置请求方法
            connection.setRequestMethod("GET");
            //2.2、设置连接超时时间 单位:毫秒
            connection.setReadTimeout(15000);

            //3、开始连接
            connection.connect();

            //4、获取响应数据
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                //获取返回的数据
                is = connection.getInputStream();
                if (null != is) {
                    fis = new BufferedInputStream(is);
                    fio = new BufferedOutputStream(new FileOutputStream("e:\\demo\\test.jpg"));

                    // 一次读取一个字节数组
                    int len = 0;
                    byte[] bys = new byte[1024];
                    while ( (len = fis.read(bys)) != -1 ){
                        System.out.print(len);
                        fio.write(bys, 0, len);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != fis) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != fio) {
                try {
                    fio.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //关闭远程连接
            connection.disconnect();
        }
    }

    public static void main(String[] args) throws IOException {
        downLoad("https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1lY20g.img?w=534&h=413&m=6&x=619&y=126&s=168&d=168");
    }
}

服务端使用springboot项目:

@RestController
public class HelloController {
    
    @RequestMapping("/postHttp")
    public String testHttp(@RequestBody Map<String, Object> map){
        System.out.println(map);
        return "post http" ;
    }

    @RequestMapping("/getHttp")
    public String testHttp(@RequestParam String id){
        System.out.println(id);
        return "get http" ;
    }

}

在这里插入图片描述


2. HttpClient

HTTPClient 对 HTTP 的封装性比较不错,通过它基本上能够满足我们大部分的需求,HttpClient3.1 是 org.apache.commons.httpclient 下操作远程 url 的工具包,虽然已不再更新,但实现工作中使用 httpClient3.1 的代码还是很多。HttpClient4.5 是org.apache.http.client下操作远程 url 最新的工具包。

<dependency>
   <groupId>commons-httpclient</groupId>
   <artifactId>commons-httpclient</artifactId>
   <version>3.1</version>
</dependency>

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.10</version>
</dependency>

POST请求:

public class HttpClientDemo {
    /**
     * httpClient 的 post 请求方式
     * 使用 PostMethod 来访问一个 URL 对应的网页实现步骤:
     * 1.生成一个 HttpClient 对象并设置相应的参数;
     * 2.生成一个 PostMethod 对象并设置响应的参数;
     * 3.用 HttpClient 生成的对象来执行 PostMethod 生成的 POST 方法;
     * 4.处理 HTTP 响应内容
     * 5.释放连接。
     */
    public static String doPost(String url, String jsonString, String charset) {
        HttpClient httpClient = null;
        PostMethod postMethod = null;
        String response = "";
        InputStream is = null;
        BufferedReader br = null;

        //1.1、生成HttpClient对象并设置参数
        httpClient = new HttpClient();
        //1.2、设置连接超时时间 单位:毫秒
        httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(15000);

        //2.1、生成GetMethod对象并设置参数
        postMethod = new PostMethod(url);
        //2.2、设置post请求参数
        postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 60000);
        postMethod.addRequestHeader("accept", "*/*");
        postMethod.addRequestHeader("connection", "Keep-Alive");
        postMethod.addRequestHeader("Content-Type", "application/json;charset=utf-8");
        postMethod.addRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");
        //2.3、添加请求参数
        try {
            postMethod.setRequestEntity(new StringRequestEntity(jsonString, "application/json", "utf-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        try {
            //3、执行HTTP POST 请求
            int statusCode = httpClient.executeMethod(postMethod);

            //4.1、判断返回的状态码
            if (statusCode == HttpStatus.SC_OK){
                //4.2、处理HTTP响应头
                Header[] headers = postMethod.getResponseHeaders();
                for(Header h : headers) {
                    System.out.println(h.getName() + "headers:" + h.getValue());
                }
                //4.3、处理HTTP响应体 方式一:
                /*byte[] responseBody = postMethod.getResponseBody();
                response = new String(responseBody, charset);
                System.out.println("response:" + response);*/

                //方式二:
                is = postMethod.getResponseBodyAsStream();
                br = new BufferedReader(new InputStreamReader(is, charset));
                StringBuffer sbf = new StringBuffer();
                String temp = null;
                while ((temp = br.readLine()) != null) {
                    sbf.append(temp).append("\r\n");
                }
                System.out.println("response:" + sbf);
                response = sbf.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // 5、释放连接
            postMethod.releaseConnection();
        }

        return response;
    }

    public static void main(String[] args) throws IOException {
        String post = doPost("http://127.0.0.1:8080/postHttp", "{\"id\":\"1001\",\"name\":\"丽丽\"}", "UTF-8");
        System.out.println("post:" + post);
    }
}

在这里插入图片描述

get请求:

public class HttpClientDemo {
    /**
     * httpClient的get请求方式
     * 使用GetMethod来访问一个URL对应的网页实现步骤:
     * 1.生成一个 HttpClient 对象并设置相应的参数;
     * 2.生成一个 GetMethod 对象并设置响应的参数;
     * 3.用 HttpClient 生成的对象来执行 GetMethod 生成的 Get 方法;
     * 4.处理HTTP响应内容
     * 5.释放连接。
     */
    public static String doGet(String url, String charset) {
        HttpClient httpClient = null;
        GetMethod getMethod = null;
        String response = "";
        InputStream is = null;
        BufferedReader br = null;

        //1.1、生成HttpClient对象并设置参数
        httpClient = new HttpClient();
        //1.2、设置连接超时时间 单位:毫秒
        httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(15000);

        //2.1、生成GetMethod对象并设置参数
        getMethod = new GetMethod(url);
        //2.2、设置get请求超时时间 单位:毫秒
        getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 60000);
        //2.3、设置请求重试处理,用的是默认的重试处理:请求三次
        getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());

        try {
            //3、执行HTTP GET 请求
            int statusCode = httpClient.executeMethod(getMethod);

            //4.1、判断返回的状态码
            if (statusCode != HttpStatus.SC_OK) {
                System.err.println("请求出错:" + getMethod.getStatusLine());
            }
            //4.2、处理HTTP响应头
            Header[] headers = getMethod.getResponseHeaders();
            for(Header h : headers) {
                System.out.println(h.getName() + "headers:" + h.getValue());
            }
            //4.3、处理HTTP响应体 方式一:
            /*byte[] responseBody = getMethod.getResponseBody();
            response = new String(responseBody, charset);
            System.out.println("response:" + response);*/

            //方式二:
            //读取为InputStream,在网页内容数据量大时候推荐使用
            is = getMethod.getResponseBodyAsStream();
            br = new BufferedReader(new InputStreamReader(is, charset));
            StringBuffer sbf = new StringBuffer();
            String temp = null;
            while ((temp = br.readLine()) != null) {
                sbf.append(temp).append("\r\n");
            }
            System.out.println("response:" + sbf);
            response = sbf.toString();
        } catch (HttpException e) {
            System.out.println("请检查输入的URL!");
            e.printStackTrace();
        } catch (IOException e) {
            //发生网络异常
            System.out.println("发生网络异常!");
        } finally {
            // 关闭资源
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // 5、释放连接
            getMethod.releaseConnection();
        }
        return response;
    }
    
    public static void main(String[] args) throws IOException {
        String get = doGet("http://127.0.0.1:8080/getHttp?id=1001", "UTF-8");
        System.out.println("get:" + get);
    }
}

在这里插入图片描述

服务端使用springboot项目:

@RestController
public class HelloController {
    
    @RequestMapping("/postHttp")
    public String testHttp(@RequestBody Map<String, Object> map){
        System.out.println(map);
        return "post http" ;
    }

    @RequestMapping("/getHttp")
    public String testHttp(@RequestParam String id){
        System.out.println(id);
        return "get http" ;
    }

}

在这里插入图片描述

📌 访问https网址需要配置ssl证书,可以参考 📖 轻松把玩HttpClient之配置ssl,采用绕过证书验证实现https

📌 Java使用HttpClient以multipart/form-data向接口上传文件


3. RestTemplate

RestTemplate内容过多,放在下章介绍。


引用文章:
📖java实现HTTP请求的三种方式
📖Java中实现http请求的方式

4. 应答信息乱码问题

应答信息乱码问题主要原因分为两种,体现在响应报文头的两个属性:

  • Content-Type:text/xml、binary、application/json、text/plain等
  • Content-Encoding:gzip(最常用)、compress、deflate、identity、br(brotli)

Content-Type

响应的属性是application/json encoding=utf-8,这种情况需要指定输入流使用utf-8编码解析,不然会中文乱码。

InputStream is = null;
BufferedReader br = null;
StringBuffer result = new StringBuffer();

is = connection.getInputStream();
// 指定输入流使用 UTF-8
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));

String temp = null;
while (null != (temp = br.readLine())) {
    result.append(temp);
}

Content-Encoding

一般 REST 接口返回明文 JSON 数据,该属性返回null。对于返回大数据的情况,一般会对返回报文进行压缩,再进行传输,压缩方式放在属性 Content-Encoding 中指定。

常用压缩算法是 gzip,2015 年 9 月 Google 推出了无损压缩算法 Brotli。与其他压缩算法相比,它有着更高的压塑压缩效率。启用 Brotli 压缩算法,对比 Gzip 压缩 CDN 流量再减少 20%。

Brotli算法压缩的返回报文头属性 Content-Encoding=br,br 是 Brotli 的简写。

如果用上述的 GET 方法进行接收,因为数据是经过 br 压缩的,所以会输出乱码。

解决方案:对接收数据进行解码。

gzip:
解码工具包含在 java.util.zip.GZIPInputStream

import java.util.zip.GZIPInputStream;

...

//4、获取响应数据
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
    // 获取返回的数据
    is = connection.getInputStream();
    // gzip解码
    GZIPInputStream gzipInputStream = new GZIPInputStream(is);
    if (null != is) {
        br = new BufferedReader(new InputStreamReader(gzipInputStream, "UTF-8"));
        String temp = null;
        while (null != (temp = br.readLine())) {
            result.append(temp);
        }
        System.out.println(connection.getContentEncoding());
    }
}

br(brotli):
需要引入依赖:

<dependency>
  <groupId>org.brotli</groupId>
  <artifactId>dec</artifactId>
  <version>0.1.2</version>
</dependency>
import org.brotli.dec.BrotliInputStream;

...

//4、获取响应数据
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
    // 获取返回的数据
    is = connection.getInputStream();
    // Brotli解码
    BrotliInputStream brotliInputStream = new BrotliInputStream(is);
    if (null != is) {
        br = new BufferedReader(new InputStreamReader(brotliInputStream, "UTF-8"));
        String temp = null;
        while (null != (temp = br.readLine())) {
            result.append(temp);
        }
        System.out.println(connection.getContentEncoding());
    }
}

📖 HttpURLConnection使用GET请求时应答信息乱码问题
📖 解析接口返回报文,压缩格式为br(brotli)乱码解决

后来发现了 Hutool-http,可以非常方便地上传下载文件,推荐读者们去尝试一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会叫的狼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值