我: 哇~ 同學你有好多資源是怎麼來的啊?
同學: 你猜猜看,猜錯的話我就要檢查你大腦發育有沒有正常喔~~(冷笑
我: 難道是你自己花很多時間抓的 ? ( 覺得同學怪怪的,向後退了一步
同學: No~ 我設排程讓系統自己跑的。你猜錯了,所以過來讓我看看你發育有沒有正常~!! (強拉
我: ㄚㄚㄚ,不要阿~~
在現代社會中,時間就是金錢,能夠讓機器自己去跑我們就堅決不自己做,像是證交所API
有一個功能是上市個股每 5 秒委託成交統計,我們總不能請一位工程師在電腦前每五秒點一次查詢吧!
Spring Boot本身就有提供排程讓大家去設定,以下有兩個規則需要注意
- the method should typically have a void return type (if not, the returned value will be ignored)
- the method should not expect any parameters
1.方法皆不會回傳值,有回傳值也會被忽略
2.方法不會有條件參數需求
好的,這次我們要寫一個排程功能是每天下午5點會對API請求一次,取得資料後會存在資料庫中,
讓我們先新建一個資料庫表單
CREATE TABLE `daily_tranction_stock_data` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`CODE` varchar(45) DEFAULT NULL COMMENT '證券代號',
`NAME` varchar(45) DEFAULT NULL COMMENT '證券名稱',
`TRADE_VOLUME` int(11) DEFAULT NULL COMMENT '成交股數',
`TRADE_VALUE` bigint(20) DEFAULT NULL COMMENT '成交金額',
`OPENING_PRICE` decimal(10,2) DEFAULT NULL COMMENT '開盤價',
`HIGHEST_PRICE` decimal(10,2) DEFAULT NULL COMMENT '最高價',
`LOWEST_PRICE` decimal(10,2) DEFAULT NULL COMMENT '最低價',
`CHANGE_GAP` decimal(10,2) DEFAULT NULL COMMENT '漲跌價差',
`CLOSING_PRICE` decimal(10,2) DEFAULT NULL COMMENT '收盤價',
`TRANSACTION_COUNT` int(11) DEFAULT NULL COMMENT '成交筆數',
`CREATE_TIME` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '建立時間',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1141 DEFAULT CHARSET=utf8mb4 COMMENT='上市個股日成交資訊';
再來我們更新一下 model-DailyTranctionStockData 的屬性型別
package com.stockAPI.model;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class DailyTranctionStockData {
//上市個股日成交資訊
// {
// "Code": "string", //證券代號
// "Name": "string", //證券名稱
// "TradeVolume": "string", //成交股數
// "TradeValue": "string", //成交金額
// "OpeningPrice": "string", //開盤價
// "HighestPrice": "string", //最高價
// "LowestPrice": "string", //最低價
// "ClosingPrice": "string", //收盤價
// "Change": "string", //漲跌價差
// "Transaction": "string" //成交筆數
// }
private Integer id;
private Timestamp create_time;
@JsonProperty(value="Code")
private String code;
@JsonProperty(value="Name")
private String name;
@JsonProperty(value="TradeVolume")
private Integer trade_volume;
@JsonProperty(value="TradeValue")
private BigInteger trade_value;
@JsonProperty(value="OpeningPrice")
private BigDecimal opening_price;
@JsonProperty(value="HighestPrice")
private BigDecimal highest_price;
@JsonProperty(value="LowestPrice")
private BigDecimal lowest_price;
@JsonProperty(value="ClosingPrice")
private BigDecimal closing_price;
@JsonProperty(value="Change")
private BigDecimal change_gap;
@JsonProperty(value="Transaction")
private Integer transaction_count;
public DailyTranctionStockData() {
}
public DailyTranctionStockData(String code, String name, Integer trade_volume, BigInteger trade_value,
BigDecimal opening_price, BigDecimal highest_price, BigDecimal lowest_price, BigDecimal closing_price,
BigDecimal change_gap, Integer transaction_count) {
super();
this.code = code;
this.name = name;
this.trade_volume = trade_volume;
this.trade_value = trade_value;
this.opening_price = opening_price;
this.highest_price = highest_price;
this.lowest_price = lowest_price;
this.closing_price = closing_price;
this.change_gap = change_gap;
this.transaction_count = transaction_count;
}
}
我們在repository裡面新增一個 DailyTranctionStockDataRepository 然後裡面新增一個批量新增資料的功能
@Repository
public class DailyTranctionStockDataRepository {
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
NamedParameterJdbcTemplate namedParameterJdbcTemplate;
public int[] batchAdd(DailyTranctionStockData[] dailyTranctionStockData_array) {
List<DailyTranctionStockData> dailyTranctionStockData_list = new ArrayList<DailyTranctionStockData>();
for(DailyTranctionStockData dailyTranctionStockData:dailyTranctionStockData_array) {
dailyTranctionStockData_list.add(dailyTranctionStockData);
}
String sql = " INSERT INTO stockapi.daily_tranction_stock_data ( "
+ " CODE, NAME, TRADE_VOLUME, TRADE_VALUE, OPENING_PRICE, HIGHEST_PRICE,
+ LOWEST_PRICE, CLOSING_PRICE, CHANGE_GAP, TRANSACTION_COUNT )"
+ " VALUES ( :code, :name, :trade_volume, :trade_value, :opening_price,
+ :highest_price, :change_gap, :transaction_count "
+ " :lowest_price, :closing_price, ) " ;
SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(dailyTranctionStockData_list.toArray());
int[] updateCounts = namedParameterJdbcTemplate.batchUpdate(sql, batch);
return updateCounts;
}
}
然後在TWSIOpenService新增一個功能
package com.stockAPI.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.stockAPI.enumsave.TWSIOpenAPIUrl;
import com.stockAPI.model.DailyTranctionStockData;
import com.stockAPI.repository.DailyTranctionStockDataRepository;
import com.stockAPI.util.TWSIOpenAPIUtil;
@Service
public class TWSIOpenService {
@Autowired
DailyTranctionStockDataRepository dailyTranctionStockDataRepository;
public DailyTranctionStockData[] getDailyTranctionStockData(){
DailyTranctionStockData[] resultList =
TWSIOpenAPIUtil.send(
TWSIOpenAPIUrl.EXCHANGE_REPORT_STOCK_DAY_ALL.getUrl(),
TWSIOpenAPIUrl.EXCHANGE_REPORT_STOCK_DAY_ALL.getMethod(),
DailyTranctionStockData[].class);
return resultList;
}
//新增transaction註解可以防止出錯時資料還繼續寫到資料庫內
@Transactional(rollbackFor = Exception.class)
public void schedule_AddDailyTranctionStockData() {
DailyTranctionStockData[] dailyTranctionStockData_array = getDailyTranctionStockData();
dailyTranctionStockDataRepository.batchAdd(dailyTranctionStockData_array);
}
}
新增一個package -schedule ,然後新建一個DailySchedule類別
package com.stockAPI.schedule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.stockAPI.service.TWSIOpenService;
@Component
public class DailySchedule {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
TWSIOpenService tWSIOpenService;
//上市個股日成交資訊-存入 下午五點寫入
@Scheduled(cron = "0 0 17 * * ?")
public void saveDailyTranctionStockData() {
tWSIOpenService.schedule_AddDailyTranctionStockData();
logger.info("上市個股日成交資訊-存入 下午五點寫入");
}
}
一個cron表示式有至少6個(也可能7個)有空格分隔的時間元素。
按順序依次為
這樣我們的寫入排程就完成囉!!