diff --git a/pom.xml b/pom.xml index 341677e..18c88f0 100644 --- a/pom.xml +++ b/pom.xml @@ -82,7 +82,10 @@ redisson-spring-boot-starter 3.13.3 --> - + + org.springframework.boot + spring-boot-starter-data-redis + com.github.pagehelper pagehelper diff --git a/src/main/java/cn/stock/market/domain/basic/service/SiteNewsService.java b/src/main/java/cn/stock/market/domain/basic/service/SiteNewsService.java index 08d39db..dcb72bc 100644 --- a/src/main/java/cn/stock/market/domain/basic/service/SiteNewsService.java +++ b/src/main/java/cn/stock/market/domain/basic/service/SiteNewsService.java @@ -1,11 +1,30 @@ package cn.stock.market.domain.basic.service; -import java.util.List; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; import javax.servlet.http.HttpServletRequest; +import cn.qutaojing.common.jpa.ConditionBuilder; +import cn.stock.market.infrastructure.db.po.QSiteNewsPO; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import com.github.pagehelper.PageHelper; @@ -25,7 +44,8 @@ import cn.stock.market.utils.StringUtils; import cn.stock.market.utils.Utils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import net.sf.json.JSONObject; +import org.springframework.web.client.RestTemplate; + /** * SiteNewsService @@ -40,6 +60,8 @@ import net.sf.json.JSONObject; @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class SiteNewsService { final SiteNewsRepository repository; + private final RedisTemplate redisTemplate; + private final RestTemplate restTemplate; final SiteNewsFactory factory; /*新闻资讯-查询列表*/ @@ -54,6 +76,92 @@ public class SiteNewsService { return ServerResponse.createBySuccess(Utils.toPageHelperInfo(page)); } + public ServerResponse getLatestStockNews(int pageNum) { + int pageSize = 20; + String redisKey = "fmp:stock:latest:news:page:" + pageNum; + + try { + // Step 1: get from cache + String cached = redisTemplate.opsForValue().get(redisKey); + List list; + if (cached!= null && !cached.isEmpty()) { + list = JSON.parseArray(cached, SiteNews.class); + } else { + // Step 2: call FMP API + String url = String.format("https://financialmodelingprep.com/stable/news/stock-latest?page=%d&limit=%d&apikey=57ZI1xeAsqHY7ag0FBuMkwQzt6TQ60dG", pageNum, pageSize); + HttpHeaders headers = new HttpHeaders(); + headers.add("accept", "application/json"); + HttpEntity entity = new HttpEntity<>(headers); + ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class); + + if (response.getStatusCode().value() != 200 || response.getBody() == null) { + return ServerResponse.createByErrorMsg("Failed to fetch news"); + } + + JSONArray newsArray = JSON.parseArray(response.getBody()); + list = new ArrayList<>(); + for (int i = 0; i < newsArray.size(); i++) { + JSONObject obj = newsArray.getJSONObject(i); + String sourceId = obj.getString("url"); + + SiteNews news = new SiteNews(); + news.setSourceId(sourceId); + news.setTitle(obj.getString("title")); + news.setSourceName(obj.getString("publisher")); + news.setDescription(obj.getString("text")); + news.setContent(obj.getString("text")); + news.setImgurl(obj.getString("image")); + news.setStatus(1); + news.setType(1); + news.setViews(0); + news.setAddTime(new Date()); + + try { + ZonedDateTime ny = ZonedDateTime.of( + LocalDateTime.parse(obj.getString("publishedDate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), + ZoneId.of("America/New_York") + ); + news.setShowTime(Date.from(ny.withZoneSameInstant(ZoneId.systemDefault()).toInstant())); + } catch (Exception e) { + news.setShowTime(new Date()); + } + + list.add(news); + } + + redisTemplate.opsForValue().set(redisKey, JSON.toJSONString(list), Duration.ofMinutes(10)); + } + int simulatedTotal = 100; + + Page page = buildPage(list, pageNum, pageSize, simulatedTotal); + return ServerResponse.createBySuccess(page); + + } catch (Exception e) { + log.error("Error getting latest stock news page {}", pageNum, e); + try{ + Page page = repository.findAll(ConditionBuilder.builder().build(), PageParam.of(pageNum, pageSize), QSiteNewsPO.siteNewsPO.showTime.desc()); + + return ServerResponse.createBySuccess(page); + }catch (Exception e1) { + return ServerResponse.createByErrorMsg("Internal error"); + } + } + } + + private Page buildPage(List allNews, int pageNum, int pageSize, int totalCount) { + int offset = pageNum * pageSize; + + // Defensive bounds check + int toIndex = Math.min(offset + pageSize, allNews.size()); + + List pagedList = offset >= allNews.size() ? allNews : allNews.subList(offset, toIndex); + + Pageable pageable = PageRequest.of(pageNum, pageSize); + + // You can pass total = 100 to simulate full dataset + return new PageImpl<>(pagedList, pageable, totalCount); + } + /*新闻资讯-查询详情*/ public ServerResponse getDetail(int id) { return ServerResponse.createBySuccess(repository.find(id)); @@ -76,89 +184,8 @@ public class SiteNewsService { return ServerResponse.createBySuccess(pageInfo); } - /*新闻资讯-抓取*/ - public int grabNews() { - int ret = 0; - //新闻类型:1、财经要闻,2、经济数据,3、全球股市,4、7*24全球,5、商品资讯,6、上市公司,7、全球央行 - ret = addNews(1, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetImportantNewsList"); - log.info("财经要闻-抓取条数:" + ret); - ret = addNews(2, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetInfoList?code=125&pageNumber=1&pagesize=20&condition=&r="); - log.info("经济数据-抓取条数:" + ret); - ret = addNews(3, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetInfoList?code=105&pageNumber=1&pagesize=20&condition=&r="); - log.info("全球股市-抓取条数:" + ret); - - ret = addNews(4, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetInfoList?code=100&pageNumber=1&pagesize=20&condition=&r="); - log.info("7*24全球-抓取条数:" + ret); - - ret = addNews(5, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetInfoList?code=106&pageNumber=1&pagesize=20&condition=&r="); - log.info("商品资讯-抓取条数:" + ret); - - ret = addNews(6, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetInfoList?code=103&pageNumber=1&pagesize=20&condition=&r="); - log.info("上市公司-抓取条数:" + ret); - - ret = addNews(7, PropertiesUtil.getProperty("news.main.url") + "/pc_news/FastNews/GetInfoList?code=118&pageNumber=1&pagesize=20&condition=&r="); - log.info("全球央行-抓取条数:" + ret); - - return ret; - } - - /* - *抓取新闻专用 - * type:新闻类型:1、财经要闻,2、经济数据,3、全球股市,4、7*24全球,5、商品资讯,6、上市公司,7、全球央行 - * */ - private int addNews(Integer type, String url){ - int k = 0; - try { - String newlist = HttpRequest.doGrabGet(url); - JSONObject json = JSONObject.fromObject(newlist); - if(json != null && json.getJSONArray("items") != null && json.getJSONArray("items").size() > 0){ - for (int i = 0; i < json.getJSONArray("items").size(); i++){ - JSONObject model = JSONObject.fromObject(json.getJSONArray("items").getString(i)); - String newsId = model.getString("code"); - String imgUrl = null; - if(model.has("imgUrl")){ - imgUrl = model.getString("imgUrl"); - } - //新闻不存在则添加 - if(repository.getNewsBySourceIdCount(newsId) == 0){ - //获取新闻详情 - String newdata = HttpRequest.doGrabGet(PropertiesUtil.getProperty("news.main.url") + "/PC_News/Detail/GetDetailContent?id="+ newsId +"&type=1"); - newdata = newdata.substring(1,newdata.length()-1).replace("\\\\\\\"","\""); - newdata = newdata.replace("\\\"","\""); - newdata = StringUtils.UnicodeToCN(newdata); - newdata = StringUtils.delHTMLTag(newdata); - - JSONObject jsonnew = JSONObject.fromObject(newdata); - if(jsonnew != null && jsonnew.get("data") != null){ - JSONObject news = JSONObject.fromObject(jsonnew.get("data")); - SiteNews siteNews = new SiteNews(); - siteNews.setSourceId(newsId); - siteNews.setSourceName(news.getString("source")); - siteNews.setTitle(news.getString("title")); - String showTime = news.getString("showTime"); - siteNews.setShowTime(DateTimeUtil.strToDate(showTime)); - siteNews.setImgurl(imgUrl); - siteNews.setDescription(news.getString("description")); - siteNews.setContent(news.getString("content")); - siteNews.setStatus(1); - siteNews.setType(type); - try { - repository.saveAndFlush(siteNews); - } catch(Exception e) { - log.warn("siteNewsMapper insert error: {}", e.getLocalizedMessage()); - } - k++; - } - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return k; - } public SiteNewsRepository repository() { return repository; diff --git a/src/main/java/cn/stock/market/infrastructure/job/InvestingTask.java b/src/main/java/cn/stock/market/infrastructure/job/InvestingTask.java index d807405..42a21f2 100644 --- a/src/main/java/cn/stock/market/infrastructure/job/InvestingTask.java +++ b/src/main/java/cn/stock/market/infrastructure/job/InvestingTask.java @@ -16,6 +16,7 @@ import com.alibaba.fastjson.JSONObject; import com.google.common.base.Stopwatch; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.digest.DigestUtils; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; @@ -36,6 +37,7 @@ import javax.annotation.PostConstruct; import java.io.IOException; import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.TimeUnit; @@ -188,128 +190,93 @@ public class InvestingTask { } /*德国新闻接口*/ -// @Scheduled(cron = "0 0 0/3 * * ?") + @Scheduled(cron = "0 0 0/3 * * ?") +// @PostConstruct public void saveGerNews() { - log.info("德国股票新闻数据同步开始"); + log.info("FMP 股票新闻数据同步开始"); int savedCount = 0; int totalCount = 0; + try { - // API URL for getting news list - String newsListUrl = "https://api.boerse-frankfurt.de/v1/data/category_news?newsType=ALL&lang=de&offset=0&limit=50"; - - // Headers for the API request + String newsListUrl = "https://financialmodelingprep.com/stable/news/stock-latest?page=0&limit=30&apikey=57ZI1xeAsqHY7ag0FBuMkwQzt6TQ60dG"; + HttpHeaders headers = new HttpHeaders(); - headers.add("accept", "application/json, text/plain, */*"); - headers.add("accept-language", "en-US,en;q=0.9,vi;q=0.8,ug;q=0.7,fr;q=0.6"); - headers.add("origin", "https://www.boerse-frankfurt.de"); - headers.add("priority", "u=1, i"); - headers.add("referer", "https://www.boerse-frankfurt.de/"); - headers.add("user-agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36"); + headers.add("accept", "application/json"); HttpEntity entity = new HttpEntity<>(headers); - - // Get news list ResponseEntity response = restTemplate.exchange( - newsListUrl, - HttpMethod.GET, - entity, - String.class + newsListUrl, + HttpMethod.GET, + entity, + String.class ); if (response.getStatusCode().value() == 200 && response.getBody() != null) { - JSONObject newsListResponse = JSON.parseObject(response.getBody()); - JSONArray newsData = newsListResponse.getJSONArray("data"); - - if (newsData != null && newsData.size() > 0) { - totalCount = newsData.size(); - log.info("Found {} German news items to process", totalCount); - - for (int i = 0; i < newsData.size(); i++) { - try { - JSONObject newsItem = newsData.getJSONObject(i); - String newsId = newsItem.getString("id"); - String headline = newsItem.getString("headline"); - String time = newsItem.getString("time"); - String source = newsItem.getString("source"); - String teaserText = newsItem.getString("teaserText"); - String teaserImageUrl = newsItem.getString("teaserImageUrl"); - - // Check if news already exists - List existingNews = newsRepository.findAll(QSiteNewsPO.siteNewsPO.sourceId.eq(newsId)); - if (existingNews.size() == 0) { - // Get news detail - String newsDetailUrl = "https://api.boerse-frankfurt.de/v1/data/news?id=" + newsId + "&lang=de"; - HttpEntity detailEntity = new HttpEntity<>(headers); - - ResponseEntity detailResponse = restTemplate.exchange( - newsDetailUrl, - HttpMethod.GET, - detailEntity, - String.class - ); - - if (detailResponse.getStatusCode().value() == 200 && detailResponse.getBody() != null) { - JSONObject newsDetail = JSON.parseObject(detailResponse.getBody()); - String body = newsDetail.getString("body"); - - // Create SiteNews entity - SiteNews siteNews = new SiteNews(); - siteNews.setAddTime(new Date()); - siteNews.setSourceId(newsId); - siteNews.setTitle(headline); - siteNews.setSourceName(source); - siteNews.setDescription(teaserText != null ? teaserText : ""); - siteNews.setImgurl(teaserImageUrl); - siteNews.setContent(body != null ? body : ""); - siteNews.setStatus(1); - siteNews.setType(1); // Set as financial news type - siteNews.setViews(0); - - // Parse and set show time - if (time != null && !time.isEmpty()) { - try { - // Parse ISO 8601 format: "2025-06-19T08:37:58+02:00" - // Remove timezone offset and convert to standard format - String timeStr = time.replace("+02:00", "").replace("T", " "); - siteNews.setShowTime(DateTimeUtil.strToDate(timeStr, "yyyy-MM-dd HH:mm:ss")); - } catch (Exception e) { - log.warn("Failed to parse time for news {}: {}", newsId, time); - siteNews.setShowTime(new Date()); - } - } else { - siteNews.setShowTime(new Date()); - } - - try { - newsRepository.save(siteNews); - savedCount++; - log.info("Saved German news [{}/{}]: {}", savedCount, totalCount, headline); - } catch (Exception e) { - log.warn("Failed to save German news {}: {}", newsId, e.getMessage()); - } - } else { - log.warn("Failed to get news detail for {}: HTTP {}", newsId, detailResponse.getStatusCode()); - } - } else { - log.debug("News {} already exists, skipping", newsId); - } - } catch (Exception e) { - log.warn("Error processing news item {}: {}", i, e.getMessage()); + JSONArray newsArray = JSON.parseArray(response.getBody()); + totalCount = newsArray.size(); + log.info("Found {} news items to process", totalCount); + + for (int i = 0; i < newsArray.size(); i++) { + try { + JSONObject newsItem = newsArray.getJSONObject(i); + String sourceId = newsItem.getString("url"); + + // Check existence + List existingNews = newsRepository.findAll(QSiteNewsPO.siteNewsPO.sourceId.eq(sourceId)); + if (!existingNews.isEmpty()) { + log.debug("News {} already exists, skipping", sourceId); + continue; } + + // Create and populate SiteNews entity + SiteNews siteNews = new SiteNews(); + siteNews.setAddTime(new Date()); + siteNews.setSourceId(sourceId); + siteNews.setTitle(newsItem.getString("title")); + siteNews.setSourceName(newsItem.getString("publisher")); + siteNews.setDescription(newsItem.getString("symbol")); + siteNews.setImgurl(newsItem.getString("image")); + siteNews.setContent(newsItem.getString("text")); + siteNews.setStatus(1); + siteNews.setType(1); + siteNews.setViews(0); + + // Parse publishedDate + String publishedDate = newsItem.getString("publishedDate"); + try { + ZonedDateTime nyTime = ZonedDateTime.of( + LocalDateTime.parse(publishedDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), + ZoneId.of("America/New_York") + ); + + ZonedDateTime localTime = nyTime.withZoneSameInstant(ZoneId.systemDefault()); + siteNews.setShowTime(Date.from(localTime.toInstant())); + } catch (Exception e) { + log.warn("Failed to parse publishedDate with timezone for {}: {}", sourceId, publishedDate); + siteNews.setShowTime(new Date()); + } + + // Save news + newsRepository.save(siteNews); + savedCount++; + log.info("Saved news [{}/{}]: {}", savedCount, totalCount, siteNews.getTitle()); + + } catch (Exception e) { + log.warn("Error processing news item {}: {}", i, e.getMessage()); } - } else { - log.warn("No news data found in API response"); } + } else { - log.error("Failed to get news list: HTTP {}", response.getStatusCode()); + log.error("Failed to fetch news: HTTP {}", response.getStatusCode()); } - log.info("德国股票新闻数据同步完成,处理了 {} 条新闻,保存了 {} 条新闻", totalCount, savedCount); + + log.info("FMP 股票新闻数据同步完成,总数 {},已保存 {}", totalCount, savedCount); } catch (Exception e) { - log.error("德国新闻数据同步异常,异常信息: {}", e.getMessage(), e); + log.error("FMP 新闻同步异常: {}", e.getMessage(), e); } } - @Scheduled(cron = "0 0 0/3 * * ?") +// @Scheduled(cron = "0 0 0/3 * * ?") // @PostConstruct public void getBoerseNews(){ String url_request = "https://www.boerse-online.de"; diff --git a/src/main/java/cn/stock/market/infrastructure/job/JobBoot.java b/src/main/java/cn/stock/market/infrastructure/job/JobBoot.java index a3aa98f..d3ca295 100644 --- a/src/main/java/cn/stock/market/infrastructure/job/JobBoot.java +++ b/src/main/java/cn/stock/market/infrastructure/job/JobBoot.java @@ -57,11 +57,11 @@ public class JobBoot { /* * 新闻资讯抓取 * */ - @Scheduled(cron = "0 0/30 9-20 * * ?") - public void newsInfoTask() { - MdcUtil.setTraceIdIfAbsent(); - Stopwatch stopwatch = Stopwatch.createStarted(); - int count = SiteNewsService.of().grabNews(); - log.info("newsInfoTask执行, 受影响数{}, 耗时:{}毫秒", count, stopwatch.elapsed(TimeUnit.MILLISECONDS)); - } +// @Scheduled(cron = "0 0/30 9-20 * * ?") +// public void newsInfoTask() { +// MdcUtil.setTraceIdIfAbsent(); +// Stopwatch stopwatch = Stopwatch.createStarted(); +// int count = SiteNewsService.of().grabNews(); +// log.info("newsInfoTask执行, 受影响数{}, 耗时:{}毫秒", count, stopwatch.elapsed(TimeUnit.MILLISECONDS)); +// } } diff --git a/src/main/java/cn/stock/market/infrastructure/redis/config/RedisConfig.java b/src/main/java/cn/stock/market/infrastructure/redis/config/RedisConfig.java index 2bab268..9f5c238 100644 --- a/src/main/java/cn/stock/market/infrastructure/redis/config/RedisConfig.java +++ b/src/main/java/cn/stock/market/infrastructure/redis/config/RedisConfig.java @@ -1,70 +1,53 @@ -//package cn.stock.market.infrastructure.redis.config; -// -//import java.time.Duration; -// -//import org.redisson.api.RedissonClient; -//import org.springframework.cache.CacheManager; -//import org.springframework.cache.annotation.EnableCaching; -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -//import org.springframework.data.redis.cache.RedisCacheConfiguration; -//import org.springframework.data.redis.cache.RedisCacheManager; -//import org.springframework.data.redis.connection.RedisConnectionFactory; -//import org.springframework.data.redis.core.RedisTemplate; -//import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; -//import org.springframework.data.redis.serializer.RedisSerializationContext; -//import org.springframework.data.redis.serializer.StringRedisSerializer; -// -//import cn.qutaojing.common.aop.distributedlock.DistributedLockTemplate; -//import cn.stock.market.infrastructure.redis.SingleDistributedLockTemplate; -// -///** -// * -// * @author xlfd -// * @email xlfd@gmail.com -// * @version 1.0 -// * @created Jun 3, 2021 4:56:28 PM -// */ -//@Configuration -//@EnableCaching -//public class RedisConfig { -// -// @Bean -// public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { -// RedisTemplate redisTemplate = new RedisTemplate<>(); -// redisTemplate.setConnectionFactory(redisConnectionFactory); -// redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); -// redisTemplate.setKeySerializer(new StringRedisSerializer()); -// -// redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); -// redisTemplate.setHashKeySerializer(new StringRedisSerializer()); -// -// return redisTemplate; -// } -// -// @Bean -// public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { -// // 配置序列化 -// RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); -// config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())); -// config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer<>(Object.class))); -// -// // 设置缓存的默认过期时间 ,30分钟 -// config.entryTtl(Duration.ofMinutes(30)); -// // 不缓存空值 -// config.disableCachingNullValues(); -// RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config) -// .build(); -// return cacheManager; -// } -// -// /** -// * 分布式锁实现 -// * @param redissonClient -// * @return -// */ -// @Bean -// public DistributedLockTemplate distributedLockTemplate(RedissonClient redissonClient) { -// return new SingleDistributedLockTemplate(redissonClient); -// } -//} +package cn.stock.market.infrastructure.redis.config; + +import org.springframework.boot.autoconfigure.data.redis.RedisProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisPassword; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +@EnableConfigurationProperties(RedisProperties.class) +public class RedisConfig { + + private RedisProperties redisProperties; + + public RedisConfig(RedisProperties redisProperties) { + this.redisProperties = redisProperties; + } + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); + config.setHostName(redisProperties.getHost()); + config.setPort(redisProperties.getPort()); + config.setDatabase(redisProperties.getDatabase()); + + if (redisProperties.getPassword() != null) { + config.setPassword(RedisPassword.of(redisProperties.getPassword())); + } + + return new LettuceConnectionFactory(config); + } + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + + StringRedisSerializer serializer = new StringRedisSerializer(); + template.setKeySerializer(serializer); + template.setValueSerializer(serializer); + template.setHashKeySerializer(serializer); + template.setHashValueSerializer(serializer); + + template.afterPropertiesSet(); + return template; + } +} \ No newline at end of file diff --git a/src/main/java/cn/stock/market/web/SiteNewsController.java b/src/main/java/cn/stock/market/web/SiteNewsController.java index a509522..e4a1edc 100644 --- a/src/main/java/cn/stock/market/web/SiteNewsController.java +++ b/src/main/java/cn/stock/market/web/SiteNewsController.java @@ -39,7 +39,7 @@ public class SiteNewsController { @RequestParam(value = "type", defaultValue = "0") Integer type, @RequestParam(value = "sort", defaultValue = "time1") String sort, @RequestParam(value = "keyword", required = false) String keyword, HttpServletRequest request) { - return this.iSiteNewsService.getList(pageNum, pageSize, type, sort, keyword, request); + return this.iSiteNewsService.getLatestStockNews(pageNum); } //新闻资讯-详情 diff --git a/src/main/java/cn/stock/market/web/StockApiController.java b/src/main/java/cn/stock/market/web/StockApiController.java index 4126cff..a30041c 100644 --- a/src/main/java/cn/stock/market/web/StockApiController.java +++ b/src/main/java/cn/stock/market/web/StockApiController.java @@ -13,6 +13,7 @@ import cn.qutaojing.common.PageParam; import cn.qutaojing.common.jpa.ConditionBuilder; import cn.stock.market.domain.basic.entity.SiteNews; import cn.stock.market.domain.basic.repository.SiteNewsRepository; +import cn.stock.market.domain.basic.service.SiteNewsService; import cn.stock.market.infrastructure.db.po.QSiteNewsPO; import cn.stock.market.infrastructure.job.InvestingTask; import cn.stock.market.web.annotations.EncryptFilter; @@ -72,6 +73,8 @@ public class StockApiController { StockService stockService; @Autowired SiteNewsRepository newsRepository; + @Autowired + SiteNewsService siteNewsService; @RequestMapping({"getRawSinaStock.do"}) @ResponseBody @@ -167,7 +170,7 @@ public class StockApiController { @ApiOperation(value = "印度新闻列表", httpMethod = "GET") @ResponseBody public ServerResponse getINDNews(@RequestParam("pageSize") Integer pageSize, @RequestParam("pageNum") Integer pageNum) { - return ServerResponse.createBySuccess(newsRepository.findAll(ConditionBuilder.builder().build(), PageParam.of(pageNum, pageSize), QSiteNewsPO.siteNewsPO.showTime.desc())); + return siteNewsService.getLatestStockNews(pageNum); } @RequestMapping({"test.do"}) diff --git a/src/main/java/cn/stock/market/web/service/MoneyApiService.java b/src/main/java/cn/stock/market/web/service/MoneyApiService.java index 3bc78d6..500385a 100644 --- a/src/main/java/cn/stock/market/web/service/MoneyApiService.java +++ b/src/main/java/cn/stock/market/web/service/MoneyApiService.java @@ -6,6 +6,7 @@ import cn.stock.market.domain.basic.repository.StockRepository; import cn.stock.market.dto.*; import cn.stock.market.infrastructure.db.po.QStockPO; import cn.stock.market.web.config.Config; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; @@ -15,8 +16,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; @Service @@ -172,6 +172,7 @@ public class MoneyApiService { .collect(Collectors.toList()); } + public List getTopStocksFromTradingView(String sortOrder) { String url = "https://scanner.tradingview.com/germany/scan"; diff --git a/src/main/resources/application-base-alpha.yml b/src/main/resources/application-base-alpha.yml index 846edf1..65d6fb8 100644 --- a/src/main/resources/application-base-alpha.yml +++ b/src/main/resources/application-base-alpha.yml @@ -3,8 +3,8 @@ spring: show-sql: true # Redis配置 redis: - host: 43.160.197.177 - password: redispass123 + host: 43.165.126.173 + password: a5v8b86P4mVzFlUqJV port: 6379 database: 1 lettuce: @@ -17,9 +17,9 @@ spring: datasource: stock-market: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://43.160.197.177:3306/germany_stock?useUnicode=true&characterEncoding=utf-8 + url: jdbc:mysql://use-cdb-45wol5su.sql.tencentcdb.com:22490/stock-api?useUnicode=true&characterEncoding=utf-8 username: root - password: mysqlpass123 + password: 6QJXv8dA76klnqsWh6f maxActive: 500 testWhileIdle: true validationQuery: SELECT 1