当前位置: 首页 > news >正文

SpringBoot案例 调用第三方接口传输数据

一、前言

最近再写调用三方接口传输数据的项目,这篇博客记录项目完成的过程,方便后续再碰到类似的项目可以快速上手
项目结构:
在这里插入图片描述

二、编码

这里主要介绍HttpClient发送POST请求工具类和定时器的使用,mvc三层架构编码不做探究

pom.xml

<dependencies><!--web启动依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- httpclient --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version></dependency><!--fastjson--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.79</version></dependency><!--swagger2--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.1</version></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!--druid--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.14</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--测试单元--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>

application-dev.yml

#####端口配置#####
server:port: 9991#####数据源配置#####
spring:datasource:username: devpassword: dev1234url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8driver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSource#druid 数据源专有配置initialSize: 5minIdle: 5maxActive: 20maxWait: 60000timeBetweenEvictionRunsMillis: 60000minEvictableIdleTimeMillis: 300000validationQuery: SELECT 1 FROM DUALtestWhileIdle: truetestOnBorrow: falsetestOnReturn: falsepoolPreparedStatements: true#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入filters: stat,wall,log4jmaxPoolPreparedStatementPerConnectionSize: 20useGlobalDataSourceStat: trueconnectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500#####mybatis配置#####
mybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.jzj.pojoconfiguration:map-underscore-to-camel-case: true#####配置日志文件#####
logging:config: classpath:logback.xml#设置日志级别的节点level:com:jzj: debug

Constast

package com.jzj.common;public class Constast {/*** 请求头信息*/public static final String CONTENT_TYPE = "application/json;charset=UTF-8";/*** 返回状态值*/public static final Integer OK = 200;public static  final String YK_URL = "三方接口地址";
}

utils

package com.jzj.utils;import com.jzj.common.Constast;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.nio.charset.StandardCharsets;/*** Apache HttpClient发送POST请求工具类** @author 黎明* @version 1.0* @date 2023/8/14 14:18*/
public class HttpUtils {/*** 发送post请求** @param url       请求url* @param jsonParam 请求参数* @return 响应数据*/public static String doPostJson(String url, String jsonParam) {// 创建一个HttpPost对象,并指定URLHttpPost httpPost = new HttpPost(url);// 声明一个CloseableHttpResponse对象来接收请求的响应CloseableHttpResponse response = null;// 创建一个CloseableHttpClient对象。wrapClient方法是自定义的方法,用于构建和配置HttpClient对象CloseableHttpClient httpClient = wrapClient(url);try {// 通过重新赋值的方式为HttpPost对象设置URLhttpPost = new HttpPost(url);// 设置请求头的内容类型。Constast.CONTENT_TYPE表示请求的数据类型httpPost.setHeader("Content-type", Constast.CONTENT_TYPE);// 创建一个StringEntity对象,用于封装JSON参数。StringEntity entity = new StringEntity(jsonParam, "UTF-8");// 将实体的内容编码设置为与请求头的内容类型相同entity.setContentEncoding(new BasicHeader("Content-type", Constast.CONTENT_TYPE));// 将StringEntity对象设置为HttpPost请求的实体httpPost.setEntity(entity);// 执行HttpPost请求,并将响应赋值给response对象response = httpClient.execute(httpPost);// 判断响应的状态码是否等于200if (response.getStatusLine().getStatusCode() == Constast.OK) {// 将响应实体转换为字符串并返回。EntityUtils.toString方法用于读取响应实体的内容。return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);}} catch (Exception e) {throw new RuntimeException("[发送POST请求错误:]" + e.getMessage());} finally {// 释放连接、关闭响应和关闭HttpClient对象try {httpPost.releaseConnection();response.close();if (httpClient != null) {httpClient.close();}} catch (IOException e) {e.printStackTrace();}}return null;}/*** 根据URL的协议来配置HttpClient对象* @param url url地址* @return CloseableHttpClient*/private static CloseableHttpClient wrapClient(String url) {// 使用HttpClientBuilder类创建一个默认的HttpClient对象CloseableHttpClient client = HttpClientBuilder.create().build();if (url.startsWith("https")) { // 检查URL是否以"https"开头,以确定是否需要使用HTTPS协议// 如果URL以"https"开头,调用方法获取配置了HTTPS支持的CloseableHttpClient对象client = getCloseableHttpsClients();}return client;}/*** 创建一个支持HTTPS的CloseableHttpClient对象* @return CloseableHttpClient*/private static CloseableHttpClient getCloseableHttpsClients() {// 采用绕过验证的方式处理https请求SSLClient ssl = new SSLClient();SSLContext sslcontext = ssl.createIgnoreVerifySSL();// 设置协议http和https对应的处理socket链接工厂的对象org.apache.http.config.Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE).register("https", new SSLConnectionSocketFactory(sslcontext)).build();PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);HttpClients.custom().setConnectionManager(connManager);// 创建自定义的httpsclient对象CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build();return client;}
}
package com.jzj.utils;import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;/*** 用于创建一个支持绕过HTTPS验证的SSLContext对象** @author 黎明* @version 1.0* @date 2023/8/14 14:35*/
public class SSLClient {// 使用@SuppressWarnings注解来抑制未使用的警告@SuppressWarnings("unused")public SSLContext createIgnoreVerifySSL() {// 创建套接字对象SSLContext sslContext = null;try {// 指定TLS版本sslContext = SSLContext.getInstance("TLSv1.2");} catch (NoSuchAlgorithmException e) {throw new RuntimeException("[创建套接字失败:] " + e.getMessage());}// 实现X509TrustManager接口,用于绕过验证X509TrustManager trustManager = new X509TrustManager() {// 该方法用于验证客户端证书@Overridepublic void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,String paramString) throws CertificateException {}// 该方法用于验证服务器证书@Overridepublic void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,String paramString) throws CertificateException {}// 该方法返回受信任的颁发机构(证书颁发机构)数组。在这里,返回null表示不对颁发机构进行限制@Overridepublic java.security.cert.X509Certificate[] getAcceptedIssuers() {return null;}};try {// 初始化sslContext对象sslContext.init(null, new TrustManager[]{trustManager}, null);} catch (KeyManagementException e) {throw new RuntimeException("[初始化套接字失败:] " + e.getMessage());}return sslContext;}
}

scheduled

package com.jzj.scheduled;import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jzj.common.Constast;
import com.jzj.pojo.TrsfToYk;
import com.jzj.pojo.TrsfToYkLog;
import com.jzj.service.SfSfmxService;
import com.jzj.service.TrsfToYkLogService;
import com.jzj.service.TrsfToYkService;
import com.jzj.utils.HttpUtils;
import com.jzj.vo.YkResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import java.util.List;/*** 定时器任务** @author 黎明* @version 1.0* @date 2023/8/15 15:03*/
@Component
@Slf4j
public class TrsfToYkScheduled {// 注入trsfToYkService@Autowiredprivate TrsfToYkService trsfToYkService;// 注入trsfToYkLogService@Autowiredprivate TrsfToYkLogService trsfToYkLogService;// 注入SfSfmxService@Autowiredprivate SfSfmxService sfSfmxService;/*** 审方信息下传英克*/@Scheduled(cron = "*/10 * * * * *")public void toYk() {// 根据视图查询所有bs=0审方信息List<TrsfToYk> sfAllInfo = trsfToYkService.findAll();if (sfAllInfo.size() != 0) { // 判断是否有数据ObjectMapper mapper = new ObjectMapper();String requestData = null;try {requestData = mapper.writeValueAsString(sfAllInfo);} catch (JsonProcessingException e) {e.printStackTrace();}log.info("发送的数据是:{}", requestData);String responseData = HttpUtils.doPostJson(Constast.YK_URL, requestData);log.info("响应的数据是:{}", responseData);JSONObject responseJson = JSONObject.parseObject(responseData);YkResultVo ykResultVo = responseJson.toJavaObject(YkResultVo.class);// 判断响应状态是否为200if (ykResultVo.getStatus().equals("200") && ykResultVo.getStatus() != null) {// 记录日志ykResultVo.getData().stream().forEach(v -> {TrsfToYkLog trsfToYkLog = new TrsfToYkLog();trsfToYkLog.setAuditId(v.getAuditId());trsfToYkLog.setStatus(v.getStatus());trsfToYkLogService.insertLog(trsfToYkLog);});// 更新审方明细表bs字段ykResultVo.getData().stream().filter(v -> v.getStatus().equals("200")).forEach(v -> {long aid = Long.parseLong(v.getAuditId());sfSfmxService.renewalBs(aid);});}}}
}

三、总结

该定时任务每10秒执行一次,将满足条件的审方信息发送到三方系统,并根据返回的结果进行相应的日志记录和数据更新操作。再调用三方接口时,使用的是封装好了的工具类将post请求发送给三方接口,并对https安全传输协议做了跳过操作。

相关文章:

SpringBoot案例 调用第三方接口传输数据

一、前言 最近再写调用三方接口传输数据的项目&#xff0c;这篇博客记录项目完成的过程&#xff0c;方便后续再碰到类似的项目可以快速上手 项目结构&#xff1a; 二、编码 这里主要介绍HttpClient发送POST请求工具类和定时器的使用&#xff0c;mvc三层架构编码不做探究 pom.x…...

第三章,矩阵,08-矩阵的秩及相关性质

第三章&#xff0c;矩阵&#xff0c;08-矩阵的秩及相关性质 秩的定义1最高阶非零子式定理秩的定义2秩的性质性质1性质2性质3性质4性质5性质6性质7性质8性质9性质10性质11性质12性质12的推论 玩转线性代数(20)矩阵的秩的笔记&#xff0c;相关证明以及例子见原文 秩的定义1 设矩…...

VS2019 + Qt : setToolTip的提示内容出现乱码

VS2019 Qt : setToolTip的提示内容出现乱码 在使用setToolTip()时&#xff0c; setToolTip(QString("asd你好&#xff01;");标签提示只有英文是对的&#xff0c;中文是乱码&#xff01; 应该是编码出了问题。默认情况下&#xff0c;Qt使用的是UTF-8编码&#xf…...

PO、BO、VO、DTO、DAO、POJO

文章目录 PO&#xff08;Persistant Object&#xff09;持久对象DO&#xff08;Data Object&#xff09;数据对象AO&#xff08;Application Object&#xff09;应用对象BO&#xff08;Business Object&#xff09;业务对象VO&#xff08;Value Object&#xff09;表现对象DTO&…...

MySQL— 基础语法大全及操作演示!!!(下)

MySQL—— 基础语法大全及操作演示&#xff08;下&#xff09;—— 持续更新 三、函数3.1 字符串函数3.2 数值函数3.3 日期函数3.4 流程函数 四、约束4.1 概述4.2 约束演示4.3 外键约束4.3.1 介绍4.3.2 语法4.3.3 删除/更新行为 五、多表查询5.1 多表关系5.1.1 一对多5.1.2 多对…...

Springboot+vue网上招聘系统

系统的首页&#xff0c;头部有三个选项框&#xff0c;第一个是主页&#xff0c;第二个是才艺技能平台&#xff0c;第三个是登录注册。1.1.2 登录注册模块 系统的登录注册包括登录和注册两个部分。所有系统用户使用后台管理功能都需要经行登录&#xff0c;根据选择不同的身份进入…...

奥威BI数据可视化工具:报表就是平台,随时自助分析

别的数据可视化工具&#xff0c;报表就只是报表&#xff0c;而奥威BI数据可视化工具&#xff0c;一张报表就约等于一个平台&#xff0c;可随时展开多维动态自助分析&#xff0c;按需分析&#xff0c;立得数据信息。 奥威BI是一款多维立体分析数据的数据可视化工具。它可以帮助…...

iPhone(iPad)安装deb文件

最简单的方法就是把deb相关的文件拖入手机对应的目录&#xff0c;一般是DynamicLibraries文件夹 参考&#xff1a;探讨手机越狱和安装deb文件的几种方式研究 1、在 Mac 上安装 dpkg 命令 打包 deb 教程之在 Mac 上安装 dpkg 命令_xcode打包root权限deb_qq_34810996的博客-CS…...

手撕单链表

目录 链表的概念和结构 单链表的实现 申请新结点 打印 尾插 头插 尾删 头删 ​编辑 查找 在pos位置前插入元素 在pos位置后插入元素 删除pos位置的元素 删除pos位置之后的位置的元素​编辑 完整代码 SListNode.h SListNode.c 链表的概念和结构 链表是一种物理存储…...

Spring-aop特点,专业术语及案例演示

一.aop简介 AOP&#xff08;Aspect-Oriented Programming&#xff09;是Spring框架的一个重要特性&#xff0c;它通过将横切关注点&#xff08;cross-cutting concerns&#xff09;从核心业务逻辑中分离出来&#xff0c;以模块化的方式在整个应用程序中重复使用。以下是关于AOP…...

探秘Java的Map集合:键值映射的奇妙世界

文章目录 1. 单列集合 vs. 双列集合2. Map接口&#xff1a;键与值的契约3. 深入探索HashMap3.1 特性与构造方法3.2 常用方法3.3 遍历HashMap 4. 美妙的LinkedHashMap 在Java编程中&#xff0c;集合是不可或缺的重要部分&#xff0c;它为我们提供了各种数据结构和算法的实现。其…...

git权限问题解决方法Access denied fatal: Authentication failed

文章目录 遇到Access denied 的权限问题解决方法1、git的密码修改过&#xff0c;但是本地没更新。2、确定问题&#xff0c;然后增加配置① 查询用户信息②如果名称和email不对&#xff0c;设置名称&#xff1a;③ 检查ssh-add是否链接正常④ 设置不要每次都输入用户名密码 3、配…...

Hands on RL 之 Off-policy Maximum Entropy Actor-Critic (SAC)

Hands on RL 之 Off-policy Maximum Entropy Actor-Critic (SAC) 文章目录 Hands on RL 之 Off-policy Maximum Entropy Actor-Critic (SAC)1. 理论基础1.1 Maximum Entropy Reinforcement Learning, MERL1.2 Soft Policy Evaluation and Soft Policy Improvement in SAC1.3 Tw…...

JavaScript中的this指向,call、apply、bind的简单实现

JavaScript中的this this是JavaScript中一个特殊关键字&#xff0c;用于指代当前执行上下文中的对象。它的难以理解之处就是值不是固定的&#xff0c;是再函数被调用时根据调用场景动态确定的&#xff0c;主要根据函数的调用方式来决定this指向的对象。this 的值在函数被调用时…...

Linux学习之基本指令一

在学习Linux下的基本指令之前首先大家要知道Linux下一切皆目录&#xff0c;我们的操作基本上也都是对目录的操作&#xff0c;这里我们可以联想我们是如何在windows上是如何操作的&#xff0c;只是形式上不同&#xff0c;类比学习更容易理解。 目录 01.ls指令 02. pwd命令 0…...

appium默认60秒关闭应用的问题

问题&#xff1a;appium默认启动一个应用的session过期时间是60秒到时间会自动停了刚启动的应用&#xff0c;工作台打印&#xff1a;info: [debug] We shut down because no new commands came in的日志 分析&#xff1a;--command-timeout 60 The default command timeout fo…...

Docker 容器内无法使用vim命令 解决方法

目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 进入Docker容器后 无法使用vim编辑器,出现如下问题:bash: vim: command not found 如图所示: 想着通过apt-get 安装vim,出现如下问题: root@b9f0fd330d5b:/# apt-get install vim Reading package lists... Done B…...

Django的简介安装与配置及两大设计模式

一.Djang的介绍 1.Django是什么 Django 是使用 Python 语言开发的一款免费而且开源的 Web 应用框架。 由于 Python 语言的跨平台性&#xff0c;所以 Django 同样支持 Windows、Linux 和 Mac 系统。 在 Python 语言炽手可热的当下&#xff0c;Django 也迅速的崛起&#xff0c;在…...

Mybatis分页插件——PageHelper

一、定义 PageHelper用在mybatis插件里面&#xff0c;可以自动的为最近的sql语句进行分页查询&#xff0c;提供分页的页码size和每页数量num&#xff0c;在查询过程中hi自动的拼接limit关键字&#xff0c;不用再改写sql语句了 在PageHelper.startPage()&#xff1b; 在启动查询…...

k8s认证详解 k8s证书详解 2023推荐

推荐阅读 https://www.yii666.com/blog/478731.html?actiononAll 在 Kube-apiserver 中提供了很多认证方式&#xff0c;其中最常用的就是 TLS 认证&#xff0c;当然也有 BootstrapToken&#xff0c;BasicAuth 认证等&#xff0c;只要有一个认证通过&#xff0c;那么 Kube-api…...

php初解

php是什么&#xff1f; PHP&#xff0c;全称 Hypertext Preprocessor &#xff0c;中文翻译“超文本预处理器”。 PHP是一种被广泛应用的开源通用脚本语言&#xff0c;尤其适用于 Web 开发。 拥有快速&#xff0c;灵活&#xff0c;实用的特点&#xff0c;PHP能做任何事&#xf…...

【C语言】回调函数,qsort排序函数的使用和自己实现,超详解

文章目录 前言一、回调函数是什么二、回调函数的使用1.使用标准库中的qsort函数2.利用qsort函数对结构体数组进行排序 三、实现qsort函数总结 先记录一下访问量突破2000啦&#xff0c;谢谢大家支持&#xff01;&#xff01;&#xff01; 这里是上期指针进阶链接&#xff0c;方便…...

PHP手术麻醉系统源码,自动生成麻醉和护理医疗文书

一套手术麻醉系统源码&#xff0c;可二次开发 手术室麻醉临床信息系统&#xff08;AIMS&#xff09;是应用于医院手术室、麻醉科室的计算机软件系统。该系统针对整个围术期&#xff0c;对病人进行全程跟踪与信息管理&#xff0c;自动集成病人HIS、LIS、RIS、PACS信息&#xff0…...

内网穿透实战应用——【通过cpolar分享本地电脑上有趣的照片:发布piwigo网页】

通过cpolar分享本地电脑上有趣的照片&#xff1a;发布piwigo网页 文章目录 通过cpolar分享本地电脑上有趣的照片&#xff1a;发布piwigo网页前言1. 设定一条内网穿透数据隧道2. 与piwigo网站绑定3. 在创建隧道界面填写关键信息4. 隧道创建完成 总结 前言 首先在本地电脑上部署…...

iPhone删除的照片能恢复吗?不小心误删了照片怎么找回?

iPhone最近删除清空了照片还能恢复吗&#xff1f;大家都知道&#xff0c;照片对于我们来说是承载着美好回忆的一种形式。它记录着我们的平淡生活&#xff0c;也留住了我们的美好瞬间&#xff0c;具有极其重要的纪念价值。 照片不小心误删是一件非常难受的事&#xff0c;那么iP…...

LeetCode--HOT100题(32)

目录 题目描述&#xff1a;138. 复制带随机指针的链表&#xff08;中等&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;138. 复制带随机指针的链表&#xff08;中等&#xff09; 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &…...

SAP MM学习笔记24-以评估收货(评价)和非评估收货(非评价)

SAP 中 有评价入库&#xff08;评估收货&#xff09;和非评价入库&#xff08;非评估收货&#xff09;两种入库方式。 一般来说在库品目会采用评价入库&#xff0c;而消费品目&#xff0c;会采用非评价入库。 其实评价入库&#xff0c;非评价入库对外都无所谓的&#xff0c;人…...

Hadoop的DataNode无法启动的解决方案

Hadoop重启一次&#xff0c;里面的数据需要重新导入&#xff0c;发现无法导入数据&#xff0c;查看jps发现是DataNode没有启动&#xff0c;重新启动发现也无法启动&#xff0c;原因是前面重新启动NameNode&#xff0c;里面的文件格式化一次&#xff0c;DataNode的文件不一致&am…...

re中的match和search有什么区别?

问题:请说明以下re模块中的match和search有什么区别? re.match()与re.search()的区别 re.match()只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,结果返回None,而re.search()匹配整个字符串,直到找到一个匹配 re.search() re.search()扫描整个字符串并…...

《内网穿透》无需公网IP,公网SSH远程访问家中的树莓派

文章目录 前言 如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar内网穿透4.2 cpolar进行token认证4.3 配置cpolar服务开机自启动4.4 查看映射到公网的隧道地…...