背景:
最近在做一个项目 前台需要调取平台api 但是直接调用会跨域 所以需要后台调取数据返回给前台
所以。。。。
先贴代码:
/**
* 发送远端GET请求的公共方法
*
* @param url (远程请求的URL)
* @param access_token (用户名 密码 选填)
* @param acceptType( 接受的数据格式 )
* @return string
*/
public static String sendGetUrl(String url, String accessToken,String acceptType) throws Exception {
String result = "";
BufferedReader in = null;
try {
URL realUrl = new URL(url);
if ("https".equalsIgnoreCase(realUrl.getProtocol())) {
//忽略https的ssl认证
SslUtil.ignoreSsl();
}
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("Authorization", accessToken);
connection.setRequestProperty("Accept", acceptType);
//由于我调用时 存在问题 我就模拟了一下请求头
connection.setRequestProperty("Use-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36");
//connection.setRequestProperty("Cache-Control ", "no-store");
//connection.setRequestProperty("Expires", "-1");
//connection.setRequestProperty("X-UA-Compatible", "IE=edge");
//connection.setRequestProperty("Server", "Mushroom");
//connection.setRequestProperty("Pragma", "no-cache");
// 建立实际的连接
connection.connect();
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
throw e;
} finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
以上GET方式就差不多了 但是这几个参数可以讲一讲
**
一、参数
**
1.url:地址
2.access_token: 用户验证信息
需要自己拼
例如:用户名 liu 密码 123 则 access_token 拼出的结步骤代码为:
String userName = "liu";
String pwd = "123";
String userInfo = userName + ":" + pwd;
//使用base64进行加密
byte[] tokenByte = Base64.encodeBase64(userInfo.getBytes());
//将加密的信息转换为string
String tokenStr = DataTypeChange.bytesSub2String(tokenByte, 0, tokenByte.length);
//Basic后有一个空格!!!!!!
String token = "Basic "+tokenStr;
//传入请求头的Authorization即可
connection.setRequestProperty("Authorization", access_token);
3.acceptType : 发送端(客户端)希望接受的数据类型。
常用有 application/json;text/xml;text/html;text/plain; 有时候不设定好像也没有问题
但我这个场景就必须设定好接受的数据类型
扩展 Content-Type:发送端(客户端|服务器)发送的实体数据的数据类型。 get一般不需要
SSL认证去掉 <上网找的>
注意的一点就是 必须在打开链接之前 去掉ssl认证
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.io.IOUtils;
/**
* created by liu on 2020/03/18 14:23
*/
public class SslUtil {
private static void trustAllHttpsCertificates() throws Exception {
TrustManager[] trustAllCerts = new TrustManager[1];
TrustManager tm = new miTM();
trustAllCerts[0] = tm;
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
static class miTM implements TrustManager, X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(X509Certificate[] certs, String authType)
throws CertificateException {
return;
}
public void checkClientTrusted(X509Certificate[] certs, String authType)
throws CertificateException {
return;
}
}
/**
* 忽略HTTPS请求的SSL证书,必须在openConnection之前调用
*
* @throws Exception
*/
public static void ignoreSsl() throws Exception {
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName
+ " vs. " + session.getPeerHost());
return true;
}
};
trustAllHttpsCertificates();
HttpsURLConnection.setDefaultHostnameVerifier(hv);
}
public static String getRequest(String url, int timeOut) throws Exception {
URL u = new URL(url);
if ("https".equalsIgnoreCase(u.getProtocol())) {
SslUtil.ignoreSsl();
}
URLConnection conn = u.openConnection();
conn.setConnectTimeout(timeOut);
conn.setReadTimeout(timeOut);
return IOUtils.toString(conn.getInputStream());
}
public static String postRequest(String urlAddress, String args, int timeOut)
throws Exception {
URL url = new URL(urlAddress);
if ("https".equalsIgnoreCase(url.getProtocol())) {
SslUtil.ignoreSsl();
}
URLConnection u = url.openConnection();
u.setDoInput(true);
u.setDoOutput(true);
u.setConnectTimeout(timeOut);
u.setReadTimeout(timeOut);
OutputStreamWriter osw = new OutputStreamWriter(u.getOutputStream(),
"UTF-8");
osw.write(args);
osw.flush();
osw.close();
u.getOutputStream();
return IOUtils.toString(u.getInputStream());
}
}
这样其实get方法就没什么了 同理post方法 我只是给代码就可以了 我感觉肯定就可以看懂了
/**
* 发送远端POST请求的公共方法
*
* @param url (远程请求的URL)
* @param param (请求体参数)
* @param accessToken (用户认证信息)
* @param acceptType (接受结果数据类型)
* @return String (远程请求返回的JSON)
*/
public static String sendPostUrl(String url, String param, String accessToken,String acceptType) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
if ("https".equalsIgnoreCase(realUrl.getProtocol())) {
try {
SslUtil.ignoreSsl();
} catch (Exception e) {
e.printStackTrace();
}
}
// 打开和URL之间的连接
HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
//设置header
conn.setRequestProperty("Authorization", accessToken);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", acceptType);
//setDoOutput()和setDoInput()的作用主要是发送Post请求。
//Post请求需要向服务器端发送数据参数,所以setDoInput(true)
//总是要通过getInputStream() 需从服务端获得响应所以setDoInput()默认是true;
conn.setDoOutput(true);
conn.setDoInput(true);
// Post 请求不能使用缓存
conn.setUseCaches(false);
// 设定请求的方法为"POST",默认是GET
conn.setRequestMethod("POST");
//设置连接主机超时 10s
conn.setConnectTimeout(10000);
//设置连接读取信息超时 10s
conn.setReadTimeout(10000);
//打开连接
conn.connect();
//获取HttpURLConnection对象对应的输出流(设置请求编码为UTF-8)
//获取服务端发送的信息:conn.getOutputStream()
out = new PrintWriter(
new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8));
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 获取请求返回数据(设置返回数据编码为UTF-8)
// BufferedReader由Reader类扩展而来,提供通用的缓冲方式文本读取,而且提供了很实用的readLine,读取一个文本行,从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (IOException e) {
System.out.println("发送POST请求出现异常!" + e);
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
最后说一下 我在测试环节的时候 得到的一些结果
404 肯定是找不到网页 url不对
429 to many request 原因是你调用的接口有限制 可能是一分钟只能调几次那种
而我当时做这个功能的时候 是监控页面 主页需要60个接口 所以不可能等所有数据都查到
才显示页面 而且这个平台限制一分钟调5个接口
所以综合下 我们选择数据落地 我定时任务每小时拉取数据 之后落地
前端调我本地方法
406 Not acceptable 接收头HEADER有问题 我当时就是Accept有问题
400 Bad Request 我调这个出现的问题是由于我post请求的param参数不对
与服务器要求的参数题相比少了括号。而且参数它验证有问题可能
415 Unsupported media type POST请求的content-type 可能有问题