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

这篇具有很好参考价值的文章主要介绍了SpringBoot案例 调用第三方接口传输数据。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、前言

最近再写调用三方接口传输数据的项目,这篇博客记录项目完成的过程,方便后续再碰到类似的项目可以快速上手
项目结构:
SpringBoot案例 调用第三方接口传输数据,SpringBoot,spring boot,后端,java

二、编码

这里主要介绍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: dev
    password: dev1234
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    #druid 数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

#####mybatis配置#####
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.jzj.pojo
  configuration:
    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对象,并指定URL
        HttpPost httpPost = new HttpPost(url);
        // 声明一个CloseableHttpResponse对象来接收请求的响应
        CloseableHttpResponse response = null;
        // 创建一个CloseableHttpClient对象。wrapClient方法是自定义的方法,用于构建和配置HttpClient对象
        CloseableHttpClient httpClient = wrapClient(url);
        try {
            // 通过重新赋值的方式为HttpPost对象设置URL
            httpPost = 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);
            // 判断响应的状态码是否等于200
            if (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() {
            // 该方法用于验证客户端证书
            @Override
            public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                                           String paramString) throws CertificateException {
            }

            // 该方法用于验证服务器证书
            @Override
            public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                                           String paramString) throws CertificateException {
            }

            // 该方法返回受信任的颁发机构(证书颁发机构)数组。在这里,返回null表示不对颁发机构进行限制
            @Override
            public 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
    @Autowired
    private TrsfToYkService trsfToYkService;
    // 注入trsfToYkLogService
    @Autowired
    private TrsfToYkLogService trsfToYkLogService;
    // 注入SfSfmxService
    @Autowired
    private 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);
            // 判断响应状态是否为200
            if (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安全传输协议做了跳过操作。

四、RestTemplate

Spring给我们提供了一个RestTemplate的API,可以方便的实现Http请求的发送。其中提供了大量的方法,方便我们发送Http请求,例如:

SpringBoot案例 调用第三方接口传输数据,SpringBoot,spring boot,后端,java

可以看到常见的Get、Post、Put、Delete请求都支持,如果请求参数比较复杂,还可以使用exchange方法来构造请求。

先将RestTemplate注册为一个Bean:

<!--okhttp-->
 <dependency>
     <groupId>com.squareup.okhttp3</groupId>
     <artifactId>okhttp</artifactId>
     <version>4.3.1</version>
 </dependency>

配置文件:

ok:
  http:
    connect-timeout: 1
    read-timeout: 3
    write-timeout: 3
    # 连接池中整体的空闲连接的最大数量
    max-idle-connections: 200
    # 连接空闲时间最多为 300 秒
    keep-alive-duration: 300
package com.jzj.config;

import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

/**
 * 描述:RestTemplate配置
 * 创建人: 黎明
 * 创建时间: 2023/11/17
 * 版本: 1.0.0
 */
@Configuration
public class RestTemplateConfig {

    @Value("${ok.http.connect-timeout}")
    private Integer connectTimeout;

    @Value("${ok.http.read-timeout}")
    private Integer readTimeout;

    @Value("${ok.http.write-timeout}")
    private Integer writeTimeout;

    @Value("${ok.http.max-idle-connections}")
    private Integer maxIdleConnections;

    @Value("${ok.http.keep-alive-duration}")
    private Long keepAliveDuration;


    @Bean
    public RestTemplate restTemplate() {
        ClientHttpRequestFactory factory = httpRequestFactory();
        RestTemplate restTemplate = new RestTemplate(factory);
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }

    public ClientHttpRequestFactory httpRequestFactory() {
        return new OkHttp3ClientHttpRequestFactory(okHttpConfigClient());
    }

    public OkHttpClient okHttpConfigClient(){
        return new OkHttpClient().newBuilder()
                .connectionPool(pool())
                .connectTimeout(connectTimeout, TimeUnit.SECONDS)
                .readTimeout(readTimeout, TimeUnit.SECONDS)
                .writeTimeout(writeTimeout, TimeUnit.SECONDS)
                .hostnameVerifier((hostname, session) -> true)
                .build();
    }

    public ConnectionPool pool() {
        return new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.SECONDS);
    }
}

远程调用

方式一:

// 2.5 调用接口下传商品数据
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// 2.5.1 设置请求参数
HttpEntity<AddGoodsVo> requestEntity = new HttpEntity<>(addGoodsVo, headers);
// 2.5.2 发送请求
ResponseEntity<ResponseDto> response = restTemplate.exchange(
        Request.URL,//请求地址
        HttpMethod.POST,//请求方式
        requestEntity,//请求参数
        ResponseDto.class //自定义返回值类型
);
// 2.5.3 解析响应
if(!response.getStatusCode().is2xxSuccessful()){
    // 查询失败,直接结束
    log.error("调用百望接口错误!!!");
}

方式二:

SpringBoot案例 调用第三方接口传输数据,SpringBoot,spring boot,后端,java文章来源地址https://www.toymoban.com/news/detail-651746.html

到了这里,关于SpringBoot案例 调用第三方接口传输数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 我调用第三方接口遇到的13大坑

    在实际工作中,我们经常需要在项目中调用第三方API接口,获取数据,或者上报数据,进行数据交换和通信。 那么,调用第三方API接口会遇到哪些问题?如何解决这些问题呢? 这篇文章就跟大家一起聊聊第三方API接口的话题,希望对你会有所帮助。   一般我们在第一次对接

    2023年04月16日
    浏览(44)
  • 仅仅是调用第三方接口那么简单吗?

    最近有个项目需要本地处理之后,然后调用第三方接口,本来开始觉得很简单得事情,不就是调用第三方接口吗?但是却一波三折。 首先有了下面的第一版的设计。 这个设计很简单,也是最容易想到的。主要有下面几步 1、本地处理; 2、调用第三方接口; 3、本地日志打印

    2024年02月06日
    浏览(48)
  • Java调用第三方http接口的常用方式

    前言 一、通过JDK网络类Java.net.HttpURLConnection 二、通过apache common封装好的HttpClient 三、通过Spring的RestTemplate 总结 今天项目需要接口互相调用,就看了一下这几个调用的方式 通过java.net包下的原生java.api提供的http请求 使用步骤: 通过统一的资源定位器(java.net.URL)获取连接器(java.

    2024年02月08日
    浏览(49)
  • 借助HttpWebRequest 调用第三方接口,获取Token和数据

    1、传入语句获取数据 2、获取token 3、获取设置身份认证及请求超时时间 4、在我使用的时候出现了下面的错误,通过查找是证书的问题,因为客户的web访问使用的IP地址访问,所以在代码中要加入跳过ssl验证的一行代码

    2024年03月18日
    浏览(41)
  • SAP PO 接口配置1:连通WebService-通过PO调用第三方接口

    SAP 通过 PO 中间件进行接口调用,调用外部接口。 外部接口可以用任意方式生成,常见的REST类型接口即可,关于如何使用python生成接口,其他章节另述。 本教程的前置条件,PO中已配置Business Systems,并与SAP环境连通。 这里以常见的post接口做示例,如有其他类型接口,需要每

    2024年02月05日
    浏览(81)
  • JAVA调用第三方接口的GET/POST/PUT请求方式

    GET请求 POST请求 POST请求(JSON传参) PUT请求(传TOKEN)

    2024年02月03日
    浏览(48)
  • Java以form-data(表单)的形式调用第三方接口

    之前写的调用第三方接口: Java使用原生API调用第三方接口 但是其中只包含了简单的接口(传递数据为JSON)调用。也就是 Content-Type 的值是设置成: 当第三方接口需要包含 文件 类型的参数,我们要设置成以 表单形式 提交,就要那么该属性就应该设置成 表示是以 表单形式

    2024年02月02日
    浏览(47)
  • SpringBoot中 如何优雅的 重试调用 第三方API?

    引言 在实际的应用中,我们经常需要调用第三方API来获取数据或执行某些操作。然而,由于网络不稳定、第三方服务异常等原因,API调用可能会失败。为了提高系统的稳定性和可靠性,我们通常会考虑实现重试机制。 本文将深入探讨如何在Spring Boot项目中优雅地重试调用第三

    2024年01月21日
    浏览(40)
  • feign自定义第三方接口;配置化Feign接口URL;调用指定IP的feign服务

    最近接手一个项目,各子工程之间通过feign调用;各服务部署在K8S上,通过nacos管理配置;由于服务部署的机器无法开放端口等原因,导致本机服务与测试环境网络端口无法互通,故需要重写feign的调用地址;个人总结的方法有以下几种: 目录  第一种:feignclient配置URL 第二种

    2024年02月04日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包