java使用httpclient 、HttpURLConnection 发送第三方请求 使用详解、总结。HttpClient 的使用

您所在的位置:网站首页 发送还有第2个方法 java使用httpclient 、HttpURLConnection 发送第三方请求 使用详解、总结。HttpClient 的使用

java使用httpclient 、HttpURLConnection 发送第三方请求 使用详解、总结。HttpClient 的使用

2024-04-09 06:54| 来源: 网络整理| 查看: 265

文章目录 一、前言二、HttpURLConnection1. 介绍2. 依赖 三、GET、POST请求1、GET请求2、POST请求3、总结a、connect()方法调用不调用:b、是否调用connect方法?c、openConnection()方法到底是如何返回URLConnection对象的:d、必须调用getResponseCode()方法 。 四、小方法解释1、flush() 五、HttpClient 开发webservice1、doGet 请求2、doPost 请求3、doDelete请求4、doPut 请求 六、遇到的异常1. java.net.SocketTimeoutException: Read timed out 异常a、异常信息b、异常描述c、解决方法

一、前言

实习第二个月了,遇到了一个问题,需求使用Java 的 HttpURLConnection 来转发请求。需求也给了示例,但是流程不明白,所以再网上查找了很长时间之后,特来总结一番。

3.3中,是关于这次的问题总结,建议大家看一下。

这里的demo 可以直接拿出来用的,

二、HttpURLConnection 1. 介绍

JDK的java.net包中提供了访问HTTP协议的基本功能的类:HttpURLConnection。

URLConnection是个抽象类,它有两个直接子类分别是HttpURLConnection和JarURLConnection。另外一个重要的类是URL,通常URL可以通过传给构造器一个String类型的参数来生成一个指向特定地址的URL实例。

HttpURLConnection是Java的标准类,它继承自URLConnection,可用于向指定网站发送GET请求、POST请求。它在URLConnection的基础上提供了如下便捷的方法:

int getResponseCode(); // 获取服务器的响应代码。 String getResponseMessage(); // 获取服务器的响应消息。 String getResponseMethod(); // 获取发送请求的方法。 void setRequestMethod(String method); // 设置发送请求的方法。

每个 HttpURLConnection 实例都可用于生成单个请求,但是其他实例可以透明地共享连接到 HTTP 服务器的基础网络。请求后在 HttpURLConnection 的 InputStream 或 OutputStream 上调用 close() 方法可以释放与此实例关联的网络资源,但对共享的持久连接没有任何影响。如果在调用 disconnect() 时持久连接空闲,则可能关闭基础套接字。

2. 依赖 org.apache.httpcomponents httpclient 4.5.2 org.apache.httpcomponents httpmime 4.5.3 org.apache.commons commons-lang3 3.8.1 三、GET、POST请求 1、GET请求 package com.feng.demo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; /** * GET请求示例 * * @author 安辰 * */ public class GetDemo { public void doGet(String[] args) { HttpURLConnection httpURLConnection = null; try { // 1. 得到访问地址的URL URL url = new URL( "http://localhost:8080/Servlet/do_login.do?username=test&password=123456"); // 2. 得到网络访问对象java.net.HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); /* 3. 设置请求参数(过期时间,输入、输出流、访问方式),以流的形式进行连接 */ // 设置是否向HttpURLConnection输出 httpURLConnection.setDoOutput(false); // 设置是否从httpUrlConnection读入 httpURLConnection.setDoInput(true); // 设置请求方式 默认为GET httpURLConnection.setRequestMethod("GET"); // 设置是否使用缓存 httpURLConnection.setUseCaches(true); // 设置此 HttpURLConnection 实例是否应该自动执行 HTTP 重定向 httpURLConnection.setInstanceFollowRedirects(true); // 设置超时时间 httpURLConnection.setConnectTimeout(3000); // 连接 httpURLConnection.connect(); // 4. 得到响应状态码的返回值 responseCode int code = httpURLConnection.getResponseCode(); // 5. 如果返回值正常,数据在网络中是以流的形式得到服务端返回的数据 String msg = ""; if (code == 200) { // 正常响应 // 从流中读取响应信息 BufferedReader reader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { // 循环从流中读取 msg += line + "\n"; } reader.close(); // 关闭流 } // 显示响应结果 log.info(msg); } catch (IOException e) { log.error("转发出错,错误信息:"+e.getLocalizedMessage()+";"+e.getClass()); }finally { // 6. 断开连接,释放资源 if (null != httpURLConnection){ try { httpURLConnection.disconnect(); }catch (Exception e){ log.info("httpURLConnection 流关闭异常:"+ e.getLocalizedMessage()); } } } } } 2、POST请求 package com.feng.demo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; /** * POST请求示例 * * @author 安辰 * */ public class PostDemo { public void doPost(String[] args) { HttpURLConnection httpURLConnection = null; try { // 1. 获取访问地址URL URL url = new URL("http://localhost:8080/Servlet/do_login.do"); // 2. 创建HttpURLConnection对象 httpURLConnection = (HttpURLConnection) url.openConnection(); /* 3. 设置请求参数等 */ // 请求方式 默认 GET httpURLConnection.setRequestMethod("POST"); // 超时时间 httpURLConnection.setConnectTimeout(3000); // 设置是否输出 httpURLConnection.setDoOutput(true); // 设置是否读入 httpURLConnection.setDoInput(true); // 设置是否使用缓存 httpURLConnection.setUseCaches(false); // 设置此 HttpURLConnection 实例是否应该自动执行 HTTP 重定向 httpURLConnection.setInstanceFollowRedirects(true); // 设置请求头 httpURLConnection.addRequestProperty("sysId","sysId"); // 设置使用标准编码格式编码参数的名-值对 httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); // 连接 httpURLConnection.connect(); /* 4. 处理输入输出 */ // 写入参数到请求中 String params = "username=test&password=123456"; OutputStream out = httpURLConnection.getOutputStream(); out.write(params.getBytes()); // 简化 //httpURLConnection.getOutputStream().write(params.getBytes()); out.flush(); out.close(); // 从连接中读取响应信息 String msg = ""; int code = httpURLConnection.getResponseCode(); if (code == 200) { BufferedReader reader = new BufferedReader( new InputStreamReader(httpURLConnection.getInputStream())); String line; while ((line = reader.readLine()) != null) { msg += line + "\n"; } reader.close(); } // 处理结果 log.info(msg); } catch (IOException e) { log.error("转发出错,错误信息:"+e.getLocalizedMessage()+";"+e.getClass()); }finally { // 5. 断开连接 if (null != httpURLConnection){ try { httpURLConnection.disconnect(); }catch (Exception e){ log.info("httpURLConnection 流关闭异常:"+ e.getLocalizedMessage()); } } } } } 3、总结

从网上找资料的时候,发现 connect() 和 flush() 方法有时写,有时不写,还没有理由,特来总结一番。

a、connect()方法调用不调用: 调用connect()只是建立连接,并不会向服务器传送数据,只要调用getResponseCode(),就不必要调用connect方法(调用也无妨)。 b、是否调用connect方法?

不需要显示调用connect方法

c、openConnection()方法到底是如何返回URLConnection对象的: openConnection()在你不自己实现网络协议等网络相关抽象类和抽象接口的情况下,此方法最终调用的是sun.net.www.protocol.http.Handler类中的方法 d、必须调用getResponseCode()方法 。 安辰试了一下在不调用getResponseCode()方法的时候,无论是否调用connect()方法,请求都是不能成功的,调用connect()方法只是建立连接,并不会向服务器传递数据。只用调用getRespconseCode()方法时,才会向服务器传递数据(有博文说是getInputStream()才会向服务器传递数据,getResponseCode中会调用getInputStream方法)。跟着getResponseCode()源码发现里面调用了getInputStream()方法,在getInputStream()方法中会判断当前是否连接,如果没有连接,则调用connect()方法建立连接。 四、小方法解释 1、flush()

flush()意思是把**缓冲区的内容强制的写出**。 因为操作系统的某些机制,为了防止一直不停地磁盘读写,所以有了延迟写入的概念,(注意不要和frush()刷新混淆了)

主要用在IO中,即清空缓冲区数据,一般在读写流(stream)的时候,数据是先被读到了内存中,再把数据写到文件中,当你数据读完的时候不代表你的数据已经写完了,因为还有一部分有可能会留在内存这个缓冲区中。这时候如果你调用了close()方法关闭了读写流,那么这部分数据就会丢失,所以应该在关闭读写流之前先flush()。。

为了防止过于频繁的写操作 所以Java提供了一个java.io.BufferedOutputStream类 内部持有一个缓冲区 默认不直接将数据写到硬盘上 而是存到缓冲区中 直到一定条件后触发(就是调用上面的flushBuffer()了) 也可以强制通过flush()方法提前触发。

所以当你认为你完成了某一个比较重要的操作的时候 最好进行一次flush 防止数据在内存中丢失。 多数时候,如果你最后会调用一次close方法,flush方法是可以不使用的,除非你明确的想使数据尽早写到磁盘或者网络上。

五、HttpClient 开发webservice 1、doGet 请求 package com.uniview.mqtohttp.utils; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpEntity; import org.apache.http.HttpStatus; import org.apache.http.clienthods.*; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import java.io.IOException; import java.nio.charset.Charset; @Slf4j public final class HttpClientUtils { /** * @param url * @param token * @return */ public static String doGetToken(String url, String token) { log.info("Post请求url:[{}]", url); CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; String result = null; try { httpClient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet(url); // 构造请求头 httpGet.setHeader("Content-type", "application/json; charset=utf-8"); httpGet.setHeader("Connection", "keep-alive"); //httpGet.setHeader("Authorization", token); // token 鉴权 RequestConfig.Builder builder = RequestConfig.custom(); builder.setSocketTimeout(500); //设置请求时间 builder.setConnectTimeout(500); //设置超时时间 builder.setRedirectsEnabled(false);//设置是否跳转链接(反向代理) // 设置 连接 属性 httpGet.setConfig(builder.build()); // 执行Get请求 response = httpClient.execute(httpGet); // 获取响应实体 HttpEntity responseEntity = response.getEntity(); // 检验返回码 int statusCode = response.getStatusLine().getStatusCode(); log.info("获取返回信息,get 请求,返回的 状态码:" + statusCode); if (HttpStatus.SC_OK == statusCode) { result = EntityUtils.toString(responseEntity, "utf-8"); log.info("Get请求200响应结果:{}", result); return result; } } catch (IOException e) { log.error("获取日志。发送Get请求失败", e); } finally { // 关闭资源 if (null != response) { try { response.close(); } catch (IOException e) { log.error("response流关闭异常:", e.getMessage()); } } if (null != httpClient) { try { httpClient.close(); } catch (IOException e) { log.error("httpClient流关闭异常:", e.getMessage()); } } } return result; } 2、doPost 请求 /** * @param url * @param token * @param param * @return */ public static String doPostToken(String url, String token, String param){ CloseableHttpClient client = null; CloseableHttpResponse response = null; HttpPost httpPost = null; String result = null; try { client = HttpClients.createDefault(); httpPost = new HttpPost(url); httpPost.setHeader("Content-type", "application/json; charset=utf-8"); httpPost.setHeader("Connection", "keep-alive"); httpPost.setHeader("Authorization", token); StringEntity stringEntity = new StringEntity(param,"UTF-8"); stringEntity.setContentEncoding("UTF-8"); // 数据格式为 json stringEntity.setContentType("application/json"); httpPost.setEntity(stringEntity); response = client.execute(httpPost); HttpEntity entity = response.getEntity(); int statusCode = response.getStatusLine().getStatusCode(); log.info("获取返回信息,get 请求,返回的 状态码:" + statusCode); if (HttpStatus.SC_OK == statusCode) { result = EntityUtils.toString(entity, "utf-8"); log.info("Get请求200响应结果:{}", result); return result; } } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源 if (null != response) { try { response.close(); } catch (IOException e) { log.error("response流关闭异常:", e.getMessage()); } } if (null != client) { try { client.close(); } catch (IOException e) { log.error("httpClient流关闭异常:", e.getMessage()); } } } return result; } 3、doDelete请求 /** * @param url * @param token * @return */ public static String doDeleteToken(String url, String token) { CloseableHttpClient client = null; CloseableHttpResponse response = null; HttpDelete httpDelete; String result = null; try { client = HttpClients.createDefault(); httpDelete = new HttpDelete(url); httpDelete.setHeader("Content-type", "application/json; charset=utf-8"); httpDelete.setHeader("Connection", "keep-alive"); httpDelete.setHeader("Authorization", token); response = client.execute(httpDelete); HttpEntity entity = response.getEntity(); int statusCode = response.getStatusLine().getStatusCode(); log.info("获取返回信息,get 请求,返回的 状态码:" + statusCode); if (HttpStatus.SC_OK == statusCode) { result = EntityUtils.toString(entity, "utf-8"); log.info("Get请求200响应结果:{}", result); return result; } } catch (IOException e) { e.printStackTrace(); } finally { if (null != response) { try { response.close(); } catch (IOException e) { log.error("response流关闭异常:", e.getMessage()); } } if (null != client) { try { client.close(); } catch (IOException e) { log.error("httpClient流关闭异常:", e.getMessage()); } } } return result; } 4、doPut 请求 /** * @param url * @param token * @return */ public static String doPutToken(String url, String token, String param) { CloseableHttpClient client = null; CloseableHttpResponse response =null; HttpPut httpPut = null; String result=null; try { client = HttpClients.createDefault(); httpPut = new HttpPut(url); httpPut.setHeader("Content-type", "application/json; charset=utf-8"); httpPut.setHeader("Connection", "keep-alive"); httpPut.setHeader("Authorization", token); StringEntity stringEntity = new StringEntity(param, Charset.forName("UTF-8")); stringEntity.setContentEncoding("UTF-8"); stringEntity.setContentType("application/json"); httpPut.setEntity(stringEntity); response = client.execute(httpPut); int statusCode = response.getStatusLine().getStatusCode(); HttpEntity entity = response.getEntity(); log.info("获取返回信息,get 请求,返回的 状态码:" + statusCode); if (HttpStatus.SC_OK == statusCode) { result = EntityUtils.toString(entity, "utf-8"); log.info("Get请求200响应结果:{}", result); return result; } } catch (IOException e) { e.printStackTrace(); } finally { if (null != response){ try { response.close(); } catch (IOException e) { log.error("response流关闭异常:", e.getMessage()); } } if (null != client){ try { client.close(); } catch (IOException e) { log.error("httpClient流关闭异常:", e.getMessage()); } } } return result; } } 六、遇到的异常 1. java.net.SocketTimeoutException: Read timed out 异常 a、异常信息 2022-10-18 21:16:16.937 INFO 2788 --- [nio-8084-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms 2022-10-18 21:16:17.153 INFO 2788 --- [nio-8084-exec-1] c.e.demo_fengfanli.utils.HttpUtils : Post 请求url:[http://172.31.254.76:5000/text/text_process] 2022-10-18 21:16:17.838 ERROR 2788 --- [nio-8084-exec-1] c.e.demo_fengfanli.utils.HttpUtils : 获取日志。发送Post请求失败 java.net.SocketTimeoutException: Read timed out at java.base/sun.nio.ch.NioSocketImpl.timedRead(NioSocketImpl.java:280) ~[na:na] at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:306) ~[na:na] at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:347) ~[na:na] at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:800) ~[na:na] at java.base/java.net.Socket$SocketInputStream.read(Socket.java:966) ~[na:na] b、异常描述

使用httpclient发送第三方请求时报错。

c、解决方法

解决: 将超时时间设置更长

RequestConfig.Builder builder = RequestConfig.custom(); builder.setConnectionRequestTimeout(5000); builder.setSocketTimeout(5000); //设置请求时间 builder.setConnectTimeout(5000); //设置超时时间 builder.setRedirectsEnabled(false);//设置是否跳转链接(反向代理) // 设置 连接 属性 httpPost.setConfig(builder.build());

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3