实习第二个月了,遇到了一个问题,需求使用Java 的 HttpURLConnection 来转发请求。需求也给了示例,但是流程不明白,所以再网上查找了很长时间之后,特来总结一番。
3.3中,是关于这次的问题总结,建议大家看一下。
这里的demo 可以直接拿出来用的,
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() 时持久连接空闲,则可能关闭基础套接字。
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());
}
}
}
}
}
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());
}
}
}
}
}
从网上找资料的时候,发现 connect() 和 flush() 方法有时写,有时不写,还没有理由,特来总结一番。
不需要显示调用connect方法
flush()意思是把**缓冲区的内容强制的写出**。 因为操作系统的某些机制,为了防止一直不停地磁盘读写,所以有了延迟写入的概念,(注意不要和frush()刷新混淆了)
主要用在IO中,即清空缓冲区数据,一般在读写流(stream)的时候,数据是先被读到了内存中,再把数据写到文件中,当你数据读完的时候不代表你的数据已经写完了,因为还有一部分有可能会留在内存这个缓冲区中。这时候如果你调用了close()方法关闭了读写流,那么这部分数据就会丢失,所以应该在关闭读写流之前先flush()。。
为了防止过于频繁的写操作 所以Java提供了一个java.io.BufferedOutputStream类 内部持有一个缓冲区 默认不直接将数据写到硬盘上 而是存到缓冲区中 直到一定条件后触发(就是调用上面的flushBuffer()了) 也可以强制通过flush()方法提前触发。
所以当你认为你完成了某一个比较重要的操作的时候 最好进行一次flush 防止数据在内存中丢失。
多数时候,如果你最后会调用一次close方法,flush方法是可以不使用的,除非你明确的想使数据尽早写到磁盘或者网络上。
package com.uniview.mqtohttp.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.*;
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;
}
/**
* @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;
}
/**
* @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;
}
/**
* @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;
}
}