Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6413161dc8 | ||
|
|
46a89d9847 | ||
|
|
d83d6b5671 | ||
|
|
b1abe91bd2 | ||
|
|
bf4138178b | ||
|
|
5b99084616 | ||
|
|
b95064b87e | ||
|
|
e1eece34b7 | ||
|
|
19d6a06bfa | ||
|
|
2fd13d1481 | ||
|
|
23a0a80e3a | ||
|
|
bb493d43b5 | ||
|
|
ef9eaa0a66 | ||
|
|
1d640f943a | ||
|
|
84f5f065ad | ||
|
|
921aedaf9d | ||
|
|
0f545923b2 | ||
|
|
5b32a91874 | ||
|
|
25b2528416 | ||
|
|
d29c95c38f | ||
|
|
a661ab2ff5 | ||
|
|
ac08ebee75 | ||
|
|
8e1a287ed1 | ||
|
|
9b656b3970 | ||
|
|
a1c0bbf413 | ||
|
|
2ad8c5d425 | ||
|
|
75aaa980cf | ||
|
|
7c55326d23 | ||
|
|
aa3ade5912 | ||
|
|
c692deebe9 | ||
|
|
9ff161c97d | ||
|
|
5b1f820621 | ||
|
|
30b2cffcb8 | ||
|
|
709439bfca | ||
|
|
34adb238f7 | ||
|
|
76c54f8d54 | ||
|
|
6196c05f12 | ||
|
|
37df0af56c |
9
bin/restart.bat
Normal file
9
bin/restart.bat
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
SET APP_HOME=%~dp0
|
||||||
|
|
||||||
|
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||||
|
|
||||||
|
call %APP_HOME%\bin\shutdown.bat
|
||||||
|
|
||||||
|
call %APP_HOME%\bin\start.bat
|
||||||
20
bin/restart.sh
Normal file
20
bin/restart.sh
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
export LC_ALL="zh_CN.UTF-8"
|
||||||
|
|
||||||
|
APP_HOME=`dirname "$0"`
|
||||||
|
|
||||||
|
cd "$APP_HOME"/..
|
||||||
|
|
||||||
|
APP_HOME=`pwd`
|
||||||
|
|
||||||
|
if [ ! -f "$APP_HOME"/conf/application.xml ]; then
|
||||||
|
APP_HOME="$APP_HOME"/..
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$APP_HOME"
|
||||||
|
|
||||||
|
./bin/shutdown.sh
|
||||||
|
|
||||||
|
./bin/start.sh
|
||||||
|
|
||||||
@@ -37,9 +37,11 @@
|
|||||||
threads: 线程总数, 默认: <group>节点数*CPU核数*8
|
threads: 线程总数, 默认: <group>节点数*CPU核数*8
|
||||||
bufferCapacity: ByteBuffer的初始化大小, 默认: 8K;
|
bufferCapacity: ByteBuffer的初始化大小, 默认: 8K;
|
||||||
bufferPoolSize: ByteBuffer池的大小,默认: <group>节点数*CPU核数*8
|
bufferPoolSize: ByteBuffer池的大小,默认: <group>节点数*CPU核数*8
|
||||||
|
readTimeoutSecond: TCP读取超时秒数, 默认为6秒, 为0表示无超时限制
|
||||||
|
writeTimeoutSecond: TCP写入超时秒数, 默认为6秒, 为0表示无超时限制
|
||||||
strategy: 远程请求的负载均衡策略, 必须是org.redkale.net.TransportStrategy的实现类
|
strategy: 远程请求的负载均衡策略, 必须是org.redkale.net.TransportStrategy的实现类
|
||||||
-->
|
-->
|
||||||
<transport bufferCapacity="8K" bufferPoolSize="32" threads="32"/>
|
<transport bufferCapacity="8K" bufferPoolSize="32" threads="32" readTimeoutSecond="6" writeTimeoutSecond="6"/>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
一个组包含多个node, 同一Service服务可以由多个进程提供,这些进程称为一个GROUP,且同一GROUP内的进程必须在同一机房或局域网内
|
一个组包含多个node, 同一Service服务可以由多个进程提供,这些进程称为一个GROUP,且同一GROUP内的进程必须在同一机房或局域网内
|
||||||
@@ -64,7 +66,7 @@
|
|||||||
<!--
|
<!--
|
||||||
全局的数据源设置, 可以是CacheSource、DataSource, JDBC的DataSource通常通过persistence.xml配置,此处多用于CacheSource的配置
|
全局的数据源设置, 可以是CacheSource、DataSource, JDBC的DataSource通常通过persistence.xml配置,此处多用于CacheSource的配置
|
||||||
name: 资源名,用于依赖注入。
|
name: 资源名,用于依赖注入。
|
||||||
value:类名,必须是CacheSource或DataSource的子类,且必须实现Service接口。
|
value:类名,必须是CacheSource或DataSource的子类,且必须实现Service接口。如果是DataSource.class,系统自动映射成DataJdbcSource.class
|
||||||
groups: 指定groups。
|
groups: 指定groups。
|
||||||
xxx: 其他属性与子节点通过Service.init方法传入的AnyValue获取。
|
xxx: 其他属性与子节点通过Service.init方法传入的AnyValue获取。
|
||||||
-->
|
-->
|
||||||
@@ -92,7 +94,8 @@
|
|||||||
System.setProperty("convert.json.writer.buffer.defsize", "4096");
|
System.setProperty("convert.json.writer.buffer.defsize", "4096");
|
||||||
System.setProperty("convert.bson.writer.buffer.defsize", "4096");
|
System.setProperty("convert.bson.writer.buffer.defsize", "4096");
|
||||||
|
|
||||||
<properties>节点下也可包含非<property>节点,其节点可以通过@Resource(name="properties.xxxxxx")进行注入, 被注解的字段类型只能是AnyValue、AnyValue[]
|
<properties>节点下也可包含非<property>节点.
|
||||||
|
非<property>其节点可以通过@Resource(name="properties.xxxxxx")进行注入, 被注解的字段类型只能是AnyValue、AnyValue[]
|
||||||
-->
|
-->
|
||||||
<properties load="config.properties">
|
<properties load="config.properties">
|
||||||
<property name="system.property.yyyy" value="YYYYYY"/>
|
<property name="system.property.yyyy" value="YYYYYY"/>
|
||||||
@@ -147,7 +150,7 @@
|
|||||||
<service value="com.xxx.XXX2Service" name="" groups="xxx;yyy"/>
|
<service value="com.xxx.XXX2Service" name="" groups="xxx;yyy"/>
|
||||||
<!-- 给Service增加配置属性 -->
|
<!-- 给Service增加配置属性 -->
|
||||||
<service value="com.xxx.XXX1Service">
|
<service value="com.xxx.XXX1Service">
|
||||||
<!-- property节点值在 public void init(AnyValue conf) 方法中可以通过 AnyValue properties = conf.getAnyValue("properties");获取 -->
|
<!-- property值在public void init(AnyValue conf)方法中可以通过AnyValue properties=conf.getAnyValue("properties")获取 -->
|
||||||
<property name="xxxxxx" value="XXXXXXXX"/>
|
<property name="xxxxxx" value="XXXXXXXX"/>
|
||||||
<property name="xxxxxx" value="XXXXXXXX"/>
|
<property name="xxxxxx" value="XXXXXXXX"/>
|
||||||
</service>
|
</service>
|
||||||
@@ -172,7 +175,7 @@
|
|||||||
|
|
||||||
<!-- 给Filter增加配置属性 -->
|
<!-- 给Filter增加配置属性 -->
|
||||||
<filter value="com.xxx.XXX12Filter">
|
<filter value="com.xxx.XXX12Filter">
|
||||||
<!-- property节点值在 public void init(AnyValue conf) 方法中可以通过 AnyValue properties = conf.getAnyValue("properties");获取 -->
|
<!-- property值在public void init(AnyValue conf)方法中可以通过AnyValue properties=conf.getAnyValue("properties")获取 -->
|
||||||
<property name="xxxxxx" value="XXXXXXXX"/>
|
<property name="xxxxxx" value="XXXXXXXX"/>
|
||||||
<property name="xxxxxx" value="XXXXXXXX"/>
|
<property name="xxxxxx" value="XXXXXXXX"/>
|
||||||
</filter>
|
</filter>
|
||||||
|
|||||||
@@ -7,10 +7,11 @@
|
|||||||
module org.redkale {
|
module org.redkale {
|
||||||
|
|
||||||
requires java.se;
|
requires java.se;
|
||||||
requires jdk.unsupported;
|
requires jdk.unsupported; //sun.misc.Unsafe
|
||||||
|
|
||||||
exports javax.annotation;
|
exports javax.annotation;
|
||||||
exports javax.persistence;
|
exports javax.persistence;
|
||||||
|
exports org.redkale.asm;
|
||||||
exports org.redkale.boot;
|
exports org.redkale.boot;
|
||||||
exports org.redkale.boot.watch;
|
exports org.redkale.boot.watch;
|
||||||
exports org.redkale.convert;
|
exports org.redkale.convert;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ ClassReader.java
|
|||||||
ClassVisitor.java
|
ClassVisitor.java
|
||||||
ClassWriter.java
|
ClassWriter.java
|
||||||
Context.java
|
Context.java
|
||||||
|
CurrentFrame.java
|
||||||
Edge.java
|
Edge.java
|
||||||
FieldVisitor.java
|
FieldVisitor.java
|
||||||
FieldWriter.java
|
FieldWriter.java
|
||||||
@@ -18,25 +19,8 @@ Item.java
|
|||||||
Label.java
|
Label.java
|
||||||
MethodVisitor.java
|
MethodVisitor.java
|
||||||
MethodWriter.java
|
MethodWriter.java
|
||||||
|
ModuleVisitor.java
|
||||||
|
ModuleWriter.java
|
||||||
Opcodes.java
|
Opcodes.java
|
||||||
Type.java
|
Type.java
|
||||||
TypePath.java
|
TypePath.java
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Throwable {
|
|
||||||
File srcasmroot = new File("D:/JAVA/JDK源码/JDK9源码/java.base/jdk/internal/org/objectweb/asm");
|
|
||||||
File destasmroot = new File("D:/Java-Projects/RedkaleProject/src/org/redkale/asm");
|
|
||||||
String line = null;
|
|
||||||
LineNumberReader txtin = new LineNumberReader(new FileReader(new File(destasmroot, "asm.txt")));
|
|
||||||
while ((line = txtin.readLine()) != null) {
|
|
||||||
line = line.trim();
|
|
||||||
if (!line.endsWith(".java")) continue;
|
|
||||||
File srcfile = new File(srcasmroot, line);
|
|
||||||
File destfile = new File(destasmroot, line);
|
|
||||||
String content = Utility.readThenClose(new FileInputStream(srcfile));
|
|
||||||
FileOutputStream out = new FileOutputStream(destfile);
|
|
||||||
out.write(content.replace("jdk.internal.org.objectweb", "org.redkale").getBytes());
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -245,6 +245,8 @@ public final class Application {
|
|||||||
TransportStrategy strategy = null;
|
TransportStrategy strategy = null;
|
||||||
int bufferCapacity = 8 * 1024;
|
int bufferCapacity = 8 * 1024;
|
||||||
int bufferPoolSize = Runtime.getRuntime().availableProcessors() * 16;
|
int bufferPoolSize = Runtime.getRuntime().availableProcessors() * 16;
|
||||||
|
int readTimeoutSecond = TransportFactory.DEFAULT_READTIMEOUTSECOND;
|
||||||
|
int writeTimeoutSecond = TransportFactory.DEFAULT_WRITETIMEOUTSECOND;
|
||||||
AtomicLong createBufferCounter = new AtomicLong();
|
AtomicLong createBufferCounter = new AtomicLong();
|
||||||
AtomicLong cycleBufferCounter = new AtomicLong();
|
AtomicLong cycleBufferCounter = new AtomicLong();
|
||||||
if (resources != null) {
|
if (resources != null) {
|
||||||
@@ -255,6 +257,8 @@ public final class Application {
|
|||||||
//--------------transportBufferPool-----------
|
//--------------transportBufferPool-----------
|
||||||
bufferCapacity = Math.max(parseLenth(transportConf.getValue("bufferCapacity"), bufferCapacity), 4 * 1024);
|
bufferCapacity = Math.max(parseLenth(transportConf.getValue("bufferCapacity"), bufferCapacity), 4 * 1024);
|
||||||
bufferPoolSize = parseLenth(transportConf.getValue("bufferPoolSize"), groupsize * Runtime.getRuntime().availableProcessors() * 8);
|
bufferPoolSize = parseLenth(transportConf.getValue("bufferPoolSize"), groupsize * Runtime.getRuntime().availableProcessors() * 8);
|
||||||
|
readTimeoutSecond = transportConf.getIntValue("readTimeoutSecond", readTimeoutSecond);
|
||||||
|
writeTimeoutSecond = transportConf.getIntValue("writeTimeoutSecond", writeTimeoutSecond);
|
||||||
final int threads = parseLenth(transportConf.getValue("threads"), groupsize * Runtime.getRuntime().availableProcessors() * 8);
|
final int threads = parseLenth(transportConf.getValue("threads"), groupsize * Runtime.getRuntime().availableProcessors() * 8);
|
||||||
final int capacity = bufferCapacity;
|
final int capacity = bufferCapacity;
|
||||||
transportPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, bufferPoolSize,
|
transportPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, bufferPoolSize,
|
||||||
@@ -306,7 +310,7 @@ public final class Application {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.sncpTransportFactory = TransportFactory.create(transportExec, transportPool, transportGroup, strategy);
|
this.sncpTransportFactory = TransportFactory.create(transportExec, transportPool, transportGroup, readTimeoutSecond, writeTimeoutSecond, strategy);
|
||||||
DefaultAnyValue tarnsportConf = DefaultAnyValue.create(TransportFactory.NAME_PINGINTERVAL, System.getProperty("net.transport.pinginterval", "30"));
|
DefaultAnyValue tarnsportConf = DefaultAnyValue.create(TransportFactory.NAME_PINGINTERVAL, System.getProperty("net.transport.pinginterval", "30"));
|
||||||
this.sncpTransportFactory.init(tarnsportConf, Sncp.PING_BUFFER, Sncp.PONG_BUFFER.remaining());
|
this.sncpTransportFactory.init(tarnsportConf, Sncp.PING_BUFFER, Sncp.PONG_BUFFER.remaining());
|
||||||
Thread.currentThread().setContextClassLoader(this.classLoader);
|
Thread.currentThread().setContextClassLoader(this.classLoader);
|
||||||
|
|||||||
@@ -179,6 +179,7 @@ public abstract class NodeServer {
|
|||||||
for (AnyValue sourceConf : resources.getAnyValues("source")) {
|
for (AnyValue sourceConf : resources.getAnyValues("source")) {
|
||||||
try {
|
try {
|
||||||
Class type = serverClassLoader.loadClass(sourceConf.getValue("value"));
|
Class type = serverClassLoader.loadClass(sourceConf.getValue("value"));
|
||||||
|
if (type == DataSource.class) type = DataJdbcSource.class;
|
||||||
if (!Service.class.isAssignableFrom(type)) {
|
if (!Service.class.isAssignableFrom(type)) {
|
||||||
logger.log(Level.SEVERE, "load application source resource, but not Service error: " + sourceConf);
|
logger.log(Level.SEVERE, "load application source resource, but not Service error: " + sourceConf);
|
||||||
} else if (CacheSource.class.isAssignableFrom(type)) {
|
} else if (CacheSource.class.isAssignableFrom(type)) {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
|
|||||||
factory.register(type, this);
|
factory.register(type, this);
|
||||||
this.decoder = factory.loadDecoder(this.componentType);
|
this.decoder = factory.loadDecoder(this.componentType);
|
||||||
} else {
|
} else {
|
||||||
throw new ConvertException("collectiondecoder not support the type (" + type + ")");
|
throw new ConvertException("CollectionDecoder not support the type (" + type + ")");
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
inited = true;
|
inited = true;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.channels.CompletionHandler;
|
import java.nio.channels.CompletionHandler;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.*;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.*;
|
import java.util.stream.*;
|
||||||
import org.redkale.convert.ext.*;
|
import org.redkale.convert.ext.*;
|
||||||
@@ -88,6 +88,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
this.register(String.class, StringSimpledCoder.instance);
|
this.register(String.class, StringSimpledCoder.instance);
|
||||||
this.register(CharSequence.class, CharSequenceSimpledCoder.instance);
|
this.register(CharSequence.class, CharSequenceSimpledCoder.instance);
|
||||||
this.register(java.util.Date.class, DateSimpledCoder.instance);
|
this.register(java.util.Date.class, DateSimpledCoder.instance);
|
||||||
|
this.register(AtomicInteger.class, AtomicIntegerSimpledCoder.instance);
|
||||||
this.register(AtomicLong.class, AtomicLongSimpledCoder.instance);
|
this.register(AtomicLong.class, AtomicLongSimpledCoder.instance);
|
||||||
this.register(BigInteger.class, BigIntegerSimpledCoder.instance);
|
this.register(BigInteger.class, BigIntegerSimpledCoder.instance);
|
||||||
this.register(BigDecimal.class, BigDecimalSimpledCoder.instance);
|
this.register(BigDecimal.class, BigDecimalSimpledCoder.instance);
|
||||||
@@ -376,12 +377,17 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
encoders.put(clazz, coder);
|
encoders.put(clazz, coder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final <E> void register(final Type clazz, final Decodeable<R, E> decoder, final Encodeable<W, E> encoder) {
|
||||||
|
decoders.put(clazz, decoder);
|
||||||
|
encoders.put(clazz, encoder);
|
||||||
|
}
|
||||||
|
|
||||||
public final <E> void register(final Type clazz, final Decodeable<R, E> decoder) {
|
public final <E> void register(final Type clazz, final Decodeable<R, E> decoder) {
|
||||||
decoders.put(clazz, decoder);
|
decoders.put(clazz, decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final <E> void register(final Type clazz, final Encodeable<W, E> printer) {
|
public final <E> void register(final Type clazz, final Encodeable<W, E> encoder) {
|
||||||
encoders.put(clazz, printer);
|
encoders.put(clazz, encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final <E> Decodeable<R, E> findDecoder(final Type type) {
|
public final <E> Decodeable<R, E> findDecoder(final Type type) {
|
||||||
@@ -462,6 +468,8 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
decoder = new StreamDecoder(this, type);
|
decoder = new StreamDecoder(this, type);
|
||||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||||
decoder = new MapDecoder(this, type);
|
decoder = new MapDecoder(this, type);
|
||||||
|
} else if (Optional.class == clazz) {
|
||||||
|
decoder = new OptionalCoder(this, type);
|
||||||
} else if (clazz == Object.class) {
|
} else if (clazz == Object.class) {
|
||||||
od = new ObjectDecoder(type);
|
od = new ObjectDecoder(type);
|
||||||
decoder = od;
|
decoder = od;
|
||||||
@@ -547,6 +555,8 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
encoder = new StreamEncoder(this, type);
|
encoder = new StreamEncoder(this, type);
|
||||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||||
encoder = new MapEncoder(this, type);
|
encoder = new MapEncoder(this, type);
|
||||||
|
} else if (Optional.class == clazz) {
|
||||||
|
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) {
|
} else if (!clazz.getName().startsWith("java.") || java.net.HttpCookie.class == clazz) {
|
||||||
|
|||||||
107
src/org/redkale/convert/OptionalCoder.java
Normal file
107
src/org/redkale/convert/OptionalCoder.java
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.redkale.convert;
|
||||||
|
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional 的SimpledCoder实现
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @param <R> Reader输入的子类型
|
||||||
|
* @param <W> Writer输出的子类型
|
||||||
|
*/
|
||||||
|
public class OptionalCoder<R extends Reader, W extends Writer, T> extends SimpledCoder<R, W, Optional<T>> {
|
||||||
|
|
||||||
|
private final Type type;
|
||||||
|
|
||||||
|
private final Type componentType;
|
||||||
|
|
||||||
|
protected final Class componentClass;
|
||||||
|
|
||||||
|
protected final Decodeable<Reader, T> decoder;
|
||||||
|
|
||||||
|
protected final Encodeable<Writer, T> encoder;
|
||||||
|
|
||||||
|
private boolean inited = false;
|
||||||
|
|
||||||
|
private final Object lock = new Object();
|
||||||
|
|
||||||
|
public OptionalCoder(final ConvertFactory factory, final Type type) {
|
||||||
|
this.type = type;
|
||||||
|
try {
|
||||||
|
if (type instanceof ParameterizedType) {
|
||||||
|
final ParameterizedType pt = (ParameterizedType) type;
|
||||||
|
this.componentType = pt.getActualTypeArguments()[0];
|
||||||
|
factory.register(type, this);
|
||||||
|
this.decoder = factory.loadDecoder(this.componentType);
|
||||||
|
if (this.componentType instanceof TypeVariable) {
|
||||||
|
this.encoder = factory.getAnyEncoder();
|
||||||
|
this.componentClass = Object.class;
|
||||||
|
} else {
|
||||||
|
if (componentType instanceof ParameterizedType) {
|
||||||
|
final ParameterizedType pt2 = (ParameterizedType) componentType;
|
||||||
|
this.componentClass = (Class) pt2.getRawType();
|
||||||
|
} else {
|
||||||
|
this.componentClass = (Class) componentType;
|
||||||
|
}
|
||||||
|
this.encoder = factory.loadEncoder(this.componentType);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.componentType = Object.class;
|
||||||
|
this.componentClass = Object.class;
|
||||||
|
this.decoder = factory.loadDecoder(this.componentType);
|
||||||
|
this.encoder = factory.getAnyEncoder();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
inited = true;
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void convertTo(W out, Optional<T> value) {
|
||||||
|
if (value == null || !value.isPresent()) {
|
||||||
|
out.writeObjectNull(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.encoder == null) {
|
||||||
|
if (!this.inited) {
|
||||||
|
synchronized (lock) {
|
||||||
|
try {
|
||||||
|
lock.wait();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.encoder.convertTo(out, value.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<T> convertFrom(R in) {
|
||||||
|
if (this.decoder == null) {
|
||||||
|
if (!this.inited) {
|
||||||
|
synchronized (lock) {
|
||||||
|
try {
|
||||||
|
lock.wait();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.ofNullable(this.decoder.convertFrom(in));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -73,7 +73,7 @@ public final class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void offerBsonReader(final BsonReader in) {
|
public void offerBsonReader(final BsonReader in) {
|
||||||
if (in != null) readerPool.offer(in);
|
if (in != null) readerPool.accept(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------ writer -----------------------------------------------------------
|
//------------------------------ writer -----------------------------------------------------------
|
||||||
@@ -90,7 +90,7 @@ public final class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void offerBsonWriter(final BsonWriter out) {
|
public void offerBsonWriter(final BsonWriter out) {
|
||||||
if (out != null) writerPool.offer(out);
|
if (out != null) writerPool.accept(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------ convertFrom -----------------------------------------------------------
|
//------------------------------ convertFrom -----------------------------------------------------------
|
||||||
@@ -106,7 +106,7 @@ public final class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
|||||||
in.setBytes(bytes, start, len);
|
in.setBytes(bytes, start, len);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
T rs = (T) factory.loadDecoder(type).convertFrom(in);
|
T rs = (T) factory.loadDecoder(type).convertFrom(in);
|
||||||
readerPool.offer(in);
|
readerPool.accept(in);
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ public final class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
|||||||
final BsonWriter out = writerPool.get().tiny(tiny);
|
final BsonWriter out = writerPool.get().tiny(tiny);
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
byte[] result = out.toArray();
|
byte[] result = out.toArray();
|
||||||
writerPool.offer(out);
|
writerPool.accept(out);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return convertTo(value.getClass(), value);
|
return convertTo(value.getClass(), value);
|
||||||
@@ -157,7 +157,7 @@ public final class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
|||||||
final BsonWriter out = writerPool.get().tiny(tiny);
|
final BsonWriter out = writerPool.get().tiny(tiny);
|
||||||
factory.loadEncoder(type).convertTo(out, value);
|
factory.loadEncoder(type).convertTo(out, value);
|
||||||
byte[] result = out.toArray();
|
byte[] result = out.toArray();
|
||||||
writerPool.offer(out);
|
writerPool.accept(out);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ public final class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
|||||||
final BsonWriter out = writerPool.get().tiny(tiny);
|
final BsonWriter out = writerPool.get().tiny(tiny);
|
||||||
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(out, values);
|
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(out, values);
|
||||||
byte[] result = out.toArray();
|
byte[] result = out.toArray();
|
||||||
writerPool.offer(out);
|
writerPool.accept(out);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
35
src/org/redkale/convert/ext/AtomicIntegerSimpledCoder.java
Normal file
35
src/org/redkale/convert/ext/AtomicIntegerSimpledCoder.java
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.redkale.convert.ext;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import org.redkale.convert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AtomicInteger 的SimpledCoder实现
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @param <R> Reader输入的子类型
|
||||||
|
* @param <W> Writer输出的子类型
|
||||||
|
*/
|
||||||
|
public class AtomicIntegerSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, AtomicInteger> {
|
||||||
|
|
||||||
|
public static final AtomicIntegerSimpledCoder instance = new AtomicIntegerSimpledCoder();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void convertTo(W out, AtomicInteger value) {
|
||||||
|
out.writeInt(value == null ? 0 : value.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AtomicInteger convertFrom(R in) {
|
||||||
|
return new AtomicInteger(in.readInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@ import org.redkale.util.*;
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
||||||
|
|
||||||
public static final Type TYPE_MAP_STRING_STRING = new TypeToken<java.util.LinkedHashMap<String, String>>() {
|
public static final Type TYPE_MAP_STRING_STRING = new TypeToken<java.util.HashMap<String, String>>() {
|
||||||
}.getType();
|
}.getType();
|
||||||
|
|
||||||
private static final ObjectPool<JsonReader> readerPool = JsonReader.createPool(Integer.getInteger("convert.json.pool.size", 16));
|
private static final ObjectPool<JsonReader> readerPool = JsonReader.createPool(Integer.getInteger("convert.json.pool.size", 16));
|
||||||
@@ -60,7 +60,7 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void offerJsonReader(final JsonReader in) {
|
public void offerJsonReader(final JsonReader in) {
|
||||||
if (in != null) readerPool.offer(in);
|
if (in != null) readerPool.accept(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------ writer -----------------------------------------------------------
|
//------------------------------ writer -----------------------------------------------------------
|
||||||
@@ -81,7 +81,7 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void offerJsonWriter(final JsonWriter out) {
|
public void offerJsonWriter(final JsonWriter out) {
|
||||||
if (out != null) writerPool.offer(out);
|
if (out != null) writerPool.accept(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------ convertFrom -----------------------------------------------------------
|
//------------------------------ convertFrom -----------------------------------------------------------
|
||||||
@@ -100,7 +100,7 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
final JsonReader in = readerPool.get();
|
final JsonReader in = readerPool.get();
|
||||||
in.setText(text, start, len);
|
in.setText(text, start, len);
|
||||||
T rs = (T) factory.loadDecoder(type).convertFrom(in);
|
T rs = (T) factory.loadDecoder(type).convertFrom(in);
|
||||||
readerPool.offer(in);
|
readerPool.accept(in);
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
final JsonWriter out = writerPool.get().tiny(tiny);
|
final JsonWriter out = writerPool.get().tiny(tiny);
|
||||||
factory.loadEncoder(type).convertTo(out, value);
|
factory.loadEncoder(type).convertTo(out, value);
|
||||||
String result = out.toString();
|
String result = out.toString();
|
||||||
writerPool.offer(out);
|
writerPool.accept(out);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
final JsonWriter out = writerPool.get().tiny(tiny);
|
final JsonWriter out = writerPool.get().tiny(tiny);
|
||||||
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(out, values);
|
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(out, values);
|
||||||
String result = out.toString();
|
String result = out.toString();
|
||||||
writerPool.offer(out);
|
writerPool.accept(out);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +160,7 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
if (value == null) {
|
if (value == null) {
|
||||||
new JsonStreamWriter(tiny, out).writeNull();
|
new JsonStreamWriter(tiny, out).writeNull();
|
||||||
} else {
|
} else {
|
||||||
factory.loadEncoder(value.getClass()).convertTo(new JsonStreamWriter(tiny, out), value);
|
convertTo(out, value.getClass(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +169,15 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
if (value == null) {
|
if (value == null) {
|
||||||
new JsonStreamWriter(tiny, out).writeNull();
|
new JsonStreamWriter(tiny, out).writeNull();
|
||||||
} else {
|
} else {
|
||||||
factory.loadEncoder(type).convertTo(new JsonStreamWriter(tiny, out), value);
|
final JsonWriter writer = writerPool.get().tiny(tiny);
|
||||||
|
factory.loadEncoder(type).convertTo(writer, value);
|
||||||
|
byte[] bs = writer.toBytes();
|
||||||
|
writerPool.accept(writer);
|
||||||
|
try {
|
||||||
|
out.write(bs);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +185,15 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
if (values == null) {
|
if (values == null) {
|
||||||
new JsonStreamWriter(tiny, out).writeNull();
|
new JsonStreamWriter(tiny, out).writeNull();
|
||||||
} else {
|
} else {
|
||||||
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(new JsonStreamWriter(tiny, out), values);
|
final JsonWriter writer = writerPool.get().tiny(tiny);
|
||||||
|
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(writer, values);
|
||||||
|
byte[] bs = writer.toBytes();
|
||||||
|
writerPool.accept(writer);
|
||||||
|
try {
|
||||||
|
out.write(bs);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ public class JsonWriter extends Writer {
|
|||||||
* 返回指定至少指定长度的缓冲区
|
* 返回指定至少指定长度的缓冲区
|
||||||
*
|
*
|
||||||
* @param len
|
* @param len
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private char[] expand(int len) {
|
private char[] expand(int len) {
|
||||||
@@ -108,6 +109,10 @@ public class JsonWriter extends Writer {
|
|||||||
return new ByteBuffer[]{ByteBuffer.wrap(Utility.encodeUTF8(content, 0, count))};
|
return new ByteBuffer[]{ByteBuffer.wrap(Utility.encodeUTF8(content, 0, count))};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] toBytes() {
|
||||||
|
return Utility.encodeUTF8(content, 0, count);
|
||||||
|
}
|
||||||
|
|
||||||
public int count() {
|
public int count() {
|
||||||
return this.count;
|
return this.count;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
|
|||||||
protected volatile long writetime;
|
protected volatile long writetime;
|
||||||
|
|
||||||
//关闭数
|
//关闭数
|
||||||
AtomicLong closedCounter;
|
protected AtomicLong closedCounter;
|
||||||
|
|
||||||
//在线数
|
//在线数
|
||||||
AtomicLong livingCounter;
|
protected AtomicLong livingCounter;
|
||||||
|
|
||||||
public final long getLastReadTime() {
|
public final long getLastReadTime() {
|
||||||
return readtime;
|
return readtime;
|
||||||
|
|||||||
@@ -130,13 +130,13 @@ public class Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void offerBuffer(ByteBuffer buffer) {
|
public void offerBuffer(ByteBuffer buffer) {
|
||||||
bufferPool.offer(buffer);
|
bufferPool.accept(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void offerBuffer(ByteBuffer... buffers) {
|
public void offerBuffer(ByteBuffer... buffers) {
|
||||||
if (buffers == null) return;
|
if (buffers == null) return;
|
||||||
for (ByteBuffer buffer : buffers) {
|
for (ByteBuffer buffer : buffers) {
|
||||||
bufferPool.offer(buffer);
|
bufferPool.accept(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,14 +48,16 @@ public final class PrepareRunner implements Runnable {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final ByteBuffer buffer = context.pollBuffer();
|
final Response response = responsePool.get();
|
||||||
|
final ByteBuffer buffer = response.request.pollReadBuffer();
|
||||||
try {
|
try {
|
||||||
channel.read(buffer, null, new CompletionHandler<Integer, Void>() {
|
channel.read(buffer, null, new CompletionHandler<Integer, Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void completed(Integer count, Void attachment1) {
|
public void completed(Integer count, Void attachment1) {
|
||||||
if (count < 1 && buffer.remaining() == buffer.limit()) {
|
if (count < 1 && buffer.remaining() == buffer.limit()) {
|
||||||
try {
|
try {
|
||||||
context.offerBuffer(buffer);
|
response.request.offerReadBuffer(buffer);
|
||||||
|
response.finish(true);
|
||||||
channel.close();
|
channel.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
context.logger.log(Level.FINEST, "PrepareRunner close channel erroneous on no read bytes", e);
|
context.logger.log(Level.FINEST, "PrepareRunner close channel erroneous on no read bytes", e);
|
||||||
@@ -69,7 +71,6 @@ public final class PrepareRunner implements Runnable {
|
|||||||
// System.println(new String(bs));
|
// System.println(new String(bs));
|
||||||
// }
|
// }
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
final Response response = responsePool.get();
|
|
||||||
response.init(channel);
|
response.init(channel);
|
||||||
try {
|
try {
|
||||||
prepare.prepare(buffer, response.request, response);
|
prepare.prepare(buffer, response.request, response);
|
||||||
@@ -81,7 +82,8 @@ public final class PrepareRunner implements Runnable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void failed(Throwable exc, Void attachment2) {
|
public void failed(Throwable exc, Void attachment2) {
|
||||||
context.offerBuffer(buffer);
|
response.request.offerReadBuffer(buffer);
|
||||||
|
response.finish(true);
|
||||||
try {
|
try {
|
||||||
channel.close();
|
channel.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -90,7 +92,8 @@ public final class PrepareRunner implements Runnable {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Exception te) {
|
} catch (Exception te) {
|
||||||
context.offerBuffer(buffer);
|
response.request.offerReadBuffer(buffer);
|
||||||
|
response.finish(true);
|
||||||
try {
|
try {
|
||||||
channel.close();
|
channel.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -214,11 +214,11 @@ public abstract class PrepareServlet<K extends Serializable, C extends Context,
|
|||||||
executeCounter.incrementAndGet();
|
executeCounter.incrementAndGet();
|
||||||
final int rs = request.readHeader(buffer);
|
final int rs = request.readHeader(buffer);
|
||||||
if (rs < 0) {
|
if (rs < 0) {
|
||||||
response.context.offerBuffer(buffer);
|
request.offerReadBuffer(buffer);
|
||||||
if (rs != Integer.MIN_VALUE) illRequestCounter.incrementAndGet();
|
if (rs != Integer.MIN_VALUE) illRequestCounter.incrementAndGet();
|
||||||
response.finish(true);
|
response.finish(true);
|
||||||
} else if (rs == 0) {
|
} else if (rs == 0) {
|
||||||
response.context.offerBuffer(buffer);
|
request.offerReadBuffer(buffer);
|
||||||
request.prepare();
|
request.prepare();
|
||||||
response.filter = this.headFilter;
|
response.filter = this.headFilter;
|
||||||
response.servlet = this;
|
response.servlet = this;
|
||||||
@@ -236,7 +236,7 @@ public abstract class PrepareServlet<K extends Serializable, C extends Context,
|
|||||||
buffer.clear();
|
buffer.clear();
|
||||||
request.channel.read(buffer, buffer, this);
|
request.channel.read(buffer, buffer, this);
|
||||||
} else {
|
} else {
|
||||||
response.context.offerBuffer(buffer);
|
request.offerReadBuffer(buffer);
|
||||||
request.prepare();
|
request.prepare();
|
||||||
try {
|
try {
|
||||||
response.filter = PrepareServlet.this.headFilter;
|
response.filter = PrepareServlet.this.headFilter;
|
||||||
@@ -253,7 +253,7 @@ public abstract class PrepareServlet<K extends Serializable, C extends Context,
|
|||||||
@Override
|
@Override
|
||||||
public void failed(Throwable exc, ByteBuffer attachment) {
|
public void failed(Throwable exc, ByteBuffer attachment) {
|
||||||
illRequestCounter.incrementAndGet();
|
illRequestCounter.incrementAndGet();
|
||||||
response.context.offerBuffer(buffer);
|
request.offerReadBuffer(buffer);
|
||||||
response.finish(true);
|
response.finish(true);
|
||||||
if (exc != null) request.context.logger.log(Level.FINER, "Servlet read channel erroneous, forece to close channel ", exc);
|
if (exc != null) request.context.logger.log(Level.FINER, "Servlet read channel erroneous, forece to close channel ", exc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ public abstract class ProtocolServer {
|
|||||||
AsyncConnection conn = AsyncConnection.create(channel, null, context.readTimeoutSecond, context.writeTimeoutSecond);
|
AsyncConnection conn = AsyncConnection.create(channel, null, context.readTimeoutSecond, context.writeTimeoutSecond);
|
||||||
conn.livingCounter = livingCounter;
|
conn.livingCounter = livingCounter;
|
||||||
conn.closedCounter = closedCounter;
|
conn.closedCounter = closedCounter;
|
||||||
context.submitAsync(new PrepareRunner(context, conn, null));
|
context.runAsync(new PrepareRunner(context, conn, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ public abstract class Request<C extends Context> {
|
|||||||
|
|
||||||
protected AsyncConnection channel;
|
protected AsyncConnection channel;
|
||||||
|
|
||||||
|
protected ByteBuffer readBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* properties 与 attributes 的区别在于:调用recycle时, attributes会被清空而properties会保留;
|
* properties 与 attributes 的区别在于:调用recycle时, attributes会被清空而properties会保留;
|
||||||
* properties 通常存放需要永久绑定在request里的一些对象
|
* properties 通常存放需要永久绑定在request里的一些对象
|
||||||
@@ -43,10 +45,28 @@ public abstract class Request<C extends Context> {
|
|||||||
|
|
||||||
protected Request(C context) {
|
protected Request(C context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
this.readBuffer = context.pollBuffer();
|
||||||
this.bsonConvert = context.getBsonConvert();
|
this.bsonConvert = context.getBsonConvert();
|
||||||
this.jsonConvert = context.getJsonConvert();
|
this.jsonConvert = context.getJsonConvert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ByteBuffer pollReadBuffer() {
|
||||||
|
ByteBuffer buffer = this.readBuffer;
|
||||||
|
this.readBuffer = null;
|
||||||
|
if (buffer == null) buffer = context.pollBuffer();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void offerReadBuffer(ByteBuffer buffer) {
|
||||||
|
if (buffer == null) return;
|
||||||
|
if (this.readBuffer == null) {
|
||||||
|
buffer.clear();
|
||||||
|
this.readBuffer = buffer;
|
||||||
|
} else {
|
||||||
|
context.offerBuffer(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回值:Integer.MIN_VALUE: 帧数据; -1:数据不合法; 0:解析完毕; >0: 需再读取的字节数。
|
* 返回值:Integer.MIN_VALUE: 帧数据; -1:数据不合法; 0:解析完毕; >0: 需再读取的字节数。
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ package org.redkale.net;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.CompletionHandler;
|
import java.nio.channels.CompletionHandler;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,6 +30,10 @@ public abstract class Response<C extends Context, R extends Request<C>> {
|
|||||||
|
|
||||||
protected AsyncConnection channel;
|
protected AsyncConnection channel;
|
||||||
|
|
||||||
|
protected ByteBuffer writeHeadBuffer;
|
||||||
|
|
||||||
|
protected ByteBuffer writeBodyBuffer;
|
||||||
|
|
||||||
private boolean inited = true;
|
private boolean inited = true;
|
||||||
|
|
||||||
protected Object output; //输出的结果对象
|
protected Object output; //输出的结果对象
|
||||||
@@ -40,6 +44,8 @@ public abstract class Response<C extends Context, R extends Request<C>> {
|
|||||||
|
|
||||||
protected Servlet<C, R, ? extends Response<C, R>> servlet;
|
protected Servlet<C, R, ? extends Response<C, R>> servlet;
|
||||||
|
|
||||||
|
private Supplier<ByteBuffer> bodyBufferSupplier;
|
||||||
|
|
||||||
private final CompletionHandler finishHandler = new CompletionHandler<Integer, ByteBuffer>() {
|
private final CompletionHandler finishHandler = new CompletionHandler<Integer, ByteBuffer>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -47,17 +53,31 @@ public abstract class Response<C extends Context, R extends Request<C>> {
|
|||||||
if (attachment.hasRemaining()) {
|
if (attachment.hasRemaining()) {
|
||||||
channel.write(attachment, attachment, this);
|
channel.write(attachment, attachment, this);
|
||||||
} else {
|
} else {
|
||||||
context.offerBuffer(attachment);
|
offerResponseBuffer(attachment);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void failed(Throwable exc, ByteBuffer attachment) {
|
public void failed(Throwable exc, ByteBuffer attachment) {
|
||||||
context.offerBuffer(attachment);
|
offerResponseBuffer(attachment);
|
||||||
finish(true);
|
finish(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void offerResponseBuffer(ByteBuffer attachment) {
|
||||||
|
if (writeHeadBuffer == null) {
|
||||||
|
if (context.bufferPool.getRecyclerPredicate().test(attachment)) {
|
||||||
|
writeHeadBuffer = attachment;
|
||||||
|
}
|
||||||
|
} else if (writeBodyBuffer == null) {
|
||||||
|
if (context.bufferPool.getRecyclerPredicate().test(attachment)) {
|
||||||
|
writeBodyBuffer = attachment;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
context.offerBuffer(attachment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private final CompletionHandler finishHandler2 = new CompletionHandler<Integer, ByteBuffer[]>() {
|
private final CompletionHandler finishHandler2 = new CompletionHandler<Integer, ByteBuffer[]>() {
|
||||||
@@ -74,26 +94,66 @@ public abstract class Response<C extends Context, R extends Request<C>> {
|
|||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
channel.write(attachments, index, attachments.length - index, attachments, this);
|
channel.write(attachments, index, attachments.length - index, attachments, this);
|
||||||
} else {
|
} else {
|
||||||
for (ByteBuffer attachment : attachments) {
|
offerResponseBuffer(attachments);
|
||||||
context.offerBuffer(attachment);
|
|
||||||
}
|
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void failed(Throwable exc, final ByteBuffer[] attachments) {
|
public void failed(Throwable exc, final ByteBuffer[] attachments) {
|
||||||
for (ByteBuffer attachment : attachments) {
|
offerResponseBuffer(attachments);
|
||||||
context.offerBuffer(attachment);
|
|
||||||
}
|
|
||||||
finish(true);
|
finish(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void offerResponseBuffer(ByteBuffer[] attachments) {
|
||||||
|
int start = 0;
|
||||||
|
if (writeHeadBuffer == null && attachments.length > start) {
|
||||||
|
if (context.bufferPool.getRecyclerPredicate().test(attachments[start])) {
|
||||||
|
writeHeadBuffer = attachments[start];
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (writeBodyBuffer == null && attachments.length > start) {
|
||||||
|
if (context.bufferPool.getRecyclerPredicate().test(attachments[start])) {
|
||||||
|
writeBodyBuffer = attachments[start];
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = start; i < attachments.length; i++) {
|
||||||
|
context.offerBuffer(attachments[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
protected Response(C context, final R request) {
|
protected Response(C context, final R request) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.request = request;
|
this.request = request;
|
||||||
|
this.writeHeadBuffer = context.pollBuffer();
|
||||||
|
this.writeBodyBuffer = context.pollBuffer();
|
||||||
|
this.bodyBufferSupplier = () -> {
|
||||||
|
ByteBuffer buffer = writeBodyBuffer;
|
||||||
|
if (buffer == null) return context.pollBuffer();
|
||||||
|
writeBodyBuffer = null;
|
||||||
|
return buffer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ByteBuffer pollWriteReadBuffer() {
|
||||||
|
ByteBuffer buffer = this.writeHeadBuffer;
|
||||||
|
this.writeHeadBuffer = null;
|
||||||
|
if (buffer == null) buffer = context.pollBuffer();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ByteBuffer pollWriteBodyBuffer() {
|
||||||
|
ByteBuffer buffer = this.writeBodyBuffer;
|
||||||
|
this.writeBodyBuffer = null;
|
||||||
|
if (buffer == null) buffer = context.pollBuffer();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Supplier<ByteBuffer> getBodyBufferSupplier() {
|
||||||
|
return bodyBufferSupplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AsyncConnection removeChannel() {
|
protected AsyncConnection removeChannel() {
|
||||||
@@ -195,7 +255,7 @@ public abstract class Response<C extends Context, R extends Request<C>> {
|
|||||||
if (!this.inited) return; //避免重复关闭
|
if (!this.inited) return; //避免重复关闭
|
||||||
//System.println("耗时: " + (System.currentTimeMillis() - request.createtime));
|
//System.println("耗时: " + (System.currentTimeMillis() - request.createtime));
|
||||||
if (kill) refuseAlive();
|
if (kill) refuseAlive();
|
||||||
this.context.responsePool.offer(this);
|
this.context.responsePool.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish(final byte[] bs) {
|
public void finish(final byte[] bs) {
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ public final class Transport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void offerBuffer(ByteBuffer buffer) {
|
public void offerBuffer(ByteBuffer buffer) {
|
||||||
bufferPool.offer(buffer);
|
bufferPool.accept(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void offerBuffer(ByteBuffer... buffers) {
|
public void offerBuffer(ByteBuffer... buffers) {
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ import org.redkale.util.*;
|
|||||||
*/
|
*/
|
||||||
public class TransportFactory {
|
public class TransportFactory {
|
||||||
|
|
||||||
|
@Comment("默认TCP读取超时秒数")
|
||||||
|
public static int DEFAULT_READTIMEOUTSECOND = 6;
|
||||||
|
|
||||||
|
@Comment("默认TCP写入超时秒数")
|
||||||
|
public static int DEFAULT_WRITETIMEOUTSECOND = 6;
|
||||||
|
|
||||||
public static final String NAME_PINGINTERVAL = "pinginterval";
|
public static final String NAME_PINGINTERVAL = "pinginterval";
|
||||||
|
|
||||||
protected static final Logger logger = Logger.getLogger(TransportFactory.class.getSimpleName());
|
protected static final Logger logger = Logger.getLogger(TransportFactory.class.getSimpleName());
|
||||||
@@ -55,6 +61,12 @@ public class TransportFactory {
|
|||||||
//心跳周期, 单位:秒
|
//心跳周期, 单位:秒
|
||||||
protected int pinginterval;
|
protected int pinginterval;
|
||||||
|
|
||||||
|
//TCP读取超时秒数
|
||||||
|
protected int readTimeoutSecond;
|
||||||
|
|
||||||
|
//TCP写入超时秒数
|
||||||
|
protected int writeTimeoutSecond;
|
||||||
|
|
||||||
//ping的定时器
|
//ping的定时器
|
||||||
private ScheduledThreadPoolExecutor pingScheduler;
|
private ScheduledThreadPoolExecutor pingScheduler;
|
||||||
|
|
||||||
@@ -68,15 +80,18 @@ public class TransportFactory {
|
|||||||
protected final TransportStrategy strategy;
|
protected final TransportStrategy strategy;
|
||||||
|
|
||||||
protected TransportFactory(ExecutorService executor, ObjectPool<ByteBuffer> bufferPool, AsynchronousChannelGroup channelGroup,
|
protected TransportFactory(ExecutorService executor, ObjectPool<ByteBuffer> bufferPool, AsynchronousChannelGroup channelGroup,
|
||||||
final TransportStrategy strategy) {
|
int readTimeoutSecond, int writeTimeoutSecond, final TransportStrategy strategy) {
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
this.bufferPool = bufferPool;
|
this.bufferPool = bufferPool;
|
||||||
this.channelGroup = channelGroup;
|
this.channelGroup = channelGroup;
|
||||||
|
this.readTimeoutSecond = readTimeoutSecond;
|
||||||
|
this.writeTimeoutSecond = writeTimeoutSecond;
|
||||||
this.strategy = strategy;
|
this.strategy = strategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TransportFactory(ExecutorService executor, ObjectPool<ByteBuffer> bufferPool, AsynchronousChannelGroup channelGroup) {
|
protected TransportFactory(ExecutorService executor, ObjectPool<ByteBuffer> bufferPool, AsynchronousChannelGroup channelGroup,
|
||||||
this(executor, bufferPool, channelGroup, null);
|
int readTimeoutSecond, int writeTimeoutSecond) {
|
||||||
|
this(executor, bufferPool, channelGroup, readTimeoutSecond, writeTimeoutSecond, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(AnyValue conf, ByteBuffer pingBuffer, int pongLength) {
|
public void init(AnyValue conf, ByteBuffer pingBuffer, int pongLength) {
|
||||||
@@ -100,10 +115,14 @@ public class TransportFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static TransportFactory create(int threads) {
|
public static TransportFactory create(int threads) {
|
||||||
return create(threads, threads * 2, 8 * 1024);
|
return create(threads, threads * 2, 8 * 1024, DEFAULT_READTIMEOUTSECOND, DEFAULT_WRITETIMEOUTSECOND);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TransportFactory create(int threads, int bufferPoolSize, int bufferCapacity) {
|
public static TransportFactory create(int threads, int bufferPoolSize, int bufferCapacity) {
|
||||||
|
return create(threads, bufferPoolSize, bufferCapacity, DEFAULT_READTIMEOUTSECOND, DEFAULT_WRITETIMEOUTSECOND);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TransportFactory create(int threads, int bufferPoolSize, int bufferCapacity, int readTimeoutSecond, int writeTimeoutSecond) {
|
||||||
final ObjectPool<ByteBuffer> transportPool = new ObjectPool<>(new AtomicLong(), new AtomicLong(), bufferPoolSize,
|
final ObjectPool<ByteBuffer> transportPool = new ObjectPool<>(new AtomicLong(), new AtomicLong(), bufferPoolSize,
|
||||||
(Object... params) -> ByteBuffer.allocateDirect(bufferCapacity), null, (e) -> {
|
(Object... params) -> ByteBuffer.allocateDirect(bufferCapacity), null, (e) -> {
|
||||||
if (e == null || e.isReadOnly() || e.capacity() != bufferCapacity) return false;
|
if (e == null || e.isReadOnly() || e.capacity() != bufferCapacity) return false;
|
||||||
@@ -123,16 +142,21 @@ public class TransportFactory {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return create(transportExec, transportPool, transportGroup);
|
return create(transportExec, transportPool, transportGroup, readTimeoutSecond, writeTimeoutSecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TransportFactory create(ExecutorService executor, ObjectPool<ByteBuffer> bufferPool, AsynchronousChannelGroup channelGroup) {
|
public static TransportFactory create(ExecutorService executor, ObjectPool<ByteBuffer> bufferPool, AsynchronousChannelGroup channelGroup) {
|
||||||
return new TransportFactory(executor, bufferPool, channelGroup, null);
|
return new TransportFactory(executor, bufferPool, channelGroup, DEFAULT_READTIMEOUTSECOND, DEFAULT_WRITETIMEOUTSECOND, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TransportFactory create(ExecutorService executor, ObjectPool<ByteBuffer> bufferPool, AsynchronousChannelGroup channelGroup,
|
public static TransportFactory create(ExecutorService executor, ObjectPool<ByteBuffer> bufferPool, AsynchronousChannelGroup channelGroup,
|
||||||
final TransportStrategy strategy) {
|
int readTimeoutSecond, int writeTimeoutSecond) {
|
||||||
return new TransportFactory(executor, bufferPool, channelGroup, strategy);
|
return new TransportFactory(executor, bufferPool, channelGroup, readTimeoutSecond, writeTimeoutSecond, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TransportFactory create(ExecutorService executor, ObjectPool<ByteBuffer> bufferPool, AsynchronousChannelGroup channelGroup,
|
||||||
|
int readTimeoutSecond, int writeTimeoutSecond, final TransportStrategy strategy) {
|
||||||
|
return new TransportFactory(executor, bufferPool, channelGroup, readTimeoutSecond, writeTimeoutSecond, strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Transport createTransportTCP(String name, final InetSocketAddress clientAddress, final Collection<InetSocketAddress> addresses) {
|
public Transport createTransportTCP(String name, final InetSocketAddress clientAddress, final Collection<InetSocketAddress> addresses) {
|
||||||
@@ -308,7 +332,7 @@ public class TransportFactory {
|
|||||||
@Override
|
@Override
|
||||||
public void completed(Integer result, ByteBuffer attachment) {
|
public void completed(Integer result, ByteBuffer attachment) {
|
||||||
if (counter > 3) {
|
if (counter > 3) {
|
||||||
bufferPool.offer(attachment);
|
bufferPool.accept(attachment);
|
||||||
localconn.dispose();
|
localconn.dispose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -317,7 +341,7 @@ public class TransportFactory {
|
|||||||
localconn.read(pongBuffer, pongBuffer, this);
|
localconn.read(pongBuffer, pongBuffer, this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bufferPool.offer(attachment);
|
bufferPool.accept(attachment);
|
||||||
localqueue.offer(localconn);
|
localqueue.offer(localconn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import java.text.*;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.redkale.convert.*;
|
import org.redkale.convert.*;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
@@ -34,15 +35,6 @@ import org.redkale.util.*;
|
|||||||
*/
|
*/
|
||||||
public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
||||||
|
|
||||||
/**
|
|
||||||
* HttpResponse.finish 方法内调用
|
|
||||||
* 主要给@HttpCacheable使用
|
|
||||||
*/
|
|
||||||
protected static interface BufferHandler {
|
|
||||||
|
|
||||||
public ByteBuffer[] execute(final HttpResponse response, final ByteBuffer[] buffers);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final ByteBuffer buffer304 = ByteBuffer.wrap("HTTP/1.1 304 Not Modified\r\nContent-Length:0\r\n\r\n".getBytes()).asReadOnlyBuffer();
|
private static final ByteBuffer buffer304 = ByteBuffer.wrap("HTTP/1.1 304 Not Modified\r\nContent-Length:0\r\n\r\n".getBytes()).asReadOnlyBuffer();
|
||||||
|
|
||||||
private static final ByteBuffer buffer404 = ByteBuffer.wrap("HTTP/1.1 404 Not Found\r\nContent-Length:0\r\n\r\n".getBytes()).asReadOnlyBuffer();
|
private static final ByteBuffer buffer404 = ByteBuffer.wrap("HTTP/1.1 404 Not Found\r\nContent-Length:0\r\n\r\n".getBytes()).asReadOnlyBuffer();
|
||||||
@@ -117,7 +109,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
|
|
||||||
private boolean headsended = false;
|
private boolean headsended = false;
|
||||||
|
|
||||||
private BufferHandler bufferHandler;
|
private BiFunction<HttpResponse, ByteBuffer[], ByteBuffer[]> bufferHandler;
|
||||||
//------------------------------------------------
|
//------------------------------------------------
|
||||||
|
|
||||||
private final DefaultAnyValue header = new DefaultAnyValue();
|
private final DefaultAnyValue header = new DefaultAnyValue();
|
||||||
@@ -148,6 +140,10 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
return super.removeChannel();
|
return super.removeChannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected AsyncConnection getChannel() {
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean recycle() {
|
protected boolean recycle() {
|
||||||
boolean rs = super.recycle();
|
boolean rs = super.recycle();
|
||||||
@@ -229,7 +225,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
return Utility.createAsyncHandler((v, a) -> {
|
return Utility.createAsyncHandler((v, a) -> {
|
||||||
finish(v);
|
finish(v);
|
||||||
}, (t, a) -> {
|
}, (t, a) -> {
|
||||||
request.getContext().getLogger().log(Level.WARNING, "Servlet occur, forece to close channel. request = " + request + ", result is CompletionHandler", (Throwable)t);
|
request.getContext().getLogger().log(Level.WARNING, "Servlet occur, forece to close channel. request = " + request + ", result is CompletionHandler", (Throwable) t);
|
||||||
finish(500, null);
|
finish(500, null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -258,7 +254,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
public void finishJson(final Object obj) {
|
public void finishJson(final Object obj) {
|
||||||
this.contentType = "text/plain; charset=utf-8";
|
this.contentType = "text/plain; charset=utf-8";
|
||||||
if (this.recycleListener != null) this.output = obj;
|
if (this.recycleListener != null) this.output = obj;
|
||||||
finish(request.getJsonConvert().convertTo(context.getBufferSupplier(), obj));
|
finish(request.getJsonConvert().convertTo(getBodyBufferSupplier(), obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -270,7 +266,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
public void finishMapJson(final Object... objs) {
|
public void finishMapJson(final Object... objs) {
|
||||||
this.contentType = "text/plain; charset=utf-8";
|
this.contentType = "text/plain; charset=utf-8";
|
||||||
if (this.recycleListener != null) this.output = objs;
|
if (this.recycleListener != null) this.output = objs;
|
||||||
finish(request.getJsonConvert().convertMapTo(context.getBufferSupplier(), objs));
|
finish(request.getJsonConvert().convertMapTo(getBodyBufferSupplier(), objs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -282,7 +278,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
public void finishJson(final JsonConvert convert, final Object obj) {
|
public void finishJson(final JsonConvert convert, final Object obj) {
|
||||||
this.contentType = "text/plain; charset=utf-8";
|
this.contentType = "text/plain; charset=utf-8";
|
||||||
if (this.recycleListener != null) this.output = obj;
|
if (this.recycleListener != null) this.output = obj;
|
||||||
finish(convert.convertTo(context.getBufferSupplier(), obj));
|
finish(convert.convertTo(getBodyBufferSupplier(), obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -295,7 +291,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
public void finishMapJson(final JsonConvert convert, final Object... objs) {
|
public void finishMapJson(final JsonConvert convert, final Object... objs) {
|
||||||
this.contentType = "text/plain; charset=utf-8";
|
this.contentType = "text/plain; charset=utf-8";
|
||||||
if (this.recycleListener != null) this.output = objs;
|
if (this.recycleListener != null) this.output = objs;
|
||||||
finish(convert.convertMapTo(context.getBufferSupplier(), objs));
|
finish(convert.convertMapTo(getBodyBufferSupplier(), objs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -307,7 +303,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
public void finishJson(final Type type, final Object obj) {
|
public void finishJson(final Type type, final Object obj) {
|
||||||
this.contentType = "text/plain; charset=utf-8";
|
this.contentType = "text/plain; charset=utf-8";
|
||||||
this.output = obj;
|
this.output = obj;
|
||||||
finish(request.getJsonConvert().convertTo(context.getBufferSupplier(), type, obj));
|
finish(request.getJsonConvert().convertTo(getBodyBufferSupplier(), type, obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -320,7 +316,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
public void finishJson(final JsonConvert convert, final Type type, final Object obj) {
|
public void finishJson(final JsonConvert convert, final Type type, final Object obj) {
|
||||||
this.contentType = "text/plain; charset=utf-8";
|
this.contentType = "text/plain; charset=utf-8";
|
||||||
if (this.recycleListener != null) this.output = obj;
|
if (this.recycleListener != null) this.output = obj;
|
||||||
finish(convert.convertTo(context.getBufferSupplier(), type, obj));
|
finish(convert.convertTo(getBodyBufferSupplier(), type, obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -331,7 +327,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
public void finishJson(final Object... objs) {
|
public void finishJson(final Object... objs) {
|
||||||
this.contentType = "text/plain; charset=utf-8";
|
this.contentType = "text/plain; charset=utf-8";
|
||||||
if (this.recycleListener != null) this.output = objs;
|
if (this.recycleListener != null) this.output = objs;
|
||||||
finish(request.getJsonConvert().convertTo(context.getBufferSupplier(), objs));
|
finish(request.getJsonConvert().convertTo(getBodyBufferSupplier(), objs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -346,7 +342,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
this.header.addValue("retcode", String.valueOf(ret.getRetcode()));
|
this.header.addValue("retcode", String.valueOf(ret.getRetcode()));
|
||||||
this.header.addValue("retinfo", ret.getRetinfo());
|
this.header.addValue("retinfo", ret.getRetinfo());
|
||||||
}
|
}
|
||||||
finish(request.getJsonConvert().convertTo(context.getBufferSupplier(), ret));
|
finish(request.getJsonConvert().convertTo(getBodyBufferSupplier(), ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -362,7 +358,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
this.header.addValue("retcode", String.valueOf(ret.getRetcode()));
|
this.header.addValue("retcode", String.valueOf(ret.getRetcode()));
|
||||||
this.header.addValue("retinfo", ret.getRetinfo());
|
this.header.addValue("retinfo", ret.getRetinfo());
|
||||||
}
|
}
|
||||||
finish(convert.convertTo(context.getBufferSupplier(), ret));
|
finish(convert.convertTo(getBodyBufferSupplier(), ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -432,7 +428,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
} else if (obj instanceof CompletableFuture) {
|
} else if (obj instanceof CompletableFuture) {
|
||||||
((CompletableFuture) obj).whenComplete((v, e) -> {
|
((CompletableFuture) obj).whenComplete((v, e) -> {
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
context.getLogger().log(Level.WARNING, "Servlet occur, forece to close channel. request = " + request + ", result is CompletableFuture", (Throwable)e);
|
context.getLogger().log(Level.WARNING, "Servlet occur, forece to close channel. request = " + request + ", result is CompletableFuture", (Throwable) e);
|
||||||
finish(500, null);
|
finish(500, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -471,8 +467,8 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
this.header.addValue("retcode", String.valueOf(ret.getRetcode())).addValue("retinfo", ret.getRetinfo());
|
this.header.addValue("retcode", String.valueOf(ret.getRetcode())).addValue("retinfo", ret.getRetinfo());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ByteBuffer[] buffers = type == null ? convert.convertTo(context.getBufferSupplier(), obj)
|
ByteBuffer[] buffers = type == null ? convert.convertTo(getBodyBufferSupplier(), obj)
|
||||||
: convert.convertTo(context.getBufferSupplier(), type, obj);
|
: convert.convertTo(getBodyBufferSupplier(), type, obj);
|
||||||
finish(buffers);
|
finish(buffers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -494,7 +490,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
}
|
}
|
||||||
if (context.getCharset() == null) {
|
if (context.getCharset() == null) {
|
||||||
if (bufferHandler != null) {
|
if (bufferHandler != null) {
|
||||||
bufferHandler.execute(this, new ByteBuffer[]{ByteBuffer.wrap(Utility.encodeUTF8(obj))});
|
bufferHandler.apply(this, new ByteBuffer[]{ByteBuffer.wrap(Utility.encodeUTF8(obj))});
|
||||||
}
|
}
|
||||||
final char[] chars = Utility.charArray(obj);
|
final char[] chars = Utility.charArray(obj);
|
||||||
this.contentLength = Utility.encodeUTF8Length(chars);
|
this.contentLength = Utility.encodeUTF8Length(chars);
|
||||||
@@ -509,7 +505,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
} else {
|
} else {
|
||||||
ByteBuffer buffer = context.getCharset().encode(obj);
|
ByteBuffer buffer = context.getCharset().encode(obj);
|
||||||
if (bufferHandler != null) {
|
if (bufferHandler != null) {
|
||||||
ByteBuffer[] bufs = bufferHandler.execute(this, new ByteBuffer[]{buffer});
|
ByteBuffer[] bufs = bufferHandler.apply(this, new ByteBuffer[]{buffer});
|
||||||
if (bufs != null) buffer = bufs[0];
|
if (bufs != null) buffer = bufs[0];
|
||||||
}
|
}
|
||||||
this.contentLength = buffer.remaining();
|
this.contentLength = buffer.remaining();
|
||||||
@@ -554,7 +550,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
@Override
|
@Override
|
||||||
public void finish(final byte[] bs) {
|
public void finish(final byte[] bs) {
|
||||||
if (isClosed()) return; //避免重复关闭
|
if (isClosed()) return; //避免重复关闭
|
||||||
if (this.context.getBufferCapacity() == bs.length) {
|
if (this.context.getBufferCapacity() >= bs.length) {
|
||||||
ByteBuffer buffer = this.context.pollBuffer();
|
ByteBuffer buffer = this.context.pollBuffer();
|
||||||
buffer.put(bs);
|
buffer.put(bs);
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
@@ -617,7 +613,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
public void finish(boolean kill, ByteBuffer... buffers) {
|
public void finish(boolean kill, ByteBuffer... buffers) {
|
||||||
if (isClosed()) return; //避免重复关闭
|
if (isClosed()) return; //避免重复关闭
|
||||||
if (bufferHandler != null) {
|
if (bufferHandler != null) {
|
||||||
ByteBuffer[] bufs = bufferHandler.execute(this, buffers);
|
ByteBuffer[] bufs = bufferHandler.apply(this, buffers);
|
||||||
if (bufs != null) buffers = bufs;
|
if (bufs != null) buffers = bufs;
|
||||||
}
|
}
|
||||||
if (kill) refuseAlive();
|
if (kill) refuseAlive();
|
||||||
@@ -797,9 +793,10 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
this.channel.write(hbuffer, hbuffer, new TransferFileHandler(file, offset, length));
|
this.channel.write(hbuffer, hbuffer, new TransferFileHandler(file, offset, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ByteBuffer createHeader() {
|
//Header大小不能超过一个ByteBuffer的容量
|
||||||
|
protected ByteBuffer createHeader() {
|
||||||
this.headsended = true;
|
this.headsended = true;
|
||||||
ByteBuffer buffer = this.context.pollBuffer();
|
ByteBuffer buffer = this.pollWriteReadBuffer();
|
||||||
buffer.put(("HTTP/1.1 " + this.status + " " + (this.status == 200 ? "OK" : httpCodes.get(this.status)) + "\r\n").getBytes());
|
buffer.put(("HTTP/1.1 " + this.status + " " + (this.status == 200 ? "OK" : httpCodes.get(this.status)) + "\r\n").getBytes());
|
||||||
|
|
||||||
buffer.put(("Content-Type: " + (this.contentType == null ? "text/plain; charset=utf-8" : this.contentType) + "\r\n").getBytes());
|
buffer.put(("Content-Type: " + (this.contentType == null ? "text/plain; charset=utf-8" : this.contentType) + "\r\n").getBytes());
|
||||||
@@ -1011,7 +1008,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
*
|
*
|
||||||
* @return 拦截器
|
* @return 拦截器
|
||||||
*/
|
*/
|
||||||
protected BufferHandler getBufferHandler() {
|
protected BiFunction<HttpResponse, ByteBuffer[], ByteBuffer[]> getBufferHandler() {
|
||||||
return bufferHandler;
|
return bufferHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1020,7 +1017,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
|
|||||||
*
|
*
|
||||||
* @param bufferHandler 拦截器
|
* @param bufferHandler 拦截器
|
||||||
*/
|
*/
|
||||||
protected void setBufferHandler(BufferHandler bufferHandler) {
|
protected void setBufferHandler(BiFunction<HttpResponse, ByteBuffer[], ByteBuffer[]> bufferHandler) {
|
||||||
this.bufferHandler = bufferHandler;
|
this.bufferHandler = bufferHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import java.lang.reflect.Method;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
import jdk.internal.org.objectweb.asm.*;
|
import jdk.internal.org.objectweb.asm.*;
|
||||||
import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
|
import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
|
||||||
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||||
@@ -315,7 +316,7 @@ public class HttpServlet extends Servlet<HttpContext, HttpRequest, HttpResponse>
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final HttpResponse.BufferHandler cacheHandler;
|
public final BiFunction<HttpResponse, ByteBuffer[], ByteBuffer[]> cacheHandler;
|
||||||
|
|
||||||
public final ConcurrentHashMap<String, CacheEntry> cache;
|
public final ConcurrentHashMap<String, CacheEntry> cache;
|
||||||
|
|
||||||
|
|||||||
@@ -956,7 +956,7 @@ public final class Rest {
|
|||||||
av1.visitEnd();
|
av1.visitEnd();
|
||||||
av0.visitEnd();
|
av0.visitEnd();
|
||||||
}
|
}
|
||||||
|
int uploadLocal = 0;
|
||||||
if (mupload != null) { //存在文件上传
|
if (mupload != null) { //存在文件上传
|
||||||
if (muploadType == byte[].class) {
|
if (muploadType == byte[].class) {
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
mv.visitVarInsn(ALOAD, 1);
|
||||||
@@ -966,6 +966,7 @@ public final class Rest {
|
|||||||
mv.visitLdcInsn(mupload.contentTypeReg());
|
mv.visitLdcInsn(mupload.contentTypeReg());
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, "org/redkale/net/http/MultiContext", "partsFirstBytes", "(JLjava/lang/String;Ljava/lang/String;)[B", false);
|
mv.visitMethodInsn(INVOKEVIRTUAL, "org/redkale/net/http/MultiContext", "partsFirstBytes", "(JLjava/lang/String;Ljava/lang/String;)[B", false);
|
||||||
mv.visitVarInsn(ASTORE, maxLocals);
|
mv.visitVarInsn(ASTORE, maxLocals);
|
||||||
|
uploadLocal = maxLocals;
|
||||||
} else if (muploadType == File.class) {
|
} else if (muploadType == File.class) {
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
mv.visitVarInsn(ALOAD, 1);
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getMultiContext", "()Lorg/redkale/net/http/MultiContext;", false);
|
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getMultiContext", "()Lorg/redkale/net/http/MultiContext;", false);
|
||||||
@@ -976,6 +977,7 @@ public final class Rest {
|
|||||||
mv.visitLdcInsn(mupload.contentTypeReg());
|
mv.visitLdcInsn(mupload.contentTypeReg());
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, "org/redkale/net/http/MultiContext", "partsFirstFile", "(Ljava/io/File;JLjava/lang/String;Ljava/lang/String;)Ljava/io/File;", false);
|
mv.visitMethodInsn(INVOKEVIRTUAL, "org/redkale/net/http/MultiContext", "partsFirstFile", "(Ljava/io/File;JLjava/lang/String;Ljava/lang/String;)Ljava/io/File;", false);
|
||||||
mv.visitVarInsn(ASTORE, maxLocals);
|
mv.visitVarInsn(ASTORE, maxLocals);
|
||||||
|
uploadLocal = maxLocals;
|
||||||
} else if (muploadType == File[].class) { //File[]
|
} else if (muploadType == File[].class) { //File[]
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
mv.visitVarInsn(ALOAD, 1);
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getMultiContext", "()Lorg/redkale/net/http/MultiContext;", false);
|
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getMultiContext", "()Lorg/redkale/net/http/MultiContext;", false);
|
||||||
@@ -986,6 +988,7 @@ public final class Rest {
|
|||||||
mv.visitLdcInsn(mupload.contentTypeReg());
|
mv.visitLdcInsn(mupload.contentTypeReg());
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, "org/redkale/net/http/MultiContext", "partsFiles", "(Ljava/io/File;JLjava/lang/String;Ljava/lang/String;)[Ljava/io/File;", false);
|
mv.visitMethodInsn(INVOKEVIRTUAL, "org/redkale/net/http/MultiContext", "partsFiles", "(Ljava/io/File;JLjava/lang/String;Ljava/lang/String;)[Ljava/io/File;", false);
|
||||||
mv.visitVarInsn(ASTORE, maxLocals);
|
mv.visitVarInsn(ASTORE, maxLocals);
|
||||||
|
uploadLocal = maxLocals;
|
||||||
}
|
}
|
||||||
maxLocals++;
|
maxLocals++;
|
||||||
}
|
}
|
||||||
@@ -1402,7 +1405,7 @@ public final class Rest {
|
|||||||
} while ((loop = loop.getSuperclass()) != Object.class);
|
} while ((loop = loop.getSuperclass()) != Object.class);
|
||||||
|
|
||||||
if (!attrParaNames.isEmpty()) { //参数存在 RestHeader、RestCookie、RestSessionid、RestAddress、RestBody字段
|
if (!attrParaNames.isEmpty()) { //参数存在 RestHeader、RestCookie、RestSessionid、RestAddress、RestBody字段
|
||||||
mv.visitVarInsn(ALOAD, maxLocals);
|
mv.visitVarInsn(ALOAD, maxLocals); //加载JsonBean
|
||||||
Label lif = new Label();
|
Label lif = new Label();
|
||||||
mv.visitJumpInsn(IFNULL, lif); //if(bean != null) {
|
mv.visitJumpInsn(IFNULL, lif); //if(bean != null) {
|
||||||
for (Map.Entry<String, Object[]> en : attrParaNames.entrySet()) {
|
for (Map.Entry<String, Object[]> en : attrParaNames.entrySet()) {
|
||||||
@@ -1410,12 +1413,22 @@ public final class Rest {
|
|||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
mv.visitFieldInsn(GETFIELD, newDynName, en.getKey(), attrDesc);
|
mv.visitFieldInsn(GETFIELD, newDynName, en.getKey(), attrDesc);
|
||||||
mv.visitVarInsn(ALOAD, maxLocals);
|
mv.visitVarInsn(ALOAD, maxLocals);
|
||||||
boolean upload = en.getKey().contains("_upload");
|
mv.visitVarInsn(ALOAD, en.getKey().contains("_upload") ? uploadLocal : 1);
|
||||||
mv.visitVarInsn(ALOAD, upload ? (maxLocals - 1) : 1);
|
|
||||||
if (en.getKey().contains("_header_")) {
|
if (en.getKey().contains("_header_")) {
|
||||||
mv.visitLdcInsn(en.getValue()[0].toString());
|
String headerkey = en.getValue()[0].toString();
|
||||||
mv.visitLdcInsn("");
|
if ("Host".equalsIgnoreCase(headerkey)) {
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getHeader", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
|
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getHost", "()Ljava/lang/String;", false);
|
||||||
|
} else if ("Content-Type".equalsIgnoreCase(headerkey)) {
|
||||||
|
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getContentType", "()Ljava/lang/String;", false);
|
||||||
|
} else if ("Connection".equalsIgnoreCase(headerkey)) {
|
||||||
|
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getConnection", "()Ljava/lang/String;", false);
|
||||||
|
} else if ("Method".equalsIgnoreCase(headerkey)) {
|
||||||
|
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getMethod", "()Ljava/lang/String;", false);
|
||||||
|
} else {
|
||||||
|
mv.visitLdcInsn(headerkey);
|
||||||
|
mv.visitLdcInsn("");
|
||||||
|
mv.visitMethodInsn(INVOKEVIRTUAL, reqInternalName, "getHeader", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", false);
|
||||||
|
}
|
||||||
} else if (en.getKey().contains("_cookie_")) {
|
} else if (en.getKey().contains("_cookie_")) {
|
||||||
mv.visitLdcInsn(en.getValue()[0].toString());
|
mv.visitLdcInsn(en.getValue()[0].toString());
|
||||||
mv.visitLdcInsn("");
|
mv.visitLdcInsn("");
|
||||||
@@ -1562,7 +1575,7 @@ public final class Rest {
|
|||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
mv.visitFieldInsn(GETFIELD, newDynName, REST_JSONCONVERT_FIELD_PREFIX + restConverts.size(), jsonConvertDesc);
|
mv.visitFieldInsn(GETFIELD, newDynName, REST_JSONCONVERT_FIELD_PREFIX + restConverts.size(), jsonConvertDesc);
|
||||||
mv.visitVarInsn(ALOAD, maxLocals);
|
mv.visitVarInsn(ALOAD, maxLocals);
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + convertDesc + typeDesc + "Ljava/lang/Object;)V", false);
|
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(" + convertDesc + "Ljava/lang/Object;)V", false);
|
||||||
} else {
|
} else {
|
||||||
mv.visitVarInsn(ALOAD, maxLocals);
|
mv.visitVarInsn(ALOAD, maxLocals);
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/Object;)V", false);
|
mv.visitMethodInsn(INVOKEVIRTUAL, respInternalName, "finish", "(Ljava/lang/Object;)V", false);
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ public abstract class WebSocket<G extends Serializable, T> {
|
|||||||
@Comment("WebSocket已离线")
|
@Comment("WebSocket已离线")
|
||||||
public static final int RETCODE_WSOFFLINE = 1 << 8; //256
|
public static final int RETCODE_WSOFFLINE = 1 << 8; //256
|
||||||
|
|
||||||
|
@Comment("WebSocket将延迟发送")
|
||||||
|
public static final int RETCODE_DEAYSEND = 1 << 9; //512
|
||||||
|
|
||||||
WebSocketRunner _runner; //不可能为空
|
WebSocketRunner _runner; //不可能为空
|
||||||
|
|
||||||
WebSocketEngine _engine; //不可能为空
|
WebSocketEngine _engine; //不可能为空
|
||||||
@@ -90,6 +93,8 @@ public abstract class WebSocket<G extends Serializable, T> {
|
|||||||
|
|
||||||
private Map<String, Object> attributes = new HashMap<>(); //非线程安全
|
private Map<String, Object> attributes = new HashMap<>(); //非线程安全
|
||||||
|
|
||||||
|
List<WebSocketPacket> delayPackets;
|
||||||
|
|
||||||
protected WebSocket() {
|
protected WebSocket() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,6 +230,11 @@ public abstract class WebSocket<G extends Serializable, T> {
|
|||||||
* @return 0表示成功, 非0表示错误码
|
* @return 0表示成功, 非0表示错误码
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Integer> sendPacket(WebSocketPacket packet) {
|
CompletableFuture<Integer> sendPacket(WebSocketPacket packet) {
|
||||||
|
if (this._runner == null) {
|
||||||
|
if (delayPackets == null) delayPackets = new ArrayList<>();
|
||||||
|
delayPackets.add(packet);
|
||||||
|
return CompletableFuture.completedFuture(RETCODE_DEAYSEND);
|
||||||
|
}
|
||||||
CompletableFuture<Integer> rs = this._runner.sendMessage(packet);
|
CompletableFuture<Integer> rs = this._runner.sendMessage(packet);
|
||||||
if (_engine.logger.isLoggable(Level.FINEST) && packet != WebSocketPacket.DEFAULT_PING_PACKET) {
|
if (_engine.logger.isLoggable(Level.FINEST) && packet != WebSocketPacket.DEFAULT_PING_PACKET) {
|
||||||
_engine.logger.finest("userid:" + getUserid() + " send websocket message(" + packet + ")" + " on " + this);
|
_engine.logger.finest("userid:" + getUserid() + " send websocket message(" + packet + ")" + " on " + this);
|
||||||
|
|||||||
@@ -349,6 +349,7 @@ public abstract class WebSocketNode {
|
|||||||
*/
|
*/
|
||||||
public final CompletableFuture<Integer> sendMessage(final Convert convert, final Object message0, final boolean last, final Serializable... userids) {
|
public final CompletableFuture<Integer> sendMessage(final Convert convert, final Object message0, final boolean last, final Serializable... userids) {
|
||||||
if (userids == null || userids.length < 1) return CompletableFuture.completedFuture(RETCODE_GROUP_EMPTY);
|
if (userids == null || userids.length < 1) return CompletableFuture.completedFuture(RETCODE_GROUP_EMPTY);
|
||||||
|
if (message0 instanceof CompletableFuture) return ((CompletableFuture) message0).thenApply(msg -> sendMessage(convert, msg, last, userids));
|
||||||
final Object message = (convert == null || message0 instanceof WebSocketPacket) ? message0 : ((convert instanceof TextConvert) ? new WebSocketPacket(((TextConvert) convert).convertTo(message0), last) : new WebSocketPacket(((BinaryConvert) convert).convertTo(message0), last));
|
final Object message = (convert == null || message0 instanceof WebSocketPacket) ? message0 : ((convert instanceof TextConvert) ? new WebSocketPacket(((TextConvert) convert).convertTo(message0), last) : new WebSocketPacket(((BinaryConvert) convert).convertTo(message0), last));
|
||||||
if (this.localEngine != null && this.sncpNodeAddresses == null) { //本地模式且没有分布式
|
if (this.localEngine != null && this.sncpNodeAddresses == null) { //本地模式且没有分布式
|
||||||
return this.localEngine.sendMessage(message, last, userids);
|
return this.localEngine.sendMessage(message, last, userids);
|
||||||
@@ -406,6 +407,7 @@ public abstract class WebSocketNode {
|
|||||||
* @return 为0表示成功, 其他值表示部分发送异常
|
* @return 为0表示成功, 其他值表示部分发送异常
|
||||||
*/
|
*/
|
||||||
public final CompletableFuture<Integer> broadcastMessage(final Convert convert, final Object message0, final boolean last) {
|
public final CompletableFuture<Integer> broadcastMessage(final Convert convert, final Object message0, final boolean last) {
|
||||||
|
if (message0 instanceof CompletableFuture) return ((CompletableFuture) message0).thenApply(msg -> broadcastMessage(convert, msg, last));
|
||||||
final Object message = (convert == null || message0 instanceof WebSocketPacket) ? message0 : ((convert instanceof TextConvert) ? new WebSocketPacket(((TextConvert) convert).convertTo(message0), last) : new WebSocketPacket(((BinaryConvert) convert).convertTo(message0), last));
|
final Object message = (convert == null || message0 instanceof WebSocketPacket) ? message0 : ((convert instanceof TextConvert) ? new WebSocketPacket(((TextConvert) convert).convertTo(message0), last) : new WebSocketPacket(((BinaryConvert) convert).convertTo(message0), last));
|
||||||
if (this.localEngine != null && this.sncpNodeAddresses == null) { //本地模式且没有分布式
|
if (this.localEngine != null && this.sncpNodeAddresses == null) { //本地模式且没有分布式
|
||||||
return this.localEngine.broadcastMessage(message, last);
|
return this.localEngine.broadcastMessage(message, last);
|
||||||
@@ -429,7 +431,7 @@ public abstract class WebSocketNode {
|
|||||||
|
|
||||||
private CompletableFuture<Integer> sendOneMessage(final Object message, final boolean last, final Serializable userid) {
|
private CompletableFuture<Integer> sendOneMessage(final Object message, final boolean last, final Serializable userid) {
|
||||||
if (message instanceof CompletableFuture) return ((CompletableFuture) message).thenApply(msg -> sendOneMessage(msg, last, userid));
|
if (message instanceof CompletableFuture) return ((CompletableFuture) message).thenApply(msg -> sendOneMessage(msg, last, userid));
|
||||||
if (logger.isLoggable(Level.FINEST)) logger.finest("websocket want send message {userid:" + userid + ", content:'" + message + "'} from locale node to " + ((this.localEngine != null) ? "locale" : "remote") + " engine");
|
if (logger.isLoggable(Level.FINEST)) logger.finest("websocket want send message {userid:" + userid + ", content:'" + JsonConvert.root().convertTo(message) + "'} from locale node to " + ((this.localEngine != null) ? "locale" : "remote") + " engine");
|
||||||
CompletableFuture<Integer> localFuture = null;
|
CompletableFuture<Integer> localFuture = null;
|
||||||
if (this.localEngine != null) localFuture = localEngine.sendMessage(message, last, userid);
|
if (this.localEngine != null) localFuture = localEngine.sendMessage(message, last, userid);
|
||||||
if (this.sncpNodeAddresses == null || this.remoteNode == null) {
|
if (this.sncpNodeAddresses == null || this.remoteNode == null) {
|
||||||
@@ -442,7 +444,7 @@ public abstract class WebSocketNode {
|
|||||||
CompletableFuture<Integer> remoteFuture = addrsFuture.thenCompose((Collection<InetSocketAddress> addrs) -> {
|
CompletableFuture<Integer> remoteFuture = addrsFuture.thenCompose((Collection<InetSocketAddress> addrs) -> {
|
||||||
if (addrs == null || addrs.isEmpty()) {
|
if (addrs == null || addrs.isEmpty()) {
|
||||||
if (logger.isLoggable(Level.FINER)) logger.finer("websocket not found userid:" + userid + " on any node ");
|
if (logger.isLoggable(Level.FINER)) logger.finer("websocket not found userid:" + userid + " on any node ");
|
||||||
return CompletableFuture.completedFuture(0);
|
return CompletableFuture.completedFuture(RETCODE_GROUP_EMPTY);
|
||||||
}
|
}
|
||||||
if (logger.isLoggable(Level.FINEST)) logger.finest("websocket(localaddr=" + localSncpAddress + ") found userid:" + userid + " on " + addrs);
|
if (logger.isLoggable(Level.FINEST)) logger.finest("websocket(localaddr=" + localSncpAddress + ") found userid:" + userid + " on " + addrs);
|
||||||
CompletableFuture<Integer> future = null;
|
CompletableFuture<Integer> future = null;
|
||||||
@@ -452,7 +454,7 @@ public abstract class WebSocketNode {
|
|||||||
future = future == null ? remoteNode.sendMessage(addr, remoteMessage, last, userid)
|
future = future == null ? remoteNode.sendMessage(addr, remoteMessage, last, userid)
|
||||||
: future.thenCombine(remoteNode.sendMessage(addr, remoteMessage, last, userid), (a, b) -> a | b);
|
: future.thenCombine(remoteNode.sendMessage(addr, remoteMessage, last, userid), (a, b) -> a | b);
|
||||||
}
|
}
|
||||||
return future == null ? CompletableFuture.completedFuture(0) : future;
|
return future == null ? CompletableFuture.completedFuture(RETCODE_GROUP_EMPTY) : future;
|
||||||
});
|
});
|
||||||
return localFuture == null ? remoteFuture : localFuture.thenCombine(remoteFuture, (a, b) -> a | b);
|
return localFuture == null ? remoteFuture : localFuture.thenCombine(remoteFuture, (a, b) -> a | b);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -433,6 +433,10 @@ class WebSocketRunner implements Runnable {
|
|||||||
return futureResult;
|
return futureResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isClosed() {
|
||||||
|
return closed;
|
||||||
|
}
|
||||||
|
|
||||||
public void closeRunner(int code) {
|
public void closeRunner(int code) {
|
||||||
if (closed) return;
|
if (closed) return;
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ public abstract class WebSocketServlet extends HttpServlet implements Resourcabl
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sessionFuture.whenComplete((sessionid, ex) -> {
|
sessionFuture.whenComplete((sessionid, ex) -> {
|
||||||
if (sessionid == null || ex != null) {
|
if ((sessionid == null && webSocket.delayPackets == null) || ex != null) {
|
||||||
if (debug || ex != null) logger.log(ex == null ? Level.FINEST : Level.FINE, "WebSocket connect abort, Not found sessionid or occur error. request=" + request, ex);
|
if (debug || ex != null) logger.log(ex == null ? Level.FINEST : Level.FINE, "WebSocket connect abort, Not found sessionid or occur error. request=" + request, ex);
|
||||||
response.finish(true);
|
response.finish(true);
|
||||||
return;
|
return;
|
||||||
@@ -195,39 +195,93 @@ public abstract class WebSocketServlet extends HttpServlet implements Resourcabl
|
|||||||
response.addHeader("Sec-WebSocket-Accept", Base64.getEncoder().encodeToString(bytes));
|
response.addHeader("Sec-WebSocket-Accept", Base64.getEncoder().encodeToString(bytes));
|
||||||
response.sendBody((ByteBuffer) null, null, new CompletionHandler<Integer, Void>() {
|
response.sendBody((ByteBuffer) null, null, new CompletionHandler<Integer, Void>() {
|
||||||
|
|
||||||
|
WebSocketRunner temprunner = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void completed(Integer result, Void attachment) {
|
public void completed(Integer result, Void attachment) {
|
||||||
HttpContext context = response.getContext();
|
HttpContext context = response.getContext();
|
||||||
CompletableFuture<Serializable> userFuture = webSocket.createUserid();
|
|
||||||
if (userFuture == null) {
|
Runnable createUseridHandler = () -> {
|
||||||
if (debug) logger.finest("WebSocket connect abort, Create userid abort. request = " + request);
|
CompletableFuture<Serializable> userFuture = webSocket.createUserid();
|
||||||
response.finish(true);
|
if (userFuture == null) {
|
||||||
return;
|
if (debug) logger.finest("WebSocket connect abort, Create userid abort. request = " + request);
|
||||||
}
|
|
||||||
userFuture.whenComplete((userid, ex2) -> {
|
|
||||||
if (userid == null || ex2 != null) {
|
|
||||||
if (debug || ex2 != null) logger.log(ex2 == null ? Level.FINEST : Level.FINE, "WebSocket connect abort, Create userid abort. request = " + request, ex2);
|
|
||||||
response.finish(true);
|
response.finish(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
webSocket._userid = userid;
|
userFuture.whenComplete((userid, ex2) -> {
|
||||||
if (single && !anyuser) {
|
if ((userid == null && webSocket.delayPackets == null) || ex2 != null) {
|
||||||
WebSocketServlet.this.node.existsWebSocket(userid).whenComplete((rs, ex) -> {
|
if (debug || ex2 != null) logger.log(ex2 == null ? Level.FINEST : Level.FINE, "WebSocket connect abort, Create userid abort. request = " + request, ex2);
|
||||||
if (rs) webSocket.onSingleRepeatConnect();
|
|
||||||
WebSocketServlet.this.node.localEngine.add(webSocket);
|
|
||||||
WebSocketRunner runner = new WebSocketRunner(context, webSocket, restMessageConsumer, response.removeChannel());
|
|
||||||
webSocket._runner = runner;
|
|
||||||
context.runAsync(runner);
|
|
||||||
response.finish(true);
|
response.finish(true);
|
||||||
});
|
return;
|
||||||
} else {
|
}
|
||||||
WebSocketServlet.this.node.localEngine.add(webSocket);
|
Runnable runHandler = () -> {
|
||||||
WebSocketRunner runner = new WebSocketRunner(context, webSocket, restMessageConsumer, response.removeChannel());
|
temprunner = null;
|
||||||
webSocket._runner = runner;
|
webSocket._userid = userid;
|
||||||
context.runAsync(runner);
|
if (single && !anyuser) {
|
||||||
response.finish(true);
|
WebSocketServlet.this.node.existsWebSocket(userid).whenComplete((rs, ex) -> {
|
||||||
|
if (rs) webSocket.onSingleRepeatConnect();
|
||||||
|
WebSocketServlet.this.node.localEngine.add(webSocket);
|
||||||
|
WebSocketRunner runner = new WebSocketRunner(context, webSocket, restMessageConsumer, response.removeChannel());
|
||||||
|
webSocket._runner = runner;
|
||||||
|
context.runAsync(runner);
|
||||||
|
response.finish(true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
WebSocketServlet.this.node.localEngine.add(webSocket);
|
||||||
|
WebSocketRunner runner = new WebSocketRunner(context, webSocket, restMessageConsumer, response.removeChannel());
|
||||||
|
webSocket._runner = runner;
|
||||||
|
context.runAsync(runner);
|
||||||
|
response.finish(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (webSocket.delayPackets != null) { //存在待发送的消息
|
||||||
|
if (temprunner == null) temprunner = new WebSocketRunner(context, webSocket, restMessageConsumer, response.getChannel());
|
||||||
|
List<WebSocketPacket> delayPackets = webSocket.delayPackets;
|
||||||
|
webSocket.delayPackets = null;
|
||||||
|
CompletableFuture<Integer> cf = null;
|
||||||
|
for (WebSocketPacket packet : delayPackets) {
|
||||||
|
if (cf == null) {
|
||||||
|
cf = temprunner.sendMessage(packet);
|
||||||
|
} else {
|
||||||
|
cf = cf.thenCombine(temprunner.sendMessage(packet), (a, b) -> a | b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cf.whenComplete((Integer v, Throwable t) -> {
|
||||||
|
if (userid == null || t != null || (temprunner != null && temprunner.isClosed())) {
|
||||||
|
if (t != null) logger.log(Level.FINEST, "WebSocket connect abort, Response send delayPackets abort. request = " + request, t);
|
||||||
|
response.finish(true);
|
||||||
|
} else {
|
||||||
|
runHandler.run();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
runHandler.run();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
if (webSocket.delayPackets != null) { //存在待发送的消息
|
||||||
|
if (temprunner == null) temprunner = new WebSocketRunner(context, webSocket, restMessageConsumer, response.getChannel());
|
||||||
|
List<WebSocketPacket> delayPackets = webSocket.delayPackets;
|
||||||
|
webSocket.delayPackets = null;
|
||||||
|
CompletableFuture<Integer> cf = null;
|
||||||
|
for (WebSocketPacket packet : delayPackets) {
|
||||||
|
if (cf == null) {
|
||||||
|
cf = temprunner.sendMessage(packet);
|
||||||
|
} else {
|
||||||
|
cf = cf.thenCombine(temprunner.sendMessage(packet), (a, b) -> a | b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
cf.whenComplete((Integer v, Throwable t) -> {
|
||||||
|
if (sessionid == null || t != null || (temprunner != null && temprunner.isClosed())) {
|
||||||
|
if (t != null) logger.log(Level.FINEST, "WebSocket connect abort, Response send delayPackets abort. request = " + request, t);
|
||||||
|
response.finish(true);
|
||||||
|
} else {
|
||||||
|
createUseridHandler.run();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
createUseridHandler.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public final class SncpResponse extends Response<SncpContext, SncpRequest> {
|
|||||||
|
|
||||||
public void finish(final int retcode, final BsonWriter out) {
|
public void finish(final int retcode, final BsonWriter out) {
|
||||||
if (out == null) {
|
if (out == null) {
|
||||||
final ByteBuffer buffer = context.pollBuffer();
|
final ByteBuffer buffer = pollWriteReadBuffer();
|
||||||
fillHeader(buffer, 0, retcode);
|
fillHeader(buffer, 0, retcode);
|
||||||
finish(buffer);
|
finish(buffer);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -124,7 +124,8 @@ public class RetResult<T> {
|
|||||||
*/
|
*/
|
||||||
public RetResult<T> attach(String key, Object value) {
|
public RetResult<T> attach(String key, Object value) {
|
||||||
if (this.attach == null) this.attach = new HashMap<>();
|
if (this.attach == null) this.attach = new HashMap<>();
|
||||||
this.attach.put(key, value == null ? null : String.valueOf(value));
|
boolean canstr = value != null && (value instanceof CharSequence || value.getClass().isPrimitive());
|
||||||
|
this.attach.put(key, value == null ? null : (canstr ? String.valueOf(value) : JsonConvert.root().convertTo(value)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -667,6 +667,39 @@ public class CacheMemorySource<V extends Object> extends AbstractService impleme
|
|||||||
return (Collection<String>) getAndRefresh(key, expireSeconds);
|
return (Collection<String>) getAndRefresh(key, expireSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean existsSetItem(final String key, final V value) {
|
||||||
|
Collection<V> list = getCollection(key);
|
||||||
|
return list != null && list.contains(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Boolean> existsSetItemAsync(final String key, final V value) {
|
||||||
|
return CompletableFuture.supplyAsync(() -> existsSetItem(key, value), getExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean existsStringSetItem(final String key, final String value) {
|
||||||
|
Collection<String> list = getStringCollection(key);
|
||||||
|
return list != null && list.contains(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Boolean> existsStringSetItemAsync(final String key, final String value) {
|
||||||
|
return CompletableFuture.supplyAsync(() -> existsStringSetItem(key, value), getExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean existsLongSetItem(final String key, final long value) {
|
||||||
|
Collection<Long> list = getLongCollection(key);
|
||||||
|
return list != null && list.contains(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Boolean> existsLongSetItemAsync(final String key, final long value) {
|
||||||
|
return CompletableFuture.supplyAsync(() -> existsLongSetItem(key, value), getExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@RpcMultiRun
|
@RpcMultiRun
|
||||||
public Collection<Long> getLongCollectionAndRefresh(final String key, final int expireSeconds) {
|
public Collection<Long> getLongCollectionAndRefresh(final String key, final int expireSeconds) {
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ public interface CacheSource<V extends Object> {
|
|||||||
|
|
||||||
public void removeListItem(final String key, final V value);
|
public void removeListItem(final String key, final V value);
|
||||||
|
|
||||||
|
public boolean existsSetItem(final String key, final V value);
|
||||||
|
|
||||||
public void appendSetItem(final String key, final V value);
|
public void appendSetItem(final String key, final V value);
|
||||||
|
|
||||||
public void removeSetItem(final String key, final V value);
|
public void removeSetItem(final String key, final V value);
|
||||||
@@ -92,6 +94,8 @@ public interface CacheSource<V extends Object> {
|
|||||||
|
|
||||||
public void removeStringListItem(final String key, final String value);
|
public void removeStringListItem(final String key, final String value);
|
||||||
|
|
||||||
|
public boolean existsStringSetItem(final String key, final String value);
|
||||||
|
|
||||||
public void appendStringSetItem(final String key, final String value);
|
public void appendStringSetItem(final String key, final String value);
|
||||||
|
|
||||||
public void removeStringSetItem(final String key, final String value);
|
public void removeStringSetItem(final String key, final String value);
|
||||||
@@ -112,6 +116,8 @@ public interface CacheSource<V extends Object> {
|
|||||||
|
|
||||||
public void removeLongListItem(final String key, final long value);
|
public void removeLongListItem(final String key, final long value);
|
||||||
|
|
||||||
|
public boolean existsLongSetItem(final String key, final long value);
|
||||||
|
|
||||||
public void appendLongSetItem(final String key, final long value);
|
public void appendLongSetItem(final String key, final long value);
|
||||||
|
|
||||||
public void removeLongSetItem(final String key, final long value);
|
public void removeLongSetItem(final String key, final long value);
|
||||||
@@ -151,6 +157,8 @@ public interface CacheSource<V extends Object> {
|
|||||||
|
|
||||||
public CompletableFuture<Void> removeListItemAsync(final String key, final V value);
|
public CompletableFuture<Void> removeListItemAsync(final String key, final V value);
|
||||||
|
|
||||||
|
public CompletableFuture<Boolean> existsSetItemAsync(final String key, final V value);
|
||||||
|
|
||||||
public CompletableFuture<Void> appendSetItemAsync(final String key, final V value);
|
public CompletableFuture<Void> appendSetItemAsync(final String key, final V value);
|
||||||
|
|
||||||
public CompletableFuture<Void> removeSetItemAsync(final String key, final V value);
|
public CompletableFuture<Void> removeSetItemAsync(final String key, final V value);
|
||||||
@@ -177,6 +185,8 @@ public interface CacheSource<V extends Object> {
|
|||||||
|
|
||||||
public CompletableFuture<Void> removeStringListItemAsync(final String key, final String value);
|
public CompletableFuture<Void> removeStringListItemAsync(final String key, final String value);
|
||||||
|
|
||||||
|
public CompletableFuture<Boolean> existsStringSetItemAsync(final String key, final String value);
|
||||||
|
|
||||||
public CompletableFuture<Void> appendStringSetItemAsync(final String key, final String value);
|
public CompletableFuture<Void> appendStringSetItemAsync(final String key, final String value);
|
||||||
|
|
||||||
public CompletableFuture<Void> removeStringSetItemAsync(final String key, final String value);
|
public CompletableFuture<Void> removeStringSetItemAsync(final String key, final String value);
|
||||||
@@ -197,6 +207,8 @@ public interface CacheSource<V extends Object> {
|
|||||||
|
|
||||||
public CompletableFuture<Void> removeLongListItemAsync(final String key, final long value);
|
public CompletableFuture<Void> removeLongListItemAsync(final String key, final long value);
|
||||||
|
|
||||||
|
public CompletableFuture<Boolean> existsLongSetItemAsync(final String key, final long value);
|
||||||
|
|
||||||
public CompletableFuture<Void> appendLongSetItemAsync(final String key, final long value);
|
public CompletableFuture<Void> appendLongSetItemAsync(final String key, final long value);
|
||||||
|
|
||||||
public CompletableFuture<Void> removeLongSetItemAsync(final String key, final long value);
|
public CompletableFuture<Void> removeLongSetItemAsync(final String key, final long value);
|
||||||
|
|||||||
@@ -109,27 +109,33 @@ public class DataJdbcSource extends AbstractService implements DataSource, DataC
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Local
|
||||||
public void close() throws Exception {
|
public void close() throws Exception {
|
||||||
readPool.close();
|
readPool.close();
|
||||||
writePool.close();
|
writePool.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Local
|
||||||
public PoolJdbcSource getReadPoolJdbcSource() {
|
public PoolJdbcSource getReadPoolJdbcSource() {
|
||||||
return readPool;
|
return readPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Local
|
||||||
public PoolJdbcSource getWritePoolJdbcSource() {
|
public PoolJdbcSource getWritePoolJdbcSource() {
|
||||||
return writePool;
|
return writePool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Local
|
||||||
public Connection createReadSQLConnection() {
|
public Connection createReadSQLConnection() {
|
||||||
return readPool.poll();
|
return readPool.poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Local
|
||||||
public <T> Connection createWriteSQLConnection() {
|
public <T> Connection createWriteSQLConnection() {
|
||||||
return writePool.poll();
|
return writePool.poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Local
|
||||||
public void closeSQLConnection(final Connection sqlconn) {
|
public void closeSQLConnection(final Connection sqlconn) {
|
||||||
if (sqlconn == null) return;
|
if (sqlconn == null) return;
|
||||||
try {
|
try {
|
||||||
@@ -140,6 +146,7 @@ public class DataJdbcSource extends AbstractService implements DataSource, DataC
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Local
|
||||||
public EntityInfo apply(Class t) {
|
public EntityInfo apply(Class t) {
|
||||||
return loadEntityInfo(t);
|
return loadEntityInfo(t);
|
||||||
}
|
}
|
||||||
@@ -972,9 +979,8 @@ public class DataJdbcSource extends AbstractService implements DataSource, DataC
|
|||||||
}
|
}
|
||||||
String sql = "UPDATE " + info.getTable(node) + " a " + (join1 == null ? "" : (", " + join1)) + " SET " + setsql
|
String sql = "UPDATE " + info.getTable(node) + " a " + (join1 == null ? "" : (", " + join1)) + " SET " + setsql
|
||||||
+ ((where == null || where.length() == 0) ? (join2 == null ? "" : (" WHERE " + join2))
|
+ ((where == null || where.length() == 0) ? (join2 == null ? "" : (" WHERE " + join2))
|
||||||
: (" WHERE " + where + (join2 == null ? "" : (" AND " + join2))));
|
: (" WHERE " + where + (join2 == null ? "" : (" AND " + join2))))
|
||||||
//注:LIMIT 仅支持MySQL 且在多表关联式会异常, 该BUG尚未解决
|
+ info.createSQLOrderby(flipper);
|
||||||
sql += info.createSQLOrderby(flipper) + ((flipper == null || flipper.getLimit() < 1) ? "" : (" LIMIT " + flipper.getLimit()));
|
|
||||||
if (info.isLoggable(logger, Level.FINEST)) logger.finest(info.getType().getSimpleName() + " update sql=" + sql);
|
if (info.isLoggable(logger, Level.FINEST)) logger.finest(info.getType().getSimpleName() + " update sql=" + sql);
|
||||||
conn.setReadOnly(false);
|
conn.setReadOnly(false);
|
||||||
if (blobs != null) {
|
if (blobs != null) {
|
||||||
@@ -2369,7 +2375,8 @@ public class DataJdbcSource extends AbstractService implements DataSource, DataC
|
|||||||
*
|
*
|
||||||
* @return 结果数组
|
* @return 结果数组
|
||||||
*/
|
*/
|
||||||
public final int[] directExecute(String... sqls) {
|
@Local
|
||||||
|
public int[] directExecute(String... sqls) {
|
||||||
Connection conn = createWriteSQLConnection();
|
Connection conn = createWriteSQLConnection();
|
||||||
try {
|
try {
|
||||||
return directExecute(conn, sqls);
|
return directExecute(conn, sqls);
|
||||||
@@ -2385,7 +2392,8 @@ public class DataJdbcSource extends AbstractService implements DataSource, DataC
|
|||||||
* @param sql SQL语句
|
* @param sql SQL语句
|
||||||
* @param consumer 回调函数
|
* @param consumer 回调函数
|
||||||
*/
|
*/
|
||||||
public final void directQuery(String sql, Consumer<ResultSet> consumer) {
|
@Local
|
||||||
|
public void directQuery(String sql, Consumer<ResultSet> consumer) {
|
||||||
final Connection conn = createReadSQLConnection();
|
final Connection conn = createReadSQLConnection();
|
||||||
try {
|
try {
|
||||||
if (logger.isLoggable(Level.FINEST)) logger.finest("direct query sql=" + sql);
|
if (logger.isLoggable(Level.FINEST)) logger.finest("direct query sql=" + sql);
|
||||||
|
|||||||
@@ -300,7 +300,7 @@ public interface DataSource {
|
|||||||
* 更新符合过滤条件的记录的指定字段 <br>
|
* 更新符合过滤条件的记录的指定字段 <br>
|
||||||
* Flipper中offset字段将被忽略 <br>
|
* Flipper中offset字段将被忽略 <br>
|
||||||
* <b>注意</b>:Entity类中标记为@Column(updatable=false)不会被更新 <br>
|
* <b>注意</b>:Entity类中标记为@Column(updatable=false)不会被更新 <br>
|
||||||
* 等价SQL: UPDATE {table} SET {column1} = {value1}, {column2} += {value2}, {column3} *= {value3}, ··· WHERE {filter node} ORDER BY {flipper.sort} LIMIT {flipper.limit} <br>
|
* 等价SQL: UPDATE {table} SET {column1} = {value1}, {column2} += {value2}, {column3} *= {value3}, ··· WHERE {filter node} ORDER BY {flipper.sort} <br>
|
||||||
*
|
*
|
||||||
* @param <T> Entity泛型
|
* @param <T> Entity泛型
|
||||||
* @param clazz Entity类
|
* @param clazz Entity类
|
||||||
@@ -316,7 +316,7 @@ public interface DataSource {
|
|||||||
* 更新符合过滤条件的记录的指定字段 <br>
|
* 更新符合过滤条件的记录的指定字段 <br>
|
||||||
* Flipper中offset字段将被忽略 <br>
|
* Flipper中offset字段将被忽略 <br>
|
||||||
* <b>注意</b>:Entity类中标记为@Column(updatable=false)不会被更新 <br>
|
* <b>注意</b>:Entity类中标记为@Column(updatable=false)不会被更新 <br>
|
||||||
* 等价SQL: UPDATE {table} SET {column1} = {value1}, {column2} += {value2}, {column3} *= {value3}, ··· WHERE {filter node} ORDER BY {flipper.sort} LIMIT {flipper.limit} <br>
|
* 等价SQL: UPDATE {table} SET {column1} = {value1}, {column2} += {value2}, {column3} *= {value3}, ··· WHERE {filter node} ORDER BY {flipper.sort} <br>
|
||||||
*
|
*
|
||||||
* @param <T> Entity泛型
|
* @param <T> Entity泛型
|
||||||
* @param clazz Entity类
|
* @param clazz Entity类
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ public final class EntityCache<T> {
|
|||||||
rs = rs2;
|
rs = rs2;
|
||||||
} else if (func == DISTINCTCOUNT) {
|
} else if (func == DISTINCTCOUNT) {
|
||||||
Map rs2 = new LinkedHashMap();
|
Map rs2 = new LinkedHashMap();
|
||||||
rs.forEach((x, y) -> rs2.put(x, ((Set) y).size()));
|
rs.forEach((x, y) -> rs2.put(x, ((Set) y).size() + 0L));
|
||||||
rs = rs2;
|
rs = rs2;
|
||||||
}
|
}
|
||||||
return rs;
|
return rs;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import java.util.logging.*;
|
|||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 对象池元素的数据类型
|
* @param <T> 对象池元素的数据类型
|
||||||
*/
|
*/
|
||||||
public final class ObjectPool<T> implements Supplier<T> {
|
public final class ObjectPool<T> implements Supplier<T>, Consumer<T> {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ObjectPool.class.getSimpleName());
|
private static final Logger logger = Logger.getLogger(ObjectPool.class.getSimpleName());
|
||||||
|
|
||||||
@@ -67,6 +67,10 @@ public final class ObjectPool<T> implements Supplier<T> {
|
|||||||
this.creator = creator;
|
this.creator = creator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Predicate<T> getRecyclerPredicate() {
|
||||||
|
return recycler;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T get() {
|
public T get() {
|
||||||
T result = queue.poll();
|
T result = queue.poll();
|
||||||
@@ -78,21 +82,27 @@ public final class ObjectPool<T> implements Supplier<T> {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void offer(final T e) {
|
@Override
|
||||||
|
public void accept(final T e) {
|
||||||
if (e != null && recycler.test(e)) {
|
if (e != null && recycler.test(e)) {
|
||||||
if (cycleCounter != null) cycleCounter.incrementAndGet();
|
if (cycleCounter != null) cycleCounter.incrementAndGet();
|
||||||
if (debug) {
|
// if (debug) {
|
||||||
for (T t : queue) {
|
// for (T t : queue) {
|
||||||
if (t == e) {
|
// if (t == e) {
|
||||||
logger.log(Level.WARNING, "[" + Thread.currentThread().getName() + "] repeat offer the same object(" + e + ")", new Exception());
|
// logger.log(Level.WARNING, "[" + Thread.currentThread().getName() + "] repeat offer the same object(" + e + ")", new Exception());
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
queue.offer(e);
|
queue.offer(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public void offer(final T e) {
|
||||||
|
accept(e);
|
||||||
|
}
|
||||||
|
|
||||||
public long getCreatCount() {
|
public long getCreatCount() {
|
||||||
return creatCounter.longValue();
|
return creatCounter.longValue();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public final class Redkale {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getDotedVersion() {
|
public static String getDotedVersion() {
|
||||||
return "1.8.7";
|
return "1.8.9";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getMajorVersion() {
|
public static int getMajorVersion() {
|
||||||
|
|||||||
@@ -230,6 +230,191 @@ public final class Utility {
|
|||||||
return news;
|
return news;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取int数组之和
|
||||||
|
*
|
||||||
|
* @param array 数组
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static int sum(final int... array) {
|
||||||
|
if (array == null || array.length == 0) throw new NullPointerException("array is null or empty");
|
||||||
|
int sum = 0;
|
||||||
|
for (int i : array) {
|
||||||
|
sum += i;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取long数组之和
|
||||||
|
*
|
||||||
|
* @param array 数组
|
||||||
|
*
|
||||||
|
* @return long
|
||||||
|
*/
|
||||||
|
public static long sum(final long... array) {
|
||||||
|
if (array == null || array.length == 0) throw new NullPointerException("array is null or empty");
|
||||||
|
long sum = 0L;
|
||||||
|
for (long i : array) {
|
||||||
|
sum += i;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取int数组最大值
|
||||||
|
*
|
||||||
|
* @param array 数组
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static int max(final int... array) {
|
||||||
|
if (array == null || array.length == 0) throw new NullPointerException("array is null or empty");
|
||||||
|
int max = array[0];
|
||||||
|
for (int i : array) {
|
||||||
|
if (i > max) i = max;
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取long数组最大值
|
||||||
|
*
|
||||||
|
* @param array 数组
|
||||||
|
*
|
||||||
|
* @return long
|
||||||
|
*/
|
||||||
|
public static long max(final long... array) {
|
||||||
|
if (array == null || array.length == 0) throw new NullPointerException("array is null or empty");
|
||||||
|
long max = array[0];
|
||||||
|
for (long i : array) {
|
||||||
|
if (i > max) i = max;
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取int数组最小值
|
||||||
|
*
|
||||||
|
* @param array 数组
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static long min(final int... array) {
|
||||||
|
if (array == null || array.length == 0) throw new NullPointerException("array is null or empty");
|
||||||
|
int min = array[0];
|
||||||
|
for (int i : array) {
|
||||||
|
if (i < min) i = min;
|
||||||
|
}
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取long数组最小值
|
||||||
|
*
|
||||||
|
* @param array 数组
|
||||||
|
*
|
||||||
|
* @return long
|
||||||
|
*/
|
||||||
|
public static long min(final long... array) {
|
||||||
|
if (array == null || array.length == 0) throw new NullPointerException("array is null or empty");
|
||||||
|
long min = array[0];
|
||||||
|
for (long i : array) {
|
||||||
|
if (i < min) i = min;
|
||||||
|
}
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将int数组用分隔符拼接成字符串
|
||||||
|
*
|
||||||
|
* @param array 数组
|
||||||
|
* @param delimiter 分隔符
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static String joining(final int[] array, final String delimiter) {
|
||||||
|
if (array == null || array.length == 0) return "";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i : array) {
|
||||||
|
if (sb.length() > 0) sb.append(delimiter);
|
||||||
|
sb.append(i);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将long数组用分隔符拼接成字符串
|
||||||
|
*
|
||||||
|
* @param array 数组
|
||||||
|
* @param delimiter 分隔符
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static String joining(final long[] array, final String delimiter) {
|
||||||
|
if (array == null || array.length == 0) return "";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (long i : array) {
|
||||||
|
if (sb.length() > 0) sb.append(delimiter);
|
||||||
|
sb.append(i);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将对象数组用分隔符拼接成字符串
|
||||||
|
*
|
||||||
|
* @param <T> 泛型
|
||||||
|
* @param array 数组
|
||||||
|
* @param delimiter 分隔符
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static <T> String joining(final T[] array, final String delimiter) {
|
||||||
|
if (array == null || array.length == 0) return "";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (T i : array) {
|
||||||
|
if (sb.length() > 0) sb.append(delimiter);
|
||||||
|
sb.append(i);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将一个或多个int新元素添加到int数组结尾
|
||||||
|
*
|
||||||
|
* @param array 原数组
|
||||||
|
* @param objs 待追加数据
|
||||||
|
*
|
||||||
|
* @return 新数组
|
||||||
|
*/
|
||||||
|
public static int[] append(final int[] array, final int... objs) {
|
||||||
|
if (array == null || array.length == 0) return objs;
|
||||||
|
if (objs == null || objs.length == 0) return array;
|
||||||
|
final int[] news = new int[array.length + objs.length];
|
||||||
|
System.arraycopy(array, 0, news, 0, array.length);
|
||||||
|
System.arraycopy(objs, 0, news, array.length, objs.length);
|
||||||
|
return news;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将一个或多个long新元素添加到long数组结尾
|
||||||
|
*
|
||||||
|
* @param array 原数组
|
||||||
|
* @param objs 待追加数据
|
||||||
|
*
|
||||||
|
* @return 新数组
|
||||||
|
*/
|
||||||
|
public static long[] append(final long[] array, final long... objs) {
|
||||||
|
if (array == null || array.length == 0) return objs;
|
||||||
|
if (objs == null || objs.length == 0) return array;
|
||||||
|
final long[] news = new long[array.length + objs.length];
|
||||||
|
System.arraycopy(array, 0, news, 0, array.length);
|
||||||
|
System.arraycopy(objs, 0, news, array.length, objs.length);
|
||||||
|
return news;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将一个或多个新元素添加到数组结尾
|
* 将一个或多个新元素添加到数组结尾
|
||||||
*
|
*
|
||||||
|
|||||||
35
test/org/redkale/test/asm/AsmCreator.java
Normal file
35
test/org/redkale/test/asm/AsmCreator.java
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.redkale.test.asm;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import org.redkale.util.Utility;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public class AsmCreator {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Throwable {
|
||||||
|
boolean realasm = true; //从http://forge.ow2.org/projects/asm/ 下载最新asm的src放在 srcasmroot 目录下
|
||||||
|
File srcasmroot = new File("D:/JAVA/JDK源码/JDK9源码/java.base/jdk/internal/org/objectweb/asm");
|
||||||
|
if(realasm) srcasmroot = new File("D:/JAVA/JDK源码/org/objectweb/asm");
|
||||||
|
File destasmroot = new File("D:/Java-Projects/RedkaleProject/src/org/redkale/asm");
|
||||||
|
String line = null;
|
||||||
|
LineNumberReader txtin = new LineNumberReader(new FileReader(new File(destasmroot, "asm.txt")));
|
||||||
|
while ((line = txtin.readLine()) != null) {
|
||||||
|
line = line.trim();
|
||||||
|
if (!line.endsWith(".java")) continue;
|
||||||
|
File srcfile = new File(srcasmroot, line);
|
||||||
|
File destfile = new File(destasmroot, line);
|
||||||
|
String content = Utility.readThenClose(new FileInputStream(srcfile));
|
||||||
|
FileOutputStream out = new FileOutputStream(destfile);
|
||||||
|
out.write(content.replace("jdk.internal.org.objectweb", "org.redkale").replace("org.objectweb", "org.redkale").getBytes());
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import org.redkale.convert.bson.BsonConvert;
|
|||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import org.redkale.convert.json.*;
|
import org.redkale.convert.json.*;
|
||||||
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -31,6 +32,7 @@ public class BsonTestMain {
|
|||||||
main3(args);
|
main3(args);
|
||||||
main4(args);
|
main4(args);
|
||||||
main5(args);
|
main5(args);
|
||||||
|
main6(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main2(String[] args) throws Exception {
|
public static void main2(String[] args) throws Exception {
|
||||||
@@ -98,4 +100,20 @@ public class BsonTestMain {
|
|||||||
Object mapobj = convert.convertFrom(Object.class, bs);
|
Object mapobj = convert.convertFrom(Object.class, bs);
|
||||||
System.out.println(mapobj);
|
System.out.println(mapobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void main6(String[] args) throws Exception {
|
||||||
|
final BsonConvert convert = BsonFactory.root().getConvert();
|
||||||
|
|
||||||
|
Optional<String> val = Optional.ofNullable("haha");
|
||||||
|
byte[] bs = convert.convertTo(val);
|
||||||
|
Object obj = convert.convertFrom(Optional.class, bs);
|
||||||
|
System.out.println(obj);
|
||||||
|
bs = convert.convertTo(Object.class, val);
|
||||||
|
obj = convert.convertFrom(Object.class, bs);
|
||||||
|
System.out.println(obj);
|
||||||
|
bs = convert.convertTo(new TypeToken<Optional<String>>(){}.getType(), val);
|
||||||
|
obj = convert.convertFrom(new TypeToken<Optional<String>>(){}.getType(), bs);
|
||||||
|
System.out.println(obj);
|
||||||
|
System.out.println(JsonConvert.root().convertTo(val));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,11 @@ public class HelloService implements Service {
|
|||||||
if (source != null) source.update(entity);
|
if (source != null) source.update(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//修改记录
|
||||||
|
public void update2Hello(@RestAddress String clientAddr, @RestUploadFile byte[] fs) { //通过 /pipes/hello/update2?bean={...} 修改对象
|
||||||
|
System.out.println("修改记录2-" + nodeid + ": clientAddr = " + clientAddr + ", fs =" + fs);
|
||||||
|
}
|
||||||
|
|
||||||
//修改记录
|
//修改记录
|
||||||
@RestMapping(name = "partupdate")
|
@RestMapping(name = "partupdate")
|
||||||
public void updateHello(HelloEntity entity, @RestParam(name = "cols") String[] columns) { //通过 /pipes/hello/partupdate?bean={...}&cols=... 修改对象
|
public void updateHello(HelloEntity entity, @RestParam(name = "cols") String[] columns) { //通过 /pipes/hello/partupdate?bean={...}&cols=... 修改对象
|
||||||
@@ -74,6 +79,7 @@ public class HelloService implements Service {
|
|||||||
|
|
||||||
//查询List列表
|
//查询List列表
|
||||||
@RestMapping(name = "list")
|
@RestMapping(name = "list")
|
||||||
|
@RestConvert(type = HelloEntity.class, ignoreColumns = {"createtime"})
|
||||||
public List<HelloEntity> queryHello(HelloBean bean) { //通过 /pipes/hello/list?bean={...} 查询List列表
|
public List<HelloEntity> queryHello(HelloBean bean) { //通过 /pipes/hello/list?bean={...} 查询List列表
|
||||||
return source.queryList(HelloEntity.class, bean);
|
return source.queryList(HelloEntity.class, bean);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ public class SimpleRestServlet extends HttpServlet {
|
|||||||
protected static final RetResult RET_AUTHILLEGAL = RetCodes.retResult(RetCodes.RET_USER_AUTH_ILLEGAL);
|
protected static final RetResult RET_AUTHILLEGAL = RetCodes.retResult(RetCodes.RET_USER_AUTH_ILLEGAL);
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private UserService userService;
|
private UserService userService = new UserService();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preExecute(HttpRequest request, HttpResponse response) throws IOException {
|
public void preExecute(HttpRequest request, HttpResponse response) throws IOException {
|
||||||
final String sessionid = request.getSessionid(false);
|
final String sessionid = request.getSessionid(true);
|
||||||
if (sessionid != null) request.setCurrentUser(userService.current(sessionid));
|
if (sessionid != null) request.setCurrentUser(userService.current(sessionid));
|
||||||
response.nextEvent();
|
response.nextEvent();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,6 @@ public class UserService implements Service {
|
|||||||
|
|
||||||
//根据登录态获取当前用户信息
|
//根据登录态获取当前用户信息
|
||||||
public UserInfo current(String sessionid) {
|
public UserInfo current(String sessionid) {
|
||||||
return null;
|
return new UserInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ public class _DynHelloRestServlet1 extends SimpleRestServlet {
|
|||||||
//headers.put(Rest.REST_HEADER_RESOURCE_NAME, "my-res");
|
//headers.put(Rest.REST_HEADER_RESOURCE_NAME, "my-res");
|
||||||
String url = "http://127.0.0.1:" + port + "/pipes/hello/update?entity={}&bean2={}";
|
String url = "http://127.0.0.1:" + port + "/pipes/hello/update?entity={}&bean2={}";
|
||||||
System.out.println(Utility.postHttpContent(url, headers, null));
|
System.out.println(Utility.postHttpContent(url, headers, null));
|
||||||
|
url = "http://127.0.0.1:" + port + "/pipes/hello/update2?entity={}&bean2={}";
|
||||||
|
System.out.println(Utility.postHttpContent(url, headers, null));
|
||||||
|
|
||||||
url = "http://127.0.0.1:" + port + "/pipes/hello/asyncfind/1234";
|
url = "http://127.0.0.1:" + port + "/pipes/hello/asyncfind/1234";
|
||||||
System.out.println("异步查找: " + Utility.postHttpContent(url, headers, null));
|
System.out.println("异步查找: " + Utility.postHttpContent(url, headers, null));
|
||||||
|
|||||||
Reference in New Issue
Block a user