工作中一个系统会拆分成很多模块,分工给不同的项目组完成。那就不可避免地造成以下的情况:一个业务需要多个模块共同完成,也就是你必须调用别人的接口,合作完成客户发来的请求。那么怎么样远程调用别人模块中的接口呢?我们一起来看一看。
我们可以看看该类上面的注释
/*
类URL代表一个统一资源定位器,
一个指向万维网上“资源”的指针。
资源可以是简单的文件或目录,也可以是对更复杂对象的引用,
例如对数据库或搜索引擎的查询。
*/
根据注释我们可以大致了解URL是用来访问万维网或者说互联网上的资源的类。
还是先看方法上的注释
/**
返回一个URLConnection实例,该实例表示与URL所引用的远程对象的连接。
每次调用此URL的协议处理程序的
UrlStreamHandler.openConnection(URL)
方法时,都会创建URLConnection的新实例。
应该注意,URLConnection实例在创建时并不建立实际的网络连接。
只有在调用URLConnection.connect()时才会发生这种情况。
如果对于URL的协议(如HTTP或JAR),存在一个公共的、专用的URLConnection子
类,
该子类属于以下包之一或它们的子包之一:java.lang、java.io、
java.util、
java.io,
则返回的连接将属于该子类。
例如,对于HTTP,将返回一个HttpURLConnection,对于JAR,
将返回一个JarURLConnection。
**/
获取一个当前地址的连接对象,但并没有建立连接。注意注释中的URLConnection实例在创建时并不建立实际的网络连接。
只有在调用URLConnection.connect()时才会发生这种情况。
先看类上的注释
/*
支持HTTP特定功能的URLConnection。详情参见规格。
每个HttpURLConnection实例用于发出一个请求,但是到HTTP服务器的
底层网络连接可以由其他实例透明地共享。
在请求后调用HttpURLConnection的InputStream或
OutputStream上的close()方法可能会释放与此实例关联的网络资源,
但不会影响任何共享的持久连接。
如果一个持久连接在那时处于空闲状态,
调用disconnect()方法可能会关闭底层套接字。
*/
注意注释中的每个HttpURLConnection实例用于发出一个请求,也就是一个该类对象对应一个需要发出的请求。可以看作是访问请求的具体连接。还有一点调用disconnect()方法可能会关闭底层套接字,可以将之看作成关闭连接。
既然是具体连接,那肯定有很多的设置,比如请求类型是Post还是Get,连接是否是长连接,浏览器代理是什么、是否使用缓存、超时时长等等,都需要自己手动配置。具体方法大家可以看看源码。
注释
/*
打开指向此URL引用的资源的通信链接(如果尚未建立这样的连接)。
如果在连接已经打开时调用connect方法
(由值为true的connected字段指示),
则该调用将被忽略。
URLConnection对象经历两个阶段:
首先创建它们,然后连接它们。
在被创建之后,并且在被连接之前,
可以指定各种选项(例如,doInput和UseCaches)。
连接后,试图设置它们是错误的。
如有必要,依赖于连接的操作,
如getContentLength,将隐式执行连接。
*/
在这方法中与访问的接口进行连接。
现在我们大概知道了用到的类与方法,那么具体流程应该也能理出来了:
1、创建URL
2、通过openConnection()对象获取连接的对象(HttpURLConnection)
3、通过HttpURLConnection中的setXXX()方法设置连接对象的基本属性
4、调用connect()正式连接,
5、既然有连接,那么执行完任务就需要释放连接disconnect()。
具体流程如下
其实说简单点访问接口用的就是HttpURLConnection,URL只是用来构造HttpURLConnection的工具。
/**
* @description
* @author 三文鱼先生
* @date 10:27 2022/8/15
* @param url 接口的地址及方法名称
* @param map 参数的键值对
* @return java.lang.String
**/
public static String doPost(String url , HashMap<String , String> map) throws IOException {
StringBuilder urlPath = new StringBuilder(url);
//拼接参数
if(map != null) {
urlPath.append("?");
map.forEach((k,v)-> {
try {
//这里的值需要编码
urlPath.append(k).append("=").append(URLEncoder.encode(v,"UTF-8")).append("&");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
);
//去掉最后一个&
urlPath.deleteCharAt(urlPath.length() - 1);
}
BufferedReader reader = null;
try {
//创建连接
System.out.println("请求路径为:" + urlPath);
URL urlCon = new URL(urlPath.toString());
HttpURLConnection httpCon = (HttpURLConnection) urlCon.openConnection();
//设置连接的基本信息
//请求方式为Post
httpCon.setRequestMethod("POST");
//设置通用的请求属性
httpCon.setRequestProperty("accept", "*/*");
httpCon.setRequestProperty("connection", "Keep-Alive");
httpCon.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
httpCon.setRequestProperty("Content-Type", "application/json;charset=utf-8");
//是否可读写
httpCon.setDoOutput(true);
httpCon.setDoInput(true);
//是否使用缓存
httpCon.setUseCaches(false);
//设置连接超时60s
httpCon.setConnectTimeout(60000);
//设置读取响应超时60s
httpCon.setReadTimeout(60000);
//正式连接
httpCon.connect();
//获取调用接口返回信息 等待调用接口返回
boolean sign = true;
while (sign) {
System.out.println(httpCon.getInputStream().available());
if(httpCon.getInputStream().available() > 0) {
sign = false;
} else {
//0.5s检查一次是否有执行返回
Thread.sleep(500);
}
}
StringBuilder result = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
String temp = "";
while ((temp = reader.readLine()) != null ) {
result.append(temp);
}
httpCon.disconnect();
System.out.println("返回数据为:" + result);
return result.toString();
}catch (IOException exception) {
exception.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
if(reader != null) reader.close();
}
return "遇到未知错误";
}
那我们这里给接口的参数为该对象的Json字符串即可
/**
* @description
* @author 三文鱼先生
* @date 11:23 2022/8/15
* @param url 接口地址
* @param objectJson 所需要的对象json
* @return java.lang.String
**/
public static String doPost(String url , String objectJson) throws IOException {
StringBuilder urlPath = new StringBuilder(url);
//请求对应接口
BufferedReader reader = null;
BufferedWriter writer = null;
try {
//创建连接
System.out.println("请求路径为:" + urlPath);
URL urlCon = new URL(urlPath.toString());
HttpURLConnection httpCon = (HttpURLConnection) urlCon.openConnection();
//设置连接的基本信息
//请求方式为Post
httpCon.setRequestMethod("POST");
//设置通用的请求属性
httpCon.setRequestProperty("accept", "*/*");
httpCon.setRequestProperty("connection", "Keep-Alive");
httpCon.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
httpCon.setRequestProperty("Content-Type", "application/json;charset=utf-8");
//是否可读写
httpCon.setDoOutput(true);
httpCon.setDoInput(true);
//是否使用缓存
httpCon.setUseCaches(false);
//设置连接超时60s
httpCon.setConnectTimeout(60000);
//设置读取响应超时60s
httpCon.setReadTimeout(60000);
//正式连接
httpCon.connect();
//在这里传递对象的json
writer = new BufferedWriter(new OutputStreamWriter(httpCon.getOutputStream()));
//发送请求参数即数据
writer.write(objectJson);
//flush输出流的缓冲
writer.flush();
StringBuilder result = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(httpCon.getInputStream()));
String temp = "";
while ((temp = reader.readLine()) != null ) {
result.append(temp);
}
httpCon.disconnect();
System.out.println("返回数据为:" + result);
return result.toString();
}catch (IOException exception) {
exception.printStackTrace();
} finally {
if(reader != null) reader.close();
if(writer != null) writer.close();
}
return "遇到未知错误";
}
测试的话 大家可以再开一个搭好的项目,然后去访问其中的接口就行了,我这里测试的是本地的一个新增数据接口。
具体调用其他人接口的时候记得把localhost改成对应的ip和端口就可以了
其实其中的读写数据跟我之前用套接字搭建的FTP差不多,大家也可以去看看。 Java使用Socket简单实现FTP
当然了调用三方接口不止有这一个办法,还有其他的方法调用。大家可以参考这一篇:Java 调用第三方接口方法