iT邦幫忙

2021 iThome 鐵人賽

DAY 11
0
自我挑戰組

Angular+Spring Boot API 處理股市資料系列 第 11

RestTemplate實作(一)(Day11)

在串接API之前我們還有一個重要的設定要做,我們必須先匯出證交所網站的SSL證書,並加入到JAVA的驗證裡面。

先進入證交所openAPI首頁

瀏覽器取得憑證

1.點選網頁上安全鎖的標示
https://ithelp.ithome.com.tw/upload/images/20210926/20138857Qtfya5GpZx.png

2.選擇匯出憑證
https://ithelp.ithome.com.tw/upload/images/20210926/20138857uxPJFQrIYw.png

3.選擇下一步
https://ithelp.ithome.com.tw/upload/images/20210926/20138857hQZ8Rs2R3R.png

4.選擇DER編碼
https://ithelp.ithome.com.tw/upload/images/20210926/20138857axzm9aE8hq.png

5.選擇你要匯出的檔案的地址
https://ithelp.ithome.com.tw/upload/images/20210926/20138857LtDgO1qTIs.png

JAVA匯入憑證

因為我們會用到keytool ,所以PATH 環境變數要設置 C:\Program Files\Java\jdk-11.0.9\bin 這段路徑
(此處因人而異,請去看自己Java的安裝路徑)
接著執行下面的指令把憑證加入Java的憑證驗證庫中

keytool -import -file 憑證儲存路徑 -keystore cacerts -alias server

接著我們就要開始實作API請求囉~

我們先在 model建立一個Class- DailyTranctionStockData

package com.stockAPI.model;

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" //成交筆數
//		}
	
	@JsonProperty(value="Code")
	private String code;
	
	@JsonProperty(value="Name")
	private String name;
	
	@JsonProperty(value="TradeVolume")
	private String tradevolume;
	
	@JsonProperty(value="TradeValue")
	private String tradevalue;
	
	@JsonProperty(value="OpeningPrice")
	private String openingprice;
	
	@JsonProperty(value="HighestPrice")
	private String highestprice;
	
	@JsonProperty(value="LowestPrice")
	private String lowestprice;
	
	@JsonProperty(value="ClosingPrice")
	private String closingprice;
	
	@JsonProperty(value="Change")
	private String change;
	
	@JsonProperty(value="Transaction")
	private String transaction;
	
	public DailyTranctionStockData() {
		
	}

	public DailyTranctionStockData(String code, String name, String tradevolume, String tradevalue, String openingprice,
			String highestprice, String lowestprice, String closingprice, String change, String transaction) {
		super();
		this.code = code;
		this.name = name;
		this.tradevolume = tradevolume;
		this.tradevalue = tradevalue;
		this.openingprice = openingprice;
		this.highestprice = highestprice;
		this.lowestprice = lowestprice;
		this.closingprice = closingprice;
		this.change = change;
		this.transaction = transaction;
	}
	
	
}

我在註釋裡面有放上從swagger的文件上看到的回傳格式,
然後我們再用@JsonProperty這個註解告訴框架我們Java物件屬性名與實際資料key的對應狀態。

再來我們實作一個Util 用來傳送資料給API(需要保留傳送物件類別的彈性)
在util的package新增一個類別-TWSIOpenAPIUtil

package com.stockAPI.util;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

public class TWSIOpenAPIUtil {

	static Logger logger=LogManager.getLogger();
	
	public static <T> T send(String url,HttpMethod method,Class<T> t){
		
		try {
			RestTemplate restTemplate = new RestTemplate();
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			HttpEntity<String> httpEntity = new HttpEntity<String>(headers);
			ResponseEntity<T> responseEntity  = 
		                restTemplate.exchange(url,method,httpEntity,t);
			T result = responseEntity.getBody();
			logger.info(responseEntity.getStatusCode());
			return result;
		}
		catch(HttpClientErrorException httpClientErrorException) {
			logger.error(httpClientErrorException.getResponseBodyAsString());
			return null;
		}
		catch(Exception e) {
			logger.error(e.getMessage());
			return null;
		}
	}
}

可以看到我們這邊用泛型,讓使用者自己決定要回傳什麼物件

有了功能當然還需要儲存API資訊的Class囉
新建一個enumsave package並在裡面新增 TWSIOpenAPIUrl -enum

package com.stockAPI.enumsave;

import org.springframework.http.HttpMethod;

public enum TWSIOpenAPIUrl {
	
	//證卷交易(exchangeReport)
	EXCHANGE_REPORT_STOCK_DAY_ALL(1,"exchange_report",HttpMethod.GET,"https://openapi.twse.com.tw/v1/exchangeReport/STOCK_DAY_ALL");
	
	
	private  Integer id;
	private String type;
	private HttpMethod method;
	private String url;
	
	private TWSIOpenAPIUrl(Integer id, String type, HttpMethod method, String url) {
		this.id = id;
		this.type = type;
		this.method =method;
		this.url = url;
	}

	public Integer getId() {
		return id;
	}

	public String getType() {
		return type;
	}
	
	public HttpMethod getMethod() {
		return method;
	}

	public String getUrl() {
		return url;
	}


}

Enum類別可以幫助我們管理一些固定資訊

最後我們在Service裡面新增一個類別- TWSIOpenService

package com.stockAPI.service;

import org.springframework.stereotype.Service;
import com.stockAPI.enumsave.TWSIOpenAPIUrl;
import com.stockAPI.model.DailyTranctionStockData;
import com.stockAPI.util.TWSIOpenAPIUtil;

@Service
public class TWSIOpenService {
	
	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;
	}

}

這樣就完成我們獲取 證卷交易-上市個股日成交資訊 的功能了喔!

明日我們會對這個Service進行功能測試和權限設定。

參考資料:

Get and Post Lists of Objects with RestTemplate
從頭解決PKIX path building failed


上一篇
RestTemplate介紹(Day10)
下一篇
RestTemplate實作(二)(Day12)
系列文
Angular+Spring Boot API 處理股市資料30

尚未有邦友留言

立即登入留言