JAVA实现与第三方接口对接
一、GET请求和POST请求简介
Ⅰ、定义:
-
POST请求:POST请求是向服务器提交数据的一种请求方法,通过请求体传递数据。
-
GET请求:GET请求是从服务器获取数据的一种请求方法,通过URL参数传递数据。
Ⅱ、特点:
-
POST请求的特点:
-
数据传递方式:使用请求体来传输数据,数据不会直接暴露在URL中。
-
数据安全性:POST请求相对于GET请求更安全,因为数据不会明文出现在URL上。
-
请求体大小:POST请求没有限制请求体的大小,可以传输较大的数据。
-
幂等性:POST请求不具备幂等性,即多次提交同一请求可能会产生不同的结果。
-
-
GET请求的特点:
-
数据传递方式:使用URL参数来传递数据,数据会显示在URL中。
-
数据长度限制:GET请求由于URL长度限制,传输的数据量较小。
-
缓存支持:GET请求可以被浏览器缓存,对于相同的URL再次请求时可直接从缓存获取响应。
-
幂等性:GET请求具备幂等性,即多次提交同一请求会产生相同的结果。
-
Ⅲ、关联:
-
相同点:
-
都是基于HTTP协议的请求方法。
-
都可以在请求头中携带各种参数和数据进行通信。
-
都能够接收服务器返回的响应数据。
-
-
不同点:
-
数据传递方式:POST请求使用请求体传递数据,GET请求使用URL参数传递数据。
-
数据安全性:POST请求相对于GET请求更安全,因为数据不会明文出现在URL上。
-
请求体大小限制:GET请求由于URL长度限制,传输的数据量较小,而POST请求没有限制请求体的大小。
-
幂等性:POST请求不具备幂等性,GET请求具备幂等性
-
Ⅳ、扩展
-
从计算机网络的角度来看:
-
POST请求可以传输大量数据,适用于需要向服务器发送表单数据或上传文件等情况,但相对地更占用服务器资源。
-
GET请求适用于获取资源,如请求网页、检索数据,它会将数据包含在URL中发送给服务器,比较简单高效。
-
-
从Java Web开发的角度来看:
-
在Java Web开发中,POST请求常用于表单提交、文件上传等需要传递大量数据的场景。
-
GET请求常用于页面转跳、获取数据、搜索等不对服务器产生副作用的操作。
-
需要注意的是,无论是POST请求还是GET请求,使用时都要考虑安全性和性能的因素,根据实际需求选择合适的请求方式。
二、JAVA实现GET请求
-
pom文件,引入 httpclient依赖
<!-- httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.9</version>
</dependency>
-
构建请求参数
Map<String, String> req = new HashMap<String, String>();
req.put("parameter",parameter);
String response = HttpUtils.sendGet(URL+BASE_USER_INFO_API,req);
log.info("调用请求结果response:{}",response);
if (StringUtils.isEmpty(response)){
throw new BizException("请求为空");
}
JSONObject responseJSON = JSONObject.parseObject(response);
/**
* 后面就写自己的业务代码
*/
-
GET请求实现
//调用入口
public static String sendGet(String url, Map<String, String> paramsMap) {
try {
return sendGet(getUrl(url, paramsMap));
} catch (Exception var3) {
log.info("Exception异常 {}", var3);
throw new HttpException("Exception异常", var3.getMessage(), var3);
}
}
//转化URL
public static String getUrl(String url, Map<String, String> paramsMap) {
ArrayList params = new ArrayList();
try {
Iterator var3 = paramsMap.entrySet().iterator();
while(var3.hasNext()) {
Entry<String, String> entry = (Entry)var3.next();
NameValuePair nameValuePair = new BasicNameValuePair((String)entry.getKey(), (String)entry.getValue());
params.add(nameValuePair);
}
if (CollectionUtils.isNotEmpty(params)) {
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
entity.setContentType("application/x-www-form-urlencoded");
url = url + "?" + EntityUtils.toString(entity);
log.info("url == {}", url);
}
return url;
} catch (Exception var6) {
log.info("Exception异常 {}", var6);
throw new HttpException("Exception异常", var6.getMessage(), var6);
}
}
//发起请求并返回响应报文:json格式数据
public static String sendGet(String url) {
HttpGet httpget = new HttpGet(url);
httpget.setConfig(defaultRequestConfig);
CloseableHttpResponse response = null;
try {
response = httpclient.execute(httpget);
log.info("响应报文 response = {}", JSON.toJSONString(response));
} catch (IOException var13) {
log.info("IOException异常 {}", var13);
throw new HttpException("IOException异常", var13.getMessage(), var13);
}
String result = null;
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toString(entity, "UTF-8");
EntityUtils.consume(entity);
}
if (response.getStatusLine().getStatusCode() != 200) {
throw new HttpException(result, String.valueOf(response.getStatusLine().getStatusCode()));
}
} catch (IOException | ParseException var14) {
log.info("ParseException | IOException 异常 {}", var14);
throw new HttpException("IOException异常", var14.getMessage(), var14);
} finally {
try {
response.close();
} catch (IOException var12) {
log.info("IOException异常 {}", var12);
}
}
return result;
}
三、JAVA实现POST请求
-
构建请求参数:
Map<String, String> req = new HashMap<String, String>();
req.put("parameter",parameter);
String response = HttpUtils.sendPost(URL,JSONObject.toJSONString(req));
log.info("调用请求结果response:{}",response);
if (StringUtils.isEmpty(response)){
throw new BizException("请求结果为空");
}
JSONObject responseJSON = JSONObject.parseObject(response);
/**
* 后面就写自己的业务代码
*/
-
post发送请求实现方法:
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
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");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
log.error("发送 POST 请求出现异常!"+e);
throw new IybException("发送 POST 请求出现异常");
}
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
log.error("异常信息:" + ex);
}
}
log.info("HttpUtil sendPost end result = {}", url);
return result;
}
}
四、项目实例:GET请求实现
Ⅰ、背景:
在工作做项目时候,需要开发一个H5的人脸识别功能,此功能调用第三方公司api实现。发起请求认证过程省略,只简单实现认证结果的查询
Ⅱ、API对接请求
-
请求方式:GET请求
-
请求参数:如下图所示
Ⅲ、API对接响应报文
-
成功响应报文:
{ "request_id": "1462259763,e2d2f8d6-204b-4c43-92ea-1d62b071f83c", "status": "OK", "biz_info": { "biz_extra_data": "...", "biz_id": "1462259748,52b13fb5-8dfb-4537-a62b-a641d5e929f1", "biz_no": "cc47190f-5502-44a2-ab74-ea4f0f649f61" }, "idcard_info": { "idcard_mode": "1", "idcard_uneditable_feild": "idcard_number,idcard_valid_date", "idcard_number": "xxxxxx19910602xxxx", "idcard_name": "陈AB", "idcard_issued_by": "北京市公安局", "front_side": { "ocr_result": { "address": "北京市海淀区XXXX", "birthday": { "day": "2", "month": "6", "year": "1991" }, "gender": "男", "id_card_number": "xxxxxx19910602xxxx", "name": "陈XX", "race": "汉", "legality": { "ID Photo": 0.855, "Temporary ID Photo ": 0, "Photocopy": 0.049, "Screen": 0.096, "Edited": 0 } }, "upload_times": 1 }, "back_side": { "ocr_result": { "issued_by": "北京市公安局海淀分局", "valid_date": "2010.11.13-2020.11.13", "legality": { "ID Photo": 0.855, "Temporary ID Photo ": 0, "Photocopy": 0.049, "Screen": 0.096, "Edited": 0 } }, "upload_times": 2 } }, "liveness_result": { "procedure_type": "video", "result": "PASS/FAIL/TIMEOUT", "details": { "UPLOAD_TIMES": 5, "FACE_NOT_FOUND": 0, "LOW_FACE_QUALITY": 0, "INVALID_VIDEO_DURATION": 1, "SR_ERROR": 2, "NOT_SYNCHRONIZED": 1, "VIDEO_FORMAT_UNSUPPORTED": 0, "NO_AUDIO": 0 }, "face_genuineness": { "synthetic_face_confidence": 0.88, "synthetic_face_threshold": 0.5, "mask_confidence": 0.32, "mask_threshold": 0.5, "screen_replay_confidence": 0, "screen_replay_threshold": 0.5 } }, "verify_result": { "result_faceid": { "confidence": 68.918, "thresholds": { "1e-3": 64, "1e-4": 69, "1e-5": 74, "1e-6": 79.9 } }, "result_ref1": { "confidence": 68.918, "thresholds": { "1e-3": 64, "1e-4": 69, "1e-5": 74, "1e-6": 79.9 } }, "result_idcard_photo": { "confidence": 68.918, "thresholds": { "1e-3": 64, "1e-4": 69, "1e-5": 74, "1e-6": 79.9 } }, "result_idcard_datasource": { "confidence": 68.918, "thresholds": { "1e-3": 64, "1e-4": 69, "1e-5": 74, "1e-6": 79.9 } }, "id_exceptions": { "id_attacked": 0, "id_photo_monochrome": 0 } }, "images": { "image_idcard_back": "data: image/jpeg;base64,...", "image_idcard_front": "data: image/jpeg;base64,...", "image_best": "data: image/jpeg;base64,..." }, "time_used": 93 }
-
失败响应报文:
{ "error_message": "RESULT_NOT_FOUND", "request_id": "1462259901,fa79992d-ca61-48de-aa50-ea337c6aad42", "time_used": 4 }
Ⅳ、代码实现:
这代码中的发起请求方法可以上述关于get接口请求的定义。
public FaceAuthResultVO queryFaceAuthResult(String serialNo) throws Exception {
FaceAuthResultVO faceAuthResultVO = new FaceAuthResultVO();
Map<String, String> req = new HashMap<String, String>() {{
put("api_key", apiKey);
put("api_secret", secretKey);
put("biz_id", serialNo);
put("return_image", "1");
}};
try{
String faceAuthResult = HttpUtils.sendGet(resultUrl, req);
log.info("人脸识别结果查询出参faceAuthResult{}",faceAuthResult);
JSONObject resultData = JSONObject.parseObject(faceAuthResult);
if(StringUtils.isEmpty(faceAuthResult)
|| Objects.isNull(resultData.getJSONObject("liveness_result"))
|| Objects.isNull(resultData.getJSONObject("verify_result"))
|| Objects.isNull(resultData.getJSONObject("verify_result").getJSONObject("result_faceid"))){
throw new BizException("人脸识别结果查询失败");
}
/**
* 首先判断“status”是否为“OK”,status为OK表示完成了FaceID Lite验证
* 在判断“result”是否为“PASS”,为活体检测结果,检测是否被攻击(在getToken的时候fmp_mode为0时,该字段有效。)
* 最后判断“confidence”是否大于“1e-4”,大于的话我们认为是同一个人
*/
if (resultData.getJSONObject("liveness_result").getString("result").equals(FACE_AUTH_PASS)){
JSONObject verifyResult = resultData.getJSONObject("verify_result").getJSONObject("result_faceid");
JSONObject thresholds = verifyResult.getJSONObject("thresholds");
double confidence = verifyResult.getDouble("confidence");
double threshold = thresholds.getDouble("1e-4");
if (confidence>threshold){
faceAuthResultVO.setStatus("SUCCESS");
return faceAuthResultVO;
}
}
JSONObject images = resultData.getJSONObject("images");
if (Objects.nonNull(images)) {
faceAuthResultVO.setImageBase64(images.getString("image_best"));
}
faceAuthResultVO.setStatus("FAIL");
} catch (Exception e) {
log.warn("人脸识别结果查询失败",e);
e.printStackTrace();
}
return faceAuthResultVO;
}
-
Ⅴ、人脸识别扩展:
-
关于人脸识别结果计算:
-
首先判断“status”是否为“OK”,status为OK表示完成了FaceID Lite验证。
-
在判断“result”是否为“PASS”,为活体检测结果,检测是否被攻击(在getToken的时候fmp_mode为0时,该字段有效)。
-
最后判断“confidence”是否大于“1e-4”,大于的话我们认为是同一个人
-
-
接口文档:FaceID 文档中心 获取比对结果
-
TIP:旷世对接人脸识别中,在获取人脸识别请求时,用户名必须是中文,不然无法进行人脸识别,上述示例只是人脸识别的结果查询。