java第三方接口调用笔记
在实际项目开发过程中,经常需要调用外部提供的接口。如做短信认证码、身份认证、第三方电商,互联网金融、天气等。
在Java项目中调用第三方接口的常用方式有:
1)通过JDK网络类Java.net.HttpURLConnection;
2)通过common封装好的HttpClient;
3)通过Apache封装好的CloseableHttpClient;
4)通过SpringBoot-RestTemplate;
5)通过Feign插件调用;
HttpURLConnection调用
比较原始的一种调用做法,这里把get请求和post请求都统一放在一个方法里面。
代码如下:
import java.io.BufferedReader;import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class HttpUrlConnectionTest {
/**
* 以post或get方式调用对方接口方法,
*
* @param pathUrl
*/
public static void doPostOrGet(String pathUrl, String data) {
OutputStreamWriter out = null;
BufferedReader br = null;
String result = "";
try {
URL url = new URL(pathUrl);
//打开和url之间的连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//请求方式
conn.setRequestMethod("POST");
//conn.setRequestMethod("GET");
//设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
//DoOutput设置是否向httpUrlConnection输出,DoInput设置是否从httpUrlConnection读入,此外发送post请求必须设置这两个
conn.setDoOutput(true);
conn.setDoInput(true);
/**
* 下面的三句代码,就是调用第三方http接口
*/
//获取URLConnection对象对应的输出流
out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
//发送请求参数即数据
out.write(data);
//flush输出流的缓冲
out.flush();
/**
* 下面的代码相当于,获取调用第三方http接口后返回的结果
*/
//获取URLConnection对象对应的输入流
InputStream is = conn.getInputStream();
//构造一个字符流缓存
br = new BufferedReader(new InputStreamReader(is));
String str = "";
while ((str = br.readLine()) != null) {
result += str;
}
System.out.println(result);
//关闭流
is.close();
//断开连接,disconnect是在底层tcp socket链接空闲时才切断,如果正在被其他线程使用就不切断。
conn.disconnect();
} catch (Exception e) {
log.error("", e);
} finally {
try {
if (out != null) {
out.close();
}
if (br != null) {
br.close();
}
} catch (IOException e) {
log.error("", e);
}
}
}
public static void main(String[] args) {
/**
*手机信息查询接口:http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=手机号
* http://api.showji.com/Locating/www.showji.com.aspx?m=手机号&output=json&callback=querycallback
*/
doPostOrGet("https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=13168888888", "");
}
}
通过HttpClient调用
httpClient的get或post请求方式步骤:
生成一个HttpClient对象并设置相应的参数;
生成一个GetMethod对象或PostMethod并设置响应的参数;
用HttpClient生成的对象来执行GetMethod生成的Get方法;
处理响应状态码;
若响应正常,处理HTTP响应内容;
释放连接。
导入如下jar包:
<!--HttpClient-->
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
代码如下:
import java.io.IOException;import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.springframework.util.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import sun.misc.BASE64Encoder;
@Slf4j
public class HttpClientTest {
/**
* httpClient的get请求方式 使用GetMethod来访问一个URL对应的网页实现步骤: 1.生成一个HttpClient对象并设置相应的参数; 2.生成一个GetMethod对象并设置响应的参数;
* 3.用HttpClient生成的对象来执行GetMethod生成的Get方法; 4.处理响应状态码; 5.若响应正常,处理HTTP响应内容; 6.释放连接。
*
* @param url
* @param charset
* @return
*/
public static String doGet(String url, TreeMap<String, Object> parameter, String charset) throws Exception {
if (parameter == null)
parameter = new TreeMap<>();
parameter.put("timestamp", System.currentTimeMillis());
/**
* 1.生成HttpClient对象并设置参数
*/
HttpClient httpClient = new HttpClient();
//设置Http连接超时为5秒
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
/**
* 2.生成GetMethod对象并设置参数
*/
//添加请求参数
if (!CollectionUtils.isEmpty(parameter)) {
String pams = urlParameter(parameter);
url = url + "?" + pams;
}
GetMethod getMethod = new GetMethod(url);
//设置get请求超时为5秒
getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 5000);
//设置请求重试处理,用的是默认的重试处理:请求三次
getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
String response = "";
/**
* 3.执行HTTP GET 请求
*/
try {
int statusCode = httpClient.executeMethod(getMethod);
/**
* 4.判断访问的状态码
*/
if (statusCode != HttpStatus.SC_OK) {
log.info(">>>>>> 请求出错:{}", getMethod.getStatusLine());
}
/**
* 5.处理HTTP响应内容
*/
//HTTP响应头部信息,这里简单打印
Header[] headers = getMethod.getResponseHeaders();
for (Header h : headers) {
log.info(">>>>>> header: {}", h.getName() + "---------------" + h.getValue());
}
//读取HTTP响应内容,这里简单打印网页内容
//读取为字节数组
byte[] responseBody = getMethod.getResponseBody();
response = new String(responseBody, charset);
log.info(">>>>>> response: {}", response);
//读取为InputStream,在网页内容数据量大时候推荐使用
//InputStream response = getMethod.getResponseBodyAsStream();
} catch (HttpException e) {
//发生致命的异常,可能是协议不对或者返回的内容有问题
log.error("请检查输入的URL!", e);
} catch (IOException e) {
log.error("发生网络异常!", e);
} finally {
/**
* 6.释放连接
*/
getMethod.releaseConnection();
}
return response;
}
/**
* post请求
*
* @param url
* @param parameter
* @return
*/
public static String doPost(String url, TreeMap<String, Object> parameter) throws Exception {
if (parameter == null)
parameter = new TreeMap<>();
parameter.put("timestamp", System.currentTimeMillis());
HttpClient httpClient = new HttpClient();
PostMethod postMethod = new PostMethod(url);
postMethod.addRequestHeader("accept", "*/*");
postMethod.addRequestHeader("connection", "Keep-Alive");
//设置json格式传送
postMethod.addRequestHeader("Content-Type", "application/json;charset=utf-8");
//必须设置下面这个Header
postMethod.addRequestHeader("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");
//添加请求参数
if (!CollectionUtils.isEmpty(parameter)) {
String val = "";
for (Map.Entry<String, Object> entry : parameter.entrySet()) {
if (entry.getValue() != null) {
val = String.valueOf(entry.getValue());
}
postMethod.addParameter(entry.getKey(), val);
}
//getSignature(TreeMap<String, Object> parameter)
postMethod.addParameter("signature", getSignature(parameter));
}
String res = "";
try {
int code = httpClient.executeMethod(postMethod);
if (code == 200) {
res = postMethod.getResponseBodyAsString();
log.info(">>>>>> response: {}", res);
}
} catch (IOException e) {
log.error("", e);
}
return res;
}
/**
* 签名生成规则视被调用方而定
* @param parameter
* @return
* @throws Exception
*/
private static String urlParameter(TreeMap<String, Object> parameter) throws Exception {
if (CollectionUtils.isEmpty(parameter)) {
return "";
}
StringBuilder params = new StringBuilder();
int i = 1;
for (Map.Entry<String, Object> entry : parameter.entrySet()) {
if (i == 1) {
params.append(entry.getKey()).append("=").append(entry.getValue());
} else {
params.append("&").append(entry.getKey()).append("=").append(entry.getValue());
}
i++;
}
params.append("signature=").append(getSignature(parameter));
log.info(">>>>>>> urlParameter: {}", params.toString());
return params.toString();
}
private static String getSignature(TreeMap<String, Object> parameter) throws Exception {
String params = urlParameter(parameter);
params = encryptBASE64(params.getBytes(Charset.forName("UTF-8")));
byte[] param = encryptMD5(params.getBytes(Charset.forName("UTF-8")));
return new String(param);
}
/**
* BASE64加密
*
* @param data
* @return
* @throws Exception
*/
private static String encryptBASE64(byte[] data) throws Exception {
return (new BASE64Encoder()).encodeBuffer(data);
}
/**
* MD5加密
*
* @param data
* @return
* @throws Exception
*/
private static byte[] encryptMD5(byte[] data) throws Exception {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(data);
return md5.digest();
}
public static void main(String[] args) throws Exception {
TreeMap<String, Object> parameter = new TreeMap<>();
parameter.put("openId", "8888888");
parameter.put("name", "asdf");
parameter.put("age", 12);
parameter.put("sex", 1);
long timestamp = System.currentTimeMillis();
parameter.put("timestamp", timestamp);
urlParameter(parameter);
}
}
通过SpringBoot-RestTemplate调用
springBoot-RestTemple是上面三种方式的集大成者,代码编写更加简单,目前可以采用的调用第三方接口有:
delete() 在特定的URL上对资源执行HTTP DELETE操作
exchange() 在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中映射得到的
execute() 在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象
getForEntity() 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
getForObject() 发送一个HTTP GET请求,返回的请求体将映射为一个对象
postForEntity() POST 数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的
postForObject() POST 数据到一个URL,返回根据响应体匹配形成的对象
headForHeaders() 发送HTTP HEAD请求,返回包含特定资源URL的HTTP头
optionsForAllow() 发送HTTP OPTIONS请求,返回对特定URL的Allow头信息
postForLocation() POST 数据到一个URL,返回新创建资源的URL
put() PUT 资源到特定的URL
代码如下:
import com.alibaba.fastjson.JSONObject;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
public class RestTemplateTest {
@Autowired
private RestTemplate restTemplate;
/**
* 以get方式请求第三方http接口 getForEntity
* @param url
* @param request
* @return
*/
public <T> ResponseEntity<T> doGet(String url, Class<T> request){
return restTemplate.getForEntity(url, request);
}
/**
* 以post方式请求第三方http接口 postForEntity
* @param url
* @param request
* @return
*/
public <T> ResponseEntity<String> doPost(String url, Class<T> request){
return restTemplate.postForEntity(url, request, String.class);
}
/**
* exchange
* @param url
* @param request
* @return
*/
public String doExchange(String url, JSONObject request){
//header参数
HttpHeaders headers = new HttpHeaders();
String token = "asdfghjkl123456";
headers.add("authorization", token);
headers.setContentType(MediaType.APPLICATION_JSON);
//组装
HttpEntity<JSONObject> requestHttpEntity = new HttpEntity<>(request, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestHttpEntity, String.class);
return responseEntity.getBody();
}
}
通过Feign插件调用
引入feign插件
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
普通调用
@FeignClient(name = "xxx", url = "https://www.xxx.com")
public interface FeignUserService {
@RequestMapping(method = RequestMethod.POST, value = "/getUserById",consumes = "application/x-www-form-urlencoded;charset=UTF-8")
String getUserById(String id);
}
如果是调用自己Eureka上服务的接口
@FeignClient(value="被调用方Eureka上的服务名")
public interface FeignUserService {
@RequestMapping(method = RequestMethod.GET, value = "/getUserById")
String getUserById(@RequestParam(name="id") String id);
}
以上是 java第三方接口调用笔记 的全部内容, 来源链接: utcz.com/z/515837.html