From 5c5d5112e7b999381f8b20c97e53314e6cedada2 Mon Sep 17 00:00:00 2001
From: zyy <zyy@email.com>
Date: Wed, 09 Jul 2025 18:34:52 +0800
Subject: [PATCH] 股票主页、市场页面接口
---
src/main/java/com/nq/ws/WebsocketRunClient.java | 5
src/main/resources/mapper/StockMapper.xml | 6
src/main/java/com/nq/service/impl/StockServiceImpl.java | 172 ++++++++++++++----
src/main/java/com/nq/config/ThreadPoolConfig.java | 20 ++
src/main/java/com/nq/utils/redis/RedisKeyUtil.java | 21 +
src/main/java/com/nq/controller/StockApiController.java | 35 +++
src/main/java/com/nq/pojo/DataStockBean.java | 2
src/main/java/com/nq/utils/task/stock/StockTask.java | 121 +++++++------
src/main/java/com/nq/utils/redis/RedisKeyConstant.java | 5
src/main/resources/application.properties | 6
src/main/java/com/nq/utils/redis/RedisShardedPoolUtils.java | 8
src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java | 3
src/main/java/com/nq/ws/MXWebsocketRunClient.java | 4
src/main/java/com/nq/service/IStockService.java | 21 ++
src/main/java/com/nq/service/impl/PriceServicesImpl.java | 60 -----
15 files changed, 325 insertions(+), 164 deletions(-)
diff --git a/src/main/java/com/nq/config/ThreadPoolConfig.java b/src/main/java/com/nq/config/ThreadPoolConfig.java
new file mode 100644
index 0000000..00dd23f
--- /dev/null
+++ b/src/main/java/com/nq/config/ThreadPoolConfig.java
@@ -0,0 +1,20 @@
+package com.nq.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+@Configuration
+public class ThreadPoolConfig {
+
+ @Bean
+ public ThreadPoolTaskExecutor taskExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(4);
+ executor.setMaxPoolSize(4);
+ executor.setQueueCapacity(10);
+ executor.setThreadNamePrefix("stock-sync-");
+ executor.initialize();
+ return executor;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/nq/controller/StockApiController.java b/src/main/java/com/nq/controller/StockApiController.java
index d265e7a..99ecafa 100644
--- a/src/main/java/com/nq/controller/StockApiController.java
+++ b/src/main/java/com/nq/controller/StockApiController.java
@@ -54,6 +54,7 @@
+
@RequestMapping("getOptionStock.do")
@ResponseBody()
public ServerResponse getOptionStock(HttpServletRequest request){
@@ -117,4 +118,38 @@
public ServerResponse getVipByCode(String code) {
return this.iStockService.getVipByCode(code);
}
+
+ /**
+ * 获取首页数据 新闻和指数列表
+ * @param pageSize
+ * @return
+ */
+ @PostMapping({"getHomePageData.do"})
+ @ResponseBody
+ public ServerResponse getHomePageData(@RequestParam(value = "pageSize", defaultValue = "5") int pageSize) {
+ return this.iStockService.getIndicesIndexListAndNews(pageSize);
+ }
+
+ /**
+ * 获取指数id和name 默认US
+ * @param stockType
+ * @return
+ */
+ @RequestMapping("getIndicesList.do")
+ @ResponseBody
+ public ServerResponse getIndicesList(@RequestParam(value = "stockType", defaultValue = "US") String stockType) {
+ return this.iStockService.getIndicesList(stockType);
+ }
+
+ /**
+ * 获取单个指数数据和k线图 默认US
+ * @param stockType
+ * @return
+ */
+ @RequestMapping("getIndicesAndKData.do")
+ @ResponseBody
+ public ServerResponse getIndicesAndKData(@RequestParam(value = "pid") String pid,
+ @RequestParam(value = "stockType", defaultValue = "US") String stockType) {
+ return this.iStockService.getIndicesAndKData(pid, stockType);
+ }
}
diff --git a/src/main/java/com/nq/pojo/DataStockBean.java b/src/main/java/com/nq/pojo/DataStockBean.java
index 1e53a72..c927d49 100644
--- a/src/main/java/com/nq/pojo/DataStockBean.java
+++ b/src/main/java/com/nq/pojo/DataStockBean.java
@@ -64,5 +64,7 @@
private String Ticker;
+ //k线
+ private Object kData;
}
diff --git a/src/main/java/com/nq/service/IStockService.java b/src/main/java/com/nq/service/IStockService.java
index 4763888..d47a861 100644
--- a/src/main/java/com/nq/service/IStockService.java
+++ b/src/main/java/com/nq/service/IStockService.java
@@ -104,5 +104,24 @@
Object getKData(String pid,String interval,String stockType);
- ServerResponse getOptionStock(HttpServletRequest request);
+ ServerResponse getOptionStock(HttpServletRequest request);
+
+ /**
+ * 获取首页指数列表
+ * @param pageSize
+ * @return
+ */
+ ServerResponse getIndicesIndexListAndNews(Integer pageSize);
+
+ /**
+ * 获取指数数据 获取指数id和name
+ * @return
+ */
+ ServerResponse getIndicesList(String stockType);
+
+ /**
+ * 获取单个指数数据和k线图
+ * @return
+ */
+ ServerResponse getIndicesAndKData(String pid, String stockType);
}
diff --git a/src/main/java/com/nq/service/impl/PriceServicesImpl.java b/src/main/java/com/nq/service/impl/PriceServicesImpl.java
index 05dd037..6091b18 100644
--- a/src/main/java/com/nq/service/impl/PriceServicesImpl.java
+++ b/src/main/java/com/nq/service/impl/PriceServicesImpl.java
@@ -5,7 +5,6 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
import com.nq.dao.StockDzMapper;
import com.nq.dao.StockMapper;
import com.nq.dao.StockSettingMapper;
@@ -13,23 +12,14 @@
import com.nq.pojo.*;
import com.nq.service.IPriceServices;
import com.nq.service.IStockConfigServices;
-import com.nq.utils.PropertiesUtil;
-import com.nq.utils.http.HttpClientRequest;
import com.nq.utils.redis.RedisKeyUtil;
-import com.nq.utils.timeutil.TimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
-import java.io.*;
-import java.lang.reflect.Type;
import java.math.BigDecimal;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.URL;
+import java.util.Collections;
import java.util.Date;
-import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -67,7 +57,7 @@
if(stockSetting.getType().equals("0")){
return new BigDecimal(stockSetting.getPrice());
}else{
- String s = doPost(stock.getStockCode());
+ String s = RedisKeyUtil.doPost(stock.getStockCode(), stock.getStockType());
if(null != s){
Map<String, Object> stringObjectMap = jsonToMap(s);
return new BigDecimal(stringObjectMap.get("Last").toString()).multiply(new BigDecimal(stockSetting.getPrice()));
@@ -76,7 +66,7 @@
}
}
- String s = doPost(stock.getStockCode());
+ String s = RedisKeyUtil.doPost(stock.getStockCode(), stock.getStockType());
if(null != s) {
Map<String, Object> stringObjectMap = jsonToMap(s);
return new BigDecimal(stringObjectMap.get("Last").toString());
@@ -87,7 +77,7 @@
@Override
public Map<String, Object> getNewStock(String stockCode) {
Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("stock_code",stockCode));
- String s = doPost(stock.getStockCode());
+ String s = RedisKeyUtil.doPost(stock.getStockCode(), stock.getStockType());
if(null != s){
Map<String, Object> stringObjectMap = jsonToMap(s);
return stringObjectMap;
@@ -101,6 +91,9 @@
ObjectMapper objectMapper = new ObjectMapper();
try {
Object[] array = objectMapper.readValue(json, Object[].class);
+ if (array.length == 0) {
+ return Collections.emptyMap();
+ }
Gson gson = new Gson();
String s = gson.toJson(array[0]);
Map<String, Object> map = objectMapper.readValue(s, Map.class);
@@ -108,45 +101,6 @@
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
- }
-
- public String doPost(String pid) {
- // 从配置中获取 API URL,并拼接 key
- String apiUrl = PropertiesUtil.getProperty("JS_IN_HTTP_URL") + "stock?key=" + PropertiesUtil.getProperty("JS_IN_KEY");
- String result = null;
- try {
- URL url = new URL(apiUrl);
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
-
- // 设置请求方法为 POST
- connection.setRequestMethod("POST");
- // 设置请求头
- connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
- connection.setDoOutput(true); // 允许向连接输出
-
- // 构建 POST 数据
- String postData = "pid=" + pid;
-
- // 发送 POST 请求
- try (OutputStream os = connection.getOutputStream()) {
- byte[] input = postData.getBytes("utf-8");
- os.write(input, 0, input.length);
- }
-
- // 读取响应
- BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
- String inputLine;
- StringBuffer response = new StringBuffer();
-
- while ((inputLine = in.readLine()) != null) {
- response.append(inputLine);
- }
- in.close();
- result = response.toString();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return result;
}
diff --git a/src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java b/src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java
index 00908c5..6c6f172 100644
--- a/src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java
+++ b/src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java
@@ -165,7 +165,8 @@
siteNews.setSourceId(newsId);
siteNews.setSourceName("");
siteNews.setTitle(jsonObject.getString("title"));
- Long showTime = jsonObject.getLong("time");
+ //Long showTime = jsonObject.getLong("time");
+ long showTime = jsonObject.optLong("time", System.currentTimeMillis() / 1000); // 默认值,表示未找到或转换失败
siteNews.setShowTime(new Date(showTime * 1000));
if(jsonObject.has("img")){
convertBase64ToImage(jsonObject.getString("img"),PropertiesUtil.getProperty("ftp.address")+newsId+".jpg");
diff --git a/src/main/java/com/nq/service/impl/StockServiceImpl.java b/src/main/java/com/nq/service/impl/StockServiceImpl.java
index 283f5ae..7c601bd 100644
--- a/src/main/java/com/nq/service/impl/StockServiceImpl.java
+++ b/src/main/java/com/nq/service/impl/StockServiceImpl.java
@@ -1,8 +1,6 @@
package com.nq.service.impl;
-import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
-import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
@@ -10,10 +8,8 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
-import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.nq.common.ServerResponse;
-import com.nq.config.StockPoll;
import com.nq.dao.*;
import com.nq.enums.EStockType;
import com.nq.pojo.*;
@@ -26,28 +22,18 @@
import com.nq.utils.stock.pinyin.GetPyByChinese;
import com.nq.utils.stock.qq.QqStockApi;
import com.nq.utils.stock.sina.StockApi;
-import com.nq.utils.translate.GoogleTranslateUtil;
import com.nq.vo.stock.*;
import com.nq.vo.stock.k.MinDataVO;
import com.nq.vo.stock.k.echarts.EchartsDataVO;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
import java.math.BigDecimal;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.text.SimpleDateFormat;
import java.util.*;
-import java.util.concurrent.CompletableFuture;
+import java.util.function.Function;
+import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import lombok.Data;
-import net.sf.json.JSONArray;
-import net.sf.json.JSONObject;
-import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -63,14 +49,8 @@
@Autowired
StockMapper stockMapper;
- @Resource
- RealTimeMapper realTimeMapper;
-
@Autowired
IStockMarketsDayService iStockMarketsDayService;
-
- @Autowired
- StockPoll stockPoll;
@Resource
StockFuturesMapper stockFuturesMapper;
@@ -82,20 +62,16 @@
IUserService iUserService;
@Autowired
- IStockOptionService iStockOptionService;
- @Autowired
ISiteSettingService iSiteSettingService;
-
-
- @Autowired
- InStockMapper inStockMapper;
@Resource
StockDzMapper stockDzMapper;
-
@Autowired
IPriceServices iPriceServices;
+
+ @Autowired
+ SiteNewsMapper siteNewsMapper;
public ServerResponse getMarket() {
@@ -170,17 +146,26 @@
@Override
public ServerResponse getStockByType(int pageNum, int pageSize, String orderBy, String keyWords, String stockType, HttpServletRequest request) {
- List<Stock> stockList = new ArrayList<>();
PageHelper.startPage(pageNum, pageSize);
- stockList.addAll(stockMapper.findStockByType(orderBy,stockType,keyWords));
+ List<Stock> stockList = stockMapper.findStockByType(orderBy, stockType, keyWords);
+ // 获取分页信息
+ PageInfo<Stock> pageInfo = new PageInfo<>(stockList);
+
List<StockListVO> stockListVOS = Lists.newArrayList();
- if (stockList.size() > 0){
+ if (stockList.size() > 0) {
stockListVOS.addAll(Objects.requireNonNull(StockApi.getStockReailTimes(stockList)));
}
- RPageInfo pageInfo = new RPageInfo();
- pageInfo.setList(stockListVOS);
- pageInfo.setStockType(stockType);
- return ServerResponse.createBySuccess(pageInfo);
+
+ RPageInfo resultPageInfo = new RPageInfo();
+ resultPageInfo.setList(stockListVOS);
+ resultPageInfo.setStockType(stockType);
+ // 设置分页信息
+ resultPageInfo.setTotal(pageInfo.getTotal());
+ resultPageInfo.setPageNum(pageInfo.getPageNum());
+ resultPageInfo.setPageSize(pageInfo.getPageSize());
+ resultPageInfo.setPages(pageInfo.getPages());
+ resultPageInfo.setHasNextPage(pageInfo.isHasNextPage());
+ return ServerResponse.createBySuccess(resultPageInfo);
}
@Override
@@ -193,7 +178,7 @@
if (StringUtils.isBlank(code))
return ServerResponse.createByErrorMsg("");
Stock stock = stockMapper.findStockByCode(code);
- DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stock);
+ DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stock.getStockType(), stock.getStockCode());
Integer depositAmt = 0;
String introduction = null;
StockVO stockVO = StockApi.assembleInStockVO(stock);
@@ -223,7 +208,7 @@
if (StringUtils.isBlank(code))
return null;
Stock stock = stockMapper.findStockByCode(code);
- DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stock);
+ DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stock.getStockType(), stock.getStockCode());
Integer depositAmt = 0;
String introduction = null;
StockVO stockVO = StockApi.assembleInStockVO(stock);
@@ -711,4 +696,115 @@
}
return ServerResponse.createBySuccess(pool);
}
+
+ @Override
+ public ServerResponse getIndicesIndexListAndNews(Integer pageSize) {
+ try {
+ //新闻列表
+ List<SiteNews> newsList = this.siteNewsMapper.getTopNewsList(pageSize);
+
+ String usCodeList = PropertiesUtil.getProperty("us_home_indices_code");
+ String mxCodeList = PropertiesUtil.getProperty("mx_home_indices_code");
+ List<String> usStockCodeList = Arrays.asList(usCodeList.split(","));
+ List<String> mxStockCodeList = Arrays.asList(mxCodeList.split(","));
+ List<DataStockBean> usDataStockBeans = Lists.newArrayList();
+ List<DataStockBean> mxDataStockBeans = Lists.newArrayList();
+ for (int i = 0; i < usStockCodeList.size(); i++) {
+ String stockCode = usStockCodeList.get(i);
+ String stockType = EStockType.US.getCode();
+ DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stockType, stockCode);
+ // 获取K线数据
+ Object kData = RedisKeyUtil.getCaCheStockKData(stockType, stockCode);
+ if (kData == null) {
+ //重新获取并缓存redis
+ kData = getKData(stockCode, "D", stockType);
+ RedisKeyUtil.setCaCheStockKData(stockType, stockCode, kData);
+ }
+ Gson gson = new Gson();
+ List<kData> dataList = gson.fromJson(kData.toString(), new TypeToken<List<kData>>(){}.getType());
+ cacheBaseStock.setKData(dataList);
+ usDataStockBeans.add(cacheBaseStock);
+ }
+ for (int i = 0; i < mxStockCodeList.size(); i++) {
+ String stockCode = mxStockCodeList.get(i);
+ String stockType = EStockType.MX.getCode();
+ DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stockType, stockCode);
+ // 获取K线数据
+ Object kData = RedisKeyUtil.getCaCheStockKData(stockType, stockCode);
+ if (kData == null) {
+ //重新获取并缓存redis
+ kData = getKData(stockCode, "D", stockType);
+ RedisKeyUtil.setCaCheStockKData(stockType, stockCode, kData);
+ }
+ Gson gson = new Gson();
+ List<kData> dataList = gson.fromJson(kData.toString(), new TypeToken<List<kData>>(){}.getType());
+ cacheBaseStock.setKData(dataList);
+ mxDataStockBeans.add(cacheBaseStock);
+ }
+ Map<String, Object> resultMap = new HashMap<>();
+ resultMap.put("newsList", newsList); //新闻列表
+ resultMap.put("usDataStockBeans", usDataStockBeans);//美国指数
+ resultMap.put("mxDataStockBeans", mxDataStockBeans);//墨西哥指数
+ return ServerResponse.createBySuccess(resultMap);
+ } catch (Exception e){
+ e.printStackTrace();
+ }
+ return ServerResponse.createByError();
+ }
+
+ @Override
+ public ServerResponse getIndicesList(String stockType) {
+ try {
+ String codeList;
+ if (stockType.equals(EStockType.US.getCode())) {
+ codeList = PropertiesUtil.getProperty("us_home_indices_code");
+ } else {
+ codeList = PropertiesUtil.getProperty("mx_home_indices_code");
+ }
+ List<String> stockCodeList = Arrays.asList(codeList.split(","));
+
+ Map<Integer, Object> resultMap = new HashMap<>();
+ for (int i = 0; i < stockCodeList.size(); i++) {
+ String stockCode = stockCodeList.get(i);
+ DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stockType, stockCode);
+ Map<String, Object> stockInfo = new HashMap<>();
+ stockInfo.put("pid", cacheBaseStock.getId());
+ stockInfo.put("name", cacheBaseStock.getName());
+ stockInfo.put("stockType", stockType);
+ resultMap.put(i+1, stockInfo);
+ }
+ return ServerResponse.createBySuccess(resultMap);
+ } catch (Exception e){
+ e.printStackTrace();
+ }
+ return ServerResponse.createByError();
+ }
+
+ @Override
+ public ServerResponse getIndicesAndKData(String pid, String stockType) {
+ try {
+ Map<String, Object> resultMap = new HashMap<>();
+ DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stockType, pid);
+ if (cacheBaseStock != null) {
+ resultMap.put("last", cacheBaseStock.getLast());
+ resultMap.put("chg", cacheBaseStock.getChg());
+ resultMap.put("chgPct", cacheBaseStock.getChgPct());
+ resultMap.put("kData", cacheBaseStock.getChg());
+ // 获取K线数据
+ Object kData = RedisKeyUtil.getCaCheStockKData(stockType, pid);
+ if (kData == null) {
+ //重新获取并缓存redis
+ kData = getKData(pid, "D", stockType);
+ RedisKeyUtil.setCaCheStockKData(stockType, pid, kData);
+ }
+ Gson gson = new Gson();
+ List<kData> dataList = gson.fromJson(kData.toString(), new TypeToken<List<kData>>(){}.getType());
+ resultMap.put("kData", dataList);
+ return ServerResponse.createBySuccess(resultMap);
+ }
+ } catch (Exception e){
+ e.printStackTrace();
+ }
+ return ServerResponse.createByError();
+ }
}
diff --git a/src/main/java/com/nq/utils/redis/RedisKeyConstant.java b/src/main/java/com/nq/utils/redis/RedisKeyConstant.java
index 4fe11e6..ed9cb04 100644
--- a/src/main/java/com/nq/utils/redis/RedisKeyConstant.java
+++ b/src/main/java/com/nq/utils/redis/RedisKeyConstant.java
@@ -25,5 +25,8 @@
* */
public static final String RK_COMPANY_INFO = "rk_company_info";
-
+ /**
+ * 股票K线图数据key
+ * */
+ public static final String RK_STOCK_KDATA = "rk_stock_kdata";
}
diff --git a/src/main/java/com/nq/utils/redis/RedisKeyUtil.java b/src/main/java/com/nq/utils/redis/RedisKeyUtil.java
index 7e53315..fdc5ad3 100644
--- a/src/main/java/com/nq/utils/redis/RedisKeyUtil.java
+++ b/src/main/java/com/nq/utils/redis/RedisKeyUtil.java
@@ -37,8 +37,8 @@
/**
* 获取股票数据
* */
- public static DataStockBean getCacheBaseStock(Stock stock){
- String cacheBaseData = RedisShardedPoolUtils.get(RedisKeyConstant.RK_BASE_STOCK+":"+stock.getStockType()+":"+stock.getStockCode());
+ public static DataStockBean getCacheBaseStock(String stockType, String stockCode){
+ String cacheBaseData = RedisShardedPoolUtils.get(RedisKeyConstant.RK_BASE_STOCK+":"+stockType+":"+stockCode);
return new Gson().fromJson(cacheBaseData, DataStockBean.class);
}
@@ -60,7 +60,7 @@
stockRealTimeBean = new Gson().fromJson(cacheBaseData, StockRealTimeBean.class);
}
if(stockRealTimeBean == null){
- String s = doPost(stock.getStockCode());
+ String s = doPost(stock.getStockCode(), stock.getStockType());
Map<String, Object> stringObjectMap = jsonToMap(s);
stockRealTimeBean = new StockRealTimeBean();
stockRealTimeBean.setPcp(stringObjectMap.get("ChgPct").toString());
@@ -89,9 +89,11 @@
}
}
- public static String doPost(String pid) {
+ public static String doPost(String pid, String stockType) {
+ EStockType eStockType = EStockType.getEStockTypeByCode(stockType);
// 从配置中获取 API URL,并拼接 key
- String apiUrl = PropertiesUtil.getProperty("JS_IN_HTTP_URL") + "stock?key=" + PropertiesUtil.getProperty("JS_IN_KEY");
+ //String apiUrl = PropertiesUtil.getProperty("JS_IN_HTTP_URL") + "stock?key=" + PropertiesUtil.getProperty("JS_IN_KEY");
+ String apiUrl = eStockType.getStockUrl() + "stock?key=" + eStockType.getStockKey();
String result = null;
try {
URL url = new URL(apiUrl);
@@ -143,6 +145,15 @@
return JSONObject.parseObject(companiesInfo);
}
+ /**
+ * 缓存K线数据源到redis
+ * */
+ public static void setCaCheStockKData(String stockType, String stockCode, Object kData){
+ RedisShardedPoolUtils.set(RedisKeyConstant.RK_STOCK_KDATA+":"+stockType+":"+stockCode, kData.toString());
+ }
+ public static Object getCaCheStockKData(String stockType, String stockCode){
+ return RedisShardedPoolUtils.get(RedisKeyConstant.RK_STOCK_KDATA+":"+stockType+":"+stockCode);
+ }
}
diff --git a/src/main/java/com/nq/utils/redis/RedisShardedPoolUtils.java b/src/main/java/com/nq/utils/redis/RedisShardedPoolUtils.java
index c916856..5971891 100644
--- a/src/main/java/com/nq/utils/redis/RedisShardedPoolUtils.java
+++ b/src/main/java/com/nq/utils/redis/RedisShardedPoolUtils.java
@@ -142,11 +142,11 @@
try {
+ if (key == null) {
+ jedis = RedisShardedPool.getJedis();
- jedis = RedisShardedPool.getJedis();
-
- result = jedis.del(key);
-
+ result = jedis.del(key);
+ }
} catch (Exception e) {
log.error("redis del key: {} error ", key, e);
diff --git a/src/main/java/com/nq/utils/task/stock/StockTask.java b/src/main/java/com/nq/utils/task/stock/StockTask.java
index f7520a6..ec13638 100644
--- a/src/main/java/com/nq/utils/task/stock/StockTask.java
+++ b/src/main/java/com/nq/utils/task/stock/StockTask.java
@@ -1,13 +1,8 @@
package com.nq.utils.task.stock;
import com.alibaba.fastjson2.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.gson.Gson;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import com.nq.Repository.StockRepository;
import com.nq.dao.StockMapper;
@@ -17,24 +12,21 @@
import com.nq.service.IMandatoryLiquidationService;
import com.nq.service.IStockService;
import com.nq.service.IUserPositionService;
+import com.nq.service.impl.StockServiceImpl;
import com.nq.utils.PropertiesUtil;
import com.nq.utils.http.HttpClientRequest;
import com.nq.utils.http.HttpRequest;
import com.nq.utils.redis.RedisKeyUtil;
-import net.sf.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -44,85 +36,79 @@
@Component
public class StockTask {
@Autowired
- IStockService stockService;
- @Autowired
StockMapper stockMapper;
-
@Autowired
- IUserPositionService userPositionService;
-
- @Autowired
- UserPositionMapper userPositionMapper;
+ IStockService istockService;
@Autowired
StockRepository stockRepository;
private final Lock stockConstraintLock = new ReentrantLock();
-
@Autowired
IMandatoryLiquidationService mandatoryLiquidationService;
-
private static final Logger log = LoggerFactory.getLogger(StockTask.class);
-
-
private final AtomicBoolean syncINStockData = new AtomicBoolean(false);
private final Lock syncINStockDataLock = new ReentrantLock();
+
+ @Autowired
+ private ThreadPoolTaskExecutor taskExecutor;
+ @Autowired
+ private StockServiceImpl iStockService;
+
+ /**
+ * test
+ */
+ //@Scheduled(cron = "0 0/1 * * * ?")
+ @Scheduled(cron = "*/5 * * * * *")
+ public void test() {
+ //iStockService.getStockByType(1, 20, "desc","st" , "US", null);
+ //istockService.getIndicesList("US");
+ //istockService.getIndicesAndKData("15882", "US");
+ }
/**
* 同步系统所需要的股票
*/
@Scheduled(cron = "0 0/1 * * * ?")
public void syncINStockData() {
+
if (syncINStockData.get()) { // 判断任务是否在处理中
return;
}
if (syncINStockDataLock.tryLock()) {
- ExecutorService executor = Executors.newFixedThreadPool(4);
- Future<?> future1 = null;
- Future<?> future2 = null;
- Future<?> future3 = null;
- Future<?> future4 = null;
try {
- syncINStockData.set(true); // 设置处理中标识为true
+ syncINStockData.set(true);
- // 同步股票数据
- future1 = executor.submit(() -> loadAllStock(EStockType.US));
- future2 = executor.submit(() -> loadAllStock(EStockType.MX));
- // 同步指数数据
- future3 = executor.submit(() -> syncIndices(EStockType.US));
- future4 = executor.submit(() -> syncIndices(EStockType.MX));
+ // 使用CompletableFuture并行执行任务
+ CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> loadAllStock(EStockType.US), taskExecutor);
+ CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> loadAllStock(EStockType.MX), taskExecutor);
+ CompletableFuture<Void> future3 = CompletableFuture.runAsync(() -> syncIndices(EStockType.US), taskExecutor);
+ CompletableFuture<Void> future4 = CompletableFuture.runAsync(() -> syncIndices(EStockType.MX), taskExecutor);
- // 等待任务都完成
- future1.get();
- future2.get();
- future3.get();
- future4.get();
+ // 等待所有任务完成
+ CompletableFuture.allOf(future1, future2, future3, future4).join();
} catch (Exception e) {
- Thread.currentThread().interrupt();
log.error("同步股票数据出错", e);
} finally {
- // 关闭线程池
- if (executor != null) {
- executor.shutdown();
- }
syncINStockDataLock.unlock();
- syncINStockData.set(false); // 设置处理中标识为false
+ syncINStockData.set(false);
}
}
}
+ /**
+ * 加载所有指数数据
+ */
private void syncIndices(EStockType eStockType) {
List<DataStockBean> list = new ArrayList<>();
int totleStock = 1;
try {
while (totleStock > list.size()) {
try {
- //String result = HttpClientRequest.doGet(eStockType.stockUrl + "indices?key=" + eStockType.getStockKey() + "&country_id=" + eStockType.getContryId());
- //ReponseBase reponseBase = new Gson().fromJson(result, ReponseBase.class);
String result = HttpRequest.doGrabGet(eStockType.stockUrl + "indices?key=" + eStockType.getStockKey() + "&country_id=" + eStockType.getContryId());
// 把JSON数据解析为List<DataStockBean>
Type listType = new TypeToken<List<DataStockBean>>(){}.getType();
@@ -169,12 +155,44 @@
stockMapper.updateById(stock);
}*/
RedisKeyUtil.setCaCheKeyBaseStock(eStockType, o);
+
+ /*StockRealTimeBean stockRealTimeBean = new StockRealTimeBean();
+ stockRealTimeBean.setPid(o.getId());
+ stockRealTimeBean.setLast(o.getLast());
+ stockRealTimeBean.setHigh(o.getHigh());
+ stockRealTimeBean.setLow(o.getLow());
+ stockRealTimeBean.setPc(o.getChg());
+ stockRealTimeBean.setPcp(o.getChgPct()+ "%");
+ stockRealTimeBean.setTime(o.getTime());
+ RedisKeyUtil.setCacheRealTimeStock(eStockType, stockRealTimeBean);*/
}
stockRepository.saveAll(updateStockList);
+ cacheKData(eStockType.getCode(), list);
log.info("同步指数 数据 成功 {} 总共同步数据 {}", eStockType.getCode(), list.size());
} catch (Exception e) {
+ e.printStackTrace();
log.error("同步指数列表出现异常: {}", e.getMessage());
}
+ }
+
+ /**
+ * 同步指数股票后缓存k线图
+ */
+ public void cacheKData(String stockType, List<DataStockBean> list) {
+ String usCodeList = PropertiesUtil.getProperty("us_home_indices_code");
+ String mxCodeList = PropertiesUtil.getProperty("mx_home_indices_code");
+ for (DataStockBean dataStockBean : list) {
+ //缓存首页指数k线图
+ if (usCodeList.contains(dataStockBean.getId()) || mxCodeList.contains(dataStockBean.getId())) {
+ // 获取K线数据
+ Object kData = istockService.getKData(dataStockBean.getId(), "D", stockType);
+ if (kData != null) {
+ //缓存redis
+ RedisKeyUtil.setCaCheStockKData(stockType, dataStockBean.getId(), kData);
+ }
+ }
+ }
+ log.info("同步指数k线图 数据 成功 {} 总共同步数据 {}", stockType, list.size());
}
/**
@@ -218,7 +236,7 @@
try {
while (totleStock > list.size()) {
try {
- String result = HttpClientRequest.doGet(eStockType.stockUrl + "list?country_id=" + eStockType.getContryId() + "&size=1000&page=" + page + "&key=" + eStockType.stockKey);
+ String result = HttpClientRequest.doGet(eStockType.stockUrl + "list?country_id=" + eStockType.getContryId() + "&size=100000&page=" + page + "&key=" + eStockType.stockKey);
ReponseBase reponseBase = new Gson().fromJson(result, ReponseBase.class);
list.addAll(reponseBase.getData());
page++;
@@ -233,9 +251,7 @@
}
List<String> stockCodeList = list.stream().map(DataStockBean::getId).collect(Collectors.toList());
List<Stock> stockList = stockMapper.selectList(new QueryWrapper<Stock>().in("stock_code", stockCodeList));
- int i = 1;
List<Stock> updateStockList = new ArrayList<>();
- System.out.println(new Date());
for (DataStockBean o : list) {
//Stock stock = stockMapper.findStockByCode(o.getId());
Stock stock = stockList.stream()
@@ -276,11 +292,8 @@
}
updateStockList.add(stock);
RedisKeyUtil.setCaCheKeyBaseStock(eStockType, o);
- System.out.println(i);
- i++;
}
stockRepository.saveAll(updateStockList);
- System.out.println(new Date());
log.info("同步股票 数据 成功 {} 总共同步数据 {}", eStockType.getCode(), list.size());
} catch (
Exception e) {
diff --git a/src/main/java/com/nq/ws/MXWebsocketRunClient.java b/src/main/java/com/nq/ws/MXWebsocketRunClient.java
index 0e29d5f..c7f540c 100644
--- a/src/main/java/com/nq/ws/MXWebsocketRunClient.java
+++ b/src/main/java/com/nq/ws/MXWebsocketRunClient.java
@@ -51,7 +51,9 @@
heartbeatTimer.schedule(new TimerTask() {
@Override
public void run() {
- send(("key:"+ eStockType.getStockKey()+":"+eStockType.getContryId()).getBytes());
+ if (isOpen()) {
+ send(("key:"+ eStockType.getStockKey()+":"+eStockType.getContryId()).getBytes());
+ }
}
}, 0, 3000); // 每3秒发送一次心跳消息
}
diff --git a/src/main/java/com/nq/ws/WebsocketRunClient.java b/src/main/java/com/nq/ws/WebsocketRunClient.java
index 7461bc0..5d9e127 100644
--- a/src/main/java/com/nq/ws/WebsocketRunClient.java
+++ b/src/main/java/com/nq/ws/WebsocketRunClient.java
@@ -52,7 +52,10 @@
heartbeatTimer.schedule(new TimerTask() {
@Override
public void run() {
- send(("key:"+ eStockType.getStockKey()+":"+eStockType.getContryId()).getBytes());
+ if (isOpen()) {
+ send(("key:"+ eStockType.getStockKey()+":"+eStockType.getContryId()).getBytes());
+ }
+
}
}, 0, 3000); // 每3秒发送一次心跳消息
}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index eac7b5b..c30607d 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -92,9 +92,9 @@
SZHB_WS_URL = ws://api-in-ws.js-stock.top
SZHB_KEY = GBZAcUPLKZzDMDjvV9Ea
-
-
-
+#默认首页显示指数code
+us_home_indices_code=15882,15881,16571
+mx_home_indices_code=535610327,535610374,535610333
#?? ?? - ????
admin.auth.email.subject=???? - ??????
diff --git a/src/main/resources/mapper/StockMapper.xml b/src/main/resources/mapper/StockMapper.xml
index 6f3ddab..a19f47f 100644
--- a/src/main/resources/mapper/StockMapper.xml
+++ b/src/main/resources/mapper/StockMapper.xml
@@ -319,8 +319,10 @@
<include refid="Base_Column_List"/>
FROM stock
- where stock_type = #{stockType}
- and stock_spell not like '%.st%'
+ where stock_spell not like '%.st%'
+ <if test="stockType != null and stockType != '' ">
+ and stock_type = #{stockType}
+ </if>
<if test="keyWords != null and keyWords != '' ">
and (stock_spell like concat('%',#{keyWords},'%') or stock_name like concat('%',#{keyWords},'%') )
</if>
--
Gitblit v1.9.3