三方接口对接常见数据处理方式汇总

文章目录

  • 数据请求格式
    • application/json
      • 接收
      • 发送
    • multipart/form-data
      • 接收
      • 发送
    • application/x-www-form-urlencoded
      • 接收
      • 发送
    • text/xml
      • 接收
      • 发送
    • Request请求中各个数据载体获取方法
      • Header
      • Parameter
      • InputStream
      • Attribute
    • 二次封装HttpServletRequest参考
  • 验签与加密

  • 日常开发中,我们经常会对接各种各样的第三方平台,常常需要对接口接入的数据参数进行处理,比如验签,解密,数据转换,数据二次封装等情况,本文总结了一些常见的数据处理案例,基本满足日常所见的各种情况,以供学习。POST 一般用来向服务端提交数据,本文主要讨论 POST 请求数据的几种方式。

数据请求格式

application/json

  • Method只支持POST,客户端设置请求头参数:“Content-type: application/json”;
  • 方法参数可以对象构成:加@RequestBody 注解前缀,否则不能接收到;
  • 文件上传可以通过转换成base64参数;

接收

  • 使用Postman模拟发送
    在这里插入图片描述
  • 接收数据
 @PostMapping( "/outbound")public String createOutboundOrderApollo(@RequestBody OutboundCreateOrderDTO createOrderDTO) {return JSON.toJSONString(createOrderDTO);}
  • 如果需要在请求头中添加一些自己的数据,需要从HttpServletRequest中获取请求数据进行二次封装;
    在这里插入图片描述
  • 接收数据:
 @PostMapping( "/test")public CainiaoR test(HttpServletRequest request) {// 二次封装requestCustomRequestWrapper requestWrapper = new CustomRequestWrapper(request);return CainiaoR.success();}
  • 需要注意的是:Body请求的数据在InputStream中获取;

发送

try {String url = "推送消息url";// 请求参数json字符串,格式如:"{\"name\":\"张三\"}" ,可通过构建对象后再转换成json字符串:JSONObject.toJSONString(obj)String content = "请求参数json字符串";HttpHeaders requestHeaders = new HttpHeaders();requestHeaders.setContentType(MediaType.APPLICATION_JSON);requestHeaders.add("Content-Encoding", "UTF-8");HttpEntity<String> entity = new HttpEntity<>(content, requestHeaders);// 调用远程接口:httpClient   restTemplate  等都可以使用,具体看个人习惯。ResponseEntity response = restTemplate.postForEntity(url, entity, String.class);JSONObject jsonObject = JSONObject.parseObject(response.getBody().toString());if (jsonObject.containsKey("code") && jsonObject.getString("code").equals("SUCCESS")) {log.info("推送成功");}
} catch (Exception e) {log.error(e.getMessage());
}

multipart/form-data

  • 只支持POST请求,客户端设置请求头参数:“Content-type: multipart/form-data”;
  • http请求中的multipart/form-data,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开。所以multipart/form-data既可以上传文件,也可以上传键值对,它采用了键值对的方式,所以可以上传多个文件。
  • 在向服务器发送大量的文本、包含非ASCII字符的文本或二进制数据时这种编码方式效率很低。特别在文件上载时,所使用的编码类型应当是“multipart/form-data”,它既可以发送文本数据,也支持二进制数据上载。所以,大数据传输时一般选择“multipart/form-data”。
  • 属性设置为multipart/form-data,并且有至少一个input的type属性为file时,浏览器提交这个form时会在请求头部的Content-Type中自动添加boundary属性。

在这里插入图片描述

接收

  • 使用Postman模拟发送
    在这里插入图片描述

  • 接收数据

// 当请求参数有上传文件,3个及以下请求参数;
@PostMapping("/test")
public void test(String name, String id, MultipartFile file){log.info("name:{}, id:{}, file: {}", name, id, file);
}
// 当请求参数有上传文件,3个以上请求参数,封装成请求对象,不能加@RequestBody注解;
@PostMapping("/test")
public void test(RequestDto reqDto){log.info("name:{}, id:{}, file: {}", reqDto.getName(), reqDto.getIdcard(), reqDto.getFile());
}

发送

  • 以post方式调用第三方接口,以form-data 形式 发送 MultipartFile 文件数据
try {// 需要发送的文件流MultipartFile multipartFile = null;String url = "推送消息url";//  getStreamAsString 见  InputStream 提取;String content = getStreamAsString(multipartFile.getInputStream());HttpHeaders requestHeaders = new HttpHeaders();requestHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);requestHeaders.add("Content-Encoding", "UTF-8");HttpEntity<String> entity = new HttpEntity<>(content, requestHeaders);// 调用远程接口:httpClient   restTemplate  等都可以使用,具体看个人习惯。ResponseEntity response = restTemplate.postForEntity(url, entity, String.class);JSONObject jsonObject = JSONObject.parseObject(response.getBody().toString());if (jsonObject.containsKey("code") && jsonObject.getString("code").equals("SUCCESS")) {log.info("推送成功");}
} catch (Exception e) {log.error(e.getMessage());
}

application/x-www-form-urlencoded

  • 当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1&name2=value2…),然后把这个字串append到url后面,用?分割,加载这个新的url。 当action为post时候,浏览器把form数据封装到http body中,然后发送到server。

接收

  • 请求参数不含MultlpartFile类型时可同时支持 GET和POST;
  • 上传文件:只支持POST(包括MutipleFile和Base64字符串)
  • 方法参数可以对象构成:不能加@RequestBody注解,否则不能接收到
  • 使用Postman模拟发送
    在这里插入图片描述
@PostMapping( "/test")
public void test(String name, String id){log.info("name:{}, id:{}", name, id);
}
@PostMapping("/test")
public void test(RequestDto reqDto){log.info("name:{}, id:{}, file: {}", reqDto.getName(), reqDto.getIdcard(), reqDto.getFile());
}
  • 如果需要在请求头中添加一些自己的数据,需要从HttpServletRequest中获取请求数据进行二次封装; 需要注意的是:Body请求的数据在Parameter中获取;

发送

public void test() {try {// params 需要发送的数据Map<String, String> params = new HashMap<>();String url = "推送消息url";String content = buildQuery(params, "UTF-8");;HttpHeaders requestHeaders = new HttpHeaders();requestHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);requestHeaders.add("Content-Encoding", "UTF-8");HttpEntity<String> entity = new HttpEntity<>(content, requestHeaders);// 调用远程接口:httpClient   restTemplate  等都可以使用,具体看个人习惯。ResponseEntity response = restTemplate.postForEntity(url, entity, String.class);JSONObject jsonObject = JSONObject.parseObject(response.getBody().toString());if (jsonObject.containsKey("code") && jsonObject.getString("code").equals("SUCCESS")) {log.info("推送成功");}} catch (Exception e) {log.error(e.getMessage());}
}public static String buildQuery(Map<String, String> params, String charset) throws IOException {if (params == null || params.isEmpty()) {return null;}StringBuilder query = new StringBuilder();Set<Map.Entry<String, String>> entries = params.entrySet();boolean hasParam = false;for (Map.Entry<String, String> entry : entries) {String name = entry.getKey();String value = entry.getValue();// 忽略参数名或参数值为空的参数if (StringUtils.areNotEmpty(name, value)) {if (hasParam) {query.append("&");} else {hasParam = true;}query.append(name).append("=").append(URLEncoder.encode(value, charset));}}return query.toString();
}

text/xml

  • 该种方式主要用来提交XML格式的数据。

接收

  • InputStream就是Java标准库提供的最基本的输入流。HttpServletRequest中InputStream只能读取一次,如果想要二次读取就会报错。 因此需要能够重复读取 InputStream 的方法。
  • 使用Postman模拟发送
    在这里插入图片描述
private final byte[] body;
private String bodyString;@SneakyThrows
private byte[] initInputStream(HttpServletRequest request) {//  getStreamAsString 见  InputStream 提取;this.bodyString = getStreamAsString(request.getInputStream());return bodyString.getBytes(StandardCharsets.UTF_8);
}

发送

  • 与其他格式一样,将数据转为String传输。

Request请求中各个数据载体获取方法

Header

  • 请求标头是一种 HTTP 标头,它可在 HTTP 请求中使用,其提供有关请求上下文的信息,以便服务器可以定制响应。请求头由key/value对组成,每行为一对,key和value之间通过冒号(:)分割。请求头的作用主要用于通知服务端有关于客户端的请求信息。
// 获取请求头信息
private static Map<String, String> initHeaders(HttpServletRequest request) {Map<String, String> headers = new HashMap<>();Enumeration<String> headerNames = request.getHeaderNames();while (headerNames.hasMoreElements()) {String headerName = headerNames.nextElement();String header = request.getHeader(headerName);headers.put(headerName, header);}return headers;
}

Parameter

  • 参数(parameter)是从客户端(浏览器)中由用户提供的,若是GET方法是从URL中提供的,若是POST方法是从请求体(request body)中提供的;
  • request.getParameter()取得是通过容器的实现来取得通过类似post、get等方式传入的数据。request.getParameter()方法传递的数据,会从web客户端传到web服务器端,代表HTTP请求数据。
// 获取
private Map<String, String[]> initParameters(HttpServletRequest request) {Map<String, String[]> parameterMap = new HashMap<>();Enumeration<String> parameterNames = request.getParameterNames();while (parameterNames.hasMoreElements()) {String paramName = parameterNames.nextElement();String[] parameterValues = request.getParameterValues(paramName);parameterMap.put(paramName, parameterValues);}return parameterMap;
}

InputStream

private static String getStreamAsString(InputStream stream) throws IOException {try {Reader reader = new InputStreamReader(stream, StandardCharsets.UTF_8);StringBuilder response = new StringBuilder();final char[] buff = new char[1024];int read = 0;while ((read = reader.read(buff)) > 0) {response.append(buff, 0, read);}return response.toString();} finally {if (stream != null) {stream.close();}}
}

Attribute

  • request.setAttribute()和getAttribute()只是在web容器内部流转,仅仅是请求处理阶段。
  • 属性(attribute)是服务器端的组件(JSP或者Servlet)利用requst.setAttribute()设置的
  • 属性(attribute)的值既可以读取亦可以修改,读取可以使用request.getAttribute(),设置可使用request.setAttribute();

二次封装HttpServletRequest参考


/**
* @Author: carroll
* @Date: 2023-12-22
* @Since: 1.0** 自定义HttpServletRequest  实现参数重复读取,请求头写入,请求头获取等功能* 满足各种平台各种数据数据格式传输和租户信息配置
*/
public class CustomRequestWrapper extends HttpServletRequestWrapper {private final Map<String, String[]> params;//定义参数集合private Map<String, String> headerMap;private final RedisUtils redisUtils;//    将request 里面的东西 缓存到这个数组里面private final byte[] body;private String bodyString;public CustomRequestWrapper(HttpServletRequest request, RedisUtils redisUtils) {super(request);this.params = initParameters(request);this.headerMap = initHeaders(request);this.redisUtils = redisUtils;this.body = initInputStream(request);getRequestOpenid();}@SneakyThrowsprivate byte[] initInputStream(HttpServletRequest request) {this.bodyString = getStreamAsString(request.getInputStream());return bodyString.getBytes(StandardCharsets.UTF_8);}private void getRequestOpenid() {String openid = "";//  可以获取外部推送各种接口请求头中的数据  然后将对应的货主等信息放到请求头中String partner_code = getParameter("partner_code");if (CharSequenceUtil.isNotBlank(partner_code)) {openid = partner_code;}Object obj = redisUtils.get(GlobalConstants.OPENID + openid);if (Objects.isNull(obj)) {throw new BizException("未获取到有效请求头数据");}QiMenOwnerCache ownerCache = JSONUtil.toBean(obj.toString(), QiMenOwnerCache.class);initOwnerInfo(String.valueOf(ownerCache.getTenantId()), String.valueOf(ownerCache.getWarehouseId()), String.valueOf(ownerCache.getOwnerId()));}private Map<String, String[]> initParameters(HttpServletRequest request) {Map<String, String[]> parameterMap = new HashMap<>();Enumeration<String> parameterNames = request.getParameterNames();while (parameterNames.hasMoreElements()) {String paramName = parameterNames.nextElement();String[] parameterValues = request.getParameterValues(paramName);parameterMap.put(paramName, parameterValues);}return parameterMap;}public void initOwnerInfo(String tenantId,String warehouseId,String ownerId) {headerMap.put(SecurityConstants.TENANT_ID_HEADER, tenantId);headerMap.put(SecurityConstants.WAREHOUSE_ID_HEADER, warehouseId);headerMap.put(SecurityConstants.OWNER_ID_HEADER, ownerId);}private static Map<String, String> initHeaders(HttpServletRequest request) {Map<String, String> headers = new HashMap<>();Enumeration<String> headerNames = request.getHeaderNames();while (headerNames.hasMoreElements()) {String headerName = headerNames.nextElement();String header = request.getHeader(headerName);headers.put(headerName, header);}return headers;}@Overridepublic String getParameter(String name) {String[] vs = params.get(name);if (vs == null || vs.length < 1)return null;return vs[0];}@Overridepublic Enumeration<String> getParameterNames() {return Collections.enumeration(params.keySet());}@Overridepublic String[] getParameterValues(String name) {String[] vs = params.get(name);if (vs == null || vs.length < 1)return new String[0];return vs;}@Overridepublic String getHeader(String name) {return this.headerMap.getOrDefault(name, headerMap.get(name.toLowerCase()));}@Overridepublic Enumeration<String> getHeaderNames() {return Collections.enumeration(this.headerMap.keySet());}public String getBodyString() {return this.bodyString;}@Overridepublic BufferedReader getReader() {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic ServletInputStream getInputStream() {final ByteArrayInputStream innerBAIS = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}@Overridepublic int read() {return innerBAIS.read();}};}private static String getStreamAsString(InputStream stream) throws IOException {try {Reader reader = new InputStreamReader(stream, StandardCharsets.UTF_8);StringBuilder response = new StringBuilder();final char[] buff = new char[1024];int read = 0;while ((read = reader.read(buff)) > 0) {response.append(buff, 0, read);}return response.toString();} finally {if (stream != null) {stream.close();}}}}

验签与加密

  • 后续补充…

你知道的越多,你不知道的越多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/626858.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python_PySide6学习笔记(三十一)】基于PySide6实现自定义串口设备连接界面类:可实现串口连接断开、定时发送等功能

基于PySide6实现自定义串口设备连接界面类:可实现串口连接关闭、定时发送等功能 基于PySide6实现自定义串口设备连接界面类:可实现串口连接关闭、定时发送等功能前言一、界面布局二、串口相关功能实现三、完整代码四、调用方法五、实现效果基于PySide6实现自定义串口设备连接…

快慢指针-Floyd判圈算法

对于环形链表是否存在环的做法&#xff0c;普通算法可以通过额外Hash数组来存储链表元素&#xff0c;直到Hash数组中出现重复元素。时间复杂度O(n)&#xff0c;空间复杂度O(n) Floyd判圈算法通过利用快慢指针的移动来实现&#xff0c;时间复杂度O&#xff08;n&#xff09;&am…

【备战蓝桥杯】今天给大家整点解压的~

【备战蓝桥杯】今天给大家整点解压的~ 蓝桥杯备赛 | 洛谷做题打卡day8 文章目录 【备战蓝桥杯】今天给大家整点解压的~ 蓝桥杯备赛 | 洛谷做题打卡day8[NOIP2017 普及组] 成绩题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提…

【C语言编程之旅 1】刷题篇-初识c语言

文章目录 第一题答案及解析 第二题答案及解析 第三题答案及解析 第四题答案及解析 第五题答案及解析 第六题答案及解析 第一题 答案及解析 C语言中内置类型包括&#xff1a; char //字符数据类型 short //短整型 int //整形 long //长整型 long long //更长的整形 float //单精…

ArcGIS Pro 拓扑编辑和常见一些拓扑错误处理

7.4 拓扑编辑 拓扑编辑也叫共享编辑&#xff0c;多个数据修改时&#xff0c;一块修改&#xff0c;如使用数据&#xff1a;chp7\拓扑检查.gdb,数据集DS下JZX、JZD和DK&#xff0c;加载地图框中&#xff0c;在“地图”选项卡下选择“地图拓扑”或“ds_Topology(地理数据库)”&…

Oracle-java下载、开源/商业许可证(收费、免费说明)、版本发布日志

Oracle-java下载、开源/商业许可证&#xff08;收费、免费说明&#xff09;、版本发布日志 下载开源/商业许可证&#xff08;收费、免费说明&#xff09;java8版本发布日志以上是一般情况&#xff0c;具体的以官网发布信息为准 下载 下载地址&#xff1a;https://www.oracle.c…

google cloud storage批量文件下载

背景&#xff1a; 一些google cloud storage文件的下载是需要付费的&#xff0c;一些是不需要的&#xff0c;不需要的直接点击下方的下载按钮即可&#xff0c;但是常常存在大量的文件下载&#xff0c;挨个下载有点费时间而且占内存&#xff0c;所以我尝试了批量下载到HPC&…

day17 二叉树part04

110. 平衡二叉树 简单 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 class Solution {public boolean isBalanced(TreeNode root) {re…

(2023版)斯坦福CS231n学习笔记:DL与CV教程 (3) | 正则化与最优化

前言 &#x1f4da; 笔记专栏&#xff1a;斯坦福CS231N&#xff1a;面向视觉识别的卷积神经网络&#xff08;23&#xff09;&#x1f517; 课程链接&#xff1a;https://www.bilibili.com/video/BV1xV411R7i5&#x1f4bb; CS231n: 深度学习计算机视觉&#xff08;2017&#xf…

智能代码:生成式 AI 在软件开发中的革命性角色

想象一下&#xff0c;在智能手机革命性地改变了我们的生活之后&#xff0c;现在轮到了生成式 AI 在软件开发领域掀起风暴。你知道吗&#xff0c;如果代码能自己编写自己&#xff0c;这将是多么惊人的一步&#xff1f;这就好比我们现在能轻松地用手机应用管理日常生活一样&#…

【嘉立创EDA-PCB设计指南】1.PCB基本概念及原理图绘制

前言&#xff1a;本文详解PCB基本概念以及实现MCU最小系统原理图的绘制&#xff08;原理图包括MCU芯片GD32F103C8T6、外部晶振、输出端口、USB输入口、5v转3v3稳压输出、复位按键、唤醒按键、LED&#xff09;。为本专栏后面章节实现PCB绘制做准备。 最终绘制的原理图如下所示&…

2019年认证杯SPSSPRO杯数学建模B题(第二阶段)外星语词典全过程文档及程序

2019年认证杯SPSSPRO杯数学建模 基于统计和迭代匹配的未知语言文本片段提取模型 B题 外星语词典 原题再现&#xff1a; 我们发现了一种未知的语言&#xff0c;现只知道其文字是以 20 个字母构成的。我们已经获取了许多段由该语言写成的文本&#xff0c;但每段文本只是由字母…

使用Go语言的HTTP客户端和服务器

使用Go语言进行HTTP客户端和服务器开发是一种高效且强大的方式。Go语言的标准库提供了对HTTP协议的全面支持&#xff0c;使得创建HTTP客户端和服务器变得简单。 首先&#xff0c;让我们来看一下如何创建一个简单的HTTP服务器。在Go中&#xff0c;可以使用net/http包来创建HTTP…

HNU-计算机网络-实验5(自选)-安全相关编程实验

计算机网络 课程综合实验安全相关编程实验&#xff08;RUST&#xff09; 计科210X 甘晴void 202108010XXX 【前言】 这个《课程综合实验》是21级开始新加的实验&#xff0c;之前都没有。具体的可以看实验指导书&#xff0c;是用的19级同学的毕设。我完成的这个实验需要一点点R…

left join NULL踩坑

1、背景 因为最近响应监管&#xff0c;做数据全面匿名化的需求。会在写入数据库时&#xff0c;把姓名身份证做MD5处理后&#xff0c;只保留32位的前30位&#xff0c;保证即使拿到处理后的数据&#xff0c;也无法复原&#xff0c;恢复到源数据。 相应的&#xff0c;大数据BDP …

java-方法-动动小手指给个一键三连吧❤️✨

文章目录 1.概念2.静态方法和非静态方法2.1静态方法2.2非静态方法 3 参数传递方式4.方法的重载5.命令行传参6.可变参数7.递归作业 1.概念 在面向对象编程中&#xff0c;方法&#xff08;Method&#xff09;是类或对象中用于执行特定任务的一段代码。方法可以访问和操作对象的属…

layabox_2d游戏A*寻路实践

使用工具 Red Blob Games 效果 项目地址 LayaAStar2D: Laya2.0引擎2D游戏使用AStar实践。

深入理解 Flink(八)Flink Task 部署初始化和启动详解

JobMaster 部署 Task 核心入口&#xff1a; JobMaster.onStart();部署 Task 链条&#xff1a;JobMaster --> DefaultScheduler --> SchedulingStrategy --> ExecutionVertex --> Execution --> RPC请求 --> TaskExecutor TaskExecutor 处理 JobMaster 的 …

Few-shot Learning:知识点

目标&#xff1a; 让机器自己学会学习&#xff0c;学会理解和判断事物的异同&#xff08;如&#xff0c;区分两张图片内是相同的东西还是不同的东西&#xff0c;不是识别出是什么东西&#xff09; Pretraining 前景知识 C o s i n e S i m i l a r i t y Cosine \ Similarity…

❤ Uniapp使用二 ( 日常使用篇)

❤ Uniapp使用二 ( 日常使用篇) 一、表单 1、基础表单验证 form <form submit"formSubmit" reset"formReset"> <view class"uni-form-item uni-column"><view class"title">请选择类型{{selectvalue}}</view&…