简单描述一下我的应用场景,我们有两个项目分别部署在不同的服务器上,然后a项目中的某个功能需要调用b项目的接口去完成一些数据的同步和查询,并且b项目中还要做到一个ip的白名单限制,只有规定的ip才能访问,所以需要在a项目中编写一个远程访问类,下面就采用了URLConnection和HttpURLConnection分别封装了一个工具类
另外,这两个抽象类的区别我这里做了一个简单的记录,如果想要更清晰一些的讲解可以参考这位大神的帖子
1.URLConnection:抽象类 URLConnection 是所有类的超类,它代表应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源。URLConnection 基于Http协议
package com.xxx.xxx.common.utils;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
@Slf4j
public class HttpUtils {
/**
* GET请求
* @param url 请求URL 参数用?和&拼接好在入参
* @return
*/
public static String get(String url) {
String result = "";
InputStream in = null;
try {
//1.通过在 URL 上调用 openConnection 方法创建连接对象
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
//2.处理设置参数和一般请求属性
//2.1设置参数
//可以根据请求的需要设置参数
conn.setUseCaches(false);
conn.setConnectTimeout(5000); //请求超时时间
//2.2设置通用的请求属性,更多的头字段信息可以查阅HTTP协议
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
//3.使用 connect 方法建立到远程对象的实际连接。
conn.connect();
//获取URLConnection对象对应的输入流
in = conn.getInputStream();
//解析对方服务器返回的数据
result = readInputStream(in);
//关闭流
in.close();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
}
}
log.info("result=----" + result);
return result;
}
/**
* POST请求
* @param url 请求URL
* @param param 请求参数,请求参数格式 name1=value1&name2=value2(也可已同get方法一样直接拼接号url,params直接如" ")
* @return
*/
public static String post(String url, String param) {
PrintWriter out = null;
InputStream in = null;
String result = "";
try {
//1.通过在 URL 上调用 openConnection 方法创建连接对象
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
//2.处理设置参数和一般请求属性
//2.1发送POST请求必须设置如下两行 setDoOutput 和 setDoInput
conn.setDoOutput(true);//默认为false 发送post请求必须设置setDoOutput(true)
conn.setDoInput(true);//默认为true 所以不设置也可以
conn.setUseCaches(false); //是否可以使用缓存 不使用缓存
//2.2设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
//2.3设置请求正文 即要提交的数据
out = new PrintWriter(conn.getOutputStream());
out.print(param);
out.flush();
//获取URLConnection对象对应的输入流
in = conn.getInputStream();
//解析对方服务器返回的数据
result = readInputStream(in);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
try {
if (out != null) {
out.close();
}
} finally {
if (in != null) {
in.close();
}
}
} catch (Exception ex) {
}
}
return result;
}
//解析对方服务器返回流
public static String readInputStream(InputStream in) throws IOException {
byte[] b=new byte[1024];
StringBuffer sb1=new StringBuffer();
int length=0;
while ((length=in.read(b))!=-1){
String s=new String(b, 0,length);
sb1.append(s);
}
return sb1.toString();
}
public static void main(String[] args) {
//远程连接请求数据
String data = HttpUtils.get("http://x.x.x.x:7788/xxx/xxx/xxx?xxx=123456798.....");
String data1 = HttpUtils.post("http://x.x.x.x:7788/xxx/xxx/xxx","xxx=123456789...");
String data2 = HttpUtils.post("http://x.x.x.x:7788/xxx/xxx/xxx?xxx=123456798...","");
System.out.println("get="+data);
System.out.println("post="+data1);
System.out.println("post="+data2);
}
}
2.HttpURLConnection:支持 HTTP 特定功能的 URLConnection。每个 HttpURLConnection 实例都可用于生成单个请求,但是其他实例可以透明地共享连接到 HTTP 服务器的基础网络。请求后在 HttpURLConnection 的 InputStream 或 OutputStream 上调用 close() 方法可以释放与此实例关联的网络资源,但对共享的持久连接没有任何影响。如果在调用 disconnect() 时持久连接空闲,则可能关闭基础套接字,HttpURLConnection继承自URLConnection,相比较URLConnection类多了以下方法。
- getResponseCode 从 HTTP 响应消息获取状态码。
- getResponseMessage 获取与来自服务器的响应代码一起返回的 HTTP 响应消息(如果有)。
package com.xxx.xxx.common.utils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.List;
import java.util.Map;
public class HttpUtils2 {
/**
* GET请求
* @param geturl 请求URL 参数用?和&拼接好在入参
* @return
*/
public static String doGet(String geturl) {
try {
//1.通过在 URL 上调用 openConnection 方法创建连接对象
URL url=new URL(geturl);
//此处的urlConnection对象实际上是根据URL的请求协议(此处是http)生成的URLConnection类的子类HttpURLConnection,
//故此处最好将其转化为HttpURLConnection类型的对象
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
//2.处理设置参数和一般请求属性
//2.1设置参数
//可以根据请求的需要设置参数
conn.setRequestMethod("GET"); //默认为GET 所以GET不设置也行
conn.setUseCaches(false);
conn.setConnectTimeout(5000); //请求超时时间
//2.2请求属性
//设置通用的请求属性 更多的头字段信息可以查阅HTTP协议
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
//3.使用 connect 方法建立到远程对象的实际连接。
conn.connect();
//获取URLConnection对象对应的输入流
InputStream in = conn.getInputStream();
//4.远程对象变为可用。远程对象的头字段和内容变为可访问。
//4.1获取HTTP 响应消息获取状态码
if(conn.getResponseCode()==200){//一般200都是请求成功,这里根据自己的实际业务来处理
//4.2获取响应的头字段
Map<String, List<String>> headers=conn.getHeaderFields();
System.out.println(headers); //输出头字段
//4.3获取响应正文
//解析对方服务器返回的数据
String result = readInputStream(in);
return result;
}
//关闭流
in.close();
//断开连接,最好写上,disconnect是在底层tcp socket链接空闲时才切断。如果正在被其他线程使用就不切断。
//固定多线程的话,如果不disconnect,链接会增多,直到收发不出信息。写上disconnect后正常一些。
conn.disconnect();//只有httpURLConnection中有,URLConnection 是没有的
} catch (ProtocolException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* POST请求
* @param posturl 请求URL
* @param params 请求参数,请求参数格式 name1=value1&name2=value2 (也可已同get方法一样直接拼接号url,params直接如" ")
* @return
*/
public static String doPost(String posturl,String params) {
try {
//1.通过在 URL 上调用 openConnection 方法创建连接对象
URL url=new URL(posturl);
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
//2.处理设置参数和一般请求属性
//2.1设置参数,发送POST请求必须设置如下两行 setDoOutput 和 setDoInput
conn.setRequestMethod("POST");
conn.setDoOutput(true);//默认为false 发送post请求必须设置setDoOutput(true)
conn.setDoInput(true);//默认为true 所以不设置也可以
conn.setUseCaches(false); //是否可以使用缓存 不使用缓存
conn.setConnectTimeout(5000);//请求超时时间
//2.2请求属性
//设置通用的请求属性 消息报头 即设置头字段 更多的头字段信息可以查阅HTTP协议
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
//2.3设置请求正文 即要提交的数据
PrintWriter pw=new PrintWriter(new OutputStreamWriter(conn.getOutputStream()));
pw.print(params);
pw.flush();
pw.close();
//3.使用 connect 方法建立到远程对象的实际连接。
conn.connect();
InputStream in=conn.getInputStream();
//4.远程对象变为可用。远程对象的头字段和内容变为可访问。
//4.1获取HTTP 响应消息获取状态码
if(conn.getResponseCode()==200)
{
//4.2获取响应的头字段
Map<String, List<String>> headers=conn.getHeaderFields();
System.out.println(headers); //输出头字段
//4.3获取响应正文
//解析对方服务器返回的数据
String result = readInputStream(in);
return result;
}
in.close();
//断开连接,最好写上,disconnect是在底层tcp socket链接空闲时才切断。如果正在被其他线程使用就不切断。
//固定多线程的话,如果不disconnect,链接会增多,直到收发不出信息。写上disconnect后正常一些。
conn.disconnect();//只有httpURLConnection中有,URLConnection 是没有的
} catch (ProtocolException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
//解析对方服务器返回流
public static String readInputStream(InputStream in) throws IOException {
byte[] b=new byte[1024];
StringBuffer sb1=new StringBuffer();
int length=0;
while ((length=in.read(b))!=-1){
String s=new String(b, 0,length);
sb1.append(s);
}
return sb1.toString();
}
public static void main(String[] args) {
//远程连接请求数据
String data = HttpUtils2.doGet("http://192.168.1.39:7788/xxx/xxx/xxx?xxx=123456798...");
String data1 = HttpUtils2.doPost("http://192.168.1.39:7788/xxx/xxx/xxx","xxx=12345679...");
String data2 = HttpUtils2.doPost("http://192.168.1.39:7788/xxx/xxx/xxx?xxx=123456798...","");
System.out.println("get="+data);
System.out.println("post="+data1);
System.out.println("post="+data2);
}
}