小编最近在写一个登录功能,但是用户user表不在我方的数据库,而在对方的数据库中,小编只能调用对方的登录接口进行验证用户信息,然后调用用户的信息,添加到缓存中,那么,如何在后端调用对方的接口呢?话不多说,让我们一起看看。
小编在百度了半个多小时后,发现了一个强大的工具,HttpComponents,非常方便。
文章目录
HttpComponents介绍
首先我们来了解下HttpComponents
超文本传输协议(HTTP)可能是当今Internet上使用的最重要的协议。Web服务,支持网络的设备和网络计算的增长继续将HTTP协议的作用扩展到用户驱动的Web浏览器之外,同时增加了需要HTTP支持的应用程序的数量。
HttpComponents是为扩展而设计的,同时提供对基本HTTP协议的强大支持,对于构建HTTP感知的客户端和服务器应用程序(例如Web浏览器,Web Spider,HTTP代理,Web服务传输库或利用或扩展HTTP协议以进行分布式通信。
HttpComponents核心
HttpCore是一组低级HTTP传输组件,可用于以最小的占用空间构建自定义的客户端和服务器端HTTP服务。HttpCore支持两种I / O模型:基于经典Java I / O的阻塞I / O模型和基于Java NIO的非阻塞事件驱动的I / O模型。
HttpComponents客户端
HttpClient是基于HttpCore的HTTP / 1.1兼容HTTP代理实现。它还提供了用于客户端身份验证,HTTP状态管理和HTTP连接管理的可重用组件。HttpComponents Client是Commons HttpClient 3.x的继承者和替代者。
HttpComponents使用
我这里呢是使用的maven
导入依赖
我这里导入的是4.5.13的版本,大家想要导出其他版本可以在这里查找mvnrepository
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
get和post请求
参考链接:
https://www.cnblogs.com/jpfss/p/8085505.html
Get与Post在传递参数时有一些区别,Get请求的参数作为查询字符串出传递,而Post请求的参数则作为实体传递。在开发WEB项目时经常遇到乱码的问题,使用HttpComponents也会涉及到这个问题,所以在使用时应特别注意。服务器端的处理方法与WEB项目相同, HttpComponents只要注意字符编码就可以了。
Get请求传递参数方法一:将查询字符串作为请求地址的一部分
这是一种最简单的传参方式,将查询参数用(&)连接,然后放在请求地址?的后面,如下面这个请求地址
get请求
// (1)创建查询参数
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("name", "ahopedog"));
params.add(new BasicNameValuePair("work", "程序员"));
String queryString = URLEncodedUtils.format(params, "utf-8");
// (2) 创建Get实例
URI uri = URIUtils.createURI("http", "localhost", 8080, "/jsx/servlet", queryString, null);
HttpGet get = new HttpGet(uri);
get.getRequestLine();
createURL被淘汰
注意:
但是,我们在写入的时候发现,createURL已经被deprecated 了
public static URI createURI(
final String scheme,
final String host,
final int port,
final String path,
final String query,
final String fragment) throws URISyntaxException {
final StringBuilder buffer = new StringBuilder();
if (host != null) {
if (scheme != null) {
buffer.append(scheme);
buffer.append("://");
}
buffer.append(host);
if (port > 0) {
buffer.append(':');
buffer.append(port);
}
}
if (path == null || !path.startsWith("/")) {
buffer.append('/');
}
if (path != null) {
buffer.append(path);
}
if (query != null) {
buffer.append('?');
buffer.append(query);
}
if (fragment != null) {
buffer.append('#');
buffer.append(fragment);
}
return new URI(buffer.toString());
}
然后我们肯定要查为什么要被deprecated
然后发现此方法是从HttpClient 4.2版以后开始标记为Deprecated的。官方推荐使用URI
类来取代它。
java.net.URI类的构造方法:
URI(String scheme, String userInfo, String host, int port, String path, String query, String fragment)
参数说明
scheme:协议名
userInfo:用户名及授权信息
host:主机名
port:端口号
path:路径
query:查询
fragment:片段
我天,七个参数?
我发现我url构造方法中最多的也就5个
而且我导入的也就是java.net呀,那多出来的参数是什么
我便去查URL类的源码,还别说,真让我找见了
public URI(String scheme,
String userInfo, String host, int port,
String path, String query, String fragment)
throws URISyntaxException
{
String s = toString(scheme, null,
null, userInfo, host, port,
path, query, fragment);
checkPath(s, scheme, path);
new Parser(s).parse(true);
}
但其实我们不需要那么多
只需要协议,ip,端口和路径,所以我们用下面的方法就足够了
public URL(String protocol, String host, int port, String file)
throws MalformedURLException
{
this(protocol, host, port, file, null);
}
URL uri = new URL("http", "localhost", 8080, "/jsx/servlet");
HttpGet get = new HttpGet(String.valueOf(uri));
get.getRequestLine();
这里我们会发现用HttpGet,必须将uri转成字符串,这是因为HttpGet方法接收的是URI而不是URL,所以我们将uri转成字符串就可以了,然后在调用
post请求
// (1) Post请求
HttpPost post = new HttpPost("http://www.126.com");
//添加参数
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("name", "ahopedog"));
params.add(new BasicNameValuePair("work", "程序员"));
post.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
// (2) 发送请求
HttpClient http = new DefaultHttpClient();
HttpResponse response = http.execute(post);
// (3) 处理响应结果
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
// (4) 从输入流读取网页字符串内容
System.out.println(entity.getContentType());
System.out.println(entity.getContentEncoding());
System.out.println(entity.getContentLength());
InputStream in = null;
try{
in = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}finally{
//记得关闭输入流
if(in != null)
in.close();
}
HttpEntity有3个获取返回数据的描述信息(或叫做元数据)
getContentType():获取响应体的类型
getContentEncoding():获取响应体的字符编码
getContentLength():获取响应体的字节长度
元数据的内容由远程服务器返回,实际上这些信息是包含在响应的头部信息中的,HTTP请求的响应头中还包含了其它有用的信息,HttpComponents将返回头中的关键元数据封装到了HttpEntity中,已便于使用。
entity.getContent()可以得到响应体的InputStream,有了这个流对象,基本上就可以"为所欲为"了。因为InputStream是Java I/O中底层的基础类,结合相对上层的输入流对象或者对字节进行编码等方法就可以获得不同类型和形式的响应数据了。在本例中用BufferedReader将响应体以字符串形式读取(返回的内容确实也是字符串的内容)。
注意:
这个方法里有两个已经被deprecated 了
HTTP.UTF_8
package org.apache.http.protocol中的UTF_8已经被淘汰了,所以我们肯定要处理
然后还是老样子,查百度呗,这里我们会发现在java.nio.charset
中有UTF_8
public static final Charset UTF_8 = sun.nio.cs.UTF_8.INSTANCE;
new DefaultHttpClient过时
我们还会发现new DefaultHttpClient 也已经被deprecated 了
这时我们也要处理
首先我们先看DefaultHttpClient 类
发现其继承的是AbstractHttpClient
那么在进入AbstractHttpClient
发现继承的是CloseableHttpClient
那我我们就会发现,我们是不是就可以用CloseableHttpClient
来代替DefaultHttpClient
了,而且会发现,其线程是安全的,不错不错
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("http://spb.dfinfo.net.cn/spb-admin/user/login");
//拼接参数
List<NameValuePair> list = new ArrayList<>();
list.add(new BasicNameValuePair("stuNumberOrMobile", "123"));
list.add(new BasicNameValuePair("password", "123"));
System.out.println("==== 提交参数 ======" + list);
CloseableHttpResponse response = null;
try {
httpPost.setEntity(new UrlEncodedFormEntity(list));
response = httpClient.execute(httpPost);
System.out.println("========HttpResponseProxy:========" + response.getStatusLine());
HttpEntity entity = response.getEntity();
if (entity != null) {
String result = EntityUtils.toString(entity, "UTF-8");
System.out.println("===获取实体类的内容====" + entity.getContent());
System.out.println("===获取实体类的格式====" + entity.getContentEncoding());
System.out.println("===获取实体类的长度====" + entity.getContentLength());
System.out.println("========接口返回=======" + result);
}
EntityUtils.consume(entity);
// httpClient.getConnectionManager().shutdown();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
参考链接
https://blog.csdn.net/alinshen/article/details/78221031
这样我们就可以用新的方法来代替旧的方法了