This commit is contained in:
地平线
2015-05-06 15:25:57 +08:00
parent 282081cf95
commit 29c66f63d0
15 changed files with 590 additions and 167 deletions

View File

@@ -40,6 +40,10 @@ public abstract class Factory<R extends Reader, W extends Writer> {
private final HashMap<AccessibleObject, ConvertColumnEntry> columnEntrys = new HashMap();
private final Set<Class> skipIgnores = new HashSet<>();
private boolean skipAllIgnore = false;
protected Factory(Factory<R, W> parent) {
this.parent = parent;
if (parent == null) {
@@ -111,11 +115,38 @@ public abstract class Factory<R extends Reader, W extends Writer> {
if (en != null) return en;
final ConvertType ct = this.getConvertType();
for (ConvertColumn ref : field.getAnnotationsByType(ConvertColumn.class)) {
if (ref.type().contains(ct)) return new ConvertColumnEntry(ref);
if (ref.type().contains(ct)) {
ConvertColumnEntry entry = new ConvertColumnEntry(ref);
if (skipAllIgnore) {
entry.setIgnore(false);
return entry;
}
if (skipIgnores.isEmpty()) return entry;
if (skipIgnores.contains(((Member) field).getDeclaringClass())) entry.setIgnore(false);
return entry;
}
}
return null;
}
/**
* 使所有类的所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false
* <p>
* @param skipIgnore
*/
public final void registerSkipAllIgnore(final boolean skipIgnore) {
this.skipAllIgnore = skipIgnore;
}
/**
* 使该类所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false
* <p>
* @param type
*/
public final void registerSkipIgnore(final Class type) {
skipIgnores.add(type);
}
public final boolean register(final Class type, String column, ConvertColumnEntry entry) {
if (type == null || column == null || entry == null) return false;
try {

View File

@@ -483,6 +483,16 @@ public final class JsonReader implements Reader {
return null;
}
}
} else {
final int start = currpos;
for (;;) {
char ch = text0[currpos];
if (ch == ',' || ch <= ' ' || ch == '}' || ch == ']' || ch == ':') break;
currpos++;
}
if (currpos == start) throw new ConvertException("expected a string after a key but '" + text0[position] + "' (position = " + position + ")");
this.position = currpos - 1;
return new String(text0, start, currpos - start);
}
this.position = currpos;
throw new ConvertException("expected a ':' after a key but '" + text0[position] + "' (position = " + position + ")");

View File

@@ -18,7 +18,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
/**
*
* @author zhangjx
*/
*/
public abstract class BasedHttpServlet extends HttpServlet {
private Map.Entry<String, Entry>[] actions;
@@ -28,7 +28,7 @@ public abstract class BasedHttpServlet extends HttpServlet {
for (Map.Entry<String, Entry> en : actions) {
if (request.getRequestURI().startsWith(en.getKey())) {
Entry entry = en.getValue();
if (entry.ignore || authenticate(request, response)) entry.servlet.execute(request, response);
if (entry.ignore || authenticate(entry.moduleid, entry.actionid, request, response)) entry.servlet.execute(request, response);
return;
}
}
@@ -48,7 +48,7 @@ public abstract class BasedHttpServlet extends HttpServlet {
}
}
public abstract boolean authenticate(HttpRequest request, HttpResponse response) throws IOException;
public abstract boolean authenticate(int module, int actionid, HttpRequest request, HttpResponse response) throws IOException;
private HashMap<String, Entry> load() {
final boolean typeIgnore = this.getClass().getAnnotation(AuthIgnore.class) != null;

View File

@@ -5,6 +5,7 @@
*/
package com.wentch.redkale.net.http;
import com.wentch.redkale.util.ByteArray;
import com.wentch.redkale.convert.json.*;
import com.wentch.redkale.net.*;
import com.wentch.redkale.util.AnyValue.DefaultAnyValue;

View File

@@ -27,6 +27,53 @@ public final class HttpResourceServlet extends HttpServlet {
private static final Logger logger = Logger.getLogger(HttpResourceServlet.class.getSimpleName());
protected class WatchThread extends Thread {
protected final File root;
protected final WatchService watcher;
public WatchThread(File root) throws IOException {
this.root = root;
this.setName("Servlet-ResourceWatch-Thread");
this.setDaemon(true);
this.watcher = this.root.toPath().getFileSystem().newWatchService();
}
@Override
public void run() {
try {
final String rootstr = root.getCanonicalPath();
while (!this.isInterrupted()) {
final WatchKey key = watcher.take();
final Path parent = keymaps.get(key);
if (parent == null) {
key.cancel();
continue;
}
key.pollEvents().stream().forEach((event) -> {
try {
Path path = parent.resolve((Path) event.context());
final String uri = path.toString().substring(rootstr.length()).replace('\\', '/');
//logger.log(Level.FINEST, "file(" + uri + ") happen " + event.kind() + " event");
Thread.sleep(1000L); //等待update file完毕
if (event.kind() == ENTRY_DELETE) {
files.remove(uri);
} else if (event.kind() == ENTRY_MODIFY) {
FileEntry en = files.get(uri);
if (en != null) en.update();
}
} catch (Exception ex) {
logger.log(Level.FINE, event.context() + " occur erroneous", ex);
}
});
key.reset();
}
} catch (Exception e) {
}
}
}
//缓存总大小, 默认128M
protected long cachelimit = 128 * 1024 * 1024L;
@@ -39,29 +86,33 @@ public final class HttpResourceServlet extends HttpServlet {
protected final ConcurrentHashMap<String, FileEntry> files = new ConcurrentHashMap<>();
protected WatchService watcher;
protected final ConcurrentHashMap<WatchKey, Path> keymaps = new ConcurrentHashMap<>();
protected SimpleEntry<Pattern, String>[] locationRewrites;
protected Thread watchThread;
protected WatchThread watchThread;
protected List<SimpleEntry<File, WatchThread>> resx;
protected Predicate<String> ranges;
@Override
public void init(Context context, AnyValue config) {
String[] rootstrs = null;
if (config != null) {
String rootstr = config.getValue("webroot", "root").trim();
if (rootstr.indexOf(':') < 0 && rootstr.indexOf('/') != 0 && System.getProperty("APP_HOME") != null) {
rootstr = new File(System.getProperty("APP_HOME"), rootstr).getPath();
rootstrs = config.getValue("webroot", "root").trim().split(",");
for (int i = 0; i < rootstrs.length; i++) {
String rootstr = rootstrs[i];
if (rootstr.indexOf(':') < 0 && rootstr.indexOf('/') != 0 && System.getProperty("APP_HOME") != null) {
rootstrs[i] = new File(System.getProperty("APP_HOME"), rootstr).getPath();
}
}
String rangesValue = config.getValue("ranges");
this.ranges = rangesValue != null ? Pattern.compile(rangesValue).asPredicate() : null;
try {
this.root = new File(rootstr).getCanonicalFile();
this.root = new File(rootstrs[0]).getCanonicalFile();
} catch (IOException ioe) {
this.root = new File(rootstr);
this.root = new File(rootstrs[0]);
}
AnyValue cacheconf = config.getAnyValue("caches");
if (cacheconf != null) {
@@ -83,62 +134,36 @@ public final class HttpResourceServlet extends HttpServlet {
if (this.cachelimit < 1) return;
if (this.root != null) {
try {
this.watcher = this.root.toPath().getFileSystem().newWatchService();
this.watchThread = new Thread() {
@Override
public void run() {
try {
final String rootstr = root.getCanonicalPath();
while (!this.isInterrupted()) {
final WatchKey key = watcher.take();
final Path parent = keymaps.get(key);
if (parent == null) {
key.cancel();
continue;
}
key.pollEvents().stream().forEach((event) -> {
try {
Path path = parent.resolve((Path) event.context());
final String uri = path.toString().substring(rootstr.length()).replace('\\', '/');
//logger.log(Level.FINEST, "file(" + uri + ") happen " + event.kind() + " event");
Thread.sleep(1000L); //等待update file完毕
if (event.kind() == ENTRY_DELETE) {
files.remove(uri);
} else if (event.kind() == ENTRY_MODIFY) {
FileEntry en = files.get(uri);
if (en != null) en.update();
}
} catch (Exception ex) {
logger.log(Level.FINE, event.context() + " occur erroneous", ex);
}
});
key.reset();
}
} catch (Exception e) {
}
}
};
this.watchThread.setName("Servlet-ResourceWatch-Thread");
this.watchThread.setDaemon(true);
this.watchThread = new WatchThread(this.root);
this.watchThread.start();
} catch (IOException ex) {
logger.log(Level.WARNING, HttpResourceServlet.class.getSimpleName() + " start watch-thread error", ex);
}
if (rootstrs != null && rootstrs.length > 1) {
resx = new ArrayList<>(rootstrs.length - 1);
for (int i = 1; i < rootstrs.length; i++) {
try {
File f = new File(rootstrs[i]).getCanonicalFile();
WatchThread t = new WatchThread(f);
t.start();
resx.add(new SimpleEntry<>(f, t));
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
}
@Override
public void destroy(Context context, AnyValue config) {
if (this.watcher != null) {
if (this.watchThread != null) {
try {
this.watcher.close();
this.watchThread.watcher.close();
} catch (IOException ex) {
ex.printStackTrace();
logger.log(Level.WARNING, HttpResourceServlet.class.getSimpleName() + " close watch-thread error", ex);
}
}
if (this.watchThread != null && this.watchThread.isAlive()) {
this.watchThread.interrupt();
if (this.watchThread.isAlive()) this.watchThread.interrupt();
}
}
@@ -168,10 +193,10 @@ public final class HttpResourceServlet extends HttpServlet {
}
if (uri.length() == 0 || uri.equals("/")) uri = "/index.html";
//System.out.println(request);
FileEntry entry = watcher == null ? createFileEntry(uri) : files.get(uri);
FileEntry entry = watchThread == null ? createFileEntry(uri) : files.get(uri);
if (entry == null) {
entry = createFileEntry(uri);
if (entry != null && watcher != null) files.put(uri, entry);
if (entry != null && watchThread != null) files.put(uri, entry);
}
if (entry == null) {
response.finish404();
@@ -182,12 +207,30 @@ public final class HttpResourceServlet extends HttpServlet {
private FileEntry createFileEntry(String uri) {
File file = new File(root, uri);
if (!file.isFile() || !file.canRead()) return null;
if (!file.isFile() || !file.canRead()) {
if (resx != null) {
for (SimpleEntry<File, WatchThread> en : resx) {
File f = new File(en.getKey(), uri);
if (f.isFile() && f.canRead()) {
FileEntry fe = new FileEntry(this, f);
if (watchThread == null) return fe;
try {
Path p = f.getParentFile().toPath();
keymaps.put(p.register(en.getValue().watcher, ENTRY_MODIFY, ENTRY_DELETE), p);
} catch (IOException e) {
logger.log(Level.INFO, HttpResourceServlet.class.getSimpleName() + " create FileEntry(" + uri + ") erroneous", e);
}
return fe;
}
}
}
return null;
}
FileEntry en = new FileEntry(this, file);
if (watcher == null) return en;
if (watchThread == null) return en;
try {
Path p = file.getParentFile().toPath();
keymaps.put(p.register(watcher, ENTRY_MODIFY, ENTRY_DELETE), p);
keymaps.put(p.register(watchThread.watcher, ENTRY_MODIFY, ENTRY_DELETE), p);
} catch (IOException e) {
logger.log(Level.INFO, HttpResourceServlet.class.getSimpleName() + " create FileEntry(" + uri + ") erroneous", e);
}

View File

@@ -49,7 +49,7 @@ public final class HttpServer extends Server {
final int port = this.address.getPort();
AtomicLong createBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("HTTP_" + port + ".Buffer.creatCounter");
AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("HTTP_" + port + ".Buffer.cycleCounter");
int rcapacity = Math.max(this.capacity, 8 * 1024);
int rcapacity = Math.max(this.capacity, 16 * 1024 + 8); //兼容 HTTP 2.0
ObjectPool<ByteBuffer> bufferPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, this.bufferPoolSize,
(Object... params) -> ByteBuffer.allocateDirect(rcapacity), null, (e) -> {
if (e == null || e.isReadOnly() || e.capacity() != rcapacity) return false;

View File

@@ -5,6 +5,7 @@
*/
package com.wentch.redkale.net.http;
import com.wentch.redkale.util.ByteArray;
import java.io.*;
import java.nio.charset.*;
import java.util.*;

View File

@@ -5,7 +5,6 @@
*/
package com.wentch.redkale.source;
import com.wentch.redkale.source.DataSource;
import com.wentch.redkale.source.DistributeGenerator.DistributeTables;
import static com.wentch.redkale.source.FilterInfo.formatToString;
import com.wentch.redkale.util.*;
@@ -351,9 +350,7 @@ public final class DataJDBCSource implements DataSource {
EntityInfo<T> info = EntityInfo.load(clazz, this);
EntityCache<T> cache = info.getCache();
if (cache == null) return;
cache.clear();
List<T> all = queryList(clazz, null);
cache.fullLoad(all);
cache.fullLoad(queryList(clazz, null));
}
//----------------------insert-----------------------------
@@ -565,22 +562,6 @@ public final class DataJDBCSource implements DataSource {
public <T> void delete(Class<T> clazz, Serializable... ids) {
Connection conn = createWriteSQLConnection();
try {
if (ids != null && ids.length == 1 && ids[0] != null && ids[0].getClass().isArray()) {
Class clz = ids[0].getClass();
if (clz == long[].class) {
long[] vs = (long[]) ids[0];
ids = new Serializable[vs.length];
for (int i = 0; i < vs.length; i++) {
ids[i] = vs[i];
}
} else if (clz == int[].class) {
int[] vs = (int[]) ids[0];
ids = new Serializable[vs.length];
for (int i = 0; i < vs.length; i++) {
ids[i] = vs[i];
}
}
}
delete(conn, clazz, ids);
} finally {
closeSQLConnection(conn);
@@ -641,11 +622,24 @@ public final class DataJDBCSource implements DataSource {
try {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
String sql = "DELETE FROM " + info.getTable() + " WHERE " + info.getSQLColumn(column);
if (keys.length == 1) {
if (keys.length == 1 && !keys[0].getClass().isArray()) {
sql += " = " + formatToString(keys[0]);
} else {
sql += " IN (";
boolean flag = false;
if (keys.length == 1 && keys[0].getClass().isArray()) {
Class keytype = keys[0].getClass();
if (keytype.getComponentType().isPrimitive()) {
Object array = keys[0];
Serializable[] keys0 = new Serializable[Array.getLength(array)];
for (int i = 0; i < keys0.length; i++) {
keys0[i] = (Serializable) Array.get(array, i);
}
keys = keys0;
} else {
keys = (Serializable[]) keys[0];
}
}
for (final Serializable value : keys) {
if (flag) sql += ",";
sql += formatToString(value);
@@ -662,7 +656,8 @@ public final class DataJDBCSource implements DataSource {
final EntityCache<T> cache = info.inner.getCache();
if (cache == null) return;
final Attribute<T, ?> attr = info.getAttribute(column);
Serializable[] ids = cache.delete((T t) -> Arrays.binarySearch(keys, attr.get(t)) >= 0);
final Serializable[] keys2 = keys;
Serializable[] ids = cache.delete((T t) -> Arrays.binarySearch(keys2, attr.get(t)) >= 0);
if (cacheListener != null) cacheListener.delete(name, clazz, ids);
} catch (SQLException e) {
throw new RuntimeException(e);
@@ -1323,26 +1318,107 @@ public final class DataJDBCSource implements DataSource {
}
}
//-----------------------list----------------------------
//-----------------------list set----------------------------
@Override
public <T> int[] queryColumnIntSet(String selectedColumn, Class<T> clazz, String column, Serializable key) {
return formatCollectionToIntArray(queryColumnSet(selectedColumn, clazz, column, key));
}
@Override
public <T> long[] queryColumnLongSet(String selectedColumn, Class<T> clazz, String column, Serializable key) {
return formatCollectionToLongArray(queryColumnSet(selectedColumn, clazz, column, key));
}
@Override
public <T> int[] queryColumnIntList(String selectedColumn, Class<T> clazz, String column, Serializable key) {
return formatCollectionToIntArray(queryColumnList(selectedColumn, clazz, column, key));
}
@Override
public <T> long[] queryColumnLongList(String selectedColumn, Class<T> clazz, String column, Serializable key) {
return formatCollectionToLongArray(queryColumnList(selectedColumn, clazz, column, key));
}
@Override
public <T, V> Set<V> queryColumnSet(String selectedColumn, Class<T> clazz, String column, Serializable key) {
return queryColumnSet(selectedColumn, clazz, column, FilterExpress.EQUAL, key);
}
@Override
public <T, V> List<V> queryColumnList(String selectedColumn, Class<T> clazz, String column, Serializable key) {
return queryColumnList(selectedColumn, clazz, column, FilterExpress.EQUAL, key);
}
@Override
public <T> int[] queryColumnIntSet(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
return formatCollectionToIntArray(queryColumnSet(selectedColumn, clazz, column, express, key));
}
@Override
public <T> long[] queryColumnLongSet(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
return formatCollectionToLongArray(queryColumnSet(selectedColumn, clazz, column, express, key));
}
@Override
public <T> int[] queryColumnIntList(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
return formatCollectionToIntArray(queryColumnList(selectedColumn, clazz, column, express, key));
}
@Override
public <T> long[] queryColumnLongList(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
return formatCollectionToLongArray(queryColumnList(selectedColumn, clazz, column, express, key));
}
@Override
public <T, V> Set<V> queryColumnSet(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
return (Set<V>) queryColumnCollection(true, selectedColumn, clazz, column, express, key);
}
@Override
public <T, V> List<V> queryColumnList(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
return (List<V>) queryColumnCollection(false, selectedColumn, clazz, column, express, key);
}
private static int[] formatCollectionToIntArray(Collection<Integer> collection) {
if (collection == null || collection.isEmpty()) return new int[0];
int[] rs = new int[collection.size()];
int i = 0;
for (int v : collection) {
rs[i++] = v;
}
return rs;
}
private static long[] formatCollectionToLongArray(Collection<Long> collection) {
if (collection == null || collection.isEmpty()) return new long[0];
long[] rs = new long[collection.size()];
int i = 0;
for (long v : collection) {
rs[i++] = v;
}
return rs;
}
/**
* 根据指定字段值查询对象某个字段的集合
*
* @param <T>
* @param <V>
* @param set
* @param selectedColumn
* @param clazz
* @param column
* @param express
* @param key
* @return
*/
@Override
public <T, V> List<V> queryColumnList(String selectedColumn, Class<T> clazz, String column, Serializable key) {
protected final <T, V> Collection<V> queryColumnCollection(final boolean set, String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityCache<T> cache = info.inner.getCache();
if (cache != null) {
final Attribute<T, ?> attr = info.getAttribute(column);
List<T> list = cache.queryList(null, (T t) -> key.equals(attr.get(t)), null);
final List<V> rs = new ArrayList<>();
Predicate<T> filter = genFilter(info.getAttribute(column), express, key);
List<T> list = cache.queryList(SelectColumn.createIncludes(selectedColumn), filter, null);
final Collection<V> rs = set ? new LinkedHashSet<>() : new ArrayList<>();
if (!list.isEmpty()) {
final Attribute<T, V> selected = (Attribute<T, V>) info.getAttribute(selectedColumn);
for (T t : list) {
@@ -1353,18 +1429,17 @@ public final class DataJDBCSource implements DataSource {
}
final Connection conn = createReadSQLConnection();
try {
final List<V> list = new ArrayList();
final String sql = "SELECT " + info.getSQLColumn(selectedColumn) + " FROM " + info.getTable() + " WHERE " + info.getSQLColumn(column) + " = ?";
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " query sql=" + sql.replaceFirst("\\?", String.valueOf(key)));
final PreparedStatement ps = conn.prepareStatement(sql);
ps.setObject(1, key);
final ResultSet set = ps.executeQuery();
while (set.next()) {
list.add((V) set.getObject(1));
final Collection<V> collection = set ? new LinkedHashSet<>() : new ArrayList<>();
final String sql = genSQL(info.getSQLColumn(selectedColumn), info, column, express, key);
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " query sql=" + sql);
final Statement ps = conn.createStatement();
final ResultSet rs = ps.executeQuery(sql);
while (rs.next()) {
collection.add((V) rs.getObject(1));
}
set.close();
rs.close();
ps.close();
return list;
return collection;
} catch (Exception ex) {
throw new RuntimeException(ex);
} finally {
@@ -1422,55 +1497,7 @@ public final class DataJDBCSource implements DataSource {
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final EntityCache<T> cache = info.inner.getCache();
if (cache != null) {
final Attribute<T, ?> attr = info.getAttribute(column);
Predicate<T> filter = null;
switch (express) {
case EQUAL:
filter = (T t) -> key.equals(attr.get(t));
break;
case NOTEQUAL:
filter = (T t) -> !key.equals(attr.get(t));
break;
case GREATERTHAN:
filter = (T t) -> ((Number) attr.get(t)).longValue() > ((Number) key).longValue();
break;
case LESSTHAN:
filter = (T t) -> ((Number) attr.get(t)).longValue() < ((Number) key).longValue();
break;
case GREATERTHANOREQUALTO:
filter = (T t) -> ((Number) attr.get(t)).longValue() >= ((Number) key).longValue();
break;
case LESSTHANOREQUALTO:
filter = (T t) -> ((Number) attr.get(t)).longValue() <= ((Number) key).longValue();
break;
case LIKE:
filter = (T t) -> {
Object rs = attr.get(t);
return rs != null && rs.toString().contains(key.toString());
};
break;
case NOTLIKE:
filter = (T t) -> {
Object rs = attr.get(t);
return rs == null || !rs.toString().contains(key.toString());
};
break;
case ISNULL:
filter = (T t) -> attr.get(t) == null;
break;
case ISNOTNULL:
filter = (T t) -> attr.get(t) != null;
break;
case OPAND:
filter = (T t) -> (((Number) attr.get(t)).longValue() & ((Number) key).longValue()) > 0;
break;
case OPOR:
filter = (T t) -> (((Number) attr.get(t)).longValue() | ((Number) key).longValue()) > 0;
break;
case OPANDNO:
filter = (T t) -> (((Number) attr.get(t)).longValue() & ((Number) key).longValue()) == 0;
break;
}
Predicate<T> filter = genFilter(info.getAttribute(column), express, key);
List<T> rs = cache.queryList(selects, filter, null);
if (!rs.isEmpty() || cache.isFullLoaded()) return rs;
}
@@ -1478,11 +1505,10 @@ public final class DataJDBCSource implements DataSource {
try {
final SelectColumn sels = selects;
final List<T> list = new ArrayList();
final String sql = "SELECT * FROM " + info.getTable() + " WHERE " + info.getSQLColumn(column) + " " + express.value() + " ?";
final String sql = genSQL("*", info, column, express, key);
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " query sql=" + sql);
final PreparedStatement ps = conn.prepareStatement(sql);
ps.setObject(1, key);
final ResultSet set = ps.executeQuery();
final Statement ps = conn.createStatement();
final ResultSet set = ps.executeQuery(sql);
while (set.next()) {
final T result = info.createInstance();
for (AttributeX<T, Object> attr : info.query.attributes) {
@@ -1500,6 +1526,124 @@ public final class DataJDBCSource implements DataSource {
}
}
private String genSQL(String queryColumn, EntityXInfo info, String column, FilterExpress express, Serializable key) {
String sql = "SELECT " + queryColumn + " FROM " + info.getTable() + " WHERE " + info.getSQLColumn(column) + " " + express.value();
if (key instanceof Number) {
sql += " " + key;
} else if (key instanceof Collection) {
StringBuilder sb = new StringBuilder();
for (Object o : (Collection) key) {
if (sb.length() > 0) sb.append(',');
if (o instanceof Number) {
sb.append('"').append(o).append('"');
} else {
sb.append('"').append(o.toString().replace("\"", "\\\"")).append('"');
}
}
sql += " (" + sb + ")";
} else if (key.getClass().isArray()) {
StringBuilder sb = new StringBuilder();
int len = Array.getLength(key);
for (int i = 0; i < len; i++) {
Object o = Array.get(key, i);
if (sb.length() > 0) sb.append(',');
if (o instanceof Number) {
sb.append('"').append(o).append('"');
} else {
sb.append('"').append(o.toString().replace("\"", "\\\"")).append('"');
}
}
sql += " (" + sb + ")";
} else {
sql += " \"" + key.toString().replace("\"", "\\\"") + "\"";
}
return sql;
}
private <T> Predicate<T> genFilter(final Attribute<T, ?> attr, FilterExpress express, Serializable key) {
Predicate<T> filter = null;
switch (express) {
case EQUAL:
filter = (T t) -> key.equals(attr.get(t));
break;
case NOTEQUAL:
filter = (T t) -> !key.equals(attr.get(t));
break;
case GREATERTHAN:
filter = (T t) -> ((Number) attr.get(t)).longValue() > ((Number) key).longValue();
break;
case LESSTHAN:
filter = (T t) -> ((Number) attr.get(t)).longValue() < ((Number) key).longValue();
break;
case GREATERTHANOREQUALTO:
filter = (T t) -> ((Number) attr.get(t)).longValue() >= ((Number) key).longValue();
break;
case LESSTHANOREQUALTO:
filter = (T t) -> ((Number) attr.get(t)).longValue() <= ((Number) key).longValue();
break;
case IN:
case NOTIN:
if (key instanceof Collection) {
filter = (T t) -> {
Object rs = attr.get(t);
return rs != null && ((Collection) key).contains(rs);
};
} else {
Serializable[] keys;
if (key.getClass().isArray()) {
Class keytype = key.getClass();
if (keytype.getComponentType().isPrimitive()) {
Object array = key;
Serializable[] keys0 = new Serializable[Array.getLength(array)];
for (int i = 0; i < keys0.length; i++) {
keys0[i] = (Serializable) Array.get(array, i);
}
keys = keys0;
} else {
keys = (Serializable[]) key;
}
} else {
keys = new Serializable[]{key};
}
Serializable[] keys0 = keys;
filter = (T t) -> {
Object rs = attr.get(t);
return rs != null && Arrays.binarySearch(keys0, rs) > -1;
};
}
if (express == FilterExpress.NOTIN) filter = filter.negate();
break;
case LIKE:
filter = (T t) -> {
Object rs = attr.get(t);
return rs != null && rs.toString().contains(key.toString());
};
break;
case NOTLIKE:
filter = (T t) -> {
Object rs = attr.get(t);
return rs == null || !rs.toString().contains(key.toString());
};
break;
case ISNULL:
filter = (T t) -> attr.get(t) == null;
break;
case ISNOTNULL:
filter = (T t) -> attr.get(t) != null;
break;
case OPAND:
filter = (T t) -> (((Number) attr.get(t)).longValue() & ((Number) key).longValue()) > 0;
break;
case OPOR:
filter = (T t) -> (((Number) attr.get(t)).longValue() | ((Number) key).longValue()) > 0;
break;
case OPANDNO:
filter = (T t) -> (((Number) attr.get(t)).longValue() & ((Number) key).longValue()) == 0;
break;
}
return filter;
}
/**
* 根据过滤对象FilterBean查询对象集合
*
@@ -1528,6 +1672,33 @@ public final class DataJDBCSource implements DataSource {
}
//-----------------------sheet----------------------------
/**
* 根据指定参数查询对象某个字段的集合
* <p>
* @param <T>
* @param <V>
* @param selectedColumn
* @param clazz
* @param flipper
* @param bean
* @return
*/
@Override
public <T, V> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, final Flipper flipper, final FilterBean bean) {
Sheet<T> sheet = querySheet(clazz, SelectColumn.createIncludes(selectedColumn), flipper, bean);
final Sheet<V> rs = new Sheet<>();
if (sheet.isEmpty()) return rs;
rs.setTotal(sheet.getTotal());
final EntityXInfo<T> info = EntityXInfo.load(this, clazz);
final Attribute<T, V> selected = (Attribute<T, V>) info.getAttribute(selectedColumn);
final List<V> list = new ArrayList<>();
for (T t : sheet.getRows()) {
list.add(selected.get(t));
}
rs.setRows(list);
return rs;
}
/**
* 根据过滤对象FilterBean和翻页对象Flipper查询一页的数据
*
@@ -1558,18 +1729,14 @@ public final class DataJDBCSource implements DataSource {
final EntityCache<T> cache = info.inner.getCache();
if (cache != null) {
Predicate<T> filter = null;
Comparator<T> sort = null;
boolean valid = true;
if (bean != null) {
FilterInfo finfo = FilterInfo.load(bean.getClass(), this);
valid = finfo.isValidCacheJoin();
if (valid) {
filter = finfo.getFilterPredicate(info.inner, bean);
sort = finfo.getSortComparator(info.inner, flipper);
}
if (valid) filter = finfo.getFilterPredicate(info.inner, bean);
}
if (valid) {
Sheet<T> sheet = cache.querySheet(selects, filter, flipper, sort);
Sheet<T> sheet = cache.querySheet(selects, filter, flipper, FilterInfo.getSortComparator(info.inner, flipper));
if (!sheet.isEmpty() || cache.isFullLoaded()) return sheet;
}
}
@@ -2084,7 +2251,7 @@ public final class DataJDBCSource implements DataSource {
}
public void createPrimaryValue(T src) {
long v = primaryValue.incrementAndGet() * allocationSize + nodeid;
long v = allocationSize > 1 ? (primaryValue.incrementAndGet() * allocationSize + nodeid) : primaryValue.incrementAndGet();
Class p = inner.getPrimaryType();
if (p == int.class || p == Integer.class) {
getPrimary().set(src, (Integer) ((Long) v).intValue());

View File

@@ -59,6 +59,66 @@ final class DataJPASource implements DataSource {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T, V> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, Flipper flipper, FilterBean bean) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T, V> Set<V> queryColumnSet(String selectedColumn, Class<T> clazz, String column, Serializable key) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T, V> Set<V> queryColumnSet(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T, V> List<V> queryColumnList(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T> int[] queryColumnIntSet(String selectedColumn, Class<T> clazz, String column, Serializable key) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T> long[] queryColumnLongSet(String selectedColumn, Class<T> clazz, String column, Serializable key) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T> int[] queryColumnIntList(String selectedColumn, Class<T> clazz, String column, Serializable key) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T> long[] queryColumnLongList(String selectedColumn, Class<T> clazz, String column, Serializable key) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T> int[] queryColumnIntSet(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T> long[] queryColumnLongSet(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T> int[] queryColumnIntList(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T> long[] queryColumnLongList(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
private static class DataJPAConnection extends DataConnection {
private final EntityManager manager;

View File

@@ -330,7 +330,28 @@ public interface DataSource {
*/
public <T> T find(final Class<T> clazz, final FilterBean bean);
//-----------------------list----------------------------
//-----------------------list set----------------------------
public <T> int[] queryColumnIntSet(String selectedColumn, Class<T> clazz, String column, Serializable key);
public <T> long[] queryColumnLongSet(String selectedColumn, Class<T> clazz, String column, Serializable key);
public <T> int[] queryColumnIntList(String selectedColumn, Class<T> clazz, String column, Serializable key);
public <T> long[] queryColumnLongList(String selectedColumn, Class<T> clazz, String column, Serializable key);
/**
* 根据指定字段值查询对象某个字段的集合
*
* @param <T>
* @param <V>
* @param selectedColumn
* @param clazz
* @param column
* @param key
* @return
*/
public <T, V> Set<V> queryColumnSet(String selectedColumn, Class<T> clazz, String column, Serializable key);
/**
* 根据指定字段值查询对象某个字段的集合
*
@@ -344,6 +365,42 @@ public interface DataSource {
*/
public <T, V> List<V> queryColumnList(String selectedColumn, Class<T> clazz, String column, Serializable key);
public <T> int[] queryColumnIntSet(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key);
public <T> long[] queryColumnLongSet(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key);
public <T> int[] queryColumnIntList(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key);
public <T> long[] queryColumnLongList(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key);
/**
* 根据指定字段值查询对象某个字段的集合
*
* @param <T>
* @param <V>
* @param selectedColumn
* @param clazz
* @param column
* @param express
* @param key
* @return
*/
public <T, V> Set<V> queryColumnSet(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key);
/**
* 根据指定字段值查询对象某个字段的集合
*
* @param <T>
* @param <V>
* @param selectedColumn
* @param clazz
* @param column
* @param express
* @param key
* @return
*/
public <T, V> List<V> queryColumnList(String selectedColumn, Class<T> clazz, String column, FilterExpress express, Serializable key);
/**
* 根据指定字段值查询对象集合
*
@@ -415,6 +472,19 @@ public interface DataSource {
public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final FilterBean bean);
//-----------------------sheet----------------------------
/**
* 根据指定参数查询对象某个字段的集合
* <p>
* @param <T>
* @param <V>
* @param selectedColumn
* @param clazz
* @param flipper
* @param bean
* @return
*/
public <T, V> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, final Flipper flipper, final FilterBean bean);
/**
* 根据过滤对象FilterBean和翻页对象Flipper查询一页的数据
*

View File

@@ -35,5 +35,10 @@ public @interface DistributeGenerator {
int initialValue() default 1;
/**
* 如果allocationSize的值小于或等于1,则主键不会加上nodeid
* <p>
* @return
*/
int allocationSize() default 1000;
}

View File

@@ -96,9 +96,9 @@ final class EntityCache<T> {
return rs.isPresent() ? (needcopy ? reproduce.copy(this.creator.create(), rs.get()) : rs.get()) : null;
}
public List<T> queryList(final SelectColumn selects, final Predicate<T> filter, final Comparator<T> sort) {
public Collection<T> queryCollection(final boolean set, final SelectColumn selects, final Predicate<T> filter, final Comparator<T> sort) {
boolean parallel = isParallel();
final List<T> rs = parallel ? new CopyOnWriteArrayList<>() : new ArrayList<>();
final Collection<T> rs = parallel ? (set ? new CopyOnWriteArraySet<>() : new CopyOnWriteArrayList<>()) : (set ? new LinkedHashSet<>() : new ArrayList<>());
Stream<T> stream = listStream();
if (filter != null) stream = stream.filter(filter);
if (sort != null) stream = stream.sorted(sort);
@@ -115,7 +115,15 @@ final class EntityCache<T> {
rs.add(item);
});
}
return parallel ? new ArrayList<>(rs) : rs;
return parallel ? (set ? new LinkedHashSet<>(rs) : new ArrayList<>(rs)) : rs;
}
public Set<T> querySet(final SelectColumn selects, final Predicate<T> filter, final Comparator<T> sort) {
return (Set<T>) queryCollection(true, selects, filter, sort);
}
public List<T> queryList(final SelectColumn selects, final Predicate<T> filter, final Comparator<T> sort) {
return (List<T>) queryCollection(false, selects, filter, sort);
}
public Sheet<T> querySheet(final SelectColumn selects, final Predicate<T> filter, final Flipper flipper, final Comparator<T> sort) {

View File

@@ -13,6 +13,7 @@ import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.logging.Logger;
import javax.persistence.*;
/**
*
@@ -60,6 +61,7 @@ final class FilterInfo<T extends FilterBean> {
do {
for (Field field : cltmp.getDeclaredFields()) {
if (field.getAnnotation(Ignore.class) != null) continue;
if (field.getAnnotation(Transient.class) != null) continue;
if (Modifier.isStatic(field.getModifiers())) continue;
if (fields.contains(field.getName())) continue;
char[] chars = field.getName().toCharArray();
@@ -155,7 +157,7 @@ final class FilterInfo<T extends FilterBean> {
return rootNode.getFilterPredicate(info, bean);
}
public <E> Comparator<E> getSortComparator(EntityInfo<E> info, Flipper flipper) {
public static <E> Comparator<E> getSortComparator(EntityInfo<E> info, Flipper flipper) {
if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return null;
Comparator<E> comparator = null;
for (String item : flipper.getSort().split(",")) {

View File

@@ -3,9 +3,8 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.net.http;
package com.wentch.redkale.util;
import com.wentch.redkale.util.*;
import java.nio.*;
import java.nio.charset.*;
@@ -55,6 +54,10 @@ public final class ByteArray {
System.arraycopy(this.content, 0, buf, 0, count);
}
public byte[] directBytes() {
return content;
}
public int find(int offset, char value) {
return find(offset, (byte) value);
}
@@ -80,6 +83,10 @@ public final class ByteArray {
if (count > 0) count--;
}
public void addInt(int value) {
add((byte) (value >> 24 & 0xFF), (byte) (value >> 16 & 0xFF), (byte) (value >> 8 & 0xFF), (byte) (value & 0xFF));
}
public void add(byte value) {
if (count >= content.length - 1) {
byte[] ns = new byte[content.length + 8];
@@ -89,6 +96,16 @@ public final class ByteArray {
content[count++] = value;
}
public void add(byte... values) {
if (count >= content.length - values.length) {
byte[] ns = new byte[content.length + values.length];
System.arraycopy(content, 0, ns, 0, count);
this.content = ns;
}
System.arraycopy(content, count, values, 0, values.length);
count += values.length;
}
public void add(ByteBuffer buffer, int len) {
if (len < 1) return;
if (count >= content.length - len) {

View File

@@ -78,10 +78,18 @@ public final class Utility {
return today.getYear() * 10000 + today.getMonthValue() * 100 + today.getDayOfMonth();
}
public static String binToHexString(byte[] bytes) {
return new String(binToHex(bytes));
}
public static char[] binToHex(byte[] bytes) {
return binToHex(bytes, 0, bytes.length);
}
public static String binToHexString(byte[] bytes, int offset, int len) {
return new String(binToHex(bytes, offset, len));
}
public static char[] binToHex(byte[] bytes, int offset, int len) {
final char[] sb = new char[len * 2];
final int end = offset + len;