Java SpringBoot 对接知名台股 TWSE|批量采集上市股票行情实践

摘要

做跨境金融系统开发,经常需要获取中国台湾 TWSE 上市股票实时行情,用于量化分析、行情展示。本文基于 OkHttp 封装行情工具类,实现单只 / 批量台股行情拉取、K 线数据查询,结合 SpringBoot 定时任务完成数据解析与入库伪代码演示,包含连接池复用、异常捕获,数据源采用脉动行情数据 API。

关键词:Java;SpringBoot;TWSE;台股;行情采集

一、业务说明

TWSE 为台湾证券交易所上市市场,涵盖水泥、电子、金融等众多板块个股,例如台泥 1101、亚泥 1102 等标的。很多后台项目需要定时拉取多只台股行情。 直接手写网络请求容易遇到这些线上问题:

  1. OkHttp 未做单例,频繁创建实例导致端口占用;
  2. 没有超时控制,接口响应缓慢造成线程阻塞;
  3. 没有批量请求处理逻辑,循环单只请求效率低下;
  4. 缺少时区、交易时段处理,休市状态下做无效采集。

演示品种编码:TWSE:1101 (台泥),TWSE:1102 (亚泥)

二、Maven 依赖

java 复制代码
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.12.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.32</version>
</dependency>
<!-- mybatis‑plus用于数据库持久化演示 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis‑plus‑boot‑starter</artifactId>
    <version>3.5.3.1</version>
</dependency>

三、行情工具类完整代码

java 复制代码
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import com.alibaba.fastjson2.JSONObject;

import java.util.concurrent.TimeUnit;

/**
 * TWSE台股行情工具
 * demo品种:TWSE:1101 台泥,TWSE:1102 亚泥
 */
public class TwseQuoteUtil {

    private static final OkHttpClient HTTP_CLIENT;
    // 实时行情接口,仅代码内配置
    private static final String QUOTE_URL = "http://39.107.99.235:1008/getQuote.php";
    // K线接口,仅代码内配置
    private static final String KLINE_URL = "http://39.107.99.235:1008/redis.php";
    // 批量测试标的
    private static final String CODES = "TWSE:1101,TWSE:1102";

    static {
        HTTP_CLIENT = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true)
                .build();
    }

    /**
     * 获取台股实时行情,支持多标的逗号分隔
     */
    public static JSONObject getRealQuote(String code) {
        Request request = new Request.Builder()
                .url(QUOTE_URL + "?code=" + code)
                .header("Accept-Encoding", "gzip")
                .get()
                .build();
        try (Response resp = HTTP_CLIENT.newCall(request).execute()) {
            if (!resp.isSuccessful()) return null;
            return JSONObject.parseObject(resp.body().string());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取台股K线数据
     */
    public static String getKline(String code, String cycle, int rows) {
        String url = String.format("%s?code=%s&time=%s&rows=%d", KLINE_URL, code, cycle, rows);
        Request request = new Request.Builder()
                .url(url)
                .header("Accept-Encoding", "gzip")
                .get()
                .build();
        try (Response resp = HTTP_CLIENT.newCall(request).execute()) {
            if (!resp.isSuccessful()) return null;
            return resp.body().string();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) {
        JSONObject quote = getRealQuote(CODES);
        System.out.println("TWSE台股批量行情:\n" + quote);
        String kline = getKline("TWSE:1101", "1d", 100);
        System.out.println("\n台泥 日K线:\n" + kline);
    }
}

四、SpringBoot 定时同步任务

java 复制代码
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;

@Component
@EnableScheduling
public class TwseQuoteSyncTask {

    private final String batchCode = "TWSE:1101,TWSE:1102";

    @Scheduled(fixedRate = 30000)
    public void syncTwseQuote(){
        JSONObject result = TwseQuoteUtil.getRealQuote(batchCode);
        if(result == null || !"200".equals(result.getString("code"))){
            return;
        }
        JSONArray bodyArray = result.getJSONObject("data").getJSONArray("body");
        for(int i=0;i<bodyArray.size();i++){
            JSONObject item = bodyArray.getJSONObject(i);
            // 业务扩展:实体映射、入库逻辑
            // TwseQuoteEntity entity = new TwseQuoteEntity();
            // entity.setStockCode(item.getString("StockCode"));
            // entity.setPrice(item.getBigDecimal("Price"));
            // twseQuoteMapper.insert(entity);
            System.out.println("标的:"+item.getString("StockCode")+" 当前价格:"+item.getString("Price"));
        }
    }
}

五、关键字段说明

字段 释义
StockCode 台股品种编码
Price 最新成交价
Open 开盘价
LastClose 昨收价
High 日内最高
Low 日内最低
Volume 成交量
Diff 涨跌
DiffRate 涨跌幅
Time 行情更新时间

六、开发注意事项

  1. 请求头带上Accept‑Encoding: gzip开启压缩,减少网络流量;
  2. OkHttpClient 务必全局单例,禁止循环内 new 对象;
  3. TWSE 有本地交易时间,开发时要处理非开盘时段,避免无效采集;
  4. 支持 TWSE 上市、TPEx 上柜市场,更换对应编码即可;
  5. 批量拉取多个股票,code 参数用英文逗号拼接,减少 http 请求次数;
  6. 生产环境增加失败重试、日志告警,连续失败输出日志便于排查。

七、总结

本文完成 TWSE 台股批量行情采集,搭配定时任务提供解析入库示例。只修改标的编码,即可快速对接 TPEx 上柜市场其他个股,适合跨境行情后台、量化研究项目开发。

相关推荐
mldong6 小时前
一个 App,十三套后端:手机审批端 uni-jeeflow-app 开源了
java·架构
tqs_123457 小时前
MySQL RR隔离级别死锁|Gap间隙锁、临键锁,订单并发范围查询死锁根因方案
java
逆境不可逃8 小时前
Pi Agent 学习笔记:多个工具怎样并行执行
java
浪子明X8 小时前
十六位账本怎样发现传输差错:Internet Checksum 生活类比
开发语言
weixin_BYSJ19878 小时前
【计算机毕设】基于SpringBoot与Vue的文物保护档案管理系统08621
vue.js·spring boot·spring cloud·微服务·架构·django·课程设计
Flynt8 小时前
Java 27 升级实测:默认值动得比新特性多,有个老参数会让 JVM 直接起不来
java·jvm·后端
Bs_MoneyMagnet8 小时前
基于springboot+vue的个人健康管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·vue3·springboot3·计算机毕业设计
星云API技术支持9 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
niucloud-admin9 小时前
JAVA V6 多商户商城 开发文档——job 计划任务开发
java·python·github
海宇AI10 小时前
零信任架构实战:基于海宇柠檬查出险-登记证构建自动化车抵贷核保网关
java·人工智能·架构·自动化