135 Commits
1.1.0 ... 1.2.0

Author SHA1 Message Date
Redkale
54b7863be6 2016-10-10 16:40:41 +08:00
Redkale
26453fe4c5 2016-10-10 16:40:00 +08:00
Redkale
036b248092 2016-10-10 15:48:57 +08:00
Redkale
8ca79face5 2016-10-10 15:45:13 +08:00
Redkale
6fd3250fba 2016-10-10 15:33:18 +08:00
Redkale
93a213448a 2016-10-10 15:23:58 +08:00
Redkale
e12cf185d9 2016-10-10 15:17:32 +08:00
Redkale
ca6c90eacd 2016-10-10 14:35:04 +08:00
Redkale
8901dd9a07 2016-10-10 14:20:49 +08:00
Redkale
93fef97c56 2016-10-10 13:52:20 +08:00
Redkale
ddef9018e2 2016-10-10 09:50:56 +08:00
Redkale
fb51997c6b 2016-10-08 18:42:01 +08:00
Redkale
65da7118fc 2016-10-08 17:35:37 +08:00
Redkale
fc2dfa1a8a 2016-10-08 12:30:45 +08:00
Redkale
68db4e37e2 2016-09-28 21:36:15 +08:00
Redkale
28c9b2606a 2016-09-26 20:51:01 +08:00
Redkale
d47b63e47b 2016-09-26 20:21:14 +08:00
Redkale
7f86972fa1 2016-09-26 19:48:38 +08:00
Redkale
92eefc872a 2016-09-26 14:01:20 +08:00
Redkale
c43e516d14 2016-09-26 13:51:14 +08:00
Redkale
8884fabf90 2016-09-26 13:41:35 +08:00
Redkale
1720470424 2016-09-26 13:19:09 +08:00
Redkale
1da2e95f46 2016-09-26 10:22:46 +08:00
Redkale
940af0b251 2016-09-26 10:18:21 +08:00
Redkale
43102b9d35 2016-09-26 09:41:40 +08:00
Redkale
fa601c69e7 2016-09-26 09:23:35 +08:00
Redkale
b365b18be0 2016-09-26 09:05:44 +08:00
Redkale
bc8a52eef8 2016-09-25 14:11:42 +08:00
Redkale
afa45498d4 2016-09-24 18:22:01 +08:00
Redkale
6f056bbcb6 2016-09-23 10:03:49 +08:00
Redkale
4fb218fd18 2016-09-18 19:51:34 +08:00
Redkale
1e7575c7b7 2016-09-18 19:50:17 +08:00
Redkale
02fd74f6de 2016-09-18 10:53:16 +08:00
Redkale
77732347d0 2016-09-18 10:41:54 +08:00
Redkale
53eaad17ea 2016-09-18 09:01:14 +08:00
Redkale
4cdc1f82c5 2016-09-14 14:41:30 +08:00
Redkale
77c2f72b42 2016-09-14 14:39:15 +08:00
Redkale
469069d2ac 2016-09-14 14:04:39 +08:00
Redkale
d7542a0c0a 2016-09-14 14:03:05 +08:00
Redkale
15d36735da 2016-09-14 13:11:08 +08:00
Redkale
d3163a6e0d 2016-09-14 12:08:10 +08:00
Redkale
23fd664eef 2016-09-14 11:32:05 +08:00
Redkale
f21cb2c233 2016-09-14 11:22:25 +08:00
Redkale
0a2a9f0e80 2016-09-14 10:48:16 +08:00
Redkale
9b74f46b22 2016-09-14 10:44:54 +08:00
Redkale
59ca4afd8b 2016-09-14 10:41:15 +08:00
Redkale
bc1c749152 2016-09-14 10:39:56 +08:00
Redkale
d35987612d 2016-09-14 10:24:24 +08:00
Redkale
04b5b361ad 2016-09-14 10:08:16 +08:00
Redkale
a81c9f7d21 2016-09-14 09:36:33 +08:00
Redkale
2c75c04b7e 2016-09-13 17:38:46 +08:00
Redkale
9bf5044654 2016-09-13 17:19:18 +08:00
Redkale
e99fd3c049 2016-09-13 16:09:50 +08:00
Redkale
4e9b3f45fc 2016-09-13 16:07:26 +08:00
Redkale
95f4cd0634 2016-09-12 21:08:10 +08:00
Redkale
a43f9a0121 2016-09-09 15:21:57 +08:00
Redkale
6f6952ad2c 2016-09-09 11:59:10 +08:00
Redkale
21cfbebe26 2016-09-08 09:21:28 +08:00
Redkale
f16beca680 2016-09-08 09:18:46 +08:00
Redkale
1341e81361 2016-09-08 09:18:18 +08:00
Redkale
f08a29b15a 2016-09-07 22:22:09 +08:00
Redkale
fea5123915 2016-09-07 21:32:41 +08:00
Redkale
cd45cafec5 2016-09-07 19:16:30 +08:00
Redkale
bed86d44a1 2016-09-07 18:33:32 +08:00
Redkale
bd3ae4bb41 2016-09-07 18:01:37 +08:00
Redkale
589d34d8a4 2016-09-07 17:29:58 +08:00
Redkale
a455795703 2016-09-07 16:32:11 +08:00
Redkale
fbb9cdefe1 2016-09-07 16:19:14 +08:00
Redkale
d202b2fbad 2016-09-07 13:53:33 +08:00
Redkale
9d82ca84a4 2016-09-06 14:34:55 +08:00
Redkale
1f0e0accb1 2016-09-06 13:45:56 +08:00
Redkale
fa8e40f6c0 2016-09-06 12:21:30 +08:00
Redkale
1a22cd0fe1 2016-09-06 12:00:49 +08:00
Redkale
8422173411 2016-09-06 09:46:37 +08:00
Redkale
c63248ba7f 2016-09-06 08:40:39 +08:00
Redkale
de4dda7c73 2016-09-06 08:37:00 +08:00
Redkale
e546ff74a5 2016-09-06 08:29:44 +08:00
Redkale
506f930320 2016-09-06 08:23:10 +08:00
Redkale
09beaedee8 2016-09-05 21:26:32 +08:00
Redkale
40845f5f60 2016-09-05 18:29:50 +08:00
Redkale
f3f001d72d 2016-09-05 18:29:21 +08:00
Redkale
b49a4d2c83 2016-09-05 15:07:57 +08:00
Redkale
90884f4621 2016-09-04 08:19:13 +08:00
Redkale
c2fd7be5e2 2016-09-02 19:41:26 +08:00
Redkale
b1773107a1 2016-09-02 19:27:05 +08:00
Redkale
f6aa646ea4 2016-09-02 18:07:04 +08:00
Redkale
72887106ea 2016-09-02 17:56:14 +08:00
Redkale
aa6126ddec 2016-09-02 10:16:14 +08:00
Redkale
a98a35b4af 2016-09-01 10:00:28 +08:00
Redkale
07253b1f17 2016-08-31 19:10:20 +08:00
Redkale
48a4c6d53c 2016-08-31 19:06:57 +08:00
Redkale
d78c08878c 2016-08-31 13:42:32 +08:00
Redkale
d40ea81fc3 2016-08-31 09:21:12 +08:00
Redkale
78ac88b57c 2016-08-31 09:20:49 +08:00
Redkale
3595f8b6bc 2016-08-30 15:06:56 +08:00
Redkale
1421b83e49 2016-08-30 14:22:11 +08:00
Redkale
90361edba1 2016-08-30 13:01:03 +08:00
Redkale
3d3347b64f 2016-08-30 08:59:06 +08:00
Redkale
f8a439e21f 2016-08-30 02:16:33 +08:00
Redkale
9d76e693fb 2016-08-30 02:14:59 +08:00
Redkale
a206ecd76b 2016-08-30 02:13:56 +08:00
Redkale
81f386dcdb 2016-08-29 20:27:54 +08:00
Redkale
e8e6459679 2016-08-29 17:21:02 +08:00
Redkale
9f5ab4b068 2016-08-29 14:48:29 +08:00
Redkale
1ea816a60e 2016-08-29 13:50:05 +08:00
Redkale
2c5876ba3e 2016-08-27 15:29:40 +08:00
Redkale
cffe181344 删除Source异步版接口 2016-08-27 15:25:03 +08:00
Redkale
4647545ff5 2016-08-27 15:07:34 +08:00
Redkale
bfe78a805e 2016-08-27 14:52:34 +08:00
Redkale
c480b2b18e 2016-08-27 14:30:25 +08:00
Redkale
7e9885de2e 2016-08-27 14:25:57 +08:00
Redkale
db32656c8a 2016-08-27 13:50:24 +08:00
Redkale
b981307768 2016-08-26 21:38:24 +08:00
Redkale
b0e0a341ec 2016-08-26 14:12:28 +08:00
Redkale
40ef40b813 2016-08-26 09:51:36 +08:00
Redkale
dfacd49a70 2016-08-26 08:09:03 +08:00
Redkale
470a82b6e6 2016-08-26 07:16:47 +08:00
Redkale
d5a752dea0 2016-08-26 06:51:06 +08:00
Redkale
554932201b 2016-08-26 06:37:47 +08:00
Redkale
54462e8c26 2016-08-25 14:21:09 +08:00
Redkale
d9807148db 2016-08-25 13:50:13 +08:00
Redkale
66a5fc2447 2016-08-25 12:32:41 +08:00
Redkale
4f9c8ce145 2016-08-25 09:13:20 +08:00
Redkale
884cc930c8 2016-08-25 09:00:20 +08:00
Redkale
cd4b18ad45 2016-08-25 08:52:51 +08:00
Redkale
707fc783b5 2016-08-25 08:52:18 +08:00
Redkale
3ca6ad6e12 2016-08-25 07:22:48 +08:00
Redkale
4972f5804e 2016-08-24 22:34:31 +08:00
Redkale
aec69d2973 2016-08-24 22:27:27 +08:00
Redkale
3f2a7f684f 2016-08-24 22:00:48 +08:00
Redkale
ce9f517244 2016-08-24 21:53:07 +08:00
Redkale
192e52f18f 2016-08-24 18:25:49 +08:00
Redkale
cdbe53d3d9 2016-08-24 17:50:30 +08:00
Redkale
58f4f28e14 2016-08-24 17:39:53 +08:00
Redkale
bc19d75422 2016-08-24 17:34:17 +08:00
98 changed files with 4692 additions and 2034 deletions

7
bin/apidoc.bat Normal file
View File

@@ -0,0 +1,7 @@
@ECHO OFF
SET APP_HOME=%~dp0
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
java -DCMD=APIDOC -DAPP_HOME=%APP_HOME% -classpath %APP_HOME%\lib\* org.redkale.boot.Application

18
bin/apidoc.sh Normal file
View File

@@ -0,0 +1,18 @@
#!/bin/sh
export LC_ALL="zh_CN.UTF-8"
APP_HOME=`dirname "$0"`
if [ ! -a "$APP_HOME"/conf/application.xml ]; then
APP_HOME="$APP_HOME"/..
fi
lib='.'
for jar in `ls $APP_HOME/lib/*.jar`
do
lib=$lib:$jar
done
export CLASSPATH=$CLASSPATH:$lib
echo "$APP_HOME"
java -DCMD=APIDOC -DAPP_HOME="$APP_HOME" org.redkale.boot.Application

View File

@@ -4,4 +4,4 @@ SET APP_HOME=%~dp0
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0.. IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
java -DSHUTDOWN=true -DAPP_HOME=%APP_HOME% -classpath %APP_HOME%\lib\* org.redkale.boot.Application java -DCMD=SHUTDOWN -DAPP_HOME=%APP_HOME% -classpath %APP_HOME%\lib\* org.redkale.boot.Application

View File

@@ -15,4 +15,4 @@ do
done done
export CLASSPATH=$CLASSPATH:$lib export CLASSPATH=$CLASSPATH:$lib
echo "$APP_HOME" echo "$APP_HOME"
java -DSHUTDOWN=true -DAPP_HOME="$APP_HOME" org.redkale.boot.Application java -DCMD=SHUTDOWN -DAPP_HOME="$APP_HOME" org.redkale.boot.Application

View File

@@ -2,6 +2,7 @@
<!-- <!--
文件说明: 文件说明:
${APP_HOME} 指当前程序的根目录APP_HOME ${APP_HOME} 指当前程序的根目录APP_HOME
没注明唯一的节点可多个存在
required 被声明required的属性值不能为空 required 被声明required的属性值不能为空
group group
@@ -18,27 +19,31 @@
serviceid1_name1 serviceid1_name2 serviceid2_name1 serviceid2_name2 serviceid1_name1 serviceid1_name2 serviceid2_name1 serviceid2_name2
--> -->
<!-- <!--
address: 本地的IP地址 默认值为默认网卡的ip当不使用默认值需要指定值如127.0.0.1 address: 本地局域网的IP地址 默认值为默认网卡的ip当不使用默认值需要指定值如192.168.1.22
port: required 程序的管理Server的端口用于关闭或者与监管系统进行数据交互 port: required 程序的管理Server的端口用于关闭或者与监管系统进行数据交互
host: 程序的管理Server的地址; 默认为127.0.0.1。
lib: 加上额外的lib路径,多个路径用分号;隔开; 默认为空。 例如: ${APP_HOME}/lib/a.jar;${APP_HOME}/lib2/b.jar; lib: 加上额外的lib路径,多个路径用分号;隔开; 默认为空。 例如: ${APP_HOME}/lib/a.jar;${APP_HOME}/lib2/b.jar;
--> -->
<application port="6560" lib=""> <application port="6560" lib="">
<!-- 所有服务所需的资源 --> <!--
【节点全局唯一】
所有服务所需的资源
-->
<resources> <resources>
<!-- <!--
【节点全局唯一】
transport节点只能有一个用于配置所有Transport的池参数没配置该节点将自动创建一个。 transport节点只能有一个用于配置所有Transport的池参数没配置该节点将自动创建一个。
threads 线程总数, 默认: <group>节点数*CPU核数*8 threads 线程总数, 默认: <group>节点数*CPU核数*8
bufferCapacity: ByteBuffer的初始化大小 默认: 8K; bufferCapacity: ByteBuffer的初始化大小 默认: 8K;
bufferPoolSize ByteBuffer池的大小默认: <group>节点数*CPU核数*8 bufferPoolSize ByteBuffer池的大小默认: <group>节点数*CPU核数*8
--> -->
<transport capacity="8192" bufferPoolSize="32" threads="32"/> <transport bufferCapacity="8K" bufferPoolSize="32" threads="32"/>
<!-- <!--
一个组包含多个NODE 同一Service服务可以由多个进程提供这些进程称为一个GROUP且同一GROUP内的进程必须在同一机房或局域网内 一个组包含多个NODE 同一Service服务可以由多个进程提供这些进程称为一个GROUP且同一GROUP内的进程必须在同一机房或局域网内
一个group节点对应一个 Transport 对象。 一个group节点对应一个 Transport 对象。
name: 服务组ID长度不能超过11个字节. 默认为空字符串。 注意: name不能包含$符号。 name: 服务组ID长度不能超过11个字节. 默认为空字符串。 注意: name不能包含$符号。
protocol值只能是UDP TCP 默认TCP protocol值只能是UDP TCP 默认TCP
kind: 与SNCP服务连接时的数据传输类型可选值有:rest(不区分大小写);值为空或空字符串表示按SNCP协议传输; 为rest表示按REST传输。默认值为空
注意: 一个node只能所属一个group。只要存在protocol=SNCP的Server节点信息 就必须有group节点信息。 注意: 一个node只能所属一个group。只要存在protocol=SNCP的Server节点信息 就必须有group节点信息。
--> -->
<group name="" protocol="TCP"> <group name="" protocol="TCP">
@@ -53,6 +58,7 @@
<node addr="127.0.0.1" port="7070"/> <node addr="127.0.0.1" port="7070"/>
</group> </group>
<!-- <!--
【节点全局唯一】
全局的参数配置, 可以通过@Resource(name="property.xxxxxx") 进行注入, 被注解的字段类型只能是String、primitive class 全局的参数配置, 可以通过@Resource(name="property.xxxxxx") 进行注入, 被注解的字段类型只能是String、primitive class
如果name是system.property.开头的值将会在进程启动时进行System.setProperty("yyyy", "YYYYYY")操作。 如果name是system.property.开头的值将会在进程启动时进行System.setProperty("yyyy", "YYYYYY")操作。
如果name是mimetype.property.开头的值将会在进程启动时进行MimeType.add("yyyy", "YYYYYY")操作。 如果name是mimetype.property.开头的值将会在进程启动时进行MimeType.add("yyyy", "YYYYYY")操作。
@@ -78,7 +84,8 @@
host: 服务所占address 默认: 0.0.0.0 host: 服务所占address 默认: 0.0.0.0
port: required 服务所占端口 port: required 服务所占端口
root: 如果是web类型服务则包含页面 默认:{APP_HOME}/root root: 如果是web类型服务则包含页面 默认:{APP_HOME}/root
lib: server额外的class目录 默认为空 lib: server额外的class目录 默认为空
excludelibs: 排除lib.path与excludes中的正则表达式匹配的路径, 多个正则表达式用分号;隔开
charset: 文本编码, 默认: UTF-8 charset: 文本编码, 默认: UTF-8
backlog: 默认10K backlog: 默认10K
threads 线程总数, 默认: CPU核数*16 threads 线程总数, 默认: CPU核数*16
@@ -121,7 +128,25 @@
</service> </service>
</services> </services>
<!--
REST的核心配置项
当Server为HTTP协议时, rest节点才有效。存在[rest]节点则Server启动时会加载REST服务, 节点可以多个
base: REST服务的BaseServlet必须是 org.redkale.net.http.RestHttpServlet 的子类,该属性值默认值为 org.redkale.net.http.DefaultRestServlet。
autoload默认值"true" 默认值. 加载当前server所能使用的Servce对象;
mustsign默认值"true" 是否只加载标记为RestService的Service类默认只加载标记RestService且ignore=false的Service
includes当autoload="true" 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
excludes当autoload="true" 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
-->
<rest base="org.redkale.net.http.DefaultRestServlet" mustsign="false" autoload="true" includes="" excludes="">
<!--
value: Service类名列出的表示必须被加载的Service对象
ignore: 是否忽略设置为true则不会加载该Service对象默认值为false
-->
<service value="com.xxx.XXXXService"/>
</rest>
<!-- <!--
【节点在<server>中唯一】
当Server为HTTP协议时, request节点才有效。 当Server为HTTP协议时, request节点才有效。
remoteaddr 节点: 替换请求方节点的IP地址 通常请求方是由nginx等web静态服务器转发过的则需要配置该节点。 remoteaddr 节点: 替换请求方节点的IP地址 通常请求方是由nginx等web静态服务器转发过的则需要配置该节点。
且value值只能是以request.headers.开头表示从request.headers中获取对应的header值。 且value值只能是以request.headers.开头表示从request.headers中获取对应的header值。
@@ -132,6 +157,7 @@
</request> </request>
<!-- <!--
【节点在<server>中唯一】
当Server为HTTP协议时, response节点才有效。 当Server为HTTP协议时, response节点才有效。
defcookie 节点: 当response里输出的cookie没有指定domain 和path时使用该节点的默认值。 defcookie 节点: 当response里输出的cookie没有指定domain 和path时使用该节点的默认值。
如果addheader、setheader 的value值以request.parameters.开头则表示从request.parameters中获取对应的parameter值 如果addheader、setheader 的value值以request.parameters.开头则表示从request.parameters中获取对应的parameter值
@@ -144,6 +170,31 @@
<setheader name="Access-Control-Allow-Credentials" value="true"/> <setheader name="Access-Control-Allow-Credentials" value="true"/>
</response> </response>
<!--
【节点在<server>中唯一】
当Server为HTTP协议时ResourceServlet才有效. 默认存在一个有默认属性的resource-servlet节点
webroot: web资源的根目录, 默认取server节点中的root值
servlet: 静态资源HttpServlet的实现默认使用HttpResourceServlet
index : 启始页默认值index.html
-->
<resource-servlet webroot="root" index="index.html">
<!--
【节点在<resource-servlet>中唯一】
资源缓存的配置, 默认存在一个含默认属性的caches节点
limit: 资源缓存最大容量, 默认: 0, 为0表示不缓存 单位可以是B、K、M、G不区分大小写
lengthmax: 可缓存的文件大小上限, 默认: 1M超过1M的文件不会被缓存
watch: 是否监控缓存文件的变化, 默认为false不监控
-->
<cache limit="0M" lengthmax="1M" watch="false"/>
<!--
支持类似nginx中的rewrite 目前只支持静态资源对静态资源的跳转。
type: 匹配的类型, 目前只支持location(匹配requestURI), 默认: location
match: 匹配的正则表达式
forward: 需跳转后的资源链接
例如下面例子是将/xxx-yyy.html的页面全部跳转到/xxx.html
-->
<rewrite type="location" match="^/([^-]+)-[^-\.]+\.html(.*)" forward="/$1.html"/>
</resource-servlet>
<!-- <!--
加载所有的Servlet服务; 加载所有的Servlet服务;
path: servlet的ContextPath前缀 默认为空 path: servlet的ContextPath前缀 默认为空
@@ -154,28 +205,6 @@
excludes 当autoload="true" 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开 excludes 当autoload="true" 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
--> -->
<servlets path="/pipes" autoload="true" includes="" excludes=""> <servlets path="/pipes" autoload="true" includes="" excludes="">
<!--
当Server为HTTP协议时ResourceServlet才有效. 默认存在一个有默认属性的resource-servlet节点
webroot: web资源的根目录, 默认取server节点中的root值
index : 启始页默认值index.html
-->
<resource-servlet webroot="root" index="index.html">
<!--
资源缓存的配置, 默认存在一个含默认属性的caches节点
limit: 资源缓存最大容量, 默认: 0, 为0表示不缓存 单位可以是B、K、M、G不区分大小写
lengthmax: 可缓存的文件大小上限, 默认: 1M超过1M的文件不会被缓存
watch: 是否监控缓存文件的变化, 默认不监控
-->
<cache limit="0M" lengthmax="1M" watch="false"/>
<!--
支持类似nginx中的rewrite 目前只支持静态资源对静态资源的跳转。
type: 匹配的类型, 目前只支持location(匹配requestURI), 默认: location
match: 匹配的正则表达式
forward: 需跳转后的资源链接
例如下面例子是将/xxx-yyy.html的页面全部跳转到/xxx.html
-->
<rewrite type="location" match="^/([^-]+)-[^-\.]+\.html(.*)" forward="/$1.html"/>
</resource-servlet>
<!-- 显著加载指定的Servlet --> <!-- 显著加载指定的Servlet -->
<servlet value="com.xxx.XXX1Servlet" /> <servlet value="com.xxx.XXX1Servlet" />
<servlet value="com.xxx.XXX2Servlet" /> <servlet value="com.xxx.XXX2Servlet" />

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 其配置算是标准的JPA配置文件的缩略版 -->
<persistence>
<!-- 系统基本库 -->
<persistence-unit name="demouser">
<!-- 为NONE表示不启动缓存@Cacheable 失效; 非NONE值(通常用ALL)表示开启缓存。 -->
<shared-cache-mode>NONE</shared-cache-mode>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/dbuser?characterEncoding=utf8"/>
<!--
javax.persistence.jdbc.driver在JPA的值是JDBC驱动Redkale有所不同值应该是javax.sql.DataSource的子类。
为了兼容用户习惯Redkale内置常见JDBC驱动到javax.sql.DataSource的映射关系
com.mysql.jdbc.Driver —————— com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
org.mariadb.jdbc.Driver —————— org.mariadb.jdbc.MySQLDataSource
oracle.jdbc.driver.OracleDriver —————— oracle.jdbc.pool.OracleConnectionPoolDataSource
com.microsoft.sqlserver.jdbc.SQLServerDriver —————— com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource
因此 com.mysql.jdbc.Driver 会被自动转换成 com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
-->
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="123456"/>
<!-- 最大连接数默认值CPU数*16 -->
<property name="javax.persistence.connections.limit" value="32"/>
<!-- 包含的SQL模板相当于反向LIKE不同的JDBC驱动的SQL语句不一样Redkale内置了MySQL、Oracle、Sqlserver的语句 -->
<property name="javax.persistence.contain.sqltemplate" value="LOCATE(${keystr}, ${column}) > 0"/>
<property name="javax.persistence.notcontain.sqltemplate" value="LOCATE(${keystr}, ${column}) = 0"/>
<!-- 复制表结构的SQL模板Redkale内置了MySQL的语句 -->
<property name="javax.persistence.tablenotexist.sqlstates" value="42000;42S02"/>
<property name="javax.persistence.tablecopy.sqltemplate" value="CREATE TABLE ${newtable} LIKE ${oldtable}"/>
</properties>
</persistence-unit>
<!-- IM消息库 -->
<persistence-unit name="demoim">
<shared-cache-mode>NONE</shared-cache-mode>
<properties>
<!-- jdbc:mysql://127.0.0.1:3306/dbim?autoReconnect=true&amp;autoReconnectForPools=true&amp;characterEncoding=utf8 -->
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/dbim?characterEncoding=utf8"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="123456"/>
</properties>
</persistence-unit>
</persistence>

View File

@@ -0,0 +1,146 @@
/*
* 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.boot;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import org.redkale.convert.json.JsonConvert;
import org.redkale.net.http.*;
import org.redkale.util.*;
/**
* 继承 HttpBaseServlet 是为了获取 WebAction 信息
*
* @author zhangjx
*/
public class ApiDocs extends HttpBaseServlet {
private final Application app;
public ApiDocs(Application app) {
this.app = app;
}
public void run() throws Exception {
List<Map> serverList = new ArrayList<>();
Map<String, Map<String, Map<String, String>>> typesmap = new LinkedHashMap<>();
for (NodeServer node : app.servers) {
if (!(node instanceof NodeHttpServer)) continue;
final Map<String, Object> map = new LinkedHashMap<>();
serverList.add(map);
HttpServer server = node.getServer();
map.put("address", server.getSocketAddress());
List<Map<String, Object>> servletsList = new ArrayList<>();
map.put("servlets", servletsList);
for (HttpServlet servlet : server.getPrepareServlet().getServlets()) {
if (!(servlet instanceof HttpServlet)) continue;
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
if (ws == null) {
System.err.println(servlet + " not found @WebServlet");
continue;
}
final Map<String, Object> servletmap = new LinkedHashMap<>();
String prefix = _prefix(servlet);
String[] mappings = ws.value();
if (prefix != null && !prefix.isEmpty()) {
for (int i = 0; i < mappings.length; i++) {
mappings[i] = prefix + mappings[i];
}
}
servletmap.put("mappings", mappings);
servletmap.put("moduleid", ws.moduleid());
servletmap.put("name", ws.name());
servletmap.put("comment", ws.comment());
List<Map> actionsList = new ArrayList<>();
servletmap.put("actions", actionsList);
for (Method method : servlet.getClass().getMethods()) {
if (method.getParameterCount() != 2) continue;
WebAction action = method.getAnnotation(WebAction.class);
if (action == null) continue;
final Map<String, Object> actionmap = new LinkedHashMap<>();
actionmap.put("url", prefix + action.url());
actionmap.put("auth", method.getAnnotation(AuthIgnore.class) == null);
actionmap.put("actionid", action.actionid());
actionmap.put("comment", action.comment());
List<Map> paramsList = new ArrayList<>();
actionmap.put("params", paramsList);
for (WebParam param : method.getAnnotationsByType(WebParam.class)) {
final Map<String, Object> parammap = new LinkedHashMap<>();
final boolean isarray = param.type().isArray();
final Class ptype = isarray ? param.type().getComponentType() : param.type();
parammap.put("name", param.name());
parammap.put("radix", param.radix());
parammap.put("type", ptype.getName() + (isarray ? "[]" : ""));
parammap.put("src", param.src());
parammap.put("comment", param.comment());
paramsList.add(parammap);
if (ptype.isPrimitive() || ptype == String.class) continue;
if (typesmap.containsKey(ptype.getName())) continue;
final Map<String, Map<String, String>> typemap = new LinkedHashMap<>();
Class loop = ptype;
do {
if (loop == null || loop.isInterface()) break;
for (Field field : loop.getDeclaredFields()) {
if (Modifier.isFinal(field.getModifiers())) continue;
if (Modifier.isStatic(field.getModifiers())) continue;
Map<String, String> fieldmap = new LinkedHashMap<>();
fieldmap.put("type", field.getType().isArray() ? (field.getType().getComponentType().getName() + "[]") : field.getGenericType().getTypeName());
Comment comment = field.getAnnotation(Comment.class);
if (comment != null) fieldmap.put("comment", comment.value());
if (servlet.getClass().getAnnotation(Rest.RestDynamic.class) != null) {
if (field.getAnnotation(RestAddress.class) != null) continue;
}
typemap.put(field.getName(), fieldmap);
}
} while ((loop = loop.getSuperclass()) != Object.class);
typesmap.put(ptype.getName(), typemap);
}
actionmap.put("result", action.result());
actionsList.add(actionmap);
}
actionsList.sort((o1, o2) -> ((String) o1.get("url")).compareTo((String) o2.get("url")));
servletsList.add(servletmap);
}
servletsList.sort((o1, o2) -> {
String[] mappings1 = (String[]) o1.get("mappings");
String[] mappings2 = (String[]) o2.get("mappings");
return mappings1.length > 0 ? (mappings2.length > 0 ? mappings1[0].compareTo(mappings2[0]) : 1) : -1;
});
}
Map<String, Object> resultmap = new LinkedHashMap<>();
resultmap.put("servers", serverList);
resultmap.put("types", typesmap);
final String json = JsonConvert.root().convertTo(resultmap);
final FileOutputStream out = new FileOutputStream(new File(app.getHome(), "apidoc.json"));
out.write(json.getBytes("UTF-8"));
out.close();
File doctemplate = new File(app.getHome(), "conf/apidoc-template.html");
InputStream in = null;
if (doctemplate.isFile() && doctemplate.canRead()) {
in = new FileInputStream(doctemplate);
}
if (in == null) in = ApiDocs.class.getResourceAsStream("apidoc-template.html");
String content = Utility.read(in).replace("${content}", json);
in.close();
FileOutputStream outhtml = new FileOutputStream(new File(app.getHome(), "apidoc.html"));
outhtml.write(content.getBytes("UTF-8"));
outhtml.close();
}
@Override
public boolean authenticate(int module, int actionid, HttpRequest request, HttpResponse response) throws IOException {
return true;
}
}

View File

@@ -65,9 +65,7 @@ public final class Application {
final Map<InetSocketAddress, String> globalNodes = new HashMap<>(); final Map<InetSocketAddress, String> globalNodes = new HashMap<>();
final Map<String, Set<InetSocketAddress>> globalGroups = new HashMap<>(); final Map<String, GroupInfo> globalGroups = new HashMap<>();
final Map<String, String> globalGroupProtocols = new HashMap<>();
final InetAddress localAddress; final InetAddress localAddress;
@@ -77,8 +75,6 @@ public final class Application {
final List<NodeServer> servers = new CopyOnWriteArrayList<>(); final List<NodeServer> servers = new CopyOnWriteArrayList<>();
CountDownLatch servicecdl; //会出现两次赋值
final ObjectPool<ByteBuffer> transportBufferPool; final ObjectPool<ByteBuffer> transportBufferPool;
final ExecutorService transportExecutor; final ExecutorService transportExecutor;
@@ -87,6 +83,8 @@ public final class Application {
final ResourceFactory resourceFactory = ResourceFactory.root(); final ResourceFactory resourceFactory = ResourceFactory.root();
CountDownLatch servicecdl; //会出现两次赋值
//-------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------
private final boolean singletonrun; private final boolean singletonrun;
@@ -331,15 +329,14 @@ public final class Application {
if (!"TCP".equalsIgnoreCase(protocol) && !"UDP".equalsIgnoreCase(protocol)) { if (!"TCP".equalsIgnoreCase(protocol) && !"UDP".equalsIgnoreCase(protocol)) {
throw new RuntimeException("Not supported Transport Protocol " + conf.getValue("protocol")); throw new RuntimeException("Not supported Transport Protocol " + conf.getValue("protocol"));
} }
Set<InetSocketAddress> addrs = globalGroups.get(group); GroupInfo ginfo = globalGroups.get(group);
if (addrs == null) { if (ginfo == null) {
addrs = new LinkedHashSet<>(); ginfo = new GroupInfo(group, protocol, conf.getValue("kind", ""), new LinkedHashSet<>());
globalGroupProtocols.put(group, protocol); globalGroups.put(group, ginfo);
globalGroups.put(group, addrs);
} }
for (AnyValue node : conf.getAnyValues("node")) { for (AnyValue node : conf.getAnyValues("node")) {
final InetSocketAddress addr = new InetSocketAddress(node.getValue("addr"), node.getIntValue("port")); final InetSocketAddress addr = new InetSocketAddress(node.getValue("addr"), node.getIntValue("port"));
addrs.add(addr); ginfo.addrs.add(addr);
String oldgroup = globalNodes.get(addr); String oldgroup = globalNodes.get(addr);
if (oldgroup != null) throw new RuntimeException(addr + " had one more group " + (globalNodes.get(addr))); if (oldgroup != null) throw new RuntimeException(addr + " had one more group " + (globalNodes.get(addr)));
globalNodes.put(addr, group); globalNodes.put(addr, group);
@@ -362,7 +359,7 @@ public final class Application {
final DatagramChannel channel = DatagramChannel.open(); final DatagramChannel channel = DatagramChannel.open();
channel.configureBlocking(true); channel.configureBlocking(true);
channel.socket().setSoTimeout(3000); channel.socket().setSoTimeout(3000);
channel.bind(new InetSocketAddress(config.getValue("host", "127.0.0.1"), config.getIntValue("port"))); channel.bind(new InetSocketAddress("127.0.0.1", config.getIntValue("port")));
boolean loop = true; boolean loop = true;
ByteBuffer buffer = ByteBuffer.allocateDirect(1024); ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
while (loop) { while (loop) {
@@ -391,6 +388,19 @@ public final class Application {
buffer.flip(); buffer.flip();
channel.send(buffer, address); channel.send(buffer, address);
} }
} else if ("APIDOC".equalsIgnoreCase(new String(bytes))) {
try {
new ApiDocs(application).run();
buffer.clear();
buffer.put("APIDOC OK".getBytes());
buffer.flip();
channel.send(buffer, address);
} catch (Exception ex) {
buffer.clear();
buffer.put("APIDOC FAIL".getBytes());
buffer.flip();
channel.send(buffer, address);
}
} }
} }
} catch (Exception e) { } catch (Exception e) {
@@ -401,12 +411,12 @@ public final class Application {
}.start(); }.start();
} }
private void sendShutDown() throws Exception { private void sendCommand(String command) throws Exception {
final DatagramChannel channel = DatagramChannel.open(); final DatagramChannel channel = DatagramChannel.open();
channel.configureBlocking(true); channel.configureBlocking(true);
channel.connect(new InetSocketAddress(config.getValue("host", "127.0.0.1"), config.getIntValue("port"))); channel.connect(new InetSocketAddress("127.0.0.1", config.getIntValue("port")));
ByteBuffer buffer = ByteBuffer.allocate(128); ByteBuffer buffer = ByteBuffer.allocate(128);
buffer.put("SHUTDOWN".getBytes()); buffer.put(command.getBytes());
buffer.flip(); buffer.flip();
channel.write(buffer); channel.write(buffer);
buffer.clear(); buffer.clear();
@@ -464,15 +474,15 @@ public final class Application {
final String protocol = serconf.getValue("protocol", "").replaceFirst("\\..+", "").toUpperCase(); final String protocol = serconf.getValue("protocol", "").replaceFirst("\\..+", "").toUpperCase();
NodeServer server = null; NodeServer server = null;
if ("SNCP".equals(protocol)) { if ("SNCP".equals(protocol)) {
server = new NodeSncpServer(Application.this, serconf); server = NodeSncpServer.createNodeServer(Application.this, serconf);
} else if ("HTTP".equals(protocol)) { } else if ("HTTP".equalsIgnoreCase(protocol)) {
server = new NodeHttpServer(Application.this, serconf); server = new NodeHttpServer(Application.this, serconf);
} else { } else {
if (!inited.get()) { if (!inited.get()) {
synchronized (nodeClasses) { synchronized (nodeClasses) {
if (!inited.getAndSet(true)) { //加载自定义的协议SOCKS if (!inited.getAndSet(true)) { //加载自定义的协议SOCKS
ClassFilter profilter = new ClassFilter(NodeProtocol.class, NodeServer.class); ClassFilter profilter = new ClassFilter(NodeProtocol.class, NodeServer.class);
ClassFilter.Loader.load(home, profilter); ClassFilter.Loader.load(home, serconf.getValue("excludelibs", "").split(";"), profilter);
final Set<FilterEntry<NodeServer>> entrys = profilter.getFilterEntrys(); final Set<FilterEntry<NodeServer>> entrys = profilter.getFilterEntrys();
for (FilterEntry<NodeServer> entry : entrys) { for (FilterEntry<NodeServer> entry : entrys) {
final Class<? extends NodeServer> type = entry.getType(); final Class<? extends NodeServer> type = entry.getType();
@@ -537,8 +547,11 @@ public final class Application {
Utility.midnight(); //先初始化一下Utility Utility.midnight(); //先初始化一下Utility
//运行主程序 //运行主程序
final Application application = Application.create(false); final Application application = Application.create(false);
if (System.getProperty("SHUTDOWN") != null) { if (System.getProperty("CMD") != null) {
application.sendShutDown(); application.sendCommand(System.getProperty("CMD"));
return;
} else if (System.getProperty("SHUTDOWN") != null) { //兼容旧接口
application.sendCommand("SHUTDOWN");
return; return;
} }
application.init(); application.init();
@@ -572,15 +585,9 @@ public final class Application {
return null; return null;
} }
String findGroupProtocol(String group) { GroupInfo findGroupInfo(String group) {
if (group == null) return null; if (group == null) return null;
return globalGroupProtocols.get(group); return globalGroups.get(group);
}
Set<InetSocketAddress> findGlobalGroup(String group) {
if (group == null) return null;
Set<InetSocketAddress> set = globalGroups.get(group);
return set == null ? null : new LinkedHashSet<>(set);
} }
private void shutdown() throws Exception { private void shutdown() throws Exception {

View File

@@ -32,25 +32,29 @@ public final class ClassFilter<T> {
private static final boolean finer = logger.isLoggable(Level.FINER); private static final boolean finer = logger.isLoggable(Level.FINER);
private final Set<FilterEntry<T>> entrys = new HashSet<>(); private final Set<FilterEntry<T>> entrys = new HashSet<>(); //符合条件的结果
private final Set<FilterEntry<T>> expectEntrys = new HashSet<>(); private final Set<FilterEntry<T>> expectEntrys = new HashSet<>(); //准备符合条件的结果
private boolean refused; private boolean refused; //是否拒绝所有数据,设置true则其他规则失效,都是拒绝.
private Class superClass; private Class superClass; //符合的父类型。不为空时扫描结果的class必须是superClass的子类
private Class<? extends Annotation> annotationClass; private Class<? extends Annotation> annotationClass;//符合的注解。不为空时扫描结果的class必须包含该注解
private Pattern[] includePatterns; private Pattern[] includePatterns; //符合的classname正则表达式
private Pattern[] excludePatterns; private Pattern[] excludePatterns;//拒绝的classname正则表达式
private List<ClassFilter> ors; private Set<String> privilegeIncludes; //特批符合条件的classname
private List<ClassFilter> ands; private Set<String> privilegeExcludes;//特批拒绝条件的classname
private AnyValue conf; private List<ClassFilter> ors; //或关系的其他ClassFilter
private List<ClassFilter> ands;//与关系的其他ClassFilter
private AnyValue conf; //基本配置信息, 当符合条件时将conf的属性赋值到FilterEntry中去。
public ClassFilter(Class<? extends Annotation> annotationClass, Class superClass) { public ClassFilter(Class<? extends Annotation> annotationClass, Class superClass) {
this(annotationClass, superClass, null); this(annotationClass, superClass, null);
@@ -62,6 +66,15 @@ public final class ClassFilter<T> {
this.conf = conf; this.conf = conf;
} }
public static ClassFilter create(String includeregs, String excluderegs, Set<String> includeValues, Set<String> excludeValues) {
ClassFilter filter = new ClassFilter(null, null);
filter.setIncludePatterns(includeregs == null ? null : includeregs.split(";"));
filter.setExcludePatterns(excluderegs == null ? null : excluderegs.split(";"));
filter.setPrivilegeIncludes(includeValues);
filter.setPrivilegeExcludes(excludeValues);
return filter;
}
public ClassFilter<T> or(ClassFilter<T> filter) { public ClassFilter<T> or(ClassFilter<T> filter) {
if (ors == null) ors = new ArrayList<>(); if (ors == null) ors = new ArrayList<>();
ors.add(filter); ors.add(filter);
@@ -164,24 +177,20 @@ public final class ClassFilter<T> {
} catch (Throwable cfe) { } catch (Throwable cfe) {
if (finer && !clazzname.startsWith("sun.") && !clazzname.startsWith("javax.") if (finer && !clazzname.startsWith("sun.") && !clazzname.startsWith("javax.")
&& !clazzname.startsWith("com.sun.") && !clazzname.startsWith("jdk.")) { && !clazzname.startsWith("com.sun.") && !clazzname.startsWith("jdk.")) {
logger.log(Level.FINER, ClassFilter.class.getSimpleName() + " filter error", cfe); //logger.log(Level.FINEST, ClassFilter.class.getSimpleName() + " filter error", cfe);
} }
} }
} }
public static Pattern[] toPattern(String[] regs) { /**
if (regs == null) return null; * 判断class是否有效
int i = 0; *
Pattern[] rs = new Pattern[regs.length]; * @param classname String
for (String reg : regs) { *
if (reg == null || reg.trim().isEmpty()) continue; * @return boolean
rs[i++] = Pattern.compile(reg.trim()); */
} public boolean accept(String classname) {
if (i == 0) return null; return accept(null, classname);
if (i == rs.length) return rs;
Pattern[] ps = new Pattern[i];
System.arraycopy(rs, 0, ps, 0, i);
return ps;
} }
/** /**
@@ -209,6 +218,8 @@ public final class ClassFilter<T> {
private boolean accept0(AnyValue property, String classname) { private boolean accept0(AnyValue property, String classname) {
if (this.refused) return false; if (this.refused) return false;
if (this.privilegeIncludes != null && this.privilegeIncludes.contains(classname)) return true;
if (this.privilegeExcludes != null && this.privilegeExcludes.contains(classname)) return false;
if (classname.startsWith("java.") || classname.startsWith("javax.")) return false; if (classname.startsWith("java.") || classname.startsWith("javax.")) return false;
if (excludePatterns != null) { if (excludePatterns != null) {
for (Pattern reg : excludePatterns) { for (Pattern reg : excludePatterns) {
@@ -239,6 +250,21 @@ public final class ClassFilter<T> {
return superClass == null || (clazz != superClass && superClass.isAssignableFrom(clazz)); return superClass == null || (clazz != superClass && superClass.isAssignableFrom(clazz));
} }
public static Pattern[] toPattern(String[] regs) {
if (regs == null || regs.length == 0) return null;
int i = 0;
Pattern[] rs = new Pattern[regs.length];
for (String reg : regs) {
if (reg == null || reg.trim().isEmpty()) continue;
rs[i++] = Pattern.compile(reg.trim());
}
if (i == 0) return null;
if (i == rs.length) return rs;
Pattern[] ps = new Pattern[i];
System.arraycopy(rs, 0, ps, 0, i);
return ps;
}
public void setSuperClass(Class superClass) { public void setSuperClass(Class superClass) {
this.superClass = superClass; this.superClass = superClass;
} }
@@ -279,6 +305,22 @@ public final class ClassFilter<T> {
this.refused = refused; this.refused = refused;
} }
public Set<String> getPrivilegeIncludes() {
return privilegeIncludes;
}
public void setPrivilegeIncludes(Set<String> privilegeIncludes) {
this.privilegeIncludes = privilegeIncludes == null || privilegeIncludes.isEmpty() ? null : privilegeIncludes;
}
public Set<String> getPrivilegeExcludes() {
return privilegeExcludes;
}
public void setPrivilegeExcludes(Set<String> privilegeExcludes) {
this.privilegeExcludes = privilegeExcludes == null || privilegeExcludes.isEmpty() ? null : privilegeExcludes;
}
/** /**
* 存放符合条件的class与class指定的属性项 * 存放符合条件的class与class指定的属性项
* *
@@ -379,18 +421,30 @@ public final class ClassFilter<T> {
/** /**
* 加载当前线程的classpath扫描所有class进行过滤 * 加载当前线程的classpath扫描所有class进行过滤
* *
* @param exclude 不需要扫描的文件夹, 可以为null * @param excludeFile 不需要扫描的文件夹, 可以为null
* @param filters 过滤器 * @param excludeRegs 包含此关键字的文件将被跳过, 可以为null
* @param filters 过滤器
* *
* @throws IOException 异常 * @throws IOException 异常
*/ */
public static void load(final File exclude, final ClassFilter... filters) throws IOException { public static void load(final File excludeFile, final String[] excludeRegs, final ClassFilter... filters) throws IOException {
URLClassLoader loader = (URLClassLoader) Thread.currentThread().getContextClassLoader(); URLClassLoader loader = (URLClassLoader) Thread.currentThread().getContextClassLoader();
List<URL> urlfiles = new ArrayList<>(2); List<URL> urlfiles = new ArrayList<>(2);
List<URL> urljares = new ArrayList<>(2); List<URL> urljares = new ArrayList<>(2);
final URL exurl = exclude != null ? exclude.toURI().toURL() : null; final URL exurl = excludeFile != null ? excludeFile.toURI().toURL() : null;
final Pattern[] excludePatterns = toPattern(excludeRegs);
for (URL url : loader.getURLs()) { for (URL url : loader.getURLs()) {
if (exurl != null && exurl.sameFile(url)) continue; if (exurl != null && exurl.sameFile(url)) continue;
if (excludePatterns != null) {
boolean skip = false;
for (Pattern p : excludePatterns) {
if (p.matcher(url.toString()).matches()) {
skip = false;
break;
}
}
if (skip) continue;
}
if (url.getPath().endsWith(".jar")) { if (url.getPath().endsWith(".jar")) {
urljares.add(url); urljares.add(url);
} else { } else {
@@ -435,7 +489,7 @@ public final class ClassFilter<T> {
files.clear(); files.clear();
File root = new File(url.getFile()); File root = new File(url.getFile());
String rootpath = root.getPath(); String rootpath = root.getPath();
loadClassFiles(exclude, root, files); loadClassFiles(excludeFile, root, files);
for (File f : files) { for (File f : files) {
String classname = f.getPath().substring(rootpath.length() + 1, f.getPath().length() - 6).replace(File.separatorChar, '.'); String classname = f.getPath().substring(rootpath.length() + 1, f.getPath().length() - 6).replace(File.separatorChar, '.');
if (classname.startsWith("javax.") || classname.startsWith("com.sun.")) continue; if (classname.startsWith("javax.") || classname.startsWith("com.sun.")) continue;

View File

@@ -0,0 +1,74 @@
/*
* 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.boot;
import java.net.InetSocketAddress;
import java.util.*;
/**
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
public class GroupInfo {
protected String name;
protected String protocol;
protected String kind;
protected Set<InetSocketAddress> addrs;
public GroupInfo() {
}
public GroupInfo(String name, String protocol, String kind, Set<InetSocketAddress> addrs) {
this.name = name;
this.protocol = protocol;
this.kind = kind;
this.addrs = addrs;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
public Set<InetSocketAddress> getAddrs() {
return addrs;
}
public Set<InetSocketAddress> copyAddrs() {
return addrs == null ? null : new LinkedHashSet<>(addrs);
}
public void setAddrs(Set<InetSocketAddress> addrs) {
this.addrs = addrs;
}
}

View File

@@ -27,13 +27,16 @@ import org.redkale.util.*;
* @author zhangjx * @author zhangjx
*/ */
@NodeProtocol({"HTTP"}) @NodeProtocol({"HTTP"})
public final class NodeHttpServer extends NodeServer { public class NodeHttpServer extends NodeServer {
private final HttpServer httpServer; protected final boolean rest;
protected final HttpServer httpServer;
public NodeHttpServer(Application application, AnyValue serconf) { public NodeHttpServer(Application application, AnyValue serconf) {
super(application, createServer(application, serconf)); super(application, createServer(application, serconf));
this.httpServer = (HttpServer) server; this.httpServer = (HttpServer) server;
this.rest = serconf == null ? false : serconf.getAnyValue("rest") != null;
} }
private static Server createServer(Application application, AnyValue serconf) { private static Server createServer(Application application, AnyValue serconf) {
@@ -84,9 +87,9 @@ public final class NodeHttpServer extends NodeServer {
}, WebSocketNode.class); }, WebSocketNode.class);
} }
protected void loadHttpServlet(final AnyValue conf, final ClassFilter<? extends Servlet> filter) throws Exception { protected void loadHttpServlet(final AnyValue servletsConf, final ClassFilter<? extends Servlet> filter) throws Exception {
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null; final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
final String prefix = conf == null ? "" : conf.getValue("path", ""); final String prefix = servletsConf == null ? "" : servletsConf.getValue("path", "");
final String threadName = "[" + Thread.currentThread().getName() + "] "; final String threadName = "[" + Thread.currentThread().getName() + "] ";
List<FilterEntry<? extends Servlet>> list = new ArrayList(filter.getFilterEntrys()); List<FilterEntry<? extends Servlet>> list = new ArrayList(filter.getFilterEntrys());
list.sort((FilterEntry<? extends Servlet> o1, FilterEntry<? extends Servlet> o2) -> { //必须保证WebSocketServlet优先加载 因为要确保其他的HttpServlet可以注入本地模式的WebSocketNode list.sort((FilterEntry<? extends Servlet> o1, FilterEntry<? extends Servlet> o2) -> { //必须保证WebSocketServlet优先加载 因为要确保其他的HttpServlet可以注入本地模式的WebSocketNode
@@ -121,7 +124,76 @@ public final class NodeHttpServer extends NodeServer {
ss.add(new AbstractMap.SimpleEntry<>(clazz.getName(), mappings)); ss.add(new AbstractMap.SimpleEntry<>(clazz.getName(), mappings));
} }
} }
if (ss != null) { if (ss != null && sb != null) {
Collections.sort(ss, (AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey()));
int max = 0;
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
if (as.getKey().length() > max) max = as.getKey().length();
}
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
sb.append(threadName).append(" Loaded ").append(as.getKey());
for (int i = 0; i < max - as.getKey().length(); i++) {
sb.append(' ');
}
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
}
}
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
if (rest && serverConf != null) {
for (AnyValue restConf : serverConf.getAnyValues("rest")) {
loadRestServlet(prefix, restConf);
}
}
}
protected void loadRestServlet(final String prefix, final AnyValue restConf) throws Exception {
if (!rest) return;
if (restConf == null) return; //不存在REST服务
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
final String threadName = "[" + Thread.currentThread().getName() + "] ";
final List<AbstractMap.SimpleEntry<String, String[]>> ss = sb == null ? null : new ArrayList<>();
final Class baseServletClass = Class.forName(restConf.getValue("base", DefaultRestServlet.class.getName()));
final boolean autoload = restConf.getBoolValue("autoload", true);
final boolean mustsign = restConf.getBoolValue("mustsign", true); //是否只加载标记@RestService的Service类
final Set<String> includeValues = new HashSet<>();
final Set<String> excludeValues = new HashSet<>();
for (AnyValue item : restConf.getAnyValues("service")) {
if (item.getBoolValue("ignore", false)) {
excludeValues.add(item.getValue("value", ""));
} else {
includeValues.add(item.getValue("value", ""));
}
}
final ClassFilter restFilter = ClassFilter.create(restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
super.interceptorServiceWrappers.forEach((wrapper) -> {
final Class stype = wrapper.getType();
RestService rs = (RestService) stype.getAnnotation(RestService.class);
if (rs != null && rs.ignore()) return;
if (mustsign && rs == null) return;
if (stype.getAnnotation(LocalService.class) != null && rs == null) return;
final String stypename = stype.getName();
if (!autoload && !includeValues.contains(stypename)) return;
if (!restFilter.accept(stypename)) return;
RestHttpServlet servlet = httpServer.addRestServlet(wrapper.getName(), stype, wrapper.getService(), baseServletClass, prefix, (AnyValue) null);
resourceFactory.inject(servlet, NodeHttpServer.this);
if (finest) logger.finest("Create RestServlet[resource=" + wrapper.getName() + "] = " + servlet);
if (ss != null) {
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
for (int i = 0; i < mappings.length; i++) {
mappings[i] = prefix + mappings[i];
}
ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName(), mappings));
}
});
//输出信息
if (ss != null && sb != null) {
Collections.sort(ss, (AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey())); Collections.sort(ss, (AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey()));
int max = 0; int max = 0;
for (AbstractMap.SimpleEntry<String, String[]> as : ss) { for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
@@ -137,5 +209,4 @@ public final class NodeHttpServer extends NodeServer {
} }
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString()); if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
} }
} }

View File

@@ -6,13 +6,12 @@
package org.redkale.boot; package org.redkale.boot;
import java.io.*; import java.io.*;
import static java.lang.Class.forName;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.*;
import java.util.function.*; import java.util.function.*;
import java.util.logging.*; import java.util.logging.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -48,9 +47,12 @@ public abstract class NodeServer {
//日志是否为FINE级别 //日志是否为FINE级别
protected final boolean fine; protected final boolean fine;
//日志是否为FINE级别 //日志是否为FINER级别
protected final boolean finer; protected final boolean finer;
//日志是否为FINEST级别
protected final boolean finest;
//进程主类 //进程主类
protected final Application application; protected final Application application;
@@ -91,6 +93,7 @@ public abstract class NodeServer {
this.logger = Logger.getLogger(this.getClass().getSimpleName()); this.logger = Logger.getLogger(this.getClass().getSimpleName());
this.fine = logger.isLoggable(Level.FINE); this.fine = logger.isLoggable(Level.FINE);
this.finer = logger.isLoggable(Level.FINER); this.finer = logger.isLoggable(Level.FINER);
this.finest = logger.isLoggable(Level.FINEST);
} }
protected Consumer<Runnable> getExecutor() throws Exception { protected Consumer<Runnable> getExecutor() throws Exception {
@@ -162,7 +165,7 @@ public abstract class NodeServer {
initResource(); //给 DataSource、CacheSource 注册依赖注入时的监听回调事件。 initResource(); //给 DataSource、CacheSource 注册依赖注入时的监听回调事件。
String interceptorClass = this.serverConf.getValue("interceptor", ""); String interceptorClass = this.serverConf.getValue("interceptor", "");
if (!interceptorClass.isEmpty()) { if (!interceptorClass.isEmpty()) {
Class clazz = forName(interceptorClass); Class clazz = Class.forName(interceptorClass);
this.interceptor = (NodeInterceptor) clazz.newInstance(); this.interceptor = (NodeInterceptor) clazz.newInstance();
} }
@@ -170,9 +173,9 @@ public abstract class NodeServer {
ClassFilter<Service> serviceFilter = createServiceClassFilter(); ClassFilter<Service> serviceFilter = createServiceClassFilter();
long s = System.currentTimeMillis(); long s = System.currentTimeMillis();
if (servletFilter == null) { if (servletFilter == null) {
ClassFilter.Loader.load(application.getHome(), serviceFilter); ClassFilter.Loader.load(application.getHome(), serverConf.getValue("excludelibs", "").split(";"), serviceFilter);
} else { } else {
ClassFilter.Loader.load(application.getHome(), serviceFilter, servletFilter); ClassFilter.Loader.load(application.getHome(), serverConf.getValue("excludelibs", "").split(";"), serviceFilter, servletFilter);
} }
long e = System.currentTimeMillis() - s; long e = System.currentTimeMillis() - s;
logger.info(this.getClass().getSimpleName() + " load filter class in " + e + " ms"); logger.info(this.getClass().getSimpleName() + " load filter class in " + e + " ms");
@@ -234,6 +237,7 @@ public abstract class NodeServer {
source.setStoreType(pt == null ? Serializable.class : (Class) pt.getActualTypeArguments()[0], valType instanceof Class ? (Class) valType : Object.class); source.setStoreType(pt == null ? Serializable.class : (Class) pt.getActualTypeArguments()[0], valType instanceof Class ? (Class) valType : Object.class);
if (field.getAnnotation(Transient.class) != null) source.setNeedStore(false); //必须在setStoreType之后 if (field.getAnnotation(Transient.class) != null) source.setNeedStore(false); //必须在setStoreType之后
application.cacheSources.add(source); application.cacheSources.add(source);
appResFactory.register(resourceName, genericType, source);
appResFactory.register(resourceName, CacheSource.class, source); appResFactory.register(resourceName, CacheSource.class, source);
field.set(src, source); field.set(src, source);
rf.inject(source, self); // rf.inject(source, self); //
@@ -243,7 +247,7 @@ public abstract class NodeServer {
NodeSncpServer sncpServer = application.findNodeSncpServer(sncpAddr); NodeSncpServer sncpServer = application.findNodeSncpServer(sncpAddr);
Set<String> gs = application.findSncpGroups(sameGroupTransport, diffGroupTransports); Set<String> gs = application.findSncpGroups(sameGroupTransport, diffGroupTransports);
ServiceWrapper wrapper = new ServiceWrapper(CacheSourceService.class, (Service) source, resourceName, sncpServer.getSncpGroup(), gs, null); ServiceWrapper wrapper = new ServiceWrapper(CacheSourceService.class, (Service) source, resourceName, sncpServer.getSncpGroup(), gs, null);
sncpServer.getSncpServer().addService(wrapper); sncpServer.getSncpServer().addSncpServlet(wrapper);
logger.info("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService()); logger.info("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService());
} }
logger.info("[" + Thread.currentThread().getName() + "] Load Source " + source); logger.info("[" + Thread.currentThread().getName() + "] Load Source " + source);
@@ -268,7 +272,6 @@ public abstract class NodeServer {
if (Modifier.isAbstract(type.getModifiers())) continue; //修饰abstract的类跳过 if (Modifier.isAbstract(type.getModifiers())) continue; //修饰abstract的类跳过
if (DataSource.class.isAssignableFrom(type)) continue; if (DataSource.class.isAssignableFrom(type)) continue;
if (CacheSource.class.isAssignableFrom(type)) continue; if (CacheSource.class.isAssignableFrom(type)) continue;
if (DataSQLListener.class.isAssignableFrom(type)) continue;
if (DataCacheListener.class.isAssignableFrom(type)) continue; if (DataCacheListener.class.isAssignableFrom(type)) continue;
if (WebSocketNode.class.isAssignableFrom(type)) continue; if (WebSocketNode.class.isAssignableFrom(type)) continue;
} }
@@ -353,15 +356,22 @@ public abstract class NodeServer {
localServiceWrappers.clear(); localServiceWrappers.clear();
localServiceWrappers.addAll(swlist); localServiceWrappers.addAll(swlist);
final List<String> slist = sb == null ? null : new CopyOnWriteArrayList<>(); final List<String> slist = sb == null ? null : new CopyOnWriteArrayList<>();
CountDownLatch clds = new CountDownLatch(localServiceWrappers.size());
localServiceWrappers.parallelStream().forEach(y -> { localServiceWrappers.parallelStream().forEach(y -> {
long s = System.currentTimeMillis(); try {
y.getService().init(y.getConf()); long s = System.currentTimeMillis();
long e = System.currentTimeMillis() - s; y.getService().init(y.getConf());
if (slist != null) slist.add(new StringBuilder().append(threadName).append(y.toSimpleString()).append(" loaded and inited ").append(e).append(" ms").append(LINE_SEPARATOR).toString()); long e = System.currentTimeMillis() - s;
if (slist != null) slist.add(new StringBuilder().append(threadName).append(y.toSimpleString()).append(" loaded and inited ").append(e).append(" ms").append(LINE_SEPARATOR).toString());
} finally {
clds.countDown();
}
}); });
Collections.sort(slist); clds.await();
if (slist != null && sb != null) { if (slist != null && sb != null) {
for (String s : slist) { List<String> wlist = new ArrayList<>(slist); //直接使用CopyOnWriteArrayList偶尔会出现莫名的异常(CopyOnWriteArrayList源码1185行)
Collections.sort(wlist);
for (String s : wlist) {
sb.append(s); sb.append(s);
} }
} }
@@ -391,8 +401,9 @@ public abstract class NodeServer {
Set<InetSocketAddress> addrs = new HashSet(); Set<InetSocketAddress> addrs = new HashSet();
transports.forEach(t -> addrs.addAll(Arrays.asList(t.getRemoteAddresses()))); transports.forEach(t -> addrs.addAll(Arrays.asList(t.getRemoteAddresses())));
Transport first = transports.get(0); Transport first = transports.get(0);
Transport newTransport = new Transport(groupid, application.findGroupProtocol(first.getName()), application.getWatchFactory(), GroupInfo ginfo = application.findGroupInfo(first.getName());
application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs); Transport newTransport = new Transport(groupid, ginfo.getProtocol(), application.getWatchFactory(),
ginfo.getKind(), application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs);
synchronized (application.resourceFactory) { synchronized (application.resourceFactory) {
transport = application.resourceFactory.find(groupid, Transport.class); transport = application.resourceFactory.find(groupid, Transport.class);
if (transport == null) { if (transport == null) {
@@ -414,10 +425,11 @@ public abstract class NodeServer {
} }
return transport; return transport;
} }
Set<InetSocketAddress> addrs = application.findGlobalGroup(group); GroupInfo ginfo = application.findGroupInfo(group);
Set<InetSocketAddress> addrs = ginfo.copyAddrs();
if (addrs == null) throw new RuntimeException("Not found <group> = " + group + " on <resources> "); if (addrs == null) throw new RuntimeException("Not found <group> = " + group + " on <resources> ");
transport = new Transport(group, application.findGroupProtocol(group), application.getWatchFactory(), transport = new Transport(group, ginfo.getProtocol(), application.getWatchFactory(),
application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs); ginfo.getKind(), application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs);
application.resourceFactory.register(group, transport); application.resourceFactory.register(group, transport);
} }
return transport; return transport;

View File

@@ -20,14 +20,22 @@ import org.redkale.util.*;
* @author zhangjx * @author zhangjx
*/ */
@NodeProtocol({"SNCP"}) @NodeProtocol({"SNCP"})
public final class NodeSncpServer extends NodeServer { public class NodeSncpServer extends NodeServer {
private final SncpServer sncpServer; protected final SncpServer sncpServer;
public NodeSncpServer(Application application, AnyValue serconf) { private NodeSncpServer(Application application, AnyValue serconf) {
super(application, createServer(application, serconf)); super(application, createServer(application, serconf));
this.sncpServer = (SncpServer) this.server; this.sncpServer = (SncpServer) this.server;
this.consumer = sncpServer == null ? null : x -> sncpServer.addService(x); this.consumer = sncpServer == null ? null : x -> sncpServer.addSncpServlet(x);
}
public static NodeServer createNodeServer(Application application, AnyValue serconf) {
if (serconf != null && serconf.getAnyValue("rest") != null) {
((AnyValue.DefaultAnyValue) serconf).addValue("_$sncp", "true");
return new NodeHttpServer(application, serconf);
}
return new NodeSncpServer(application, serconf);
} }
private static Server createServer(Application application, AnyValue serconf) { private static Server createServer(Application application, AnyValue serconf) {

View File

@@ -0,0 +1,85 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8"><title>Document</title>
<style type="text/css">
body {text-align: center;margin:auto;}
a{text-decoration: none;}
.table {margin: auto;border-collapse: collapse;border-spacing: 0;display: block;width: 100%;overflow: auto;word-break: normal;word-break: keep-all;}
.table td,.table th{padding: 0.4rem 1.2rem 0.4rem 1.2rem;border: 1px solid #aaa;}
.table td {text-align: left;}
.s {font-size: 0.8rem; vertical-align: middle;}
.subtable {border-spacing: 0;border: 0;margin:0;}
.subtable td{border: 0;padding: 0 0 0 10px;}
.typetable {border-spacing: 0;border: 0;margin:0;}
.typetable td{border: 0;padding: 2px 20px 2px 10px;}
.typetable .l{border-bottom: 1px solid red;}
</style>
</head>
<body>
<script>
var createhtml = function (jsoncontent) {
var classmap = jsoncontent.types;
var html = [];
html.push('<div style="width:' + Math.floor(window.screen.width * 0.9) + 'px;margin:0 auto;text-align: center;">');
html.push('<br/><br/><table class="table" align="center">');
for (var i = 0; i < jsoncontent.servers.length; i++) {
for (var j = 0; j < jsoncontent.servers[i].servlets.length; j++) {
var servlet = jsoncontent.servers[i].servlets[j];
if (html.length > 2) html.push(' <tr><th colspan="5" style="border-bottom:0;">&nbsp;</th></tr>');
html.push(' <tr><th colspan="5" style="border-top:' + ((html.length > 2) ? 0 : 1) + ';">' + (servlet.comment || '未知模块') + '</th></tr>');
html.push(' <tr><th>请求URL</th><th>描 述</th><th>鉴 权</th><th>参 数 <span style="font-size:12px;">(红色: Header; 蓝色: Cookie)</span></th><th>输 出</th></tr>');
for (var k = 0; k < servlet.actions.length; k++) {
var action = servlet.actions[k];
html.push(' <tr>');
html.push('<td style="color:#ff00ff;">' + action.url + '</td>');
html.push('<td>' + action.comment + '</td>');
html.push('<td class="s">模块ID: ' + servlet.moduleid + '<br/>操作ID: ' + action.actionid + '<br/>需鉴权: ' + (action.auth ? '<font style="font-weight:bold;color:green;">true</font>' : '<font color=red>false</font>') + '</td>');
var paramshtml = [];
paramshtml.push('<table class="subtable">');
for (var p = 0; p < action.params.length; p++) {
var param = action.params[p];
var t = param.type.substring(param.type.lastIndexOf('.') + 1);
if (classmap[param.type.replace('[]', '')]) {
t = '<a href="#' + param.type.replace('[]', '') + '">' + t + '</a>';
}
if (param.name == '&') {
paramshtml.push('<tr><td style="font-size:12px;">内置 </td><td> ' + t + '</td><td> 当前用户</td></tr>');
} else {
var c = ' style="font-weight:bold;"';
if (param.src == "HEADER") c = ' style="color:red;font-weight:bold;"';
if (param.src == "COOKIE") c = ' style="color:blue;font-weight:bold;"';
paramshtml.push('<tr><td ' + c + '> ' + param.name + ' </td><td> ' + t + '</td><td> ' + param.comment + '</td></tr>');
}
}
paramshtml.push('</table>');
html.push('<td class="s" style="padding:0 5px;">' + paramshtml.join('') + '</td>');
html.push('<td>' + action.result.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/([a-zA-Z0-9_\$]+\.)+/g, "") + '</td>');
html.push('</tr>');
}
}
}
for (var type in classmap) {
html.push(' <tr><th colspan="5" style="border-bottom:0;">&nbsp;</th></tr>');
html.push(' <tr id="' + type + '"><th colspan="5" style="border-top:0;">' + type + '</th></tr>');
html.push(' <tr><td colspan="5"><table class="typetable">');
for (var fieldname in classmap[type]) {
var field = classmap[type][fieldname];
var t = field.type.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/([a-zA-Z0-9_\$]+\.)+/g, "");
html.push(' <tr class="l"><td>' + fieldname + '</td><td>' + t + '</td><td colspan="2">' + (field.comment || '') + '</td></tr>');
}
html.push(' </table></td></tr>');
}
html.push('</table><br/><br/><br/>');
html.push('</div>');
return html.join('');
};
</script>
<script>
var jsoncontent = ${content};
document.write(createhtml(jsoncontent));
</script>
</body>
</html>

View File

@@ -1,4 +1,4 @@
/** /**
* 提供RedKale服务器的启动、初始化和加载功能 * 提供Redkale服务器的启动、初始化和加载功能
*/ */
package org.redkale.boot; package org.redkale.boot;

View File

@@ -104,6 +104,14 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
this.register(double[].class, DoubleArraySimpledCoder.instance); this.register(double[].class, DoubleArraySimpledCoder.instance);
this.register(String[].class, StringArraySimpledCoder.instance); this.register(String[].class, StringArraySimpledCoder.instance);
//--------------------------------------------------------- //---------------------------------------------------------
this.register(HttpCookie.class, new Creator<HttpCookie>() {
@Override
@Creator.ConstructorParameters({"name", "value"})
public HttpCookie create(Object... params) {
return new HttpCookie((String) params[0], (String) params[1]);
}
});
} }
} }
@@ -204,7 +212,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
/** /**
* 使所有类的所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false * 使所有类的所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false
* *
* @param skipIgnore * @param skipIgnore 忽略ignore
* *
* @return 自身 * @return 自身
*/ */
@@ -387,7 +395,9 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
} else if (clazz == Object.class) { } else if (clazz == Object.class) {
od = new ObjectDecoder(type); od = new ObjectDecoder(type);
decoder = od; decoder = od;
} else if (!clazz.getName().startsWith("java.") || clazz.getName().startsWith("java.awt.geom.Point2D")) { } else if (!clazz.getName().startsWith("java.")
|| java.net.HttpCookie.class == clazz
|| clazz.getName().startsWith("java.awt.geom.Point2D")) {
Decodeable simpleCoder = null; Decodeable simpleCoder = null;
for (final Method method : clazz.getDeclaredMethods()) { for (final Method method : clazz.getDeclaredMethods()) {
if (!Modifier.isStatic(method.getModifiers())) continue; if (!Modifier.isStatic(method.getModifiers())) continue;
@@ -467,7 +477,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
encoder = new MapEncoder(this, type); encoder = new MapEncoder(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.")) { } else if (!clazz.getName().startsWith("java.") || java.net.HttpCookie.class == clazz) {
Encodeable simpleCoder = null; Encodeable simpleCoder = null;
for (final Method method : clazz.getDeclaredMethods()) { for (final Method method : clazz.getDeclaredMethods()) {
if (!Modifier.isStatic(method.getModifiers())) continue; if (!Modifier.isStatic(method.getModifiers())) continue;

View File

@@ -121,7 +121,7 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
} }
} }
} }
if (value != null && value.getClass() != this.typeClass) { if (value.getClass() != this.typeClass) {
final Class clz = value.getClass(); final Class clz = value.getClass();
if (out.needWriteClassName()) out.writeClassName(factory.getEntityAlias(clz)); if (out.needWriteClassName()) out.writeClassName(factory.getEntityAlias(clz));
factory.loadEncoder(clz).convertTo(out, value); factory.loadEncoder(clz).convertTo(out, value);

View File

@@ -91,4 +91,8 @@ public abstract class PrepareServlet<K extends Serializable, C extends Context,
protected void setServletConf(Servlet servlet, AnyValue conf) { protected void setServletConf(Servlet servlet, AnyValue conf) {
servlet._conf = conf; servlet._conf = conf;
} }
public Set<S> getServlets() {
return new LinkedHashSet<>(servlets);
}
} }

View File

@@ -44,6 +44,8 @@ public final class Transport {
protected final String name; //即<group>的name属性 protected final String name; //即<group>的name属性
protected final String kind; //即<group>的kind属性
protected final boolean tcp; protected final boolean tcp;
protected final String protocol; protected final String protocol;
@@ -54,21 +56,22 @@ public final class Transport {
protected final InetSocketAddress clientAddress; protected final InetSocketAddress clientAddress;
protected InetSocketAddress[] remoteAddres = new InetSocketAddress[0]; protected InetSocketAddress[] remoteAddres = new InetSocketAddress[0];
protected final ObjectPool<ByteBuffer> bufferPool; protected final ObjectPool<ByteBuffer> bufferPool;
protected final ConcurrentHashMap<SocketAddress, BlockingQueue<AsyncConnection>> connPool = new ConcurrentHashMap<>(); protected final ConcurrentHashMap<SocketAddress, BlockingQueue<AsyncConnection>> connPool = new ConcurrentHashMap<>();
public Transport(String name, WatchFactory watch, final ObjectPool<ByteBuffer> transportBufferPool, public Transport(String name, WatchFactory watch, String kind, final ObjectPool<ByteBuffer> transportBufferPool,
final AsynchronousChannelGroup transportChannelGroup, final InetSocketAddress clientAddress, final Collection<InetSocketAddress> addresses) { final AsynchronousChannelGroup transportChannelGroup, final InetSocketAddress clientAddress, final Collection<InetSocketAddress> addresses) {
this(name, DEFAULT_PROTOCOL, watch, transportBufferPool, transportChannelGroup, clientAddress, addresses); this(name, DEFAULT_PROTOCOL, watch, kind, transportBufferPool, transportChannelGroup, clientAddress, addresses);
} }
public Transport(String name, String protocol, WatchFactory watch, final ObjectPool<ByteBuffer> transportBufferPool, public Transport(String name, String protocol, WatchFactory watch, String kind, final ObjectPool<ByteBuffer> transportBufferPool,
final AsynchronousChannelGroup transportChannelGroup, final InetSocketAddress clientAddress, final Collection<InetSocketAddress> addresses) { final AsynchronousChannelGroup transportChannelGroup, final InetSocketAddress clientAddress, final Collection<InetSocketAddress> addresses) {
this.name = name; this.name = name;
this.watch = watch; this.watch = watch;
this.kind = kind == null ? "" : kind.trim();
this.protocol = protocol; this.protocol = protocol;
this.tcp = "TCP".equalsIgnoreCase(protocol); this.tcp = "TCP".equalsIgnoreCase(protocol);
this.group = transportChannelGroup; this.group = transportChannelGroup;
@@ -87,6 +90,7 @@ public final class Transport {
//必须按字母排列顺序确保相同内容的transport列表组合的name相同而不会因为list的顺序不同产生不同的name //必须按字母排列顺序确保相同内容的transport列表组合的name相同而不会因为list的顺序不同产生不同的name
this.name = tmpgroup.stream().sorted().collect(Collectors.joining(";")); this.name = tmpgroup.stream().sorted().collect(Collectors.joining(";"));
this.watch = first.watch; this.watch = first.watch;
this.kind = first.kind;
this.protocol = first.protocol; this.protocol = first.protocol;
this.tcp = "TCP".equalsIgnoreCase(first.protocol); this.tcp = "TCP".equalsIgnoreCase(first.protocol);
this.group = first.group; this.group = first.group;
@@ -114,6 +118,10 @@ public final class Transport {
return name; return name;
} }
public String getKind() {
return kind;
}
public void close() { public void close() {
connPool.forEach((k, v) -> v.forEach(c -> c.dispose())); connPool.forEach((k, v) -> v.forEach(c -> c.dispose()));
} }

View File

@@ -5,345 +5,14 @@
*/ */
package org.redkale.net.http; package org.redkale.net.http;
import org.redkale.net.Response;
import org.redkale.net.Request;
import org.redkale.util.AnyValue;
import java.io.IOException;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.reflect.Method;
import java.nio.*;
import java.util.*;
import java.util.concurrent.*;
import jdk.internal.org.objectweb.asm.*;
import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
import org.redkale.service.RetResult;
/** /**
* *
* <p> * <p>
* 详情见: http://redkale.org * 详情见: http://redkale.org
* *
* @deprecated 使用 org.redkale.net.http.HttpBaseServlet 代替
* @see org.redkale.net.http.HttpBaseServlet
* @author zhangjx * @author zhangjx
*/ */
public abstract class BasedHttpServlet extends HttpServlet { public abstract class BasedHttpServlet extends HttpBaseServlet {
}
public static final int RET_METHOD_ERROR = 1800_0001;
/**
* 配合 BasedHttpServlet 使用。
* 当标记为 &#64;AuthIgnore 的方法在执行execute之前不会调用authenticate 方法。
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({METHOD, TYPE})
@Retention(RUNTIME)
protected @interface AuthIgnore {
}
/**
* 配合 BasedHttpServlet 使用。
* 用于对&#64;WebServlet对应的url进行细分。 其url必须是包含WebServlet中定义的前缀 且不能是正则表达式
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
protected @interface WebAction {
int actionid() default 0;
String url();
String[] methods() default {};//允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法
}
/**
* 配合 BasedHttpServlet 使用。
* 当标记为 &#64;HttpCacheable 的方法使用response.finish的参数将被缓存一定时间(默认值timeout=15秒)。
* 通常情况下 &#64;HttpCacheable 需要与 &#64;AuthIgnore 一起使用,因为没有标记&#64;AuthIgnore的方法一般输出的结果与当前用户信息有关。
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
protected @interface HttpCacheable {
/**
* 超时的秒数
*
* @return 超时秒数
*/
int timeout() default 15;
}
private Map.Entry<String, Entry>[] actions;
public boolean preExecute(HttpRequest request, HttpResponse response) throws IOException {
return true;
}
@Override
public final void execute(HttpRequest request, HttpResponse response) throws IOException {
if (!preExecute(request, response)) return;
for (Map.Entry<String, Entry> en : actions) {
if (request.getRequestURI().startsWith(en.getKey())) {
Entry entry = en.getValue();
if (!entry.checkMethod(request.getMethod())) {
response.finishJson(new RetResult(RET_METHOD_ERROR, "Method(" + request.getMethod() + ") Error"));
return;
}
if (entry.ignore || authenticate(entry.moduleid, entry.actionid, request, response)) {
if (entry.cachetimeout > 0) {//有缓存设置
CacheEntry ce = entry.cache.get(request.getRequestURI());
if (ce != null && ce.time + entry.cachetimeout > System.currentTimeMillis()) { //缓存有效
response.setStatus(ce.status);
response.setContentType(ce.contentType);
response.finish(ce.getBuffers());
return;
}
response.setBufferHandler(entry.cacheHandler);
}
entry.servlet.execute(request, response);
}
return;
}
}
throw new IOException(this.getClass().getName() + " not found method for URI(" + request.getRequestURI() + ")");
}
public final void preInit(HttpContext context, AnyValue config) {
String path = _prefix == null ? "" : _prefix;
WebServlet ws = this.getClass().getAnnotation(WebServlet.class);
if (ws != null && !ws.repair()) path = "";
HashMap<String, Entry> map = load();
this.actions = new Map.Entry[map.size()];
int i = -1;
for (Map.Entry<String, Entry> en : map.entrySet()) {
actions[++i] = new AbstractMap.SimpleEntry<>(path + en.getKey(), en.getValue());
}
//必须要倒排序, /query /query1 /query12 确保含子集的优先匹配 /query12 /query1 /query
Arrays.sort(actions, (o1, o2) -> o2.getKey().compareTo(o1.getKey()));
}
public final void postDestroy(HttpContext context, AnyValue config) {
}
public abstract boolean authenticate(int module, int actionid, HttpRequest request, HttpResponse response) throws IOException;
private HashMap<String, Entry> load() {
final boolean typeIgnore = this.getClass().getAnnotation(AuthIgnore.class) != null;
WebServlet module = this.getClass().getAnnotation(WebServlet.class);
final int serviceid = module == null ? 0 : module.moduleid();
final HashMap<String, Entry> map = new HashMap<>();
Set<String> nameset = new HashSet<>();
for (final Method method : this.getClass().getMethods()) {
//-----------------------------------------------
String methodname = method.getName();
if ("service".equals(methodname) || "preExecute".equals(methodname) || "execute".equals(methodname) || "authenticate".equals(methodname)) continue;
//-----------------------------------------------
Class[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 2 || paramTypes[0] != HttpRequest.class
|| paramTypes[1] != HttpResponse.class) continue;
//-----------------------------------------------
Class[] exps = method.getExceptionTypes();
if (exps.length > 0 && (exps.length != 1 || exps[0] != IOException.class)) continue;
//-----------------------------------------------
final WebAction action = method.getAnnotation(WebAction.class);
if (action == null) continue;
final int actionid = action.actionid();
final String name = action.url().trim();
if (nameset.contains(name)) throw new RuntimeException(this.getClass().getSimpleName() + " has two same " + WebAction.class.getSimpleName() + "(" + name + ")");
//屏蔽以下代码,允许相互包含
// for (String n : nameset) {
// if (n.contains(name) || name.contains(n)) {
// throw new RuntimeException(this.getClass().getSimpleName() + " has two sub-contains " + WebAction.class.getSimpleName() + "(" + name + ", " + n + ")");
// }
// }
nameset.add(name);
map.put(name, new Entry(typeIgnore, serviceid, actionid, name, action.methods(), method, createHttpServlet(method)));
}
return map;
}
private HttpServlet createHttpServlet(final Method method) {
//------------------------------------------------------------------------------
final String supDynName = HttpServlet.class.getName().replace('.', '/');
final String interName = this.getClass().getName().replace('.', '/');
final String interDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(this.getClass());
final String requestSupDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(Request.class);
final String responseSupDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(Response.class);
final String requestDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(HttpRequest.class);
final String responseDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(HttpResponse.class);
String newDynName = interName + "_Dyn_" + method.getName();
int i = 0;
for (;;) {
try {
Class.forName(newDynName.replace('/', '.'));
newDynName += "_" + (++i);
} catch (Exception ex) {
break;
}
}
//------------------------------------------------------------------------------
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
final String factfield = "_factServlet";
cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null);
{
fv = cw.visitField(ACC_PUBLIC, factfield, interDesc, null, null);
fv.visitEnd();
}
{ //构造函数
mv = (cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
//mv.setDebug(true);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, supDynName, "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
mv = (cw.visitMethod(ACC_PUBLIC, "execute", "(" + requestDesc + responseDesc + ")V", null, new String[]{"java/io/IOException"}));
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, factfield, interDesc);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, interName, method.getName(), "(" + requestDesc + responseDesc + ")V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "execute", "(" + requestSupDesc + responseSupDesc + ")V", null, new String[]{"java/io/IOException"});
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, HttpRequest.class.getName().replace('.', '/'));
mv.visitVarInsn(ALOAD, 2);
mv.visitTypeInsn(CHECKCAST, HttpResponse.class.getName().replace('.', '/'));
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "execute", "(" + requestDesc + responseDesc + ")V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
}
cw.visitEnd();
//------------------------------------------------------------------------------
byte[] bytes = cw.toByteArray();
Class<?> newClazz = new ClassLoader(this.getClass().getClassLoader()) {
public final Class<?> loadClass(String name, byte[] b) {
return defineClass(name, b, 0, b.length);
}
}.loadClass(newDynName.replace('/', '.'), bytes);
try {
HttpServlet instance = (HttpServlet) newClazz.newInstance();
instance.getClass().getField(factfield).set(instance, this);
return instance;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
private static final class Entry {
public Entry(boolean typeIgnore, int moduleid, int actionid, String name, String[] methods, Method method, HttpServlet servlet) {
this.moduleid = moduleid;
this.actionid = actionid;
this.name = name;
this.methods = methods;
this.method = method;
this.servlet = servlet;
this.ignore = typeIgnore || method.getAnnotation(AuthIgnore.class) != null;
HttpCacheable hc = method.getAnnotation(HttpCacheable.class);
this.cachetimeout = hc == null ? 0 : hc.timeout() * 1000;
this.cache = cachetimeout > 0 ? new ConcurrentHashMap() : null;
this.cacheHandler = cachetimeout > 0 ? (HttpResponse response, ByteBuffer[] buffers) -> {
int status = response.getStatus();
if (status != 200) return null;
CacheEntry ce = new CacheEntry(response.getStatus(), response.getContentType(), buffers);
cache.put(response.getRequest().getRequestURI(), ce);
return ce.getBuffers();
} : null;
}
public boolean isNeedCheck() {
return this.moduleid != 0 || this.actionid != 0;
}
public boolean checkMethod(final String reqMethod) {
if (methods.length == 0) return true;
for (String m : methods) {
if (reqMethod.equalsIgnoreCase(m)) return true;
}
return false;
}
public final HttpResponse.BufferHandler cacheHandler;
public final ConcurrentHashMap<String, CacheEntry> cache;
public final int cachetimeout;
public final boolean ignore;
public final int moduleid;
public final int actionid;
public final String name;
public final String[] methods;
public final Method method;
public final HttpServlet servlet;
}
private static final class CacheEntry {
public final long time = System.currentTimeMillis();
private final ByteBuffer[] buffers;
private final int status;
private final String contentType;
public CacheEntry(int status, String contentType, ByteBuffer[] bufs) {
this.status = status;
this.contentType = contentType;
final ByteBuffer[] newBuffers = new ByteBuffer[bufs.length];
for (int i = 0; i < newBuffers.length; i++) {
newBuffers[i] = bufs[i].duplicate().asReadOnlyBuffer();
}
this.buffers = newBuffers;
}
public ByteBuffer[] getBuffers() {
final ByteBuffer[] newBuffers = new ByteBuffer[buffers.length];
for (int i = 0; i < newBuffers.length; i++) {
newBuffers[i] = buffers[i].duplicate();
}
return newBuffers;
}
}
}

View File

@@ -0,0 +1,29 @@
/*
* 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.net.http;
import java.io.IOException;
/**
* 默认Servlet, 没有配置RestHttpServlet实现类则使用该默认类
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
public class DefaultRestServlet extends RestHttpServlet<Object> {
@Override
protected Object currentUser(HttpRequest req) throws IOException {
return new Object();
}
@Override
public boolean authenticate(int module, int actionid, HttpRequest request, HttpResponse response) throws IOException {
return true;
}
}

View File

@@ -0,0 +1,408 @@
/*
* 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.net.http;
import org.redkale.net.Response;
import org.redkale.net.Request;
import org.redkale.util.AnyValue;
import java.io.IOException;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.reflect.*;
import java.nio.*;
import java.util.*;
import java.util.concurrent.*;
import jdk.internal.org.objectweb.asm.*;
import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
import org.redkale.service.RetResult;
/**
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
public abstract class HttpBaseServlet extends HttpServlet {
public static final int RET_SERVER_ERROR = 1800_0001;
public static final int RET_METHOD_ERROR = 1800_0002;
/**
* 配合 HttpBaseServlet 使用。
* 当标记为 &#64;AuthIgnore 的方法在执行execute之前不会调用authenticate 方法。
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({METHOD, TYPE})
@Retention(RUNTIME)
protected @interface AuthIgnore {
}
/**
* 配合 &#64;WebParam 使用。
* 用于对&#64;WebParam中参数的来源类型
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
protected enum ParamSourceType {
PARAMETER, HEADER, COOKIE;
}
/**
* 配合 &#64;WebAction 使用。
* 用于对&#64;WebAction方法中参数描述
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Documented
@Target({METHOD})
@Retention(RUNTIME)
@Repeatable(WebParams.class)
protected @interface WebParam {
String name(); //参数名
Class type(); //参数的数据类型
String comment() default ""; //备注描述
ParamSourceType src() default ParamSourceType.PARAMETER; //参数来源类型
int radix() default 10; //转换数字byte/short/int/long时所用的进制数 默认10进制
}
@Documented
@Target({METHOD})
@Retention(RUNTIME)
protected @interface WebParams {
WebParam[] value();
}
/**
* 配合 HttpBaseServlet 使用。
* 用于对&#64;WebServlet对应的url进行细分。 其url必须是包含WebServlet中定义的前缀 且不能是正则表达式
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Documented
@Target({METHOD})
@Retention(RUNTIME)
protected @interface WebAction {
int actionid() default 0;
String url();
String[] methods() default {};//允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法
String comment() default ""; //备注描述
String result() default "Object"; //输出结果的数据类型
}
/**
* 配合 HttpBaseServlet 使用。
* 当标记为 &#64;HttpCacheable 的方法使用response.finish的参数将被缓存一段时间(默认值timeout=15秒)。
* 通常情况下 &#64;HttpCacheable 需要与 &#64;AuthIgnore 一起使用,没有标记&#64;AuthIgnore的方法一般输出的结果与当前用户信息有关。
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Documented
@Target({METHOD})
@Retention(RUNTIME)
protected @interface HttpCacheable {
/**
* 超时的秒数
*
* @return 超时秒数
*/
int timeout() default 15;
}
private Map.Entry<String, Entry>[] actions;
public boolean preExecute(HttpRequest request, HttpResponse response) throws IOException {
return true;
}
@Override
public final void execute(HttpRequest request, HttpResponse response) throws IOException {
if (!preExecute(request, response)) return;
for (Map.Entry<String, Entry> en : actions) {
if (request.getRequestURI().startsWith(en.getKey())) {
Entry entry = en.getValue();
if (!entry.checkMethod(request.getMethod())) {
response.finishJson(new RetResult(RET_METHOD_ERROR, "Method(" + request.getMethod() + ") Error"));
return;
}
if (entry.ignore || authenticate(entry.moduleid, entry.actionid, request, response)) {
if (entry.cachetimeout > 0) {//有缓存设置
CacheEntry ce = entry.cache.get(request.getRequestURI());
if (ce != null && ce.time + entry.cachetimeout > System.currentTimeMillis()) { //缓存有效
response.setStatus(ce.status);
response.setContentType(ce.contentType);
response.finish(ce.getBuffers());
return;
}
response.setBufferHandler(entry.cacheHandler);
}
entry.servlet.execute(request, response);
}
return;
}
}
throw new IOException(this.getClass().getName() + " not found method for URI(" + request.getRequestURI() + ")");
}
public final void preInit(HttpContext context, AnyValue config) {
String path = _prefix == null ? "" : _prefix;
WebServlet ws = this.getClass().getAnnotation(WebServlet.class);
if (ws != null && !ws.repair()) path = "";
HashMap<String, Entry> map = load();
this.actions = new Map.Entry[map.size()];
int i = -1;
for (Map.Entry<String, Entry> en : map.entrySet()) {
actions[++i] = new AbstractMap.SimpleEntry<>(path + en.getKey(), en.getValue());
}
//必须要倒排序, /query /query1 /query12 确保含子集的优先匹配 /query12 /query1 /query
Arrays.sort(actions, (o1, o2) -> o2.getKey().compareTo(o1.getKey()));
}
public final void postDestroy(HttpContext context, AnyValue config) {
}
public abstract boolean authenticate(int module, int actionid, HttpRequest request, HttpResponse response) throws IOException;
protected String _prefix(HttpServlet servlet) {
return servlet._prefix;
}
private HashMap<String, Entry> load() {
final boolean typeIgnore = this.getClass().getAnnotation(AuthIgnore.class) != null;
WebServlet module = this.getClass().getAnnotation(WebServlet.class);
final int serviceid = module == null ? 0 : module.moduleid();
final HashMap<String, Entry> map = new HashMap<>();
Set<String> nameset = new HashSet<>();
for (final Method method : this.getClass().getMethods()) {
//-----------------------------------------------
String methodname = method.getName();
if ("service".equals(methodname) || "preExecute".equals(methodname) || "execute".equals(methodname) || "authenticate".equals(methodname)) continue;
//-----------------------------------------------
Class[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 2 || paramTypes[0] != HttpRequest.class
|| paramTypes[1] != HttpResponse.class) continue;
//-----------------------------------------------
Class[] exps = method.getExceptionTypes();
if (exps.length > 0 && (exps.length != 1 || exps[0] != IOException.class)) continue;
//-----------------------------------------------
final WebAction action = method.getAnnotation(WebAction.class);
if (action == null) continue;
final int actionid = action.actionid();
final String name = action.url().trim();
if (nameset.contains(name)) throw new RuntimeException(this.getClass().getSimpleName() + " has two same " + WebAction.class.getSimpleName() + "(" + name + ")");
//屏蔽以下代码,允许相互包含
// for (String n : nameset) {
// if (n.contains(name) || name.contains(n)) {
// throw new RuntimeException(this.getClass().getSimpleName() + " has two sub-contains " + WebAction.class.getSimpleName() + "(" + name + ", " + n + ")");
// }
// }
nameset.add(name);
map.put(name, new Entry(typeIgnore, serviceid, actionid, name, action.methods(), method, createHttpServlet(method)));
}
return map;
}
private HttpServlet createHttpServlet(final Method method) {
//------------------------------------------------------------------------------
final String supDynName = HttpServlet.class.getName().replace('.', '/');
final String interName = this.getClass().getName().replace('.', '/');
final String interDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(this.getClass());
final String requestSupDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(Request.class);
final String responseSupDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(Response.class);
final String requestDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(HttpRequest.class);
final String responseDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(HttpResponse.class);
String newDynName = interName + "_Dyn_" + method.getName();
int i = 0;
for (;;) {
try {
Class.forName(newDynName.replace('/', '.'));
newDynName += "_" + (++i);
} catch (Exception ex) {
break;
}
}
//------------------------------------------------------------------------------
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
final String factfield = "_factServlet";
cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null);
{
fv = cw.visitField(ACC_PUBLIC, factfield, interDesc, null, null);
fv.visitEnd();
}
{ //构造函数
mv = (cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
//mv.setDebug(true);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, supDynName, "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
mv = (cw.visitMethod(ACC_PUBLIC, "execute", "(" + requestDesc + responseDesc + ")V", null, new String[]{"java/io/IOException"}));
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, factfield, interDesc);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, interName, method.getName(), "(" + requestDesc + responseDesc + ")V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "execute", "(" + requestSupDesc + responseSupDesc + ")V", null, new String[]{"java/io/IOException"});
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, HttpRequest.class.getName().replace('.', '/'));
mv.visitVarInsn(ALOAD, 2);
mv.visitTypeInsn(CHECKCAST, HttpResponse.class.getName().replace('.', '/'));
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "execute", "(" + requestDesc + responseDesc + ")V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
}
cw.visitEnd();
//------------------------------------------------------------------------------
byte[] bytes = cw.toByteArray();
Class<?> newClazz = new ClassLoader(this.getClass().getClassLoader()) {
public final Class<?> loadClass(String name, byte[] b) {
return defineClass(name, b, 0, b.length);
}
}.loadClass(newDynName.replace('/', '.'), bytes);
try {
HttpServlet instance = (HttpServlet) newClazz.newInstance();
instance.getClass().getField(factfield).set(instance, this);
return instance;
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
private static final class Entry {
public Entry(boolean typeIgnore, int moduleid, int actionid, String name, String[] methods, Method method, HttpServlet servlet) {
this.moduleid = moduleid;
this.actionid = actionid;
this.name = name;
this.methods = methods;
this.method = method;
this.servlet = servlet;
this.ignore = typeIgnore || method.getAnnotation(AuthIgnore.class) != null;
HttpCacheable hc = method.getAnnotation(HttpCacheable.class);
this.cachetimeout = hc == null ? 0 : hc.timeout() * 1000;
this.cache = cachetimeout > 0 ? new ConcurrentHashMap() : null;
this.cacheHandler = cachetimeout > 0 ? (HttpResponse response, ByteBuffer[] buffers) -> {
int status = response.getStatus();
if (status != 200) return null;
CacheEntry ce = new CacheEntry(response.getStatus(), response.getContentType(), buffers);
cache.put(response.getRequest().getRequestURI(), ce);
return ce.getBuffers();
} : null;
}
public boolean isNeedCheck() {
return this.moduleid != 0 || this.actionid != 0;
}
public boolean checkMethod(final String reqMethod) {
if (methods.length == 0) return true;
for (String m : methods) {
if (reqMethod.equalsIgnoreCase(m)) return true;
}
return false;
}
public final HttpResponse.BufferHandler cacheHandler;
public final ConcurrentHashMap<String, CacheEntry> cache;
public final int cachetimeout;
public final boolean ignore;
public final int moduleid;
public final int actionid;
public final String name;
public final String[] methods;
public final Method method;
public final HttpServlet servlet;
}
private static final class CacheEntry {
public final long time = System.currentTimeMillis();
private final ByteBuffer[] buffers;
private final int status;
private final String contentType;
public CacheEntry(int status, String contentType, ByteBuffer[] bufs) {
this.status = status;
this.contentType = contentType;
final ByteBuffer[] newBuffers = new ByteBuffer[bufs.length];
for (int i = 0; i < newBuffers.length; i++) {
newBuffers[i] = bufs[i].duplicate().asReadOnlyBuffer();
}
this.buffers = newBuffers;
}
public ByteBuffer[] getBuffers() {
final ByteBuffer[] newBuffers = new ByteBuffer[buffers.length];
for (int i = 0; i < newBuffers.length; i++) {
newBuffers[i] = buffers[i].duplicate();
}
return newBuffers;
}
}
}

View File

@@ -23,21 +23,23 @@ import org.redkale.watch.*;
* *
* @author zhangjx * @author zhangjx
*/ */
public final class HttpPrepareServlet extends PrepareServlet<String, HttpContext, HttpRequest, HttpResponse, HttpServlet> { public class HttpPrepareServlet extends PrepareServlet<String, HttpContext, HttpRequest, HttpResponse, HttpServlet> {
private SimpleEntry<Predicate<String>, HttpServlet>[] regArray = new SimpleEntry[0]; protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
private HttpServlet resourceHttpServlet = new HttpResourceServlet(); protected SimpleEntry<Predicate<String>, HttpServlet>[] regArray = new SimpleEntry[0];
private final Map<String, Class> mapStrings = new HashMap<>(); protected HttpServlet resourceHttpServlet = new HttpResourceServlet();
protected final Map<String, Class> allMapStrings = new HashMap<>();
@Override @Override
public void init(HttpContext context, AnyValue config) { public void init(HttpContext context, AnyValue config) {
this.servlets.forEach(s -> { this.servlets.forEach(s -> {
if (s instanceof WebSocketServlet) { if (s instanceof WebSocketServlet) {
((WebSocketServlet) s).preInit(context, getServletConf(s)); ((WebSocketServlet) s).preInit(context, getServletConf(s));
} else if (s instanceof BasedHttpServlet) { } else if (s instanceof HttpBaseServlet) {
((BasedHttpServlet) s).preInit(context, getServletConf(s)); ((HttpBaseServlet) s).preInit(context, getServletConf(s));
} }
s.init(context, getServletConf(s)); s.init(context, getServletConf(s));
}); });
@@ -47,31 +49,31 @@ public final class HttpPrepareServlet extends PrepareServlet<String, HttpContext
watch.inject(s); watch.inject(s);
}); });
} }
if (config != null) { AnyValue resConfig = config.getAnyValue("resource-servlet");
AnyValue ssConfig = config.getAnyValue("servlets"); if ((resConfig instanceof DefaultAnyValue) && resConfig.getValue("webroot", "").isEmpty()) {
AnyValue resConfig = null; ((DefaultAnyValue) resConfig).addValue("webroot", config.getValue("root"));
if (ssConfig != null) {
resConfig = ssConfig.getAnyValue("resource-servlet");
if ((resConfig instanceof DefaultAnyValue) && resConfig.getValue("webroot") == null) {
((DefaultAnyValue) resConfig).addValue("webroot", config.getValue("root"));
}
}
if (resConfig == null) resConfig = config.getAnyValue("resource-servlet"); //兼容
if (resConfig == null) {
DefaultAnyValue dresConfig = new DefaultAnyValue();
dresConfig.addValue("webroot", config.getValue("root"));
dresConfig.addValue("ranges", config.getValue("ranges"));
dresConfig.addValue("cache", config.getAnyValue("cache"));
AnyValue[] rewrites = config.getAnyValues("rewrite");
if (rewrites != null) {
for (AnyValue rewrite : rewrites) {
dresConfig.addValue("rewrite", rewrite);
}
}
resConfig = dresConfig;
}
this.resourceHttpServlet.init(context, resConfig);
} }
if (resConfig == null) { //主要用于嵌入式的HttpServer初始化
DefaultAnyValue dresConfig = new DefaultAnyValue();
dresConfig.addValue("webroot", config.getValue("root"));
dresConfig.addValue("ranges", config.getValue("ranges"));
dresConfig.addValue("cache", config.getAnyValue("cache"));
AnyValue[] rewrites = config.getAnyValues("rewrite");
if (rewrites != null) {
for (AnyValue rewrite : rewrites) {
dresConfig.addValue("rewrite", rewrite);
}
}
resConfig = dresConfig;
}
String resServlet = resConfig.getValue("servlet", HttpResourceServlet.class.getName());
try {
this.resourceHttpServlet = (HttpServlet) Class.forName(resServlet).newInstance();
} catch (Exception e) {
this.resourceHttpServlet = new HttpResourceServlet();
logger.log(Level.WARNING, "init HttpResourceSerlvet(" + resServlet + ") error", e);
}
this.resourceHttpServlet.init(context, resConfig);
} }
@Override @Override
@@ -102,17 +104,14 @@ public final class HttpPrepareServlet extends PrepareServlet<String, HttpContext
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class); WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
if (ws != null) { if (ws != null) {
mappings = ws.value(); mappings = ws.value();
if (!ws.repair()) prefix = "";//被设置为自动追加前缀则清空prefix if (!ws.repair()) prefix = "";//被设置为自动追加前缀则清空prefix
} }
} }
synchronized (mapStrings) { synchronized (allMapStrings) {
for (String mapping : mappings) { for (String mapping : mappings) {
if(mapping == null) continue; if (mapping == null) continue;
if (!prefix.toString().isEmpty()) mapping = prefix + mapping; if (!prefix.toString().isEmpty()) mapping = prefix + mapping;
if (this.mapStrings.containsKey(mapping)) {
Class old = this.mapStrings.get(mapping);
throw new RuntimeException("mapping [" + mapping + "] repeat on " + old.getName() + " and " + servlet.getClass().getName());
}
if (contains(mapping, '.', '*', '{', '[', '(', '|', '^', '$', '+', '?', '\\')) { //是否是正则表达式)) if (contains(mapping, '.', '*', '{', '[', '(', '|', '^', '$', '+', '?', '\\')) { //是否是正则表达式))
if (mapping.charAt(0) != '^') mapping = '^' + mapping; if (mapping.charAt(0) != '^') mapping = '^' + mapping;
if (mapping.endsWith("/*")) { if (mapping.endsWith("/*")) {
@@ -130,7 +129,11 @@ public final class HttpPrepareServlet extends PrepareServlet<String, HttpContext
} else if (mapping != null && !mapping.isEmpty()) { } else if (mapping != null && !mapping.isEmpty()) {
super.mappings.put(mapping, servlet); super.mappings.put(mapping, servlet);
} }
this.mapStrings.put(mapping, servlet.getClass()); if (this.allMapStrings.containsKey(mapping)) {
Class old = this.allMapStrings.get(mapping);
throw new RuntimeException("mapping [" + mapping + "] repeat on " + old.getName() + " and " + servlet.getClass().getName());
}
this.allMapStrings.put(mapping, servlet.getClass());
} }
setServletConf(servlet, conf); setServletConf(servlet, conf);
servlet._prefix = prefix.toString(); servlet._prefix = prefix.toString();
@@ -165,11 +168,11 @@ public final class HttpPrepareServlet extends PrepareServlet<String, HttpContext
s.destroy(context, getServletConf(s)); s.destroy(context, getServletConf(s));
if (s instanceof WebSocketServlet) { if (s instanceof WebSocketServlet) {
((WebSocketServlet) s).postDestroy(context, getServletConf(s)); ((WebSocketServlet) s).postDestroy(context, getServletConf(s));
} else if (s instanceof BasedHttpServlet) { } else if (s instanceof HttpBaseServlet) {
((BasedHttpServlet) s).postDestroy(context, getServletConf(s)); ((HttpBaseServlet) s).postDestroy(context, getServletConf(s));
} }
}); });
this.mapStrings.clear(); this.allMapStrings.clear();
} }
} }

View File

@@ -17,10 +17,10 @@ import org.redkale.util.ByteArray;
/** /**
* Http请求包 与javax.servlet.http.HttpServletRequest 基本类似。 <br> * Http请求包 与javax.servlet.http.HttpServletRequest 基本类似。 <br>
* 同时提供json的解析接口: public Object getJsonParameter(Class clazz, String name) <br> * 同时提供json的解析接口: public Object getJsonParameter(Type type, String name) <br>
* RedKale提倡带简单的参数的GET请求采用类似REST风格, 因此提供了 getRequstURIPath 系列接口。 <br> * Redkale提倡带简单的参数的GET请求采用类似REST风格, 因此提供了 getRequstURIPath 系列接口。 <br>
* 例如简单的翻页查询 <br> * 例如简单的翻页查询 <br>
* /pipes/record/query/offset:0/limit:20 <br> * /pipes/record/query/offset:0/limit:20 <br>
* 获取页号: int offset = request.getRequstURIPath("offset:", 0); <br> * 获取页号: int offset = request.getRequstURIPath("offset:", 0); <br>
* 获取行数: int limit = request.getRequstURIPath("limit:", 10); * 获取行数: int limit = request.getRequstURIPath("limit:", 10);
* <p> * <p>
@@ -312,6 +312,7 @@ public class HttpRequest extends Request<HttpContext> {
* 获取文件上传信息列表 * 获取文件上传信息列表
* *
* @return 文件上传对象集合 * @return 文件上传对象集合
*
* @throws IOException IO异常 * @throws IOException IO异常
*/ */
public final Iterable<MultiPart> multiParts() throws IOException { public final Iterable<MultiPart> multiParts() throws IOException {
@@ -544,11 +545,27 @@ public class HttpRequest extends Request<HttpContext> {
return val == null ? defvalue : Short.parseShort(val); return val == null ? defvalue : Short.parseShort(val);
} }
/**
* 获取请求URL分段中含prefix段的short值 <br>
* 例如请求URL /pipes/record/query/type:a <br>
* 获取type参数: short type = request.getRequstURIPath(16, "type:", (short)0); //type = 10
*
* @param radix 进制数
* @param prefix prefix段前缀
* @param defvalue 默认short值
*
* @return short值
*/
public short getRequstURIPath(int radix, String prefix, short defvalue) {
String val = getRequstURIPath(prefix, null);
return val == null ? defvalue : Short.parseShort(val, radix);
}
/** /**
* 获取请求URL分段中含prefix段的int值 <br> * 获取请求URL分段中含prefix段的int值 <br>
* 例如请求URL /pipes/record/query/offset:0/limit:50 <br> * 例如请求URL /pipes/record/query/offset:0/limit:50 <br>
* 获取起址参数: int offset = request.getRequstURIPath("offset:", 0); <br> * 获取offset参数: int offset = request.getRequstURIPath("offset:", 0); <br>
* 获取行数参数: int limit = request.getRequstURIPath("limit:", 20); <br> * 获取limit参数: int limit = request.getRequstURIPath("limit:", 20); <br>
* *
* @param prefix prefix段前缀 * @param prefix prefix段前缀
* @param defvalue 默认int值 * @param defvalue 默认int值
@@ -560,6 +577,23 @@ public class HttpRequest extends Request<HttpContext> {
return val == null ? defvalue : Integer.parseInt(val); return val == null ? defvalue : Integer.parseInt(val);
} }
/**
* 获取请求URL分段中含prefix段的int值 <br>
* 例如请求URL /pipes/record/query/offset:0/limit:50 <br>
* 获取offset参数: int offset = request.getRequstURIPath("offset:", 0); <br>
* 获取limit参数: int limit = request.getRequstURIPath(16, "limit:", 20); // limit = 16 <br>
*
* @param radix 进制数
* @param prefix prefix段前缀
* @param defvalue 默认int值
*
* @return int值
*/
public int getRequstURIPath(int radix, String prefix, int defvalue) {
String val = getRequstURIPath(prefix, null);
return val == null ? defvalue : Integer.parseInt(val, radix);
}
/** /**
* 获取请求URL分段中含prefix段的float值 <br> * 获取请求URL分段中含prefix段的float值 <br>
* 例如请求URL /pipes/record/query/point:40.0 <br> * 例如请求URL /pipes/record/query/point:40.0 <br>
@@ -590,6 +624,22 @@ public class HttpRequest extends Request<HttpContext> {
return val == null ? defvalue : Long.parseLong(val); return val == null ? defvalue : Long.parseLong(val);
} }
/**
* 获取请求URL分段中含prefix段的long值 <br>
* 例如请求URL /pipes/record/query/time:1453104341363/id:40 <br>
* 获取time参数: long time = request.getRequstURIPath(16, "time:", 0L);
*
* @param radix 进制数
* @param prefix prefix段前缀
* @param defvalue 默认long值
*
* @return long值
*/
public long getRequstURIPath(int radix, String prefix, long defvalue) {
String val = getRequstURIPath(prefix, null);
return val == null ? defvalue : Long.parseLong(val, radix);
}
/** /**
* 获取请求URL分段中含prefix段的double值 <br> * 获取请求URL分段中含prefix段的double值 <br>
* 例如请求URL /pipes/record/query/point:40.0 <br> * 例如请求URL /pipes/record/query/point:40.0 <br>
@@ -641,15 +691,15 @@ public class HttpRequest extends Request<HttpContext> {
/** /**
* 获取指定的header的json值 * 获取指定的header的json值
* *
* @param <T> 泛型 * @param <T> 泛型
* @param clazz 反序列化的类名 * @param type 反序列化的类名
* @param name header名 * @param name header名
* *
* @return header值 * @return header值
*/ */
public <T> T getJsonHeader(Class<T> clazz, String name) { public <T> T getJsonHeader(java.lang.reflect.Type type, String name) {
String v = getHeader(name); String v = getHeader(name);
return v == null || v.isEmpty() ? null : jsonConvert.convertFrom(clazz, v); return v == null || v.isEmpty() ? null : jsonConvert.convertFrom(type, v);
} }
/** /**
@@ -657,14 +707,14 @@ public class HttpRequest extends Request<HttpContext> {
* *
* @param <T> 泛型 * @param <T> 泛型
* @param convert JsonConvert对象 * @param convert JsonConvert对象
* @param clazz 反序列化的类名 * @param type 反序列化的类名
* @param name header名 * @param name header名
* *
* @return header值 * @return header值
*/ */
public <T> T getJsonHeader(JsonConvert convert, Class<T> clazz, String name) { public <T> T getJsonHeader(JsonConvert convert, java.lang.reflect.Type type, String name) {
String v = getHeader(name); String v = getHeader(name);
return v == null || v.isEmpty() ? null : convert.convertFrom(clazz, v); return v == null || v.isEmpty() ? null : convert.convertFrom(type, v);
} }
/** /**
@@ -691,6 +741,19 @@ public class HttpRequest extends Request<HttpContext> {
return header.getShortValue(name, defaultValue); return header.getShortValue(name, defaultValue);
} }
/**
* 获取指定的header的short值, 没有返回默认short值
*
* @param radix 进制数
* @param name header名
* @param defaultValue 默认short值
*
* @return header值
*/
public short getShortHeader(int radix, String name, short defaultValue) {
return header.getShortValue(name, defaultValue);
}
/** /**
* 获取指定的header的short值, 没有返回默认short值 * 获取指定的header的short值, 没有返回默认short值
* *
@@ -703,6 +766,19 @@ public class HttpRequest extends Request<HttpContext> {
return header.getShortValue(name, (short) defaultValue); return header.getShortValue(name, (short) defaultValue);
} }
/**
* 获取指定的header的short值, 没有返回默认short值
*
* @param radix 进制数
* @param name header名
* @param defaultValue 默认short值
*
* @return header值
*/
public short getShortHeader(int radix, String name, int defaultValue) {
return header.getShortValue(radix, name, (short) defaultValue);
}
/** /**
* 获取指定的header的int值, 没有返回默认int值 * 获取指定的header的int值, 没有返回默认int值
* *
@@ -715,6 +791,19 @@ public class HttpRequest extends Request<HttpContext> {
return header.getIntValue(name, defaultValue); return header.getIntValue(name, defaultValue);
} }
/**
* 获取指定的header的int值, 没有返回默认int值
*
* @param radix 进制数
* @param name header名
* @param defaultValue 默认int值
*
* @return header值
*/
public int getIntHeader(int radix, String name, int defaultValue) {
return header.getIntValue(radix, name, defaultValue);
}
/** /**
* 获取指定的header的long值, 没有返回默认long值 * 获取指定的header的long值, 没有返回默认long值
* *
@@ -727,6 +816,19 @@ public class HttpRequest extends Request<HttpContext> {
return header.getLongValue(name, defaultValue); return header.getLongValue(name, defaultValue);
} }
/**
* 获取指定的header的long值, 没有返回默认long值
*
* @param radix 进制数
* @param name header名
* @param defaultValue 默认long值
*
* @return header值
*/
public long getLongHeader(int radix, String name, long defaultValue) {
return header.getLongValue(radix, name, defaultValue);
}
/** /**
* 获取指定的header的float值, 没有返回默认float值 * 获取指定的header的float值, 没有返回默认float值
* *
@@ -790,15 +892,15 @@ public class HttpRequest extends Request<HttpContext> {
/** /**
* 获取指定的参数json值 * 获取指定的参数json值
* *
* @param <T> 泛型 * @param <T> 泛型
* @param clazz 反序列化的类名 * @param type 反序列化的类名
* @param name 参数名 * @param name 参数名
* *
* @return 参数值 * @return 参数值
*/ */
public <T> T getJsonParameter(Class<T> clazz, String name) { public <T> T getJsonParameter(java.lang.reflect.Type type, String name) {
String v = getParameter(name); String v = getParameter(name);
return v == null || v.isEmpty() ? null : jsonConvert.convertFrom(clazz, v); return v == null || v.isEmpty() ? null : jsonConvert.convertFrom(type, v);
} }
/** /**
@@ -806,14 +908,14 @@ public class HttpRequest extends Request<HttpContext> {
* *
* @param <T> 泛型 * @param <T> 泛型
* @param convert JsonConvert对象 * @param convert JsonConvert对象
* @param clazz 反序列化的类名 * @param type 反序列化的类名
* @param name 参数名 * @param name 参数名
* *
* @return 参数值 * @return 参数值
*/ */
public <T> T getJsonParameter(JsonConvert convert, Class<T> clazz, String name) { public <T> T getJsonParameter(JsonConvert convert, java.lang.reflect.Type type, String name) {
String v = getParameter(name); String v = getParameter(name);
return v == null || v.isEmpty() ? null : convert.convertFrom(clazz, v); return v == null || v.isEmpty() ? null : convert.convertFrom(type, v);
} }
/** /**
@@ -842,6 +944,20 @@ public class HttpRequest extends Request<HttpContext> {
return params.getShortValue(name, defaultValue); return params.getShortValue(name, defaultValue);
} }
/**
* 获取指定的参数short值, 没有返回默认short值
*
* @param radix 进制数
* @param name 参数名
* @param defaultValue 默认short值
*
* @return 参数值
*/
public short getShortParameter(int radix, String name, short defaultValue) {
parseBody();
return params.getShortValue(radix, name, defaultValue);
}
/** /**
* 获取指定的参数short值, 没有返回默认short值 * 获取指定的参数short值, 没有返回默认short值
* *
@@ -868,6 +984,20 @@ public class HttpRequest extends Request<HttpContext> {
return params.getIntValue(name, defaultValue); return params.getIntValue(name, defaultValue);
} }
/**
* 获取指定的参数int值, 没有返回默认int值
*
* @param radix 进制数
* @param name 参数名
* @param defaultValue 默认int值
*
* @return 参数值
*/
public int getIntParameter(int radix, String name, int defaultValue) {
parseBody();
return params.getIntValue(radix, name, defaultValue);
}
/** /**
* 获取指定的参数long值, 没有返回默认long值 * 获取指定的参数long值, 没有返回默认long值
* *
@@ -881,6 +1011,20 @@ public class HttpRequest extends Request<HttpContext> {
return params.getLongValue(name, defaultValue); return params.getLongValue(name, defaultValue);
} }
/**
* 获取指定的参数long值, 没有返回默认long值
*
* @param radix 进制数
* @param name 参数名
* @param defaultValue 默认long值
*
* @return 参数值
*/
public long getLongParameter(int radix, String name, long defaultValue) {
parseBody();
return params.getLongValue(radix, name, defaultValue);
}
/** /**
* 获取指定的参数float值, 没有返回默认float值 * 获取指定的参数float值, 没有返回默认float值
* *

View File

@@ -13,7 +13,6 @@ import java.util.AbstractMap.SimpleEntry;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.LongAdder; import java.util.concurrent.atomic.LongAdder;
import java.util.function.Predicate;
import java.util.logging.*; import java.util.logging.*;
import java.util.regex.*; import java.util.regex.*;
import org.redkale.util.AnyValue; import org.redkale.util.AnyValue;
@@ -25,9 +24,9 @@ import org.redkale.util.AnyValue;
* *
* @author zhangjx * @author zhangjx
*/ */
public final class HttpResourceServlet extends HttpServlet { public class HttpResourceServlet extends HttpServlet {
private static final Logger logger = Logger.getLogger(HttpResourceServlet.class.getSimpleName()); protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
protected class WatchThread extends Thread { protected class WatchThread extends Thread {
@@ -37,7 +36,7 @@ public final class HttpResourceServlet extends HttpServlet {
public WatchThread(File root) throws IOException { public WatchThread(File root) throws IOException {
this.root = root; this.root = root;
this.setName("Servlet-ResourceWatch-Thread"); this.setName("HttpResourceServlet-Watch-Thread");
this.setDaemon(true); this.setDaemon(true);
this.watcher = this.root.toPath().getFileSystem().newWatchService(); this.watcher = this.root.toPath().getFileSystem().newWatchService();
} }
@@ -62,8 +61,13 @@ public final class HttpResourceServlet extends HttpServlet {
files.remove(uri); files.remove(uri);
} else if (event.kind() == ENTRY_MODIFY) { } else if (event.kind() == ENTRY_MODIFY) {
FileEntry en = files.get(uri); FileEntry en = files.get(uri);
if (en != null) { if (en != null && en.file != null) {
Thread.sleep(5000L); //等待update file完毕 long d; //等待update file完毕
for (;;) {
d = en.file.lastModified();
Thread.sleep(2000L);
if (d == en.file.lastModified()) break;
}
en.update(); en.update();
} }
} }
@@ -81,16 +85,16 @@ public final class HttpResourceServlet extends HttpServlet {
protected final boolean finest = logger.isLoggable(Level.FINEST); protected final boolean finest = logger.isLoggable(Level.FINEST);
protected final LongAdder cachedLength = new LongAdder(); protected final LongAdder cachedLength = new LongAdder();
//缓存总大小, 默认0 //缓存总大小, 默认0
protected long cachelimit = 0 * 1024 * 1024L; protected long cachelimit = 0 * 1024 * 1024L;
//最大可缓存的文件大小, 大于该值的文件将不被缓存 //最大可缓存的文件大小, 大于该值的文件将不被缓存
protected long cachelengthmax = 1 * 1024 * 1024; protected long cachelengthmax = 1 * 1024 * 1024;
//是否监控缓存文件的变化, 默认不监控 //是否监控缓存文件的变化, 默认不监控
protected boolean watch = false; protected boolean watch = false;
protected File root = new File("./root/"); protected File root = new File("./root/");
protected String indexHtml = "index.html"; protected String indexHtml = "index.html";
@@ -103,8 +107,6 @@ public final class HttpResourceServlet extends HttpServlet {
protected WatchThread watchThread; protected WatchThread watchThread;
protected Predicate<String> ranges;
@Override @Override
public void init(HttpContext context, AnyValue config) { public void init(HttpContext context, AnyValue config) {
if (config != null) { if (config != null) {
@@ -113,15 +115,12 @@ public final class HttpResourceServlet extends HttpServlet {
if (rootstr.indexOf(':') < 0 && rootstr.indexOf('/') != 0 && System.getProperty("APP_HOME") != null) { if (rootstr.indexOf(':') < 0 && rootstr.indexOf('/') != 0 && System.getProperty("APP_HOME") != null) {
rootstr = new File(System.getProperty("APP_HOME"), rootstr).getPath(); rootstr = new File(System.getProperty("APP_HOME"), rootstr).getPath();
} }
String rangesValue = config.getValue("ranges");
this.ranges = rangesValue != null ? Pattern.compile(rangesValue).asPredicate() : null;
try { try {
this.root = new File(rootstr).getCanonicalFile(); this.root = new File(rootstr).getCanonicalFile();
} catch (IOException ioe) { } catch (IOException ioe) {
this.root = new File(rootstr); this.root = new File(rootstr);
} }
AnyValue cacheconf = config.getAnyValue("cache"); AnyValue cacheconf = config.getAnyValue("cache");
if (cacheconf == null) cacheconf = config.getAnyValue("caches"); //兼容旧参数
if (cacheconf != null) { if (cacheconf != null) {
this.cachelimit = parseLenth(cacheconf.getValue("limit"), 0 * 1024 * 1024L); this.cachelimit = parseLenth(cacheconf.getValue("limit"), 0 * 1024 * 1024L);
this.cachelengthmax = parseLenth(cacheconf.getValue("lengthmax"), 1 * 1024 * 1024L); this.cachelengthmax = parseLenth(cacheconf.getValue("lengthmax"), 1 * 1024 * 1024L);
@@ -162,7 +161,7 @@ public final class HttpResourceServlet extends HttpServlet {
} }
} }
private static long parseLenth(String value, long defValue) { protected static long parseLenth(String value, long defValue) {
if (value == null) return defValue; if (value == null) return defValue;
value = value.toUpperCase().replace("B", ""); value = value.toUpperCase().replace("B", "");
if (value.endsWith("G")) return Long.decode(value.replace("G", "")) * 1024 * 1024 * 1024; if (value.endsWith("G")) return Long.decode(value.replace("G", "")) * 1024 * 1024 * 1024;
@@ -191,7 +190,7 @@ public final class HttpResourceServlet extends HttpServlet {
} }
//System.out.println(request); //System.out.println(request);
FileEntry entry; FileEntry entry;
if (watchThread == null) { if (watchThread == null && files.isEmpty()) {
entry = createFileEntry(uri); entry = createFileEntry(uri);
} else { //有缓存 } else { //有缓存
entry = files.computeIfAbsent(uri, x -> createFileEntry(x)); entry = files.computeIfAbsent(uri, x -> createFileEntry(x));
@@ -200,11 +199,13 @@ public final class HttpResourceServlet extends HttpServlet {
if (finest) logger.log(Level.FINEST, "Not found resource (404), request = " + request); if (finest) logger.log(Level.FINEST, "Not found resource (404), request = " + request);
response.finish404(); response.finish404();
} else { } else {
response.finishFile(entry.file, entry.content); //file = null 表示资源内容在内存而不是在File中
//file = null 时必须传 filename
response.finishFile(entry.file == null ? entry.filename : null, entry.file, entry.content);
} }
} }
private FileEntry createFileEntry(String uri) { protected FileEntry createFileEntry(String uri) {
File rfile = new File(root, uri); File rfile = new File(root, uri);
File file = rfile; File file = rfile;
if (file.isDirectory()) file = new File(rfile, this.indexHtml); if (file.isDirectory()) file = new File(rfile, this.indexHtml);
@@ -221,22 +222,53 @@ public final class HttpResourceServlet extends HttpServlet {
return en; return en;
} }
private static final class FileEntry { protected static class FileEntry {
final File file; protected final String filename;
private final HttpResourceServlet servlet; protected final File file; //如果所有资源文件打包成zip文件则file=null
ByteBuffer content; protected final HttpResourceServlet servlet;
protected ByteBuffer content;
public FileEntry(final HttpResourceServlet servlet, File file) { public FileEntry(final HttpResourceServlet servlet, File file) {
this.servlet = servlet; this.servlet = servlet;
this.file = file; this.file = file;
this.filename = file.getName();
update(); update();
} }
public FileEntry(final HttpResourceServlet servlet, String filename, ByteBuffer content) {
this.servlet = servlet;
this.file = null;
this.filename = filename;
this.content = content.asReadOnlyBuffer();
this.servlet.cachedLength.add(this.content.remaining());
}
public FileEntry(final HttpResourceServlet servlet, String filename, InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] bytes = new byte[10240];
int pos;
while ((pos = in.read(bytes)) != -1) {
out.write(bytes, 0, pos);
}
byte[] bs = out.toByteArray();
ByteBuffer buf = ByteBuffer.allocateDirect(bs.length);
buf.put(bs);
buf.flip();
this.servlet = servlet;
this.file = null;
this.filename = filename;
this.content = buf.asReadOnlyBuffer();
this.servlet.cachedLength.add(this.content.remaining());
}
public void update() { public void update() {
if (this.content != null) { if (this.file == null) return;
if (this.content != null) {
this.servlet.cachedLength.add(0L - this.content.remaining()); this.servlet.cachedLength.add(0L - this.content.remaining());
this.content = null; this.content = null;
} }
@@ -259,7 +291,7 @@ public final class HttpResourceServlet extends HttpServlet {
this.content = buf.asReadOnlyBuffer(); this.content = buf.asReadOnlyBuffer();
this.servlet.cachedLength.add(this.content.remaining()); this.servlet.cachedLength.add(this.content.remaining());
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.INFO, HttpResourceServlet.class.getSimpleName() + " update FileEntry(" + file + ") erroneous", e); this.servlet.logger.log(Level.INFO, HttpResourceServlet.class.getSimpleName() + " update FileEntry(" + file + ") erroneous", e);
} }
} }

View File

@@ -23,7 +23,7 @@ import org.redkale.util.*;
/** /**
* Http响应包 与javax.servlet.http.HttpServletResponse 基本类似。 * Http响应包 与javax.servlet.http.HttpServletResponse 基本类似。
* 同时提供发送json的系列接口: public void finishJson(Type type, Object obj) * 同时提供发送json的系列接口: public void finishJson(Type type, Object obj)
* RedKale提倡http+json的接口风格 所以主要输出的数据格式为json 同时提供异步接口。 * Redkale提倡http+json的接口风格 所以主要输出的数据格式为json 同时提供异步接口。
* <p> * <p>
* 详情见: http://redkale.org * 详情见: http://redkale.org
* *
@@ -195,6 +195,29 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
return this; return this;
} }
/**
* 增加Cookie值
*
* @param cookies cookie
*
* @return HttpResponse
*/
public HttpResponse addCookie(Collection<HttpCookie> cookies) {
if (cookies == null || cookies.isEmpty()) return this;
if (this.cookies == null) {
this.cookies = cookies.toArray(new HttpCookie[cookies.size()]);
} else {
HttpCookie[] news = new HttpCookie[this.cookies.length + cookies.size()];
System.arraycopy(this.cookies, 0, news, 0, this.cookies.length);
int i = this.cookies.length;
for (HttpCookie cookie : cookies) {
news[i++] = cookie;
}
this.cookies = news;
}
return this;
}
/** /**
* 将对象以JSON格式输出 * 将对象以JSON格式输出
* *
@@ -258,7 +281,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
this.contentType = "text/plain; charset=utf-8"; this.contentType = "text/plain; charset=utf-8";
if (ret != null && !ret.isSuccess()) { if (ret != null && !ret.isSuccess()) {
this.header.addValue("retcode", String.valueOf(ret.getRetcode())); this.header.addValue("retcode", String.valueOf(ret.getRetcode()));
this.header.addValue("retcode", ret.getRetinfo()); this.header.addValue("retinfo", ret.getRetinfo());
} }
finish(request.getJsonConvert().convertTo(context.getBufferSupplier(), ret)); finish(request.getJsonConvert().convertTo(context.getBufferSupplier(), ret));
} }
@@ -273,7 +296,7 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
this.contentType = "text/plain; charset=utf-8"; this.contentType = "text/plain; charset=utf-8";
if (ret != null && !ret.isSuccess()) { if (ret != null && !ret.isSuccess()) {
this.header.addValue("retcode", String.valueOf(ret.getRetcode())); this.header.addValue("retcode", String.valueOf(ret.getRetcode()));
this.header.addValue("retcode", ret.getRetinfo()); this.header.addValue("retinfo", ret.getRetinfo());
} }
finish(convert.convertTo(context.getBufferSupplier(), ret)); finish(convert.convertTo(context.getBufferSupplier(), ret));
} }
@@ -502,6 +525,8 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
/** /**
* 将指定文件句柄或文件内容按指定文件名输出若fileBody不为null则只输出fileBody内容 * 将指定文件句柄或文件内容按指定文件名输出若fileBody不为null则只输出fileBody内容
* file 与 fileBody 不能同时为空
* file 与 filename 也不能同时为空
* *
* @param filename 输出文件名 * @param filename 输出文件名
* @param file 输出文件 * @param file 输出文件
@@ -510,19 +535,20 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
* @throws IOException IO异常 * @throws IOException IO异常
*/ */
protected void finishFile(final String filename, final File file, ByteBuffer fileBody) throws IOException { protected void finishFile(final String filename, final File file, ByteBuffer fileBody) throws IOException {
if (file == null || !file.isFile() || !file.canRead()) { if ((file == null || !file.isFile() || !file.canRead()) && fileBody == null) {
finish404(); finish404();
return; return;
} }
if (fileBody != null) fileBody = fileBody.duplicate().asReadOnlyBuffer(); if (fileBody != null) fileBody = fileBody.duplicate().asReadOnlyBuffer();
final long length = file.length(); final long length = file == null ? fileBody.remaining() : file.length();
final String match = request.getHeader("If-None-Match"); final String match = request.getHeader("If-None-Match");
if (match != null && (file.lastModified() + "-" + length).equals(match)) { final String etag = (file == null ? 0L : file.lastModified()) + "-" + length;
if (match != null && etag.equals(match)) {
finish304(); finish304();
return; return;
} }
this.contentLength = fileBody == null ? file.length() : fileBody.remaining(); this.contentLength = length;
if (filename != null && !filename.isEmpty()) { if (filename != null && !filename.isEmpty() && file != null) {
addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
} }
this.contentType = MimeType.getByFilename(filename == null || filename.isEmpty() ? file.getName() : filename); this.contentType = MimeType.getByFilename(filename == null || filename.isEmpty() ? file.getName() : filename);
@@ -536,14 +562,14 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
int pos = range.indexOf('-'); int pos = range.indexOf('-');
start = pos == 0 ? 0 : Integer.parseInt(range.substring(0, pos)); start = pos == 0 ? 0 : Integer.parseInt(range.substring(0, pos));
long end = (pos == range.length() - 1) ? -1 : Long.parseLong(range.substring(pos + 1)); long end = (pos == range.length() - 1) ? -1 : Long.parseLong(range.substring(pos + 1));
long clen = end > 0 ? (end - start + 1) : (file.length() - start); long clen = end > 0 ? (end - start + 1) : (length - start);
this.status = 206; this.status = 206;
addHeader("Accept-Ranges", "bytes"); addHeader("Accept-Ranges", "bytes");
addHeader("Content-Range", "bytes " + start + "-" + (end > 0 ? end : length - 1) + "/" + length); addHeader("Content-Range", "bytes " + start + "-" + (end > 0 ? end : length - 1) + "/" + length);
this.contentLength = clen; this.contentLength = clen;
len = end > 0 ? clen : end; len = end > 0 ? clen : end;
} }
this.addHeader("ETag", file.lastModified() + "-" + length); this.addHeader("ETag", etag);
ByteBuffer hbuffer = createHeader(); ByteBuffer hbuffer = createHeader();
hbuffer.flip(); hbuffer.flip();
if (fileBody == null) { if (fileBody == null) {
@@ -690,6 +716,21 @@ public class HttpResponse extends Response<HttpContext, HttpRequest> {
return this; return this;
} }
/**
* 添加Header值
*
* @param map header值
*
* @return HttpResponse
*/
public HttpResponse addHeader(Map<String, ?> map) {
if (map == null || map.isEmpty()) return this;
for (Map.Entry<String, ?> en : map.entrySet()) {
this.header.addValue(en.getKey(), String.valueOf(en.getValue()));
}
return this;
}
/** /**
* 设置状态码 * 设置状态码
* *

View File

@@ -5,11 +5,13 @@
*/ */
package org.redkale.net.http; package org.redkale.net.http;
import java.lang.reflect.Field;
import java.net.HttpCookie; import java.net.HttpCookie;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import org.redkale.net.*; import org.redkale.net.*;
import org.redkale.service.Service;
import org.redkale.util.*; import org.redkale.util.*;
import org.redkale.watch.WatchFactory; import org.redkale.watch.WatchFactory;
@@ -35,10 +37,69 @@ public final class HttpServer extends Server<String, HttpContext, HttpRequest, H
super.init(config); super.init(config);
} }
public HttpServer addHttpServlet(String prefix, HttpServlet servlet, String... mappings) {
this.prepare.addServlet(servlet, prefix, null, mappings);
return this;
}
public HttpServer addHttpServlet(HttpServlet servlet, String... mappings) {
this.prepare.addServlet(servlet, null, null, mappings);
return this;
}
public void addHttpServlet(HttpServlet servlet, final String prefix, AnyValue conf, String... mappings) { public void addHttpServlet(HttpServlet servlet, final String prefix, AnyValue conf, String... mappings) {
this.prepare.addServlet(servlet, prefix, conf, mappings); this.prepare.addServlet(servlet, prefix, conf, mappings);
} }
public <S extends Service, T extends RestHttpServlet> RestHttpServlet addRestServlet(String name, Class<S> serviceType, S service, Class<T> baseServletClass, String prefix) {
return addRestServlet(name, serviceType, service, baseServletClass, prefix, null);
}
public <S extends Service, T extends RestHttpServlet> RestHttpServlet addRestServlet(
final String name, Class<S> serviceType, final S service, final Class<T> baseServletClass, final String prefix, AnyValue conf) {
RestHttpServlet servlet = null;
for (final HttpServlet item : ((HttpPrepareServlet) this.prepare).getServlets()) {
if (!(item instanceof RestHttpServlet)) continue;
if (item.getClass().getAnnotation(Rest.RestDynamic.class) == null) continue;
try {
Field field = item.getClass().getDeclaredField(Rest.REST_SERVICE_FIELD_NAME);
if (serviceType.equals(field.getType())) {
servlet = (RestHttpServlet) item;
break;
}
} catch (NoSuchFieldException | SecurityException e) {
System.err.println("serviceType = " + serviceType + ", servletClass = " + item.getClass());
e.printStackTrace();
}
}
final boolean first = servlet == null;
if (servlet == null) servlet = Rest.createRestServlet(baseServletClass, serviceType);
try { //若提供动态变更Service服务功能则改Rest服务无法做出相应更新
Field field = servlet.getClass().getDeclaredField(Rest.REST_SERVICE_FIELD_NAME);
field.setAccessible(true);
Field mapfield = servlet.getClass().getDeclaredField(Rest.REST_SERVICEMAP_FIELD_NAME);
mapfield.setAccessible(true);
Service firstService = (Service) field.get(servlet);
if (name.isEmpty()) {
field.set(servlet, service);
firstService = service;
}
Map map = (Map) mapfield.get(servlet);
if (map == null && !name.isEmpty()) map = new HashMap();
if (map != null) {
map.put(name, service);
if (firstService != null) map.put("", firstService);
}
mapfield.set(servlet, map);
} catch (Exception e) {
throw new RuntimeException(serviceType + " generate rest servlet error", e);
}
if (first) this.prepare.addServlet(servlet, prefix, conf);
return servlet;
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected HttpContext createContext() { protected HttpContext createContext() {

View File

@@ -18,14 +18,4 @@ public abstract class HttpServlet extends Servlet<HttpContext, HttpRequest, Http
String _prefix = ""; //当前HttpServlet的path前缀 String _prefix = ""; //当前HttpServlet的path前缀
@Override
public final boolean equals(Object obj) {
return this == obj;
}
@Override
public final int hashCode() {
return super.hashCode();
}
} }

View File

@@ -9,7 +9,9 @@ import java.util.*;
/** /**
* *
* <p> 详情见: http://redkale.org * <p>
* 详情见: http://redkale.org
*
* @author zhangjx * @author zhangjx
*/ */
public class MimeType { public class MimeType {
@@ -172,20 +174,20 @@ public class MimeType {
} }
public static String get(String extension) { public static String get(String extension) {
return contentTypes.getOrDefault(extension, "text/plain"); return contentTypes.getOrDefault(extension.toLowerCase(), "text/plain");
} }
public static String get(String extension, String defaultCt) { public static String get(String extension, String defaultCt) {
return contentTypes.getOrDefault(extension, defaultCt); return contentTypes.getOrDefault(extension.toLowerCase(), defaultCt);
} }
public static boolean contains(String extension) { public static boolean contains(String extension) {
return contentTypes.containsKey(extension); return contentTypes.containsKey(extension.toLowerCase());
} }
public static void add(String extension, String contentType) { public static void add(String extension, String contentType) {
if (extension != null && extension.length() != 0 && contentType != null && contentType.length() != 0) { if (extension != null && extension.length() != 0 && contentType != null && contentType.length() != 0) {
contentTypes.put(extension, contentType); contentTypes.put(extension.toLowerCase(), contentType);
} }
} }
@@ -194,7 +196,7 @@ public class MimeType {
int newEnd = fileName.lastIndexOf('#'); int newEnd = fileName.lastIndexOf('#');
if (newEnd == -1) newEnd = length; if (newEnd == -1) newEnd = length;
int i = fileName.lastIndexOf('.', newEnd); int i = fileName.lastIndexOf('.', newEnd);
return (i < 0) ? null : get(fileName.substring(i + 1, newEnd)); return (i < 0) ? null : get(fileName.substring(i + 1, newEnd).toLowerCase());
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
/*
* 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.net.http;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 只能注解于Service类的方法的String参数或参数内的String字段
* <p>
* 用于获取HTTP请求端的IP地址 HttpRequest.getRemoteAddr
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({PARAMETER, FIELD})
@Retention(RUNTIME)
public @interface RestAddress {
}

View File

@@ -0,0 +1,30 @@
/*
* 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.net.http;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 只能注解于Service类的方法的String参数或参数内的String字段
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({PARAMETER, FIELD})
@Retention(RUNTIME)
public @interface RestCookie {
String name(); //cookie名
int radix() default 10; //转换数字byte/short/int/long时所用的进制数 默认10进制
String comment() default ""; //备注描述
}

View File

@@ -0,0 +1,30 @@
/*
* 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.net.http;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 只能注解于Service类的方法的参数或参数内的String字段
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({PARAMETER, FIELD})
@Retention(RUNTIME)
public @interface RestHeader {
String name(); //参数名
int radix() default 10; //转换数字byte/short/int/long时所用的进制数 默认10进制
String comment() default ""; //备注描述
}

View File

@@ -0,0 +1,49 @@
/*
* 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.net.http;
import java.io.IOException;
import org.redkale.util.Attribute;
/**
*
* 详情见: http://redkale.org
*
* @author zhangjx
* @param <T> 当前用户对象类型
*/
public abstract class RestHttpServlet<T> extends HttpBaseServlet {
protected abstract T currentUser(HttpRequest req) throws IOException;
protected void finishJson(final HttpResponse response, RestOutput output) throws IOException {
if (output != null) {
response.addHeader(output.getHeaders());
response.addCookie(output.getCookies());
}
response.finishJson(output == null ? null : output.getResult());
}
protected void finishJsResult(final HttpResponse response, final String var, RestOutput output) throws IOException {
if (output != null) {
response.addHeader(output.getHeaders());
response.addCookie(output.getCookies());
}
response.finishJsResult(var, output == null ? null : output.getResult());
}
Attribute[] _paramAttrs; // 为null表示无DynCall处理index=0固定为null, 其他为参数标记的DynCall回调方法
protected void _callParameter(final HttpResponse response, final Object... params) {
if (_paramAttrs == null) return;
for (int i = 1; i < _paramAttrs.length; i++) {
org.redkale.util.Attribute attr = _paramAttrs[i];
if (attr == null) continue;
//convert.convertTo(out, attr.type(), attr.get(params[i - 1]));
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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.net.http;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
/**
* 只能依附在Service实现类的public方法上
* value默认为"/" + Service的类名去掉Service字样的小写字符串 (如HelloService的默认路径为/hello)。
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({METHOD})
@Retention(RUNTIME)
@Repeatable(RestMappings.class)
public @interface RestMapping {
boolean ignore() default false; //是否屏蔽该方法的转换
/**
* 请求的方法名, 不能含特殊字符
* 默认为方法名的小写(若方法名以createXXX、updateXXX、deleteXXX、queryXXX、findXXX且XXXService为Service的类名将只截取XXX之前)
*
* @return name
*/
String name() default "";
String comment() default ""; //备注描述, 对应&#64;WebAction.comment
boolean auth() default false; //是否鉴权,默认不鉴权, 对应&#64;AuthIgnore
int actionid() default 0; //操作ID值鉴权时用到, 对应&#64;WebAction.actionid
int cachetimeout() default 0; // 结果缓存的秒数, 为0表示不缓存, 对应&#64;HttpCacheable.timeout
String[] methods() default {};//允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法, 对应&#64;WebAction.methods
//String contentType() default ""; //设置Response的ContentType 默认值为 text/plain; charset=utf-8
String jsvar() default ""; //以application/javascript输出对象是指明js的对象名该值存在时则忽略contentType()的值
}

View File

@@ -0,0 +1,26 @@
/*
* 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.net.http;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
/**
* RestMapping 的多用类
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({METHOD})
@Retention(RUNTIME)
public @interface RestMappings {
RestMapping[] value();
}

View File

@@ -0,0 +1,69 @@
/*
* 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.net.http;
import java.io.Serializable;
import java.net.HttpCookie;
import java.util.*;
/**
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
* @param <T> 结果对象的类型
*/
public class RestOutput<T> {
private Map<String, String> headers;
private List<HttpCookie> cookies;
private T result;
public RestOutput() {
}
public RestOutput(T result) {
this.result = result;
}
public void addHeader(String name, Serializable value) {
if (this.headers == null) this.headers = new HashMap<>();
this.headers.put(name, String.valueOf(value));
}
public void addCookie(HttpCookie cookie) {
if (this.cookies == null) this.cookies = new ArrayList<>();
this.cookies.add(cookie);
}
public Map<String, String> getHeaders() {
return headers;
}
public void setHeaders(Map<String, String> headers) {
this.headers = headers;
}
public List<HttpCookie> getCookies() {
return cookies;
}
public void setCookies(List<HttpCookie> cookies) {
this.cookies = cookies;
}
public T getResult() {
return result;
}
public void setResult(T result) {
this.result = result;
}
}

View File

@@ -0,0 +1,32 @@
/*
* 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.net.http;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 只能依附在Service类的方法的参数上, name值不能是'&#38;'
* name='#'表示截取uri最后一段
* name='#xxx:'表示从uri中/pipes/xxx:v/截取xxx:的值
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({PARAMETER})
@Retention(RUNTIME)
public @interface RestParam {
String name(); //参数名
int radix() default 10; //转换数字byte/short/int/long时所用的进制数 默认10进制
String comment() default ""; //备注描述
}

View File

@@ -0,0 +1,59 @@
/*
* 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.net.http;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 只能依附在Service类上name默认为Service的类名小写并去掉Service字样及后面的字符串 (如HelloService/HelloServiceImpl的默认路径为 hello)。
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({TYPE})
@Retention(RUNTIME)
public @interface RestService {
/**
* 模块名, 只能是模块名,不能含特殊字符, 只能小写字母+数字,且不能以数字开头
*
* @return 模块名
*/
String name() default "";
/**
* 模块ID值鉴权时用到, 对应&#64;WebServlet.moduleid
*
* @return 模块ID值
*/
int moduleid() default 0;
/**
* 是否屏蔽该类的转换
*
* @return 默认false
*/
boolean ignore() default false;
/**
* 同&#64;WebServlet的repair属性
*
* @return 默认true
*/
boolean repair() default true;
/**
* 备注描述
*
* @return 备注描述
*/
String comment() default "";
}

View File

@@ -0,0 +1,26 @@
/*
* 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.net.http;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 只能注解于Service类的方法的参数或参数内的String字段
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({PARAMETER, FIELD})
@Retention(RUNTIME)
public @interface RestSessionid {
boolean create() default false;
}

View File

@@ -11,7 +11,9 @@ import java.lang.annotation.*;
* 功能同JSR 315 (java-servlet 3.0) 规范中的 @WebServlet * 功能同JSR 315 (java-servlet 3.0) 规范中的 @WebServlet
* *
* *
* <p> 详情见: http://redkale.org * <p>
* 详情见: http://redkale.org
*
* @author zhangjx * @author zhangjx
*/ */
@Documented @Documented
@@ -28,4 +30,6 @@ public @interface WebServlet {
int moduleid() default 0; int moduleid() default 0;
WebInitParam[] initParams() default {}; WebInitParam[] initParams() default {};
String comment() default ""; //备注描述
} }

View File

@@ -33,7 +33,7 @@ public abstract class WebSocketNode {
@Resource(name = Application.RESNAME_SERVER_ADDR) @Resource(name = Application.RESNAME_SERVER_ADDR)
protected InetSocketAddress localSncpAddress; //为SncpServer的服务address protected InetSocketAddress localSncpAddress; //为SncpServer的服务address
@DynRemote @RpcRemote
protected WebSocketNode remoteNode; protected WebSocketNode remoteNode;
//存放所有用户分布在节点上的队列信息,Set<InetSocketAddress> 为 sncpnode 的集合 //存放所有用户分布在节点上的队列信息,Set<InetSocketAddress> 为 sncpnode 的集合
@@ -58,16 +58,16 @@ public abstract class WebSocketNode {
}); });
} }
protected abstract List<String> getOnlineRemoteAddresses(@DynTargetAddress InetSocketAddress targetAddress, Serializable groupid); protected abstract List<String> getOnlineRemoteAddresses(@RpcTargetAddress InetSocketAddress targetAddress, Serializable groupid);
protected abstract int sendMessage(@DynTargetAddress InetSocketAddress targetAddress, Serializable groupid, boolean recent, Serializable message, boolean last); protected abstract int sendMessage(@RpcTargetAddress InetSocketAddress targetAddress, Serializable groupid, boolean recent, Serializable message, boolean last);
protected abstract void connect(Serializable groupid, InetSocketAddress addr); protected abstract void connect(Serializable groupid, InetSocketAddress addr);
protected abstract void disconnect(Serializable groupid, InetSocketAddress addr); protected abstract void disconnect(Serializable groupid, InetSocketAddress addr);
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
protected List<String> remoteOnlineRemoteAddresses(@DynTargetAddress InetSocketAddress targetAddress, Serializable groupid) { protected List<String> remoteOnlineRemoteAddresses(@RpcTargetAddress InetSocketAddress targetAddress, Serializable groupid) {
if (remoteNode == null) return null; if (remoteNode == null) return null;
try { try {
return remoteNode.getOnlineRemoteAddresses(targetAddress, groupid); return remoteNode.getOnlineRemoteAddresses(targetAddress, groupid);

View File

@@ -23,7 +23,7 @@ import org.redkale.util.*;
* WebSocketServlet * WebSocketServlet
* | * |
* | * |
* WebSocketEngine & WebSocketNode * WebSocketEngine &#38; WebSocketNode
* / \ * / \
* / \ * / \
* / \ * / \

View File

@@ -17,6 +17,7 @@ import jdk.internal.org.objectweb.asm.*;
import static jdk.internal.org.objectweb.asm.Opcodes.*; import static jdk.internal.org.objectweb.asm.Opcodes.*;
import jdk.internal.org.objectweb.asm.Type; import jdk.internal.org.objectweb.asm.Type;
import org.redkale.convert.bson.BsonConvert; import org.redkale.convert.bson.BsonConvert;
import org.redkale.convert.json.JsonConvert;
import org.redkale.net.Transport; import org.redkale.net.Transport;
import org.redkale.net.sncp.SncpClient.SncpAction; import org.redkale.net.sncp.SncpClient.SncpAction;
import org.redkale.service.*; import org.redkale.service.*;
@@ -25,8 +26,8 @@ import org.redkale.util.*;
/** /**
* Service Node Communicate Protocol * Service Node Communicate Protocol
* 生成Service的本地模式或远程模式Service-Class的工具类 * 生成Service的本地模式或远程模式Service-Class的工具类
* *
* *
* 详情见: http://redkale.org * 详情见: http://redkale.org
* *
* @author zhangjx * @author zhangjx
@@ -79,6 +80,7 @@ public abstract class Sncp {
* 对类名或者name字符串进行hash。 * 对类名或者name字符串进行hash。
* *
* @param name String * @param name String
*
* @return hash值 * @return hash值
*/ */
public static DLong hash(final String name) { public static DLong hash(final String name) {
@@ -131,79 +133,83 @@ public abstract class Sncp {
/** /**
* <blockquote><pre> * <blockquote><pre>
* public class TestService implements Service{ * public class TestService implements Service{
* *
* public String findSomeThing(){ * public String findSomeThing(){
* return "hello"; * return "hello";
* } * }
* *
* &#64;MultiRun(selfrun = false) * &#64;MultiRun(selfrun = false)
* public void createSomeThing(TestBean bean){ * public void createSomeThing(TestBean bean){
* //do something * //do something
* } * }
* *
* &#64;MultiRun * &#64;MultiRun
* public String updateSomeThing(String id){ * public String updateSomeThing(String id){
* return "hello" + id; * return "hello" + id;
* } * }
* } * }
* </pre></blockquote> * </pre></blockquote>
* *
* <blockquote><pre> * <blockquote><pre>
* &#64;Resource(name = "") * &#64;Resource(name = "")
* &#64;SncpDyn(remote = false) * &#64;SncpDyn(remote = false)
* &#64;ResourceType({TestService.class}) * &#64;ResourceType({TestService.class})
* public final class _DynLocalTestService extends TestService{ * public final class _DynLocalTestService extends TestService{
* *
* &#64;Resource * &#64;Resource
* private BsonConvert _redkale_convert; * private BsonConvert _redkale_bsonConvert;
* *
* &#64;Resource
* private JsonConvert _redkale_jsonConvert;
*
* private Transport _redkale_sameGroupTransport; * private Transport _redkale_sameGroupTransport;
* *
* private Transport[] _redkale_diffGroupTransports; * private Transport[] _redkale_diffGroupTransports;
* *
* private SncpClient _redkale_client; * private SncpClient _redkale_client;
* *
* private String _redkale_selfstring; * private String _redkale_selfstring;
* *
* &#64;Override * &#64;Override
* public String toString() { * public String toString() {
* return _redkale_selfstring == null ? super.toString() : _redkale_selfstring; * return _redkale_selfstring == null ? super.toString() : _redkale_selfstring;
* } * }
* *
* &#64;Override * &#64;Override
* public void createSomeThing(TestBean bean){ * public void createSomeThing(TestBean bean){
* this._redkale_createSomeThing(false, true, true, bean); * this._redkale_createSomeThing(false, true, true, bean);
* } * }
* *
* &#64;SncpDyn(remote = false, index = 0) * &#64;SncpDyn(remote = false, index = 0)
* public void _redkale_createSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, TestBean bean){ * public void _redkale_createSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, TestBean bean){
* if(selfrunnable) super.createSomeThing(bean); * if(selfrunnable) super.createSomeThing(bean);
* if (_redkale_client== null) return; * if (_redkale_client== null) return;
* if (samerunnable) _redkale_client.remoteSameGroup(_redkale_convert, _sameGroupTransport, 0, true, false, false, bean); * if (samerunnable) _redkale_client.remoteSameGroup(_redkale_bsonConvert, _redkale_jsonConvert, _sameGroupTransport, 0, true, false, false, bean);
* if (diffrunnable) _redkale_client.remoteDiffGroup(_redkale_convert, _diffGroupTransports, 0, true, true, false, bean); * if (diffrunnable) _redkale_client.remoteDiffGroup(_redkale_bsonConvert, _redkale_jsonConvert, _diffGroupTransports, 0, true, true, false, bean);
* } * }
* *
* &#64;Override * &#64;Override
* public String updateSomeThing(String id){ * public String updateSomeThing(String id){
* return this._redkale_updateSomeThing(true, true, true, id); * return this._redkale_updateSomeThing(true, true, true, id);
* } * }
* *
* &#64;SncpDyn(remote = false, index = 1) * &#64;SncpDyn(remote = false, index = 1)
* public String _redkale_updateSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, String id){ * public String _redkale_updateSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, String id){
* String rs = super.updateSomeThing(id); * String rs = super.updateSomeThing(id);
* if (_redkale_client== null) return; * if (_redkale_client== null) return;
* if (samerunnable) _redkale_client.remoteSameGroup(_redkale_convert, _sameGroupTransport, 1, true, false, false, id); * if (samerunnable) _redkale_client.remoteSameGroup(_redkale_bsonConvert, _redkale_jsonConvert, _sameGroupTransport, 1, true, false, false, id);
* if (diffrunnable) _redkale_client.remoteDiffGroup(_redkale_convert, _diffGroupTransports, 1, true, true, false, id); * if (diffrunnable) _redkale_client.remoteDiffGroup(_redkale_bsonConvert, _redkale_jsonConvert, _diffGroupTransports, 1, true, true, false, id);
* return rs; * return rs;
* } * }
* } * }
* </pre></blockquote> * </pre></blockquote>
* *
* 创建Service的本地模式Class * 创建Service的本地模式Class
* *
* @param <T> Service子类 * @param <T> Service子类
* @param name 资源名 * @param name 资源名
* @param serviceClass Service类 * @param serviceClass Service类
*
* @return Service实例 * @return Service实例
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -217,7 +223,8 @@ public abstract class Sncp {
final String supDynName = serviceClass.getName().replace('.', '/'); final String supDynName = serviceClass.getName().replace('.', '/');
final String clientName = SncpClient.class.getName().replace('.', '/'); final String clientName = SncpClient.class.getName().replace('.', '/');
final String clientDesc = Type.getDescriptor(SncpClient.class); final String clientDesc = Type.getDescriptor(SncpClient.class);
final String convertDesc = Type.getDescriptor(BsonConvert.class); final String bsonConvertDesc = Type.getDescriptor(BsonConvert.class);
final String jsonConvertDesc = Type.getDescriptor(JsonConvert.class);
final String sncpDynDesc = Type.getDescriptor(SncpDyn.class); final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
final String transportDesc = Type.getDescriptor(Transport.class); final String transportDesc = Type.getDescriptor(Transport.class);
final String transportsDesc = Type.getDescriptor(Transport[].class); final String transportsDesc = Type.getDescriptor(Transport[].class);
@@ -275,7 +282,13 @@ public abstract class Sncp {
} }
{ {
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_convert", convertDesc, null, null); fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_bsonConvert", bsonConvertDesc, null, null);
av0 = fv.visitAnnotation("Ljavax/annotation/Resource;", true);
av0.visitEnd();
fv.visitEnd();
}
{
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_jsonConvert", jsonConvertDesc, null, null);
av0 = fv.visitAnnotation("Ljavax/annotation/Resource;", true); av0 = fv.visitAnnotation("Ljavax/annotation/Resource;", true);
av0.visitEnd(); av0.visitEnd();
fv.visitEnd(); fv.visitEnd();
@@ -481,20 +494,24 @@ public abstract class Sncp {
mv.visitVarInsn(ALOAD, 0);//调用 _client mv.visitVarInsn(ALOAD, 0);//调用 _client
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc); mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
mv.visitVarInsn(ALOAD, 0); //传递 _convert mv.visitVarInsn(ALOAD, 0); //传递 _bsonConvert
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_convert", convertDesc); mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_bsonConvert", bsonConvertDesc);
mv.visitVarInsn(ALOAD, 0); //传递 _jsonConvert
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_jsonConvert", jsonConvertDesc);
mv.visitVarInsn(ALOAD, 0); //传递 _sameGroupTransport mv.visitVarInsn(ALOAD, 0); //传递 _sameGroupTransport
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_sameGroupTransport", transportDesc); mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_sameGroupTransport", transportDesc);
final int preparams = 4; //调用selfrunnable之前的参数个数; _client/_bsonConvert/_jsonConvert/_sameGroupTransport
if (index <= 5) { //第几个 SncpAction if (index <= 5) { //第几个 SncpAction
mv.visitInsn(ICONST_0 + index); mv.visitInsn(ICONST_0 + index);
} else { } else {
mv.visitIntInsn(BIPUSH, index); mv.visitIntInsn(BIPUSH, index);
} }
if (paramtypes.length + 3 <= 5) { //参数总数量 if (paramtypes.length + preparams <= 5) { //参数总数量
mv.visitInsn(ICONST_0 + paramtypes.length + 3); mv.visitInsn(ICONST_0 + paramtypes.length + preparams);
} else { } else {
mv.visitIntInsn(BIPUSH, paramtypes.length + 3); mv.visitIntInsn(BIPUSH, paramtypes.length + preparams);
} }
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
@@ -517,7 +534,7 @@ public abstract class Sncp {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
mv.visitInsn(AASTORE); mv.visitInsn(AASTORE);
int insn = 3; int insn = 3; //空3给selfrunnable、samerunnable、diffrunnable
for (int j = 0; j < paramtypes.length; j++) { for (int j = 0; j < paramtypes.length; j++) {
final Class pt = paramtypes[j]; final Class pt = paramtypes[j];
mv.visitInsn(DUP); mv.visitInsn(DUP);
@@ -544,7 +561,7 @@ public abstract class Sncp {
} }
mv.visitInsn(AASTORE); mv.visitInsn(AASTORE);
} }
mv.visitMethodInsn(INVOKEVIRTUAL, clientName, mrun.async() ? "asyncRemoteSameGroup" : "remoteSameGroup", "(" + convertDesc + transportDesc + "I[Ljava/lang/Object;)V", false); mv.visitMethodInsn(INVOKEVIRTUAL, clientName, mrun.async() ? "asyncRemoteSameGroup" : "remoteSameGroup", "(" + bsonConvertDesc + jsonConvertDesc + transportDesc + "I[Ljava/lang/Object;)V", false);
mv.visitLabel(sameLabel); mv.visitLabel(sameLabel);
//---------------------------- 调用diffrun --------------------------------- //---------------------------- 调用diffrun ---------------------------------
mv.visitVarInsn(ILOAD, 3); //读取 diffrunnable mv.visitVarInsn(ILOAD, 3); //读取 diffrunnable
@@ -554,7 +571,9 @@ public abstract class Sncp {
mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc); mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_convert", convertDesc); mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_bsonConvert", bsonConvertDesc);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_jsonConvert", jsonConvertDesc);
mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_diffGroupTransports", transportsDesc); mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_diffGroupTransports", transportsDesc);
@@ -563,10 +582,10 @@ public abstract class Sncp {
} else { } else {
mv.visitIntInsn(BIPUSH, index); mv.visitIntInsn(BIPUSH, index);
} }
if (paramtypes.length + 3 <= 5) { //参数总数量 if (paramtypes.length + preparams <= 5) { //参数总数量
mv.visitInsn(ICONST_0 + paramtypes.length + 3); mv.visitInsn(ICONST_0 + paramtypes.length + preparams);
} else { } else {
mv.visitIntInsn(BIPUSH, paramtypes.length + 3); mv.visitIntInsn(BIPUSH, paramtypes.length + preparams);
} }
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
@@ -589,7 +608,7 @@ public abstract class Sncp {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
mv.visitInsn(AASTORE); mv.visitInsn(AASTORE);
insn = 3; insn = 3;//空3给selfrunnable、samerunnable、diffrunnable
for (int j = 0; j < paramtypes.length; j++) { for (int j = 0; j < paramtypes.length; j++) {
final Class pt = paramtypes[j]; final Class pt = paramtypes[j];
mv.visitInsn(DUP); mv.visitInsn(DUP);
@@ -616,7 +635,7 @@ public abstract class Sncp {
} }
mv.visitInsn(AASTORE); mv.visitInsn(AASTORE);
} }
mv.visitMethodInsn(INVOKEVIRTUAL, clientName, mrun.async() ? "asyncRemoteDiffGroup" : "remoteDiffGroup", "(" + convertDesc + transportsDesc + "I[Ljava/lang/Object;)V", false); mv.visitMethodInsn(INVOKEVIRTUAL, clientName, mrun.async() ? "asyncRemoteDiffGroup" : "remoteDiffGroup", "(" + bsonConvertDesc + jsonConvertDesc + transportsDesc + "I[Ljava/lang/Object;)V", false);
mv.visitLabel(diffLabel); mv.visitLabel(diffLabel);
if (returnType == void.class) { if (returnType == void.class) {
@@ -712,11 +731,12 @@ public abstract class Sncp {
* @param clientAddress 本地IP地址 * @param clientAddress 本地IP地址
* @param sameGroupTransport 同组的通信组件 * @param sameGroupTransport 同组的通信组件
* @param diffGroupTransports 异组的通信组件列表 * @param diffGroupTransports 异组的通信组件列表
*
* @return Service的本地模式实例 * @return Service的本地模式实例
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T extends Service> T createLocalService(final String name, final Consumer<Runnable> executor, final ResourceFactory resourceFactory, public static <T extends Service> T createLocalService(final String name, final Consumer<Runnable> executor, final ResourceFactory resourceFactory,
final Class<T> serviceClass, final InetSocketAddress clientAddress, final Transport sameGroupTransport, final Collection<Transport> diffGroupTransports) { final Class<T> serviceClass, final InetSocketAddress clientAddress, final Transport sameGroupTransport, final Collection<Transport> diffGroupTransports) {
try { try {
final Class newClazz = createLocalServiceClass(name, serviceClass); final Class newClazz = createLocalServiceClass(name, serviceClass);
T rs = (T) newClazz.newInstance(); T rs = (T) newClazz.newInstance();
@@ -729,7 +749,7 @@ public abstract class Sncp {
for (Field field : loop.getDeclaredFields()) { for (Field field : loop.getDeclaredFields()) {
int mod = field.getModifiers(); int mod = field.getModifiers();
if (Modifier.isFinal(mod) || Modifier.isStatic(mod)) continue; if (Modifier.isFinal(mod) || Modifier.isStatic(mod)) continue;
if (field.getAnnotation(DynRemote.class) == null) continue; if (field.getAnnotation(RpcRemote.class) == null) continue;
if (!field.getType().isAssignableFrom(newClazz)) continue; if (!field.getType().isAssignableFrom(newClazz)) continue;
field.setAccessible(true); field.setAccessible(true);
if (remoteTransport == null) { if (remoteTransport == null) {
@@ -761,7 +781,7 @@ public abstract class Sncp {
try { try {
Field e = newClazz.getDeclaredField(FIELDPREFIX + "_client"); Field e = newClazz.getDeclaredField(FIELDPREFIX + "_client");
e.setAccessible(true); e.setAccessible(true);
client = new SncpClient(name, serviceClass, executor, false, newClazz, clientAddress); client = new SncpClient(name, serviceClass, rs, executor, false, newClazz, clientAddress);
e.set(rs, client); e.set(rs, client);
} catch (NoSuchFieldException ne) { } catch (NoSuchFieldException ne) {
} }
@@ -771,6 +791,7 @@ public abstract class Sncp {
sb.append(newClazz.getName()).append("{name = '").append(name).append("'"); sb.append(newClazz.getName()).append("{name = '").append(name).append("'");
if (client != null) { if (client != null) {
sb.append(", serviceid = ").append(client.getServiceid()); sb.append(", serviceid = ").append(client.getServiceid());
sb.append(", serviceversion = ").append(client.getServiceversion());
sb.append(", action.size = ").append(client.getActionCount()); sb.append(", action.size = ").append(client.getActionCount());
List<String> groups = new ArrayList<>(); List<String> groups = new ArrayList<>();
if (sameGroupTransport != null) groups.add(sameGroupTransport.getName()); if (sameGroupTransport != null) groups.add(sameGroupTransport.getName());
@@ -823,48 +844,51 @@ public abstract class Sncp {
* &#64;SncpDyn(remote = true) * &#64;SncpDyn(remote = true)
* &#64;ResourceType({TestService.class}) * &#64;ResourceType({TestService.class})
* public final class _DynRemoteTestService extends TestService{ * public final class _DynRemoteTestService extends TestService{
* *
* &#64;Resource * &#64;Resource
* private BsonConvert _redkale_convert; * private BsonConvert _redkale_bsonConvert;
* *
* &#64;Resource
* private JsonConvert _redkale_jsonConvert;
*
* private Transport _redkale_transport; * private Transport _redkale_transport;
* *
* private SncpClient _redkale_client; * private SncpClient _redkale_client;
* *
* private String _redkale_selfstring; * private String _redkale_selfstring;
* *
* &#64;Override * &#64;Override
* public String toString() { * public String toString() {
* return _redkale_selfstring == null ? super.toString() : _redkale_selfstring; * return _redkale_selfstring == null ? super.toString() : _redkale_selfstring;
* } * }
* *
* &#64;SncpDyn(remote = false, index = 0) * &#64;SncpDyn(remote = false, index = 0)
* public void _redkale_createSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, TestBean bean){ * public void _redkale_createSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, TestBean bean){
* _redkale_client.remote(_redkale_convert, _redkale_transport, 0, selfrunnable, samerunnable, diffrunnable, bean); * _redkale_client.remote(_redkale_bsonConvert, _redkale_jsonConvert, _redkale_transport, 0, selfrunnable, samerunnable, diffrunnable, bean);
* } * }
* *
* &#64;SncpDyn(remote = false, index = 1) * &#64;SncpDyn(remote = false, index = 1)
* public String _redkale_updateSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, String id){ * public String _redkale_updateSomeThing(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, String id){
* return _redkale_client.remote(_redkale_convert, _redkale_transport, 1, selfrunnable, samerunnable, diffrunnable, id); * return _redkale_client.remote(_redkale_bsonConvert, _redkale_jsonConvert, _redkale_transport, 1, selfrunnable, samerunnable, diffrunnable, id);
* } * }
* *
* &#64;Override * &#64;Override
* public void createSomeThing(TestBean bean){ * public void createSomeThing(TestBean bean){
* _redkale_client.remote(_redkale_convert, _redkale_transport, 2, bean); * _redkale_client.remote(_redkale_bsonConvert, _redkale_jsonConvert, _redkale_transport, 2, bean);
* } * }
* *
* &#64;Override * &#64;Override
* public String findSomeThing(){ * public String findSomeThing(){
* return _redkale_client.remote(_redkale_convert, _redkale_transport, 3); * return _redkale_client.remote(_redkale_bsonConvert, _redkale_jsonConvert, _redkale_transport, 3);
* } * }
* *
* &#64;Override * &#64;Override
* public String updateSomeThing(String id){ * public String updateSomeThing(String id){
* return _redkale_client.remote(_redkale_convert, _redkale_transport, 4, id); * return _redkale_client.remote(_redkale_bsonConvert, _redkale_jsonConvert, _redkale_transport, 4, id);
* } * }
* } * }
* </pre></blockquote> * </pre></blockquote>
* *
* 创建远程模式的Service实例 * 创建远程模式的Service实例
* *
* @param <T> Service泛型 * @param <T> Service泛型
@@ -878,7 +902,7 @@ public abstract class Sncp {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T extends Service> T createRemoteService(final String name, final Consumer<Runnable> executor, final Class<T> serviceClass, public static <T extends Service> T createRemoteService(final String name, final Consumer<Runnable> executor, final Class<T> serviceClass,
final InetSocketAddress clientAddress, final Transport transport) { final InetSocketAddress clientAddress, final Transport transport) {
if (serviceClass == null) return null; if (serviceClass == null) return null;
if (!Service.class.isAssignableFrom(serviceClass)) return null; if (!Service.class.isAssignableFrom(serviceClass)) return null;
int mod = serviceClass.getModifiers(); int mod = serviceClass.getModifiers();
@@ -888,15 +912,16 @@ public abstract class Sncp {
final String clientName = SncpClient.class.getName().replace('.', '/'); final String clientName = SncpClient.class.getName().replace('.', '/');
final String clientDesc = Type.getDescriptor(SncpClient.class); final String clientDesc = Type.getDescriptor(SncpClient.class);
final String sncpDynDesc = Type.getDescriptor(SncpDyn.class); final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
final String convertDesc = Type.getDescriptor(BsonConvert.class); final String bsonConvertDesc = Type.getDescriptor(BsonConvert.class);
final String jsonConvertDesc = Type.getDescriptor(JsonConvert.class);
final String transportDesc = Type.getDescriptor(Transport.class); final String transportDesc = Type.getDescriptor(Transport.class);
final String anyValueDesc = Type.getDescriptor(AnyValue.class); final String anyValueDesc = Type.getDescriptor(AnyValue.class);
ClassLoader loader = Sncp.class.getClassLoader(); ClassLoader loader = Sncp.class.getClassLoader();
String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + REMOTEPREFIX + serviceClass.getSimpleName(); String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + REMOTEPREFIX + serviceClass.getSimpleName();
final SncpClient client = new SncpClient(name, serviceClass, executor, true, realed ? createLocalServiceClass(name, serviceClass) : serviceClass, clientAddress);
try { try {
Class newClazz = Class.forName(newDynName.replace('/', '.')); Class newClazz = Class.forName(newDynName.replace('/', '.'));
T rs = (T) newClazz.newInstance(); T rs = (T) newClazz.newInstance();
SncpClient client = new SncpClient(name, serviceClass, rs, executor, true, realed ? createLocalServiceClass(name, serviceClass) : serviceClass, clientAddress);
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_client"); Field c = newClazz.getDeclaredField(FIELDPREFIX + "_client");
c.setAccessible(true); c.setAccessible(true);
c.set(rs, client); c.set(rs, client);
@@ -906,7 +931,8 @@ public abstract class Sncp {
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(newClazz.getName()).append("{name = '").append(name); sb.append(newClazz.getName()).append("{name = '").append(name);
sb.append("', serviceid = ").append(client.getServiceid()); sb.append("', serviceid = '").append(client.getServiceid());
sb.append("', serviceversion = ").append(client.getServiceversion());
sb.append(", action.size = ").append(client.getActionCount()); sb.append(", action.size = ").append(client.getActionCount());
sb.append(", address = ").append(clientAddress).append(", groups = ").append(transport == null ? null : transport.getName()); sb.append(", address = ").append(clientAddress).append(", groups = ").append(transport == null ? null : transport.getName());
sb.append(", remoteaddrs = ").append(transport == null ? null : Arrays.asList(transport.getRemoteAddresses())); sb.append(", remoteaddrs = ").append(transport == null ? null : Arrays.asList(transport.getRemoteAddresses()));
@@ -958,7 +984,13 @@ public abstract class Sncp {
} }
} }
{ {
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_convert", convertDesc, null, null); fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_bsonConvert", bsonConvertDesc, null, null);
av0 = fv.visitAnnotation("Ljavax/annotation/Resource;", true);
av0.visitEnd();
fv.visitEnd();
}
{
fv = cw.visitField(ACC_PRIVATE, FIELDPREFIX + "_jsonConvert", jsonConvertDesc, null, null);
av0 = fv.visitAnnotation("Ljavax/annotation/Resource;", true); av0 = fv.visitAnnotation("Ljavax/annotation/Resource;", true);
av0.visitEnd(); av0.visitEnd();
fv.visitEnd(); fv.visitEnd();
@@ -1015,7 +1047,7 @@ public abstract class Sncp {
mv.visitEnd(); mv.visitEnd();
} }
int i = -1; int i = -1;
for (final SncpAction entry : client.actions) { for (final SncpAction entry : SncpClient.getSncpActions(realed ? createLocalServiceClass(name, serviceClass) : serviceClass)) {
final int index = ++i; final int index = ++i;
final java.lang.reflect.Method method = entry.method; final java.lang.reflect.Method method = entry.method;
{ {
@@ -1032,7 +1064,9 @@ public abstract class Sncp {
mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc); mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_client", clientDesc);
mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_convert", convertDesc); mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_bsonConvert", bsonConvertDesc);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_jsonConvert", jsonConvertDesc);
mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_transport", transportDesc); mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_transport", transportDesc);
if (index <= 5) { if (index <= 5) {
@@ -1079,7 +1113,7 @@ public abstract class Sncp {
} }
} }
mv.visitMethodInsn(INVOKEVIRTUAL, clientName, "remote", "(" + convertDesc + transportDesc + "I[Ljava/lang/Object;)Ljava/lang/Object;", false); mv.visitMethodInsn(INVOKEVIRTUAL, clientName, "remote", "(" + bsonConvertDesc + jsonConvertDesc + transportDesc + "I[Ljava/lang/Object;)Ljava/lang/Object;", false);
//mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false); //mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
if (method.getGenericReturnType() == void.class) { if (method.getGenericReturnType() == void.class) {
mv.visitInsn(POP); mv.visitInsn(POP);
@@ -1124,6 +1158,7 @@ public abstract class Sncp {
T rs = (T) newClazz.newInstance(); T rs = (T) newClazz.newInstance();
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_client"); Field c = newClazz.getDeclaredField(FIELDPREFIX + "_client");
c.setAccessible(true); c.setAccessible(true);
SncpClient client = new SncpClient(name, serviceClass, rs, executor, true, realed ? createLocalServiceClass(name, serviceClass) : serviceClass, clientAddress);
c.set(rs, client); c.set(rs, client);
Field t = newClazz.getDeclaredField(FIELDPREFIX + "_transport"); Field t = newClazz.getDeclaredField(FIELDPREFIX + "_transport");
t.setAccessible(true); t.setAccessible(true);
@@ -1132,6 +1167,7 @@ public abstract class Sncp {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(newClazz.getName()).append("{name = '").append(name); sb.append(newClazz.getName()).append("{name = '").append(name);
sb.append("', serviceid = ").append(client.getServiceid()); sb.append("', serviceid = ").append(client.getServiceid());
sb.append(", serviceversion = ").append(client.getServiceversion());
sb.append(", action.size = ").append(client.getActionCount()); sb.append(", action.size = ").append(client.getActionCount());
sb.append(", address = ").append(clientAddress).append(", groups = ").append(transport == null ? null : transport.getName()); sb.append(", address = ").append(clientAddress).append(", groups = ").append(transport == null ? null : transport.getName());
sb.append(", remotes = ").append(transport == null ? null : Arrays.asList(transport.getRemoteAddresses())); sb.append(", remotes = ").append(transport == null ? null : Arrays.asList(transport.getRemoteAddresses()));

View File

@@ -43,10 +43,6 @@ public final class SncpClient {
protected final Attribute[] paramAttrs; // 为null表示无DynCall处理index=0固定为null, 其他为参数标记的DynCall回调方法 protected final Attribute[] paramAttrs; // 为null表示无DynCall处理index=0固定为null, 其他为参数标记的DynCall回调方法
protected final int handlerFuncParamIndex;
protected final int handlerAttachParamIndex;
protected final int addressTargetParamIndex; protected final int addressTargetParamIndex;
protected final int addressSourceParamIndex; protected final int addressSourceParamIndex;
@@ -64,26 +60,18 @@ public final class SncpClient {
Annotation[][] anns = method.getParameterAnnotations(); Annotation[][] anns = method.getParameterAnnotations();
int targetAddrIndex = -1; int targetAddrIndex = -1;
int sourceAddrIndex = -1; int sourceAddrIndex = -1;
int handlerAttachIndex = -1;
int handlerFuncIndex = -1;
boolean hasattr = false; boolean hasattr = false;
Attribute[] atts = new Attribute[paramTypes.length + 1]; Attribute[] atts = new Attribute[paramTypes.length + 1];
if (anns.length > 0) { if (anns.length > 0) {
Class<?>[] params = method.getParameterTypes(); Class<?>[] params = method.getParameterTypes();
for (int i = 0; i < params.length; i++) {
if (CompletionHandler.class.isAssignableFrom(params[i])) {
handlerFuncIndex = i;
break;
}
}
for (int i = 0; i < anns.length; i++) { for (int i = 0; i < anns.length; i++) {
if (anns[i].length > 0) { if (anns[i].length > 0) {
for (Annotation ann : anns[i]) { for (Annotation ann : anns[i]) {
if (ann.annotationType() == DynAttachment.class) { if (ann.annotationType() == RpcTargetAddress.class && SocketAddress.class.isAssignableFrom(params[i])) {
handlerAttachIndex = i;
} else if (ann.annotationType() == DynTargetAddress.class && SocketAddress.class.isAssignableFrom(params[i])) {
targetAddrIndex = i; targetAddrIndex = i;
} else if (ann.annotationType() == DynSourceAddress.class && SocketAddress.class.isAssignableFrom(params[i])) { } else if (ann.annotationType() == RpcSourceAddress.class && SocketAddress.class.isAssignableFrom(params[i])) {
sourceAddrIndex = i; sourceAddrIndex = i;
} }
} }
@@ -103,10 +91,7 @@ public final class SncpClient {
} }
this.addressTargetParamIndex = targetAddrIndex; this.addressTargetParamIndex = targetAddrIndex;
this.addressSourceParamIndex = sourceAddrIndex; this.addressSourceParamIndex = sourceAddrIndex;
this.handlerFuncParamIndex = handlerFuncIndex;
this.handlerAttachParamIndex = handlerAttachIndex;
this.paramAttrs = hasattr ? atts : null; this.paramAttrs = hasattr ? atts : null;
if (this.handlerFuncParamIndex >= 0 && method.getReturnType() != void.class) throw new RuntimeException(method + " has CompletionHandler type parameter but return type is not void");
} }
@Override @Override
@@ -119,7 +104,7 @@ public final class SncpClient {
protected final boolean finest = logger.isLoggable(Level.FINEST); protected final boolean finest = logger.isLoggable(Level.FINEST);
protected final JsonConvert jsonConvert = JsonFactory.root().getConvert(); protected final JsonConvert convert = JsonFactory.root().getConvert();
protected final String name; protected final String name;
@@ -135,15 +120,18 @@ public final class SncpClient {
protected final DLong serviceid; protected final DLong serviceid;
protected final int serviceversion;
protected final SncpAction[] actions; protected final SncpAction[] actions;
protected final Consumer<Runnable> executor; protected final Consumer<Runnable> executor;
public <T extends Service> SncpClient(final String serviceName, final Class<T> serviceType, final Consumer<Runnable> executor, public <T extends Service> SncpClient(final String serviceName, final Class<T> serviceType, final T service, final Consumer<Runnable> executor,
final boolean remote, final Class serviceClass, final InetSocketAddress clientAddress) { final boolean remote, final Class serviceClass, final InetSocketAddress clientAddress) {
this.remote = remote; this.remote = remote;
this.executor = executor; this.executor = executor;
this.serviceClass = serviceClass; this.serviceClass = serviceClass;
this.serviceversion = service.version();
this.clientAddress = clientAddress; this.clientAddress = clientAddress;
this.name = serviceName; this.name = serviceName;
this.serviceid = Sncp.hash(serviceType.getName() + ':' + serviceName); this.serviceid = Sncp.hash(serviceType.getName() + ':' + serviceName);
@@ -157,6 +145,15 @@ public final class SncpClient {
this.addrPort = clientAddress == null ? 0 : clientAddress.getPort(); this.addrPort = clientAddress == null ? 0 : clientAddress.getPort();
} }
static List<SncpAction> getSncpActions(final Class serviceClass) {
final List<SncpAction> actions = new ArrayList<>();
//------------------------------------------------------------------------------
for (java.lang.reflect.Method method : parseMethod(serviceClass)) {
actions.add(new SncpAction(method, Sncp.hash(method)));
}
return actions;
}
public InetSocketAddress getClientAddress() { public InetSocketAddress getClientAddress() {
return clientAddress; return clientAddress;
} }
@@ -165,6 +162,10 @@ public final class SncpClient {
return serviceid; return serviceid;
} }
public int getServiceversion() {
return serviceversion;
}
public int getActionCount() { public int getActionCount() {
return actions.length; return actions.length;
} }
@@ -173,9 +174,9 @@ public final class SncpClient {
public String toString() { public String toString() {
String service = serviceClass.getName(); String service = serviceClass.getName();
if (remote) service = service.replace(Sncp.LOCALPREFIX, Sncp.REMOTEPREFIX); if (remote) service = service.replace(Sncp.LOCALPREFIX, Sncp.REMOTEPREFIX);
return this.getClass().getSimpleName() + "(service = " + service + ", serviceid = " + serviceid + ", name = '" + name return this.getClass().getSimpleName() + "(service = " + service + ", serviceid = " + serviceid + ", serviceversion = " + serviceversion + ", name = '" + name
+ "', address = " + (clientAddress == null ? "" : (clientAddress.getHostString() + ":" + clientAddress.getPort())) + "', address = " + (clientAddress == null ? "" : (clientAddress.getHostString() + ":" + clientAddress.getPort()))
+ ", actions.size = " + actions.length + ")"; + ", actions.size = " + actions.length + ")";
} }
public static List<Method> parseMethod(final Class serviceClass) { public static List<Method> parseMethod(final Class serviceClass) {
@@ -192,6 +193,7 @@ public final class SncpClient {
if (method.getName().equals("equals") || method.getName().equals("hashCode")) continue; if (method.getName().equals("equals") || method.getName().equals("hashCode")) continue;
if (method.getName().equals("notify") || method.getName().equals("notifyAll") || method.getName().equals("wait")) continue; if (method.getName().equals("notify") || method.getName().equals("notifyAll") || method.getName().equals("wait")) continue;
if (method.getName().equals("init") || method.getName().equals("destroy")) continue; if (method.getName().equals("init") || method.getName().equals("destroy")) continue;
if (method.getName().equals("version") || method.getName().equals("name")) continue;
//if (onlySncpDyn && method.getAnnotation(SncpDyn.class) == null) continue; //if (onlySncpDyn && method.getAnnotation(SncpDyn.class) == null) continue;
DLong actionid = Sncp.hash(method); DLong actionid = Sncp.hash(method);
Method old = actionids.get(actionid); Method old = actionids.get(actionid);
@@ -218,83 +220,90 @@ public final class SncpClient {
return multis; return multis;
} }
public void remoteSameGroup(final BsonConvert convert, Transport transport, final int index, final Object... params) { public void remoteSameGroup(final BsonConvert bsonConvert, final JsonConvert jsonConvert, Transport transport, final int index, final Object... params) {
final SncpAction action = actions[index]; final SncpAction action = actions[index];
if (action.handlerFuncParamIndex >= 0) params[action.handlerFuncParamIndex] = null; //不能让远程调用handler因为之前本地方法已经调用过了
for (InetSocketAddress addr : transport.getRemoteAddresses()) { for (InetSocketAddress addr : transport.getRemoteAddresses()) {
remote0(null, convert, transport, addr, action, params); remote0(bsonConvert, jsonConvert, transport, addr, action, params);
} }
} }
public void asyncRemoteSameGroup(final BsonConvert convert, Transport transport, final int index, final Object... params) { public void asyncRemoteSameGroup(final BsonConvert bsonConvert, final JsonConvert jsonConvert, Transport transport, final int index, final Object... params) {
if (executor != null) { if (executor != null) {
executor.accept(() -> { executor.accept(() -> {
remoteSameGroup(convert, transport, index, params); remoteSameGroup(bsonConvert, jsonConvert, transport, index, params);
}); });
} else { } else {
remoteSameGroup(convert, transport, index, params); remoteSameGroup(bsonConvert, jsonConvert, transport, index, params);
} }
} }
public void remoteDiffGroup(final BsonConvert convert, Transport[] transports, final int index, final Object... params) { public void remoteDiffGroup(final BsonConvert bsonConvert, final JsonConvert jsonConvert, Transport[] transports, final int index, final Object... params) {
if (transports == null || transports.length < 1) return; if (transports == null || transports.length < 1) return;
final SncpAction action = actions[index]; final SncpAction action = actions[index];
if (action.handlerFuncParamIndex >= 0) params[action.handlerFuncParamIndex] = null; //不能让远程调用handler因为之前本地方法已经调用过了
for (Transport transport : transports) { for (Transport transport : transports) {
remote0(null, convert, transport, null, action, params); remote0(bsonConvert, jsonConvert, transport, null, action, params);
} }
} }
public void asyncRemoteDiffGroup(final BsonConvert convert, Transport[] transports, final int index, final Object... params) { public void asyncRemoteDiffGroup(final BsonConvert bsonConvert, final JsonConvert jsonConvert, Transport[] transports, final int index, final Object... params) {
if (transports == null || transports.length < 1) return; if (transports == null || transports.length < 1) return;
if (executor != null) { if (executor != null) {
executor.accept(() -> { executor.accept(() -> {
remoteDiffGroup(convert, transports, index, params); remoteDiffGroup(bsonConvert, jsonConvert, transports, index, params);
}); });
} else { } else {
remoteDiffGroup(convert, transports, index, params); remoteDiffGroup(bsonConvert, jsonConvert, transports, index, params);
} }
} }
//只给远程模式调用的 //只给远程模式调用的
public <T> T remote(final BsonConvert convert, Transport transport, final int index, final Object... params) { public <T> T remote(final BsonConvert bsonConvert, final JsonConvert jsonConvert, Transport transport, final int index, final Object... params) {
final SncpAction action = actions[index]; final SncpAction action = actions[index];
final CompletionHandler handlerFunc = action.handlerFuncParamIndex >= 0 ? (CompletionHandler) params[action.handlerFuncParamIndex] : null; SncpFuture<byte[]> future = remote0(bsonConvert, jsonConvert, transport, null, action, params);
if (action.handlerFuncParamIndex >= 0) params[action.handlerFuncParamIndex] = null;
Future<byte[]> future = remote0(handlerFunc, convert, transport, null, action, params); final BsonReader reader = bsonConvert.pollBsonReader();
if (handlerFunc != null) return null;
final BsonReader reader = convert.pollBsonReader();
try { try {
reader.setBytes(future.get(5, TimeUnit.SECONDS)); reader.setBytes(future.get(5, TimeUnit.SECONDS));
byte i; byte i;
while ((i = reader.readByte()) != 0) { while ((i = reader.readByte()) != 0) {
final Attribute attr = action.paramAttrs[i]; final Attribute attr = action.paramAttrs[i];
attr.set(params[i - 1], convert.convertFrom(attr.type(), reader)); attr.set(params[i - 1], bsonConvert.convertFrom(attr.type(), reader));
} }
return convert.convertFrom(action.resultTypes, reader); return bsonConvert.convertFrom(action.resultTypes, reader);
} catch (InterruptedException | ExecutionException | TimeoutException e) { } catch (InterruptedException | ExecutionException | TimeoutException e) {
logger.log(Level.SEVERE, actions[index].method + " sncp (params: " + jsonConvert.convertTo(params) + ") remote error", e); logger.log(Level.SEVERE, actions[index].method + " sncp (params: " + jsonConvert.convertTo(params) + ") remote error", e);
throw new RuntimeException(actions[index].method + " sncp remote error", e); throw new RuntimeException(actions[index].method + " sncp remote error", e);
} finally { } finally {
convert.offerBsonReader(reader); bsonConvert.offerBsonReader(reader);
} }
} }
public <T> void remote(final BsonConvert convert, Transport[] transports, final int index, final Object... params) { public <T> void remote(final BsonConvert bsonConvert, final JsonConvert jsonConvert, Transport[] transports, final int index, final Object... params) {
if (transports == null || transports.length < 1) return; if (transports == null || transports.length < 1) return;
remote(convert, transports[0], index, params); remote(bsonConvert, jsonConvert, transports[0], index, params);
for (int i = 1; i < transports.length; i++) { for (int i = 1; i < transports.length; i++) {
remote0(null, convert, transports[i], null, actions[index], params); remote0(bsonConvert, jsonConvert, transports[i], null, actions[index], params);
} }
} }
private Future<byte[]> remote0(final CompletionHandler handler, final BsonConvert convert, final Transport transport, final SocketAddress addr0, final SncpAction action, final Object... params) { private SncpFuture<byte[]> remote0(final BsonConvert bsonConvert, final JsonConvert jsonConvert, final Transport transport, final SocketAddress addr0, final SncpAction action, final Object... params) {
if ("rest".equalsIgnoreCase(transport.getKind())) {
return remoteRest0(jsonConvert, transport, addr0, action, params);
}
return remoteSncp0(bsonConvert, transport, addr0, action, params);
}
private SncpFuture<byte[]> remoteRest0(final JsonConvert jsonConvert, final Transport transport, final SocketAddress addr0, final SncpAction action, final Object... params) {
return null;
}
private SncpFuture<byte[]> remoteSncp0(final BsonConvert bsonConvert, final Transport transport, final SocketAddress addr0, final SncpAction action, final Object... params) {
Type[] myparamtypes = action.paramTypes; Type[] myparamtypes = action.paramTypes;
if (action.addressSourceParamIndex >= 0) params[action.addressSourceParamIndex] = this.clientAddress; if (action.addressSourceParamIndex >= 0) params[action.addressSourceParamIndex] = this.clientAddress;
final BsonWriter writer = convert.pollBsonWriter(transport.getBufferSupplier()); // 将head写入 final BsonWriter writer = bsonConvert.pollBsonWriter(transport.getBufferSupplier()); // 将head写入
writer.writeTo(DEFAULT_HEADER); writer.writeTo(DEFAULT_HEADER);
for (int i = 0; i < params.length; i++) { for (int i = 0; i < params.length; i++) {
convert.convertTo(writer, myparamtypes[i], params[i]); bsonConvert.convertTo(writer, myparamtypes[i], params[i]);
} }
final int reqBodyLength = writer.count() - HEADER_SIZE; //body总长度 final int reqBodyLength = writer.count() - HEADER_SIZE; //body总长度
final long seqid = System.nanoTime(); final long seqid = System.nanoTime();
@@ -302,14 +311,14 @@ public final class SncpClient {
final SocketAddress addr = addr0 == null ? (action.addressTargetParamIndex >= 0 ? (SocketAddress) params[action.addressTargetParamIndex] : null) : addr0; final SocketAddress addr = addr0 == null ? (action.addressTargetParamIndex >= 0 ? (SocketAddress) params[action.addressTargetParamIndex] : null) : addr0;
final AsyncConnection conn = transport.pollConnection(addr); final AsyncConnection conn = transport.pollConnection(addr);
if (conn == null || !conn.isOpen()) { if (conn == null || !conn.isOpen()) {
logger.log(Level.SEVERE, action.method + " sncp (params: " + jsonConvert.convertTo(params) + ") cannot connect " + (conn == null ? addr : conn.getRemoteAddress())); logger.log(Level.SEVERE, action.method + " sncp (params: " + convert.convertTo(params) + ") cannot connect " + (conn == null ? addr : conn.getRemoteAddress()));
throw new RuntimeException("sncp " + (conn == null ? addr : conn.getRemoteAddress()) + " cannot connect"); throw new RuntimeException("sncp " + (conn == null ? addr : conn.getRemoteAddress()) + " cannot connect");
} }
final ByteBuffer[] sendBuffers = writer.toBuffers(); final ByteBuffer[] sendBuffers = writer.toBuffers();
fillHeader(sendBuffers[0], seqid, actionid, reqBodyLength); fillHeader(sendBuffers[0], seqid, actionid, reqBodyLength);
final ByteBuffer buffer = transport.pollBuffer(); final ByteBuffer buffer = transport.pollBuffer();
final SncpFuture<byte[]> future = new SncpFuture(); final SncpFuture<byte[]> future = new SncpFuture(false);
conn.write(sendBuffers, sendBuffers, new CompletionHandler<Integer, ByteBuffer[]>() { conn.write(sendBuffers, sendBuffers, new CompletionHandler<Integer, ByteBuffer[]>() {
@Override @Override
@@ -370,7 +379,7 @@ public final class SncpClient {
final int respBodyLength = buffer.getInt(); final int respBodyLength = buffer.getInt();
final int retcode = buffer.getInt(); final int retcode = buffer.getInt();
if (retcode != 0) { if (retcode != 0) {
logger.log(Level.SEVERE, action.method + " sncp (params: " + jsonConvert.convertTo(params) + ") deal error (retcode=" + retcode + ", retinfo=" + SncpResponse.getRetCodeInfo(retcode) + ")"); logger.log(Level.SEVERE, action.method + " sncp (params: " + convert.convertTo(params) + ") deal error (retcode=" + retcode + ", retinfo=" + SncpResponse.getRetCodeInfo(retcode) + ")");
throw new RuntimeException("remote service(" + action.method + ") deal error (retcode=" + retcode + ", retinfo=" + SncpResponse.getRetCodeInfo(retcode) + ")"); throw new RuntimeException("remote service(" + action.method + ") deal error (retcode=" + retcode + ", retinfo=" + SncpResponse.getRetCodeInfo(retcode) + ")");
} }
@@ -391,43 +400,21 @@ public final class SncpClient {
future.set(this.body); future.set(this.body);
transport.offerBuffer(buffer); transport.offerBuffer(buffer);
transport.offerConnection(false, conn); transport.offerConnection(false, conn);
if (handler != null) {
final Object handlerAttach = action.handlerAttachParamIndex >= 0 ? params[action.handlerAttachParamIndex] : null;
final BsonReader reader = convert.pollBsonReader();
try {
reader.setBytes(this.body);
int i;
while ((i = (reader.readByte() & 0xff)) != 0) {
final Attribute attr = action.paramAttrs[i];
attr.set(params[i - 1], convert.convertFrom(attr.type(), reader));
}
Object rs = convert.convertFrom(action.resultTypes, reader);
handler.completed(rs, handlerAttach);
} catch (Exception e) {
handler.failed(e, handlerAttach);
} finally {
convert.offerBsonReader(reader);
}
}
} }
@Override @Override
public void failed(Throwable exc, Void attachment2) { public void failed(Throwable exc, Void attachment2) {
logger.log(Level.SEVERE, action.method + " sncp (params: " + jsonConvert.convertTo(params) + ") remote read exec failed", exc); logger.log(Level.SEVERE, action.method + " sncp (params: " + convert.convertTo(params) + ") remote read exec failed", exc);
future.set(new RuntimeException(action.method + " sncp remote exec failed")); future.set(new RuntimeException(action.method + " sncp remote exec failed"));
transport.offerBuffer(buffer); transport.offerBuffer(buffer);
transport.offerConnection(true, conn); transport.offerConnection(true, conn);
if (handler != null) {
final Object handlerAttach = action.handlerAttachParamIndex >= 0 ? params[action.handlerAttachParamIndex] : null;
handler.failed(exc, handlerAttach);
}
} }
}); });
} }
@Override @Override
public void failed(Throwable exc, ByteBuffer[] attachment) { public void failed(Throwable exc, ByteBuffer[] attachment) {
logger.log(Level.SEVERE, action.method + " sncp (params: " + jsonConvert.convertTo(params) + ") remote write exec failed", exc); logger.log(Level.SEVERE, action.method + " sncp (params: " + convert.convertTo(params) + ") remote write exec failed", exc);
transport.offerBuffer(buffer); transport.offerBuffer(buffer);
transport.offerConnection(true, conn); transport.offerConnection(true, conn);
} }
@@ -440,7 +427,9 @@ public final class SncpClient {
if (rseqid != seqid) throw new RuntimeException("sncp(" + action.method + ") response.seqid = " + seqid + ", but request.seqid =" + rseqid); if (rseqid != seqid) throw new RuntimeException("sncp(" + action.method + ") response.seqid = " + seqid + ", but request.seqid =" + rseqid);
if (buffer.getChar() != HEADER_SIZE) throw new RuntimeException("sncp(" + action.method + ") buffer receive header.length not " + HEADER_SIZE); if (buffer.getChar() != HEADER_SIZE) throw new RuntimeException("sncp(" + action.method + ") buffer receive header.length not " + HEADER_SIZE);
DLong rserviceid = DLong.read(buffer); DLong rserviceid = DLong.read(buffer);
if (!rserviceid.equals(serviceid)) throw new RuntimeException("sncp(" + action.method + ") response.serviceid = " + serviceid + ", but request.serviceid =" + rserviceid); if (!rserviceid.equals(this.serviceid)) throw new RuntimeException("sncp(" + action.method + ") response.serviceid = " + serviceid + ", but request.serviceid =" + rserviceid);
int version = buffer.getInt();
if (version != this.serviceversion) throw new RuntimeException("sncp(" + action.method + ") response.serviceversion = " + serviceversion + ", but request.serviceversion =" + version);
DLong raction = DLong.read(buffer); DLong raction = DLong.read(buffer);
if (!action.actionid.equals(raction)) throw new RuntimeException("sncp(" + action.method + ") response.actionid = " + action.actionid + ", but request.actionid =(" + raction + ")"); if (!action.actionid.equals(raction)) throw new RuntimeException("sncp(" + action.method + ") response.actionid = " + action.actionid + ", but request.actionid =(" + raction + ")");
buffer.getInt(); //地址 buffer.getInt(); //地址
@@ -454,6 +443,7 @@ public final class SncpClient {
buffer.putLong(seqid); //序列号 buffer.putLong(seqid); //序列号
buffer.putChar((char) HEADER_SIZE); //header长度 buffer.putChar((char) HEADER_SIZE); //header长度
DLong.write(buffer, this.serviceid); DLong.write(buffer, this.serviceid);
buffer.putInt(this.serviceversion);
DLong.write(buffer, actionid); DLong.write(buffer, actionid);
buffer.put(addrBytes); buffer.put(addrBytes);
buffer.putChar((char) this.addrPort); buffer.putChar((char) this.addrPort);
@@ -470,14 +460,22 @@ public final class SncpClient {
private RuntimeException ex; private RuntimeException ex;
public SncpFuture() { private final boolean rest;
public SncpFuture(boolean rest) {
this.rest = rest;
} }
public SncpFuture(T result) { public SncpFuture(boolean rest, T result) {
this.rest = rest;
this.result = result; this.result = result;
this.done = true; this.done = true;
} }
public boolean isRest() {
return this.rest;
}
public void set(T result) { public void set(T result) {
this.result = result; this.result = result;
this.done = true; this.done = true;

View File

@@ -62,7 +62,8 @@ public final class SncpDynServlet extends SncpServlet {
if (method.getName().equals("getClass") || method.getName().equals("toString")) continue; if (method.getName().equals("getClass") || method.getName().equals("toString")) continue;
if (method.getName().equals("equals") || method.getName().equals("hashCode")) continue; if (method.getName().equals("equals") || method.getName().equals("hashCode")) continue;
if (method.getName().equals("notify") || method.getName().equals("notifyAll") || method.getName().equals("wait")) continue; if (method.getName().equals("notify") || method.getName().equals("notifyAll") || method.getName().equals("wait")) continue;
if (method.getName().equals("init") || method.getName().equals("destroy") || method.getName().equals("name")) continue; if (method.getName().equals("init") || method.getName().equals("destroy")) continue;
if (method.getName().equals("version") || method.getName().equals("name")) continue;
final DLong actionid = Sncp.hash(method); final DLong actionid = Sncp.hash(method);
SncpServletAction action = SncpServletAction.create(service, actionid, method); SncpServletAction action = SncpServletAction.create(service, actionid, method);
action.convert = convert; action.convert = convert;
@@ -146,7 +147,7 @@ public final class SncpDynServlet extends SncpServlet {
public abstract void action(final BsonReader in, final BsonWriter out) throws Throwable; public abstract void action(final BsonReader in, final BsonWriter out) throws Throwable;
public final void callParameter(final BsonWriter out, final Object... params) { public final void _callParameter(final BsonWriter out, final Object... params) {
if (paramAttrs != null) { if (paramAttrs != null) {
for (int i = 1; i < paramAttrs.length; i++) { for (int i = 1; i < paramAttrs.length; i++) {
org.redkale.util.Attribute attr = paramAttrs[i]; org.redkale.util.Attribute attr = paramAttrs[i];
@@ -176,15 +177,15 @@ public final class SncpDynServlet extends SncpServlet {
* String arg2 = convert.convertFrom(paramTypes[2], in); * String arg2 = convert.convertFrom(paramTypes[2], in);
* int arg3 = convert.convertFrom(paramTypes[3], in); * int arg3 = convert.convertFrom(paramTypes[3], in);
* Object rs = service.change(arg1, arg2, arg3); * Object rs = service.change(arg1, arg2, arg3);
* callParameter(out, arg1, arg2, arg3); * _callParameter(out, arg1, arg2, arg3);
* convert.convertTo(out, paramTypes[0], rs); * convert.convertTo(out, paramTypes[0], rs);
* } * }
* } * }
* </pre></blockquote> * </pre></blockquote>
* *
* @param service Service * @param service Service
* @param actionid 操作ID * @param actionid 操作ID
* @param method 方法 * @param method 方法
* *
* @return SncpServletAction * @return SncpServletAction
*/ */
@@ -317,7 +318,7 @@ public final class SncpDynServlet extends SncpServlet {
} }
mv.visitVarInsn(ASTORE, store); //11 mv.visitVarInsn(ASTORE, store); //11
} }
//------------------------- callParameter 方法 -------------------------------- //------------------------- _callParameter 方法 --------------------------------
mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 2); mv.visitVarInsn(ALOAD, 2);
if (paramClasses.length <= 5) { //参数总数量 if (paramClasses.length <= 5) { //参数总数量
@@ -353,7 +354,7 @@ public final class SncpDynServlet extends SncpServlet {
} }
mv.visitInsn(AASTORE); mv.visitInsn(AASTORE);
} }
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "callParameter", "(" + convertWriterDesc + "[Ljava/lang/Object;)V", false); mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "_callParameter", "(" + convertWriterDesc + "[Ljava/lang/Object;)V", false);
//-------------------------直接返回 或者 调用convertTo方法 -------------------------------- //-------------------------直接返回 或者 调用convertTo方法 --------------------------------
int maxStack = codes.length > 0 ? codes[codes.length - 1][1] : 1; int maxStack = codes.length > 0 ? codes[codes.length - 1][1] : 1;

View File

@@ -20,7 +20,7 @@ import org.redkale.util.*;
*/ */
public final class SncpRequest extends Request<SncpContext> { public final class SncpRequest extends Request<SncpContext> {
public static final int HEADER_SIZE = 56; public static final int HEADER_SIZE = 60;
public static final byte[] DEFAULT_HEADER = new byte[HEADER_SIZE]; public static final byte[] DEFAULT_HEADER = new byte[HEADER_SIZE];
@@ -28,6 +28,8 @@ public final class SncpRequest extends Request<SncpContext> {
private long seqid; private long seqid;
private int serviceversion;
private DLong serviceid; private DLong serviceid;
private DLong actionid; private DLong actionid;
@@ -60,6 +62,7 @@ public final class SncpRequest extends Request<SncpContext> {
return -1; return -1;
} }
this.serviceid = DLong.read(buffer); this.serviceid = DLong.read(buffer);
this.serviceversion = buffer.getInt();
this.actionid = DLong.read(buffer); this.actionid = DLong.read(buffer);
buffer.get(bufferbytes); buffer.get(bufferbytes);
this.bodylength = buffer.getInt(); this.bodylength = buffer.getInt();
@@ -92,15 +95,16 @@ public final class SncpRequest extends Request<SncpContext> {
@Override @Override
public String toString() { public String toString() {
return SncpRequest.class.getSimpleName() + "{seqid=" + this.seqid return SncpRequest.class.getSimpleName() + "{seqid=" + this.seqid
+ ",serviceid=" + this.serviceid + ",actionid=" + this.actionid + ",serviceversion=" + this.serviceversion + ",serviceid=" + this.serviceid
+ ",bodylength=" + this.bodylength + ",bodyoffset=" + this.bodyoffset + ",actionid=" + this.actionid + ",bodylength=" + this.bodylength
+ ",remoteAddress=" + getRemoteAddress() + "}"; + ",bodyoffset=" + this.bodyoffset + ",remoteAddress=" + getRemoteAddress() + "}";
} }
@Override @Override
protected void recycle() { protected void recycle() {
this.seqid = 0; this.seqid = 0;
this.serviceid = null; this.serviceid = null;
this.serviceversion = 0;
this.actionid = null; this.actionid = null;
this.bodylength = 0; this.bodylength = 0;
this.bodyoffset = 0; this.bodyoffset = 0;
@@ -122,6 +126,10 @@ public final class SncpRequest extends Request<SncpContext> {
return seqid; return seqid;
} }
public int getServiceversion() {
return serviceversion;
}
public DLong getServiceid() { public DLong getServiceid() {
return serviceid; return serviceid;
} }
@@ -133,7 +141,7 @@ public final class SncpRequest extends Request<SncpContext> {
public InetSocketAddress getRemoteAddress() { public InetSocketAddress getRemoteAddress() {
if (bufferbytes[0] == 0) return null; if (bufferbytes[0] == 0) return null;
return new InetSocketAddress((0xff & bufferbytes[0]) + "." + (0xff & bufferbytes[1]) + "." + (0xff & bufferbytes[2]) + "." + (0xff & bufferbytes[3]), return new InetSocketAddress((0xff & bufferbytes[0]) + "." + (0xff & bufferbytes[1]) + "." + (0xff & bufferbytes[2]) + "." + (0xff & bufferbytes[3]),
((0xff00 & (bufferbytes[4] << 8)) | (0xff & bufferbytes[5]))); ((0xff00 & (bufferbytes[4] << 8)) | (0xff & bufferbytes[5])));
} }
} }

View File

@@ -23,7 +23,9 @@ public final class SncpResponse extends Response<SncpContext, SncpRequest> {
public static final int RETCODE_ILLSERVICEID = (1 << 10); //无效serviceid public static final int RETCODE_ILLSERVICEID = (1 << 10); //无效serviceid
public static final int RETCODE_ILLACTIONID = (1 << 11); //无效actionid public static final int RETCODE_ILLSERVICEVER = (1 << 11); //无效serviceversion
public static final int RETCODE_ILLACTIONID = (1 << 15); //无效actionid
public static final int RETCODE_THROWEXCEPTION = (1 << 30); //内部异常 public static final int RETCODE_THROWEXCEPTION = (1 << 30); //内部异常
@@ -37,6 +39,7 @@ public final class SncpResponse extends Response<SncpContext, SncpRequest> {
public static String getRetCodeInfo(int retcode) { public static String getRetCodeInfo(int retcode) {
if (retcode == RETCODE_ILLSERVICEID) return "serviceid is invalid"; if (retcode == RETCODE_ILLSERVICEID) return "serviceid is invalid";
if (retcode == RETCODE_ILLSERVICEVER) return "serviceversion is invalid";
if (retcode == RETCODE_ILLACTIONID) return "actionid is invalid"; if (retcode == RETCODE_ILLACTIONID) return "actionid is invalid";
if (retcode == RETCODE_THROWEXCEPTION) return "Inner exception"; if (retcode == RETCODE_THROWEXCEPTION) return "Inner exception";
return null; return null;
@@ -68,6 +71,7 @@ public final class SncpResponse extends Response<SncpContext, SncpRequest> {
buffer.putLong(request.getSeqid()); buffer.putLong(request.getSeqid());
buffer.putChar((char) SncpRequest.HEADER_SIZE); buffer.putChar((char) SncpRequest.HEADER_SIZE);
DLong.write(buffer, request.getServiceid()); DLong.write(buffer, request.getServiceid());
buffer.putInt(request.getServiceversion());
DLong.write(buffer, request.getActionid()); DLong.write(buffer, request.getActionid());
buffer.put(addrBytes); buffer.put(addrBytes);
buffer.putChar((char) this.addrPort); buffer.putChar((char) this.addrPort);

View File

@@ -10,6 +10,7 @@ import java.util.*;
import java.util.concurrent.atomic.*; import java.util.concurrent.atomic.*;
import org.redkale.convert.bson.*; import org.redkale.convert.bson.*;
import org.redkale.net.*; import org.redkale.net.*;
import org.redkale.service.Service;
import org.redkale.util.*; import org.redkale.util.*;
import org.redkale.watch.*; import org.redkale.watch.*;
@@ -37,13 +38,18 @@ public final class SncpServer extends Server<DLong, SncpContext, SncpRequest, Sn
super.init(config); super.init(config);
} }
public void addService(ServiceWrapper entry) { public void addSncpServlet(ServiceWrapper entry) {
for (Class type : entry.getTypes()) { for (Class type : entry.getTypes()) {
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), entry.getName(), type, entry.getService()); SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), entry.getName(), type, entry.getService());
this.prepare.addServlet(sds, null, entry.getConf()); this.prepare.addServlet(sds, null, entry.getConf());
} }
} }
public <T extends Service> void addSncpServlet(Class<T> serviceType, String name, T service, AnyValue conf) {
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), name, serviceType, service);
this.prepare.addServlet(sds, null, conf);
}
public List<SncpServlet> getSncpServlets() { public List<SncpServlet> getSncpServlets() {
return ((SncpPrepareServlet) this.prepare).getSncpServlets(); return ((SncpPrepareServlet) this.prepare).getSncpServlets();
} }
@@ -56,16 +62,16 @@ public final class SncpServer extends Server<DLong, SncpContext, SncpRequest, Sn
AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Buffer.cycleCounter"); AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Buffer.cycleCounter");
final int rcapacity = Math.max(this.bufferCapacity, 4 * 1024); final int rcapacity = Math.max(this.bufferCapacity, 4 * 1024);
ObjectPool<ByteBuffer> bufferPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, this.bufferPoolSize, ObjectPool<ByteBuffer> bufferPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, this.bufferPoolSize,
(Object... params) -> ByteBuffer.allocateDirect(rcapacity), null, (e) -> { (Object... params) -> ByteBuffer.allocateDirect(rcapacity), null, (e) -> {
if (e == null || e.isReadOnly() || e.capacity() != rcapacity) return false; if (e == null || e.isReadOnly() || e.capacity() != rcapacity) return false;
e.clear(); e.clear();
return true; return true;
}); });
AtomicLong createResponseCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Response.creatCounter"); AtomicLong createResponseCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Response.creatCounter");
AtomicLong cycleResponseCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Response.cycleCounter"); AtomicLong cycleResponseCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Response.cycleCounter");
ObjectPool<Response> responsePool = SncpResponse.createPool(createResponseCounter, cycleResponseCounter, this.responsePoolSize, null); ObjectPool<Response> responsePool = SncpResponse.createPool(createResponseCounter, cycleResponseCounter, this.responsePoolSize, null);
SncpContext sncpcontext = new SncpContext(this.serverStartTime, this.logger, executor, rcapacity, bufferPool, responsePool, SncpContext sncpcontext = new SncpContext(this.serverStartTime, this.logger, executor, rcapacity, bufferPool, responsePool,
this.maxbody, this.charset, this.address, this.prepare, this.watch, this.readTimeoutSecond, this.writeTimeoutSecond); this.maxbody, this.charset, this.address, this.prepare, this.watch, this.readTimeoutSecond, this.writeTimeoutSecond);
responsePool.setCreator((Object... params) -> new SncpResponse(sncpcontext, new SncpRequest(sncpcontext))); responsePool.setCreator((Object... params) -> new SncpResponse(sncpcontext, new SncpRequest(sncpcontext)));
return sncpcontext; return sncpcontext;
} }

View File

@@ -8,7 +8,6 @@ package org.redkale.service;
import java.beans.*; import java.beans.*;
import java.io.*; import java.io.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.nio.channels.*;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.function.*; import java.util.function.*;
@@ -26,6 +25,7 @@ import org.redkale.util.*;
* @param <V> value类型 * @param <V> value类型
* <p> * <p>
* 详情见: http://redkale.org * 详情见: http://redkale.org
*
* @author zhangjx * @author zhangjx
*/ */
@AutoLoad(false) @AutoLoad(false)
@@ -191,11 +191,6 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
return !entry.isExpired(); return !entry.isExpired();
} }
@Override
public void exists(final CompletionHandler<Boolean, K> handler, @DynAttachment final K key) {
if (handler != null) handler.completed(exists(key), key);
}
@Override @Override
public V get(K key) { public V get(K key) {
if (key == null) return null; if (key == null) return null;
@@ -206,11 +201,6 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
return (V) entry.getValue(); return (V) entry.getValue();
} }
@Override
public void get(final CompletionHandler<V, K> handler, @DynAttachment final K key) {
if (handler != null) handler.completed(get(key), key);
}
@Override @Override
@MultiRun @MultiRun
public V getAndRefresh(K key, final int expireSeconds) { public V getAndRefresh(K key, final int expireSeconds) {
@@ -224,12 +214,6 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
return (V) entry.getValue(); return (V) entry.getValue();
} }
@Override
public void getAndRefresh(final CompletionHandler<V, K> handler, @DynAttachment final K key, final int expireSeconds) {
V rs = getAndRefresh(key, expireSeconds);
if (handler != null) handler.completed(rs, key);
}
@Override @Override
@MultiRun @MultiRun
public void refresh(K key, final int expireSeconds) { public void refresh(K key, final int expireSeconds) {
@@ -240,12 +224,6 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
entry.expireSeconds = expireSeconds; entry.expireSeconds = expireSeconds;
} }
@Override
public void refresh(final CompletionHandler<Void, K> handler, final K key, final int expireSeconds) {
refresh(key, expireSeconds);
if (handler != null) handler.completed(null, key);
}
@Override @Override
@MultiRun @MultiRun
public void set(K key, V value) { public void set(K key, V value) {
@@ -261,12 +239,6 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
} }
} }
@Override
public void set(final CompletionHandler<Void, K> handler, @DynAttachment final K key, final V value) {
set(key, value);
if (handler != null) handler.completed(null, key);
}
@Override @Override
@MultiRun @MultiRun
public void set(int expireSeconds, K key, V value) { public void set(int expireSeconds, K key, V value) {
@@ -282,12 +254,6 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
} }
} }
@Override
public void set(final CompletionHandler<Void, K> handler, final int expireSeconds, @DynAttachment final K key, final V value) {
set(expireSeconds, key, value);
if (handler != null) handler.completed(null, key);
}
@Override @Override
@MultiRun @MultiRun
public void setExpireSeconds(K key, int expireSeconds) { public void setExpireSeconds(K key, int expireSeconds) {
@@ -297,12 +263,6 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
entry.expireSeconds = expireSeconds; entry.expireSeconds = expireSeconds;
} }
@Override
public void setExpireSeconds(final CompletionHandler<Void, K> handler, @DynAttachment final K key, final int expireSeconds) {
setExpireSeconds(key, expireSeconds);
if (handler != null) handler.completed(null, key);
}
@Override @Override
@MultiRun @MultiRun
public void remove(K key) { public void remove(K key) {
@@ -310,32 +270,16 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
container.remove(key); container.remove(key);
} }
@Override
public void remove(final CompletionHandler<Void, K> handler, @DynAttachment final K key) {
remove(key);
if (handler != null) handler.completed(null, key);
}
@Override @Override
public Collection<V> getCollection(final K key) { public Collection<V> getCollection(final K key) {
return (Collection<V>) get(key); return (Collection<V>) get(key);
} }
@Override
public void getCollection(final CompletionHandler<Collection<V>, K> handler, @DynAttachment final K key) {
if (handler != null) handler.completed(getCollection(key), key);
}
@Override @Override
public Collection<V> getCollectionAndRefresh(final K key, final int expireSeconds) { public Collection<V> getCollectionAndRefresh(final K key, final int expireSeconds) {
return (Collection<V>) getAndRefresh(key, expireSeconds); return (Collection<V>) getAndRefresh(key, expireSeconds);
} }
@Override
public void getCollectionAndRefresh(final CompletionHandler<Collection<V>, K> handler, @DynAttachment final K key, final int expireSeconds) {
if (handler != null) handler.completed(getCollectionAndRefresh(key, expireSeconds), key);
}
@Override @Override
@MultiRun @MultiRun
public void appendListItem(K key, V value) { public void appendListItem(K key, V value) {
@@ -352,12 +296,6 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
} }
} }
@Override
public void appendListItem(final CompletionHandler<Void, K> handler, @DynAttachment final K key, final V value) {
appendListItem(key, value);
if (handler != null) handler.completed(null, key);
}
@Override @Override
@MultiRun @MultiRun
public void removeListItem(K key, V value) { public void removeListItem(K key, V value) {
@@ -367,12 +305,6 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
((Collection) entry.getValue()).remove(value); ((Collection) entry.getValue()).remove(value);
} }
@Override
public void removeListItem(final CompletionHandler<Void, K> handler, @DynAttachment final K key, final V value) {
removeListItem(key, value);
if (handler != null) handler.completed(null, key);
}
@Override @Override
@MultiRun @MultiRun
public void appendSetItem(K key, V value) { public void appendSetItem(K key, V value) {
@@ -389,12 +321,6 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
} }
} }
@Override
public void appendSetItem(final CompletionHandler<Void, K> handler, @DynAttachment final K key, final V value) {
appendSetItem(key, value);
if (handler != null) handler.completed(null, key);
}
@Override @Override
@MultiRun @MultiRun
public void removeSetItem(K key, V value) { public void removeSetItem(K key, V value) {
@@ -404,12 +330,6 @@ public class CacheSourceService<K extends Serializable, V extends Object> implem
((Set) entry.getValue()).remove(value); ((Set) entry.getValue()).remove(value);
} }
@Override
public void removeSetItem(final CompletionHandler<Void, K> handler, @DynAttachment final K key, final V value) {
removeSetItem(key, value);
if (handler != null) handler.completed(null, key);
}
public static enum CacheEntryType { public static enum CacheEntryType {
OBJECT, SET, LIST; OBJECT, SET, LIST;
} }

View File

@@ -1,128 +0,0 @@
/*
* 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.service;
import org.redkale.source.DataSQLListener;
import org.redkale.source.DataSource;
import org.redkale.source.DataDefaultSource;
import org.redkale.util.AnyValue;
import org.redkale.util.AutoLoad;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.*;
import javax.annotation.Resource;
import org.redkale.util.*;
/**
* 暂时不实现
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Deprecated
@AutoLoad(false)
@ResourceType({DataSQLListenerService.class, DataSQLListener.class})
public class DataSQLListenerService implements DataSQLListener, Service {
private static final String format = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL";
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
private final boolean finest = logger.isLoggable(Level.FINEST);
@Resource(name = "APP_HOME")
private File home;
@Resource(name = "$")
private DataSource source;
private final BlockingQueue<String> queue = new ArrayBlockingQueue<>(1024 * 1024);
private PrintStream syncfile;
@Override
public void init(AnyValue config) {
new Thread() {
{
setName(DataSQLListener.class.getSimpleName() + "-Thread");
setDaemon(true);
}
@Override
public void run() {
while (true) {
try {
String sql = queue.take();
send(sql);
} catch (Exception e) {
logger.log(Level.SEVERE, this.getName() + " occur error");
}
}
}
}.start();
}
public String name() {
return this.getClass().getAnnotation(Resource.class).name();
}
@Override
public void destroy(AnyValue config) {
if (syncfile != null) syncfile.close();
}
private void write(String... sqls) {
try {
if (syncfile == null) {
File root = new File(home, "dbsync");
root.mkdirs();
syncfile = new PrintStream(new FileOutputStream(new File(root, "sql-" + name() + ".sql"), true), false, "UTF-8");
}
for (String sql : sqls) {
syncfile.print(sql + ";\r\n");
}
syncfile.flush();
} catch (Exception e) {
logger.log(Level.WARNING, "write sql file error. (" + name() + ", " + Arrays.toString(sqls) + ")", e);
}
}
@Override
public void insert(String... sqls) {
put(sqls);
}
@Override
public void update(String... sqls) {
put(sqls);
}
@Override
public void delete(String... sqls) {
put(sqls);
}
private void put(String... sqls) {
String date = String.format(format, System.currentTimeMillis());
for (String sql : sqls) {
try {
queue.put("/* " + date + " */ " + sql);
} catch (Exception e) {
write(sql);
}
}
}
@MultiRun(selfrun = false, async = true)
public void send(String... sqls) {
((DataDefaultSource) source).directExecute(sqls);
}
}

View File

@@ -6,7 +6,6 @@
package org.redkale.service; package org.redkale.service;
import java.io.*; import java.io.*;
import java.nio.channels.*;
import java.sql.*; import java.sql.*;
import java.util.*; import java.util.*;
import java.util.function.*; import java.util.function.*;
@@ -34,163 +33,89 @@ public class DataSourceService implements DataSource, Service, AutoCloseable {
source.insert(values); source.insert(values);
} }
@Override
public <T> void insert(final CompletionHandler<Void, T[]> handler, @DynAttachment @DynCall(DataCallArrayAttribute.class) final T... values) {
source.insert(values);
if (handler != null) handler.completed(null, values);
}
@Override @Override
public <T> void delete(T... values) { public <T> void delete(T... values) {
source.delete(values); source.delete(values);
} }
@Override
public <T> void delete(final CompletionHandler<Void, T[]> handler, @DynAttachment final T... values) {
source.delete(values);
if (handler != null) handler.completed(null, values);
}
@Override @Override
public <T> void delete(final Class<T> clazz, final Serializable... ids) { public <T> void delete(final Class<T> clazz, final Serializable... ids) {
source.delete(clazz, ids); source.delete(clazz, ids);
} }
@Override
public <T> void delete(final CompletionHandler<Void, Serializable[]> handler, final Class<T> clazz, @DynAttachment final Serializable... ids) {
source.delete(clazz, ids);
if (handler != null) handler.completed(null, ids);
}
@Override @Override
public <T> void delete(final Class<T> clazz, FilterNode node) { public <T> void delete(final Class<T> clazz, FilterNode node) {
source.delete(clazz, node); source.delete(clazz, node);
} }
@Override
public <T> void delete(final CompletionHandler<Void, FilterNode> handler, final Class<T> clazz, @DynAttachment final FilterNode node) {
source.delete(clazz, node);
if (handler != null) handler.completed(null, node);
}
@Override @Override
public <T> void update(T... values) { public <T> void update(T... values) {
source.update(values); source.update(values);
} }
@Override
public <T> void update(final CompletionHandler<Void, T[]> handler, @DynAttachment final T... values) {
source.update(values);
if (handler != null) handler.completed(null, values);
}
@Override @Override
public <T> void updateColumn(final Class<T> clazz, final Serializable id, final String column, final Serializable value) { public <T> void updateColumn(final Class<T> clazz, final Serializable id, final String column, final Serializable value) {
source.updateColumn(clazz, id, column, value); source.updateColumn(clazz, id, column, value);
} }
@Override
public <T> void updateColumn(final CompletionHandler<Void, Serializable> handler, final Class<T> clazz, @DynAttachment final Serializable id, final String column, final Serializable value) {
source.updateColumn(clazz, id, column, value);
if (handler != null) handler.completed(null, id);
}
@Override @Override
public <T> void updateColumn(final Class<T> clazz, final String column, final Serializable value, final FilterNode node) { public <T> void updateColumn(final Class<T> clazz, final String column, final Serializable value, final FilterNode node) {
source.updateColumn(clazz, column, value, node); source.updateColumn(clazz, column, value, node);
} }
@Override
public <T> void updateColumn(final CompletionHandler<Void, FilterNode> handler, final Class<T> clazz, final String column, final Serializable value, @DynAttachment final FilterNode node) {
source.updateColumn(clazz, column, value, node);
if (handler != null) handler.completed(null, node);
}
@Override @Override
public <T> void updateColumnIncrement(final Class<T> clazz, final Serializable id, final String column, long incvalue) { public <T> void updateColumnIncrement(final Class<T> clazz, final Serializable id, final String column, long incvalue) {
source.updateColumnIncrement(clazz, id, column, incvalue); source.updateColumnIncrement(clazz, id, column, incvalue);
} }
@Override
public <T> void updateColumnIncrement(final CompletionHandler<Void, Serializable> handler, final Class<T> clazz, @DynAttachment final Serializable id, final String column, long incvalue) {
source.updateColumnIncrement(clazz, id, column, incvalue);
if (handler != null) handler.completed(null, id);
}
@Override @Override
public <T> void updateColumnAnd(final Class<T> clazz, final Serializable id, final String column, long incvalue) { public <T> void updateColumnAnd(final Class<T> clazz, final Serializable id, final String column, long incvalue) {
source.updateColumnAnd(clazz, id, column, incvalue); source.updateColumnAnd(clazz, id, column, incvalue);
} }
@Override
public <T> void updateColumnAnd(final CompletionHandler<Void, Serializable> handler, final Class<T> clazz, @DynAttachment final Serializable id, final String column, long incvalue) {
source.updateColumnAnd(clazz, id, column, incvalue);
if (handler != null) handler.completed(null, id);
}
@Override @Override
public <T> void updateColumnOr(final Class<T> clazz, final Serializable id, final String column, long incvalue) { public <T> void updateColumnOr(final Class<T> clazz, final Serializable id, final String column, long incvalue) {
source.updateColumnOr(clazz, id, column, incvalue); source.updateColumnOr(clazz, id, column, incvalue);
} }
@Override
public <T> void updateColumnOr(final CompletionHandler<Void, Serializable> handler, final Class<T> clazz, @DynAttachment final Serializable id, final String column, long incvalue) {
source.updateColumnOr(clazz, id, column, incvalue);
if (handler != null) handler.completed(null, id);
}
@Override @Override
public <T> void updateColumns(T bean, final String... columns) { public <T> void updateColumns(T bean, final String... columns) {
source.updateColumns(bean, columns); source.updateColumns(bean, columns);
} }
@Override
public <T> void updateColumns(final CompletionHandler<Void, T> handler, @DynAttachment final T bean, final String... columns) {
source.updateColumns(bean, columns);
if (handler != null) handler.completed(null, bean);
}
@Override @Override
public <T> void updateColumns(T bean, final FilterNode node, final String... columns) { public <T> void updateColumns(T bean, final FilterNode node, final String... columns) {
source.updateColumns(bean, node, columns); source.updateColumns(bean, node, columns);
} }
@Override
public <T> void updateColumns(final CompletionHandler<Void, FilterNode> handler, final T bean, @DynAttachment final FilterNode node, final String... columns) {
source.updateColumns(bean, node, columns);
if (handler != null) handler.completed(null, node);
}
@Override @Override
public Number getNumberResult(final Class entityClass, FilterFunc func, final String column) { public Number getNumberResult(final Class entityClass, FilterFunc func, final String column) {
return source.getNumberResult(entityClass, func, column); return source.getNumberResult(entityClass, func, column);
} }
@Override
public void getNumberResult(final CompletionHandler<Number, String> handler, final Class entityClass, final FilterFunc func, @DynAttachment final String column) {
Number rs = source.getNumberResult(entityClass, func, column);
if (handler != null) handler.completed(rs, column);
}
@Override @Override
public final Number getNumberResult(final Class entityClass, FilterFunc func, final String column, FilterBean bean) { public final Number getNumberResult(final Class entityClass, FilterFunc func, final String column, FilterBean bean) {
return getNumberResult(entityClass, func, column, FilterNodeBean.createFilterNode(bean)); return getNumberResult(entityClass, func, column, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final void getNumberResult(final CompletionHandler<Number, FilterNode> handler, final Class entityClass, final FilterFunc func, final String column, final FilterBean bean) {
getNumberResult(handler, entityClass, func, column, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public Number getNumberResult(final Class entityClass, FilterFunc func, final String column, FilterNode node) { public Number getNumberResult(final Class entityClass, FilterFunc func, final String column, FilterNode node) {
return source.getNumberResult(entityClass, func, column, node); return source.getNumberResult(entityClass, func, column, node);
} }
@Override @Override
public void getNumberResult(final CompletionHandler<Number, FilterNode> handler, final Class entityClass, final FilterFunc func, final String column, @DynAttachment final FilterNode node) { public Number getNumberResult(final Class entityClass, FilterFunc func, final Number defVal, final String column) {
Number rs = source.getNumberResult(entityClass, func, column, node); return source.getNumberResult(entityClass, func, defVal, column);
if (handler != null) handler.completed(rs, node); }
@Override
public final Number getNumberResult(final Class entityClass, FilterFunc func, final Number defVal, final String column, FilterBean bean) {
return getNumberResult(entityClass, func, defVal, column, FilterNodeBean.createFilterNode(bean));
}
@Override
public Number getNumberResult(final Class entityClass, FilterFunc func, final Number defVal, final String column, FilterNode node) {
return source.getNumberResult(entityClass, func, defVal, column, node);
} }
@Override @Override
@@ -198,373 +123,176 @@ public class DataSourceService implements DataSource, Service, AutoCloseable {
return source.queryColumnMap(entityClass, keyColumn, func, funcColumn); return source.queryColumnMap(entityClass, keyColumn, func, funcColumn);
} }
@Override
public <T, K extends Serializable, N extends Number> void queryColumnMap(final CompletionHandler<Map<K, N>, String> handler, final Class<T> entityClass, final String keyColumn, final FilterFunc func, @DynAttachment final String funcColumn) {
Map<K, N> map = source.queryColumnMap(entityClass, keyColumn, func, funcColumn);
if (handler != null) handler.completed(map, funcColumn);
}
@Override @Override
public final <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, FilterFunc func, final String funcColumn, FilterBean bean) { public final <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, FilterFunc func, final String funcColumn, FilterBean bean) {
return queryColumnMap(entityClass, keyColumn, func, funcColumn, FilterNodeBean.createFilterNode(bean)); return queryColumnMap(entityClass, keyColumn, func, funcColumn, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final <T, K extends Serializable, N extends Number> void queryColumnMap(final CompletionHandler<Map<K, N>, FilterNode> handler, final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn, final FilterBean bean) {
queryColumnMap(handler, entityClass, keyColumn, func, funcColumn, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, FilterFunc func, final String funcColumn, FilterNode node) { public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, FilterFunc func, final String funcColumn, FilterNode node) {
return source.queryColumnMap(entityClass, keyColumn, func, funcColumn, node); return source.queryColumnMap(entityClass, keyColumn, func, funcColumn, node);
} }
@Override
public <T, K extends Serializable, N extends Number> void queryColumnMap(final CompletionHandler<Map<K, N>, FilterNode> handler, final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn, @DynAttachment final FilterNode node) {
Map<K, N> map = source.queryColumnMap(entityClass, keyColumn, func, funcColumn, node);
if (handler != null) handler.completed(map, node);
}
@Override @Override
public <T> T find(final Class<T> clazz, final Serializable pk) { public <T> T find(final Class<T> clazz, final Serializable pk) {
return source.find(clazz, pk); return source.find(clazz, pk);
} }
@Override
public <T> void find(final CompletionHandler<T, Serializable> handler, final Class<T> clazz, @DynAttachment final Serializable pk) {
T rs = source.find(clazz, pk);
if (handler != null) handler.completed(rs, pk);
}
@Override @Override
public <T> T find(final Class<T> clazz, SelectColumn selects, final Serializable pk) { public <T> T find(final Class<T> clazz, SelectColumn selects, final Serializable pk) {
return source.find(clazz, selects, pk); return source.find(clazz, selects, pk);
} }
@Override
public <T> void find(final CompletionHandler<T, Serializable> handler, final Class<T> clazz, final SelectColumn selects, @DynAttachment final Serializable pk) {
T rs = source.find(clazz, selects, pk);
if (handler != null) handler.completed(rs, pk);
}
@Override @Override
public <T> T find(final Class<T> clazz, final String column, final Serializable key) { public <T> T find(final Class<T> clazz, final String column, final Serializable key) {
return source.find(clazz, column, key); return source.find(clazz, column, key);
} }
@Override
public <T> void find(final CompletionHandler<T, Serializable> handler, final Class<T> clazz, final String column, @DynAttachment final Serializable key) {
T rs = source.find(clazz, column, key);
if (handler != null) handler.completed(rs, key);
}
@Override @Override
public final <T> T find(final Class<T> clazz, FilterBean bean) { public final <T> T find(final Class<T> clazz, FilterBean bean) {
return find(clazz, FilterNodeBean.createFilterNode(bean)); return find(clazz, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final <T> void find(final CompletionHandler<T, FilterNode> handler, final Class<T> clazz, final FilterBean bean) {
find(handler, clazz, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T> T find(final Class<T> clazz, FilterNode node) { public <T> T find(final Class<T> clazz, FilterNode node) {
return source.find(clazz, node); return source.find(clazz, node);
} }
@Override
public <T> void find(final CompletionHandler<T, FilterNode> handler, final Class<T> clazz, @DynAttachment final FilterNode node) {
T rs = source.find(clazz, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public final <T> T find(final Class<T> clazz, final SelectColumn selects, FilterBean bean) { public final <T> T find(final Class<T> clazz, final SelectColumn selects, FilterBean bean) {
return find(clazz, selects, FilterNodeBean.createFilterNode(bean)); return find(clazz, selects, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final <T> void find(final CompletionHandler<T, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final FilterBean bean) {
find(handler, clazz, selects, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T> T find(final Class<T> clazz, final SelectColumn selects, final FilterNode node) { public <T> T find(final Class<T> clazz, final SelectColumn selects, final FilterNode node) {
return source.find(clazz, selects, node); return source.find(clazz, selects, node);
} }
@Override
public <T> void find(final CompletionHandler<T, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, @DynAttachment final FilterNode node) {
T rs = source.find(clazz, selects, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> boolean exists(final Class<T> clazz, final Serializable pk) { public <T> boolean exists(final Class<T> clazz, final Serializable pk) {
return source.exists(clazz, pk); return source.exists(clazz, pk);
} }
@Override
public <T> void exists(final CompletionHandler<Boolean, Serializable> handler, final Class<T> clazz, @DynAttachment final Serializable pk) {
boolean rs = source.exists(clazz, pk);
if (handler != null) handler.completed(rs, pk);
}
@Override @Override
public final <T> boolean exists(final Class<T> clazz, FilterBean bean) { public final <T> boolean exists(final Class<T> clazz, FilterBean bean) {
return exists(clazz, FilterNodeBean.createFilterNode(bean)); return exists(clazz, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final <T> void exists(final CompletionHandler<Boolean, FilterNode> handler, final Class<T> clazz, final FilterBean bean) {
exists(handler, clazz, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T> boolean exists(final Class<T> clazz, FilterNode node) { public <T> boolean exists(final Class<T> clazz, FilterNode node) {
return source.exists(clazz, node); return source.exists(clazz, node);
} }
@Override
public <T> void exists(final CompletionHandler<Boolean, FilterNode> handler, final Class<T> clazz, @DynAttachment final FilterNode node) {
boolean rs = source.exists(clazz, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T, V extends Serializable> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, final String column, final Serializable key) { public <T, V extends Serializable> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, final String column, final Serializable key) {
return source.queryColumnSet(selectedColumn, clazz, column, key); return source.queryColumnSet(selectedColumn, clazz, column, key);
} }
@Override
public <T, V extends Serializable> void queryColumnSet(final CompletionHandler<HashSet<V>, Serializable> handler, final String selectedColumn, final Class<T> clazz, final String column, @DynAttachment final Serializable key) {
HashSet<V> rs = source.queryColumnSet(selectedColumn, clazz, column, key);
if (handler != null) handler.completed(rs, key);
}
@Override @Override
public final <T, V extends Serializable> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, FilterBean bean) { public final <T, V extends Serializable> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, FilterBean bean) {
return queryColumnSet(selectedColumn, clazz, FilterNodeBean.createFilterNode(bean)); return queryColumnSet(selectedColumn, clazz, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final <T, V extends Serializable> void queryColumnSet(final CompletionHandler<HashSet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final FilterBean bean) {
queryColumnSet(handler, selectedColumn, clazz, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T, V extends Serializable> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, FilterNode node) { public <T, V extends Serializable> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, FilterNode node) {
return source.queryColumnSet(selectedColumn, clazz, node); return source.queryColumnSet(selectedColumn, clazz, node);
} }
@Override
public <T, V extends Serializable> void queryColumnSet(final CompletionHandler<HashSet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, @DynAttachment final FilterNode node) {
HashSet<V> rs = source.queryColumnSet(selectedColumn, clazz, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T, V extends Serializable> List<V> queryColumnList(String selectedColumn, Class<T> clazz, final String column, final Serializable key) { public <T, V extends Serializable> List<V> queryColumnList(String selectedColumn, Class<T> clazz, final String column, final Serializable key) {
return source.queryColumnList(selectedColumn, clazz, column, key); return source.queryColumnList(selectedColumn, clazz, column, key);
} }
@Override
public <T, V extends Serializable> void queryColumnList(final CompletionHandler<List<V>, Serializable> handler, final String selectedColumn, final Class<T> clazz, final String column, @DynAttachment final Serializable key) {
List<V> rs = source.queryColumnList(selectedColumn, clazz, column, key);
if (handler != null) handler.completed(rs, key);
}
@Override @Override
public final <T, V extends Serializable> List<V> queryColumnList(String selectedColumn, Class<T> clazz, FilterBean bean) { public final <T, V extends Serializable> List<V> queryColumnList(String selectedColumn, Class<T> clazz, FilterBean bean) {
return queryColumnList(selectedColumn, clazz, FilterNodeBean.createFilterNode(bean)); return queryColumnList(selectedColumn, clazz, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final <T, V extends Serializable> void queryColumnList(final CompletionHandler<List<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, @DynAttachment final FilterBean bean) {
queryColumnList(handler, selectedColumn, clazz, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T, V extends Serializable> List<V> queryColumnList(String selectedColumn, Class<T> clazz, FilterNode node) { public <T, V extends Serializable> List<V> queryColumnList(String selectedColumn, Class<T> clazz, FilterNode node) {
return source.queryColumnList(selectedColumn, clazz, node); return source.queryColumnList(selectedColumn, clazz, node);
} }
@Override
public <T, V extends Serializable> void queryColumnList(final CompletionHandler<List<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, @DynAttachment final FilterNode node) {
List<V> rs = source.queryColumnList(selectedColumn, clazz, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public final <T, V extends Serializable> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, Flipper flipper, FilterBean bean) { public final <T, V extends Serializable> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, Flipper flipper, FilterBean bean) {
return queryColumnSheet(selectedColumn, clazz, flipper, FilterNodeBean.createFilterNode(bean)); return queryColumnSheet(selectedColumn, clazz, flipper, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final <T, V extends Serializable> void queryColumnSheet(final CompletionHandler<Sheet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final Flipper flipper, final FilterBean bean) {
queryColumnSheet(handler, selectedColumn, clazz, flipper, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T, V extends Serializable> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, Flipper flipper, FilterNode node) { public <T, V extends Serializable> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, Flipper flipper, FilterNode node) {
return source.queryColumnSheet(selectedColumn, clazz, flipper, node); return source.queryColumnSheet(selectedColumn, clazz, flipper, node);
} }
@Override
public <T, V extends Serializable> void queryColumnSheet(final CompletionHandler<Sheet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final Flipper flipper, @DynAttachment final FilterNode node) {
Sheet<V> rs = source.queryColumnSheet(selectedColumn, clazz, flipper, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> List<T> queryList(final Class<T> clazz, final String column, final Serializable key) { public <T> List<T> queryList(final Class<T> clazz, final String column, final Serializable key) {
return source.queryList(clazz, column, key); return source.queryList(clazz, column, key);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, Serializable> handler, final Class<T> clazz, final String column, @DynAttachment final Serializable key) {
List<T> rs = source.queryList(clazz, column, key);
if (handler != null) handler.completed(rs, key);
}
@Override @Override
public final <T> List<T> queryList(final Class<T> clazz, final FilterBean bean) { public final <T> List<T> queryList(final Class<T> clazz, final FilterBean bean) {
return queryList(clazz, FilterNodeBean.createFilterNode(bean)); return queryList(clazz, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final FilterBean bean) {
queryList(handler, clazz, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T> List<T> queryList(final Class<T> clazz, final FilterNode node) { public <T> List<T> queryList(final Class<T> clazz, final FilterNode node) {
return source.queryList(clazz, node); return source.queryList(clazz, node);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, @DynAttachment final FilterNode node) {
List<T> rs = source.queryList(clazz, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public final <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final FilterBean bean) { public final <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final FilterBean bean) {
return queryList(clazz, FilterNodeBean.createFilterNode(bean)); return queryList(clazz, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final FilterBean bean) {
queryList(handler, clazz, selects, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final FilterNode node) { public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final FilterNode node) {
return source.queryList(clazz, selects, node); return source.queryList(clazz, selects, node);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, @DynAttachment final FilterNode node) {
List<T> rs = source.queryList(clazz, selects, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final String column, final Serializable key) { public <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final String column, final Serializable key) {
return source.queryList(clazz, flipper, column, key); return source.queryList(clazz, flipper, column, key);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, Serializable> handler, final Class<T> clazz, final Flipper flipper, final String column, @DynAttachment final Serializable key) {
List<T> rs = source.queryList(clazz, flipper, column, key);
if (handler != null) handler.completed(rs, key);
}
@Override @Override
public final <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final FilterBean bean) { public final <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final FilterBean bean) {
return queryList(clazz, flipper, FilterNodeBean.createFilterNode(bean)); return queryList(clazz, flipper, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, final FilterBean bean) {
queryList(handler, clazz, flipper, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final FilterNode node) { public <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final FilterNode node) {
return source.queryList(clazz, flipper, node); return source.queryList(clazz, flipper, node);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, @DynAttachment final FilterNode node) {
List<T> rs = source.queryList(clazz, flipper, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public final <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) { public final <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) {
return queryList(clazz, selects, flipper, FilterNodeBean.createFilterNode(bean)); return queryList(clazz, selects, flipper, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, SelectColumn selects, final Flipper flipper, final FilterBean bean) {
queryList(handler, clazz, selects, flipper, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) { public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
return source.queryList(clazz, selects, flipper, node); return source.queryList(clazz, selects, flipper, node);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, SelectColumn selects, final Flipper flipper, @DynAttachment final FilterNode node) {
List<T> rs = source.queryList(clazz, selects, flipper, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public final <T> Sheet<T> querySheet(final Class<T> clazz, final Flipper flipper, final FilterBean bean) { public final <T> Sheet<T> querySheet(final Class<T> clazz, final Flipper flipper, final FilterBean bean) {
return querySheet(clazz, flipper, FilterNodeBean.createFilterNode(bean)); return querySheet(clazz, flipper, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final <T> void querySheet(final CompletionHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, final FilterBean bean) {
querySheet(handler, clazz, flipper, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T> Sheet<T> querySheet(final Class<T> clazz, final Flipper flipper, final FilterNode node) { public <T> Sheet<T> querySheet(final Class<T> clazz, final Flipper flipper, final FilterNode node) {
return source.querySheet(clazz, flipper, node); return source.querySheet(clazz, flipper, node);
} }
@Override
public <T> void querySheet(final CompletionHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, @DynAttachment final FilterNode node) {
Sheet<T> rs = source.querySheet(clazz, flipper, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public final <T> Sheet<T> querySheet(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) { public final <T> Sheet<T> querySheet(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) {
return querySheet(clazz, selects, flipper, FilterNodeBean.createFilterNode(bean)); return querySheet(clazz, selects, flipper, FilterNodeBean.createFilterNode(bean));
} }
@Override
public final <T> void querySheet(final CompletionHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) {
querySheet(handler, clazz, selects, flipper, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T> Sheet<T> querySheet(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) { public <T> Sheet<T> querySheet(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
return source.querySheet(clazz, selects, flipper, node); return source.querySheet(clazz, selects, flipper, node);
} }
@Override
public <T> void querySheet(final CompletionHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, @DynAttachment final FilterNode node) {
Sheet<T> rs = source.querySheet(clazz, selects, flipper, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public void close() throws Exception { public void close() throws Exception {
source.getClass().getMethod("close").invoke(source); source.getClass().getMethod("close").invoke(source);

View File

@@ -13,7 +13,9 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* 本地模式注解。 * 本地模式注解。
* 声明为LocalService的Service只能以本地模式存在 即使配置文件中配置成远程模式也将被忽略。 * 声明为LocalService的Service只能以本地模式存在 即使配置文件中配置成远程模式也将被忽略。
* *
* <p> 详情见: http://redkale.org * <p>
* 详情见: http://redkale.org
*
* @author zhangjx * @author zhangjx
*/ */
@Inherited @Inherited
@@ -21,5 +23,6 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Target({TYPE}) @Target({TYPE})
@Retention(RUNTIME) @Retention(RUNTIME)
public @interface LocalService { public @interface LocalService {
String comment() default ""; //备注描述
} }

View File

@@ -19,6 +19,6 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented @Documented
@Target({FIELD}) @Target({FIELD})
@Retention(RUNTIME) @Retention(RUNTIME)
public @interface DynRemote { public @interface RpcRemote {
} }

View File

@@ -20,6 +20,6 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented @Documented
@Target({PARAMETER}) @Target({PARAMETER})
@Retention(RUNTIME) @Retention(RUNTIME)
public @interface DynSourceAddress { public @interface RpcSourceAddress {
} }

View File

@@ -20,6 +20,6 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented @Documented
@Target({PARAMETER}) @Target({PARAMETER})
@Retention(RUNTIME) @Retention(RUNTIME)
public @interface DynTargetAddress { public @interface RpcTargetAddress {
} }

View File

@@ -10,7 +10,7 @@ import org.redkale.util.*;
/** /**
* 所有Service的实现类不得声明为final 允许远程模式的public方法都不能声明为final。 * 所有Service的实现类不得声明为final 允许远程模式的public方法都不能声明为final。
* 注意: "$"是一个很特殊的Service.name值 。 被标记为@Resource(name = "$") 的Service的资源名与所属父Service的资源名一致。 * 注意: "$"是一个很特殊的Service.name值 。 被标记为@Resource(name = "$") 的Service的资源名与所属父Service的资源名一致。
* *
* <blockquote><pre> * <blockquote><pre>
* Service的资源类型 * Service的资源类型
* 业务逻辑的Service通常有两种编写方式 * 业务逻辑的Service通常有两种编写方式
@@ -18,7 +18,7 @@ import org.redkale.util.*;
* 2、先定义业务的Service接口或抽象类再编写具体实现类。 * 2、先定义业务的Service接口或抽象类再编写具体实现类。
* 第二种方式需要在具体实现类上使用&#64;ResourceType指明资源注入的类型。 * 第二种方式需要在具体实现类上使用&#64;ResourceType指明资源注入的类型。
* </pre></blockquote> * </pre></blockquote>
* *
* <p> * <p>
* 详情见: http://redkale.org * 详情见: http://redkale.org
* *
@@ -44,4 +44,14 @@ public interface Service {
} }
/**
* Service的接口版本号
* <b>注: public方法的参数或返回类型或参数类型内部变更后改值必须进行改变</b>
*
* @return 接口版本号
*/
default int version() {
return 0;
}
} }

View File

@@ -34,7 +34,7 @@ public class WebSocketNodeService extends WebSocketNode implements Service {
} }
@Override @Override
public List<String> getOnlineRemoteAddresses(@DynTargetAddress InetSocketAddress targetAddress, Serializable groupid) { public List<String> getOnlineRemoteAddresses(@RpcTargetAddress InetSocketAddress targetAddress, Serializable groupid) {
if (localSncpAddress == null || !localSncpAddress.equals(targetAddress)) return remoteOnlineRemoteAddresses(targetAddress, groupid); if (localSncpAddress == null || !localSncpAddress.equals(targetAddress)) return remoteOnlineRemoteAddresses(targetAddress, groupid);
final Set<String> engineids = localNodes.get(groupid); final Set<String> engineids = localNodes.get(groupid);
if (engineids == null || engineids.isEmpty()) return null; if (engineids == null || engineids.isEmpty()) return null;
@@ -49,7 +49,7 @@ public class WebSocketNodeService extends WebSocketNode implements Service {
} }
@Override @Override
public int sendMessage(@DynTargetAddress InetSocketAddress addr, Serializable groupid, boolean recent, Serializable message, boolean last) { public int sendMessage(@RpcTargetAddress InetSocketAddress addr, Serializable groupid, boolean recent, Serializable message, boolean last) {
final Set<String> engineids = localNodes.get(groupid); final Set<String> engineids = localNodes.get(groupid);
if (engineids == null || engineids.isEmpty()) return RETCODE_GROUP_EMPTY; if (engineids == null || engineids.isEmpty()) return RETCODE_GROUP_EMPTY;
int code = RETCODE_GROUP_EMPTY; int code = RETCODE_GROUP_EMPTY;

View File

@@ -6,7 +6,6 @@
package org.redkale.source; package org.redkale.source;
import java.io.*; import java.io.*;
import java.nio.channels.*;
import java.util.*; import java.util.*;
/** /**
@@ -15,6 +14,7 @@ import java.util.*;
* @param <V> value的类型 * @param <V> value的类型
* <p> * <p>
* 详情见: http://redkale.org * 详情见: http://redkale.org
*
* @author zhangjx * @author zhangjx
*/ */
public interface CacheSource<K extends Serializable, V extends Object> { public interface CacheSource<K extends Serializable, V extends Object> {
@@ -51,36 +51,4 @@ public interface CacheSource<K extends Serializable, V extends Object> {
public void removeSetItem(final K key, final V value); public void removeSetItem(final K key, final V value);
//----------------------异步版---------------------------------
public void exists(final CompletionHandler<Boolean, K> handler, final K key);
public void get(final CompletionHandler<V, K> handler, final K key);
public void getAndRefresh(final CompletionHandler<V, K> handler, final K key, final int expireSeconds);
public void refresh(final CompletionHandler<Void, K> handler, final K key, final int expireSeconds);
public void set(final CompletionHandler<Void, K> handler, final K key, final V value);
public void set(final CompletionHandler<Void, K> handler, final int expireSeconds, final K key, final V value);
public void setExpireSeconds(final CompletionHandler<Void, K> handler, final K key, final int expireSeconds);
public void remove(final CompletionHandler<Void, K> handler, final K key);
public void getCollection(final CompletionHandler<Collection<V>, K> handler, final K key);
public void getCollectionAndRefresh(final CompletionHandler<Collection<V>, K> handler, final K key, final int expireSeconds);
public void appendListItem(final CompletionHandler<Void, K> handler, final K key, final V value);
public void removeListItem(final CompletionHandler<Void, K> handler, final K key, final V value);
public void appendSetItem(final CompletionHandler<Void, K> handler, final K key, final V value);
public void removeSetItem(final CompletionHandler<Void, K> handler, final K key, final V value);
default void isOpen(final CompletionHandler<Boolean, Void> handler) {
if (handler != null) handler.completed(Boolean.TRUE, null);
}
} }

View File

@@ -30,7 +30,7 @@ public class DataCallAttribute implements Attribute<Object, Serializable> {
Class cltmp = clazz; Class cltmp = clazz;
do { do {
for (Field field : cltmp.getDeclaredFields()) { for (Field field : cltmp.getDeclaredFields()) {
if (field.getAnnotation(javax.persistence.Id.class) == null) continue; if (field.getAnnotation(javax.persistence.GeneratedValue.class) == null) continue;
try { try {
rs = Attribute.create(cltmp, field); rs = Attribute.create(cltmp, field);
attributes.put(clazz, rs); attributes.put(clazz, rs);

View File

@@ -8,7 +8,6 @@ package org.redkale.source;
import java.io.*; import java.io.*;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URL; import java.net.URL;
import java.nio.channels.CompletionHandler;
import java.sql.*; import java.sql.*;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@@ -37,6 +36,10 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
static final String JDBC_NOTCONTAIN_SQLTEMPLATE = "javax.persistence.notcontain.sqltemplate"; static final String JDBC_NOTCONTAIN_SQLTEMPLATE = "javax.persistence.notcontain.sqltemplate";
static final String JDBC_TABLENOTEXIST_SQLSTATES = "javax.persistence.tablenotexist.sqlstates";
static final String JDBC_TABLECOPY_SQLTEMPLATE = "javax.persistence.tablecopy.sqltemplate";
static final String JDBC_URL = "javax.persistence.jdbc.url"; static final String JDBC_URL = "javax.persistence.jdbc.url";
static final String JDBC_USER = "javax.persistence.jdbc.user"; static final String JDBC_USER = "javax.persistence.jdbc.user";
@@ -66,9 +69,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
@Resource(name = "property.datasource.nodeid") @Resource(name = "property.datasource.nodeid")
private int nodeid; private int nodeid;
@Resource(name = "$")
private DataSQLListener writeListener;
@Resource(name = "$") @Resource(name = "$")
private DataCacheListener cacheListener; private DataCacheListener cacheListener;
@@ -326,82 +326,76 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void insert(final CompletionHandler<Void, T[]> handler, final T... values) {
insert(values);
if (handler != null) handler.completed(null, values);
}
private <T> void insert(final Connection conn, final EntityInfo<T> info, T... values) { private <T> void insert(final Connection conn, final EntityInfo<T> info, T... values) {
if (values.length == 0) return; if (values.length == 0) return;
try { try {
if (!info.isVirtualEntity()) { if (!info.isVirtualEntity()) {
final String sql = info.insertSQL; final String sql = info.getInsertSQL(values[0]);
final PreparedStatement prestmt = info.autoGenerated
? conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) : conn.prepareStatement(sql);
final Class primaryType = info.getPrimary().type(); final Class primaryType = info.getPrimary().type();
final Attribute primary = info.getPrimary(); final Attribute primary = info.getPrimary();
final boolean distributed = info.distributed; final boolean distributed = info.distributed;
Attribute<T, Serializable>[] attrs = info.insertAttributes; Attribute<T, Serializable>[] attrs = info.insertAttributes;
String[] sqls = null;
if (distributed && !info.initedPrimaryValue && primaryType.isPrimitive()) { //由DataSource生成主键 if (distributed && !info.initedPrimaryValue && primaryType.isPrimitive()) { //由DataSource生成主键
synchronized (info) { synchronized (info) {
if (!info.initedPrimaryValue) { //初始化最大主键值 if (!info.initedPrimaryValue) { //初始化最大主键值
Statement stmt = conn.createStatement(); try {
ResultSet rs = stmt.executeQuery("SELECT MAX(" + info.getPrimarySQLColumn() + ") FROM " + info.getTable(values[0])); Statement stmt = conn.createStatement();
if (rs.next()) { ResultSet rs = stmt.executeQuery("SELECT MAX(" + info.getPrimarySQLColumn() + ") FROM " + info.getTable(values[0]));
if (primaryType == int.class) { if (rs.next()) {
int v = rs.getInt(1) / info.allocationSize; if (primaryType == int.class) {
if (v > info.primaryValue.get()) info.primaryValue.set(v); int v = rs.getInt(1) / info.allocationSize;
} else { if (v > info.primaryValue.get()) info.primaryValue.set(v);
long v = rs.getLong(1) / info.allocationSize; } else {
if (v > info.primaryValue.get()) info.primaryValue.set(v); long v = rs.getLong(1) / info.allocationSize;
if (v > info.primaryValue.get()) info.primaryValue.set(v);
}
} }
rs.close();
stmt.close();
} catch (SQLException se) {
if (info.tableStrategy == null) throw se;
} }
rs.close();
stmt.close();
info.initedPrimaryValue = true; info.initedPrimaryValue = true;
} }
} }
} }
if (writeListener == null) { PreparedStatement prestmt = createInsertPreparedStatement(conn, sql, info, values);
for (final T value : values) { try {
int i = 0; prestmt.executeBatch();
if (distributed) info.createPrimaryValue(value); } catch (SQLException se) {
for (Attribute<T, Serializable> attr : attrs) { if (info.tableStrategy == null || !info.tablenotexistSqlstates.contains(';' + se.getSQLState() + ';')) throw se;
prestmt.setObject(++i, attr.get(value)); synchronized (info.tables) {
} final String oldTable = info.table;
prestmt.addBatch(); final String newTable = info.getTable(values[0]);
} if (!info.tables.contains(newTable)) {
} else { //调用writeListener回调接口 try {
char[] sqlchars = sql.toCharArray(); Statement st = conn.createStatement();
sqls = new String[values.length]; st.execute(info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable));
CharSequence[] ps = new CharSequence[attrs.length]; st.close();
int index = 0; info.tables.add(newTable);
for (final T value : values) { } catch (SQLException sqle) { //多进程并发时可能会出现重复建表
int i = 0; if (newTable.indexOf('.') > 0 && info.tablenotexistSqlstates.contains(';' + se.getSQLState() + ';')) {
if (distributed) info.createPrimaryValue(value); Statement st = conn.createStatement();
for (Attribute<T, Serializable> attr : attrs) { st.execute("CREATE DATABASE " + newTable.substring(0, newTable.indexOf('.')));
Object a = attr.get(value); st.close();
ps[i] = FilterNode.formatToString(a); try {
prestmt.setObject(++i, a); st = conn.createStatement();
} st.execute(info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable));
prestmt.addBatch(); st.close();
//----------------------------- info.tables.add(newTable);
StringBuilder sb = new StringBuilder(128); } catch (SQLException sqle2) {
i = 0; logger.log(Level.SEVERE, "create table2(" + info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable) + ") error", sqle2);
for (char ch : sqlchars) { }
if (ch == '?') { } else {
sb.append(ps[i++]); logger.log(Level.SEVERE, "create table(" + info.tablecopySQL.replace("${newtable}", newTable).replace("${oldtable}", oldTable) + ") error", sqle);
} else { }
sb.append(ch);
} }
} }
sqls[index++] = sb.toString();
} }
prestmt.close();
prestmt = createInsertPreparedStatement(conn, sql, info, values);
prestmt.executeBatch();
} }
prestmt.executeBatch();
if (writeListener != null) writeListener.insert(sqls);
if (info.autoGenerated) { //由数据库自动生成主键值 if (info.autoGenerated) { //由数据库自动生成主键值
ResultSet set = prestmt.getGeneratedKeys(); ResultSet set = prestmt.getGeneratedKeys();
int i = -1; int i = -1;
@@ -452,6 +446,23 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
private <T> PreparedStatement createInsertPreparedStatement(final Connection conn, final String sql,
final EntityInfo<T> info, T... values) throws SQLException {
Attribute<T, Serializable>[] attrs = info.insertAttributes;
final PreparedStatement prestmt = info.autoGenerated
? conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) : conn.prepareStatement(sql);
for (final T value : values) {
int i = 0;
if (info.distributed || info.autouuid) info.createPrimaryValue(value);
for (Attribute<T, Serializable> attr : attrs) {
prestmt.setObject(++i, attr.get(value));
}
prestmt.addBatch();
}
return prestmt;
}
public <T> void insertCache(Class<T> clazz, T... values) { public <T> void insertCache(Class<T> clazz, T... values) {
if (values.length == 0) return; if (values.length == 0) return;
final EntityInfo<T> info = loadEntityInfo(clazz); final EntityInfo<T> info = loadEntityInfo(clazz);
@@ -485,12 +496,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void delete(final CompletionHandler<Void, T[]> handler, final T... values) {
delete(values);
if (handler != null) handler.completed(null, values);
}
private <T> void delete(final Connection conn, final EntityInfo<T> info, T... values) { private <T> void delete(final Connection conn, final EntityInfo<T> info, T... values) {
if (values.length == 0) return; if (values.length == 0) return;
final Attribute primary = info.getPrimary(); final Attribute primary = info.getPrimary();
@@ -517,28 +522,18 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void delete(final CompletionHandler<Void, Serializable[]> handler, final Class<T> clazz, final Serializable... ids) {
delete(clazz, ids);
if (handler != null) handler.completed(null, ids);
}
private <T> void delete(final Connection conn, final EntityInfo<T> info, Serializable... keys) { private <T> void delete(final Connection conn, final EntityInfo<T> info, Serializable... keys) {
if (keys.length == 0) return; if (keys.length == 0) return;
try { try {
if (!info.isVirtualEntity()) { if (!info.isVirtualEntity()) {
final Statement stmt = conn.createStatement(); final Statement stmt = conn.createStatement();
String[] sqls = new String[keys.length];
int index = -1;
for (Serializable key : keys) { for (Serializable key : keys) {
String sql = "DELETE FROM " + info.getTable(keys) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(key); String sql = "DELETE FROM " + info.getTable(keys) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(key);
sqls[++index] = sql;
if (debug.get()) logger.finest(info.getType().getSimpleName() + " delete sql=" + sql); if (debug.get()) logger.finest(info.getType().getSimpleName() + " delete sql=" + sql);
stmt.addBatch(sql); stmt.addBatch(sql);
} }
stmt.executeBatch(); stmt.executeBatch();
stmt.close(); stmt.close();
if (writeListener != null) writeListener.delete(sqls);
} }
//------------------------------------ //------------------------------------
final EntityCache<T> cache = info.getCache(); final EntityCache<T> cache = info.getCache();
@@ -567,12 +562,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void delete(final CompletionHandler<Void, FilterNode> handler, final Class<T> clazz, final FilterNode node) {
delete(clazz, node);
if (handler != null) handler.completed(null, node);
}
private <T> void delete(final Connection conn, final EntityInfo<T> info, final FilterNode node) { private <T> void delete(final Connection conn, final EntityInfo<T> info, final FilterNode node) {
try { try {
if (!info.isVirtualEntity()) { if (!info.isVirtualEntity()) {
@@ -584,7 +573,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
final Statement stmt = conn.createStatement(); final Statement stmt = conn.createStatement();
stmt.execute(sql); stmt.execute(sql);
stmt.close(); stmt.close();
if (writeListener != null) writeListener.delete(sql);
} }
//------------------------------------ //------------------------------------
final EntityCache<T> cache = info.getCache(); final EntityCache<T> cache = info.getCache();
@@ -629,60 +617,25 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void update(final CompletionHandler<Void, T[]> handler, final T... values) {
update(values);
if (handler != null) handler.completed(null, values);
}
private <T> void update(final Connection conn, final EntityInfo<T> info, T... values) { private <T> void update(final Connection conn, final EntityInfo<T> info, T... values) {
try { try {
Class clazz = info.getType(); Class clazz = info.getType();
if (!info.isVirtualEntity()) { if (!info.isVirtualEntity()) {
if (debug.get()) logger.finest(clazz.getSimpleName() + " update sql=" + info.updateSQL); final String updateSQL = info.getUpdateSQL(values[0]);
if (debug.get()) logger.finest(clazz.getSimpleName() + " update sql=" + updateSQL);
final Attribute<T, Serializable> primary = info.getPrimary(); final Attribute<T, Serializable> primary = info.getPrimary();
final PreparedStatement prestmt = conn.prepareStatement(info.updateSQL); final PreparedStatement prestmt = conn.prepareStatement(updateSQL);
Attribute<T, Serializable>[] attrs = info.updateAttributes; Attribute<T, Serializable>[] attrs = info.updateAttributes;
String[] sqls = null; for (final T value : values) {
if (writeListener == null) { int i = 0;
for (final T value : values) { for (Attribute<T, Serializable> attr : attrs) {
int i = 0; prestmt.setObject(++i, attr.get(value));
for (Attribute<T, Serializable> attr : attrs) {
prestmt.setObject(++i, attr.get(value));
}
prestmt.setObject(++i, primary.get(value));
prestmt.addBatch();
}
} else {
char[] sqlchars = info.updateSQL.toCharArray();
sqls = new String[values.length];
CharSequence[] ps = new CharSequence[attrs.length];
int index = 0;
for (final T value : values) {
int i = 0;
for (Attribute<T, Serializable> attr : attrs) {
Object a = attr.get(value);
ps[i] = FilterNode.formatToString(a);
prestmt.setObject(++i, a);
}
prestmt.setObject(++i, primary.get(value));
prestmt.addBatch();
//-----------------------------
StringBuilder sb = new StringBuilder(128);
i = 0;
for (char ch : sqlchars) {
if (ch == '?') {
sb.append(ps[i++]);
} else {
sb.append(ch);
}
}
sqls[index++] = sb.toString();
} }
prestmt.setObject(++i, primary.get(value));
prestmt.addBatch();
} }
prestmt.executeBatch(); prestmt.executeBatch();
prestmt.close(); prestmt.close();
if (writeListener != null) writeListener.update(sqls);
} }
//--------------------------------------------------- //---------------------------------------------------
final EntityCache<T> cache = info.getCache(); final EntityCache<T> cache = info.getCache();
@@ -720,22 +673,15 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void updateColumn(final CompletionHandler<Void, Serializable> handler, final Class<T> clazz, final Serializable id, final String column, final Serializable value) {
updateColumn(clazz, id, column, value);
if (handler != null) handler.completed(null, id);
}
private <T> void updateColumn(Connection conn, final EntityInfo<T> info, Serializable id, String column, Serializable value) { private <T> void updateColumn(Connection conn, final EntityInfo<T> info, Serializable id, String column, Serializable value) {
try { try {
if (!info.isVirtualEntity()) { if (!info.isVirtualEntity()) {
String sql = "UPDATE " + info.getTable(id) + " SET " + info.getSQLColumn(null, column) + " = " String sql = "UPDATE " + info.getTable(id) + " SET " + info.getSQLColumn(null, column) + " = "
+ FilterNode.formatToString(value) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(id); + info.formatToString(value) + " WHERE " + info.getPrimarySQLColumn() + " = " + FilterNode.formatToString(id);
if (debug.get()) logger.finest(info.getType().getSimpleName() + " update sql=" + sql); if (debug.get()) logger.finest(info.getType().getSimpleName() + " update sql=" + sql);
final Statement stmt = conn.createStatement(); final Statement stmt = conn.createStatement();
stmt.execute(sql); stmt.execute(sql);
stmt.close(); stmt.close();
if (writeListener != null) writeListener.update(sql);
} }
//--------------------------------------------------- //---------------------------------------------------
final EntityCache<T> cache = info.getCache(); final EntityCache<T> cache = info.getCache();
@@ -773,12 +719,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void updateColumn(final CompletionHandler<Void, FilterNode> handler, final Class<T> clazz, final String column, final Serializable value, FilterNode node) {
updateColumn(clazz, column, value, node);
if (handler != null) handler.completed(null, node);
}
private <T> void updateColumn(Connection conn, final EntityInfo<T> info, String column, Serializable value, FilterNode node) { private <T> void updateColumn(Connection conn, final EntityInfo<T> info, String column, Serializable value, FilterNode node) {
try { try {
if (!info.isVirtualEntity()) { if (!info.isVirtualEntity()) {
@@ -787,12 +727,11 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
CharSequence where = node.createSQLExpress(info, joinTabalis); CharSequence where = node.createSQLExpress(info, joinTabalis);
String sql = "UPDATE " + info.getTable(node) + " a SET " + info.getSQLColumn("a", column) + " = " String sql = "UPDATE " + info.getTable(node) + " a SET " + info.getSQLColumn("a", column) + " = "
+ FilterNode.formatToString(value) + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where)); + info.formatToString(value) + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where));
if (debug.get()) logger.finest(info.getType().getSimpleName() + " update sql=" + sql); if (debug.get()) logger.finest(info.getType().getSimpleName() + " update sql=" + sql);
final Statement stmt = conn.createStatement(); final Statement stmt = conn.createStatement();
stmt.execute(sql); stmt.execute(sql);
stmt.close(); stmt.close();
if (writeListener != null) writeListener.update(sql);
} }
//--------------------------------------------------- //---------------------------------------------------
final EntityCache<T> cache = info.getCache(); final EntityCache<T> cache = info.getCache();
@@ -831,12 +770,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void updateColumnIncrement(final CompletionHandler<Void, Serializable> handler, final Class<T> clazz, final Serializable id, final String column, long incvalue) {
updateColumnIncrement(clazz, id, column, incvalue);
if (handler != null) handler.completed(null, id);
}
private <T> void updateColumnIncrement(Connection conn, final EntityInfo<T> info, Serializable id, String column, long incvalue) { private <T> void updateColumnIncrement(Connection conn, final EntityInfo<T> info, Serializable id, String column, long incvalue) {
try { try {
if (!info.isVirtualEntity()) { if (!info.isVirtualEntity()) {
@@ -847,7 +780,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
final Statement stmt = conn.createStatement(); final Statement stmt = conn.createStatement();
stmt.execute(sql); stmt.execute(sql);
stmt.close(); stmt.close();
if (writeListener != null) writeListener.update(sql);
} }
//--------------------------------------------------- //---------------------------------------------------
final EntityCache<T> cache = info.getCache(); final EntityCache<T> cache = info.getCache();
@@ -887,12 +819,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void updateColumnAnd(final CompletionHandler<Void, Serializable> handler, final Class<T> clazz, final Serializable id, final String column, long incvalue) {
updateColumnAnd(clazz, id, column, incvalue);
if (handler != null) handler.completed(null, id);
}
private <T> void updateColumnAnd(Connection conn, final EntityInfo<T> info, Serializable id, String column, long andvalue) { private <T> void updateColumnAnd(Connection conn, final EntityInfo<T> info, Serializable id, String column, long andvalue) {
try { try {
if (!info.isVirtualEntity()) { if (!info.isVirtualEntity()) {
@@ -903,7 +829,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
final Statement stmt = conn.createStatement(); final Statement stmt = conn.createStatement();
stmt.execute(sql); stmt.execute(sql);
stmt.close(); stmt.close();
if (writeListener != null) writeListener.update(sql);
} }
//--------------------------------------------------- //---------------------------------------------------
final EntityCache<T> cache = info.getCache(); final EntityCache<T> cache = info.getCache();
@@ -943,12 +868,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void updateColumnOr(final CompletionHandler<Void, Serializable> handler, final Class<T> clazz, final Serializable id, final String column, long incvalue) {
updateColumnOr(clazz, id, column, incvalue);
if (handler != null) handler.completed(null, id);
}
private <T> void updateColumnOr(Connection conn, final EntityInfo<T> info, Serializable id, String column, long orvalue) { private <T> void updateColumnOr(Connection conn, final EntityInfo<T> info, Serializable id, String column, long orvalue) {
try { try {
if (!info.isVirtualEntity()) { if (!info.isVirtualEntity()) {
@@ -959,7 +878,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
final Statement stmt = conn.createStatement(); final Statement stmt = conn.createStatement();
stmt.execute(sql); stmt.execute(sql);
stmt.close(); stmt.close();
if (writeListener != null) writeListener.update(sql);
} }
//--------------------------------------------------- //---------------------------------------------------
final EntityCache<T> cache = info.getCache(); final EntityCache<T> cache = info.getCache();
@@ -996,12 +914,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void updateColumns(final CompletionHandler<Void, T> handler, final T bean, final String... columns) {
updateColumns(bean, columns);
if (handler != null) handler.completed(null, bean);
}
private <T> void updateColumns(final Connection conn, final EntityInfo<T> info, final T bean, final String... columns) { private <T> void updateColumns(final Connection conn, final EntityInfo<T> info, final T bean, final String... columns) {
if (bean == null || columns.length < 1) return; if (bean == null || columns.length < 1) return;
try { try {
@@ -1016,7 +928,7 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
attrs.add(attr); attrs.add(attr);
if (!virtual) { if (!virtual) {
if (setsql.length() > 0) setsql.append(", "); if (setsql.length() > 0) setsql.append(", ");
setsql.append(info.getSQLColumn(null, col)).append(" = ").append(FilterNode.formatToString(attr.get(bean))); setsql.append(info.getSQLColumn(null, col)).append(" = ").append(info.formatToString(attr.get(bean)));
} }
} }
if (!virtual) { if (!virtual) {
@@ -1025,7 +937,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
final Statement stmt = conn.createStatement(); final Statement stmt = conn.createStatement();
stmt.execute(sql); stmt.execute(sql);
stmt.close(); stmt.close();
if (writeListener != null) writeListener.update(sql);
} }
//--------------------------------------------------- //---------------------------------------------------
final EntityCache<T> cache = info.getCache(); final EntityCache<T> cache = info.getCache();
@@ -1060,12 +971,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void updateColumns(final CompletionHandler<Void, FilterNode> handler, final T bean, final FilterNode node, final String... columns) {
updateColumns(bean, node, columns);
if (handler != null) handler.completed(null, node);
}
private <T> void updateColumns(final Connection conn, final EntityInfo<T> info, final T bean, final FilterNode node, final String... columns) { private <T> void updateColumns(final Connection conn, final EntityInfo<T> info, final T bean, final FilterNode node, final String... columns) {
if (bean == null || node == null || columns.length < 1) return; if (bean == null || node == null || columns.length < 1) return;
try { try {
@@ -1080,7 +985,7 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
attrs.add(attr); attrs.add(attr);
if (!virtual) { if (!virtual) {
if (setsql.length() > 0) setsql.append(", "); if (setsql.length() > 0) setsql.append(", ");
setsql.append(info.getSQLColumn("a", col)).append(" = ").append(FilterNode.formatToString(attr.get(bean))); setsql.append(info.getSQLColumn("a", col)).append(" = ").append(info.formatToString(attr.get(bean)));
} }
} }
if (!virtual) { if (!virtual) {
@@ -1094,7 +999,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
final Statement stmt = conn.createStatement(); final Statement stmt = conn.createStatement();
stmt.execute(sql); stmt.execute(sql);
stmt.close(); stmt.close();
if (writeListener != null) writeListener.update(sql);
} }
//--------------------------------------------------- //---------------------------------------------------
final EntityCache<T> cache = info.getCache(); final EntityCache<T> cache = info.getCache();
@@ -1131,34 +1035,38 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
//-----------------------getNumberResult----------------------------- //-----------------------getNumberResult-----------------------------
@Override @Override
public Number getNumberResult(final Class entityClass, final FilterFunc func, final String column) { public Number getNumberResult(final Class entityClass, final FilterFunc func, final String column) {
return getNumberResult(entityClass, func, column, (FilterNode) null); return getNumberResult(entityClass, func, null, column, (FilterNode) null);
}
@Override
public void getNumberResult(final CompletionHandler<Number, String> handler, final Class entityClass, final FilterFunc func, final String column) {
Number rs = getNumberResult(entityClass, func, column);
if (handler != null) handler.completed(rs, column);
} }
@Override @Override
public Number getNumberResult(final Class entityClass, final FilterFunc func, final String column, FilterBean bean) { public Number getNumberResult(final Class entityClass, final FilterFunc func, final String column, FilterBean bean) {
return getNumberResult(entityClass, func, column, FilterNodeBean.createFilterNode(bean)); return getNumberResult(entityClass, func, null, column, FilterNodeBean.createFilterNode(bean));
}
@Override
public void getNumberResult(final CompletionHandler<Number, FilterNode> handler, final Class entityClass, final FilterFunc func, final String column, final FilterBean bean) {
getNumberResult(handler, entityClass, func, column, FilterNodeBean.createFilterNode(bean));
} }
@Override @Override
public Number getNumberResult(final Class entityClass, final FilterFunc func, final String column, final FilterNode node) { public Number getNumberResult(final Class entityClass, final FilterFunc func, final String column, final FilterNode node) {
return getNumberResult(entityClass, func, null, column, node);
}
@Override
public Number getNumberResult(final Class entityClass, final FilterFunc func, final Number defVal, final String column) {
return getNumberResult(entityClass, func, defVal, column, (FilterNode) null);
}
@Override
public Number getNumberResult(final Class entityClass, final FilterFunc func, final Number defVal, final String column, FilterBean bean) {
return getNumberResult(entityClass, func, defVal, column, FilterNodeBean.createFilterNode(bean));
}
@Override
public Number getNumberResult(final Class entityClass, final FilterFunc func, final Number defVal, final String column, final FilterNode node) {
final Connection conn = createReadSQLConnection(); final Connection conn = createReadSQLConnection();
try { try {
final EntityInfo info = loadEntityInfo(entityClass); final EntityInfo info = loadEntityInfo(entityClass);
final EntityCache cache = info.getCache(); final EntityCache cache = info.getCache();
if (cache != null && (info.isVirtualEntity() || cache.isFullLoaded())) { if (cache != null && (info.isVirtualEntity() || cache.isFullLoaded())) {
if (node == null || node.isCacheUseable(this)) { if (node == null || node.isCacheUseable(this)) {
return cache.getNumberResult(func, column, node); return cache.getNumberResult(func, defVal, column, node);
} }
} }
final Map<Class, String> joinTabalis = node == null ? null : node.getJoinTabalis(); final Map<Class, String> joinTabalis = node == null ? null : node.getJoinTabalis();
@@ -1168,7 +1076,7 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
+ (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where)); + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where));
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(entityClass.getSimpleName() + " single sql=" + sql); if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(entityClass.getSimpleName() + " single sql=" + sql);
final PreparedStatement prestmt = conn.prepareStatement(sql); final PreparedStatement prestmt = conn.prepareStatement(sql);
Number rs = null; Number rs = defVal;
ResultSet set = prestmt.executeQuery(); ResultSet set = prestmt.executeQuery();
if (set.next()) { if (set.next()) {
rs = (Number) set.getObject(1); rs = (Number) set.getObject(1);
@@ -1183,34 +1091,17 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public void getNumberResult(final CompletionHandler<Number, FilterNode> handler, final Class entityClass, final FilterFunc func, final String column, final FilterNode node) {
Number rs = getNumberResult(entityClass, func, column, node);
if (handler != null) handler.completed(rs, node);
}
//-----------------------queryColumnMap----------------------------- //-----------------------queryColumnMap-----------------------------
@Override @Override
public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, FilterFunc func, final String funcColumn) { public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, FilterFunc func, final String funcColumn) {
return queryColumnMap(entityClass, keyColumn, func, funcColumn, (FilterNode) null); return queryColumnMap(entityClass, keyColumn, func, funcColumn, (FilterNode) null);
} }
@Override
public <T, K extends Serializable, N extends Number> void queryColumnMap(final CompletionHandler<Map<K, N>, String> handler, final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn) {
Map<K, N> map = queryColumnMap(entityClass, keyColumn, func, funcColumn);
if (handler != null) handler.completed(map, funcColumn);
}
@Override @Override
public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, FilterFunc func, final String funcColumn, FilterBean bean) { public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, FilterFunc func, final String funcColumn, FilterBean bean) {
return queryColumnMap(entityClass, keyColumn, func, funcColumn, FilterNodeBean.createFilterNode(bean)); return queryColumnMap(entityClass, keyColumn, func, funcColumn, FilterNodeBean.createFilterNode(bean));
} }
@Override
public <T, K extends Serializable, N extends Number> void queryColumnMap(final CompletionHandler<Map<K, N>, FilterNode> handler, final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn, final FilterBean bean) {
queryColumnMap(handler, entityClass, keyColumn, func, funcColumn, FilterNodeBean.createFilterNode(bean));
}
@Override @Override
public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn, FilterNode node) { public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn, FilterNode node) {
final Connection conn = createReadSQLConnection(); final Connection conn = createReadSQLConnection();
@@ -1247,12 +1138,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T, K extends Serializable, N extends Number> void queryColumnMap(final CompletionHandler<Map<K, N>, FilterNode> handler, final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn, final FilterNode node) {
Map<K, N> map = queryColumnMap(entityClass, keyColumn, func, funcColumn, node);
if (handler != null) handler.completed(map, node);
}
//-----------------------find---------------------------- //-----------------------find----------------------------
/** /**
* 根据主键获取对象 * 根据主键获取对象
@@ -1268,12 +1153,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
return find(clazz, (SelectColumn) null, pk); return find(clazz, (SelectColumn) null, pk);
} }
@Override
public <T> void find(final CompletionHandler<T, Serializable> handler, final Class<T> clazz, final Serializable pk) {
T rs = find(clazz, pk);
if (handler != null) handler.completed(rs, pk);
}
@Override @Override
public <T> T find(Class<T> clazz, final SelectColumn selects, Serializable pk) { public <T> T find(Class<T> clazz, final SelectColumn selects, Serializable pk) {
final EntityInfo<T> info = loadEntityInfo(clazz); final EntityInfo<T> info = loadEntityInfo(clazz);
@@ -1301,58 +1180,26 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void find(final CompletionHandler<T, Serializable> handler, final Class<T> clazz, final SelectColumn selects, final Serializable pk) {
T rs = find(clazz, selects, pk);
if (handler != null) handler.completed(rs, pk);
}
@Override @Override
public <T> T find(final Class<T> clazz, final String column, final Serializable key) { public <T> T find(final Class<T> clazz, final String column, final Serializable key) {
return find(clazz, null, FilterNode.create(column, key)); return find(clazz, null, FilterNode.create(column, key));
} }
@Override
public <T> void find(final CompletionHandler<T, Serializable> handler, final Class<T> clazz, final String column, final Serializable key) {
T rs = find(clazz, column, key);
if (handler != null) handler.completed(rs, key);
}
@Override @Override
public <T> T find(final Class<T> clazz, final FilterBean bean) { public <T> T find(final Class<T> clazz, final FilterBean bean) {
return find(clazz, null, FilterNodeBean.createFilterNode(bean)); return find(clazz, null, FilterNodeBean.createFilterNode(bean));
} }
@Override
public <T> void find(final CompletionHandler<T, FilterNode> handler, final Class<T> clazz, final FilterBean bean) {
FilterNode node = FilterNodeBean.createFilterNode(bean);
T rs = find(clazz, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> T find(final Class<T> clazz, final FilterNode node) { public <T> T find(final Class<T> clazz, final FilterNode node) {
return find(clazz, null, node); return find(clazz, null, node);
} }
@Override
public <T> void find(final CompletionHandler<T, FilterNode> handler, final Class<T> clazz, final FilterNode node) {
T rs = find(clazz, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> T find(final Class<T> clazz, final SelectColumn selects, final FilterBean bean) { public <T> T find(final Class<T> clazz, final SelectColumn selects, final FilterBean bean) {
return find(clazz, selects, FilterNodeBean.createFilterNode(bean)); return find(clazz, selects, FilterNodeBean.createFilterNode(bean));
} }
@Override
public <T> void find(final CompletionHandler<T, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final FilterBean bean) {
FilterNode node = FilterNodeBean.createFilterNode(bean);
T rs = find(clazz, selects, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> T find(final Class<T> clazz, final SelectColumn selects, final FilterNode node) { public <T> T find(final Class<T> clazz, final SelectColumn selects, final FilterNode node) {
final EntityInfo<T> info = loadEntityInfo(clazz); final EntityInfo<T> info = loadEntityInfo(clazz);
@@ -1380,12 +1227,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void find(final CompletionHandler<T, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final FilterNode node) {
T rs = find(clazz, selects, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> boolean exists(Class<T> clazz, Serializable pk) { public <T> boolean exists(Class<T> clazz, Serializable pk) {
final EntityInfo<T> info = loadEntityInfo(clazz); final EntityInfo<T> info = loadEntityInfo(clazz);
@@ -1412,24 +1253,11 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void exists(final CompletionHandler<Boolean, Serializable> handler, final Class<T> clazz, final Serializable pk) {
boolean rs = exists(clazz, pk);
if (handler != null) handler.completed(rs, pk);
}
@Override @Override
public <T> boolean exists(final Class<T> clazz, final FilterBean bean) { public <T> boolean exists(final Class<T> clazz, final FilterBean bean) {
return exists(clazz, FilterNodeBean.createFilterNode(bean)); return exists(clazz, FilterNodeBean.createFilterNode(bean));
} }
@Override
public <T> void exists(final CompletionHandler<Boolean, FilterNode> handler, final Class<T> clazz, final FilterBean bean) {
FilterNode node = FilterNodeBean.createFilterNode(bean);
boolean rs = exists(clazz, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> boolean exists(final Class<T> clazz, final FilterNode node) { public <T> boolean exists(final Class<T> clazz, final FilterNode node) {
final EntityInfo<T> info = loadEntityInfo(clazz); final EntityInfo<T> info = loadEntityInfo(clazz);
@@ -1456,81 +1284,37 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
} }
} }
@Override
public <T> void exists(final CompletionHandler<Boolean, FilterNode> handler, final Class<T> clazz, final FilterNode node) {
boolean rs = exists(clazz, node);
if (handler != null) handler.completed(rs, node);
}
//-----------------------list set---------------------------- //-----------------------list set----------------------------
@Override @Override
public <T, V extends Serializable> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, String column, Serializable key) { public <T, V extends Serializable> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, String column, Serializable key) {
return queryColumnSet(selectedColumn, clazz, FilterNode.create(column, key)); return queryColumnSet(selectedColumn, clazz, FilterNode.create(column, key));
} }
@Override
public <T, V extends Serializable> void queryColumnSet(final CompletionHandler<HashSet<V>, Serializable> handler, final String selectedColumn, final Class<T> clazz, final String column, final Serializable key) {
HashSet<V> rs = queryColumnSet(selectedColumn, clazz, column, key);
if (handler != null) handler.completed(rs, key);
}
@Override @Override
public <T, V extends Serializable> HashSet<V> queryColumnSet(final String selectedColumn, final Class<T> clazz, final FilterBean bean) { public <T, V extends Serializable> HashSet<V> queryColumnSet(final String selectedColumn, final Class<T> clazz, final FilterBean bean) {
return new LinkedHashSet<>(queryColumnList(selectedColumn, clazz, bean)); return new LinkedHashSet<>(queryColumnList(selectedColumn, clazz, bean));
} }
@Override
public <T, V extends Serializable> void queryColumnSet(final CompletionHandler<HashSet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final FilterBean bean) {
FilterNode node = FilterNodeBean.createFilterNode(bean);
HashSet<V> rs = queryColumnSet(selectedColumn, clazz, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T, V extends Serializable> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, FilterNode node) { public <T, V extends Serializable> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, FilterNode node) {
return new LinkedHashSet<>(queryColumnList(selectedColumn, clazz, node)); return new LinkedHashSet<>(queryColumnList(selectedColumn, clazz, node));
} }
@Override
public <T, V extends Serializable> void queryColumnSet(final CompletionHandler<HashSet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final FilterNode node) {
HashSet<V> rs = queryColumnSet(selectedColumn, clazz, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T, V extends Serializable> List<V> queryColumnList(final String selectedColumn, final Class<T> clazz, final String column, final Serializable key) { public <T, V extends Serializable> List<V> queryColumnList(final String selectedColumn, final Class<T> clazz, final String column, final Serializable key) {
return queryColumnList(selectedColumn, clazz, FilterNode.create(column, key)); return queryColumnList(selectedColumn, clazz, FilterNode.create(column, key));
} }
@Override
public <T, V extends Serializable> void queryColumnList(final CompletionHandler<List<V>, Serializable> handler, final String selectedColumn, final Class<T> clazz, final String column, final Serializable key) {
List<V> rs = queryColumnList(selectedColumn, clazz, column, key);
if (handler != null) handler.completed(rs, key);
}
@Override @Override
public <T, V extends Serializable> List<V> queryColumnList(final String selectedColumn, final Class<T> clazz, final FilterBean bean) { public <T, V extends Serializable> List<V> queryColumnList(final String selectedColumn, final Class<T> clazz, final FilterBean bean) {
return (List<V>) queryColumnSheet(selectedColumn, clazz, null, bean).list(true); return (List<V>) queryColumnSheet(selectedColumn, clazz, null, bean).list(true);
} }
@Override
public <T, V extends Serializable> void queryColumnList(final CompletionHandler<List<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final FilterBean bean) {
final FilterNode node = FilterNodeBean.createFilterNode(bean);
List<V> rs = queryColumnList(selectedColumn, clazz, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T, V extends Serializable> List<V> queryColumnList(final String selectedColumn, final Class<T> clazz, final FilterNode node) { public <T, V extends Serializable> List<V> queryColumnList(final String selectedColumn, final Class<T> clazz, final FilterNode node) {
return (List<V>) queryColumnSheet(selectedColumn, clazz, null, node).list(true); return (List<V>) queryColumnSheet(selectedColumn, clazz, null, node).list(true);
} }
@Override
public <T, V extends Serializable> void queryColumnList(final CompletionHandler<List<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final FilterNode node) {
List<V> rs = queryColumnList(selectedColumn, clazz, node);
if (handler != null) handler.completed(rs, node);
}
/** /**
* 根据指定参数查询对象某个字段的集合 * 根据指定参数查询对象某个字段的集合
* <p> * <p>
@@ -1548,13 +1332,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
return queryColumnSheet(selectedColumn, clazz, flipper, FilterNodeBean.createFilterNode(bean)); return queryColumnSheet(selectedColumn, clazz, flipper, FilterNodeBean.createFilterNode(bean));
} }
@Override
public <T, V extends Serializable> void queryColumnSheet(final CompletionHandler<Sheet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final Flipper flipper, final FilterBean bean) {
final FilterNode node = FilterNodeBean.createFilterNode(bean);
Sheet<V> rs = queryColumnSheet(selectedColumn, clazz, flipper, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T, V extends Serializable> Sheet<V> queryColumnSheet(final String selectedColumn, final Class<T> clazz, final Flipper flipper, final FilterNode node) { public <T, V extends Serializable> Sheet<V> queryColumnSheet(final String selectedColumn, final Class<T> clazz, final Flipper flipper, final FilterNode node) {
Sheet<T> sheet = querySheet(true, true, clazz, SelectColumn.createIncludes(selectedColumn), flipper, node); Sheet<T> sheet = querySheet(true, true, clazz, SelectColumn.createIncludes(selectedColumn), flipper, node);
@@ -1571,12 +1348,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
return rs; return rs;
} }
@Override
public <T, V extends Serializable> void queryColumnSheet(final CompletionHandler<Sheet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final Flipper flipper, final FilterNode node) {
Sheet<V> rs = queryColumnSheet(selectedColumn, clazz, flipper, node);
if (handler != null) handler.completed(rs, node);
}
private <K extends Serializable, T> Map<K, T> formatMap(final Class<T> clazz, final Collection<T> list) { private <K extends Serializable, T> Map<K, T> formatMap(final Class<T> clazz, final Collection<T> list) {
Map<K, T> map = new LinkedHashMap<>(); Map<K, T> map = new LinkedHashMap<>();
if (list == null || list.isEmpty()) return map; if (list == null || list.isEmpty()) return map;
@@ -1602,12 +1373,6 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
return queryList(clazz, FilterNode.create(column, key)); return queryList(clazz, FilterNode.create(column, key));
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, Serializable> handler, final Class<T> clazz, final String column, final Serializable key) {
List<T> rs = queryList(clazz, column, key);
if (handler != null) handler.completed(rs, key);
}
/** /**
* 根据过滤对象FilterBean查询对象集合 * 根据过滤对象FilterBean查询对象集合
* *
@@ -1622,24 +1387,11 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
return queryList(clazz, (SelectColumn) null, bean); return queryList(clazz, (SelectColumn) null, bean);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final FilterBean bean) {
FilterNode node = FilterNodeBean.createFilterNode(bean);
List<T> rs = queryList(clazz, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> List<T> queryList(final Class<T> clazz, final FilterNode node) { public <T> List<T> queryList(final Class<T> clazz, final FilterNode node) {
return queryList(clazz, (SelectColumn) null, node); return queryList(clazz, (SelectColumn) null, node);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final FilterNode node) {
List<T> rs = queryList(clazz, node);
if (handler != null) handler.completed(rs, node);
}
/** /**
* 根据过滤对象FilterBean查询对象集合 对象只填充或排除SelectField指定的字段 * 根据过滤对象FilterBean查询对象集合 对象只填充或排除SelectField指定的字段
* *
@@ -1655,81 +1407,36 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
return queryList(clazz, selects, (Flipper) null, bean); return queryList(clazz, selects, (Flipper) null, bean);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final FilterBean bean) {
FilterNode node = FilterNodeBean.createFilterNode(bean);
List<T> rs = queryList(clazz, selects, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final FilterNode node) { public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final FilterNode node) {
return queryList(clazz, selects, (Flipper) null, node); return queryList(clazz, selects, (Flipper) null, node);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final FilterNode node) {
List<T> rs = queryList(clazz, selects, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final String column, final Serializable key) { public <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final String column, final Serializable key) {
return queryList(clazz, flipper, FilterNode.create(column, key)); return queryList(clazz, flipper, FilterNode.create(column, key));
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, Serializable> handler, final Class<T> clazz, final Flipper flipper, final String column, final Serializable key) {
List<T> rs = queryList(clazz, flipper, column, key);
if (handler != null) handler.completed(rs, key);
}
@Override @Override
public <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final FilterBean bean) { public <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final FilterBean bean) {
return queryList(clazz, null, flipper, bean); return queryList(clazz, null, flipper, bean);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, final FilterBean bean) {
FilterNode node = FilterNodeBean.createFilterNode(bean);
List<T> rs = queryList(clazz, flipper, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final FilterNode node) { public <T> List<T> queryList(final Class<T> clazz, final Flipper flipper, final FilterNode node) {
return queryList(clazz, null, flipper, node); return queryList(clazz, null, flipper, node);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, final FilterNode node) {
List<T> rs = queryList(clazz, flipper, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) { public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) {
return querySheet(true, false, clazz, selects, flipper, FilterNodeBean.createFilterNode(bean)).list(true); return querySheet(true, false, clazz, selects, flipper, FilterNodeBean.createFilterNode(bean)).list(true);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) {
FilterNode node = FilterNodeBean.createFilterNode(bean);
List<T> rs = queryList(clazz, selects, flipper, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) { public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
return querySheet(true, false, clazz, selects, flipper, node).list(true); return querySheet(true, false, clazz, selects, flipper, node).list(true);
} }
@Override
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
List<T> rs = queryList(clazz, selects, flipper, node);
if (handler != null) handler.completed(rs, node);
}
//-----------------------sheet---------------------------- //-----------------------sheet----------------------------
/** /**
* 根据过滤对象FilterBean和翻页对象Flipper查询一页的数据 * 根据过滤对象FilterBean和翻页对象Flipper查询一页的数据
@@ -1746,24 +1453,11 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
return querySheet(clazz, null, flipper, bean); return querySheet(clazz, null, flipper, bean);
} }
@Override
public <T> void querySheet(final CompletionHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, final FilterBean bean) {
FilterNode node = FilterNodeBean.createFilterNode(bean);
Sheet<T> rs = querySheet(clazz, flipper, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> Sheet<T> querySheet(final Class<T> clazz, final Flipper flipper, final FilterNode node) { public <T> Sheet<T> querySheet(final Class<T> clazz, final Flipper flipper, final FilterNode node) {
return querySheet(clazz, null, flipper, node); return querySheet(clazz, null, flipper, node);
} }
@Override
public <T> void querySheet(final CompletionHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, final FilterNode node) {
Sheet<T> rs = querySheet(clazz, flipper, node);
if (handler != null) handler.completed(rs, node);
}
/** /**
* 根据过滤对象FilterBean和翻页对象Flipper查询一页的数据 对象只填充或排除SelectField指定的字段 * 根据过滤对象FilterBean和翻页对象Flipper查询一页的数据 对象只填充或排除SelectField指定的字段
* *
@@ -1780,24 +1474,11 @@ public final class DataDefaultSource implements DataSource, Function<Class, Enti
return querySheet(true, true, clazz, selects, flipper, FilterNodeBean.createFilterNode(bean)); return querySheet(true, true, clazz, selects, flipper, FilterNodeBean.createFilterNode(bean));
} }
@Override
public <T> void querySheet(final CompletionHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) {
FilterNode node = FilterNodeBean.createFilterNode(bean);
Sheet<T> rs = querySheet(clazz, selects, flipper, node);
if (handler != null) handler.completed(rs, node);
}
@Override @Override
public <T> Sheet<T> querySheet(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) { public <T> Sheet<T> querySheet(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
return querySheet(true, true, clazz, selects, flipper, node); return querySheet(true, true, clazz, selects, flipper, node);
} }
@Override
public <T> void querySheet(final CompletionHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
Sheet<T> rs = querySheet(clazz, selects, flipper, node);
if (handler != null) handler.completed(rs, node);
}
private <T> Sheet<T> querySheet(final boolean readcache, final boolean needtotal, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) { private <T> Sheet<T> querySheet(final boolean readcache, final boolean needtotal, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
final EntityInfo<T> info = loadEntityInfo(clazz); final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache(); final EntityCache<T> cache = info.getCache();

View File

@@ -1,21 +0,0 @@
/*
* 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.source;
/**
* &#64;Resource(name = "property.datasource.nodeid")
*
* <p> 详情见: http://redkale.org
* @author zhangjx
*/
public interface DataSQLListener {
public void insert(String... sqls);
public void update(String... sqls);
public void delete(String... sqls);
}

View File

@@ -6,14 +6,13 @@
package org.redkale.source; package org.redkale.source;
import java.io.Serializable; import java.io.Serializable;
import java.nio.channels.CompletionHandler;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.util.*; import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.redkale.util.*; import org.redkale.util.*;
/** /**
* *
* DataSource 为数据库或内存数据库的数据源提供类似JPA、Hibernate的接口与功能。 * DataSource 为数据库或内存数据库的数据源提供类似JPA、Hibernate的接口与功能。
* *
* <p> * <p>
@@ -33,9 +32,6 @@ public interface DataSource {
*/ */
public <T> void insert(final T... values); public <T> void insert(final T... values);
//----------------------异步版---------------------------------
public <T> void insert(final CompletionHandler<Void, T[]> handler, final T... values);
//-------------------------delete-------------------------- //-------------------------delete--------------------------
/** /**
* 删除对象, 必须是Entity对象 * 删除对象, 必须是Entity对象
@@ -57,13 +53,6 @@ public interface DataSource {
public <T> void delete(final Class<T> clazz, final FilterNode node); public <T> void delete(final Class<T> clazz, final FilterNode node);
//----------------------异步版---------------------------------
public <T> void delete(final CompletionHandler<Void, T[]> handler, final T... values);
public <T> void delete(final CompletionHandler<Void, Serializable[]> handler, final Class<T> clazz, final Serializable... ids);
public <T> void delete(final CompletionHandler<Void, FilterNode> handler, final Class<T> clazz, final FilterNode node);
//------------------------update--------------------------- //------------------------update---------------------------
/** /**
* 更新对象, 必须是Entity对象 * 更新对象, 必须是Entity对象
@@ -87,23 +76,6 @@ public interface DataSource {
public <T> void updateColumns(final T bean, final FilterNode node, final String... columns); public <T> void updateColumns(final T bean, final FilterNode node, final String... columns);
//----------------------异步版---------------------------------
public <T> void update(final CompletionHandler<Void, T[]> handler, final T... values);
public <T> void updateColumn(final CompletionHandler<Void, Serializable> handler, final Class<T> clazz, final Serializable id, final String column, final Serializable value);
public <T> void updateColumn(final CompletionHandler<Void, FilterNode> handler, final Class<T> clazz, final String column, final Serializable value, final FilterNode node);
public <T> void updateColumnIncrement(final CompletionHandler<Void, Serializable> handler, final Class<T> clazz, final Serializable id, final String column, long incvalue);
public <T> void updateColumnAnd(final CompletionHandler<Void, Serializable> handler, final Class<T> clazz, final Serializable id, final String column, long incvalue);
public <T> void updateColumnOr(final CompletionHandler<Void, Serializable> handler, final Class<T> clazz, final Serializable id, final String column, long incvalue);
public <T> void updateColumns(final CompletionHandler<Void, T> handler, final T bean, final String... columns);
public <T> void updateColumns(final CompletionHandler<Void, FilterNode> handler, final T bean, final FilterNode node, final String... columns);
//############################################# 查询接口 ############################################# //############################################# 查询接口 #############################################
//-----------------------getXXXXResult----------------------------- //-----------------------getXXXXResult-----------------------------
public Number getNumberResult(final Class entityClass, final FilterFunc func, final String column); public Number getNumberResult(final Class entityClass, final FilterFunc func, final String column);
@@ -112,25 +84,18 @@ public interface DataSource {
public Number getNumberResult(final Class entityClass, final FilterFunc func, final String column, final FilterNode node); public Number getNumberResult(final Class entityClass, final FilterFunc func, final String column, final FilterNode node);
public Number getNumberResult(final Class entityClass, final FilterFunc func, final Number defVal, final String column);
public Number getNumberResult(final Class entityClass, final FilterFunc func, final Number defVal, final String column, final FilterBean bean);
public Number getNumberResult(final Class entityClass, final FilterFunc func, final Number defVal, final String column, final FilterNode node);
public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn); public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn);
public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn, final FilterBean bean); public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn, final FilterBean bean);
public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn, final FilterNode node); public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn, final FilterNode node);
//----------------------异步版---------------------------------
public void getNumberResult(final CompletionHandler<Number, String> handler, final Class entityClass, final FilterFunc func, final String column);
public void getNumberResult(final CompletionHandler<Number, FilterNode> handler, final Class entityClass, final FilterFunc func, final String column, final FilterBean bean);
public void getNumberResult(final CompletionHandler<Number, FilterNode> handler, final Class entityClass, final FilterFunc func, final String column, final FilterNode node);
public <T, K extends Serializable, N extends Number> void queryColumnMap(final CompletionHandler<Map<K, N>, String> handler, final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn);
public <T, K extends Serializable, N extends Number> void queryColumnMap(final CompletionHandler<Map<K, N>, FilterNode> handler, final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn, final FilterBean bean);
public <T, K extends Serializable, N extends Number> void queryColumnMap(final CompletionHandler<Map<K, N>, FilterNode> handler, final Class<T> entityClass, final String keyColumn, final FilterFunc func, final String funcColumn, final FilterNode node);
//-----------------------find---------------------------- //-----------------------find----------------------------
/** /**
* 根据主键获取对象 * 根据主键获取对象
@@ -161,27 +126,6 @@ public interface DataSource {
public <T> boolean exists(final Class<T> clazz, final FilterNode node); public <T> boolean exists(final Class<T> clazz, final FilterNode node);
//----------------------异步版---------------------------------
public <T> void find(final CompletionHandler<T, Serializable> handler, final Class<T> clazz, final Serializable pk);
public <T> void find(final CompletionHandler<T, Serializable> handler, final Class<T> clazz, final SelectColumn selects, final Serializable pk);
public <T> void find(final CompletionHandler<T, Serializable> handler, final Class<T> clazz, final String column, final Serializable key);
public <T> void find(final CompletionHandler<T, FilterNode> handler, final Class<T> clazz, final FilterBean bean);
public <T> void find(final CompletionHandler<T, FilterNode> handler, final Class<T> clazz, final FilterNode node);
public <T> void find(final CompletionHandler<T, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final FilterBean bean);
public <T> void find(final CompletionHandler<T, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final FilterNode node);
public <T> void exists(final CompletionHandler<Boolean, Serializable> handler, final Class<T> clazz, final Serializable pk);
public <T> void exists(final CompletionHandler<Boolean, FilterNode> handler, final Class<T> clazz, final FilterBean bean);
public <T> void exists(final CompletionHandler<Boolean, FilterNode> handler, final Class<T> clazz, final FilterNode node);
//-----------------------list set---------------------------- //-----------------------list set----------------------------
/** /**
* 根据指定字段值查询对象某个字段的集合 * 根据指定字段值查询对象某个字段的集合
@@ -207,19 +151,6 @@ public interface DataSource {
public <T, V extends Serializable> List<V> queryColumnList(final String selectedColumn, final Class<T> clazz, final FilterNode node); public <T, V extends Serializable> List<V> queryColumnList(final String selectedColumn, final Class<T> clazz, final FilterNode node);
//----------------------异步版---------------------------------
public <T, V extends Serializable> void queryColumnSet(final CompletionHandler<HashSet<V>, Serializable> handler, final String selectedColumn, final Class<T> clazz, final String column, final Serializable key);
public <T, V extends Serializable> void queryColumnSet(final CompletionHandler<HashSet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final FilterBean bean);
public <T, V extends Serializable> void queryColumnSet(final CompletionHandler<HashSet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final FilterNode node);
public <T, V extends Serializable> void queryColumnList(final CompletionHandler<List<V>, Serializable> handler, final String selectedColumn, final Class<T> clazz, final String column, final Serializable key);
public <T, V extends Serializable> void queryColumnList(final CompletionHandler<List<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final FilterBean bean);
public <T, V extends Serializable> void queryColumnList(final CompletionHandler<List<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final FilterNode node);
/** /**
* 根据指定参数查询对象某个字段的集合 * 根据指定参数查询对象某个字段的集合
* *
@@ -236,11 +167,6 @@ public interface DataSource {
public <T, V extends Serializable> Sheet<V> queryColumnSheet(final String selectedColumn, final Class<T> clazz, final Flipper flipper, final FilterNode node); public <T, V extends Serializable> Sheet<V> queryColumnSheet(final String selectedColumn, final Class<T> clazz, final Flipper flipper, final FilterNode node);
//----------------------异步版---------------------------------
public <T, V extends Serializable> void queryColumnSheet(final CompletionHandler<Sheet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final Flipper flipper, final FilterBean bean);
public <T, V extends Serializable> void queryColumnSheet(final CompletionHandler<Sheet<V>, FilterNode> handler, final String selectedColumn, final Class<T> clazz, final Flipper flipper, final FilterNode node);
/** /**
* 根据指定字段值查询对象集合 * 根据指定字段值查询对象集合
* *
@@ -271,27 +197,6 @@ public interface DataSource {
public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node); public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node);
//----------------------异步版---------------------------------
public <T> void queryList(final CompletionHandler<List<T>, Serializable> handler, final Class<T> clazz, final String column, final Serializable key);
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final FilterBean bean);
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final FilterNode node);
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final FilterBean bean);
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final FilterNode node);
public <T> void queryList(final CompletionHandler<List<T>, Serializable> handler, final Class<T> clazz, final Flipper flipper, final String column, final Serializable key);
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, final FilterBean bean);
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, final FilterNode node);
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean);
public <T> void queryList(final CompletionHandler<List<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node);
//-----------------------sheet---------------------------- //-----------------------sheet----------------------------
/** /**
* 根据指定参数查询对象某个对象的集合页 * 根据指定参数查询对象某个对象的集合页
@@ -311,15 +216,6 @@ public interface DataSource {
public <T> Sheet<T> querySheet(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node); public <T> Sheet<T> querySheet(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node);
//----------------------异步版---------------------------------
public <T> void querySheet(final CompletionHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, final FilterBean bean);
public <T> void querySheet(final CompletionHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final Flipper flipper, final FilterNode node);
public <T> void querySheet(final CompletionHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean);
public <T> void querySheet(final CompletionHandler<Sheet<T>, FilterNode> handler, final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node);
//-----------------------direct---------------------------- //-----------------------direct----------------------------
/** /**
* 直接本地执行SQL语句进行查询远程模式不可用 * 直接本地执行SQL语句进行查询远程模式不可用

View File

@@ -10,20 +10,6 @@ import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;
/** /**
*
* <pre>
* int 10万-100万 (36进制 4位) 255t - lflr 长度4 rewrite "^/dir/(\w+)/((\w{2})(\w{2})\..*)$" /$1/$3/$2 last;
* int 1000万-6000万 (36进制 5位) 5yc1t - zq0an 长度5-6 rewrite "^/dir/(\w+)/((\w{2})(\w{2})(\w\w?)\..*)$" /$1/$3/$4/$2 last;
* int 2亿-20亿 (36进制 6位) 3b2ozl - x2qxvk
* long 30亿-770亿 (36进制 7位) 1dm4etd - zdft88v 长度7-8 rewrite "^/dir/(\w+)/((\w{2})(\w{2})(\w{2})(\w\w?)\..*)$" /$1/$3/$4/$5/$2 last;
* long 1000亿-2万亿 (36进制 8位) 19xtf1tt - piscd0jj
* 随机文件名: (32进制 26位) 26-27长度
* #文件名 长度: 26 (1)
* rewrite "^/dir/(\w+)/((\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{14})\..*)$" /dir/$1/$3/$4/$5/$6/$7/$8/$2;
* #文件名 长度: 26 (2)
* rewrite "^/dir/(\w+)/(\w\w/\w\w/\w\w/\w\w/\w\w/\w\w)/(\w{12}(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})\..*)$" /$1/$2/$4/$5/$6/$7/$8/$9/$3 last;
*
* </pre>
* *
* <p> * <p>
* 详情见: http://redkale.org * 详情见: http://redkale.org

View File

@@ -0,0 +1,24 @@
/*
* 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.source;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
*/
@Target({TYPE})
@Retention(RUNTIME)
public @interface DistributeTable {
Class<? extends DistributeTableStrategy> strategy();
}

View File

@@ -0,0 +1,29 @@
/*
* 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.source;
import java.io.Serializable;
/**
*
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx
* @param <T> Entity类型
*/
public interface DistributeTableStrategy<T> {
default String getTable(String table, Serializable primary) {
return null;
}
default String getTable(String table, FilterNode node) {
return null;
}
public String getTable(String table, T bean);
}

View File

@@ -71,8 +71,7 @@ public final class EntityCache<T> {
java.lang.reflect.Field field = type.getDeclaredField(m); java.lang.reflect.Field field = type.getDeclaredField(m);
if (field.getAnnotation(Transient.class) != null) return false; if (field.getAnnotation(Transient.class) != null) return false;
Column column = field.getAnnotation(Column.class); Column column = field.getAnnotation(Column.class);
if (column != null && !column.updatable()) return false; return (column == null || column.updatable());
return true;
} catch (Exception e) { } catch (Exception e) {
return true; return true;
} }
@@ -109,14 +108,14 @@ public final class EntityCache<T> {
public T find(Serializable id) { public T find(Serializable id) {
if (id == null) return null; if (id == null) return null;
T rs = map.get(id); T rs = map.get(id);
return rs == null ? null : (needcopy ? newReproduce.copy(this.creator.create(), rs) : rs); return rs == null ? null : (needcopy ? newReproduce.apply(this.creator.create(), rs) : rs);
} }
public T find(final SelectColumn selects, final Serializable id) { public T find(final SelectColumn selects, final Serializable id) {
if (id == null) return null; if (id == null) return null;
T rs = map.get(id); T rs = map.get(id);
if (rs == null) return null; if (rs == null) return null;
if (selects == null) return (needcopy ? newReproduce.copy(this.creator.create(), rs) : rs); if (selects == null) return (needcopy ? newReproduce.apply(this.creator.create(), rs) : rs);
T t = this.creator.create(); T t = this.creator.create();
for (Attribute attr : this.info.attributes) { for (Attribute attr : this.info.attributes) {
if (selects.test(attr.field())) attr.set(t, attr.get(rs)); if (selects.test(attr.field())) attr.set(t, attr.get(rs));
@@ -130,7 +129,7 @@ public final class EntityCache<T> {
if (filter != null) stream = stream.filter(filter); if (filter != null) stream = stream.filter(filter);
Optional<T> opt = stream.findFirst(); Optional<T> opt = stream.findFirst();
if (!opt.isPresent()) return null; if (!opt.isPresent()) return null;
if (selects == null) return (needcopy ? newReproduce.copy(this.creator.create(), opt.get()) : opt.get()); if (selects == null) return (needcopy ? newReproduce.apply(this.creator.create(), opt.get()) : opt.get());
T rs = opt.get(); T rs = opt.get();
T t = this.creator.create(); T t = this.creator.create();
for (Attribute attr : this.info.attributes) { for (Attribute attr : this.info.attributes) {
@@ -221,7 +220,7 @@ public final class EntityCache<T> {
return rs; return rs;
} }
public <V> Number getNumberResult(final FilterFunc func, final String column, FilterNode node) { public <V> Number getNumberResult(final FilterFunc func, final Number defResult, final String column, final FilterNode node) {
final Attribute<T, Serializable> attr = column == null ? null : info.getAttribute(column); final Attribute<T, Serializable> attr = column == null ? null : info.getAttribute(column);
final Predicate<T> filter = node == null ? null : node.createPredicate(this); final Predicate<T> filter = node == null ? null : node.createPredicate(this);
Stream<T> stream = this.list.stream(); Stream<T> stream = this.list.stream();
@@ -229,15 +228,20 @@ public final class EntityCache<T> {
switch (func) { switch (func) {
case AVG: case AVG:
if (attr.type() == int.class || attr.type() == Integer.class) { if (attr.type() == int.class || attr.type() == Integer.class) {
return (int) stream.mapToInt(x -> (Integer) attr.get(x)).average().orElse(0); OptionalDouble rs = stream.mapToInt(x -> (Integer) attr.get(x)).average();
return rs.isPresent() ? (int) rs.getAsDouble() : defResult;
} else if (attr.type() == long.class || attr.type() == Long.class) { } else if (attr.type() == long.class || attr.type() == Long.class) {
return (long) stream.mapToLong(x -> (Long) attr.get(x)).average().orElse(0); OptionalDouble rs = stream.mapToLong(x -> (Long) attr.get(x)).average();
return rs.isPresent() ? (long) rs.getAsDouble() : defResult;
} else if (attr.type() == short.class || attr.type() == Short.class) { } else if (attr.type() == short.class || attr.type() == Short.class) {
return (short) stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).average().orElse(0); OptionalDouble rs = stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).average();
return rs.isPresent() ? (short) rs.getAsDouble() : defResult;
} else if (attr.type() == float.class || attr.type() == Float.class) { } else if (attr.type() == float.class || attr.type() == Float.class) {
return (float) stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).average().orElse(0); OptionalDouble rs = stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).average();
return rs.isPresent() ? (float) rs.getAsDouble() : defResult;
} else if (attr.type() == double.class || attr.type() == Double.class) { } else if (attr.type() == double.class || attr.type() == Double.class) {
return stream.mapToDouble(x -> (Double) attr.get(x)).average().orElse(0); OptionalDouble rs = stream.mapToDouble(x -> (Double) attr.get(x)).average();
return rs.isPresent() ? rs.getAsDouble() : defResult;
} }
throw new RuntimeException("getNumberResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type()); throw new RuntimeException("getNumberResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type());
case COUNT: case COUNT:
@@ -247,29 +251,39 @@ public final class EntityCache<T> {
case MAX: case MAX:
if (attr.type() == int.class || attr.type() == Integer.class) { if (attr.type() == int.class || attr.type() == Integer.class) {
return stream.mapToInt(x -> (Integer) attr.get(x)).max().orElse(0); OptionalInt rs = stream.mapToInt(x -> (Integer) attr.get(x)).max();
return rs.isPresent() ? rs.getAsInt() : defResult;
} else if (attr.type() == long.class || attr.type() == Long.class) { } else if (attr.type() == long.class || attr.type() == Long.class) {
return stream.mapToLong(x -> (Long) attr.get(x)).max().orElse(0); OptionalLong rs = stream.mapToLong(x -> (Long) attr.get(x)).max();
return rs.isPresent() ? rs.getAsLong() : defResult;
} else if (attr.type() == short.class || attr.type() == Short.class) { } else if (attr.type() == short.class || attr.type() == Short.class) {
return (short) stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).max().orElse(0); OptionalInt rs = stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).max();
return rs.isPresent() ? (short) rs.getAsInt() : defResult;
} else if (attr.type() == float.class || attr.type() == Float.class) { } else if (attr.type() == float.class || attr.type() == Float.class) {
return (float) stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).max().orElse(0); OptionalDouble rs = stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).max();
return rs.isPresent() ? (float) rs.getAsDouble() : defResult;
} else if (attr.type() == double.class || attr.type() == Double.class) { } else if (attr.type() == double.class || attr.type() == Double.class) {
return stream.mapToDouble(x -> (Double) attr.get(x)).max().orElse(0); OptionalDouble rs = stream.mapToDouble(x -> (Double) attr.get(x)).max();
return rs.isPresent() ? rs.getAsDouble() : defResult;
} }
throw new RuntimeException("getNumberResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type()); throw new RuntimeException("getNumberResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type());
case MIN: case MIN:
if (attr.type() == int.class || attr.type() == Integer.class) { if (attr.type() == int.class || attr.type() == Integer.class) {
return stream.mapToInt(x -> (Integer) attr.get(x)).min().orElse(0); OptionalInt rs = stream.mapToInt(x -> (Integer) attr.get(x)).min();
return rs.isPresent() ? rs.getAsInt() : defResult;
} else if (attr.type() == long.class || attr.type() == Long.class) { } else if (attr.type() == long.class || attr.type() == Long.class) {
return stream.mapToLong(x -> (Long) attr.get(x)).min().orElse(0); OptionalLong rs = stream.mapToLong(x -> (Long) attr.get(x)).min();
return rs.isPresent() ? rs.getAsLong() : defResult;
} else if (attr.type() == short.class || attr.type() == Short.class) { } else if (attr.type() == short.class || attr.type() == Short.class) {
return (short) stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).min().orElse(0); OptionalInt rs = stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).min();
return rs.isPresent() ? (short) rs.getAsInt() : defResult;
} else if (attr.type() == float.class || attr.type() == Float.class) { } else if (attr.type() == float.class || attr.type() == Float.class) {
return (float) stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).min().orElse(0); OptionalDouble rs = stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).min();
return rs.isPresent() ? (float) rs.getAsDouble() : defResult;
} else if (attr.type() == double.class || attr.type() == Double.class) { } else if (attr.type() == double.class || attr.type() == Double.class) {
return stream.mapToDouble(x -> (Double) attr.get(x)).min().orElse(0); OptionalDouble rs = stream.mapToDouble(x -> (Double) attr.get(x)).min();
return rs.isPresent() ? rs.getAsDouble() : defResult;
} }
throw new RuntimeException("getNumberResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type()); throw new RuntimeException("getNumberResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type());
@@ -287,7 +301,7 @@ public final class EntityCache<T> {
} }
throw new RuntimeException("getNumberResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type()); throw new RuntimeException("getNumberResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type());
} }
return -1; return defResult;
} }
public Sheet<T> querySheet(final SelectColumn selects, final Flipper flipper, final FilterNode node) { public Sheet<T> querySheet(final SelectColumn selects, final Flipper flipper, final FilterNode node) {
@@ -310,7 +324,7 @@ public final class EntityCache<T> {
if (flipper != null) stream = stream.skip(flipper.getOffset()).limit(flipper.getLimit()); if (flipper != null) stream = stream.skip(flipper.getOffset()).limit(flipper.getLimit());
final List<T> rs = new ArrayList<>(); final List<T> rs = new ArrayList<>();
if (selects == null) { if (selects == null) {
Consumer<? super T> action = x -> rs.add(needcopy ? newReproduce.copy(creator.create(), x) : x); Consumer<? super T> action = x -> rs.add(needcopy ? newReproduce.apply(creator.create(), x) : x);
if (comparator != null) { if (comparator != null) {
stream.forEachOrdered(action); stream.forEachOrdered(action);
} else { } else {
@@ -340,7 +354,7 @@ public final class EntityCache<T> {
public void insert(T value) { public void insert(T value) {
if (value == null) return; if (value == null) return;
final T rs = newReproduce.copy(this.creator.create(), value); //确保同一主键值的map与list中的对象必须共用。 final T rs = newReproduce.apply(this.creator.create(), value); //确保同一主键值的map与list中的对象必须共用。
T old = this.map.put(this.primary.get(rs), rs); T old = this.map.put(this.primary.get(rs), rs);
if (old == null) { if (old == null) {
this.list.add(rs); this.list.add(rs);
@@ -373,7 +387,7 @@ public final class EntityCache<T> {
if (value == null) return; if (value == null) return;
T rs = this.map.get(this.primary.get(value)); T rs = this.map.get(this.primary.get(value));
if (rs == null) return; if (rs == null) return;
this.chgReproduce.copy(rs, value); this.chgReproduce.apply(rs, value);
} }
public T update(final T value, Collection<Attribute<T, Serializable>> attrs) { public T update(final T value, Collection<Attribute<T, Serializable>> attrs) {

View File

@@ -37,7 +37,7 @@ public final class EntityInfo<T> {
private final Class<T> type; private final Class<T> type;
//类对应的数据表名, 如果是VirtualEntity 类, 则该字段为null //类对应的数据表名, 如果是VirtualEntity 类, 则该字段为null
private final String table; final String table;
private final Creator<T> creator; private final Creator<T> creator;
@@ -62,19 +62,27 @@ public final class EntityInfo<T> {
final String notcontainSQL; //用于反向LIKE使用 final String notcontainSQL; //用于反向LIKE使用
final String tablenotexistSqlstates; //用于判断表不存在的使用, 多个SQLState用;隔开
final String tablecopySQL; //用于复制表结构使用
final Set<String> tables = new HashSet<>(); //用于存在table_20160202类似这种分布式表
final DistributeTableStrategy<T> tableStrategy;
final String querySQL; final String querySQL;
private final Attribute<T, Serializable>[] queryAttributes; //数据库中所有字段 private final Attribute<T, Serializable>[] queryAttributes; //数据库中所有字段
final String insertSQL; private final String insertSQL;
final Attribute<T, Serializable>[] insertAttributes; //数据库中所有可新增字段 final Attribute<T, Serializable>[] insertAttributes; //数据库中所有可新增字段
final String updateSQL; private final String updateSQL;
final Attribute<T, Serializable>[] updateAttributes; //数据库中所有可更新字段 final Attribute<T, Serializable>[] updateAttributes; //数据库中所有可更新字段
final String deleteSQL; private final String deleteSQL;
private final int logLevel; private final int logLevel;
@@ -85,6 +93,8 @@ public final class EntityInfo<T> {
final boolean autoGenerated; final boolean autoGenerated;
final boolean autouuid;
final boolean distributed; final boolean distributed;
boolean initedPrimaryValue = false; boolean initedPrimaryValue = false;
@@ -145,6 +155,15 @@ public final class EntityInfo<T> {
this.fullloader = fullloader; this.fullloader = fullloader;
this.table = (t == null) ? type.getSimpleName().toLowerCase() : (t.catalog().isEmpty()) ? t.name() : (t.catalog() + '.' + t.name()); this.table = (t == null) ? type.getSimpleName().toLowerCase() : (t.catalog().isEmpty()) ? t.name() : (t.catalog() + '.' + t.name());
} }
DistributeTable dt = type.getAnnotation(DistributeTable.class);
DistributeTableStrategy dts = null;
try {
dts = (dt == null) ? null : dt.strategy().newInstance();
} catch (Exception e) {
logger.severe(type + " init DistributeTableStrategy error", e);
}
this.tableStrategy = dts;
this.creator = Creator.create(type); this.creator = Creator.create(type);
Attribute idAttr0 = null; Attribute idAttr0 = null;
Map<String, String> aliasmap0 = null; Map<String, String> aliasmap0 = null;
@@ -156,6 +175,7 @@ public final class EntityInfo<T> {
List<String> updatecols = new ArrayList<>(); List<String> updatecols = new ArrayList<>();
List<Attribute<T, Serializable>> updateattrs = new ArrayList<>(); List<Attribute<T, Serializable>> updateattrs = new ArrayList<>();
boolean auto = false; boolean auto = false;
boolean uuid = false;
boolean sqldistribute = false; boolean sqldistribute = false;
int allocationSize0 = 0; int allocationSize0 = 0;
@@ -196,6 +216,10 @@ public final class EntityInfo<T> {
allocationSize0 = dg.allocationSize(); allocationSize0 = dg.allocationSize();
primaryValue.set(dg.initialValue()); primaryValue.set(dg.initialValue());
} }
if (gv != null && field.getType() == String.class) { //UUID
uuid = true;
auto = false;
}
if (!auto) { if (!auto) {
insertcols.add(sqlfield); insertcols.add(sqlfield);
insertattrs.add(attr); insertattrs.add(attr);
@@ -231,14 +255,14 @@ public final class EntityInfo<T> {
if (insertsb2.length() > 0) insertsb2.append(','); if (insertsb2.length() > 0) insertsb2.append(',');
insertsb2.append('?'); insertsb2.append('?');
} }
this.insertSQL = "INSERT INTO " + table + "(" + insertsb + ") VALUES(" + insertsb2 + ")"; this.insertSQL = "INSERT INTO " + (this.tableStrategy == null ? table : "${newtable}") + "(" + insertsb + ") VALUES(" + insertsb2 + ")";
StringBuilder updatesb = new StringBuilder(); StringBuilder updatesb = new StringBuilder();
for (String col : updatecols) { for (String col : updatecols) {
if (updatesb.length() > 0) updatesb.append(", "); if (updatesb.length() > 0) updatesb.append(", ");
updatesb.append(col).append(" = ?"); updatesb.append(col).append(" = ?");
} }
this.updateSQL = "UPDATE " + table + " SET " + updatesb + " WHERE " + getPrimarySQLColumn(null) + " = ?"; this.updateSQL = "UPDATE " + (this.tableStrategy == null ? table : "${newtable}") + " SET " + updatesb + " WHERE " + getPrimarySQLColumn(null) + " = ?";
this.deleteSQL = "DELETE FROM " + table + " WHERE " + getPrimarySQLColumn(null) + " = ?"; this.deleteSQL = "DELETE FROM " + (this.tableStrategy == null ? table : "${newtable}") + " WHERE " + getPrimarySQLColumn(null) + " = ?";
this.querySQL = "SELECT * FROM " + table + " WHERE " + getPrimarySQLColumn(null) + " = ?"; this.querySQL = "SELECT * FROM " + table + " WHERE " + getPrimarySQLColumn(null) + " = ?";
} else { } else {
this.insertSQL = null; this.insertSQL = null;
@@ -247,6 +271,7 @@ public final class EntityInfo<T> {
this.querySQL = null; this.querySQL = null;
} }
this.autoGenerated = auto; this.autoGenerated = auto;
this.autouuid = uuid;
this.distributed = sqldistribute; this.distributed = sqldistribute;
this.allocationSize = allocationSize0; this.allocationSize = allocationSize0;
//----------------cache-------------- //----------------cache--------------
@@ -259,9 +284,16 @@ public final class EntityInfo<T> {
if (conf == null) conf = new Properties(); if (conf == null) conf = new Properties();
this.containSQL = conf.getProperty(JDBC_CONTAIN_SQLTEMPLATE, "LOCATE(${keystr}, ${column}) > 0"); this.containSQL = conf.getProperty(JDBC_CONTAIN_SQLTEMPLATE, "LOCATE(${keystr}, ${column}) > 0");
this.notcontainSQL = conf.getProperty(JDBC_NOTCONTAIN_SQLTEMPLATE, "LOCATE(${keystr}, ${column}) = 0"); this.notcontainSQL = conf.getProperty(JDBC_NOTCONTAIN_SQLTEMPLATE, "LOCATE(${keystr}, ${column}) = 0");
this.tablenotexistSqlstates = ";" + conf.getProperty(JDBC_TABLENOTEXIST_SQLSTATES, "42000;42S02") + ";";
this.tablecopySQL = conf.getProperty(JDBC_TABLECOPY_SQLTEMPLATE, "CREATE TABLE ${newtable} LIKE ${oldtable}");
} }
public void createPrimaryValue(T src) { public void createPrimaryValue(T src) {
if (autouuid) {
getPrimary().set(src, Utility.uuid());
return;
}
long v = allocationSize > 1 ? (primaryValue.incrementAndGet() * allocationSize + nodeid) : primaryValue.incrementAndGet(); long v = allocationSize > 1 ? (primaryValue.incrementAndGet() * allocationSize + nodeid) : primaryValue.incrementAndGet();
if (primary.type() == int.class || primary.type() == Integer.class) { if (primary.type() == int.class || primary.type() == Integer.class) {
getPrimary().set(src, (Integer) ((Long) v).intValue()); getPrimary().set(src, (Integer) ((Long) v).intValue());
@@ -295,16 +327,37 @@ public final class EntityInfo<T> {
return table == null; return table == null;
} }
public String getInsertSQL(T bean) {
if (this.tableStrategy == null) return insertSQL;
return insertSQL.replace("${newtable}", getTable(bean));
}
public String getUpdateSQL(T bean) {
if (this.tableStrategy == null) return updateSQL;
return updateSQL.replace("${newtable}", getTable(bean));
}
public String getDeleteSQL(T bean) {
if (this.tableStrategy == null) return deleteSQL;
return deleteSQL.replace("${newtable}", getTable(bean));
}
public String getTable(Serializable primary) { public String getTable(Serializable primary) {
return table; if (tableStrategy == null) return table;
String t = tableStrategy.getTable(table, primary);
return t == null || t.isEmpty() ? table : t;
} }
public String getTable(FilterNode node) { public String getTable(FilterNode node) {
return table; if (tableStrategy == null) return table;
String t = tableStrategy.getTable(table, node);
return t == null || t.isEmpty() ? table : t;
} }
public String getTable(T bean) { public String getTable(T bean) {
return table; if (tableStrategy == null) return table;
String t = tableStrategy.getTable(table, bean);
return t == null || t.isEmpty() ? table : t;
} }
public Attribute<T, Serializable> getPrimary() { public Attribute<T, Serializable> getPrimary() {
@@ -379,25 +432,53 @@ public final class EntityInfo<T> {
return l.intValue() >= this.logLevel; return l.intValue() >= this.logLevel;
} }
protected String formatToString(Object value) {
if (value == null) return null;
if (value instanceof CharSequence) {
return new StringBuilder().append('\'').append(value.toString().replace("'", "\\'")).append('\'').toString();
}
return String.valueOf(value);
}
protected T getValue(final SelectColumn sels, final ResultSet set) throws SQLException { protected T getValue(final SelectColumn sels, final ResultSet set) throws SQLException {
T obj = creator.create(); T obj = creator.create();
for (Attribute<T, Serializable> attr : queryAttributes) { for (Attribute<T, Serializable> attr : queryAttributes) {
if (sels == null || sels.test(attr.field())) { if (sels == null || sels.test(attr.field())) {
Serializable o = (Serializable) set.getObject(this.getSQLColumn(null, attr.field())); Serializable o = (Serializable) set.getObject(this.getSQLColumn(null, attr.field()));
if (o != null) { final Class t = attr.type();
Class t = attr.type(); if (t.isPrimitive()) {
if (t == int.class) { if (o != null) {
o = ((Number) o).intValue(); if (t == int.class) {
} else if (t == short.class) { o = ((Number) o).intValue();
o = ((Number) o).shortValue(); } else if (t == long.class) {
o = ((Number) o).longValue();
} else if (t == short.class) {
o = ((Number) o).shortValue();
} else if (t == float.class) {
o = ((Number) o).floatValue();
} else if (t == double.class) {
o = ((Number) o).doubleValue();
} else if (t == byte.class) {
o = ((Number) o).byteValue();
} else if (t == char.class) {
o = (char) ((Number) o).intValue();
}
} else if (t == int.class) {
o = 0;
} else if (t == long.class) { } else if (t == long.class) {
o = ((Number) o).longValue(); o = 0L;
} else if (t == short.class) {
o = (short) 0;
} else if (t == float.class) { } else if (t == float.class) {
o = ((Number) o).floatValue(); o = 0.0f;
} else if (t == double.class) { } else if (t == double.class) {
o = ((Number) o).doubleValue(); o = 0.0d;
} else if (t == byte.class) { } else if (t == byte.class) {
o = ((Number) o).byteValue(); o = (byte) 0;
} else if (t == boolean.class) {
o = false;
} else if (t == char.class) {
o = (char) 0;
} }
} }
attr.set(obj, o); attr.set(obj, o);

View File

@@ -34,6 +34,10 @@ public @interface FilterJoinColumn {
* 多个关联字段, 默认使用join表(b)的主键, join表与被join表(a)的字段必须一样 * 多个关联字段, 默认使用join表(b)的主键, join表与被join表(a)的字段必须一样
* 例如: SELECT a.* FROM user a INNER JOIN record b ON a.userid = b.userid AND a.usertype = b.usertype * 例如: SELECT a.* FROM user a INNER JOIN record b ON a.userid = b.userid AND a.usertype = b.usertype
* 那么注解为: &#64;FilterJoinColumn(table = Record.class, columns = {"userid", "usertype"}) * 那么注解为: &#64;FilterJoinColumn(table = Record.class, columns = {"userid", "usertype"})
* <p>
* columns中的字段名如果不一致可以将两个字段名用=连接成一个字段名
* 例如: SELECT a.* FROM user a INNER JOIN record b ON a.userid = b.buyerid AND a.usertype = b.usertype
* 那么注解为: &#64;FilterJoinColumn(table = Record.class, columns = {"userid=buyerid", "usertype"})
* *
* @return 关联字段 * @return 关联字段
*/ */

View File

@@ -128,14 +128,23 @@ public class FilterJoinNode extends FilterNode {
if (filter == null && !more.get()) return rs; if (filter == null && !more.get()) return rs;
if (filter != null) { if (filter != null) {
final Predicate<E> inner = filter; final Predicate<E> inner = filter;
final String[][] localJoinColumns = new String[joinColumns.length][2];
for (int i = 0; i < joinColumns.length; i++) {
int pos = joinColumns[i].indexOf('=');
if (pos > 0) {
localJoinColumns[i] = new String[]{joinColumns[i].substring(0, pos), joinColumns[i].substring(pos + 1)};
} else {
localJoinColumns[i] = new String[]{joinColumns[i], joinColumns[i]};
}
}
rs = new Predicate<T>() { rs = new Predicate<T>() {
@Override @Override
public boolean test(final T t) { public boolean test(final T t) {
Predicate<E> joinPredicate = null; Predicate<E> joinPredicate = null;
for (String joinColumn : joinColumns) { for (String[] localJoinColumn : localJoinColumns) {
final Serializable key = cache.getAttribute(joinColumn).get(t); final Serializable key = cache.getAttribute(localJoinColumn[0]).get(t);
final Attribute<E, Serializable> joinAttr = joinCache.getAttribute(joinColumn); final Attribute<E, Serializable> joinAttr = joinCache.getAttribute(localJoinColumn[1]);
Predicate<E> p = (E e) -> key.equals(joinAttr.get(e)); Predicate<E> p = (E e) -> key.equals(joinAttr.get(e));
joinPredicate = joinPredicate == null ? p : joinPredicate.and(p); joinPredicate = joinPredicate == null ? p : joinPredicate.and(p);
} }
@@ -145,9 +154,9 @@ public class FilterJoinNode extends FilterNode {
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(" #-- ON ").append(joinColumns[0]).append("=").append(joinClass == null ? "null" : joinClass.getSimpleName()).append(".").append(joinColumns[0]); sb.append(" #-- ON ").append(localJoinColumns[0][0]).append("=").append(joinClass == null ? "null" : joinClass.getSimpleName()).append(".").append(localJoinColumns[0][1]);
for (int i = 1; i < joinColumns.length; i++) { for (int i = 1; i < localJoinColumns.length; i++) {
sb.append(" AND ").append(joinColumns[i]).append("=").append(joinClass == null ? "null" : joinClass.getSimpleName()).append(".").append(joinColumns[i]); sb.append(" AND ").append(localJoinColumns[i][0]).append("=").append(joinClass == null ? "null" : joinClass.getSimpleName()).append(".").append(localJoinColumns[i][1]);
} }
sb.append(" --# ").append(inner.toString()); sb.append(" --# ").append(inner.toString());
return sb.toString(); return sb.toString();
@@ -277,10 +286,12 @@ public class FilterJoinNode extends FilterNode {
if (node.joinClass == null) return null; if (node.joinClass == null) return null;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String[] joinColumns = node.joinColumns; String[] joinColumns = node.joinColumns;
int pos = joinColumns[0].indexOf('=');
sb.append(" INNER JOIN ").append(node.joinEntity.getTable(node)).append(" ").append(joinTabalis.get(node.joinClass)) sb.append(" INNER JOIN ").append(node.joinEntity.getTable(node)).append(" ").append(joinTabalis.get(node.joinClass))
.append(" ON ").append(info.getSQLColumn("a", joinColumns[0])).append(" = ").append(node.joinEntity.getSQLColumn(joinTabalis.get(node.joinClass), joinColumns[0])); .append(" ON ").append(info.getSQLColumn("a", pos > 0 ? joinColumns[0].substring(0, pos) : joinColumns[0])).append(" = ").append(node.joinEntity.getSQLColumn(joinTabalis.get(node.joinClass), pos > 0 ? joinColumns[0].substring(pos + 1) : joinColumns[0]));
for (int i = 1; i < joinColumns.length; i++) { for (int i = 1; i < joinColumns.length; i++) {
sb.append(" AND ").append(info.getSQLColumn("a", joinColumns[i])).append(" = ").append(node.joinEntity.getSQLColumn(joinTabalis.get(node.joinClass), joinColumns[i])); pos = joinColumns[i].indexOf('=');
sb.append(" AND ").append(info.getSQLColumn("a", pos > 0 ? joinColumns[i].substring(0, pos) : joinColumns[i])).append(" = ").append(node.joinEntity.getSQLColumn(joinTabalis.get(node.joinClass), pos > 0 ? joinColumns[i].substring(pos + 1) : joinColumns[i]));
} }
return sb; return sb;
} }

View File

@@ -129,7 +129,12 @@ public class JDBCPoolSource {
try { try {
while (!this.isInterrupted()) { while (!this.isInterrupted()) {
final WatchKey key = watcher.take(); final WatchKey key = watcher.take();
Thread.sleep(3000); //防止文件正在更新过程中去读取 long d; //防止文件正在更新过程中去读取
for (;;) {
d = f.lastModified();
Thread.sleep(2000L);
if (d == f.lastModified()) break;
}
final Map<String, Properties> m = loadProperties(new FileInputStream(file)); final Map<String, Properties> m = loadProperties(new FileInputStream(file));
key.pollEvents().stream().forEach((event) -> { key.pollEvents().stream().forEach((event) -> {
if (event.kind() != ENTRY_MODIFY) return; if (event.kind() != ENTRY_MODIFY) return;

View File

@@ -23,16 +23,20 @@ public abstract class AnyValue {
/** /**
* 可读写的AnyValue默认实现类 * 可读写的AnyValue默认实现类
* *
* <p>
* 详情见: http://redkale.org
*
* @author zhangjx * @author zhangjx
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static final class DefaultAnyValue extends AnyValue { public static final class DefaultAnyValue extends AnyValue {
/**
* 区分name大小写的比较策略
*
*/
public static final BiPredicate<String, String> EQUALS = (name1, name2) -> name1.equals(name2); public static final BiPredicate<String, String> EQUALS = (name1, name2) -> name1.equals(name2);
/**
* 不区分name大小写的比较策略
*/
public static final BiPredicate<String, String> EQUALSIGNORE = (name1, name2) -> name1.equalsIgnoreCase(name2); public static final BiPredicate<String, String> EQUALSIGNORE = (name1, name2) -> name1.equalsIgnoreCase(name2);
private final BiPredicate<String, String> predicate; private final BiPredicate<String, String> predicate;
@@ -41,34 +45,74 @@ public abstract class AnyValue {
private Entry<AnyValue>[] entityValues = new Entry[0]; private Entry<AnyValue>[] entityValues = new Entry[0];
/**
* 创建空的DefaultAnyValue对象
*
* @return DefaultAnyValue对象
*/
public static final DefaultAnyValue create() { public static final DefaultAnyValue create() {
return new DefaultAnyValue(); return new DefaultAnyValue();
} }
/**
* 创建含name-value值的DefaultAnyValue对象
*
* @param name name
* @param value value值
*
* @return DefaultAnyValue对象
*/
public static final DefaultAnyValue create(String name, String value) { public static final DefaultAnyValue create(String name, String value) {
DefaultAnyValue conf = new DefaultAnyValue(); DefaultAnyValue conf = new DefaultAnyValue();
conf.addValue(name, value); conf.addValue(name, value);
return conf; return conf;
} }
/**
* 创建含name-value值的DefaultAnyValue对象
*
* @param name name
* @param value value值
*
* @return DefaultAnyValue对象
*/
public static final DefaultAnyValue create(String name, AnyValue value) { public static final DefaultAnyValue create(String name, AnyValue value) {
DefaultAnyValue conf = new DefaultAnyValue(); DefaultAnyValue conf = new DefaultAnyValue();
conf.addValue(name, value); conf.addValue(name, value);
return conf; return conf;
} }
/**
* 创建一个区分大小写比较策略的DefaultAnyValue对象
*
*/
public DefaultAnyValue() { public DefaultAnyValue() {
this(false); this(false);
} }
/**
* 创建DefaultAnyValue对象
*
* @param ignoreCase name是否不区分大小写
*/
public DefaultAnyValue(boolean ignoreCase) { public DefaultAnyValue(boolean ignoreCase) {
this.predicate = ignoreCase ? EQUALSIGNORE : EQUALS; this.predicate = ignoreCase ? EQUALSIGNORE : EQUALS;
} }
/**
* 创建DefaultAnyValue对象
*
* @param predicate name比较策略
*/
public DefaultAnyValue(BiPredicate<String, String> predicate) { public DefaultAnyValue(BiPredicate<String, String> predicate) {
this.predicate = predicate; this.predicate = predicate;
} }
/**
* 创建共享此内容的DefaultAnyValue对象
*
* @return DefaultAnyValue对象
*/
public DefaultAnyValue duplicate() { public DefaultAnyValue duplicate() {
DefaultAnyValue rs = new DefaultAnyValue(this.predicate); DefaultAnyValue rs = new DefaultAnyValue(this.predicate);
rs.stringValues = this.stringValues; rs.stringValues = this.stringValues;
@@ -211,6 +255,14 @@ public abstract class AnyValue {
return this; return this;
} }
public DefaultAnyValue addValue(String name, boolean value) {
return addValue(name, String.valueOf(value));
}
public DefaultAnyValue addValue(String name, Number value) {
return addValue(name, String.valueOf(value));
}
public DefaultAnyValue addValue(String name, String value) { public DefaultAnyValue addValue(String name, String value) {
if (name == null) return this; if (name == null) return this;
int len = this.stringValues.length; int len = this.stringValues.length;
@@ -321,7 +373,7 @@ public abstract class AnyValue {
} }
} }
public static AnyValue create() { public static DefaultAnyValue create() {
return new DefaultAnyValue(); return new DefaultAnyValue();
} }
@@ -378,6 +430,11 @@ public abstract class AnyValue {
return value == null || value.length() == 0 ? defaultValue : Byte.decode(value); return value == null || value.length() == 0 ? defaultValue : Byte.decode(value);
} }
public byte getByteValue(int radix, String name, byte defaultValue) {
String value = getValue(name);
return value == null || value.length() == 0 ? defaultValue : (radix == 10 ? Byte.decode(value) : Byte.parseByte(value, radix));
}
public char getCharValue(String name) { public char getCharValue(String name) {
return getValue(name).charAt(0); return getValue(name).charAt(0);
} }
@@ -396,6 +453,11 @@ public abstract class AnyValue {
return value == null || value.length() == 0 ? defaultValue : Short.decode(value); return value == null || value.length() == 0 ? defaultValue : Short.decode(value);
} }
public short getShortValue(int radix, String name, short defaultValue) {
String value = getValue(name);
return value == null || value.length() == 0 ? defaultValue : (radix == 10 ? Short.decode(value) : Short.parseShort(value, radix));
}
public int getIntValue(String name) { public int getIntValue(String name) {
return Integer.decode(getValue(name)); return Integer.decode(getValue(name));
} }
@@ -405,6 +467,11 @@ public abstract class AnyValue {
return value == null || value.length() == 0 ? defaultValue : Integer.decode(value); return value == null || value.length() == 0 ? defaultValue : Integer.decode(value);
} }
public int getIntValue(int radix, String name, int defaultValue) {
String value = getValue(name);
return value == null || value.length() == 0 ? defaultValue : (radix == 10 ? Integer.decode(value) : Integer.parseInt(value, radix));
}
public long getLongValue(String name) { public long getLongValue(String name) {
return Long.decode(getValue(name)); return Long.decode(getValue(name));
} }
@@ -414,6 +481,11 @@ public abstract class AnyValue {
return value == null || value.length() == 0 ? defaultValue : Long.decode(value); return value == null || value.length() == 0 ? defaultValue : Long.decode(value);
} }
public long getLongValue(int radix, String name, long defaultValue) {
String value = getValue(name);
return value == null || value.length() == 0 ? defaultValue : (radix == 10 ? Long.decode(value) : Long.parseLong(value, radix));
}
public float getFloatValue(String name) { public float getFloatValue(String name) {
return Float.parseFloat(getValue(name)); return Float.parseFloat(getValue(name));
} }

View File

@@ -72,6 +72,12 @@ public class AsmMethodVisitor {
return av; return av;
} }
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
AnnotationVisitor av = visitor.visitTypeAnnotation(typeRef, typePath, desc, visible);
if (debug) System.out.println("mv.visitTypeAnnotation(" + typeRef + ", " + typePath + ", \"" + desc + "\", " + visible + ");");
return av;
}
public void visitParameter(String name, int access) { public void visitParameter(String name, int access) {
visitor.visitParameter(name, access); visitor.visitParameter(name, access);
if (debug) System.out.println("mv.visitParameter(" + name + ", " + access + ");"); if (debug) System.out.println("mv.visitParameter(" + name + ", " + access + ");");
@@ -82,6 +88,25 @@ public class AsmMethodVisitor {
if (debug) System.out.println("mv.visitVarInsn(" + opcodes[opcode] + ", " + var + ");"); if (debug) System.out.println("mv.visitVarInsn(" + opcodes[opcode] + ", " + var + ");");
} }
public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
visitor.visitFrame(type, nLocal, local, nStack, stack);
if (debug) {
String typestr = "" + type;
if (type == -1) {
typestr = "Opcodes.F_NEW";
} else if (type == 1) {
typestr = "Opcodes.F_APPEND";
} else if (type == 2) {
typestr = "Opcodes.F_CHOP";
} else if (type == 3) {
typestr = "Opcodes.F_SAME";
} else if (type == 4) {
typestr = "Opcodes.F_SAME1";
}
System.out.println("mv.visitFrame(" + typestr + ", " + nLocal + ", " + Arrays.toString(local) + ", " + nStack + ", " + Arrays.toString(stack) + ");");
}
}
public void visitJumpInsn(int opcode, Label var) { //调用此方法的 ClassWriter 必须由 COMPUTE_FRAMES 构建 public void visitJumpInsn(int opcode, Label var) { //调用此方法的 ClassWriter 必须由 COMPUTE_FRAMES 构建
visitor.visitJumpInsn(opcode, var); visitor.visitJumpInsn(opcode, var);
if (debug) { if (debug) {

View File

@@ -44,17 +44,17 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
* public String get(Record obj) { * public String get(Record obj) {
* return obj.getName(); * return obj.getName();
* } * }
* *
* &#64;Override * &#64;Override
* public void set(Record obj, String value) { * public void set(Record obj, String value) {
* obj.setName(value); * obj.setName(value);
* } * }
* *
* &#64;Override * &#64;Override
* public Class type() { * public Class type() {
* return String.class; * return String.class;
* } * }
* *
* &#64;Override * &#64;Override
* public Class declaringClass() { * public Class declaringClass() {
* return Record.class; * return Record.class;
@@ -63,8 +63,8 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
* </pre></blockquote> * </pre></blockquote>
* <p> * <p>
* 映射Field时field必须满足以下条件之一 <br> * 映射Field时field必须满足以下条件之一 <br>
* 1、field属性是public且非final <br> * 1、field属性是public且非final <br>
* 2、至少存在对应的getter、setter方法中的一个 <br> * 2、至少存在对应的getter、setter方法中的一个 <br>
* 当不存在getter方法时get操作固定返回null <br> * 当不存在getter方法时get操作固定返回null <br>
* 当不存在setter方法时set操作为空方法 <br> * 当不存在setter方法时set操作为空方法 <br>
* <p> * <p>
@@ -421,6 +421,8 @@ public interface Attribute<T, F> {
column = tgetter.getReturnType(); column = tgetter.getReturnType();
} else if (tsetter != null) { } else if (tsetter != null) {
column = tsetter.getParameterTypes()[0]; column = tsetter.getParameterTypes()[0];
} else if (fieldtype == null) {
throw new RuntimeException("[" + clazz + "]have no public field or setter or getter");
} }
final Class pcolumn = column; final Class pcolumn = column;
if (column.isPrimitive()) column = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(column, 1), 0).getClass(); if (column.isPrimitive()) column = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(column, 1), 0).getClass();

View File

@@ -94,7 +94,7 @@ public final class ByteArray {
/** /**
* 将buf内容覆盖到本对象内容中 * 将buf内容覆盖到本对象内容中
* *
* @param buf * @param buf 目标容器
*/ */
public void copyTo(byte[] buf) { public void copyTo(byte[] buf) {
System.arraycopy(this.content, 0, buf, 0, count); System.arraycopy(this.content, 0, buf, 0, count);
@@ -103,7 +103,7 @@ public final class ByteArray {
/** /**
* 将array的内容引用复制给本对象 * 将array的内容引用复制给本对象
* *
* @param array * @param array ByteArray
*/ */
public void directFrom(ByteArray array) { public void directFrom(ByteArray array) {
if (array != null) { if (array != null) {
@@ -115,7 +115,7 @@ public final class ByteArray {
/** /**
* 将本对象的内容引用复制给array * 将本对象的内容引用复制给array
* *
* @param array * @param array ByteArray
*/ */
public void directTo(ByteArray array) { public void directTo(ByteArray array) {
if (array != null) { if (array != null) {
@@ -270,8 +270,8 @@ public final class ByteArray {
/** /**
* 写入ByteBuffer指定长度的数据 * 写入ByteBuffer指定长度的数据
* *
* @param buffer * @param buffer 数据
* @param len * @param len 指定长度
*/ */
public void write(ByteBuffer buffer, int len) { public void write(ByteBuffer buffer, int len) {
if (len < 1) return; if (len < 1) return;
@@ -294,7 +294,7 @@ public final class ByteArray {
* *
* @param charset 字符集 * @param charset 字符集
* *
* @return * @return 字符串
*/ */
public String toString(final Charset charset) { public String toString(final Charset charset) {
return toString(0, count, charset); return toString(0, count, charset);
@@ -305,7 +305,7 @@ public final class ByteArray {
* *
* @param charset 字符集 * @param charset 字符集
* *
* @return * @return 字符串
*/ */
public String toStringAndClear(final Charset charset) { public String toStringAndClear(final Charset charset) {
String str = toString(0, count, charset); String str = toString(0, count, charset);
@@ -320,7 +320,7 @@ public final class ByteArray {
* @param len 长度 * @param len 长度
* @param charset 字符集 * @param charset 字符集
* *
* @return * @return 字符串
*/ */
public String toString(final int offset, int len, final Charset charset) { public String toString(final int offset, int len, final Charset charset) {
if (charset == null) return new String(Utility.decodeUTF8(content, offset, len)); if (charset == null) return new String(Utility.decodeUTF8(content, offset, len));
@@ -334,7 +334,7 @@ public final class ByteArray {
* @param len 长度 * @param len 长度
* @param charset 字符集 * @param charset 字符集
* *
* @return * @return 字符串
*/ */
public String toDecodeString(final int offset, int len, final Charset charset) { public String toDecodeString(final int offset, int len, final Charset charset) {
int index = offset; int index = offset;

View File

@@ -3,23 +3,25 @@
* To change this template file, choose Tools | Templates * To change this template file, choose Tools | Templates
* and open the template in the editor. * and open the template in the editor.
*/ */
package org.redkale.service; package org.redkale.util;
import java.lang.annotation.*; import java.lang.annotation.*;
import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;
/** /**
* SNCP协议中用于CompletionHandler回调函数中的attach字段 * 标记注释备注
* *
* <p>
* 详情见: http://redkale.org
* *
* <p> 详情见: http://redkale.org
* @author zhangjx * @author zhangjx
*/ */
@Inherited @Inherited
@Documented @Documented
@Target({PARAMETER}) @Target({TYPE, METHOD, FIELD, PARAMETER})
@Retention(RUNTIME) @Retention(RUNTIME)
public @interface DynAttachment { public @interface Comment {
String value();
} }

View File

@@ -1,7 +1,7 @@
package org.redkale.util; package org.redkale.util;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.function.Predicate; import java.util.function.*;
import static jdk.internal.org.objectweb.asm.Opcodes.*; import static jdk.internal.org.objectweb.asm.Opcodes.*;
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;
@@ -15,9 +15,10 @@ import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
* @param <D> 目标对象的数据类型 * @param <D> 目标对象的数据类型
* @param <S> 源对象的数据类型 * @param <S> 源对象的数据类型
*/ */
public interface Reproduce<D, S> { public interface Reproduce<D, S> extends BiFunction<D, S, D>{
public D copy(D dest, S src); @Override
public D apply(D dest, S src);
public static <D, S> Reproduce<D, S> create(final Class<D> destClass, final Class<S> srcClass) { public static <D, S> Reproduce<D, S> create(final Class<D> destClass, final Class<S> srcClass) {
return create(destClass, srcClass, null); return create(destClass, srcClass, null);
@@ -59,7 +60,7 @@ public interface Reproduce<D, S> {
mv.visitEnd(); mv.visitEnd();
} }
{ {
mv = (cw.visitMethod(ACC_PUBLIC, "copy", "(" + destDesc + srcDesc + ")" + destDesc, null, null)); mv = (cw.visitMethod(ACC_PUBLIC, "apply", "(" + destDesc + srcDesc + ")" + destDesc, null, null));
//mv.setDebug(true); //mv.setDebug(true);
for (java.lang.reflect.Field field : srcClass.getFields()) { for (java.lang.reflect.Field field : srcClass.getFields()) {
@@ -112,14 +113,14 @@ public interface Reproduce<D, S> {
mv.visitEnd(); mv.visitEnd();
} }
{ {
mv = (cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "copy", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", null, null)); mv = (cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "apply", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", null, null));
//mv.setDebug(true); //mv.setDebug(true);
mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, destName); mv.visitTypeInsn(CHECKCAST, destName);
mv.visitVarInsn(ALOAD, 2); mv.visitVarInsn(ALOAD, 2);
mv.visitTypeInsn(CHECKCAST, srcName); mv.visitTypeInsn(CHECKCAST, srcName);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "copy", "(" + destDesc + srcDesc + ")" + destDesc, false); mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "apply", "(" + destDesc + srcDesc + ")" + destDesc, false);
mv.visitInsn(ARETURN); mv.visitInsn(ARETURN);
mv.visitMaxs(3, 3); mv.visitMaxs(3, 3);
mv.visitEnd(); mv.visitEnd();

View File

@@ -15,6 +15,9 @@ import javax.annotation.Resource;
/** /**
* 如果Resource(name = "$") 表示资源name采用所属对象的name * 如果Resource(name = "$") 表示资源name采用所属对象的name
* name规则:
* 1: "$"有特殊含义, 不能表示"$"资源本身
* 2: 只能是字母、数字、(短横)-、(下划线)_、点(.)的组合
* <p> * <p>
* 详情见: http://redkale.org * 详情见: http://redkale.org
* *
@@ -51,6 +54,12 @@ public final class ResourceFactory {
this.store.clear(); this.store.clear();
} }
public void checkName(String name) {
if (name == null || (!name.isEmpty() && !name.matches("^[a-zA-Z0-9_\\-\\.\\[\\]\\(\\)]+$"))) {
throw new IllegalArgumentException("Resource.name(" + name + ") contains illegal character, must be (a-z,A-Z,0-9,_,.,(,),-,[,])");
}
}
public <A> A register(final Class<? extends A> clazz, final A rs) { public <A> A register(final Class<? extends A> clazz, final A rs) {
return register(true, clazz, rs); return register(true, clazz, rs);
} }
@@ -141,6 +150,7 @@ public final class ResourceFactory {
} }
public <A> A register(final boolean autoSync, final String name, final A rs) { public <A> A register(final boolean autoSync, final String name, final A rs) {
checkName(name);
final Class<?> claz = rs.getClass(); final Class<?> claz = rs.getClass();
ResourceType rtype = claz.getAnnotation(ResourceType.class); ResourceType rtype = claz.getAnnotation(ResourceType.class);
if (rtype == null) { if (rtype == null) {
@@ -164,21 +174,24 @@ public final class ResourceFactory {
} }
public <A> A register(final boolean autoSync, final String name, final Type clazz, final A rs) { public <A> A register(final boolean autoSync, final String name, final Type clazz, final A rs) {
checkName(name);
ConcurrentHashMap<String, ResourceEntry> map = this.store.get(clazz); ConcurrentHashMap<String, ResourceEntry> map = this.store.get(clazz);
if (map == null) { if (map == null) {
ConcurrentHashMap<String, ResourceEntry> sub = new ConcurrentHashMap(); synchronized (clazz) {
sub.put(name, new ResourceEntry(rs)); map = this.store.get(clazz);
store.put(clazz, sub); if (map == null) {
return null; map = new ConcurrentHashMap();
} else { store.put(clazz, map);
ResourceEntry re = map.get(name); }
if (re == null) {
map.put(name, new ResourceEntry(rs));
} else {
map.put(name, new ResourceEntry(rs, name, re.elements, autoSync));
} }
return re == null ? null : (A) re.value;
} }
ResourceEntry re = map.get(name);
if (re == null) {
map.put(name, new ResourceEntry(rs));
} else {
map.put(name, new ResourceEntry(rs, name, re.elements, autoSync));
}
return re == null ? null : (A) re.value;
} }
public <A> A find(Class<? extends A> clazz) { public <A> A find(Class<? extends A> clazz) {
@@ -490,7 +503,7 @@ public final class ResourceFactory {
m = method; m = method;
m.setAccessible(true); m.setAccessible(true);
break; break;
} }
} }
} while ((loop = loop.getSuperclass()) != Object.class); } while ((loop = loop.getSuperclass()) != Object.class);
listenerMethods.put(clazz, m); listenerMethods.put(clazz, m);

View File

@@ -84,6 +84,10 @@ public final class Utility {
private Utility() { private Utility() {
} }
public static String uuid() {
return UUID.randomUUID().toString().replace("-", "");
}
public static String now() { public static String now() {
return String.format(format, System.currentTimeMillis()); return String.format(format, System.currentTimeMillis());
} }
@@ -183,6 +187,19 @@ public final class Utility {
return today.getYear() * 10000 + today.getMonthValue() * 100 + today.getDayOfMonth(); return today.getYear() * 10000 + today.getMonthValue() * 100 + today.getDayOfMonth();
} }
/**
* 获取指定时间的20160202格式的int值
*
* @param time 指定时间
*
* @return 毫秒数
*/
public static int yyyyMMdd(long time) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(time);
return cal.get(Calendar.YEAR) * 10000 + (cal.get(Calendar.MONTH) + 1) * 100 + cal.get(Calendar.DAY_OF_MONTH);
}
/** /**
* 获取时间点所在星期的周一 * 获取时间点所在星期的周一
* *
@@ -621,7 +638,7 @@ public final class Utility {
conn.disconnect(); conn.disconnect();
return remoteHttpContent(ctx, method, newurl, headers, body); return remoteHttpContent(ctx, method, newurl, headers, body);
} }
InputStream in = rs < 400 ? conn.getInputStream() : conn.getErrorStream(); InputStream in = rs < 400 || rs == 404 ? conn.getInputStream() : conn.getErrorStream();
ByteArrayOutputStream out = new ByteArrayOutputStream(1024); ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
byte[] bytes = new byte[1024]; byte[] bytes = new byte[1024];
int pos; int pos;
@@ -645,4 +662,33 @@ public final class Utility {
} }
return charsetName == null ? out.toString() : out.toString(charsetName); return charsetName == null ? out.toString() : out.toString(charsetName);
} }
public static ByteArrayOutputStream readStream(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
byte[] bytes = new byte[1024];
int pos;
while ((pos = in.read(bytes)) != -1) {
out.write(bytes, 0, pos);
}
return out;
}
public static byte[] readBytes(InputStream in) throws IOException {
return readStream(in).toByteArray();
}
public static ByteArrayOutputStream readStreamThenClose(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
byte[] bytes = new byte[1024];
int pos;
while ((pos = in.read(bytes)) != -1) {
out.write(bytes, 0, pos);
}
in.close();
return out;
}
public static byte[] readBytesThenClose(InputStream in) throws IOException {
return readStreamThenClose(in).toByteArray();
}
} }

View File

@@ -1,4 +1,4 @@
/** /**
* RedKale工具包 * Redkale工具包
*/ */
package org.redkale.util; package org.redkale.util;

View File

@@ -1,4 +1,4 @@
/** /**
* 提供RedKale服务的监控、动态部署、数据收集功能 * 提供Redkale服务的监控、动态部署、数据收集功能
*/ */
package org.redkale.watch; package org.redkale.watch;

View File

@@ -6,6 +6,7 @@
package org.redkale.test.http; package org.redkale.test.http;
import java.io.*; import java.io.*;
import java.lang.reflect.Type;
import java.net.*; import java.net.*;
import java.nio.charset.*; import java.nio.charset.*;
import java.util.*; import java.util.*;
@@ -18,24 +19,6 @@ import org.redkale.net.http.*;
*/ */
public interface HttpRequestDesc { public interface HttpRequestDesc {
//获取请求方法 GET、POST等
public String getMethod();
//获取协议名 http、https、ws、wss等
public String getProtocol();
//获取Host的Header值
public String getHost();
//获取请求内容的长度, 为-1表示内容长度不确定
public long getContentLength();
//获取Content-Type的header值
public String getContentType();
//获取Connection的Header值
public String getConnection();
//获取客户端地址IP //获取客户端地址IP
public SocketAddress getRemoteAddress(); public SocketAddress getRemoteAddress();
@@ -67,11 +50,29 @@ public interface HttpRequestDesc {
//获取所有Cookie对象 //获取所有Cookie对象
public java.net.HttpCookie[] getCookies(); public java.net.HttpCookie[] getCookies();
//获取Cookie值
public String getCookie(String name);
//获取Cookie值 没有返回默认值 //获取Cookie值 没有返回默认值
public String getCookie(String name, String defaultValue); public String getCookie(String name, String defaultValue);
//获取Cookie值 //获取协议名 http、https、ws、wss等
public String getCookie(String name); public String getProtocol();
//获取请求方法 GET、POST等
public String getMethod();
//获取Content-Type的header值
public String getContentType();
//获取请求内容的长度, 为-1表示内容长度不确定
public long getContentLength();
//获取Connection的Header值
public String getConnection();
//获取Host的Header值
public String getHost();
//获取请求的URL //获取请求的URL
public String getRequestURI(); public String getRequestURI();
@@ -82,20 +83,9 @@ public interface HttpRequestDesc {
//从prefix之后截取getRequestURI再对"/"进行分隔 //从prefix之后截取getRequestURI再对"/"进行分隔
public String[] getRequstURIPaths(String prefix); public String[] getRequstURIPaths(String prefix);
//获取请求URL分段中含prefix段的long // 获取请求URL分段中含prefix段的值
// 例如请求URL /pipes/record/query/time:1453104341363/id:40 // 例如请求URL /pipes/record/query/name:hello
// 获取time参数: long time = request.getRequstURIPath("time:", 0L); // 获取name参数: String name = request.getRequstURIPath("name:", "none");
public long getRequstURIPath(String prefix, long defaultValue);
//获取请求URL分段中含prefix段的int值
// 例如请求URL /pipes/record/query/offset:2/limit:50
// 获取page参数: int offset = request.getRequstURIPath("offset:", 1);
// 获取size参数: int limit = request.getRequstURIPath("limit:", 20);
public int getRequstURIPath(String prefix, int defaultValue);
//获取请求URL分段中含prefix段的值
//例如请求URL /pipes/record/query/name:hello
//获取name参数: String name = request.getRequstURIPath("name:", "none");
public String getRequstURIPath(String prefix, String defaultValue); public String getRequstURIPath(String prefix, String defaultValue);
// 获取请求URL分段中含prefix段的short值 // 获取请求URL分段中含prefix段的short值
@@ -103,6 +93,43 @@ public interface HttpRequestDesc {
// 获取type参数: short type = request.getRequstURIPath("type:", (short)0); // 获取type参数: short type = request.getRequstURIPath("type:", (short)0);
public short getRequstURIPath(String prefix, short defaultValue); public short getRequstURIPath(String prefix, short defaultValue);
// 获取请求URL分段中含prefix段的short值
// 例如请求URL /pipes/record/query/type:a
// 获取type参数: short type = request.getRequstURIPath(16, "type:", (short)0); type = 10
public short getRequstURIPath(int radix, String prefix, short defvalue);
// 获取请求URL分段中含prefix段的int值
// 例如请求URL /pipes/record/query/offset:2/limit:50
// 获取offset参数: int offset = request.getRequstURIPath("offset:", 1);
// 获取limit参数: int limit = request.getRequstURIPath("limit:", 20);
public int getRequstURIPath(String prefix, int defaultValue);
// 获取请求URL分段中含prefix段的int值
// 例如请求URL /pipes/record/query/offset:2/limit:10
// 获取offset参数: int offset = request.getRequstURIPath("offset:", 1);
// 获取limit参数: int limit = request.getRequstURIPath(16, "limit:", 20); // limit = 16
public int getRequstURIPath(int radix, String prefix, int defaultValue);
// 获取请求URL分段中含prefix段的float值
// 例如请求URL /pipes/record/query/point:40.0
// 获取time参数: float point = request.getRequstURIPath("point:", 0.0f);
public float getRequstURIPath(String prefix, float defvalue);
// 获取请求URL分段中含prefix段的long值
// 例如请求URL /pipes/record/query/time:1453104341363/id:40
// 获取time参数: long time = request.getRequstURIPath("time:", 0L);
public long getRequstURIPath(String prefix, long defaultValue);
// 获取请求URL分段中含prefix段的long值
// 例如请求URL /pipes/record/query/time:1453104341363/id:40
// 获取time参数: long time = request.getRequstURIPath("time:", 0L);
public long getRequstURIPath(int radix, String prefix, long defvalue);
// 获取请求URL分段中含prefix段的double值 <br>
// 例如请求URL /pipes/record/query/point:40.0 <br>
// 获取time参数: double point = request.getRequstURIPath("point:", 0.0);
public double getRequstURIPath(String prefix, double defvalue);
//获取所有的header名 //获取所有的header名
public String[] getHeaderNames(); public String[] getHeaderNames();
@@ -113,10 +140,10 @@ public interface HttpRequestDesc {
public String getHeader(String name, String defaultValue); public String getHeader(String name, String defaultValue);
//获取指定的header的json值 //获取指定的header的json值
public <T> T getJsonHeader(JsonConvert convert, Class<T> clazz, String name); public <T> T getJsonHeader(Type type, String name);
//获取指定的header的json值 //获取指定的header的json值
public <T> T getJsonHeader(Class<T> clazz, String name); public <T> T getJsonHeader(JsonConvert convert, Type type, String name);
//获取指定的header的boolean值, 没有返回默认boolean值 //获取指定的header的boolean值, 没有返回默认boolean值
public boolean getBooleanHeader(String name, boolean defaultValue); public boolean getBooleanHeader(String name, boolean defaultValue);
@@ -124,15 +151,30 @@ public interface HttpRequestDesc {
// 获取指定的header的short值, 没有返回默认short值 // 获取指定的header的short值, 没有返回默认short值
public short getShortHeader(String name, short defaultValue); public short getShortHeader(String name, short defaultValue);
// 获取指定的header的short值, 没有返回默认short值
public short getShortHeader(int radix, String name, short defaultValue);
// 获取指定的header的short值, 没有返回默认short值
public short getShortHeader(String name, int defaultValue);
// 获取指定的header的short值, 没有返回默认short值
public short getShortHeader(int radix, String name, int defaultValue);
//获取指定的header的int值, 没有返回默认int值 //获取指定的header的int值, 没有返回默认int值
public int getIntHeader(String name, int defaultValue); public int getIntHeader(String name, int defaultValue);
// 获取指定的header的float值, 没有返回默认float值 //获取指定的header的int值, 没有返回默认int值
public float getFloatHeader(String name, float defaultValue); public int getIntHeader(int radix, String name, int defaultValue);
// 获取指定的header的long值, 没有返回默认long值 // 获取指定的header的long值, 没有返回默认long值
public long getLongHeader(String name, long defaultValue); public long getLongHeader(String name, long defaultValue);
// 获取指定的header的long值, 没有返回默认long值
public long getLongHeader(int radix, String name, long defaultValue);
// 获取指定的header的float值, 没有返回默认float值
public float getFloatHeader(String name, float defaultValue);
//获取指定的header的double值, 没有返回默认double值 //获取指定的header的double值, 没有返回默认double值
public double getDoubleHeader(String name, double defaultValue); public double getDoubleHeader(String name, double defaultValue);
@@ -146,10 +188,10 @@ public interface HttpRequestDesc {
public String getParameter(String name, String defaultValue); public String getParameter(String name, String defaultValue);
//获取指定的参数json值 //获取指定的参数json值
public <T> T getJsonParameter(JsonConvert convert, Class<T> clazz, String name); public <T> T getJsonParameter(Type type, String name);
//获取指定的参数json值 //获取指定的参数json值
public <T> T getJsonParameter(Class<T> clazz, String name); public <T> T getJsonParameter(JsonConvert convert, Type type, String name);
//获取指定的参数boolean值, 没有返回默认boolean值 //获取指定的参数boolean值, 没有返回默认boolean值
public boolean getBooleanParameter(String name, boolean defaultValue); public boolean getBooleanParameter(String name, boolean defaultValue);
@@ -157,18 +199,47 @@ public interface HttpRequestDesc {
//获取指定的参数short值, 没有返回默认short值 //获取指定的参数short值, 没有返回默认short值
public short getShortParameter(String name, short defaultValue); public short getShortParameter(String name, short defaultValue);
//获取指定的参数short值, 没有返回默认short值
public short getShortParameter(int radix, String name, short defaultValue);
//获取指定的参数short值, 没有返回默认short值
public short getShortParameter(int radix, String name, int defaultValue);
//获取指定的参数int值, 没有返回默认int值 //获取指定的参数int值, 没有返回默认int值
public int getIntParameter(String name, int defaultValue); public int getIntParameter(String name, int defaultValue);
//获取指定的参数float值, 没有返回默认float值 //获取指定的参数int值, 没有返回默认int值
public float getFloatParameter(String name, float defaultValue); public int getIntParameter(int radix, String name, int defaultValue);
//获取指定的参数long值, 没有返回默认long值 //获取指定的参数long值, 没有返回默认long值
public long getLongParameter(String name, long defaultValue); public long getLongParameter(String name, long defaultValue);
//获取指定的参数long值, 没有返回默认long值
public long getLongParameter(int radix, String name, long defaultValue);
//获取指定的参数float值, 没有返回默认float值
public float getFloatParameter(String name, float defaultValue);
//获取指定的参数double值, 没有返回默认double值 //获取指定的参数double值, 没有返回默认double值
public double getDoubleParameter(String name, double defaultValue); public double getDoubleParameter(String name, double defaultValue);
//获取翻页对象 同 getFlipper("flipper", false, 0);
public org.redkale.source.Flipper getFlipper();
//获取翻页对象 同 getFlipper("flipper", needcreate, 0);
public org.redkale.source.Flipper getFlipper(boolean needcreate);
//获取翻页对象 同 getFlipper("flipper", false, maxLimit);
public org.redkale.source.Flipper getFlipper(int maxLimit);
//获取翻页对象 同 getFlipper("flipper", needcreate, maxLimit)
public org.redkale.source.Flipper getFlipper(boolean needcreate, int maxLimit);
//获取翻页对象 http://redkale.org/pipes/records/list/offset:0/limit:20/sort:createtime%20ASC
//http://redkale.org/pipes/records/list?flipper={'offset':0,'limit':20, 'sort':'createtime ASC'}
//以上两种接口都可以获取到翻页对象
public org.redkale.source.Flipper getFlipper(String name, boolean needcreate, int maxLimit);
//获取HTTP上下文对象 //获取HTTP上下文对象
public HttpContext getContext(); public HttpContext getContext();

View File

@@ -10,7 +10,10 @@ import java.lang.reflect.*;
import java.net.*; import java.net.*;
import java.nio.*; import java.nio.*;
import java.nio.channels.*; import java.nio.channels.*;
import java.util.*;
import java.util.function.BiConsumer;
import org.redkale.convert.json.*; import org.redkale.convert.json.*;
import org.redkale.net.http.*;
/** /**
* *
@@ -18,6 +21,12 @@ import org.redkale.convert.json.*;
*/ */
public interface HttpResponseDesc { public interface HttpResponseDesc {
//增加Cookie值
public HttpResponse addCookie(HttpCookie... cookies);
//增加Cookie值
public HttpResponse addCookie(Collection<HttpCookie> cookies);
//设置状态码 //设置状态码
public void setStatus(int status); public void setStatus(int status);
@@ -28,26 +37,26 @@ public interface HttpResponseDesc {
public String getContentType(); public String getContentType();
//设置 ContentType //设置 ContentType
public void setContentType(String contentType); public HttpResponse setContentType(String contentType);
//获取内容长度 //获取内容长度
public long getContentLength(); public long getContentLength();
//设置内容长度 //设置内容长度
public void setContentLength(long contentLength); public HttpResponse setContentLength(long contentLength);
//设置Header值 //设置Header值
public void setHeader(String name, Object value); public HttpResponse setHeader(String name, Object value);
//添加Header值 //添加Header值
public void addHeader(String name, Object value); public HttpResponse addHeader(String name, Object value);
//添加Header值
public HttpResponse addHeader(Map<String, ?> map);
//跳过header的输出 //跳过header的输出
//通常应用场景是调用者的输出内容里已经包含了HTTP的响应头信息因此需要调用此方法避免重复输出HTTP响应头信息。 //通常应用场景是调用者的输出内容里已经包含了HTTP的响应头信息因此需要调用此方法避免重复输出HTTP响应头信息。
public void skipHeader(); public HttpResponse skipHeader();
//增加Cookie值
public void addCookie(HttpCookie... cookies);
//异步输出指定内容 //异步输出指定内容
public <A> void sendBody(ByteBuffer buffer, A attachment, CompletionHandler<Integer, A> handler); public <A> void sendBody(ByteBuffer buffer, A attachment, CompletionHandler<Integer, A> handler);
@@ -73,6 +82,18 @@ public interface HttpResponseDesc {
//将对象以JSON格式输出 //将对象以JSON格式输出
public void finishJson(final Object... objs); public void finishJson(final Object... objs);
//将RetResult对象以JSON格式输出
public void finishJson(final org.redkale.service.RetResult ret);
//将RetResult对象以JSON格式输出
public void finishJson(final JsonConvert convert, final org.redkale.service.RetResult ret);
//将对象以JavaScript格式输出
public void finishJsResult(String var, Object result);
//将对象以JavaScript格式输出
public void finishJsResult(JsonConvert jsonConvert, String var, Object result);
//将指定字符串以响应结果输出 //将指定字符串以响应结果输出
public void finish(String obj); public void finish(String obj);
@@ -102,4 +123,10 @@ public interface HttpResponseDesc {
//将指定文件按响应结果输出 //将指定文件按响应结果输出
public void finish(File file) throws IOException; public void finish(File file) throws IOException;
//将文件按指定文件名输出
public void finish(final String filename, File file) throws IOException;
//HttpResponse回收时回调的监听方法
public void setRecycleListener(BiConsumer<HttpRequest, HttpResponse> recycleListener);
} }

View File

@@ -0,0 +1,35 @@
package org.redkale.test.rest;
import org.redkale.convert.json.JsonFactory;
import org.redkale.net.http.*;
import org.redkale.source.FilterBean;
public class HelloBean implements FilterBean {
private int helloid;
@RestHeader(name = "hello-res")
private String res;
public int getHelloid() {
return helloid;
}
public void setHelloid(int helloid) {
this.helloid = helloid;
}
public String getRes() {
return res;
}
public void setRes(String res) {
this.res = res;
}
@Override
public String toString() {
return JsonFactory.root().getConvert().convertTo(this);
}
}

View File

@@ -0,0 +1,88 @@
package org.redkale.test.rest;
import javax.persistence.Id;
import org.redkale.convert.json.JsonFactory;
import org.redkale.net.http.*;
import org.redkale.source.VirtualEntity;
@VirtualEntity
public class HelloEntity {
@Id
private int helloid;
private String helloname;
private int creator;
private long updatetime;
private long createtime;
@RestHeader(name = "hello-res")
private String resname;
@RestAddress
private String clientaddr;
public int getHelloid() {
return helloid;
}
public void setHelloid(int helloid) {
this.helloid = helloid;
}
public String getHelloname() {
return helloname;
}
public void setHelloname(String helloname) {
this.helloname = helloname;
}
public long getUpdatetime() {
return updatetime;
}
public void setUpdatetime(long updatetime) {
this.updatetime = updatetime;
}
public long getCreatetime() {
return createtime;
}
public void setCreatetime(long createtime) {
this.createtime = createtime;
}
public int getCreator() {
return creator;
}
public void setCreator(int creator) {
this.creator = creator;
}
public String getClientaddr() {
return clientaddr;
}
public void setClientaddr(String clientaddr) {
this.clientaddr = clientaddr;
}
public String getResname() {
return resname;
}
public void setResname(String resname) {
this.resname = resname;
}
@Override
public String toString() {
return JsonFactory.root().getConvert().convertTo(this);
}
}

View File

@@ -0,0 +1,79 @@
package org.redkale.test.rest;
import java.util.List;
import javax.annotation.Resource;
import org.redkale.net.http.*;
import org.redkale.service.*;
import org.redkale.source.DataSource;
import org.redkale.source.Flipper;
import org.redkale.util.Sheet;
/**
* 类说明:
* Flipper : Source组件中的翻页对象
* UserInfo :当前用户类
* HelloEntity: Hello模块的实体类
* HelloBean: Hellow模块实现FilterBean的过滤Bean类
*
*/
public class HelloService implements Service {
private int nodeid;
@Resource
private DataSource source;
public HelloService() {
}
public HelloService(int nodeid) {
this.nodeid = nodeid;
}
//增加记录
public RetResult<HelloEntity> createHello(UserInfo info, HelloEntity entity) {
entity.setCreator(info == null ? 0 : info.getUserid()); //设置当前用户ID
entity.setCreatetime(System.currentTimeMillis());
source.insert(entity);
return new RetResult<>(entity);
}
//删除记录
public void deleteHello(int id) { //通过 /hello/delete/1234 删除对象
source.delete(HelloEntity.class, id);
}
//修改记录
public void updateHello(@RestAddress String clientAddr, HelloEntity entity) { //通过 /hello/update?bean={...} 修改对象
System.out.println("修改记录-" + nodeid + ": clientAddr = " + clientAddr + ", entity =" + entity);
if (entity != null) entity.setUpdatetime(System.currentTimeMillis());
if (source != null) source.update(entity);
}
//修改记录
@RestMapping(name = "partupdate")
public void updateHello(HelloEntity entity, @RestParam(name = "cols") String[] columns) { //通过 /hello/partupdate?bean={...} 修改对象
entity.setUpdatetime(System.currentTimeMillis());
source.updateColumns(entity, columns);
}
//查询Sheet列表
public Sheet<HelloEntity> queryHello(HelloBean bean, Flipper flipper) { //通过 /hello/query/offset:0/limit:20?bean={...} 查询Sheet列表
return source.querySheet(HelloEntity.class, flipper, bean);
}
//查询List列表
@RestMapping(name = "list")
public List<HelloEntity> queryHello(HelloBean bean) { //通过 /hello/list?bean={...} 查询List列表
return source.queryList(HelloEntity.class, bean);
}
//查询单个
@RestMapping(name = "find")
@RestMapping(name = "jsfind", jsvar = "varhello")
public HelloEntity findHello(@RestParam(name = "#") int id) { //通过 /hello/find/1234 查询对象
return source.find(HelloEntity.class, id);
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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.rest;
import javax.annotation.Resource;
import org.redkale.net.http.*;
import org.redkale.service.*;
import org.redkale.source.*;
import org.redkale.util.Sheet;
/**
* 类说明:
* Flipper : Source组件中的翻页对象
* UserInfo :当前用户类
* HelloEntity: Hello模块的实体类
* HelloBean: Hellow模块实现FilterBean的过滤Bean类
*
*/
@RestService(name = "hello", moduleid = 0, repair = true, ignore = false)
public class HelloService2 implements Service {
@Resource
private DataSource source;
//增加记录
@RestMapping(name = "create", auth = false)
public RetResult<HelloEntity> createHello(UserInfo info, @RestParam(name = "bean") HelloEntity entity) {
entity.setCreator(info == null ? 0 : info.getUserid()); //设置当前用户ID
entity.setCreatetime(System.currentTimeMillis());
source.insert(entity);
return new RetResult<>(entity);
}
//删除记录
@RestMapping(name = "delete", auth = false)
public void deleteHello(@RestParam(name = "#") int id) { //通过 /hello/delete/1234 删除对象
source.delete(HelloEntity.class, id);
}
//修改记录
@RestMapping(name = "update", auth = false)
public void updateHello(@RestParam(name = "bean") HelloEntity entity) { //通过 /hello/update?bean={...} 修改对象
entity.setUpdatetime(System.currentTimeMillis());
source.update(entity);
}
//查询列表
@RestMapping(name = "query", auth = false)
public Sheet<HelloEntity> queryHello(@RestParam(name = "bean") HelloBean bean, Flipper flipper) { //通过 /hello/query/offset:0/limit:20?bean={...} 查询列表
return source.querySheet(HelloEntity.class, flipper, bean);
}
//查询单个
@RestMapping(name = "find", auth = false)
public HelloEntity findHello(@RestParam(name = "#") int id) { //通过 /hello/find/1234 查询对象
return source.find(HelloEntity.class, id);
}
}

View File

@@ -0,0 +1,163 @@
/*
* 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.rest;
import java.lang.reflect.*;
import java.util.*;
import org.redkale.service.*;
/**
*
* @author zhangjx
*/
public abstract class RetCodes {
protected static final Map<Integer, String> rets = new HashMap<>();
protected RetCodes() {
}
//-----------------------------------------------------------------------------------------------------------
protected static void load(Class clazz) {
for (Field field : clazz.getFields()) {
if (!Modifier.isStatic(field.getModifiers())) continue;
if (field.getType() != int.class) continue;
RetLabel info = field.getAnnotation(RetLabel.class);
if (info == null) continue;
int value;
try {
value = field.getInt(null);
} catch (Exception ex) {
ex.printStackTrace();
continue;
}
rets.put(value, info.value());
}
}
public static RetResult retResult(int retcode) {
if (retcode == 0) return RetResult.success();
return new RetResult(retcode, retInfo(retcode));
}
public static String retInfo(int retcode) {
if (retcode == 0) return "成功";
return rets.getOrDefault(retcode, "未知错误");
}
//2000_0001 - 2999_9999 预留给 Redkale的扩展包redkalex使用
//3000_0001 - 7999_9999 为平台系统使用
//8000_0001 - 9999_9999 为OSS系统使用
//------------------------------------- 通用模块 -----------------------------------------
@RetLabel("参数无效")
public static final int RET_PARAMS_ILLEGAL = 30010001;
@RetLabel("无上传文件")
public static final int RET_UPLOAD_NOFILE = 30010002;
@RetLabel("上传文件过大")
public static final int RET_UPLOAD_FILETOOBIG = 30010003;
@RetLabel("上传文件不是图片")
public static final int RET_UPLOAD_NOTIMAGE = 30010004;
//------------------------------------- 用户模块 -----------------------------------------
@RetLabel("未登陆")
public static final int RET_USER_UNLOGIN = 30020001;
@RetLabel("用户登录失败")
public static final int RET_USER_LOGIN_FAIL = 30020002;
@RetLabel("用户或密码错误")
public static final int RET_USER_ACCOUNT_PWD_ILLEGAL = 30020003;
@RetLabel("密码设置无效")
public static final int RET_USER_PASSWORD_ILLEGAL = 30020004;
@RetLabel("用户被禁用")
public static final int RET_USER_FREEZED = 30020005;
@RetLabel("用户权限不够")
public static final int RET_USER_AUTH_ILLEGAL = 30020006;
@RetLabel("用户不存在")
public static final int RET_USER_NOTEXISTS = 30020007;
@RetLabel("用户状态异常")
public static final int RET_USER_STATUS_ILLEGAL = 30020008;
@RetLabel("用户注册参数无效")
public static final int RET_USER_SIGNUP_ILLEGAL = 30020009;
@RetLabel("用户性别参数无效")
public static final int RET_USER_GENDER_ILLEGAL = 30020010;
@RetLabel("用户名无效")
public static final int RET_USER_USERNAME_ILLEGAL = 30020011;
@RetLabel("用户账号无效")
public static final int RET_USER_ACCOUNT_ILLEGAL = 30020012;
@RetLabel("用户账号已存在")
public static final int RET_USER_ACCOUNT_EXISTS = 30020013;
@RetLabel("手机号码无效")
public static final int RET_USER_MOBILE_ILLEGAL = 30020014;
@RetLabel("手机号码已存在")
public static final int RET_USER_MOBILE_EXISTS = 30020015;
@RetLabel("手机验证码发送过于频繁")
public static final int RET_USER_MOBILE_SMSFREQUENT = 30020016;
@RetLabel("邮箱地址无效")
public static final int RET_USER_EMAIL_ILLEGAL = 30020017;
@RetLabel("邮箱地址已存在")
public static final int RET_USER_EMAIL_EXISTS = 30020018;
@RetLabel("微信绑定号无效")
public static final int RET_USER_WXID_ILLEGAL = 30020019;
@RetLabel("微信绑定号已存在")
public static final int RET_USER_WXID_EXISTS = 30020020;
@RetLabel("绑定微信号失败")
public static final int RET_USER_WXID_BIND_FAIL = 30020021;
@RetLabel("QQ绑定号无效")
public static final int RET_USER_QQID_ILLEGAL = 30020022;
@RetLabel("QQ绑定号已存在")
public static final int RET_USER_QQID_EXISTS = 30020023;
@RetLabel("绑定QQ号失败")
public static final int RET_USER_QQID_BIND_FAIL = 30020024;
@RetLabel("获取绑定QQ信息失败")
public static final int RET_USER_QQID_INFO_FAIL = 30020025;
@RetLabel("验证码无效")
public static final int RET_USER_RANDCODE_ILLEGAL = 30020026; //邮件或者短信验证码
@RetLabel("验证码已过期")
public static final int RET_USER_RANDCODE_EXPIRED = 30020027; //邮件或者短信验证码
@RetLabel("验证码错误或失效")
public static final int RET_USER_CAPTCHA_ILLEGAL = 30020028; //图片验证码
@RetLabel("用户类型无效")
public static final int RET_USER_TYPE_ILLEGAL = 30020029;
@RetLabel("用户设备ID无效")
public static final int RET_USER_APPTOKEN_ILLEGAL = 30020030;
static {
load(RetCodes.class);
}
}

View File

@@ -0,0 +1,41 @@
package org.redkale.test.rest;
import java.io.IOException;
import javax.annotation.Resource;
import org.redkale.net.http.*;
import org.redkale.service.RetResult;
public class SimpleRestServlet extends RestHttpServlet<UserInfo> {
protected static final RetResult RET_UNLOGIN = RetCodes.retResult(RetCodes.RET_USER_UNLOGIN);
protected static final RetResult RET_AUTHILLEGAL = RetCodes.retResult(RetCodes.RET_USER_AUTH_ILLEGAL);
@Resource
private UserService userService;
//获取当前用户信息
@Override
protected UserInfo currentUser(HttpRequest req) throws IOException {
String sessionid = req.getSessionid(false);
if (sessionid == null || sessionid.isEmpty()) return null;
return userService.current(sessionid);
}
//普通鉴权
@Override
public boolean authenticate(int module, int actionid, HttpRequest request, HttpResponse response) throws IOException {
UserInfo info = currentUser(request);
if (info == null) {
response.finishJson(RET_UNLOGIN);
return false;
} else if (!info.checkAuth(module, actionid)) {
response.finishJson(RET_AUTHILLEGAL);
return false;
}
return true;
}
}

View File

@@ -0,0 +1,42 @@
package org.redkale.test.rest;
import org.redkale.convert.json.JsonFactory;
/**
* 当前用户对象
*
* @author zhangjx
*/
public class UserInfo {
private int userid;
private String username = "";
public int getUserid() {
return userid;
}
public boolean checkAuth(int moduleid, int actionid) {
if (moduleid == 0 || actionid == 0) return true;
//权限判断
return true;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return JsonFactory.root().getConvert().convertTo(this);
}
}

View File

@@ -0,0 +1,21 @@
/*
* 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.rest;
import org.redkale.service.Service;
/**
* 简单的定义UserService接口
*
* @author zhangjx
*/
public class UserService implements Service {
//根据登录态获取当前用户信息
public UserInfo current(String sessionid) {
return null;
}
}

View File

@@ -0,0 +1,119 @@
package org.redkale.test.rest;
import java.io.IOException;
import java.util.*;
import javax.annotation.Resource;
import org.redkale.net.http.*;
import org.redkale.service.RetResult;
import org.redkale.source.Flipper;
import org.redkale.util.*;
import org.redkale.util.AnyValue.DefaultAnyValue;
@WebServlet(value = {"/hello/*"}, repair = true)
public class _DynHelloRestServlet1 extends SimpleRestServlet {
@Resource
private HelloService _service;
@Resource
private Map<String, HelloService> _servicemap;
public static void main(String[] args) throws Throwable {
final int port = 8888;
HelloService service = new HelloService();
HttpServer server = new HttpServer();
System.out.println(server.addRestServlet("", HelloService.class, service, SimpleRestServlet.class, "/pipes"));
System.out.println(server.addRestServlet("my-res", HelloService.class, new HelloService(3), SimpleRestServlet.class, "/pipes"));
DefaultAnyValue conf = DefaultAnyValue.create("port", "" + port);
server.init(conf);
server.start();
Thread.sleep(100);
HelloEntity entity = new HelloEntity();
entity.setHelloname("my name");
Map<String, String> headers = new HashMap<>();
headers.put("hello-res", "my res");
//headers.put(Rest.REST_HEADER_RESOURCE_NAME, "my-res");
String url = "http://127.0.0.1:" + port + "/pipes/hello/update?entity={}&bean2={}";
System.out.println(Utility.postHttpContent(url, headers, null));
}
@AuthIgnore
@WebAction(url = "/hello/create")
public void create(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
UserInfo user = currentUser(req);
RetResult<HelloEntity> result = service.createHello(user, bean);
resp.finishJson(result);
}
@AuthIgnore
@WebAction(url = "/hello/delete/")
public void delete(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
int id = Integer.parseInt(req.getRequstURILastPath());
service.deleteHello(id);
resp.finishJson(RetResult.success());
}
@AuthIgnore
@WebAction(url = "/hello/update")
public void update(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
String clientaddr = req.getRemoteAddr();
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
service.updateHello(clientaddr, bean);
resp.finishJson(RetResult.success());
}
@AuthIgnore
@WebAction(url = "/hello/partupdate")
public void partupdate(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
String[] cols = req.getJsonParameter(String[].class, "cols");
service.updateHello(bean, cols);
resp.finishJson(RetResult.success());
}
@AuthIgnore
@WebAction(url = "/hello/query")
public void query(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloBean bean = req.getJsonParameter(HelloBean.class, "bean");
Flipper flipper = req.getFlipper();
Sheet<HelloEntity> result = service.queryHello(bean, flipper);
resp.finishJson(result);
}
@AuthIgnore
@WebAction(url = "/hello/list")
public void list(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloBean bean = req.getJsonParameter(HelloBean.class, "bean");
List<HelloEntity> result = service.queryHello(bean);
resp.finishJson(result);
}
@AuthIgnore
@WebAction(url = "/hello/find/")
public void find(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
int id = Integer.parseInt(req.getRequstURILastPath());
HelloEntity bean = service.findHello(id);
resp.finishJson(bean);
}
@AuthIgnore
@WebAction(url = "/hello/jsfind/")
public void jsfind(HttpRequest req, HttpResponse resp) throws IOException {
HelloService service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
int id = Integer.parseInt(req.getRequstURILastPath());
HelloEntity bean = service.findHello(id);
resp.finishJsResult("varhello", bean);
}
}

View File

@@ -0,0 +1,75 @@
/*
* 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.rest;
import java.io.IOException;
import java.util.Map;
import javax.annotation.Resource;
import org.redkale.net.http.*;
import org.redkale.service.RetResult;
import org.redkale.source.Flipper;
import org.redkale.util.Sheet;
/**
*
* @author zhangjx
*/
@WebServlet(value = {"/hello/*"}, repair = true)
public class _DynHelloRestServlet2 extends SimpleRestServlet {
@Resource
private HelloService2 _service;
@Resource
private Map<String, HelloService2> _servicemap;
@AuthIgnore
@WebAction(url = "/hello/create")
public void create(HttpRequest req, HttpResponse resp) throws IOException {
HelloService2 service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
UserInfo user = currentUser(req);
RetResult<HelloEntity> result = service.createHello(user, bean);
resp.finishJson(result);
}
@AuthIgnore
@WebAction(url = "/hello/delete/")
public void delete(HttpRequest req, HttpResponse resp) throws IOException {
HelloService2 service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
int id = Integer.parseInt(req.getRequstURILastPath());
service.deleteHello(id);
resp.finishJson(RetResult.success());
}
@AuthIgnore
@WebAction(url = "/hello/update")
public void update(HttpRequest req, HttpResponse resp) throws IOException {
HelloService2 service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloEntity bean = req.getJsonParameter(HelloEntity.class, "bean");
service.updateHello(bean);
resp.finishJson(RetResult.success());
}
@AuthIgnore
@WebAction(url = "/hello/query")
public void query(HttpRequest req, HttpResponse resp) throws IOException {
HelloService2 service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
HelloBean bean = req.getJsonParameter(HelloBean.class, "bean");
Flipper flipper = req.getFlipper();
Sheet<HelloEntity> result = service.queryHello(bean, flipper);
resp.finishJson(result);
}
@AuthIgnore
@WebAction(url = "/hello/find/")
public void find(HttpRequest req, HttpResponse resp) throws IOException {
HelloService2 service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, ""));
int id = Integer.parseInt(req.getRequstURILastPath());
HelloEntity bean = service.findHello(id);
resp.finishJson(bean);
}
}

View File

@@ -68,11 +68,11 @@ public class SncpTest {
public static ObjectPool<ByteBuffer> newBufferPool() { public static ObjectPool<ByteBuffer> newBufferPool() {
return new ObjectPool<>(new AtomicLong(), new AtomicLong(), 16, return new ObjectPool<>(new AtomicLong(), new AtomicLong(), 16,
(Object... params) -> ByteBuffer.allocateDirect(8192), null, (e) -> { (Object... params) -> ByteBuffer.allocateDirect(8192), null, (e) -> {
if (e == null || e.isReadOnly() || e.capacity() != 8192) return false; if (e == null || e.isReadOnly() || e.capacity() != 8192) return false;
e.clear(); e.clear();
return true; return true;
}); });
} }
private static void runClient() throws Exception { private static void runClient() throws Exception {
@@ -81,7 +81,7 @@ public class SncpTest {
set.add(addr); set.add(addr);
if (port2 > 0) set.add(new InetSocketAddress(myhost, port2)); if (port2 > 0) set.add(new InetSocketAddress(myhost, port2));
//String name, WatchFactory, ObjectPool<ByteBuffer>, AsynchronousChannelGroup, InetSocketAddress clientAddress, Collection<InetSocketAddress> //String name, WatchFactory, ObjectPool<ByteBuffer>, AsynchronousChannelGroup, InetSocketAddress clientAddress, Collection<InetSocketAddress>
final Transport transport = new Transport("", WatchFactory.root(), newBufferPool(), newChannelGroup(), null, set); final Transport transport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, set);
final SncpTestService service = Sncp.createRemoteService(serviceName, null, SncpTestService.class, null, transport); final SncpTestService service = Sncp.createRemoteService(serviceName, null, SncpTestService.class, null, transport);
ResourceFactory.root().inject(service); ResourceFactory.root().inject(service);
@@ -97,7 +97,7 @@ public class SncpTest {
callbean.setContent("数据X"); callbean.setContent("数据X");
service.insert(callbean); service.insert(callbean);
System.out.println("bean.id应该会被修改 " + callbean); System.out.println("bean.id应该会被修改(id不会是1) " + callbean);
System.out.println("---------------------------------------------------"); System.out.println("---------------------------------------------------");
final int count = 10; final int count = 10;
final CountDownLatch cld = new CountDownLatch(count); final CountDownLatch cld = new CountDownLatch(count);
@@ -151,10 +151,10 @@ public class SncpTest {
Set<InetSocketAddress> set = new LinkedHashSet<>(); Set<InetSocketAddress> set = new LinkedHashSet<>();
if (port2 > 0) set.add(new InetSocketAddress(myhost, port2)); if (port2 > 0) set.add(new InetSocketAddress(myhost, port2));
//String name, WatchFactory, ObjectPool<ByteBuffer>, AsynchronousChannelGroup, InetSocketAddress clientAddress, Collection<InetSocketAddress> //String name, WatchFactory, ObjectPool<ByteBuffer>, AsynchronousChannelGroup, InetSocketAddress clientAddress, Collection<InetSocketAddress>
final Transport transport = new Transport("", WatchFactory.root(), newBufferPool(), newChannelGroup(), null, set); final Transport transport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, set);
SncpTestService service = Sncp.createLocalService("", null, ResourceFactory.root(), SncpTestService.class, addr, transport, null); SncpTestService service = Sncp.createLocalService("", null, ResourceFactory.root(), SncpTestService.class, addr, transport, null);
ResourceFactory.root().inject(service); ResourceFactory.root().inject(service);
server.addService(new ServiceWrapper(service, "", "", new HashSet<>(), null)); server.addSncpServlet(new ServiceWrapper(service, "", "", new HashSet<>(), null));
System.out.println(service); System.out.println(service);
AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue(); AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue();
conf.addValue("host", "0.0.0.0"); conf.addValue("host", "0.0.0.0");
@@ -185,9 +185,9 @@ public class SncpTest {
Set<InetSocketAddress> set = new LinkedHashSet<>(); Set<InetSocketAddress> set = new LinkedHashSet<>();
set.add(new InetSocketAddress(myhost, port)); set.add(new InetSocketAddress(myhost, port));
//String name, WatchFactory, ObjectPool<ByteBuffer>, AsynchronousChannelGroup, InetSocketAddress clientAddress, Collection<InetSocketAddress> //String name, WatchFactory, ObjectPool<ByteBuffer>, AsynchronousChannelGroup, InetSocketAddress clientAddress, Collection<InetSocketAddress>
final Transport transport = new Transport("", WatchFactory.root(), newBufferPool(), newChannelGroup(), null, set); final Transport transport = new Transport("", WatchFactory.root(), "", newBufferPool(), newChannelGroup(), null, set);
Service service = Sncp.createLocalService("", null, ResourceFactory.root(), SncpTestService.class, addr, transport, null); Service service = Sncp.createLocalService("", null, ResourceFactory.root(), SncpTestService.class, addr, transport, null);
server.addService(new ServiceWrapper(service, "", "", new HashSet<>(), null)); server.addSncpServlet(new ServiceWrapper(service, "", "", new HashSet<>(), null));
AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue(); AnyValue.DefaultAnyValue conf = new AnyValue.DefaultAnyValue();
conf.addValue("host", "0.0.0.0"); conf.addValue("host", "0.0.0.0");
conf.addValue("port", "" + port2); conf.addValue("port", "" + port2);

View File

@@ -18,6 +18,7 @@ import org.redkale.convert.json.*;
public class SncpTestBean implements FilterBean { public class SncpTestBean implements FilterBean {
@Id @Id
@GeneratedValue
private long id; private long id;
private String content; private String content;

View File

@@ -29,7 +29,7 @@ public class UntilTestMain {
Reproduce<TestXBean, TestBean> action2 = new Reproduce<TestXBean, TestBean>() { Reproduce<TestXBean, TestBean> action2 = new Reproduce<TestXBean, TestBean>() {
@Override @Override
public TestXBean copy(TestXBean dest, TestBean src) { public TestXBean apply(TestXBean dest, TestBean src) {
dest.time = src.time; dest.time = src.time;
dest.setId(src.getId()); dest.setId(src.getId());
dest.setName(src.getName()); dest.setName(src.getName());
@@ -40,13 +40,13 @@ public class UntilTestMain {
final int count = 1_000_000; final int count = 1_000_000;
long s = System.nanoTime(); long s = System.nanoTime();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
action2.copy(beanx, bean); action2.apply(beanx, bean);
} }
long e = System.nanoTime() - s; long e = System.nanoTime() - s;
System.out.println("静态Reproduce耗时: " + e); System.out.println("静态Reproduce耗时: " + e);
s = System.nanoTime(); s = System.nanoTime();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
action1.copy(beanx, bean); action1.apply(beanx, bean);
} }
e = System.nanoTime() - s; e = System.nanoTime() - s;
System.out.println("动态Reproduce耗时: " + e); System.out.println("动态Reproduce耗时: " + e);

View File

@@ -9,12 +9,8 @@ import org.redkale.net.http.WebServlet;
import org.redkale.net.http.WebSocketServlet; import org.redkale.net.http.WebSocketServlet;
import org.redkale.net.http.WebSocket; import org.redkale.net.http.WebSocket;
import java.io.*; import java.io.*;
import static java.lang.Thread.sleep;
import java.text.*;
import java.util.concurrent.atomic.*; import java.util.concurrent.atomic.*;
import static java.lang.Thread.sleep; import org.redkale.util.Utility;
import static java.lang.Thread.sleep;
import static java.lang.Thread.sleep;
/** /**
* *
@@ -33,8 +29,6 @@ public class ChatWebSocketServlet extends WebSocketServlet {
debug = "true".equalsIgnoreCase(System.getProperty("debug", "false")); debug = "true".equalsIgnoreCase(System.getProperty("debug", "false"));
Thread t = new Thread() { Thread t = new Thread() {
private final DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
{ {
setName("Debug-ChatWebSocket-ShowCount-Thread"); setName("Debug-ChatWebSocket-ShowCount-Thread");
} }
@@ -47,7 +41,7 @@ public class ChatWebSocketServlet extends WebSocketServlet {
} catch (Exception e) { } catch (Exception e) {
return; return;
} }
System.out.println(format.format(new java.util.Date()) + ": 消息总数: " + counter.get() + ",间隔消息数: " + icounter.getAndSet(0)); System.out.println(Utility.now() + ": 消息总数: " + counter.get() + ",间隔消息数: " + icounter.getAndSet(0));
} }
} }
}; };

View File

@@ -113,19 +113,15 @@ public class VideoWebSocketServlet extends WebSocketServlet {
public static void main(String[] args) throws Throwable { public static void main(String[] args) throws Throwable {
CountDownLatch cdl = new CountDownLatch(1); CountDownLatch cdl = new CountDownLatch(1);
AnyValue.DefaultAnyValue config = new AnyValue.DefaultAnyValue(); AnyValue.DefaultAnyValue config = AnyValue.create()
config.addValue("threads", System.getProperty("threads")); .addValue("threads", System.getProperty("threads"))
config.addValue("bufferPoolSize", System.getProperty("bufferPoolSize")); .addValue("bufferPoolSize", System.getProperty("bufferPoolSize"))
config.addValue("responsePoolSize", System.getProperty("responsePoolSize")); .addValue("responsePoolSize", System.getProperty("responsePoolSize"))
config.addValue("host", System.getProperty("host", "0.0.0.0")); .addValue("host", System.getProperty("host", "0.0.0.0"))
config.addValue("port", System.getProperty("port", "8070")); .addValue("port", System.getProperty("port", "8070"))
config.addValue("root", System.getProperty("root", "./root3/")); .addValue("root", System.getProperty("root", "./root3/"));
AnyValue.DefaultAnyValue resConf = new AnyValue.DefaultAnyValue();
resConf.setValue("cacheMaxLength", "200M");
resConf.setValue("cacheMaxItemLength", "10M");
config.setValue("ResourceServlet", resConf);
HttpServer server = new HttpServer(); HttpServer server = new HttpServer();
server.addHttpServlet(new VideoWebSocketServlet(), "/pipes", null, "/listen/*"); server.addHttpServlet("/pipes", new VideoWebSocketServlet(), "/listen/*");
server.init(config); server.init(config);
server.start(); server.start();
cdl.await(); cdl.await();