17 Commits

Author SHA1 Message Date
Redkale
d373ab7204 2019-11-05 09:31:38 +08:00
Redkale
4f9a563ba7 2019-11-05 09:26:15 +08:00
Redkale
852da19b1e Redkale 2.0.0.rc2 结束 2019-11-05 09:21:49 +08:00
Redkale
ddfc040a53 2019-11-05 09:16:34 +08:00
Redkale
df3ccb763a 2019-11-04 11:53:11 +08:00
Redkale
f42561ca93 convert支持sql包的几个date类型 2019-11-03 11:47:54 +08:00
Redkale
580e28519a 2019-11-02 15:08:38 +08:00
Redkale
9ecc1d8f19 2019-11-02 14:20:07 +08:00
Redkale
40629ed7b9 2019-10-28 13:14:38 +08:00
Redkale
5790135add 2019-10-28 11:59:23 +08:00
Redkale
fd862ed6c6 Convert兼容java.util.Map.Entry 2019-10-28 11:56:45 +08:00
Redkale
33763af96c 兼容TypeToken.typeToClass 方法 2019-10-26 16:03:36 +08:00
Redkale
7c05df3cfb 2019-10-26 15:32:16 +08:00
Redkale
f471e2d4c5 配置支持远程地址 2019-10-26 09:45:33 +08:00
Redkale
d4fd093521 2019-10-25 11:42:50 +08:00
Redkale
40003c7789 2019-10-24 11:45:51 +08:00
Redkale
b94f99f338 2019-10-22 09:11:37 +08:00
18 changed files with 181 additions and 86 deletions

View File

@@ -116,7 +116,7 @@
excludelibs: 排除lib.path与excludes中的正则表达式匹配的路径, 多个正则表达式用分号;隔开 excludelibs: 排除lib.path与excludes中的正则表达式匹配的路径, 多个正则表达式用分号;隔开
charset: 文本编码, 默认: UTF-8 charset: 文本编码, 默认: UTF-8
backlog: 默认10K backlog: 默认10K
threads 线程数, 默认: CPU核数*32 threads 线程数, 默认: CPU核数*2最小8个
maxconns最大连接数, 小于1表示无限制 默认: 0 maxconns最大连接数, 小于1表示无限制 默认: 0
maxbody: request.body最大值 默认: 64K maxbody: request.body最大值 默认: 64K
bufferCapacity: ByteBuffer的初始化大小 TCP默认: 32K; (HTTP 2.0、WebSocket必须要16k以上); UDP默认: 1350B bufferCapacity: ByteBuffer的初始化大小 TCP默认: 32K; (HTTP 2.0、WebSocket必须要16k以上); UDP默认: 1350B

View File

@@ -30,5 +30,7 @@ module org.redkale {
exports org.redkale.util; exports org.redkale.util;
exports org.redkale.watch; exports org.redkale.watch;
uses org.redkale.source.SourceLoader;
uses org.redkale.util.ResourceInjectLoader;
} }
*/ */

View File

@@ -196,7 +196,7 @@ public final class ApiDocsService {
final FileOutputStream out = new FileOutputStream(new File(app.getHome(), "apidoc.json")); final FileOutputStream out = new FileOutputStream(new File(app.getHome(), "apidoc.json"));
out.write(json.getBytes("UTF-8")); out.write(json.getBytes("UTF-8"));
out.close(); out.close();
File doctemplate = new File(app.getConfPath(), "apidoc-template.html"); File doctemplate = new File(app.getConfPath().toString(), "apidoc-template.html");
InputStream in = null; InputStream in = null;
if (doctemplate.isFile() && doctemplate.canRead()) { if (doctemplate.isFile() && doctemplate.canRead()) {
in = new FileInputStream(doctemplate); in = new FileInputStream(doctemplate);

View File

@@ -57,12 +57,12 @@ public final class Application {
public static final String RESNAME_APP_TIME = "APP_TIME"; public static final String RESNAME_APP_TIME = "APP_TIME";
/** /**
* 当前进程的根目录, 类型String、File、Path * 当前进程的根目录, 类型String、File、Path、URI
*/ */
public static final String RESNAME_APP_HOME = "APP_HOME"; public static final String RESNAME_APP_HOME = "APP_HOME";
/** /**
* 当前进程的配置目录如果不是绝对路径则视为HOME目录下的相对路径 类型String、File、Path * 当前进程的配置目录如果不是绝对路径则视为HOME目录下的相对路径 类型String、File、Path、URI
*/ */
public static final String RESNAME_APP_CONF = "APP_CONF"; public static final String RESNAME_APP_CONF = "APP_CONF";
@@ -143,7 +143,7 @@ public final class Application {
private final File home; private final File home;
//配置文件目录 //配置文件目录
private final File confPath; private final URI confPath;
//日志 //日志
private final Logger logger; private final Logger logger;
@@ -176,16 +176,19 @@ public final class Application {
this.resourceFactory.register(RESNAME_APP_TIME, long.class, this.startTime); this.resourceFactory.register(RESNAME_APP_TIME, long.class, this.startTime);
this.resourceFactory.register(RESNAME_APP_HOME, Path.class, root.toPath()); this.resourceFactory.register(RESNAME_APP_HOME, Path.class, root.toPath());
this.resourceFactory.register(RESNAME_APP_HOME, File.class, root); this.resourceFactory.register(RESNAME_APP_HOME, File.class, root);
this.resourceFactory.register(RESNAME_APP_HOME, URI.class, root.toURI());
try { try {
this.resourceFactory.register(RESNAME_APP_HOME, root.getCanonicalPath()); this.resourceFactory.register(RESNAME_APP_HOME, root.getCanonicalPath());
this.home = root.getCanonicalFile(); this.home = root.getCanonicalFile();
String confsubpath = System.getProperty(RESNAME_APP_CONF, "conf"); String confsubpath = System.getProperty(RESNAME_APP_CONF, "conf");
if (confsubpath.charAt(0) == '/' || confsubpath.indexOf(':') > 0) { if (confsubpath.contains("://")) {
this.confPath = new File(confsubpath).getCanonicalFile(); this.confPath = new URI(confsubpath);
} else if (confsubpath.charAt(0) == '/' || confsubpath.indexOf(':') > 0) {
this.confPath = new File(confsubpath).getCanonicalFile().toURI();
} else { } else {
this.confPath = new File(this.home, confsubpath).getCanonicalFile(); this.confPath = new File(this.home, confsubpath).getCanonicalFile().toURI();
} }
} catch (IOException e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
String localaddr = config.getValue("address", "").trim(); String localaddr = config.getValue("address", "").trim();
@@ -209,11 +212,12 @@ public final class Application {
System.setProperty(RESNAME_APP_NODE, node); System.setProperty(RESNAME_APP_NODE, node);
} }
//以下是初始化日志配置 //以下是初始化日志配置
final File logconf = new File(confPath, "logging.properties"); final URI logConfURI = "file".equals(confPath.getScheme()) ? new File(new File(confPath), "logging.properties").toURI()
if (logconf.isFile() && logconf.canRead()) { : URI.create(confPath.toString() + (confPath.toString().endsWith("/") ? "" : "/") + "logging.properties");
if (!"file".equals(confPath.getScheme()) || (new File(logConfURI).isFile() && new File(logConfURI).canRead())) {
try { try {
final String rootpath = root.getCanonicalPath().replace('\\', '/'); final String rootpath = root.getCanonicalPath().replace('\\', '/');
FileInputStream fin = new FileInputStream(logconf); InputStream fin = logConfURI.toURL().openStream();
Properties properties = new Properties(); Properties properties = new Properties();
properties.load(fin); properties.load(fin);
fin.close(); fin.close();
@@ -301,7 +305,7 @@ public final class Application {
transportExec = Executors.newFixedThreadPool(threads, (Runnable r) -> { transportExec = Executors.newFixedThreadPool(threads, (Runnable r) -> {
Thread t = new Thread(r); Thread t = new Thread(r);
t.setDaemon(true); t.setDaemon(true);
t.setName("Transport-Thread-" + counter.incrementAndGet()); t.setName("Redkale-Transport-Thread-" + counter.incrementAndGet());
return t; return t;
}); });
transportGroup = AsynchronousChannelGroup.withCachedThreadPool(transportExec, 1); transportGroup = AsynchronousChannelGroup.withCachedThreadPool(transportExec, 1);
@@ -316,7 +320,7 @@ public final class Application {
transportExec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 8, (Runnable r) -> { transportExec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 8, (Runnable r) -> {
Thread t = new Thread(r); Thread t = new Thread(r);
t.setDaemon(true); t.setDaemon(true);
t.setName("Transport-Thread-" + counter.incrementAndGet()); t.setName("Redkale-Transport-Thread-" + counter.incrementAndGet());
return t; return t;
}); });
try { try {
@@ -375,7 +379,7 @@ public final class Application {
return home; return home;
} }
public File getConfPath() { public URI getConfPath() {
return confPath; return confPath;
} }
@@ -398,10 +402,14 @@ public final class Application {
System.setProperty("convert.bson.writer.buffer.defsize", "4096"); System.setProperty("convert.bson.writer.buffer.defsize", "4096");
System.setProperty("convert.json.writer.buffer.defsize", "4096"); System.setProperty("convert.json.writer.buffer.defsize", "4096");
File persist = new File(this.confPath, "persistence.xml"); final String confpath = this.confPath.toString();
final String homepath = this.home.getCanonicalPath(); final String homepath = this.home.getCanonicalPath();
final String confpath = this.confPath.getCanonicalPath(); if ("file".equals(this.confPath.getScheme())) {
File persist = new File(new File(confPath), "persistence.xml");
if (persist.isFile()) System.setProperty(DataSources.DATASOURCE_CONFPATH, persist.getCanonicalPath()); if (persist.isFile()) System.setProperty(DataSources.DATASOURCE_CONFPATH, persist.getCanonicalPath());
} else {
System.setProperty(DataSources.DATASOURCE_CONFPATH, confpath + (confpath.endsWith("/") ? "" : "/") + "persistence.xml");
}
String pidstr = ""; String pidstr = "";
try { //JDK 9+ try { //JDK 9+
Class phclass = Class.forName("java.lang.ProcessHandle"); Class phclass = Class.forName("java.lang.ProcessHandle");
@@ -425,13 +433,17 @@ public final class Application {
if (dfloads != null) { if (dfloads != null) {
for (String dfload : dfloads.split(";")) { for (String dfload : dfloads.split(";")) {
if (dfload.trim().isEmpty()) continue; if (dfload.trim().isEmpty()) continue;
final File df = (dfload.indexOf('/') < 0) ? new File(confPath, "/" + dfload) : new File(dfload); final URI df = (dfload.indexOf('/') < 0) ? URI.create(confpath + (confpath.endsWith("/") ? "" : "/") + dfload) : new File(dfload).toURI();
if (df.isFile()) { if (!"file".equals(df.getScheme()) || new File(df).isFile()) {
Properties ps = new Properties(); Properties ps = new Properties();
InputStream in = new FileInputStream(df); try {
InputStream in = df.toURL().openStream();
ps.load(in); ps.load(in);
in.close(); in.close();
ps.forEach((x, y) -> resourceFactory.register("property." + x, y.toString().replace("${APP_HOME}", homepath))); ps.forEach((x, y) -> resourceFactory.register("property." + x, y.toString().replace("${APP_HOME}", homepath)));
} catch (Exception e) {
logger.log(Level.WARNING, "load properties(" + dfload + ") error", e);
}
} }
} }
} }
@@ -558,9 +570,10 @@ public final class Application {
} }
public void restoreConfig() throws IOException { public void restoreConfig() throws IOException {
if (!"file".equals(this.confPath.getScheme())) return;
synchronized (this) { synchronized (this) {
File confFile = new File(this.confPath, "application.xml"); File confFile = new File(this.confPath.toString(), "application.xml");
confFile.renameTo(new File(this.confPath, "application_" + String.format("%1$tY%1$tm%1$td%1$tH%1$tM%1$tS", System.currentTimeMillis()) + ".xml")); confFile.renameTo(new File(this.confPath.toString(), "application_" + String.format("%1$tY%1$tm%1$td%1$tH%1$tM%1$tS", System.currentTimeMillis()) + ".xml"));
final PrintStream ps = new PrintStream(new FileOutputStream(confFile)); final PrintStream ps = new PrintStream(new FileOutputStream(confFile));
ps.append(config.toXML("application")); ps.append(config.toXML("application"));
ps.close(); ps.close();
@@ -571,7 +584,7 @@ public final class Application {
final Application application = this; final Application application = this;
new Thread() { new Thread() {
{ {
setName("Application-Control-Thread"); setName("Redkale-Application-SelfServer-Thread");
} }
@Override @Override
@@ -742,7 +755,7 @@ public final class Application {
Thread thread = new Thread() { Thread thread = new Thread() {
{ {
String host = serconf.getValue("host", "0.0.0.0").replace("0.0.0.0", "*"); String host = serconf.getValue("host", "0.0.0.0").replace("0.0.0.0", "*");
setName(serconf.getValue("protocol", "Server").toUpperCase() + "-" + host + ":" + serconf.getIntValue("port") + "-Thread"); setName("Redkale-" + serconf.getValue("protocol", "Server").toUpperCase() + "-" + host + ":" + serconf.getIntValue("port") + "-Thread");
this.setDaemon(true); this.setDaemon(true);
} }
@@ -843,18 +856,20 @@ public final class Application {
final String home = new File(System.getProperty(RESNAME_APP_HOME, "")).getCanonicalPath().replace('\\', '/'); final String home = new File(System.getProperty(RESNAME_APP_HOME, "")).getCanonicalPath().replace('\\', '/');
System.setProperty(RESNAME_APP_HOME, home); System.setProperty(RESNAME_APP_HOME, home);
String confsubpath = System.getProperty(RESNAME_APP_CONF, "conf"); String confsubpath = System.getProperty(RESNAME_APP_CONF, "conf");
File appfile; URI appconf;
if (confsubpath.charAt(0) == '/' || confsubpath.indexOf(':') > 0) { if (confsubpath.contains("://")) {
appfile = new File(confsubpath).getCanonicalFile(); appconf = URI.create(confsubpath + (confsubpath.endsWith("/") ? "" : "/") + "application.xml");
} else if (confsubpath.charAt(0) == '/' || confsubpath.indexOf(':') > 0) {
appconf = new File(confsubpath, "application.xml").toURI();
} else { } else {
appfile = new File(new File(home), confsubpath); appconf = new File(new File(home, confsubpath), "application.xml").toURI();
} }
File appconf = new File(appfile, "application.xml"); return new Application(singleton, load(appconf.toURL().openStream()));
return new Application(singleton, load(new FileInputStream(appconf)));
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
Utility.midnight(); //先初始化一下Utility Utility.midnight(); //先初始化一下Utility
Thread.currentThread().setName("Redkale-Application-Main-Thread");
//运行主程序 //运行主程序
final Application application = Application.create(false); final Application application = Application.create(false);
if (System.getProperty("CMD") != null) { if (System.getProperty("CMD") != null) {

View File

@@ -133,7 +133,7 @@ public class LogFileHandler extends Handler {
} }
private void open() { private void open() {
final String name = "Logging-" + getClass().getSimpleName() + "-Thread"; final String name = "Redkale-Logging-" + getClass().getSimpleName() + "-Thread";
new Thread() { new Thread() {
{ {
setName(name); setName(name);

View File

@@ -133,6 +133,54 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
} }
}); });
try {
Class sqldateClass = Class.forName("java.sql.Date");
this.register(sqldateClass, new SimpledCoder<R, W, java.sql.Date>() {
@Override
public void convertTo(W out, java.sql.Date value) {
out.writeSmallString(value == null ? null : value.toString());
}
@Override
public java.sql.Date convertFrom(R in) {
String t = in.readSmallString();
return t == null ? null : java.sql.Date.valueOf(t);
}
});
Class sqltimeClass = Class.forName("java.sql.Time");
this.register(sqltimeClass, new SimpledCoder<R, W, java.sql.Time>() {
@Override
public void convertTo(W out, java.sql.Time value) {
out.writeSmallString(value == null ? null : value.toString());
}
@Override
public java.sql.Time convertFrom(R in) {
String t = in.readSmallString();
return t == null ? null : java.sql.Time.valueOf(t);
}
});
Class timestampClass = Class.forName("java.sql.Timestamp");
this.register(timestampClass, new SimpledCoder<R, W, java.sql.Timestamp>() {
@Override
public void convertTo(W out, java.sql.Timestamp value) {
out.writeSmallString(value == null ? null : value.toString());
}
@Override
public java.sql.Timestamp convertFrom(R in) {
String t = in.readSmallString();
return t == null ? null : java.sql.Timestamp.valueOf(t);
}
});
} catch (Throwable t) {
}
} }
} }
@@ -711,7 +759,8 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
encoder = new OptionalCoder(this, type); encoder = new OptionalCoder(this, type);
} else if (clazz == Object.class) { } else if (clazz == Object.class) {
return (Encodeable<W, E>) this.anyEncoder; return (Encodeable<W, E>) this.anyEncoder;
} else if (!clazz.getName().startsWith("java.") || java.net.HttpCookie.class == clazz || java.util.AbstractMap.SimpleEntry.class == clazz) { } else if (!clazz.getName().startsWith("java.") || java.net.HttpCookie.class == clazz
|| java.util.Map.Entry.class == clazz || java.util.AbstractMap.SimpleEntry.class == clazz) {
Encodeable simpleCoder = null; Encodeable simpleCoder = null;
for (final Method method : clazz.getDeclaredMethods()) { for (final Method method : clazz.getDeclaredMethods()) {
if (!Modifier.isStatic(method.getModifiers())) continue; if (!Modifier.isStatic(method.getModifiers())) continue;

View File

@@ -26,10 +26,7 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
private static final JsonFactory instance = new JsonFactory(null, Boolean.getBoolean("convert.json.tiny")); private static final JsonFactory instance = new JsonFactory(null, Boolean.getBoolean("convert.json.tiny"));
static { static {
instance.register(InetAddress.class, InetAddressSimpledCoder.InetAddressJsonSimpledCoder.instance);
instance.register(InetSocketAddress.class, InetAddressSimpledCoder.InetSocketAddressJsonSimpledCoder.instance);
instance.register(DLong.class, DLongSimpledCoder.DLongJsonSimpledCoder.instance);
instance.register(BigInteger.class, BigIntegerSimpledCoder.BigIntegerJsonSimpledCoder.instance);
instance.register(Serializable.class, instance.loadEncoder(Object.class)); instance.register(Serializable.class, instance.loadEncoder(Object.class));
instance.register(AnyValue.class, instance.loadDecoder(AnyValue.DefaultAnyValue.class)); instance.register(AnyValue.class, instance.loadDecoder(AnyValue.DefaultAnyValue.class));
@@ -38,6 +35,12 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
private JsonFactory(JsonFactory parent, boolean tiny) { private JsonFactory(JsonFactory parent, boolean tiny) {
super(parent, tiny); super(parent, tiny);
if (parent == null) {
this.register(InetAddress.class, InetAddressSimpledCoder.InetAddressJsonSimpledCoder.instance);
this.register(InetSocketAddress.class, InetAddressSimpledCoder.InetSocketAddressJsonSimpledCoder.instance);
this.register(DLong.class, DLongSimpledCoder.DLongJsonSimpledCoder.instance);
this.register(BigInteger.class, BigIntegerSimpledCoder.BigIntegerJsonSimpledCoder.instance);
}
} }
@Override @Override

View File

@@ -129,7 +129,7 @@ public abstract class Server<K extends Serializable, C extends Context, R extend
this.maxbody = parseLenth(config.getValue("maxbody"), 64 * 1024); this.maxbody = parseLenth(config.getValue("maxbody"), 64 * 1024);
int bufCapacity = parseLenth(config.getValue("bufferCapacity"), "UDP".equalsIgnoreCase(protocol) ? 1350 : 32 * 1024); int bufCapacity = parseLenth(config.getValue("bufferCapacity"), "UDP".equalsIgnoreCase(protocol) ? 1350 : 32 * 1024);
this.bufferCapacity = "UDP".equalsIgnoreCase(protocol) ? bufCapacity : (bufCapacity < 8 * 1024 ? 8 * 1024 : bufCapacity); this.bufferCapacity = "UDP".equalsIgnoreCase(protocol) ? bufCapacity : (bufCapacity < 8 * 1024 ? 8 * 1024 : bufCapacity);
this.threads = config.getIntValue("threads", Runtime.getRuntime().availableProcessors() * 32); this.threads = config.getIntValue("threads", Math.max(8, Runtime.getRuntime().availableProcessors() * 2));
this.bufferPoolSize = config.getIntValue("bufferPoolSize", this.threads * 4); this.bufferPoolSize = config.getIntValue("bufferPoolSize", this.threads * 4);
this.responsePoolSize = config.getIntValue("responsePoolSize", this.threads * 2); this.responsePoolSize = config.getIntValue("responsePoolSize", this.threads * 2);
this.name = config.getValue("name", "Server-" + protocol + "-" + this.address.getPort()); this.name = config.getValue("name", "Server-" + protocol + "-" + this.address.getPort());
@@ -153,7 +153,7 @@ public abstract class Server<K extends Serializable, C extends Context, R extend
final String n = name; final String n = name;
this.executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(threads, (Runnable r) -> { this.executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(threads, (Runnable r) -> {
Thread t = new WorkThread(executor, r); Thread t = new WorkThread(executor, r);
t.setName(n + "-ServletThread-" + f.format(counter.incrementAndGet())); t.setName("Redkale-" + n + "-ServletThread-" + f.format(counter.incrementAndGet()));
return t; return t;
}); });
} }

View File

@@ -119,7 +119,7 @@ public class TransportFactory {
if (this.checkinterval < 2) this.checkinterval = 2; if (this.checkinterval < 2) this.checkinterval = 2;
} }
this.scheduler = new ScheduledThreadPoolExecutor(1, (Runnable r) -> { this.scheduler = new ScheduledThreadPoolExecutor(1, (Runnable r) -> {
final Thread t = new Thread(r, this.getClass().getSimpleName() + "-TransportFactoryTask-Thread"); final Thread t = new Thread(r, "Redkale-" + this.getClass().getSimpleName() + "-Schedule-Thread");
t.setDaemon(true); t.setDaemon(true);
return t; return t;
}); });
@@ -162,7 +162,7 @@ public class TransportFactory {
ExecutorService transportExec = Executors.newFixedThreadPool(threads, (Runnable r) -> { ExecutorService transportExec = Executors.newFixedThreadPool(threads, (Runnable r) -> {
Thread t = new Thread(r); Thread t = new Thread(r);
t.setDaemon(true); t.setDaemon(true);
t.setName("Transport-Thread-" + counter.incrementAndGet()); t.setName("Redkale-Transport-Thread-" + counter.incrementAndGet());
return t; return t;
}); });
AsynchronousChannelGroup transportGroup = null; AsynchronousChannelGroup transportGroup = null;

View File

@@ -37,7 +37,7 @@ public class HttpResourceServlet extends HttpServlet {
public WatchThread(File root) throws IOException { public WatchThread(File root) throws IOException {
this.root = root; this.root = root;
this.setName("HttpResourceServlet-Watch-Thread"); this.setName("Redkale-HttpResourceServlet-Watch-Thread");
this.setDaemon(true); this.setDaemon(true);
this.watcher = this.root.toPath().getFileSystem().newWatchService(); this.watcher = this.root.toPath().getFileSystem().newWatchService();
} }

View File

@@ -855,8 +855,10 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
} }
this.contentLength = length; this.contentLength = length;
if (filename != null && !filename.isEmpty() && file != null) { if (filename != null && !filename.isEmpty() && file != null) {
if (this.header.getValue("Content-Disposition") == null) {
addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
} }
}
this.contentType = MimeType.getByFilename(filename == null || filename.isEmpty() ? file.getName() : filename); this.contentType = MimeType.getByFilename(filename == null || filename.isEmpty() ? file.getName() : filename);
if (this.contentType == null) this.contentType = "application/octet-stream"; if (this.contentType == null) this.contentType = "application/octet-stream";
String range = request.getHeader("Range"); String range = request.getHeader("Range");

View File

@@ -70,18 +70,17 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
} }
c = c1; c = c1;
} catch (SQLException se) { } catch (SQLException se) {
if (info.tableStrategy == null || !info.isTableNotExist(se)) throw se; if (info.getTableStrategy() == null || !info.isTableNotExist(se)) throw se;
synchronized (info.tables) { synchronized (info.disTableLock()) {
final String oldTable = info.table;
final String catalog = conn.getCatalog(); final String catalog = conn.getCatalog();
final String newTable = info.getTable(entitys[0]); final String newTable = info.getTable(entitys[0]);
final String tablekey = newTable.indexOf('.') > 0 ? newTable : (catalog + '.' + newTable); final String tablekey = newTable.indexOf('.') > 0 ? newTable : (catalog + '.' + newTable);
if (!info.tables.contains(tablekey)) { if (!info.containsDisTable(tablekey)) {
try { try {
Statement st = conn.createStatement(); Statement st = conn.createStatement();
st.execute(info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable)); st.execute(info.getTableCopySQL(newTable));
st.close(); st.close();
info.tables.add(tablekey); info.addDisTable(tablekey);
} catch (SQLException sqle) { //多进程并发时可能会出现重复建表 } catch (SQLException sqle) { //多进程并发时可能会出现重复建表
if (newTable.indexOf('.') > 0 && info.isTableNotExist(se)) { if (newTable.indexOf('.') > 0 && info.isTableNotExist(se)) {
Statement st; Statement st;
@@ -94,14 +93,14 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
} }
try { try {
st = conn.createStatement(); st = conn.createStatement();
st.execute(info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable)); st.execute(info.getTableCopySQL(newTable));
st.close(); st.close();
info.tables.add(tablekey); info.addDisTable(tablekey);
} catch (SQLException sqle2) { } catch (SQLException sqle2) {
logger.log(Level.SEVERE, "create table2(" + info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable) + ") error", sqle2); logger.log(Level.SEVERE, "create table2(" + info.getTableCopySQL(newTable) + ") error", sqle2);
} }
} else { } else {
logger.log(Level.SEVERE, "create table(" + info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable) + ") error", sqle); logger.log(Level.SEVERE, "create table(" + info.getTableCopySQL(newTable) + ") error", sqle);
} }
} }
} }
@@ -143,7 +142,7 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
} catch (SQLException e) { } catch (SQLException e) {
CompletableFuture future = new CompletableFuture(); CompletableFuture future = new CompletableFuture();
future.completeExceptionally(e); future.completeExceptionally(e);
return future; return future;//return CompletableFuture.failedFuture(e);
} finally { } finally {
if (conn != null) writePool.offerConnection(conn); if (conn != null) writePool.offerConnection(conn);
} }
@@ -201,7 +200,7 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
} catch (SQLException e) { } catch (SQLException e) {
CompletableFuture future = new CompletableFuture(); CompletableFuture future = new CompletableFuture();
future.completeExceptionally(e); future.completeExceptionally(e);
return future; return future;//return CompletableFuture.failedFuture(e);
} finally { } finally {
if (conn != null) writePool.offerConnection(conn); if (conn != null) writePool.offerConnection(conn);
} }
@@ -222,7 +221,7 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
if (info.isTableNotExist(e)) return CompletableFuture.completedFuture(-1); if (info.isTableNotExist(e)) return CompletableFuture.completedFuture(-1);
CompletableFuture future = new CompletableFuture(); CompletableFuture future = new CompletableFuture();
future.completeExceptionally(e); future.completeExceptionally(e);
return future; return future;//return CompletableFuture.failedFuture(e);
} finally { } finally {
if (conn != null) writePool.offerConnection(conn); if (conn != null) writePool.offerConnection(conn);
} }
@@ -243,7 +242,7 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
if (info.isTableNotExist(e)) return CompletableFuture.completedFuture(-1); if (info.isTableNotExist(e)) return CompletableFuture.completedFuture(-1);
CompletableFuture future = new CompletableFuture(); CompletableFuture future = new CompletableFuture();
future.completeExceptionally(e); future.completeExceptionally(e);
return future; return future;//return CompletableFuture.failedFuture(e);
} finally { } finally {
if (conn != null) writePool.offerConnection(conn); if (conn != null) writePool.offerConnection(conn);
} }
@@ -296,7 +295,7 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
} catch (SQLException e) { } catch (SQLException e) {
CompletableFuture future = new CompletableFuture(); CompletableFuture future = new CompletableFuture();
future.completeExceptionally(e); future.completeExceptionally(e);
return future; return future;//return CompletableFuture.failedFuture(e);
} finally { } finally {
if (conn != null) writePool.offerConnection(conn); if (conn != null) writePool.offerConnection(conn);
} }
@@ -330,7 +329,7 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
} catch (SQLException e) { } catch (SQLException e) {
CompletableFuture future = new CompletableFuture(); CompletableFuture future = new CompletableFuture();
future.completeExceptionally(e); future.completeExceptionally(e);
return future; return future;//return CompletableFuture.failedFuture(e);
} finally { } finally {
if (conn != null) writePool.offerConnection(conn); if (conn != null) writePool.offerConnection(conn);
} }
@@ -339,12 +338,12 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
@Override @Override
protected <T, N extends Number> CompletableFuture<Map<String, N>> getNumberMapDB(EntityInfo<T> info, String sql, FilterFuncColumn... columns) { protected <T, N extends Number> CompletableFuture<Map<String, N>> getNumberMapDB(EntityInfo<T> info, String sql, FilterFuncColumn... columns) {
Connection conn = null; Connection conn = null;
final Map map = new HashMap<>();
try { try {
conn = readPool.poll(); conn = readPool.poll();
//conn.setReadOnly(true); //conn.setReadOnly(true);
final Statement stmt = conn.createStatement(); final Statement stmt = conn.createStatement();
ResultSet set = stmt.executeQuery(sql); ResultSet set = stmt.executeQuery(sql);
final Map map = new HashMap<>();
if (set.next()) { if (set.next()) {
int index = 0; int index = 0;
for (FilterFuncColumn ffc : columns) { for (FilterFuncColumn ffc : columns) {
@@ -360,9 +359,10 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
stmt.close(); stmt.close();
return CompletableFuture.completedFuture(map); return CompletableFuture.completedFuture(map);
} catch (SQLException e) { } catch (SQLException e) {
if (info.getTableStrategy() != null && info.isTableNotExist(e)) return CompletableFuture.completedFuture(map);
CompletableFuture future = new CompletableFuture(); CompletableFuture future = new CompletableFuture();
future.completeExceptionally(e); future.completeExceptionally(e);
return future; return future;//return CompletableFuture.failedFuture(e);
} finally { } finally {
if (conn != null) readPool.offerConnection(conn); if (conn != null) readPool.offerConnection(conn);
} }
@@ -385,9 +385,10 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
stmt.close(); stmt.close();
return CompletableFuture.completedFuture(rs); return CompletableFuture.completedFuture(rs);
} catch (SQLException e) { } catch (SQLException e) {
if (info.getTableStrategy() != null && info.isTableNotExist(e)) return CompletableFuture.completedFuture(defVal);
CompletableFuture future = new CompletableFuture(); CompletableFuture future = new CompletableFuture();
future.completeExceptionally(e); future.completeExceptionally(e);
return future; return future;//return CompletableFuture.failedFuture(e);
} finally { } finally {
if (conn != null) readPool.offerConnection(conn); if (conn != null) readPool.offerConnection(conn);
} }
@@ -396,11 +397,11 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
@Override @Override
protected <T, K extends Serializable, N extends Number> CompletableFuture<Map<K, N>> queryColumnMapDB(EntityInfo<T> info, String sql, String keyColumn) { protected <T, K extends Serializable, N extends Number> CompletableFuture<Map<K, N>> queryColumnMapDB(EntityInfo<T> info, String sql, String keyColumn) {
Connection conn = null; Connection conn = null;
Map<K, N> rs = new LinkedHashMap<>();
try { try {
conn = readPool.poll(); conn = readPool.poll();
//conn.setReadOnly(true); //conn.setReadOnly(true);
final Statement stmt = conn.createStatement(); final Statement stmt = conn.createStatement();
Map<K, N> rs = new LinkedHashMap<>();
ResultSet set = stmt.executeQuery(sql); ResultSet set = stmt.executeQuery(sql);
ResultSetMetaData rsd = set.getMetaData(); ResultSetMetaData rsd = set.getMetaData();
boolean smallint = rsd == null ? false : rsd.getColumnType(1) == Types.SMALLINT; boolean smallint = rsd == null ? false : rsd.getColumnType(1) == Types.SMALLINT;
@@ -411,9 +412,10 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
stmt.close(); stmt.close();
return CompletableFuture.completedFuture(rs); return CompletableFuture.completedFuture(rs);
} catch (SQLException e) { } catch (SQLException e) {
if (info.getTableStrategy() != null && info.isTableNotExist(e)) return CompletableFuture.completedFuture(rs);
CompletableFuture future = new CompletableFuture(); CompletableFuture future = new CompletableFuture();
future.completeExceptionally(e); future.completeExceptionally(e);
return future; return future;//return CompletableFuture.failedFuture(e);
} finally { } finally {
if (conn != null) readPool.offerConnection(conn); if (conn != null) readPool.offerConnection(conn);
} }
@@ -433,10 +435,10 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
ps.close(); ps.close();
return CompletableFuture.completedFuture(rs); return CompletableFuture.completedFuture(rs);
} catch (SQLException e) { } catch (SQLException e) {
if (info.tableStrategy != null && info.isTableNotExist(e)) return CompletableFuture.completedFuture(null); if (info.getTableStrategy() != null && info.isTableNotExist(e)) return CompletableFuture.completedFuture(null);
CompletableFuture future = new CompletableFuture(); CompletableFuture future = new CompletableFuture();
future.completeExceptionally(e); future.completeExceptionally(e);
return future; return future;//return CompletableFuture.failedFuture(e);
} finally { } finally {
if (conn != null) readPool.offerConnection(conn); if (conn != null) readPool.offerConnection(conn);
} }
@@ -460,10 +462,10 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
ps.close(); ps.close();
return CompletableFuture.completedFuture(val == null ? defValue : val); return CompletableFuture.completedFuture(val == null ? defValue : val);
} catch (SQLException e) { } catch (SQLException e) {
if (info.tableStrategy != null && info.isTableNotExist(e)) return CompletableFuture.completedFuture(defValue); if (info.getTableStrategy() != null && info.isTableNotExist(e)) return CompletableFuture.completedFuture(defValue);
CompletableFuture future = new CompletableFuture(); CompletableFuture future = new CompletableFuture();
future.completeExceptionally(e); future.completeExceptionally(e);
return future; return future;//return CompletableFuture.failedFuture(e);
} finally { } finally {
if (conn != null) readPool.offerConnection(conn); if (conn != null) readPool.offerConnection(conn);
} }
@@ -483,10 +485,10 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " exists (" + rs + ") sql=" + sql); if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " exists (" + rs + ") sql=" + sql);
return CompletableFuture.completedFuture(rs); return CompletableFuture.completedFuture(rs);
} catch (SQLException e) { } catch (SQLException e) {
if (info.tableStrategy != null && info.isTableNotExist(e)) return CompletableFuture.completedFuture(false); if (info.getTableStrategy() != null && info.isTableNotExist(e)) return CompletableFuture.completedFuture(false);
CompletableFuture future = new CompletableFuture(); CompletableFuture future = new CompletableFuture();
future.completeExceptionally(e); future.completeExceptionally(e);
return future; return future;//return CompletableFuture.failedFuture(e);
} finally { } finally {
if (conn != null) readPool.offerConnection(conn); if (conn != null) readPool.offerConnection(conn);
} }
@@ -557,10 +559,10 @@ public class DataJdbcSource extends DataSqlSource<Connection> {
ps.close(); ps.close();
return CompletableFuture.completedFuture(new Sheet<>(total, list)); return CompletableFuture.completedFuture(new Sheet<>(total, list));
} catch (SQLException e) { } catch (SQLException e) {
if (info.tableStrategy != null && info.isTableNotExist(e)) return CompletableFuture.completedFuture(new Sheet<>()); if (info.getTableStrategy() != null && info.isTableNotExist(e)) return CompletableFuture.completedFuture(new Sheet<>());
CompletableFuture future = new CompletableFuture(); CompletableFuture future = new CompletableFuture();
future.completeExceptionally(e); future.completeExceptionally(e);
return future; return future;//return CompletableFuture.failedFuture(e);
} finally { } finally {
if (conn != null) readPool.offerConnection(conn); if (conn != null) readPool.offerConnection(conn);
} }

View File

@@ -7,7 +7,7 @@ package org.redkale.source;
import java.io.*; import java.io.*;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.net.URL; import java.net.*;
import java.util.*; import java.util.*;
import javax.xml.stream.*; import javax.xml.stream.*;
import org.redkale.util.AnyValue; import org.redkale.util.AnyValue;
@@ -139,7 +139,7 @@ public final class DataSources {
public static DataSource createDataSource(final String unitName) throws IOException { public static DataSource createDataSource(final String unitName) throws IOException {
return createDataSource(unitName, System.getProperty(DATASOURCE_CONFPATH) == null return createDataSource(unitName, System.getProperty(DATASOURCE_CONFPATH) == null
? DataJdbcSource.class.getResource("/META-INF/persistence.xml") ? DataJdbcSource.class.getResource("/META-INF/persistence.xml")
: new File(System.getProperty(DATASOURCE_CONFPATH)).toURI().toURL()); : (System.getProperty(DATASOURCE_CONFPATH, "").contains("://") ? URI.create(System.getProperty(DATASOURCE_CONFPATH)).toURL() : new File(System.getProperty(DATASOURCE_CONFPATH)).toURI().toURL()));
} }
public static DataSource createDataSource(final String unitName, URL persistxml) throws IOException { public static DataSource createDataSource(final String unitName, URL persistxml) throws IOException {

View File

@@ -91,7 +91,7 @@ public abstract class DataSqlSource<DBChannel> extends AbstractService implement
} else if (s.length() == 2) { } else if (s.length() == 2) {
s = "0" + s; s = "0" + s;
} }
t.setName(cname + "-Thread-" + s); t.setName("Redkale-"+cname + "-Thread-" + s);
t.setUncaughtExceptionHandler(ueh); t.setUncaughtExceptionHandler(ueh);
return t; return t;
}); });

View File

@@ -89,16 +89,16 @@ public final class EntityInfo<T> {
final String notcontainSQL; final String notcontainSQL;
//用于判断表不存在的使用, 多个SQLState用;隔开 //用于判断表不存在的使用, 多个SQLState用;隔开
final String tablenotexistSqlstates; private final String tablenotexistSqlstates;
//用于复制表结构使用 //用于复制表结构使用
final String tablecopySQL; private final String tablecopySQL;
//用于存在database.table_20160202类似这种分布式表 //用于存在database.table_20160202类似这种分布式表
final Set<String> tables = new HashSet<>(); private final Set<String> tables = new HashSet<>();
//分表 策略 //分表 策略
final DistributeTableStrategy<T> tableStrategy; private final DistributeTableStrategy<T> tableStrategy;
//根据主键查找单个对象的SQL //根据主键查找单个对象的SQL
private final String queryPrepareSQL; private final String queryPrepareSQL;
@@ -239,7 +239,7 @@ public final class EntityInfo<T> {
} }
//--------------------------------------------- //---------------------------------------------
Table t = type.getAnnotation(Table.class); Table t = type.getAnnotation(Table.class);
if (type.getAnnotation(VirtualEntity.class) != null || "memory".equalsIgnoreCase(source.getType())) { if (type.getAnnotation(VirtualEntity.class) != null || (source == null || "memory".equalsIgnoreCase(source.getType()))) {
this.table = null; this.table = null;
BiFunction<DataSource, Class, List> loader = null; BiFunction<DataSource, Class, List> loader = null;
try { try {
@@ -510,6 +510,18 @@ public final class EntityInfo<T> {
return tableStrategy; return tableStrategy;
} }
public Object disTableLock() {
return tables;
}
public boolean containsDisTable(String tablekey) {
return tables.contains(tablekey);
}
public void addDisTable(String tablekey) {
tables.add(tablekey);
}
public String getTableNotExistSqlStates2() { public String getTableNotExistSqlStates2() {
return tablenotexistSqlstates; return tablenotexistSqlstates;
} }

View File

@@ -85,6 +85,13 @@ public interface Creator<T> {
creatorCacheMap.put(Stream.class, (params) -> new ArrayList<>().stream()); creatorCacheMap.put(Stream.class, (params) -> new ArrayList<>().stream());
creatorCacheMap.put(ConcurrentHashMap.class, (params) -> new ConcurrentHashMap<>()); creatorCacheMap.put(ConcurrentHashMap.class, (params) -> new ConcurrentHashMap<>());
creatorCacheMap.put(CompletableFuture.class, (params) -> new CompletableFuture<>()); creatorCacheMap.put(CompletableFuture.class, (params) -> new CompletableFuture<>());
creatorCacheMap.put(Map.Entry.class, new Creator<Map.Entry>() {
@Override
@ConstructorParameters({"key", "value"})
public Map.Entry create(Object... params) {
return new AbstractMap.SimpleEntry(params[0], params[1]);
}
});
creatorCacheMap.put(AbstractMap.SimpleEntry.class, new Creator<AbstractMap.SimpleEntry>() { creatorCacheMap.put(AbstractMap.SimpleEntry.class, new Creator<AbstractMap.SimpleEntry>() {
@Override @Override
@ConstructorParameters({"key", "value"}) @ConstructorParameters({"key", "value"})
@@ -232,6 +239,8 @@ public interface Creator<T> {
clazz = (Class<T>) ConcurrentHashMap.class; clazz = (Class<T>) ConcurrentHashMap.class;
} else if (Collection.class.isAssignableFrom(clazz) && clazz.isAssignableFrom(ArrayList.class)) { } else if (Collection.class.isAssignableFrom(clazz) && clazz.isAssignableFrom(ArrayList.class)) {
clazz = (Class<T>) ArrayList.class; clazz = (Class<T>) ArrayList.class;
} else if (Map.Entry.class.isAssignableFrom(clazz) && (Modifier.isInterface(clazz.getModifiers()) || Modifier.isAbstract(clazz.getModifiers()) || !Modifier.isPublic(clazz.getModifiers()))) {
clazz = (Class<T>) AbstractMap.SimpleEntry.class;
} }
Creator creator = CreatorInner.creatorCacheMap.get(clazz); Creator creator = CreatorInner.creatorCacheMap.get(clazz);
if (creator != null) return creator; if (creator != null) return creator;

View File

@@ -17,7 +17,7 @@ public final class Redkale {
} }
public static String getDotedVersion() { public static String getDotedVersion() {
return "2.0.0-rc1"; return "2.0.0-rc2";
} }
public static int getMajorVersion() { public static int getMajorVersion() {

View File

@@ -83,7 +83,8 @@ public abstract class TypeToken<T> {
if (type instanceof TypeVariable) return null; if (type instanceof TypeVariable) return null;
if (type instanceof GenericArrayType) return Array.newInstance(typeToClass(((GenericArrayType) type).getGenericComponentType()), 0).getClass(); if (type instanceof GenericArrayType) return Array.newInstance(typeToClass(((GenericArrayType) type).getGenericComponentType()), 0).getClass();
if (!(type instanceof ParameterizedType)) return null; //只能是null了 if (!(type instanceof ParameterizedType)) return null; //只能是null了
return typeToClass(((ParameterizedType) type).getOwnerType()); Type owner = ((ParameterizedType) type).getOwnerType();
return typeToClass(owner == null ? ((ParameterizedType) type).getRawType() : owner);
} }
public static Type[] getGenericType(final Type[] types, final Type declaringClass) { public static Type[] getGenericType(final Type[] types, final Type declaringClass) {