forked from fanruan/demo-tabledata-redis
richie
6 years ago
35 changed files with 1044 additions and 186 deletions
@ -0,0 +1,52 @@ |
|||||||
|
package com.fr.plugin.db.redis; |
||||||
|
|
||||||
|
import com.fr.base.TableData; |
||||||
|
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; |
||||||
|
import com.fr.design.fun.ServerTableDataDefineProvider; |
||||||
|
import com.fr.design.fun.impl.AbstractTableDataDefineProvider; |
||||||
|
import com.fr.locale.InterProviderFactory; |
||||||
|
import com.fr.plugin.db.redis.core.RedisScriptTableData; |
||||||
|
import com.fr.plugin.db.redis.ui.RedisScriptTableDataPane; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-03-18 |
||||||
|
*/ |
||||||
|
public class RedisScriptTableDataDefine extends AbstractTableDataDefineProvider implements ServerTableDataDefineProvider { |
||||||
|
|
||||||
|
@Override |
||||||
|
public int currentAPILevel() { |
||||||
|
return CURRENT_LEVEL; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<? extends TableData> classForTableData() { |
||||||
|
return RedisScriptTableData.class; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<? extends TableData> classForInitTableData() { |
||||||
|
return RedisScriptTableData.class; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<? extends AbstractTableDataPane> appearanceForTableData() { |
||||||
|
return RedisScriptTableDataPane.class; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String nameForTableData() { |
||||||
|
return InterProviderFactory.getProvider().getLocText("Plugin-Redis_Script_Table_Data"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String prefixForTableData() { |
||||||
|
return "redis"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String iconPathForTableData() { |
||||||
|
return "/com/fr/plugin/db/redis/images/redis.png"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,75 @@ |
|||||||
|
package com.fr.plugin.db.redis.core; |
||||||
|
|
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.third.redis.clients.jedis.Jedis; |
||||||
|
import com.fr.third.redis.clients.jedis.JedisPool; |
||||||
|
import com.fr.third.redis.clients.jedis.JedisPoolConfig; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-03-18 |
||||||
|
*/ |
||||||
|
public class RedisPool { |
||||||
|
|
||||||
|
private static final int TIME_OUT = 100 * 1000; |
||||||
|
|
||||||
|
private static RedisPool pool = new RedisPool(); |
||||||
|
|
||||||
|
public static RedisPool getPool() { |
||||||
|
return pool; |
||||||
|
} |
||||||
|
|
||||||
|
private Map<String, JedisPool> jedisPoolMap = new ConcurrentHashMap<String, JedisPool>(); |
||||||
|
|
||||||
|
public Jedis getResource(String host, int port, String password, int maxTotal) { |
||||||
|
JedisPool jedisPool = jedisPoolMap.get(host); |
||||||
|
if (jedisPool == null) { |
||||||
|
jedisPool = createJedisPool(host, port, password, maxTotal); |
||||||
|
jedisPoolMap.put(host, jedisPool); |
||||||
|
} |
||||||
|
return jedisPool.getResource(); |
||||||
|
} |
||||||
|
|
||||||
|
private JedisPool createJedisPool(String host, int port, String password, int maxTotal) { |
||||||
|
JedisPoolConfig config = new JedisPoolConfig(); |
||||||
|
config.setMaxTotal(maxTotal); |
||||||
|
//连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
|
||||||
|
config.setBlockWhenExhausted(true); |
||||||
|
//设置的逐出策略类名, 默认DefaultEvictionPolicy(当连接超过最大空闲时间,或连接数超过最大空闲连接数)
|
||||||
|
config.setEvictionPolicyClassName("com.fr.third.org.apache.commons.pool2.impl.DefaultEvictionPolicy"); |
||||||
|
//是否启用pool的jmx管理功能, 默认true
|
||||||
|
config.setJmxEnabled(true); |
||||||
|
//MBean ObjectName = new ObjectName("org.apache.commons.pool2:type=GenericObjectPool,name=" + "pool" + i); 默认为"pool", JMX不熟,具体不知道是干啥的...默认就好.
|
||||||
|
config.setJmxNamePrefix("pool"); |
||||||
|
//是否启用后进先出, 默认true
|
||||||
|
config.setLifo(true); |
||||||
|
//最大空闲连接数
|
||||||
|
config.setMaxIdle(10); |
||||||
|
//最大连接数,可配置
|
||||||
|
//获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1
|
||||||
|
config.setMaxWaitMillis(-1); |
||||||
|
//逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
|
||||||
|
config.setMinEvictableIdleTimeMillis(1800000); |
||||||
|
//最小空闲连接数, 默认0
|
||||||
|
config.setMinIdle(0); |
||||||
|
//每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3
|
||||||
|
config.setNumTestsPerEvictionRun(3); |
||||||
|
//对象空闲多久后逐出, 当空闲时间>该值 且 空闲连接>最大空闲数 时直接逐出,不再根据MinEvictableIdleTimeMillis判断 (默认逐出策略)
|
||||||
|
config.setSoftMinEvictableIdleTimeMillis(1800000); |
||||||
|
//在获取连接的时候检查有效性, 默认false
|
||||||
|
config.setTestOnBorrow(false); |
||||||
|
//在空闲时检查有效性, 默认false
|
||||||
|
config.setTestWhileIdle(false); |
||||||
|
//逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
|
||||||
|
config.setTimeBetweenEvictionRunsMillis(-1); |
||||||
|
if (StringUtils.isNotBlank(password)) { |
||||||
|
return new JedisPool(config, host, port, TIME_OUT, password); |
||||||
|
} else { |
||||||
|
return new JedisPool(config, host, port, TIME_OUT); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,144 @@ |
|||||||
|
package com.fr.plugin.db.redis.core; |
||||||
|
|
||||||
|
import com.fr.base.Parameter; |
||||||
|
import com.fr.base.TableData; |
||||||
|
import com.fr.config.holder.Conf; |
||||||
|
import com.fr.config.holder.factory.Holders; |
||||||
|
import com.fr.config.holder.factory.XmlHolders; |
||||||
|
import com.fr.data.AbstractParameterTableData; |
||||||
|
import com.fr.data.core.DataCoreXmlUtils; |
||||||
|
import com.fr.data.impl.Connection; |
||||||
|
import com.fr.data.impl.NameDatabaseConnection; |
||||||
|
import com.fr.file.DatasourceManager; |
||||||
|
import com.fr.general.data.DataModel; |
||||||
|
import com.fr.general.xml.GeneralXMLTools; |
||||||
|
import com.fr.intelli.record.Focus; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.plugin.db.redis.core.order.OrderValue; |
||||||
|
import com.fr.plugin.db.redis.core.order.impl.NumberOrderValue; |
||||||
|
import com.fr.plugin.db.redis.util.RedisUtils; |
||||||
|
import com.fr.record.analyzer.EnableMetrics; |
||||||
|
import com.fr.script.Calculator; |
||||||
|
import com.fr.stable.ParameterProvider; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.xml.XMLPrintWriter; |
||||||
|
import com.fr.stable.xml.XMLableReader; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-03-18 |
||||||
|
*/ |
||||||
|
@EnableMetrics |
||||||
|
public class RedisScriptTableData extends AbstractParameterTableData { |
||||||
|
|
||||||
|
private static final long serialVersionUID = 1525853354993816818L; |
||||||
|
|
||||||
|
private Conf<Connection> database = Holders.obj(null, Connection.class); |
||||||
|
private Conf<OrderValue> dbIndex = XmlHolders.obj(new NumberOrderValue(0), OrderValue.class, OrderValue.XML_TAG); |
||||||
|
private Conf<String> script = Holders.simple(StringUtils.EMPTY); |
||||||
|
|
||||||
|
public void setDatabase(Connection c) { |
||||||
|
this.database.set(c); |
||||||
|
} |
||||||
|
|
||||||
|
public Connection getDatabase() { |
||||||
|
return database.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public OrderValue getOrderValue() { |
||||||
|
return dbIndex.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setOrderValue(OrderValue dbIndex) { |
||||||
|
this.dbIndex.set(dbIndex); |
||||||
|
} |
||||||
|
|
||||||
|
public String getScript() { |
||||||
|
return script.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setScript(String script) { |
||||||
|
this.script.set(script); |
||||||
|
} |
||||||
|
|
||||||
|
public void setParameters(ParameterProvider[] providers) { |
||||||
|
super.setDefaultParameters(providers); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public DataModel createDataModel(Calculator calculator) { |
||||||
|
return createDataModel(calculator, TableData.RESULT_ALL); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
@Focus(id = RedisConstants.PLUGIN_ID, text = "Plugin-Redis_Script_Table_Data") |
||||||
|
public DataModel createDataModel(Calculator calculator, int rowCount) { |
||||||
|
long start = System.currentTimeMillis(); |
||||||
|
Parameter[] ps = Parameter.providers2Parameter(getParameters(calculator)); |
||||||
|
Connection connection = database.get(); |
||||||
|
if (connection instanceof NameDatabaseConnection) { |
||||||
|
String name = ((NameDatabaseConnection) connection).getName(); |
||||||
|
RedisDatabaseConnection rc = DatasourceManager.getProviderInstance().getConnection(name, RedisDatabaseConnection.class); |
||||||
|
if (rc != null) { |
||||||
|
OrderValue orderValue = dbIndex.get(); |
||||||
|
DataModel model = new RedisScriptTableDataModel(rc, |
||||||
|
orderValue == null ? 0 : orderValue.toIndex(calculator, ps), |
||||||
|
RedisUtils.calculateQuery(script.get(), ps), |
||||||
|
rowCount); |
||||||
|
FineLoggerFactory.getLogger().info("Build data model spend time {} ms.", System.currentTimeMillis() - start); |
||||||
|
return model; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public void readXML(XMLableReader reader) { |
||||||
|
super.readXML(reader); |
||||||
|
|
||||||
|
if (reader.isChildNode()) { |
||||||
|
String tmpName = reader.getTagName(); |
||||||
|
String tmpVal; |
||||||
|
|
||||||
|
if (OrderValue.XML_TAG.equals(tmpName)) { |
||||||
|
OrderValue orderValue = (OrderValue) GeneralXMLTools.readXMLable(reader); |
||||||
|
if (orderValue != null) { |
||||||
|
setOrderValue(orderValue); |
||||||
|
} |
||||||
|
} else if (com.fr.data.impl.Connection.XML_TAG.equals(tmpName)) { |
||||||
|
if (reader.getAttrAsString("class", null) != null) { |
||||||
|
com.fr.data.impl.Connection con = DataCoreXmlUtils.readXMLConnection(reader); |
||||||
|
this.setDatabase(con); |
||||||
|
} |
||||||
|
} else if ("Script".equals(tmpName)) { |
||||||
|
tmpVal = reader.getElementValue(); |
||||||
|
if (isNotNullValue(tmpVal)) { |
||||||
|
this.setScript(tmpVal); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void writeXML(XMLPrintWriter writer) { |
||||||
|
super.writeXML(writer); |
||||||
|
GeneralXMLTools.writeXMLable(writer, dbIndex.get(), OrderValue.XML_TAG); |
||||||
|
if (this.database.get() != null) { |
||||||
|
DataCoreXmlUtils.writeXMLConnection(writer, this.database.get()); |
||||||
|
} |
||||||
|
writer.startTAG("Script").textNode(getScript()).end(); |
||||||
|
} |
||||||
|
|
||||||
|
private boolean isNotNullValue(String value) { |
||||||
|
return value != null && !"null".equals(value); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object clone() throws CloneNotSupportedException { |
||||||
|
RedisScriptTableData cloned = (RedisScriptTableData) super.clone(); |
||||||
|
cloned.database = (Conf<Connection>) database.clone(); |
||||||
|
cloned.script = (Conf<String>) script.clone(); |
||||||
|
cloned.dbIndex = (Conf<OrderValue>) dbIndex.clone(); |
||||||
|
return cloned; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,141 @@ |
|||||||
|
package com.fr.plugin.db.redis.core; |
||||||
|
|
||||||
|
import com.eclipsesource.v8.V8; |
||||||
|
import com.eclipsesource.v8.V8Array; |
||||||
|
import com.eclipsesource.v8.V8Object; |
||||||
|
import com.fr.data.AbstractDataModel; |
||||||
|
import com.fr.plugin.db.redis.help.Console; |
||||||
|
import com.fr.plugin.db.redis.help.Files; |
||||||
|
import com.fr.plugin.db.redis.help.RedisClient; |
||||||
|
import com.fr.plugin.db.redis.util.RedisUtils; |
||||||
|
import com.fr.third.redis.clients.jedis.Jedis; |
||||||
|
|
||||||
|
import java.lang.reflect.Method; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-03-18 |
||||||
|
*/ |
||||||
|
public class RedisScriptTableDataModel extends AbstractDataModel { |
||||||
|
|
||||||
|
private RedisDatabaseConnection mc; |
||||||
|
private String script; |
||||||
|
private int dbIndex; |
||||||
|
private int rowCount; |
||||||
|
private List<List<Object>> data = new ArrayList<List<Object>>(); |
||||||
|
private String[] columnNames = null; |
||||||
|
|
||||||
|
public RedisScriptTableDataModel(RedisDatabaseConnection mc, int dbIndex, String script, int rowCount) { |
||||||
|
this.mc = mc; |
||||||
|
this.script = script; |
||||||
|
this.dbIndex = dbIndex; |
||||||
|
this.rowCount = rowCount; |
||||||
|
} |
||||||
|
|
||||||
|
private void buildData() { |
||||||
|
if (columnNames != null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
Jedis jedis = mc.createRedisClient(); |
||||||
|
jedis.select(dbIndex); |
||||||
|
V8 v8 = V8.createV8Runtime(); |
||||||
|
RedisClient client = new RedisClient(v8, jedis); |
||||||
|
V8Object v8Console = initConsole(v8); |
||||||
|
V8Object v8Require = initRequire(v8); |
||||||
|
V8Object v8Client = initRedis(v8, client); |
||||||
|
|
||||||
|
v8.executeVoidScript( |
||||||
|
"function unique(array) {return Array.from(new Set(array));};" + |
||||||
|
"function merge(table, column) {return {content:table, column:column}};"); |
||||||
|
|
||||||
|
V8Object returnObj = v8.executeObjectScript(String.format("(function(){%s})();", script)); |
||||||
|
|
||||||
|
V8Array v8Column = returnObj.getArray("column"); |
||||||
|
V8Array v8Table = returnObj.getArray("content"); |
||||||
|
int columnCount = v8Column.length(); |
||||||
|
columnNames = new String[columnCount]; |
||||||
|
for (int i = 0; i < columnCount; i++) { |
||||||
|
columnNames[i] = String.valueOf(v8Column.get(i)); |
||||||
|
} |
||||||
|
int returnRowCount = v8Table.length(); |
||||||
|
for (int i = 0, realCount = Math.min(returnRowCount, this.rowCount); i < realCount; i++) { |
||||||
|
V8Array v8Row = v8Table.getArray(i); |
||||||
|
List<Object> row = new ArrayList<Object>(); |
||||||
|
for (int j = 0, col = v8Row.length(); j < col; j++) { |
||||||
|
row.add(v8Row.get(j)); |
||||||
|
} |
||||||
|
v8Row.release(); |
||||||
|
data.add(row); |
||||||
|
} |
||||||
|
jedis.close(); |
||||||
|
v8Table.release(); |
||||||
|
v8Column.release(); |
||||||
|
returnObj.release(); |
||||||
|
v8Client.release(); |
||||||
|
v8Require.release(); |
||||||
|
v8Console.release(); |
||||||
|
|
||||||
|
v8.release(true); |
||||||
|
} |
||||||
|
|
||||||
|
private V8Object initConsole(V8 v8) { |
||||||
|
V8Object v8Console = new V8Object(v8); |
||||||
|
v8.add("console", v8Console); |
||||||
|
Console console = new Console(v8); |
||||||
|
RedisUtils.registerJavaMethods(v8Console, console); |
||||||
|
return v8Console; |
||||||
|
} |
||||||
|
|
||||||
|
private V8Object initRequire(V8 v8) { |
||||||
|
V8Object v8Files = new V8Object(v8); |
||||||
|
v8.add("Files", v8Files); |
||||||
|
Files console = new Files(v8); |
||||||
|
RedisUtils.registerJavaMethods(v8Files, console); |
||||||
|
return v8Files; |
||||||
|
} |
||||||
|
|
||||||
|
private V8Object initRedis(final V8 v8, final RedisClient client) { |
||||||
|
V8Object v8Client = new V8Object(v8); |
||||||
|
v8.add("redis", v8Client); |
||||||
|
RedisUtils.registerJavaMethods(v8Client, client); |
||||||
|
return v8Client; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getColumnCount() { |
||||||
|
buildData(); |
||||||
|
return columnNames == null ? 0 : columnNames.length; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getColumnName(int i) { |
||||||
|
buildData(); |
||||||
|
return columnNames == null ? null : columnNames[i]; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getRowCount() { |
||||||
|
buildData(); |
||||||
|
return data.size(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getValueAt(int rowIndex, int columnIndex) { |
||||||
|
buildData(); |
||||||
|
if (data != null && data.size() > rowIndex) { |
||||||
|
List<Object> rowData = data.get(rowIndex); |
||||||
|
if (rowData != null && rowData.size() > columnIndex) { |
||||||
|
return rowData.get(columnIndex); |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void release() throws Exception { |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package com.fr.plugin.db.redis.help; |
||||||
|
|
||||||
|
import com.eclipsesource.v8.V8; |
||||||
|
import com.fr.general.IOUtils; |
||||||
|
import com.fr.io.utils.ResourceIOUtils; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.stable.EncodeConstants; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.FileInputStream; |
||||||
|
import java.io.FileNotFoundException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.UnsupportedEncodingException; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-03-18 |
||||||
|
*/ |
||||||
|
public class Console { |
||||||
|
|
||||||
|
private V8 v8; |
||||||
|
|
||||||
|
public Console(V8 v8) { |
||||||
|
this.v8 = v8; |
||||||
|
} |
||||||
|
|
||||||
|
public void log(Object message) { |
||||||
|
FineLoggerFactory.getLogger().info(message == null ? null : message.toString()); |
||||||
|
} |
||||||
|
|
||||||
|
public void error(Object message) { |
||||||
|
FineLoggerFactory.getLogger().error(message == null ? null : message.toString()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package com.fr.plugin.db.redis.help; |
||||||
|
|
||||||
|
import com.eclipsesource.v8.V8; |
||||||
|
import com.fr.general.IOUtils; |
||||||
|
import com.fr.io.utils.ResourceIOUtils; |
||||||
|
import com.fr.stable.EncodeConstants; |
||||||
|
|
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.UnsupportedEncodingException; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-03-19 |
||||||
|
*/ |
||||||
|
public class Files { |
||||||
|
|
||||||
|
private V8 v8; |
||||||
|
|
||||||
|
public Files(V8 v8) { |
||||||
|
this.v8 = v8; |
||||||
|
} |
||||||
|
|
||||||
|
public void require(String filePath) { |
||||||
|
InputStream in = ResourceIOUtils.read(filePath); |
||||||
|
if (in != null) { |
||||||
|
try { |
||||||
|
v8.executeVoidScript(IOUtils.inputStream2String(in, EncodeConstants.ENCODING_UTF_8)); |
||||||
|
} catch (UnsupportedEncodingException ignore) { |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,102 @@ |
|||||||
|
package com.fr.plugin.db.redis.help; |
||||||
|
|
||||||
|
import com.eclipsesource.v8.V8; |
||||||
|
import com.eclipsesource.v8.V8Array; |
||||||
|
import com.eclipsesource.v8.V8Object; |
||||||
|
import com.eclipsesource.v8.utils.V8ObjectUtils; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.third.redis.clients.jedis.Jedis; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-03-18 |
||||||
|
*/ |
||||||
|
public class RedisClient { |
||||||
|
|
||||||
|
private Jedis jedis; |
||||||
|
private V8 v8; |
||||||
|
|
||||||
|
public RedisClient(V8 v8, Jedis jedis) { |
||||||
|
this.jedis = jedis; |
||||||
|
this.v8 = v8; |
||||||
|
} |
||||||
|
|
||||||
|
public String get(String key) { |
||||||
|
long start = System.currentTimeMillis(); |
||||||
|
try { |
||||||
|
return jedis.get(key); |
||||||
|
} finally { |
||||||
|
FineLoggerFactory.getLogger().info("Fetch data from redis spend time {} ms.", System.currentTimeMillis() - start); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public String hget(String key, String field) { |
||||||
|
long start = System.currentTimeMillis(); |
||||||
|
try { |
||||||
|
return jedis.hget(key, field); |
||||||
|
} finally { |
||||||
|
FineLoggerFactory.getLogger().info("Fetch data from redis spend time {} ms.", System.currentTimeMillis() - start); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public V8Array hkeys(String key) { |
||||||
|
long start = System.currentTimeMillis(); |
||||||
|
Set<String> set = jedis.keys(key); |
||||||
|
FineLoggerFactory.getLogger().info("Fetch data from redis spend time {} ms.", System.currentTimeMillis() - start); |
||||||
|
return V8ObjectUtils.toV8Array(v8, new ArrayList<String>(set)); |
||||||
|
} |
||||||
|
|
||||||
|
public V8Array hmget(String key, String... fields) { |
||||||
|
long start = System.currentTimeMillis(); |
||||||
|
List<String> list = jedis.hmget(key, fields); |
||||||
|
FineLoggerFactory.getLogger().info("Fetch data from redis spend time {} ms.", System.currentTimeMillis() - start); |
||||||
|
return V8ObjectUtils.toV8Array(v8, list); |
||||||
|
} |
||||||
|
|
||||||
|
public V8Object hgetAll(String key) { |
||||||
|
long start = System.currentTimeMillis(); |
||||||
|
Map<String, String> map = jedis.hgetAll(key); |
||||||
|
FineLoggerFactory.getLogger().info("Fetch data from redis spend time {} ms.", System.currentTimeMillis() - start); |
||||||
|
return V8ObjectUtils.toV8Object(v8, map); |
||||||
|
} |
||||||
|
|
||||||
|
public V8Array keys(String pattern) { |
||||||
|
long start = System.currentTimeMillis(); |
||||||
|
Set<String> set = jedis.keys(pattern); |
||||||
|
FineLoggerFactory.getLogger().info("Fetch data from redis spend time {} ms.", System.currentTimeMillis() - start); |
||||||
|
return V8ObjectUtils.toV8Array(v8, new ArrayList<String>(set)); |
||||||
|
} |
||||||
|
|
||||||
|
public V8Array lrange(String key, long start, long end) { |
||||||
|
long start0 = System.currentTimeMillis(); |
||||||
|
List<String> list = jedis.lrange(key, start, end); |
||||||
|
FineLoggerFactory.getLogger().info("Fetch data from redis spend time {} ms.", System.currentTimeMillis() - start0); |
||||||
|
return V8ObjectUtils.toV8Array(v8, list); |
||||||
|
} |
||||||
|
|
||||||
|
public V8Array mget(V8Array keys) { |
||||||
|
long start = System.currentTimeMillis(); |
||||||
|
int len = keys.length(); |
||||||
|
String[] parameters = new String[len]; |
||||||
|
for (int i = 0; i < len; i ++) { |
||||||
|
parameters[i] = keys.getString(i); |
||||||
|
} |
||||||
|
List<String> list = jedis.mget(parameters); |
||||||
|
FineLoggerFactory.getLogger().info("Fetch data from redis spend time {} ms.", System.currentTimeMillis() - start); |
||||||
|
keys.release(); |
||||||
|
return V8ObjectUtils.toV8Array(v8, list); |
||||||
|
} |
||||||
|
|
||||||
|
public V8Array smembers(String key) { |
||||||
|
long start = System.currentTimeMillis(); |
||||||
|
Set<String> set = jedis.smembers(key); |
||||||
|
FineLoggerFactory.getLogger().info("Fetch data from redis spend time {} ms.", System.currentTimeMillis() - start); |
||||||
|
return V8ObjectUtils.toV8Array(v8, new ArrayList<String>(set)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,164 @@ |
|||||||
|
package com.fr.plugin.db.redis.ui; |
||||||
|
|
||||||
|
import com.fr.base.BaseUtils; |
||||||
|
import com.fr.base.ParameterHelper; |
||||||
|
import com.fr.base.TableData; |
||||||
|
import com.fr.design.actions.UpdateAction; |
||||||
|
import com.fr.design.data.datapane.preview.PreviewTablePane; |
||||||
|
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; |
||||||
|
import com.fr.design.gui.itableeditorpane.ParameterTableModel; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableEditAction; |
||||||
|
import com.fr.design.gui.itableeditorpane.UITableEditorPane; |
||||||
|
import com.fr.design.gui.itoolbar.UIToolbar; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.menu.ToolBarDef; |
||||||
|
import com.fr.plugin.db.redis.core.order.OrderValue; |
||||||
|
import com.fr.stable.ArrayUtils; |
||||||
|
import com.fr.stable.ParameterProvider; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import java.awt.*; |
||||||
|
import java.awt.event.ActionEvent; |
||||||
|
import java.util.ArrayList; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-03-18 |
||||||
|
*/ |
||||||
|
public abstract class RedisBaseTableDataPane<T extends TableData> extends AbstractTableDataPane<T> { |
||||||
|
|
||||||
|
private static final String PREVIEW_BUTTON = Toolkit.i18nText("Plugin-Redis_Preview"); |
||||||
|
private static final String REFRESH_BUTTON = Toolkit.i18nText("Plugin-Redis_Refresh"); |
||||||
|
|
||||||
|
protected RedisDBConnectionChosePane chosePane; |
||||||
|
|
||||||
|
protected UITableEditorPane<ParameterProvider> editorPane; |
||||||
|
|
||||||
|
|
||||||
|
public RedisBaseTableDataPane() { |
||||||
|
this.setLayout(new BorderLayout(4, 4)); |
||||||
|
|
||||||
|
Box box = new Box(BoxLayout.Y_AXIS); |
||||||
|
|
||||||
|
JPanel northPane = new JPanel(new BorderLayout(4, 4)); |
||||||
|
JToolBar editToolBar = createToolBar(); |
||||||
|
northPane.add(editToolBar, BorderLayout.CENTER); |
||||||
|
northPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 6, 0)); |
||||||
|
|
||||||
|
|
||||||
|
ParameterTableModel model = new ParameterTableModel() { |
||||||
|
@Override |
||||||
|
public UITableEditAction[] createAction() { |
||||||
|
return ArrayUtils.add(super.createDBTableAction(), new RedisBaseTableDataPane.RefreshAction()); |
||||||
|
} |
||||||
|
}; |
||||||
|
editorPane = new UITableEditorPane<ParameterProvider>(model); |
||||||
|
|
||||||
|
box.add(northPane); |
||||||
|
|
||||||
|
box.add(createQueryPane()); |
||||||
|
|
||||||
|
box.add(editorPane); |
||||||
|
|
||||||
|
JPanel sqlSplitPane = new JPanel(new BorderLayout(4, 4)); |
||||||
|
sqlSplitPane.add(box, BorderLayout.CENTER); |
||||||
|
|
||||||
|
chosePane = new RedisDBConnectionChosePane(); |
||||||
|
chosePane.setPreferredSize(new Dimension(200, 200)); |
||||||
|
sqlSplitPane.add(chosePane, BorderLayout.WEST); |
||||||
|
|
||||||
|
this.add(sqlSplitPane, BorderLayout.CENTER); |
||||||
|
} |
||||||
|
|
||||||
|
private JToolBar createToolBar() { |
||||||
|
ToolBarDef toolBarDef = new ToolBarDef(); |
||||||
|
toolBarDef.addShortCut(new RedisBaseTableDataPane.PreviewAction()); |
||||||
|
UIToolbar editToolBar = ToolBarDef.createJToolBar(); |
||||||
|
toolBarDef.updateToolBar(editToolBar); |
||||||
|
return editToolBar; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return Toolkit.i18nText("Plugin-Redis_Query"); |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract JComponent createQueryPane(); |
||||||
|
|
||||||
|
protected abstract String[] paramTexts(); |
||||||
|
|
||||||
|
public abstract OrderValue getOrderValue(); |
||||||
|
|
||||||
|
|
||||||
|
private void refresh() { |
||||||
|
String[] paramTexts = paramTexts(); |
||||||
|
|
||||||
|
ParameterProvider[] parameters = ParameterHelper.analyze4Parameters(paramTexts, false); |
||||||
|
|
||||||
|
ParameterProvider[] providers = getOrderValue().analyze4Parameters(); |
||||||
|
|
||||||
|
editorPane.populate(ArrayUtils.addAll(parameters, providers)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void checkParameter() { |
||||||
|
String[] paramTexts = paramTexts(); |
||||||
|
|
||||||
|
ParameterProvider[] parameters = ParameterHelper.analyze4Parameters(paramTexts, false); |
||||||
|
parameters = ArrayUtils.addAll(parameters, getOrderValue().analyze4Parameters()); |
||||||
|
|
||||||
|
if (parameters.length < 1 && editorPane.update().size() < 1) { |
||||||
|
return; |
||||||
|
} |
||||||
|
boolean isIn = true; |
||||||
|
java.util.List<ParameterProvider> list = editorPane.update(); |
||||||
|
java.util.List<String> name = new ArrayList<String>(); |
||||||
|
for (int i = 0; i < list.size(); i++) { |
||||||
|
name.add(list.get(i).getName()); |
||||||
|
} |
||||||
|
for (int i = 0; i < parameters.length; i++) { |
||||||
|
if (!name.contains(parameters[i].getName())) { |
||||||
|
isIn = false; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (list.size() == parameters.length && isIn) { |
||||||
|
return; |
||||||
|
} |
||||||
|
refresh(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private class PreviewAction extends UpdateAction { |
||||||
|
public PreviewAction() { |
||||||
|
this.setName(PREVIEW_BUTTON); |
||||||
|
this.setMnemonic('P'); |
||||||
|
this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/preview.png")); |
||||||
|
} |
||||||
|
|
||||||
|
public void actionPerformed(ActionEvent evt) { |
||||||
|
checkParameter(); |
||||||
|
PreviewTablePane.previewTableData(RedisBaseTableDataPane.this.updateBean()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
protected class RefreshAction extends UITableEditAction { |
||||||
|
public RefreshAction() { |
||||||
|
this.setName(REFRESH_BUTTON); |
||||||
|
this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png")); |
||||||
|
} |
||||||
|
|
||||||
|
public void actionPerformed(ActionEvent e) { |
||||||
|
refresh(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void checkEnabled() { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,71 @@ |
|||||||
|
package com.fr.plugin.db.redis.ui; |
||||||
|
|
||||||
|
import com.fr.design.dialog.BasicPane; |
||||||
|
import com.fr.design.editor.ValueEditorPane; |
||||||
|
import com.fr.design.gui.ilable.UILabel; |
||||||
|
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; |
||||||
|
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.layout.TableLayout; |
||||||
|
import com.fr.design.layout.TableLayoutHelper; |
||||||
|
import com.fr.plugin.db.redis.core.order.OrderValue; |
||||||
|
import com.fr.plugin.db.redis.ui.value.IndexValuePaneFactory; |
||||||
|
import com.fr.plugin.db.redis.util.RedisDesignUtils; |
||||||
|
|
||||||
|
import java.awt.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-03-18 |
||||||
|
*/ |
||||||
|
public class RedisScriptPane extends BasicPane { |
||||||
|
|
||||||
|
private ValueEditorPane dbIndexEditor; |
||||||
|
private RSyntaxTextArea scriptTextPane; |
||||||
|
|
||||||
|
public RedisScriptPane() { |
||||||
|
|
||||||
|
setLayout(new BorderLayout()); |
||||||
|
|
||||||
|
scriptTextPane = new RSyntaxTextArea(); |
||||||
|
|
||||||
|
dbIndexEditor = IndexValuePaneFactory.createValueEditorPane(); |
||||||
|
|
||||||
|
Component[][] coms = new Component[][]{ |
||||||
|
{new UILabel(com.fr.design.i18n.Toolkit.i18nText("Plugin-Redis_DB_Index") + ":"), dbIndexEditor}, |
||||||
|
{new UILabel(Toolkit.i18nText("Plugin-Redis_Script_Query_Text") + ":"), |
||||||
|
RedisDesignUtils.createConditionTextPane(scriptTextPane, SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT, 350)}, |
||||||
|
}; |
||||||
|
|
||||||
|
double p = TableLayout.PREFERRED; |
||||||
|
double f = TableLayout.FILL; |
||||||
|
|
||||||
|
double[] rowSize = {p, p, p}; |
||||||
|
double[] columnSize = {p, f}; |
||||||
|
|
||||||
|
add(TableLayoutHelper.createTableLayoutPane(coms, rowSize, columnSize)); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String title4PopupWindow() { |
||||||
|
return "Script"; |
||||||
|
} |
||||||
|
|
||||||
|
public OrderValue getOrderValue() { |
||||||
|
return (OrderValue) dbIndexEditor.update(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setOrderValue(OrderValue orderValue) { |
||||||
|
dbIndexEditor.populate(orderValue); |
||||||
|
} |
||||||
|
|
||||||
|
public String getScript() { |
||||||
|
return scriptTextPane.getText(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setScript(String script) { |
||||||
|
scriptTextPane.setText(script); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
package com.fr.plugin.db.redis.ui; |
||||||
|
|
||||||
|
import com.fr.data.impl.NameDatabaseConnection; |
||||||
|
import com.fr.plugin.db.redis.core.RedisScriptTableData; |
||||||
|
import com.fr.plugin.db.redis.core.order.OrderValue; |
||||||
|
import com.fr.script.Calculator; |
||||||
|
import com.fr.stable.ParameterProvider; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import javax.swing.*; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-03-18 |
||||||
|
*/ |
||||||
|
public class RedisScriptTableDataPane extends RedisBaseTableDataPane<RedisScriptTableData> { |
||||||
|
|
||||||
|
private RedisScriptPane scriptPane; |
||||||
|
|
||||||
|
public RedisScriptTableDataPane() { |
||||||
|
super(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected JComponent createQueryPane() { |
||||||
|
if (scriptPane == null) { |
||||||
|
scriptPane = new RedisScriptPane(); |
||||||
|
} |
||||||
|
return scriptPane; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String[] paramTexts() { |
||||||
|
return new String[] {scriptPane.getScript()}; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OrderValue getOrderValue() { |
||||||
|
return scriptPane.getOrderValue(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateBean(RedisScriptTableData tableData) { |
||||||
|
if (tableData == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
Calculator c = Calculator.createCalculator(); |
||||||
|
|
||||||
|
editorPane.populate(tableData.getParameters(c)); |
||||||
|
|
||||||
|
chosePane.populateConnection(tableData.getDatabase()); |
||||||
|
|
||||||
|
scriptPane.setScript(tableData.getScript()); |
||||||
|
|
||||||
|
scriptPane.setOrderValue(tableData.getOrderValue()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public RedisScriptTableData updateBean() { |
||||||
|
RedisScriptTableData tableData = new RedisScriptTableData(); |
||||||
|
String connectionName = chosePane.getSelectRedisConnectionName(); |
||||||
|
if (StringUtils.isNotEmpty(connectionName)) { |
||||||
|
tableData.setDatabase(new NameDatabaseConnection(connectionName)); |
||||||
|
} |
||||||
|
List<ParameterProvider> parameterList = editorPane.update(); |
||||||
|
ParameterProvider[] parameters = parameterList.toArray(new ParameterProvider[parameterList.size()]); |
||||||
|
tableData.setParameters(parameters); |
||||||
|
|
||||||
|
tableData.setScript(scriptPane.getScript()); |
||||||
|
tableData.setOrderValue(scriptPane.getOrderValue()); |
||||||
|
|
||||||
|
return tableData; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package com.fr.plugin.db.redis.util; |
||||||
|
|
||||||
|
import com.fr.design.border.UIRoundedBorder; |
||||||
|
import com.fr.design.constants.UIConstants; |
||||||
|
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; |
||||||
|
import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane; |
||||||
|
|
||||||
|
import java.awt.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-03-18 |
||||||
|
*/ |
||||||
|
public class RedisDesignUtils { |
||||||
|
public static RTextScrollPane createConditionTextPane(RSyntaxTextArea editorPane, String type, int height) { |
||||||
|
editorPane.setSyntaxEditingStyle(type); |
||||||
|
RTextScrollPane sqlTextScrollPane = new RTextScrollPane(editorPane); |
||||||
|
sqlTextScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); |
||||||
|
sqlTextScrollPane.setPreferredSize(new Dimension(680, height)); |
||||||
|
sqlTextScrollPane.setLineNumbersEnabled(false); |
||||||
|
return sqlTextScrollPane; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
package com.fr.plugin.db.redis.util; |
||||||
|
|
||||||
|
import com.eclipsesource.v8.V8Object; |
||||||
|
import com.fr.base.Parameter; |
||||||
|
import com.fr.base.TemplateUtils; |
||||||
|
import com.fr.stable.ArrayUtils; |
||||||
|
|
||||||
|
import java.lang.reflect.Method; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author richie |
||||||
|
* @version 10.0 |
||||||
|
* Created by richie on 2019-03-18 |
||||||
|
*/ |
||||||
|
public class RedisUtils { |
||||||
|
|
||||||
|
public static String calculateQuery(String query, Parameter[] ps) { |
||||||
|
if (ArrayUtils.isEmpty(ps)) { |
||||||
|
return query; |
||||||
|
} |
||||||
|
Map<String, Object> map = new HashMap<String, Object>(); |
||||||
|
for (Parameter p : ps) { |
||||||
|
map.put(p.getName(), p.getValue()); |
||||||
|
} |
||||||
|
try { |
||||||
|
return TemplateUtils.renderParameter4Tpl(query, map); |
||||||
|
} catch (Exception e) { |
||||||
|
return query; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void registerJavaMethods(V8Object v8Object, Object target) { |
||||||
|
Method[] methods = target.getClass().getDeclaredMethods(); |
||||||
|
for (Method m : methods) { |
||||||
|
v8Object.registerJavaMethod(target, m.getName(), m.getName(), m.getParameterTypes()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue