功能实现

This commit is contained in:
cheney
2022-07-22 17:01:09 +08:00
parent 4b7110bb18
commit fbdc8d8b30
21 changed files with 1272 additions and 153 deletions
@@ -3,4 +3,17 @@ package com.sunyard.sge.database;
public class Consts {
public static final int ECB_DEC = 0;
public static final int ECB_ENC = 1;
// 唯一包
public static final int PkgNumAll = 0;
// 首包
public static final int PkgNumHead = 1;
// 中间包
public static final int PkgNumMiddle = 2;
// 结束包
public static final int PkgNumTail = 3;
}
@@ -1,4 +1,20 @@
package com.sunyard.sge.database;
public class LongDataReturn<T, T1> {
public class LongDataReturn<T1, T2> {
private T1 procData;
private T2 data;
public LongDataReturn(T1 procData, T2 data) {
this.procData = procData;
this.data = data;
}
public T1 getProcData() {
return procData;
}
public T2 getData() {
return data;
}
}
@@ -7,8 +7,23 @@ import java.util.List;
*/
public interface SydApi {
void warmUpMode(boolean use);
/**
* 设置全局日志相应的配置
*
*@param pcLogPath: 输入。日志存储路径
*@param iLogLevel: 输入。日志级别设置
* 0:不记录日志,
* 1:记录网络层错误日志,
* 2:记录接口错误日志及网络层错误日志,
* 3:记录正确日志及错误日志
*
* @return 无
**/
static void SYD_SetLogConfig(
String pcLogPath,
int iLogLevel) {
}
/**
* 建立到指定地址和端口号的签名服务器的 TCP/IP 连接,返回 API 操作对象 SydApi。
@@ -20,6 +35,7 @@ public interface SydApi {
* @param iDealTimeOut 交易接口超时设定,单位毫秒(不超过10ms)。
* @return SydApi 的对象,只要有设备可用则返回。
*/
@Deprecated
SydApi SYD_Connect_Ex(
String[] pcIpList,
int[] iPortList,
@@ -1,6 +1,7 @@
package com.sunyard.sge.database;
import com.sunyard.SydApiException;
import com.sunyard.proto.Util;
import com.sunyard.util.SYMUtil;
import racal.sunyard.main.SydApi4j;
@@ -8,136 +9,355 @@ import java.util.List;
/**
* 上海黄金交易所 - 数据库加密方案
*
*/
public class SydApi4Database implements SydApi
{
public class SydApi4Database implements SydApi {
// public static void SYD_SetLogConfig (
// String pcLogPath,
// int iLogLevel) {
// }
private SydApi4j api4j = null;
@Override
public void warmUpMode(boolean use) {
this.api4j.warmUpMode( use );
}
private SydApi4j[] hsms = null;
@Override
public SydApi SYD_Connect_Ex(String[] pcIpList, int[] iPortList, int iConnectTimeOut, int iDealTimeOut) {
if ( null == pcIpList &&
null == iPortList &&
pcIpList.length != iPortList.length ) {
throw new IllegalArgumentException("入参错误");
}
if ( null != api4j ) {
this.SYD_Disconnect_Ex();
}
api4j = (SydApi4j) new SydApi4j().connect( pcIpList[0], iPortList[0], null, iConnectTimeOut, iDealTimeOut);
SydApi4j api = (SydApi4j) new SydApi4j().connect(pcIpList[0], iPortList[0], null, iConnectTimeOut);
hsms = new SydApi4j[]{ api };
return this;
}
@Override
public void SYD_Disconnect_Ex() {
if ( null != this.api4j ) {
try {
this.api4j.disconnect();
}catch ( Exception e ){
}
}
this.api4j = null;
// 配合链接池,不再需要释放。
// if ( null != api ) {
// try {
// api.disconnect();
// }catch ( Exception e ){
// }
// }
// api = null;
}
@Override
public String SYD_SM3_Hash_ShortData(byte[] pcData) {
return null;
if (null == this.hsms || this.hsms.length < 1) {
throw new SydApiException(-1);
}
SydApiException le = null;
for (SydApi4j api : this.hsms) {
try {
byte[] hash = api.SYD_SM3_LongData(pcData, null, 0);
return Util.bytes2HexString(hash);
} catch (SydApiException e) {
le = e;
if (e.getRetCode() < 0) {
continue;
}
throw e;
}
}
throw le;
}
@Override
public LongDataReturn<String, String> SYD_SM3_Hash_LongData(byte[] pcData, int iPkgNum, String pcProcData) {
return null;
if (null == this.hsms || this.hsms.length < 1) {
throw new SydApiException(-1);
}
byte[] procData = null;
if (2 == iPkgNum || 3 == iPkgNum) {
procData = Util.hexString2Bytes(pcProcData);
}
SydApiException le = null;
for (SydApi4j api : this.hsms) {
try {
byte[] hash = api.SYD_SM3_LongData(pcData, procData, iPkgNum);
if (0 == iPkgNum || 3 == iPkgNum) {
return new LongDataReturn<String, String>(null, Util.bytes2HexString(hash));
} else {
return new LongDataReturn<String, String>(Util.bytes2HexString(hash), null);
}
} catch (SydApiException e) {
le = e;
if (e.getRetCode() < 0) {
continue;
}
throw e;
}
}
throw le;
}
@Override
public byte[] SYD_SM4_ShortData(int iKeyIndex, byte[] pcData, int iFlag) {
if ( null == this.api4j ) {
if (null == this.hsms || this.hsms.length < 1) {
throw new SydApiException(-1);
}
String keyIndex = String.format("%08d", iKeyIndex);
SydApiException le = null;
for (SydApi4j api : this.hsms) {
try {
if (Consts.ECB_ENC == iFlag) {
return api.SYMEncryptData(
com.sunyard.SydApi.NALG_SM4,
"SK" + SYMUtil.genPrivateKeyMark("000000", "00A", keyIndex),
1,
pcData);
} else {
return api.SYMDecryptData(
com.sunyard.SydApi.NALG_SM4,
"SK" + SYMUtil.genPrivateKeyMark("000000", "00A", keyIndex),
1,
pcData);
}
} catch (SydApiException e) {
le = e;
if (e.getRetCode() < 0) {
continue;
}
throw e;
}
}
throw le;
}
@Override
public List<byte[]> SYD_SM4_BatchData(int[] iKeyIndex, List<byte[]> pcData, int iFlag) {
if (null == this.hsms || this.hsms.length < 1) {
throw new SydApiException(-1);
}
String[] keys = new String[iKeyIndex.length];
for (int i = 0; i < iKeyIndex.length; i++) {
keys[i] = "SK" + SYMUtil.genPrivateKeyMark("000000", "00A", String.format("%08d", iKeyIndex[i]));
}
SydApiException le = null;
for (SydApi4j api : this.hsms) {
try {
if (Consts.ECB_ENC == iFlag) {
return api.SYMEncryptDecryptBatchData(8, 1, null, keys, 1, pcData);
} else {
return api.SYMEncryptDecryptBatchData(9, 1, null, keys, 1, pcData);
}
} catch (SydApiException e) {
le = e;
if (e.getRetCode() < 0) {
continue;
}
throw e;
}
}
throw le;
}
@Override
public byte[] SYD_SM4_LongData(int iKeyIndex, byte[] pcData, int iPkgNum, int iFlag) {
if (null == this.hsms || this.hsms.length < 1) {
throw new SydApiException(-1);
}
String keyIndex = String.format("%08d", iKeyIndex);
if ( Consts.ECB_ENC == iFlag ) {
return this.api4j.SYMEncryptData(
com.sunyard.SydApi.NALG_SM4,
"SK" + SYMUtil.genPrivateKeyMark("000000", "00A", keyIndex),
1,
pcData );
} else {
return this.api4j.SYMDecryptData(
com.sunyard.SydApi.NALG_SM4,
"SK" + SYMUtil.genPrivateKeyMark("000000", "00A", keyIndex),
1,
pcData );
}
}
SydApiException le = null;
for (SydApi4j api : this.hsms) {
try {
if (Consts.ECB_ENC == iFlag) {
return api.SYD_SM4_LongData(
8,
1, null,
"SK" + SYMUtil.genPrivateKeyMark("000000", "00A", keyIndex),
1,
pcData, iPkgNum);
} else {
return api.SYD_SM4_LongData(
9,
1, null,
"SK" + SYMUtil.genPrivateKeyMark("000000", "00A", keyIndex),
1,
pcData, iPkgNum);
}
@Override
public List<byte[]> SYD_SM4_BatchData(int[] iKeyIndex, List<byte[]> pcData, int iFlag) {
if ( null == this.api4j ) {
throw new SydApiException(-1);
} catch (SydApiException e) {
le = e;
if (e.getRetCode() < 0) {
continue;
}
throw e;
}
}
String[] keys = new String[ iKeyIndex.length ];
for ( int i = 0 ; i < iKeyIndex.length ; i++ ) {
keys[i] = "SK" + SYMUtil.genPrivateKeyMark("000000", "00A", String.format("%08d", iKeyIndex[i] ));
}
if ( Consts.ECB_ENC == iFlag ) {
return this.api4j.SYMEncryptDecryptBatchData(8, keys, 1, pcData);
} else {
return this.api4j.SYMEncryptDecryptBatchData(9, keys, 1, pcData);
}
}
@Override
public byte[] SYD_SM4_LongData(int iKeyIndex, byte[] pcData, int iPkgNum, int iFlag) {
return new byte[0];
throw le;
}
@Override
public String[] SYD_SM4Mac_BatchData(int[] iKeyIndex, List<byte[]> pcData) {
return new String[0];
if (null == this.hsms || this.hsms.length < 1) {
throw new SydApiException(-1);
}
String[] keys = new String[iKeyIndex.length];
for (int i = 0; i < iKeyIndex.length; i++) {
keys[i] = "SK" + SYMUtil.genPrivateKeyMark("000000", "00A", String.format("%08d", iKeyIndex[i]));
}
SydApiException le = null;
for (SydApi4j api : this.hsms) {
try {
List<byte[]> list = api.SYMEncryptDecryptBatchData(8, 2, null, keys, 1, pcData);
String[] ret = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
byte[] mac = new byte[16];
byte[] buff = list.get(i);
System.arraycopy(buff, buff.length - 16, mac, 0, 16);
ret[i] = Util.bytes2HexString(buff);
}
return ret;
} catch (SydApiException e) {
le = e;
if (e.getRetCode() < 0) {
continue;
}
throw e;
}
}
throw le;
}
@Override
public boolean[] SYD_SM4Mac_BatchData(int[] iKeyIndex, List<byte[]> pcData, String[] pcMac) {
return new boolean[0];
if (null == this.hsms || this.hsms.length < 1) {
throw new SydApiException(-1);
}
String[] keys = new String[iKeyIndex.length];
for (int i = 0; i < iKeyIndex.length; i++) {
keys[i] = "SK" + SYMUtil.genPrivateKeyMark("000000", "00A", String.format("%08d", iKeyIndex[i]));
}
SydApiException le = null;
for (SydApi4j api : this.hsms) {
try {
List<byte[]> list = api.SYMEncryptDecryptBatchData(8, 2, null, keys, 1, pcData);
boolean[] ret = new boolean[list.size()];
for (int i = 0; i < list.size(); i++) {
byte[] mac = new byte[16];
byte[] buff = list.get(i);
System.arraycopy(buff, buff.length - 16, mac, 0, 16);
ret[i] = pcMac[i].equals(Util.bytes2HexString(buff));
}
return ret;
} catch (SydApiException e) {
le = e;
if (e.getRetCode() < 0) {
continue;
}
throw e;
}
}
throw le;
}
@Override
public LongDataReturn<String, String> SYD_SM4Mac_LongData(int iKeyIndex, byte[] pcData, int iPkgNum, String pcProcData) {
return null;
if (null == this.hsms || this.hsms.length < 1) {
throw new SydApiException(-1);
}
String keyIndex = String.format("%08d", iKeyIndex);
byte[] iv = null;
// 仅一包 和 第一包 忽略 pcProcData 参数
if (Consts.PkgNumAll != iPkgNum && Consts.PkgNumHead != iPkgNum) {
iv = pcProcData.getBytes();
}
SydApiException le = null;
for (SydApi4j api : this.hsms) {
try {
byte[] ret = api.SYD_SM4_LongData(
8,
2, iv,
"SK" + SYMUtil.genPrivateKeyMark("000000", "00A", keyIndex),
1,
pcData, iPkgNum);
byte[] mac = new byte[16];
System.arraycopy(ret, ret.length - 16, mac, 0, 16);
// 仅一包 和 尾包 返回最终结果
if (Consts.PkgNumAll == iPkgNum || Consts.PkgNumTail == iPkgNum) {
return new LongDataReturn<>(null, Util.bytes2HexString(mac));
} else {
// 返回中间值
return new LongDataReturn<>(Util.bytes2HexString(mac), null);
}
} catch (SydApiException e) {
le = e;
if (e.getRetCode() < 0) {
continue;
}
throw e;
}
}
throw le;
}
@Override
public LongDataReturn<String, Boolean> SYD_SM4Mac_LongData(int iKeyIndex, byte[] pcData, int iPkgNum, String pcProcData, String pcMac) {
return null;
LongDataReturn<String, String> ret = SYD_SM4Mac_LongData(iKeyIndex, pcData, iPkgNum, pcProcData);
// 仅一包 和 尾包 返回最终结果
if (Consts.PkgNumAll == iPkgNum || Consts.PkgNumTail == iPkgNum) {
return new LongDataReturn<>(null, pcMac.equals(ret.getData()));
} else {
// 返回中间值
return new LongDataReturn<>(ret.getProcData(), false);
}
}
@Override
public String SYD_SM4Mac_ShortData(int iKeyIndex, byte[] pcData) {
return null;
if (null == this.hsms || this.hsms.length < 1) {
throw new SydApiException(-1);
}
String keyIndex = "SK" + SYMUtil.genPrivateKeyMark("000000", "00A", String.format("%08d", iKeyIndex));
SydApiException le = null;
for (SydApi4j api : this.hsms) {
try {
return api.SYD_SM4Mac_ShortData(keyIndex, pcData);
} catch (SydApiException e) {
le = e;
if (e.getRetCode() < 0) {
continue;
}
throw e;
}
}
throw le;
}
@Override
public boolean SYD_SM4Mac_ShortData(int iKeyIndex, byte[] pcData, String pcMac) {
return false;
if (null == this.hsms || this.hsms.length < 1) {
throw new SydApiException(-1);
}
if (null == pcMac) {
throw new IllegalArgumentException();
}
String mac = this.SYD_SM4Mac_ShortData(iKeyIndex, pcData);
return pcMac.equals(mac);
}
}
@@ -0,0 +1,65 @@
package com.sunyard.sge.database;
import com.sunyard.sge.database.pool.HsmLinkInfo;
import com.sunyard.sge.database.pool.SydApiPool;
import com.sunyard.sge.log.LogFactory;
import org.slf4j.Logger;
public class SydApiBuilder {
private SydApiPool pool;
public SydApiBuilder(
String[] pcIpList,
int[] iPortList,
int iConnectTimeOut,
int iDealTimeOut
) {
Logger log = LogFactory.getLogger();
log.debug("创建链接");
HsmLinkInfo[] linkInfo = HsmLinkInfo.mutiHsmLinkInfo(pcIpList, iPortList, iConnectTimeOut, iDealTimeOut);
this.pool = new SydApiPool(linkInfo);
warmUp( pcIpList, iPortList, iConnectTimeOut, iDealTimeOut );
}
public SydApi build() {
return pool.get();
}
private void warmUp(String[] pcIpList,
int[] iPortList,
int iConnectTimeOut,
int iDealTimeOut){
SydApi api = null;
try {
api = new SydApi4Database();
api.SYD_Connect_Ex( pcIpList, iPortList, iConnectTimeOut, iDealTimeOut );
try {
api.SYD_SM3_Hash_ShortData( new byte[8] );
}catch ( Exception e) {
// 忽略
}
try {
api.SYD_SM4_ShortData( 0 , new byte[16], Consts.ECB_ENC );
}catch ( Exception e) {
// 忽略
}
} catch ( Exception e ){
// 忽略预热失败
} finally {
if ( null != api ) {
api.SYD_Disconnect_Ex();
}
}
}
}
@@ -0,0 +1,17 @@
package com.sunyard.sge.database;
/**
* 日志配置接口
* */
public class SydApiConfig {
// 数据包长度
private final int MaxDataLenEachPack = 4064;
// 批量数据包,单包数据长度
// 加密
private final int MaxDataLenEachBatchPackEn = 1024;
// 解密
private final int MaxDataLenEachBatchPackDe = 1040;
}
@@ -1,24 +0,0 @@
package com.sunyard.sge.database;
/**
*
* 日志配置接口
* */
public interface SydConfigApi {
/**
* 设置日志相应的配置
*
*@param pcLogPath: 输入。日志存储路径
*@param iLogPathLen: 输入。日志路径长度。
*@param iLogLevel: 输入。日志级别设置 0:不记录日志,1:记录网络层错误日志,2:记录接口错误日志及网络层错误日志,3:记录正确日志及错误日志
*
* @return null
* */
static void SYD_SetLogConfig(
String pcLogPath,
int iLogPathLen,
int iLogLevel) {
}
}
@@ -0,0 +1,69 @@
package com.sunyard.sge.database.pool;
import com.sunyard.sge.log.LogFactory;
import org.slf4j.Logger;
/**
* 到加密机的链接信息
*/
public class HsmLinkInfo {
private String pcIp;
private int iPort;
private int iConnectTimeOut;
private int iDealTimeOut;
public HsmLinkInfo(String pcIp, int iPort, int iConnectTimeOut, int iDealTimeOut) {
this.pcIp = pcIp;
this.iPort = iPort;
this.iConnectTimeOut = iConnectTimeOut;
this.iDealTimeOut = iDealTimeOut;
}
public static HsmLinkInfo[] mutiHsmLinkInfo(String[] pcIpList, int[] iPortList, int iConnectTimeOut, int iAllDealTimeOut) {
Logger log = LogFactory.getLogger();
log.debug("链接参数整理");
if (null == pcIpList &&
null == iPortList &&
pcIpList.length != iPortList.length) {
log.error("加密机配置 ip 和 port 数量错误");
throw new IllegalArgumentException("入参错误");
}
if ( iAllDealTimeOut < pcIpList.length) {
log.error("加密机配置交易时间过短");
throw new IllegalArgumentException("入参错误");
}
// 交易时间进行处理
int iDealTimeOut = iAllDealTimeOut / pcIpList.length;
HsmLinkInfo[]hsms = new HsmLinkInfo[ pcIpList.length ];
for ( int i = 0 ; i < pcIpList.length ; i++ ) {
hsms[ i ] = new HsmLinkInfo( pcIpList[i], iPortList[i], iConnectTimeOut, iDealTimeOut );
}
return hsms;
}
public String getPcIp() {
return pcIp;
}
public int getiPort() {
return iPort;
}
public int getiConnectTimeOut() {
return iConnectTimeOut;
}
public int getiDealTimeOut() {
return iDealTimeOut;
}
}
@@ -0,0 +1,51 @@
package com.sunyard.sge.database.pool;
import com.sunyard.sge.database.SydApi;
import com.sunyard.sge.pool.ThreadBasedConnectPool;
import racal.sunyard.main.SydApi4j;
public class SydApiPool extends ThreadBasedConnectPool<SydApi> {
private HsmLinkInfo[] linkInfos;
public SydApiPool(HsmLinkInfo[] linkInfos) {
super();
this.linkInfos = linkInfos;
}
// 继承 初始化
protected SydApi initialValue() {
// 所有加密机一次性链接
SydApi4j[] apis = new SydApi4j[ linkInfos.length ];
// 只有所有都不好,才报错。
boolean connected = false;
for ( int i = 0; i < apis.length; i ++ ) {
HsmLinkInfo info = linkInfos[i];
try {
apis[ i ] = (SydApi4j) new SydApi4j().connect(info.getPcIp(), info.getiPort(),
null,
info.getiConnectTimeOut(),
info.getiDealTimeOut()
);
connected = true;
} catch ( Exception e ) {
// 忽略单个错误
}
}
return null;
}
// 保活接口
protected boolean check(SydApi o) {
return null != o;
}
// 释放
protected void free(SydApi o) {
}
}
@@ -0,0 +1,115 @@
package com.sunyard.sge.log;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.FileAppender;
import org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy;
import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
import org.apache.logging.log4j.core.config.AppenderRef;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 金交所定制日志
*/
public class LogFactory {
// 金交所定制日志
public static final String logName = "sge-hsm-sydapi-log";
// 日志级别
public static final int LogLevelOFF = 0;
public static final int LogLevelError = 1;
public static final int LogLevelInfo = 2;
public static final int LogLevelDebug = 3;
public static int iLogLevel = LogLevelDebug;
// Levels
public static final Level[] levels = new Level[]{ Level.OFF, Level.ERROR, Level.INFO, Level.DEBUG };
// 日志目录
public static String pcLogPath = "./sydapi-logs/";
// 日期格式
private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
private LogFactory() {
}
public static void start() {
// 上下文
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();
// 创建一个展示的样式
Layout layout = PatternLayout.createLayout(
"[%level{DEBUG=3, INFO=2, ERROR=1, OFF=0}: %d{ISO8601} <%thread>] %message%n%throwable%n",
null,
config, null, null, true, false, null, null);
TriggeringPolicy tp = SizeBasedTriggeringPolicy.createPolicy("10MB");
// Appender appender = RollingFileAppender.createAppender(String.format("logs/test/syncshows-job-%s.log", jobID),
// "/logs/test/" + jobID + "/syncshows-job-" + jobID + ".log.gz",
// "true", jobID, null, null, null, tp, null, layout, null,
// null, null, null, config);
// 日志打印方式——输出为文件   
Appender appender = FileAppender.createAppender(
String.format( pcLogPath + getToday() + ".log"),
"true", "false",
logName, null, "true", "true", null, layout, null, null, null, config);
appender.start();
config.addAppender(appender);
AppenderRef ref = AppenderRef.createAppenderRef( logName, levels[ iLogLevel ], null);
AppenderRef[] refs = new AppenderRef[]{ref};
LoggerConfig loggerConfig = LoggerConfig.createLogger("false", levels[ iLogLevel ], logName,
"true", refs, null, config, null);
loggerConfig.addAppender(appender, levels[ iLogLevel ], null);
config.addLogger( logName, loggerConfig);
ctx.updateLoggers();
}
public static void stop() {
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();
config.getAppender( logName ).stop();
config.getLoggerConfig(logName).removeAppender( logName);
config.removeLogger(logName);
ctx.updateLoggers();
}
public static String getToday(){
return format.format( new Date());
}
/**
* 创建 Logger
* @return Logger
*/
public static Logger createLogger() {
start();
return LoggerFactory.getLogger( logName );
}
/**
* 获取 Logger
* @return Logger
*/
public static Logger getLogger() {
return LoggerFactory.getLogger( logName );
}
}
@@ -0,0 +1,24 @@
package com.sunyard.sge.pool;
public class ObjectInPool<T> {
private T object;
private long lasUseAt = System.currentTimeMillis();
public ObjectInPool(T object) {
this.object = object;
}
public T getObjectForCheck() {
return object;
}
public T getObject() {
this.lasUseAt = System.currentTimeMillis();
return object;
}
public long getLasUseAt() {
return lasUseAt;
}
}
@@ -0,0 +1,26 @@
package com.sunyard.sge.pool;
public class PoolConfig {
// 最大空闲时间
private long maxIdle = 5 * 3600 * 1000; // 5 分钟
// 最大无用时间
private long maxUseless = 30 * 3600 * 1000; // 30 分钟
public long getMaxIdle() {
return maxIdle;
}
public void setMaxIdle(long maxIdle) {
this.maxIdle = maxIdle;
}
public long getMaxUseless() {
return maxUseless;
}
public void setMaxUseless(long maxUseless) {
this.maxUseless = maxUseless;
}
}
@@ -0,0 +1,128 @@
package com.sunyard.sge.pool;
import com.sunyard.sge.log.LogFactory;
import org.slf4j.Logger;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadBasedConnectPool<T> {
// ThreadLocal
private final Map<Thread, ObjectInPool<T>> map = new HashMap<>();
// 守护
private final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(1);
// 配置
private PoolConfig config;
public ThreadBasedConnectPool(PoolConfig config) {
this.config = config;
threadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
Logger log = LogFactory.getLogger();
log.debug("连接池检测进程开始执行");
log.debug("共有链接 {} 个", map.size());
// 检测和回收逻辑
Iterator<Map.Entry<Thread, ObjectInPool<T>>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Thread, ObjectInPool<T>> entry = it.next();
ObjectInPool<T> oip = entry.getValue();
if (System.currentTimeMillis() - oip.getLasUseAt() < config.getMaxIdle()) {
// 空闲时间不足,免检。
continue;
}
if (System.currentTimeMillis() - oip.getLasUseAt() > config.getMaxUseless()) {
// 长时间未使用,回收链接
log.debug("回收一个链接");
it.remove();
try {
free(oip.getObject());
} catch (Exception e) {
}
continue;
}
boolean checkRet = false;
try {
checkRet = check(entry.getValue().getObject());
} catch (Exception e) {
checkRet = false;
}
if (checkRet) {
log.debug("一个链接检查未通过");
// 检查未通过
it.remove();
try {
free(oip.getObject());
} catch (Exception e) {
}
continue;
}
}
log.debug("连接池检测进程执行结束");
}
}, config.getMaxIdle(), config.getMaxIdle(), TimeUnit.MILLISECONDS);
}
public ThreadBasedConnectPool() {
this(new PoolConfig());
}
// 继承 初始化
protected T initialValue() {
return null;
}
// 保活接口
protected boolean check(T o) {
return null != o;
}
// 释放
protected void free(T o) {
}
// 获取
public T get() {
ObjectInPool<T> o = map.get(Thread.currentThread());
if (null != o) {
return o.getObject();
}
return setInitialValue();
}
// 设置
public void set(T o) {
map.put(Thread.currentThread(), new ObjectInPool<>(o));
}
// 清除
public void remove() {
map.remove(Thread.currentThread());
}
private T setInitialValue() {
T value = initialValue();
map.put(Thread.currentThread(), new ObjectInPool<>(value));
return value;
}
}