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


<<:  [ Day 11 ] - DOM

>>:  EP 18 Search and SearchBar design in TopStore App

Day.24 「你点了按钮~同时也点了网页本身!」 —— JavaScript 事件冒泡(Event bubbling)

我们上一个篇章认识了绑定事件,了解到不管是什麽节点,都可以绑定事件 那为什麽 JavaScript...

Day31 -- Whack A Mole

目标 今天要来做的是打地鼠 Step1 const holes = document.querySe...

Day1 後端及PHP介绍

Day1 後端及PHP介绍 大家好~ 之後的30天来跟大家介绍一下我学习PHP到现在的过程,主要会以...

Day-17 就是要重现这一部!没有极限的 PS2!

在这第六世代的战争中、面对来势汹汹的 DC、SONY 当然也早就有准备、非常机歪的选在 DC 发售的...

day3_精简指令集带给 arm 的优势与短板

指令集与执行的程序 看完後上一篇我们知道,指令集代表在 cpu 内预先准备好的动作代号,比如说 代号...