| pom.xml | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/controller/StockApiController.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/enums/EStockType.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/pojo/reponse/kResponse.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/service/IStockService.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/service/impl/StockServiceImpl.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/service/impl/UserPositionServiceImpl.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/utils/redis/RedisKeyConstant.java | ●●●●● patch | view | raw | blame | history | |
| src/main/java/com/nq/utils/task/stock/StockTask.java | ●●●●● patch | view | raw | blame | history | |
| src/main/resources/application.properties | ●●●●● patch | view | raw | blame | history |
pom.xml
@@ -25,7 +25,11 @@ <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.12.5</version> </dependency> <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> src/main/java/com/nq/controller/StockApiController.java
@@ -1,5 +1,6 @@ package com.nq.controller; import com.fasterxml.jackson.core.JsonProcessingException; import com.nq.common.ServerResponse; import com.nq.pojo.SiteSetting; import com.nq.service.IStockService; @@ -60,20 +61,22 @@ @ResponseBody public ServerResponse getGoldCrudeOil(HttpServletRequest request) { String gold = RedisShardedPoolUtils.get(RedisKeyConstant.gold); String crudeOil = RedisShardedPoolUtils.get(RedisKeyConstant.crude_oil); String gold = RedisShardedPoolUtils.get(RedisKeyConstant.XAUUSD); String crudeOil = RedisShardedPoolUtils.get(RedisKeyConstant.USOIL); HashMap<String,HashMap> hashMap = new HashMap<>(); HashMap<String,String> goldMap = new HashMap<>(); String goldName = new GoogleTranslateUtil().translate("GOLD", request.getHeader("lang")); goldMap.put(goldName,gold); hashMap.put("GOLD",goldMap); goldMap.put("XAUUSD",gold); goldMap.put("hcrate",RedisShardedPoolUtils.get("XAUUSD"+"_H")); goldMap.put("hcrateP",RedisShardedPoolUtils.get("XAUUSD"+"_H")+"%"); hashMap.put("XAUUSD",goldMap); HashMap<String,String> crudOilMap = new HashMap<>(); String crudeOilName = new GoogleTranslateUtil().translate("CRUDE OIL", request.getHeader("lang")); crudOilMap.put(crudeOilName,crudeOil); hashMap.put("CRUDE OIL",crudOilMap); crudOilMap.put("USOIL",crudeOil); crudOilMap.put("hcrate",RedisShardedPoolUtils.get("USOIL"+"_H")); crudOilMap.put("hcrateP",RedisShardedPoolUtils.get("USOIL"+"_H")+"%"); hashMap.put("USOIL",crudOilMap); return ServerResponse.createBySuccess(hashMap); } @@ -90,7 +93,7 @@ //通过股票代码查询股票信息 @RequestMapping({"getSingleStock.do"}) @ResponseBody public ServerResponse getSingleStock(@RequestParam("code") String code, HttpServletRequest request) { public ServerResponse getSingleStock(@RequestParam("code") String code, HttpServletRequest request) throws JsonProcessingException { return this.iStockService.getSingleStock(code, request); } @@ -101,9 +104,15 @@ public Object getKData( @RequestParam("pid") String pid, @RequestParam("interval") String interval, @RequestParam("stockType") String stockType @RequestParam("stockType") String stockType, HttpServletRequest request ) { return this.iStockService.getKData(pid,interval,stockType); try { return this.iStockService.getKData(pid,interval,stockType); }catch (Exception e){ log.error("获取k线失败",e.getMessage()); } return ServerResponse.createByErrorMsg("获取k线失败",request); } src/main/java/com/nq/enums/EStockType.java
@@ -16,7 +16,8 @@ MAS("MAS","马来西亚股票","42",PropertiesUtil.getProperty("MAS_HTTP_API"),PropertiesUtil.getProperty("MAS_KEY"),"MYR","RM"), IN("IN","印度股票","14", PropertiesUtil.getProperty("JS_IN_HTTP_URL"),PropertiesUtil.getProperty("JS_IN_KEY"),"INR","₹"), ST("ST","沙特股票","52", PropertiesUtil.getProperty("ST_HTTP_API"),PropertiesUtil.getProperty("ST_KEY"),"SAR","﷼"); ST("ST","沙特股票","52", PropertiesUtil.getProperty("ST_HTTP_API"),PropertiesUtil.getProperty("ST_KEY"),"SAR","﷼"), USDT("USDT","USDT","52", PropertiesUtil.getProperty("ST_HTTP_API"),PropertiesUtil.getProperty("ST_KEY"),"USDT","$"); // TH("TH","泰国股票","41",PropertiesUtil.getProperty("TH_HTTP_API"),PropertiesUtil.getProperty("TH_KEY")), // HG("HG","韩国股票","11",PropertiesUtil.getProperty("HG_HTTP_API"),PropertiesUtil.getProperty("HG_KEY")), // SZHB("SZHB","数字货币","41",PropertiesUtil.getProperty("SZHB_HTTP_API"),PropertiesUtil.getProperty("SZHB_KEY")); @@ -54,7 +55,7 @@ }else if(EStockType.ST.getCode().equals(code)){ return ST; }else{ return MAS; return USDT; } } src/main/java/com/nq/pojo/reponse/kResponse.java
New file @@ -0,0 +1,37 @@ package com.nq.pojo.reponse; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.annotations.SerializedName; import lombok.Data; import java.util.List; /** * @program: dabaogp * @description: * @create: 2025-04-25 17:29 **/ @Data public class kResponse { private int ret; private String msg; private String trace; private Data data; @lombok.Data public static class Data { @SerializedName("kline_list") private List<KlineData> klineList; } @lombok.Data public static class KlineData { private long timestamp; private String open_price; private String close_price; private String high_price; private String low_price; private String volume; private String turnover; } } src/main/java/com/nq/service/IStockService.java
@@ -1,5 +1,6 @@ package com.nq.service; import com.fasterxml.jackson.core.JsonProcessingException; import com.github.pagehelper.PageInfo; import com.nq.common.ServerResponse; import com.nq.pojo.Stock; @@ -46,7 +47,7 @@ // void bj1(); ServerResponse getDateline(HttpServletResponse paramHttpServletResponse, String paramString); ServerResponse getSingleStock(String paramString,HttpServletRequest request); ServerResponse getSingleStock(String paramString,HttpServletRequest request) throws JsonProcessingException; ServerResponse getMinK(String paramString, Integer paramInteger1, Integer paramInteger2, Integer paramInteger3); @@ -101,7 +102,7 @@ ServerResponse getStockDayK(String code); Object getKData(String pid,String interval,String stockType); Object getKData(String pid,String interval,String stockType) throws JsonProcessingException; ServerResponse getOptionStock(HttpServletRequest request); src/main/java/com/nq/service/impl/StockServiceImpl.java
@@ -5,6 +5,8 @@ import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.google.common.collect.Lists; @@ -18,6 +20,7 @@ import com.nq.enums.EStockType; import com.nq.pojo.*; import com.nq.pojo.reponse.RPageInfo; import com.nq.pojo.reponse.kResponse; import com.nq.service.*; import com.nq.utils.http.HttpClientRequest; import com.nq.utils.PropertiesUtil; @@ -63,6 +66,7 @@ import org.springframework.web.client.RestTemplate; import static com.nq.utils.timeutil.DateTimeUtil.getWeekDay; import static net.sf.jsqlparser.util.validation.metadata.NamedObject.user; @Service("iStockService") public class StockServiceImpl implements IStockService { @@ -208,21 +212,24 @@ } public ServerResponse getSingleStock(String code, HttpServletRequest request) { public ServerResponse getSingleStock(String code, HttpServletRequest request) throws JsonProcessingException { if(code.equals("GOLD")){ String price = RedisShardedPoolUtils.get(RedisKeyConstant.gold); if(code.equals("XAUUSD")){ String price = RedisShardedPoolUtils.get(RedisKeyConstant.XAUUSD); getKData(null, "1", code);//只是为了得到下面redis的值 StockVO stockVO = new StockVO(); stockVO.setNowPrice(price); stockVO.setName(code); stockVO.setHcrate(RedisShardedPoolUtils.get(code+"_H")); Map map = Maps.newHashMap(); map.put("stock", stockVO); return ServerResponse.createBySuccess(map); }else if(code.equals("CRUDE OIL")){ String price = RedisShardedPoolUtils.get(RedisKeyConstant.crude_oil); }else if(code.equals("USOIL")){ String price = RedisShardedPoolUtils.get(RedisKeyConstant.USOIL); StockVO stockVO = new StockVO(); stockVO.setNowPrice(price); stockVO.setName(code); stockVO.setHcrate(RedisShardedPoolUtils.get(code+"_H")); Map map = Maps.newHashMap(); map.put("stock", stockVO); return ServerResponse.createBySuccess(map); @@ -470,22 +477,15 @@ } //黄金 private static final String gold_API_URL = "http://139.196.211.109/ldMetal_k.action?username=Qq112233&password=3ce25a66d5b3a8cd661024fea6c79388&id=AUUSDO&num=-100&period="; //原油 private static final String crude_oil_API_URL = "http://47.112.169.122/fOption_k.action?username=Qq112233&password=3ce25a66d5b3a8cd661024fea6c79388&id=@CL0W&num=-100&period="; /*股票日线-K线*/ @Override public Object getKData(String pid, String interval, String stockType) { if(stockType.equals("GOLD")){ public Object getKData(String pid, String interval, String stockType) throws JsonProcessingException { if(stockType.equals("XAUUSD")){ // 使用RestTemplate发起HTTP请求 String response = RedisShardedPoolUtils.get("k_gold_"+interval.toLowerCase()); return parseData(interval,response, stockType); }else if(stockType.equals("CRUDE OIL")){ }else if(stockType.equals("USOIL")){ // 使用RestTemplate发起HTTP请求 RestTemplate restTemplate = new RestTemplate(); String response = RedisShardedPoolUtils.get("k_crude_oil_"+interval.toLowerCase()); return parseData(interval,response, stockType); }else{ @@ -508,82 +508,34 @@ } } public List<kData> parseData(String interval,String data,String key) { public List<kData> parseData(String interval,String data,String key) throws JsonProcessingException { String price = null; if(key.equals("GOLD")){ price = RedisShardedPoolUtils.get(RedisKeyConstant.gold); }else if(key.equals("CRUDE OIL")){ price = RedisShardedPoolUtils.get(RedisKeyConstant.crude_oil); if(key.equals("XAUUSD")){ price = RedisShardedPoolUtils.get(RedisKeyConstant.XAUUSD); }else if(key.equals("USOIL")){ price = RedisShardedPoolUtils.get(RedisKeyConstant.USOIL); } List<kData> kDataList = new ArrayList<>(); // 使用 Gson 解析 JSON 字符串 Gson gson = new Gson(); kResponse kResponse = gson.fromJson(data, kResponse.class); // 将数据按行分割 String[] lines = data.split("\n"); // 跳过第一行(列名) for (int i = 1; i < lines.length; i++) { String line = lines[i].trim(); // 确保行不为空 if (!line.isEmpty()) { String[] fields = line.split(","); // 确保每行有至少7个字段:日期、开盘价、最高价、最低价、收盘价、成交量、持仓量 if ((key.equals("CRUDE OIL") && fields.length == 7) || (key.equals("GOLD") && fields.length == 5)) { kData kData = new kData(); kData.setT(convDate(fields[0],interval)); kData.setC(fields[4]); kData.setO(fields[1]); kData.setH(fields[2]); kData.setL(fields[3]); if(key.equals("CRUDE OIL")){ kData.setV(fields[5]); kData.setVo(fields[6]); }else{ kData.setV("0"); kData.setVo("0"); } // 将每一条 KData 对象添加到列表中 kDataList.add(kData); } } // 打印 kline_list 的内容 for (kResponse.KlineData item : kResponse.getData().getKlineList()) { kData kData = new kData(); kData.setT(item.getTimestamp()); kData.setC(item.getClose_price()); kData.setO(item.getOpen_price()); kData.setH(item.getHigh_price()); kData.setL(item.getLow_price()); kData.setV(item.getVolume()); kData.setVo(item.getTurnover()); kDataList.add(kData); } kDataList.get(kDataList.size() - 1).setC(price); return kDataList; } // 常量,定义日期格式 private static final String DATE_PATTERN = "yyyyMMdd"; private static final String DATE_TIME_PATTERN = "yyyyMMdd HH:mm"; public long convDate(String dateStr, String interval) { // 输入校验,确保 dateStr 和 interval 不为 null 或空 if (dateStr == null || dateStr.trim().isEmpty() || interval == null || interval.trim().isEmpty()) { throw new IllegalArgumentException("日期字符串或时间间隔不能为空。"); } // 根据 interval 的值,选择日期格式 String pattern = (interval.equalsIgnoreCase("D") || interval.equalsIgnoreCase("W") || interval.equalsIgnoreCase("M")) ? DATE_PATTERN : DATE_TIME_PATTERN; // 创建 DateTimeFormatter,使用合适的格式 DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); try { // 根据是否包含时间部分,选择 LocalDate 或 LocalDateTime 进行解析 if (pattern.equals(DATE_PATTERN)) { LocalDate localDate = LocalDate.parse(dateStr, formatter); Instant timestamp = localDate.atStartOfDay(ZoneOffset.UTC).toInstant(); return timestamp.getEpochSecond(); } else { LocalDateTime localDateTime = LocalDateTime.parse(dateStr, formatter); Instant timestamp = localDateTime.toInstant(ZoneOffset.UTC); return timestamp.getEpochSecond(); } } catch (Exception e) { throw new IllegalArgumentException("无效的日期格式: " + dateStr, e); } } @Override public ServerResponse getOptionStock(HttpServletRequest request) { src/main/java/com/nq/service/impl/UserPositionServiceImpl.java
@@ -395,7 +395,7 @@ BigDecimal nowPrice = BigDecimal.ZERO; String stockType; if(userPosition.getStockSpell().equals("GOLD") || userPosition.getStockSpell().equals("CRUDE_OIL")){ if(userPosition.getStockSpell().equals("XAUUSD") || userPosition.getStockSpell().equals("USOIL")){ nowPrice = new BigDecimal(RedisShardedPoolUtils.get(userPosition.getStockSpell())); stockType = "USDT"; }else{ @@ -451,7 +451,7 @@ } BigDecimal nowPrice = BigDecimal.ZERO; String stockType = null; if(userPosition.getStockSpell().equals("GOLD") || userPosition.getStockSpell().equals("CRUDE_OIL")){ if(userPosition.getStockSpell().equals("XAUUSD") || userPosition.getStockSpell().equals("USOIL")){ nowPrice = new BigDecimal(RedisShardedPoolUtils.get(userPosition.getStockSpell())); stockType = "USDT"; }else{ @@ -745,7 +745,7 @@ if (userPositions.size() > 0) { for (UserPosition position : userPositions) { BigDecimal nowPrice = BigDecimal.ZERO; if(position.getStockSpell().equals("GOLD") || position.getStockSpell().equals("CRUDE_OIL")){ if(position.getStockSpell().equals("XAUUSD") || position.getStockSpell().equals("USOIL")){ nowPrice = new BigDecimal(RedisShardedPoolUtils.get(position.getStockSpell())); }else{ if(state == 0){ @@ -1323,7 +1323,7 @@ adminPositionVO.setStockPlate(position.getStockPlate()); BigDecimal nowPrice = BigDecimal.ZERO; if(position.getStockSpell().equals("GOLD") || position.getStockSpell().equals("CRUDE_OIL")){ if(position.getStockSpell().equals("XAUUSD") || position.getStockSpell().equals("USOIL")){ nowPrice = new BigDecimal(RedisShardedPoolUtils.get(position.getStockSpell())); }else{ nowPrice = priceServices.getNowPrice(position.getStockCode()); src/main/java/com/nq/utils/redis/RedisKeyConstant.java
@@ -35,10 +35,27 @@ /** * 黄金行情 */ public static final String gold= "GOLD"; public static final String XAUUSD= "XAUUSD"; /** * 原油行情 */ public static final String crude_oil= "CRUDE_OIL"; public static final String USOIL= "USOIL"; /** * 根据传入的 key 名称获取对应的 Redis key 常量 * * @param key 名称 * @return 对应的 Redis Key 或者 null 如果没有匹配的 key */ public static String getRedisKey(String key) { switch (key) { case "XAUUSD": return XAUUSD; case "USOIL": return USOIL; default: return null; // 如果没有匹配的 key,返回 null } } } src/main/java/com/nq/utils/task/stock/StockTask.java
@@ -1,8 +1,7 @@ package com.nq.utils.task.stock; import cn.hutool.json.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; @@ -13,13 +12,16 @@ import com.nq.pojo.ReponseBase; import com.nq.pojo.Stock; import com.nq.pojo.UserPosition; import com.nq.pojo.reponse.kResponse; 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.http.HttpClientRequest; import com.nq.utils.redis.RedisKeyConstant; import com.nq.utils.redis.RedisKeyUtil; import com.nq.utils.redis.RedisShardedPoolUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -27,9 +29,14 @@ import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.text.DecimalFormat; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -81,116 +88,246 @@ } } } //最新价格url private static final String PRICE_URL = "https://quote.alltick.io/quote-b-api/trade-tick?token=794ea65dc03c5af582cddec476fbb0d7-c-app&query="; //k线url private static final String K_URL = "https://quote.alltick.io/quote-b-api/kline?token=794ea65dc03c5af582cddec476fbb0d7-c-app&query="; //黄金 private static final String gold_API_URL = "http://139.196.211.109/exchange_curr.action?username=Qq112233&password=3ce25a66d5b3a8cd661024fea6c79388&id=AUUSDO"; //原油 private static final String crude_oil_API_URL = "http://47.112.169.122/fOption_curr.action?username=Qq112233&password=3ce25a66d5b3a8cd661024fea6c79388&id=@CL0W"; public String getPriceData() { // 创建查询数据 JSONObject data = new JSONObject(); @Scheduled(cron = "0/6 * * * * ?") // 每6秒执行一次 // 用于存储符号的列表 JSONArray symbolList = new JSONArray(); // 需要查询的符号列表(按你的要求,这里符号从 ["857.HK", "UNH.US"] 开始) String[] symbols = {"GOLD", "USOIL"}; // 遍历符号列表,构建 JSON 对象 for (String symbol : symbols) { JSONObject symbolObject = new JSONObject(); symbolObject.put("code", symbol); symbolList.put(symbolObject); } // 将 symbol_list 放入 data 对象中 data.put("symbol_list", symbolList); // 创建查询请求对象 JSONObject query = new JSONObject(); query.put("trace", generateTraceCode()); // 假设 generateTraceCode() 是生成唯一追踪代码的方法 query.put("data", data); // 返回构建的查询对象 return buildUrlWithQuery(query); } // 生成唯一追踪码 public static String generateTraceCode() { // 获取当前时间戳 long timestamp = System.currentTimeMillis(); // 生成唯一的 UUID String uuid = UUID.randomUUID().toString(); // 组合时间戳和 UUID,保证唯一性 return uuid + "-" + timestamp; } @Scheduled(cron = "0/2 * * * * ?") // 每6秒执行一次 public void sync() throws InterruptedException { ReentrantLock lock = new ReentrantLock(); if (lock.tryLock()) { // 尝试获取锁 try { gold(); Thread.sleep(1000); getKDate(); } finally { lock.unlock(); // 释放锁 } } else { // 如果锁不可用,可以选择不执行或打印日志等 System.out.println("任务正在执行,跳过本次执行。"); } } public void gold() { try { // 使用RestTemplate发起HTTP请求 RestTemplate restTemplate = new RestTemplate(); String response = restTemplate.getForObject(gold_API_URL, String.class); String url = PRICE_URL+getPriceData(); URL obj = new URL(url); HttpURLConnection con = (HttpURLConnection) obj.openConnection(); con.setRequestMethod("GET"); int responseCode = con.getResponseCode(); BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); String inputLine; StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); if(responseCode == 200){ // 创建 ObjectMapper 对象 ObjectMapper objectMapper = new ObjectMapper(); // 解析返回的CSV格式数据,去除可能存在的换行符 if (response != null && !response.contains("参数错误")) { // 清除换行符并按逗号分割数据 String[] parts = response.trim().split(","); String price = parts[2].trim(); // "3348.4" // 转换价格为Double类型 // 保存价格到Redis RedisShardedPoolUtils.set(RedisKeyConstant.gold, String.valueOf(price)); log.info("黄金定时任务------成功"); } else { log.info("黄金定时任务------没有接收到数据"); // 解析 JSON 字符串 JsonNode rootNode = objectMapper.readTree(response.toString()); // 获取 "data" 节点下的 "tick_list" 数组 JsonNode tickList = rootNode.path("data").path("tick_list"); // 遍历 tick_list 数组并提取 code 和 price for (JsonNode tick : tickList) { String code = tick.path("code").asText().equals("GOLD") ? "XAUUSD" : tick.path("code").asText(); String price = tick.path("price").asText(); RedisShardedPoolUtils.set(RedisKeyConstant.getRedisKey(code), price); } }else{ log.info("黄金原油获实时价格定时任务------没有接收到数据:"+response); } } catch (Exception e) { e.printStackTrace(); log.error("黄金定时任务------请求或数据解析失败:" + e.getMessage()); } } @Scheduled(cron = "0/7 * * * * ?") // 每6秒执行一次 public void crudeOil() { public static String buildUrlWithQuery(JSONObject jsonObject) { try { // 使用RestTemplate发起HTTP请求 RestTemplate restTemplate = new RestTemplate(); String response = restTemplate.getForObject(crude_oil_API_URL, String.class); // 解析返回的CSV格式数据,去除可能存在的换行符 if (response != null && !response.contains("参数错误")) { // 清除换行符并按逗号分割数据 String[] parts = response.trim().split(","); String price = parts[2].trim(); // "3348.4" // 转换价格为Double类型 // 保存价格到Redis RedisShardedPoolUtils.set(RedisKeyConstant.crude_oil, String.valueOf(price)); log.info("原油定时任务------没有接收到数据"); } else { log.info("原油定时任务------没有接收到数据"); } } catch (Exception e) { // 将 JSON 对象转换为字符串 String jsonString = jsonObject.toString(); // 使用 URLEncoder 编码 JSON 字符串 String encodedJson = URLEncoder.encode(jsonString, "UTF-8"); return encodedJson; } catch (UnsupportedEncodingException e) { e.printStackTrace(); log.error("原油定时任务------请求或数据解析失败:" + e.getMessage()); return null; } } //黄金 private static final String k_gold_API_URL = "http://139.196.211.109/ldMetal_k.action?username=Qq112233&password=3ce25a66d5b3a8cd661024fea6c79388&id=AUUSDO&num=-100&period="; //原油 private static final String k_crude_oil_API_URL = "http://47.112.169.122/fOption_k.action?username=Qq112233&password=3ce25a66d5b3a8cd661024fea6c79388&id=@CL0W&num=-100&period="; @Scheduled(cron = "0/6 * * * * ?") // 每6秒执行一次 public void getKDate() throws InterruptedException { RestTemplate restTemplate = new RestTemplate(); String[] arr = {"d", "w", "m", "1", "5", "30"}; for (String str : arr) { String g = restTemplate.getForObject(k_gold_API_URL+str, String.class); if(!g.contains("参数错误")){ RedisShardedPoolUtils.set("k_gold_"+str, g); Thread.sleep(10000); // 创建Map对象 Map<String, Integer> map = new HashMap<>(); // 写死键值对 map.put("d", 8); map.put("w", 9); map.put("m", 10); map.put("1", 1); map.put("5", 2); map.put("30", 4); for (Map.Entry<String, Integer> entry : map.entrySet()) { String gold = getResp(K_URL + getKQueryData(entry.getValue(), "XAUUSD")); if(StringUtils.isNotEmpty(gold)){ if(entry.getKey().equals("d")){ priceLimit(gold,"XAUUSD"); } RedisShardedPoolUtils.set("k_gold_"+entry.getKey(), gold); } String c = restTemplate.getForObject(k_crude_oil_API_URL+str, String.class); if(!c.contains("参数错误")){ RedisShardedPoolUtils.set("k_crude_oil_"+str, c); Thread.sleep(10000); Thread.sleep(1000); String c = getResp(K_URL+getKQueryData(entry.getValue(),"USOIL")); if(StringUtils.isNotEmpty(c)){ if(entry.getKey().equals("d")) { priceLimit(c, "USOIL"); } RedisShardedPoolUtils.set("k_crude_oil_"+entry.getKey(), c); } Thread.sleep(1000); } } /** * 同步美国股票 */ // @Scheduled(cron = "0 0/30 * * * ?") // public void loadStockCompanies() { // loadAllCompanies(); // } // // // /** // * 加载公司信息 // */ // public void loadAllCompanies() { // List<Stock> list = stockMapper.findStockList(); // for (int i = 0; i < list.size(); i++) { // Stock stock = list.get(i); // EStockType eStockType = EStockType.getEStockTypeByCode(stock.getStockType()); // String result = HttpClientRequest.doGet(eStockType.stockUrl + "companies?pid=+" + stock.getStockCode() + "+country_id=" + eStockType.getContryId() + "&size=1&page=1&key=" + eStockType.stockKey); // try { // JSONObject jsonObject = JSONObject.parseObject(result); // JSONObject companiesInfo = jsonObject.getJSONArray("data").getJSONObject(0); // RedisKeyUtil.setCacheCompanies(stock, new Gson().toJson(companiesInfo)); // } catch (Exception e) { // log.info(""); // // } // } // // } @lombok.Data class kData { long t; String c; String o; String h; String l; String v; String vo; } public void priceLimit(String data,String key){ List<kData> kDataList = new ArrayList<>(); // 使用 Gson 解析 JSON 字符串 Gson gson = new Gson(); kResponse kResponse = gson.fromJson(data, kResponse.class); // 打印 kline_list 的内容 for (kResponse.KlineData item : kResponse.getData().getKlineList()) { kData kData = new kData(); kData.setT(item.getTimestamp()); kData.setC(item.getClose_price()); kData.setO(item.getOpen_price()); kData.setH(item.getHigh_price()); kData.setL(item.getLow_price()); kData.setV(item.getVolume()); kData.setVo(item.getTurnover()); kDataList.add(kData); } DecimalFormat decimalFormat = new DecimalFormat("#.00"); double oneC = Double.valueOf(kDataList.get(kDataList.size() - 1).getC()); double twoC = Double.valueOf(kDataList.get(kDataList.size() - 2).getC()); String h = String.valueOf(decimalFormat.format(((oneC - twoC) / oneC * 100))); RedisShardedPoolUtils.set(key+"_H",h); RedisShardedPoolUtils.set(key+"_H",h); } public String getResp(String url){ try { URL obj = new URL(url); HttpURLConnection con = (HttpURLConnection) obj.openConnection(); con.setRequestMethod("GET"); int responseCode = con.getResponseCode(); BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); String inputLine; StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); if(responseCode == 200){ return response.toString(); } }catch (Exception e){ e.printStackTrace(); log.error("k线请求错误!", e.getMessage()); } return null; } //k线请求组装数据 public String getKQueryData(Integer k_data,String code){ JSONObject queryData = new JSONObject(); queryData.put("trace", generateTraceCode()); JSONObject data = new JSONObject(); data.put("code", code);//产品code /** * k线类型 * 1、1是1分钟K,2是5分钟K,3是15分钟K,4是30分钟K,5是小时K,6是2小时K(股票不支持2小时),7是4小时K(股票不支持4小时),8是日K,9是周K,10是月K (注:股票不支持2小时K、4小时K) * 2、最短的k线只支持1分钟 * 3、查询昨日收盘价,kline_type 传8 */ data.put("kline_type", k_data); /** * 从指定时间往前查询K线 * 1、传0表示从当前最新的交易日往前查k线 * 2、指定时间请传时间戳,传时间戳表示从该时间戳往前查k线 * 3、只有外汇贵金属加密货币支持传时间戳,股票类的code不支持 */ data.put("kline_timestamp_end", 0); /** * 1、表示查询多少根K线,每次最大请求1000根,可根据时间戳循环往前请求 * 2、通过该字段可查询昨日收盘价,kline_type 传8,query_kline_num传2,返回2根k线数据中,时间戳较小的数据是昨日收盘价 */ data.put("query_kline_num", 200); /* 复权类型,对于股票类的code才有效,例如:0:除权,1:前复权,目前仅支持0 */ data.put("adjust_type", 0); queryData.put("data", data); return buildUrlWithQuery(queryData); } /** * 加载所有股票数据 src/main/resources/application.properties
@@ -62,7 +62,7 @@ ST_HTTP_API = http://api-sa.js-stock.top/ ST_WS_URL = ws://api-sa-ws.js-stock.top ST_KEY = DP6jTI2ow7unfakP0fRM ST_KEY = chetm43ZxsgzEzqr3dZ0 #HK_HTTP_API = http://api-v1.js-stock.top/