| | |
| | | package com.nq.service.impl; |
| | | |
| | | import cn.hutool.core.date.DateTime; |
| | | import cn.hutool.core.date.DateUtil; |
| | | import cn.hutool.http.HttpUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.fasterxml.jackson.core.JsonProcessingException; |
| | | import com.google.gson.Gson; |
| | |
| | | import com.nq.dao.StockMapper; |
| | | import com.nq.dao.StockSettingMapper; |
| | | import com.nq.enums.EConfigKey; |
| | | import com.nq.enums.EStockType; |
| | | 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.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.io.BufferedReader; |
| | | import java.io.InputStreamReader; |
| | | 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.Date; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | |
| | | @Service |
| | |
| | | Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("stock_code",stockCode)); |
| | | StockSetting stockSetting = stockSettingMapper.selectOne(new QueryWrapper<StockSetting>().eq("stock_code",stockCode)); |
| | | if(stockSetting != null){ |
| | | if(TimeUtil.isTradingHour(stockSetting.getStartTime(),stockSetting.getEndTime())){ |
| | | Date newDate = new Date(); |
| | | DateTime startTime = DateUtil.parseDateTime(stockSetting.getStartTime()); |
| | | DateTime endTime = DateUtil.parseDateTime(stockSetting.getEndTime()); |
| | | if(newDate.after(startTime) && newDate.before(endTime)){ |
| | | // if(TimeUtil.isTradingHour(stockSetting.getStartTime(),stockSetting.getEndTime())){ |
| | | if(stockSetting.getType().equals("0")){ |
| | | return new BigDecimal(stockSetting.getPrice()); |
| | | }else{ |
| | | String s = doGet(stock.getStockCode()); |
| | | if(null != s){ |
| | | Map<String, Object> stringObjectMap = jsonToMap(s); |
| | | return new BigDecimal(stringObjectMap.get("last").toString()).multiply(new BigDecimal(stockSetting.getPrice())); |
| | | return new BigDecimal(stringObjectMap.get("Last").toString()).multiply(new BigDecimal(stockSetting.getPrice())); |
| | | } |
| | | } |
| | | } |
| | |
| | | String s = doGet(stock.getStockCode()); |
| | | if(null != s) { |
| | | Map<String, Object> stringObjectMap = jsonToMap(s); |
| | | return new BigDecimal(stringObjectMap.get("last").toString()); |
| | | return new BigDecimal(stringObjectMap.get("Last").toString()); |
| | | } |
| | | return BigDecimal.ZERO; |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | public String doGet(String pid){ |
| | | String apiUrl = "http://api-in-2.js-stock.top/stock?pid="+pid+"&key=eVKtHt7aG4m6ozwWL9qG"; |
| | | try { |
| | | URL url = new URL(apiUrl); |
| | | HttpURLConnection connection = (HttpURLConnection) url.openConnection(); |
| | | connection.setRequestMethod("GET"); |
| | | private static class CacheEntry { |
| | | String result; |
| | | long lastExecuteTime; |
| | | } |
| | | |
| | | BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); |
| | | String inputLine; |
| | | StringBuffer response = new StringBuffer(); |
| | | private static final Map<String, CacheEntry> cacheMap = new ConcurrentHashMap<>(); |
| | | private static final long MIN_INTERVAL_MS = 3000; |
| | | private static final Object globalLock = new Object(); |
| | | |
| | | while ((inputLine = in.readLine()) != null) { |
| | | public static String doGet(String pid) { |
| | | long currentTime = System.currentTimeMillis(); |
| | | |
| | | // 1. 先检查该pid是否有缓存 |
| | | CacheEntry entry = cacheMap.get(pid); |
| | | if (entry != null && (currentTime - entry.lastExecuteTime) < MIN_INTERVAL_MS) { |
| | | return entry.result; |
| | | } |
| | | |
| | | // 2. 使用双重检查锁定更新缓存 |
| | | synchronized (getLockForPid(pid)) { |
| | | currentTime = System.currentTimeMillis(); |
| | | entry = cacheMap.get(pid); |
| | | |
| | | if (entry != null && (currentTime - entry.lastExecuteTime) < MIN_INTERVAL_MS) { |
| | | return entry.result; |
| | | } |
| | | |
| | | // 3. 执行实际请求 |
| | | String newResult = doActualPost(pid); |
| | | |
| | | // 4. 更新该pid的缓存 |
| | | CacheEntry newEntry = new CacheEntry(); |
| | | newEntry.result = newResult; |
| | | newEntry.lastExecuteTime = System.currentTimeMillis(); |
| | | cacheMap.put(pid, newEntry); |
| | | |
| | | return newResult; |
| | | } |
| | | } |
| | | |
| | | // 为每个pid提供独立的锁对象,避免不同pid间的阻塞 |
| | | private static final Map<String, Object> pidLocks = new ConcurrentHashMap<>(); |
| | | |
| | | private static Object getLockForPid(String pid) { |
| | | return pidLocks.computeIfAbsent(pid, k -> new Object()); |
| | | } |
| | | |
| | | |
| | | private static String doActualPost(String pid) { |
| | | String apiUrl = PropertiesUtil.getProperty("JS_IN_HTTP_URL") + |
| | | "stock?key=" + PropertiesUtil.getProperty("JS_IN_KEY"); |
| | | |
| | | try { |
| | | URL url = new URL(apiUrl); |
| | | HttpURLConnection connection = (HttpURLConnection) url.openConnection(); |
| | | |
| | | connection.setRequestMethod("POST"); |
| | | connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); |
| | | connection.setDoOutput(true); |
| | | connection.setConnectTimeout(5000); |
| | | connection.setReadTimeout(10000); |
| | | |
| | | String postData = "pid=" + pid; |
| | | |
| | | 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; |
| | | StringBuilder response = new StringBuilder(); |
| | | |
| | | while ((inputLine = in.readLine()) != null) { |
| | | response.append(inputLine); |
| | | } |
| | | in.close(); |
| | | return response.toString(); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public BigDecimal getNowPrice(String stockCode, String stockType) { |
| | | BigDecimal nowPrice = getNowPrice(stockCode); |
| | | if (!stockType.equals("DZ")){ |
| | | return nowPrice; |
| | | } |
| | | QueryWrapper queryWrapper = new QueryWrapper<>(); |
| | | queryWrapper.eq("stock_code",stockCode); |
| | | StockDz stockDz = stockDZMapper.selectOne(queryWrapper); |
| | | if(stockDz == null){ |
| | | return nowPrice;} |
| | | return nowPrice.multiply(stockDz.getDiscount()); |
| | | return response.toString(); |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | // 如果请求失败,返回该pid的旧缓存(如果有) |
| | | CacheEntry oldEntry = cacheMap.get(pid); |
| | | if (oldEntry != null && oldEntry.result != null) { |
| | | return oldEntry.result; |
| | | } |
| | | return "{\"error\":\"请求失败:" + e.getMessage() + "\"}"; |
| | | } |
| | | } |
| | | |
| | | @Override |