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安全传输协议做了跳过操作。

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

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

相关文章

43、TCP报文(一)

本节内容开始&#xff0c;我们正式学习TCP协议中具体的一些原理。首先&#xff0c;最重要的内容仍然是这个协议的封装结构和首部格式&#xff0c;因为这里面牵扯到一些环环相扣的知识点&#xff0c;例如ACK、SYN等等&#xff0c;如果这些内容不能很好的理解&#xff0c;那么后续…

SASS 学习笔记

SASS 学习笔记 总共会写两个练手项目&#xff0c;成品在 https://goldenaarcher.com/scss-study 可以看到&#xff0c;代码在 https://github.com/GoldenaArcher/scss-study。 什么是 SASS SASS 是 CSS 预处理&#xff0c;它提供了变量&#xff08;虽然现在 CSS 也提供了&am…

web集群学习:搭建 LNMP应用环境

目录 LNMP的介绍&#xff1a; LNMP组合工作流程&#xff1a; FastCGI介绍&#xff1a; 1、什么是 CGI 2、什么是 FastCGI 配置LNMP 1、部署LNMP环境 2、配置LNMP环境 LNMP的介绍&#xff1a; 随着 Nginx Web 服务的逐渐流行&#xff0c;又岀现了新的 Web 服务环境组合—…

面向对象编程(OOP):Python中的抽象与封装

文章目录 &#x1f340;引言&#x1f340; 类与对象&#x1f340;封装&#x1f340;继承&#x1f340;多态&#x1f340;面向对象编程的优势&#x1f340;使用面向对象编程的场景&#x1f340;实例化与构造函数&#x1f340; 成员属性和类属性&#x1f340;魔术方法&#x1f34…

初识Sentinel

目录 1.解决雪崩的方式有4种&#xff1a; 1.1.2超时处理&#xff1a; 1.1.3仓壁模式 1.1.4.断路器 1.1.5.限流 1.1.6.总结 1.2.服务保护技术对比 1.3.Sentinel介绍和安装 1.3.1.初识Sentinel 1.3.2.安装Sentinel 1.4.微服务整合Sentinel 2.流量控制 2.1.簇点链路 …

K8S调度

K8S调度 一、List-Watch 机制 controller-manager、scheduler、kubelet 通过 List-Watch 机制监听 apiserver 发出的事件&#xff0c;apiserver 通过 List-Watch 机制监听 etcd 发出的事件1.scheduler 的调度策略 预选策略/预算策略&#xff1a;通过调度算法过滤掉不满足条件…

什么是EM(最大期望值算法)

什么是EM(最大期望值算法) 在现实生活中&#xff0c;苹果百分百是苹果&#xff0c;梨百分白是梨。 生活中还有很多事物是概率分布&#xff0c;比如有多少人结了婚&#xff0c;又有多少人有工作&#xff0c; 如果我们想要调查人群中吸大麻者的比例呢&#xff1f;敏感问题很难得…

PHP8的字符串操作1-PHP8知识详解

字符串是php中最重要的数据之一&#xff0c;字符串的操作在PHP编程占有重要的地位。在使用PHP语言开发web项目的过程中&#xff0c;为了实现某些功能&#xff0c;经常需要对某些字符串进行特殊的处理&#xff0c;比如字符串的格式化、字符串的连接与分割、字符串的比较、查找等…

【Hyper-V】Windows11 家庭版怎么启用虚拟机Hyper-V

在电脑Windows11系统上启用虚拟机Hyper-V&#xff0c;打开 启用和关闭WIndows功能&#xff0c;找到其中一项Hyper-V&#xff0c;对于家庭版的系统用户来说&#xff0c;这个选项是没有的&#xff0c;接下来讲一讲怎么开启。 安装Hyper-V 创建一个文件名为Hyper-v.bat&#xff…

springcloud3 hystrix实现服务降级的案例配置2

一 服务降级的说明 1.1 服务降级说明 "服务器忙&#xff0c;请稍后在试"不让客户达等待&#xff0c;立即返回一个友好的提示。 1.2 服务降级的触发情况 1.程序运行异常&#xff1b; 2.超时&#xff1b; 3.服务熔断触发服务降级&#xff1b;4 .线程池/信号量打…

Web菜鸟教程 - Springboot接入认证授权模块

网络安全的重要性不言而喻&#xff0c;如今早已不是以前随便弄个http请求就能爬到数据的时代&#xff0c;而作为一个架构师&#xff0c;网络安全必须在产品开发之初就考虑好。因为在产品开发的后期&#xff0c;一方面是客户增多&#xff0c;压力变大&#xff0c;可供利用的时间…

[LeetCode]矩阵对角线元素的和

解题 思路 1: 循环,找到主对角线的下标和副对角线的下标,如果矩阵长或宽为奇数的时候,需要减去中间公共的那一个值,中间公共的那个数的下标为mat[mat.size()/2][mat.size()/2]副对角线的下标为 mat [i][mat.size()-i-1] class Solution { public:int diagonalSum(vector<ve…

2.阿里云对象存储OSS

1.对象存储概述 文件上传&#xff0c;是指将本地图片、视频、音频等文件上传到服务器上&#xff0c;可以供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛&#xff0c;我们经常发抖音、发朋友圈都用到了文件上传功能。 实现文件上传服务&#xff0c;需要有存储的支持…

软考笔记——10.项目管理

进度管理 进度管理就是采用科学的方法&#xff0c;确定进度目标&#xff0c;编制进度计划和资源供应计划&#xff0c;进行进度控制&#xff0c;在与质量、成本目标协调的基础上&#xff0c;实现工期目标。 具体来说&#xff0c;包括以下过程&#xff1a; (1) 活动定义&#…

(stm32)低功耗模式

低功耗模式 执行哪个低功耗模式的程序判断流程 标志位设置操作一定要在WFI/WFE之前&#xff0c;调用此指令后立即进入睡眠判断流程 模式对比 睡眠模式 停止模式 待机模式

Effective C++学习笔记(8)

目录 条款49&#xff1a;了解new-handler的行为条款50&#xff1a;了解new和delete的合理替换时机条款51&#xff1a;编写new和delete时需固守常规条款52&#xff1a;写了placement new也要写placement delete条款53&#xff1a;不要轻忽编译器的警告条款54&#xff1a;让自己熟…

智能楼宇综合布线实训室建设方案

一、楼宇智能综合布线实训室方案概述 楼宇智能综合布线实训室方案旨在为学生提供一个真实的学习和实践环境&#xff0c;以培养他们在楼宇智能综合布线领域的实际操作能力和技能。以下是一个概述&#xff1a; 1. 培养目标&#xff1a;培养学生在楼宇智能综合布线方面的综合能力…

LeetCode150道面试经典题-- 环形链表(简单)

1.题目 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&…

React2023电商项目实战 - 1.项目搭建

古人学问无遗力&#xff0c;少壮工夫老始成。 纸上得来终觉浅&#xff0c;绝知此事要躬行。 —— 陆游《《冬夜读书示子聿》》 系列文章目录 项目搭建App登录及网关App文章自媒体平台&#xff08;博主后台&#xff09;内容审核(自动) 文章目录 系列文章目录一、项目介绍1.页面…

Smartbi 李代:人尽其才、数尽其用,Smartbi Eagle智慧数据运营平台全新亮相

数据是企业数字化转型的基石&#xff0c;也是赢得未来的核心资产和竞争力。数字化转型的关键&#xff0c;是在全公司建立一种数据驱动的组织和机制&#xff0c;营造数据文化的氛围&#xff0c;让更多的用户、在更多的场景中&#xff0c;有意愿、有能力使用数据&#xff0c;从而…