383 Commits

Author SHA1 Message Date
Redkale
b7acce0814 Redkale 2.0.0.beta4 结束 2019-09-20 08:58:51 +08:00
Redkale
8744e76cad 2019-09-19 21:52:52 +08:00
Redkale
446b3c13dc 2019-09-19 21:38:53 +08:00
Redkale
3951e28148 2019-09-19 21:38:22 +08:00
Redkale
b74d679608 修复ByteBuffer Utility.encodeUTF8的bug 2019-09-19 21:35:05 +08:00
Redkale
edbc878b73 修复Utility.encodeUTF8Length的bug 2019-09-19 21:22:47 +08:00
Redkale
f706209ec1 RestResult合并进HttpResult 2019-09-19 21:08:36 +08:00
Redkale
bf000b188f 增加RestResult功能 2019-09-19 20:30:30 +08:00
Redkale
def1736a9b 2019-09-19 13:22:56 +08:00
Redkale
0242f4c0c3 2019-09-19 13:22:20 +08:00
Redkale
5cd399b2df 2019-09-19 13:12:33 +08:00
Redkale
9ddb662016 Convert增加BiFunction<Attribute, Object, Object> fieldFunc参数 2019-09-19 12:05:03 +08:00
Redkale
2947275d54 2019-09-18 11:27:54 +08:00
Redkale
e43f814872 Utility增加containsMatch、removeMatch方法 2019-09-18 11:22:28 +08:00
Redkale
6e16f52e28 2019-09-18 11:02:13 +08:00
Redkale
fca13557df 【不兼容】删掉javax.persistence.GeneratedValue功能 2019-09-16 16:35:41 +08:00
Redkale
824a6df55a 2019-09-16 16:29:12 +08:00
Redkale
b98b526c50 2019-09-09 16:35:08 +08:00
Redkale
8f6aa4f4a5 2019-09-09 16:29:48 +08:00
Redkale
00a07a79b2 2019-09-09 16:25:10 +08:00
Redkale
264dfbef2e HttpServlet增加postStart方法 2019-09-04 10:00:29 +08:00
Redkale
2e27814809 2019-09-04 09:22:42 +08:00
Redkale
f767f40e56 StringConvertWrapper 改成 StringWrapper 2019-08-30 15:18:03 +08:00
Redkale
543ecc071a 2019-08-30 10:50:24 +08:00
Redkale
2a14f39495 2019-08-30 09:30:41 +08:00
Redkale
95c8ae2334 2019-08-30 08:05:28 +08:00
Redkale
338ea13828 2019-08-29 17:44:13 +08:00
Redkale
4a8b9e5fec 2019-08-29 16:43:45 +08:00
Redkale
e281cac3d3 2019-08-28 16:15:28 +08:00
Redkale
a495829a3c RestHeader支持InetSocketAddress类型 2019-08-28 14:31:33 +08:00
Redkale
b0deed2a89 WebSocket增加getSncpAddress方法,获取分布式下的sncp地址 2019-08-28 12:56:50 +08:00
Redkale
70a75abf74 Redkale 2.0.0.beta3 结束 2019-08-15 13:11:17 +08:00
Redkale
1aa97f8e79 2019-08-06 10:08:24 +08:00
Redkale
b4000235ac 2019-08-05 17:51:26 +08:00
Redkale
4b93f29a1c 2019-08-05 17:14:14 +08:00
Redkale
4892a50670 2019-08-05 16:26:52 +08:00
Redkale
2fe0ac0ef9 修复ColumnValue.mov时字段类型是long,而参数值是int会报错的bug 2019-07-31 17:19:35 +08:00
Redkale
333ae72148 2019-07-30 11:05:11 +08:00
Redkale
5fd5b7f303 2019-07-30 10:58:37 +08:00
Redkale
528cf45f3f ColumnExpress增加除法、取模表达式 2019-07-30 10:31:48 +08:00
Redkale
c7308e7320 修复ConvertFacotry.register方法中column参数没有对应field时会导致method的ignore失效的bug 2019-07-29 13:20:23 +08:00
Redkale
e2a49eaab7 2019-07-29 11:40:33 +08:00
Redkale
44bd6f235c 2019-07-25 16:58:20 +08:00
Redkale
601d15b513 2019-07-17 19:00:18 +08:00
Redkale
9e93485a97 新增HttpRequest.getQueryBytes方法 2019-07-17 18:42:45 +08:00
Redkale
ad87b2115d 修改多个@RetLabel不能正确根据locale获取对应值的bug 2019-07-17 15:14:48 +08:00
Redkale
27a587d31f 修复mysql下update操作值带转义字符导致失败的bug 2019-07-12 16:52:46 +08:00
Redkale
fc8fa27602 RetResult增加map静态方法 2019-07-11 14:53:51 +08:00
Redkale
f9aebc8ee3 修复同一个Entity类被多个source源分表分库操作时判断表是否已建有误的bug 2019-07-09 14:18:07 +08:00
Redkale
1167da8f4c Redkale 2.0.0.beta2 结束 2019-07-08 09:15:26 +08:00
Redkale
7a5fbcdccd 2019-07-03 11:35:37 +08:00
Redkale
345e929712 [不兼容修改]CacheSource的getCollectionMap序列方法增加一个set参数 2019-06-27 18:21:19 +08:00
Redkale
358862fe59 修复Entity类带boolean字段调DataSource.insert出现异常的bug 2019-06-26 16:51:48 +08:00
Redkale
3dde9bb293 2019-06-21 17:00:40 +08:00
Redkale
99ae4ccadd 从Context中移除BufferPool和ResponsePool 2019-06-20 15:26:20 +08:00
Redkale
98e9ffe0ef 2019-06-20 10:02:24 +08:00
Redkale
6927bfe8ac 2019-06-19 16:52:00 +08:00
Redkale
340a3a8fa3 2019-06-19 16:46:12 +08:00
Redkale
4724763991 2019-06-19 16:45:45 +08:00
Redkale
03353ad08c 2019-06-19 16:21:05 +08:00
Redkale
95c3354fcd WebSocketParam增加getAnnotations系列方法 2019-06-19 15:47:46 +08:00
Redkale
1bda2f92b9 HttpRequest增加getAnnotation系列方法 2019-06-18 22:59:07 +08:00
Redkale
bd3c706934 修复DataSource中json字段不为Serializable时会异常的bug 2019-06-13 22:34:53 +08:00
Redkale
ef3663aa36 修复DataSource中json字段不为Serializable时会异常的bug 2019-06-13 22:23:30 +08:00
Redkale
427ff717d4 UDP协议下bufferCapacity默认值为1350字节 2019-05-30 12:07:09 +08:00
Redkale
b409300412 UDP协议下bufferCapacity默认值为1480字节 2019-05-30 12:04:13 +08:00
Redkale
ca1f974dbe 2019-05-28 17:43:48 +08:00
Redkale
6a8c86096b DataSource的clearTable、dropTable在表不存在的情况下由抛异常改为结果值返回-1 2019-05-28 15:51:59 +08:00
Redkale
2b2fd9965b Redkale 2.0.0.beta1 结束 2019-05-25 10:46:10 +08:00
Redkale
0938635eb2 2019-05-18 08:37:53 +08:00
Redkale
a4a186751e 2019-05-01 08:05:37 +08:00
Redkale
ea5169b5c5 修改mysql中字符串带\会丢失的bug 2019-04-27 11:17:28 +08:00
Redkale
01bd195847 2019-04-26 21:24:02 +08:00
Redkale
a72c26a935 修复Utility.encodeUTF8和decodeUTF8 对4字节字符不能正常编码的bug 2019-04-22 12:24:55 +08:00
Redkale
a9900d9bfa 2019-04-19 19:41:04 +08:00
Redkale
6896401d2d 2019-04-19 19:32:24 +08:00
Redkale
886f01c9f3 DataSource在Cachable定时load时屏蔽log 2019-04-19 19:31:09 +08:00
Redkale
59c9251d70 2019-04-12 12:14:52 +08:00
Redkale
fad5f010d2 2019-04-12 11:57:21 +08:00
Redkale
737c4a92b9 修复ConvertFactory.registerIgnoreAll方法出现不生效的bug 2019-04-04 22:20:16 +08:00
Redkale
d3e8675948 Redkale 2.0.0.alpha2 开始 2019-04-04 22:18:49 +08:00
Redkale
a4ffc7a27c 2019-03-30 20:23:55 +08:00
Redkale
91bf7b1387 2019-03-30 17:28:25 +08:00
Redkale
1396296337 2019-03-29 11:51:19 +08:00
Redkale
e4672355fc Convert增加StringConvertWrapper功能 2019-03-29 11:44:37 +08:00
Redkale
129ed25ca4 2019-03-29 09:08:16 +08:00
Redkale
e6d7e5fe98 2019-03-28 17:36:31 +08:00
Redkale
73ce5fa11f Convert支持AbstractMap.SimpleEntry 2019-03-28 14:56:28 +08:00
Redkale
ce01c3d4ce 2019-03-22 12:21:38 +08:00
Redkale
3b3de316ea 2019-03-21 14:19:35 +08:00
Redkale
8c739ce54d 2019-03-16 12:58:54 +08:00
Redkale
0aa4d6c967 2019-03-15 10:19:00 +08:00
Redkale
d7a3f4d87d 2019-03-14 21:25:14 +08:00
Redkale
fe9e074581 2019-03-14 17:00:22 +08:00
Redkale
40813e8752 2019-03-14 16:17:43 +08:00
Redkale
e90f2e4142 WebSocket增加mergemsg属性功能 2019-03-14 15:27:05 +08:00
Redkale
2a19ea709b 2019-03-14 13:47:57 +08:00
Redkale
30c9be303f Convert增加ConvertMask[]参数方法 2019-03-14 13:17:31 +08:00
Redkale
e101b79472 修复ws数据包过大粘包的bug 2019-03-14 12:32:07 +08:00
Redkale
8ad919f952 修复了Convert在忽略子类某些字段时因为Method导致无法忽略父类的getter方法的bug 2019-03-06 09:31:18 +08:00
Redkale
294543c46e 取消DataSource兼容找不到unitName时使用第一个配置的功能 2019-03-05 20:16:57 +08:00
Redkale
79f8363d47 2019-03-05 12:23:21 +08:00
Redkale
6d3553b0b5 2019-02-12 13:16:43 +08:00
Redkale
403ab4e281 2019-02-12 12:23:03 +08:00
Redkale
87e7c43032 修复JDK9+以上RedkaleClassLoader的getAllURLS方法中的BUG 2019-02-12 11:52:23 +08:00
Redkale
a321b41699 2019-01-19 16:28:44 +08:00
Redkale
fea34863e3 2019-01-18 22:25:20 +08:00
Redkale
bcaf7ab73e 2019-01-18 19:48:32 +08:00
Redkale
b9d7eaee1b 2019-01-18 18:52:47 +08:00
Redkale
d605045858 2019-01-18 16:55:48 +08:00
Redkale
cf2ab617c2 修复AioAsyncConnection关闭时write队列还有数据没写完的bug 2019-01-18 15:50:23 +08:00
Redkale
204514cb08 增加Utility.nowMillis方法 2019-01-18 10:41:30 +08:00
Redkale
cfe01cca75 2019-01-16 19:04:54 +08:00
Redkale
ac294c58ae 2019-01-16 19:01:48 +08:00
Redkale
6950eb2f30 2019-01-13 16:51:06 +08:00
Redkale
847f81374b 2019-01-12 11:44:50 +08:00
Redkale
bb09aea8bb 2019-01-12 11:28:29 +08:00
Redkale
2e1ff333f5 Application.singleton多加一个参数,指定其他Service也被加载 2019-01-12 11:16:27 +08:00
Redkale
c14a2b4011 updateColumnCompose 2019-01-12 11:15:02 +08:00
Redkale
d9c6c3d2d0 2019-01-11 16:51:21 +08:00
Redkale
91d4477ed9 DataSource增加字段加解密功能,主类:CryptColumn/CryptHandler 2019-01-11 16:41:14 +08:00
Redkale
623c0a127e Attribute增加attach方法 2019-01-11 15:22:29 +08:00
Redkale
bc64666700 Reproduce.create方法中BiPredicate参数的第一个泛型改为AccessibleObject 2019-01-10 18:43:45 +08:00
Redkale
5c7dd7d782 2019-01-09 16:17:48 +08:00
Redkale
e78a2da6c0 2019-01-09 16:16:08 +08:00
Redkale
065be6f3d7 增加RetResult.success(V result)方法 2019-01-09 09:44:53 +08:00
Redkale
874f3330b8 Update README.md 2019-01-08 14:33:41 +08:00
Redkale
684edfa10b 2019-01-08 12:54:09 +08:00
Redkale
e69a120965 2019-01-08 12:46:20 +08:00
Redkale
4a36244294 2019-01-08 12:39:21 +08:00
Redkale
cb444be0f7 优化Application.singleton方法 2019-01-08 12:32:47 +08:00
Redkale
8b5cbf186f 2019-01-08 09:13:05 +08:00
Redkale
dbc6f8a196 2019-01-07 21:38:44 +08:00
Redkale
9b94604166 2019-01-07 21:17:20 +08:00
Redkale
cc98a85711 2019-01-07 21:09:22 +08:00
Redkale
6855d06f55 JsonConvert增加不带Type参数的convertTo方法 2019-01-07 20:07:36 +08:00
Redkale
89d90ddf5b 修复getHttpContent会变成POST请求的bug 2019-01-07 17:05:02 +08:00
Redkale
6280111121 2019-01-05 09:42:03 +08:00
Redkale
231d41c15f DataSource增加清空表clear和删除表drop的系列方法 2019-01-04 14:26:20 +08:00
Redkale
cfca7adc66 2019-01-03 18:38:07 +08:00
Redkale
aedd215de4 2019-01-03 18:33:49 +08:00
Redkale
df8e839580 优化WebSocket给多个userid发消息的实现 2019-01-03 09:35:28 +08:00
Redkale
300441b9f7 DataSource增加getCollectionMap系列接口 2019-01-03 09:33:19 +08:00
Redkale
1a5e9022ae Convert支持java.time.Duration 2019-01-03 09:07:26 +08:00
Redkale
2a3b8f87d3 兼容@Resource标记在泛型类型字段上 2019-01-03 09:06:08 +08:00
Redkale
b7930f1ed7 Redkale 2.0.0 开始 2019-01-03 09:05:00 +08:00
Redkale
a78c2145e6 2018-12-24 17:16:39 +08:00
Redkale
ee20a34a70 2018-12-24 14:52:05 +08:00
Redkale
33bd80c572 2018-12-22 15:16:00 +08:00
Redkale
031309b105 2018-12-22 15:08:56 +08:00
Redkale
bcbd981a9b 2018-12-21 10:55:20 +08:00
Redkale
b7ce390c33 WebServlet.value带.不视为正则表达式 2018-12-21 10:38:37 +08:00
Redkale
c9d099c694 2018-12-20 17:22:16 +08:00
Redkale
fcca0329c6 2018-12-20 13:55:46 +08:00
Redkale
c82c0bc680 2018-12-20 11:51:12 +08:00
Redkale
2921478a0a 2018-12-20 11:38:11 +08:00
Redkale
61a5420d48 兼容泛型嵌套 2018-12-19 18:38:28 +08:00
Redkale
702ab6ef6e 2018-12-19 16:03:11 +08:00
Redkale
2576e71a7d 2018-12-19 11:33:08 +08:00
Redkale
0d0bd78213 2018-12-18 15:20:13 +08:00
Redkale
8d9fa8f9cf 2018-12-18 14:15:27 +08:00
Redkale
25eaf6e353 AsyncConnection接口大变动 2018-12-18 14:04:49 +08:00
Redkale
8afcaa0b34 2018-12-18 09:41:20 +08:00
Redkale
1824f8150c 2018-12-17 10:57:49 +08:00
Redkale
2f89778fd6 2018-12-17 10:56:00 +08:00
Redkale
f9d250b43c 2018-12-17 10:29:23 +08:00
Redkale
3a3c09d8aa 2018-12-15 15:07:46 +08:00
Redkale
09a0d4f9e2 2018-12-15 15:06:24 +08:00
Redkale
3bba781183 WATCH服务增加功能:更改Server的监听地址和端口 2018-12-13 13:47:44 +08:00
Redkale
6426f8fe91 2018-12-11 19:46:31 +08:00
Redkale
5906594148 2018-12-11 18:58:15 +08:00
Redkale
1b188c863c 2018-12-10 19:51:31 +08:00
Redkale
087b4cb571 2018-12-10 19:47:26 +08:00
Redkale
c9496b6231 application.xml中source节点兼容DataJdbcSource 2018-12-10 19:44:56 +08:00
Redkale
60d95d7628 2018-12-06 21:29:55 +08:00
Redkale
dd9e7e77b5 2018-12-06 21:06:21 +08:00
Redkale
50c9363876 2018-12-05 17:59:56 +08:00
Redkale
938e357745 2018-12-03 09:04:27 +08:00
Redkale
08ee51f8ab 2018-12-01 14:22:30 +08:00
Redkale
40ae555645 2018-11-29 14:09:18 +08:00
Redkale
33f89264a6 2018-11-29 13:54:14 +08:00
Redkale
e4ea20cc5f 2018-11-28 14:33:55 +08:00
Redkale
045b7db1af 修复JsonConvert的""空字符串转换对象抛异常的BUG 2018-11-28 14:23:10 +08:00
Redkale
676c1b5d21 修复JsonConvert的""空字符串转换对象抛异常的BUG 2018-11-28 14:22:00 +08:00
Redkale
e4319246b8 2018-11-28 14:04:07 +08:00
Redkale
32d8515bf4 DataSource增加部分JSON功能 2018-11-28 11:17:55 +08:00
Redkale
d7e7113201 Sncp的部分Attribute.type()改为genericType方法 2018-11-28 09:18:12 +08:00
Redkale
9493aa43a7 Attribute增加genericType方法 2018-11-28 09:12:58 +08:00
Redkale
d07c55b831 【不兼容】BSON格式升级,兼容子类数据转父类对象 2018-11-27 15:10:19 +08:00
Redkale
47dab88d72 调整Convert部分内部接口 2018-11-27 14:10:58 +08:00
Redkale
9e553aeff6 修复JsonReader.readSmallString() BUG 2018-11-27 11:48:50 +08:00
Redkale
ed8e754557 兼容ColumnValue...含null的情况 2018-11-24 14:20:06 +08:00
Redkale
651dc3df2a 还原 2018-11-22 14:47:58 +08:00
Redkale
84e5bc3437 2018-11-22 14:46:55 +08:00
Redkale
64fd0176ac 兼容手动new XXXService字段inject时抛异常 2018-11-22 14:45:24 +08:00
Redkale
c1f3115d4e 2018-11-20 10:55:09 +08:00
Redkale
1c70834760 2018-11-19 17:33:33 +08:00
Redkale
7c901731bc Bson的skipValue方法支持部分常规Collection<JavaBean>、Map<String, JavaBean>字段类型 2018-11-19 15:32:24 +08:00
Redkale
2b2d53e515 Bson的skipValue方法支持部分常规Collection、Map字段类型 2018-11-19 15:14:48 +08:00
Redkale
be051ecf45 Redkale 1.9.9 开始 2018-11-19 15:12:20 +08:00
Redkale
18534eb654 2018-11-08 16:08:48 +08:00
Redkale
a5a926fd94 FilterNode、FilterJoinNode增加copy方法 2018-10-18 14:47:07 +08:00
Redkale
0cb9f2cad3 2018-10-17 08:18:23 +08:00
Redkale
98209cc82e 修改WebSocketNode.existsWebSocket的实现 2018-10-10 14:03:54 +08:00
Redkale
1879afa6a4 2018-10-09 16:34:35 +08:00
Redkale
4a6404dfec 2018-09-27 09:54:42 +08:00
Redkale
0fa1c4a08f 修复WebSocket中Connection重复的bug 2018-09-27 09:51:44 +08:00
Redkale
573d7c5776 修复Rest.createRestWebSocketServlet空指针bug 2018-09-26 17:23:19 +08:00
Redkale
c56c9bf260 Redkale 1.9.8 开始 2018-09-26 17:21:33 +08:00
Redkale
387865789f 2018-09-20 16:03:33 +08:00
Redkale
03fcf43a89 2018-09-19 11:11:59 +08:00
Redkale
df8090813a 2018-09-12 12:11:19 +08:00
Redkale
849b29d00f CacheSource的增删改查操作增加Type参数 2018-09-12 12:04:59 +08:00
Redkale
4b7f65e1c4 2018-09-11 14:29:42 +08:00
Redkale
4545d81e50 2018-09-11 11:12:43 +08:00
Redkale
1ac5f060a4 增加WebSocketAction功能 2018-09-11 09:13:19 +08:00
Redkale
7e1ff8e315 2018-09-10 17:23:23 +08:00
Redkale
4e0c1fee97 2018-09-10 14:02:26 +08:00
Redkale
0b38f23f2d 2018-09-10 14:01:56 +08:00
Redkale
98ea6861c1 2018-09-10 10:44:03 +08:00
Redkale
c07b628ea1 FilterNode增加readonly属性 2018-09-07 10:21:48 +08:00
Redkale
b1b979c0b5 优化Rest.createRestServlet减少preInit的耗时 2018-09-07 09:20:52 +08:00
Redkale
35b708b01d 2018-09-07 08:50:20 +08:00
Redkale
229ae0d44f 2018-09-06 18:17:11 +08:00
Redkale
7d6897fa36 2018-09-06 14:33:53 +08:00
Redkale
5851093590 2018-09-05 16:58:19 +08:00
Redkale
4646c1d1f0 2018-09-05 16:57:09 +08:00
Redkale
f3763dbf72 2018-09-05 16:41:44 +08:00
Redkale
6a8c60ec78 优化NodeHttpServer.loadRestServlet 2018-09-05 16:15:21 +08:00
Redkale
ae437fd5d6 优化Rest.createRestServlet 2018-09-05 15:53:54 +08:00
Redkale
7251c984c8 修复FilterNode.findValue的bug 2018-09-05 11:00:47 +08:00
Redkale
ec449220eb 2018-09-05 09:49:20 +08:00
Redkale
78265944f0 2018-09-05 09:23:41 +08:00
Redkale
d2791f6d1b 2018-09-05 08:29:58 +08:00
Redkale
d525d2664b 2018-08-31 10:39:43 +08:00
Redkale
a4ccea91ad 修复FilterJoinNode.any方法bug 2018-08-29 16:06:41 +08:00
Redkale
750da161eb 增强HttpUserType的类型校验 2018-08-28 10:18:27 +08:00
Redkale
ac50312f0b 2018-08-27 18:28:56 +08:00
Redkale
8d44d48072 2018-08-27 18:26:16 +08:00
Redkale
6c2baa1708 增加RestConvertCoder功能 2018-08-27 18:25:08 +08:00
Redkale
4525cfe594 2018-08-27 12:36:35 +08:00
Redkale
921f96c975 优化toBuffers方法 2018-08-27 12:29:59 +08:00
Redkale
29ce57d3af BsonWriter.toBuffers存在并发问题 2018-08-27 12:07:45 +08:00
Redkale
2ca1e6305c 修改HttpResponse.finish(byte[]) 2018-08-27 11:55:36 +08:00
Redkale
827b404a57 Update application.xml 2018-08-25 13:35:48 +08:00
Redkale
83569142c1 2018-08-25 13:12:24 +08:00
Redkale
2da0faacc3 2018-08-24 16:24:58 +08:00
Redkale
cf51bee2cc 2018-08-24 16:07:19 +08:00
Redkale
0dd55dc947 2018-08-24 16:04:49 +08:00
Redkale
620fa0430c ClassFilter输出更详细日志 2018-08-23 19:54:47 +08:00
Redkale
d053590257 增加JDK9+环境下显示进程PID功能 2018-08-23 19:28:20 +08:00
Redkale
684af3de61 application.xml的properties值支持${APP_HOME} 2018-08-23 09:59:14 +08:00
Redkale
6c6e26ed0b 2018-08-22 10:37:49 +08:00
Redkale
4a05bfbd08 2018-08-22 10:34:48 +08:00
Redkale
787dc7b32f 2018-08-22 10:03:20 +08:00
Redkale
85a1f99f6e 2018-08-22 09:42:51 +08:00
Redkale
4fe8a1199e 修复CollectionDecoder的creator指定错误的bug 2018-08-22 09:30:11 +08:00
Redkale
7312dbc4c5 增加H2数据库的支持 2018-08-21 10:06:05 +08:00
Redkale
cfecfabc92 createRestServlet兼容throws IOException和RuntimeException的子类 2018-08-20 17:28:34 +08:00
Redkale
587160c5fe Redkale 1.9.7 开始 2018-08-20 17:23:13 +08:00
Redkale
ee7fe3ed33 2018-08-20 16:49:39 +08:00
Redkale
47d4a6cc29 2018-08-20 14:42:16 +08:00
Redkale
c1e4763369 2018-08-20 14:28:02 +08:00
Redkale
333ba0f162 2018-08-18 11:27:50 +08:00
Redkale
e039b0e9f6 2018-08-17 11:26:45 +08:00
Redkale
b3c5e3beca 2018-08-15 18:18:27 +08:00
Redkale
70ba45c3bd 2018-08-15 18:13:09 +08:00
Redkale
14ae44fcac 修复DataJdbcSource.queryList会查total的BUG 2018-08-15 16:57:44 +08:00
Redkale
f7618f5da4 DataSqlSource.directQuery接口变动 2018-08-15 14:49:20 +08:00
Redkale
d6c6e4c02e 2018-08-14 10:40:11 +08:00
Redkale
9365052b85 2018-08-13 19:20:21 +08:00
Redkale
ef88063094 修复EntityCache重复insert数据时会导致map和list的同一id的对象不一致的BUG 2018-08-13 19:12:05 +08:00
Redkale
4cbaf85eea 2018-08-13 18:30:07 +08:00
Redkale
6c07123da3 2018-08-13 18:29:12 +08:00
Redkale
04a4ce12c7 2018-08-09 19:32:03 +08:00
Redkale
e00ed8ae37 增加DataMemorySource 2018-08-08 14:30:51 +08:00
Redkale
218a79b60a 2018-08-07 15:41:22 +08:00
Redkale
19ae86c71f 2018-08-07 13:52:00 +08:00
Redkale
9250d4e64d 2018-08-07 11:53:26 +08:00
Redkale
9f5aa58a31 2018-08-06 19:58:19 +08:00
Redkale
c8b0a88573 2018-08-06 18:05:13 +08:00
Redkale
7cf3f49aa1 1.9.5.1 2018-08-06 17:39:17 +08:00
Redkale
be2c803f82 2018-08-06 17:38:03 +08:00
Redkale
fd1197e8dc 2018-08-04 23:40:52 +08:00
Redkale
115f91b64a 2018-08-04 18:31:29 +08:00
Redkale
dfb800473a 2018-08-04 18:08:11 +08:00
Redkale
c69c1bb134 ppl 2018-08-04 15:12:22 +08:00
Redkale
5b501c7c2f 2018-08-04 14:52:44 +08:00
Redkale
8d5ce56ec2 FileHandler.limit支持G/M/K 2018-08-03 22:23:56 +08:00
Redkale
15c97ddc18 2018-08-02 13:51:41 +08:00
Redkale
36d7fbf4e9 2018-07-31 15:47:18 +08:00
Redkale
919e7aa5c6 2018-07-30 16:02:26 +08:00
Redkale
2174de2b71 2018-07-30 16:01:39 +08:00
Redkale
cb9e914e44 2018-07-30 15:51:20 +08:00
Redkale
15f856b762 2018-07-30 15:26:47 +08:00
Redkale
991dba0d62 2018-07-27 21:29:50 +08:00
Redkale
aa2685d6e4 修复WebSocketEngine的future = future.whenComplete问题 2018-07-27 20:35:48 +08:00
Redkale
0952150328 2018-07-27 20:29:13 +08:00
Redkale
e6ef4d1546 2018-07-27 20:02:08 +08:00
Redkale
16cf85abb9 2018-07-27 19:59:58 +08:00
Redkale
5afe0ead94 修复WebSocketNode远程模式下forceCloseWebSocket会报错的BUG 2018-07-27 19:52:12 +08:00
Redkale
b6c933f989 WebSocketNode远程模式下forceCloseWebSocket会报错 2018-07-27 19:38:46 +08:00
Redkale
feaf1a1f06 Redkale 1.9.6 开始 2018-07-27 19:19:00 +08:00
Redkale
6b54c6e886 2018-07-26 16:16:09 +08:00
Redkale
a95b69ab79 2018-07-26 11:54:09 +08:00
Redkale
a2492ae248 2018-07-26 11:36:51 +08:00
Redkale
0db1c4413c 2018-07-26 10:53:35 +08:00
Redkale
8718bca6e8 2018-07-26 08:48:23 +08:00
Redkale
6486863d00 2018-07-25 16:36:09 +08:00
Redkale
bfc2397dbf 2018-07-25 14:58:02 +08:00
Redkale
0cfdb9795b 2018-07-25 12:06:11 +08:00
Redkale
d327757d59 2018-07-25 11:43:51 +08:00
Redkale
e88c4fa2e3 修复进程关闭时WebSocket没有执行onClose方法的BUG 2018-07-24 20:11:02 +08:00
Redkale
69a0071e17 2018-07-23 10:06:36 +08:00
Redkale
d3cfe809e7 2018-07-23 09:38:47 +08:00
Redkale
0ca6e5401a 2018-07-23 09:37:49 +08:00
Redkale
8ff2b60ed4 2018-07-22 18:37:07 +08:00
Redkale
1dbe125e27 2018-07-22 18:15:24 +08:00
Redkale
32a595262d 2018-07-22 18:03:30 +08:00
Redkale
01431a93a4 2018-07-22 17:55:02 +08:00
Redkale
00a12d8113 2018-07-21 14:21:50 +08:00
Redkale
0f2474386c 2018-07-21 10:58:17 +08:00
Redkale
5de52ed6e8 Convert优化 2018-07-21 10:50:01 +08:00
Redkale
099b3fb7f3 2018-07-20 15:00:18 +08:00
Redkale
ed85e33403 2018-07-20 11:38:53 +08:00
Redkale
daff7d095f 2018-07-20 10:58:51 +08:00
Redkale
a8ff82229f 2018-07-20 10:01:59 +08:00
Redkale
2874e7d195 2018-07-20 09:48:47 +08:00
Redkale
8baea2657d 2018-07-20 09:04:05 +08:00
Redkale
03e9a5cbcb 更新Convert的Array、Map相关接口 2018-07-19 10:26:40 +08:00
Redkale
8d2f2a28af 2018-07-18 16:14:09 +08:00
Redkale
4a4bade180 Decoder/Encoder获取更多信息 2018-07-16 19:16:10 +08:00
Redkale
28e72f9883 Convert增加readByteArray和writeByteArray方法 2018-07-16 18:38:02 +08:00
Redkale
681e3967d2 2018-07-16 14:02:30 +08:00
Redkale
640dcbc8d7 2018-07-16 12:40:32 +08:00
Redkale
19276ecb91 2018-07-16 00:36:45 +08:00
Redkale
9f9078cdc5 2018-07-16 00:33:45 +08:00
Redkale
9bd1e0c97b 2018-07-15 23:42:28 +08:00
Redkale
c2c8f700a2 2018-07-15 22:18:52 +08:00
Redkale
86895eb5ef 2018-07-15 20:10:09 +08:00
Redkale
e8dacd6b70 2018-07-15 18:11:30 +08:00
Redkale
03fcf1dc95 2018-07-15 17:43:58 +08:00
Redkale
953b2be224 2018-07-14 12:54:48 +08:00
Redkale
55645ba2a0 2018-07-14 09:22:42 +08:00
Redkale
858c6a0aaf 2018-07-14 00:14:10 +08:00
Redkale
85d4023fa2 2018-07-13 23:22:02 +08:00
Redkale
607fc8e45f 2018-07-13 23:13:42 +08:00
Redkale
511a966ce5 2018-07-13 23:11:36 +08:00
Redkale
6d135efbc6 2018-07-13 22:56:33 +08:00
Redkale
5dff6310aa 2018-07-13 11:52:28 +08:00
Redkale
194a06c748 2018-07-13 09:41:26 +08:00
Redkale
1ce97aa20d 2018-07-13 06:46:55 +08:00
Redkale
1c88fb0355 修复JsonConvert没有按指定Type进行convertTo的BUG 2018-07-12 17:45:41 +08:00
Redkale
7b81c42377 JsonConvert支持带空格的数值字符串转成Number对象 2018-07-12 14:19:40 +08:00
Redkale
1afa38a947 2018-07-11 16:58:03 +08:00
Redkale
eedb418299 增加RpcRemoteException 2018-07-11 16:15:24 +08:00
Redkale
9efc14e627 2018-07-10 15:36:23 +08:00
Redkale
0dc3d65307 去掉对Rest中find、delete开头方法的特殊处理 2018-07-10 15:25:40 +08:00
Redkale
e3ddbe609c 2018-07-09 11:10:15 +08:00
Redkale
f115934499 2018-07-08 14:49:48 +08:00
Redkale
f5e290a47a Watch组件增加可以获取指定Servie中某个可序列化的字段的值 2018-07-06 22:28:20 +08:00
Redkale
29cd395888 RestConvert增加可以返回skipAllIgnore(true)的Convert功能 2018-07-06 18:53:39 +08:00
Redkale
9ca7855756 2018-07-05 11:47:58 +08:00
Redkale
1f1ab112eb 2018-07-05 11:36:30 +08:00
Redkale
b172b66263 去掉persistence.xml的监听文件变化功能,该有watch组件提供动态修改数据源配置 2018-07-05 09:49:19 +08:00
Redkale
b08f9f5757 增加java.util.Properties的convert 2018-07-05 09:47:39 +08:00
Redkale
32e65ff304 2018-07-03 15:49:32 +08:00
Redkale
40126c923e 2018-07-03 15:09:40 +08:00
Redkale
83ae5b0a13 2018-07-03 15:05:54 +08:00
Redkale
aea6a2839d 增加LogExcludeLevel功能 2018-07-03 10:10:52 +08:00
Redkale
6211d9ff18 Redkale 1.9.5 开始 2018-07-03 09:28:17 +08:00
Redkale
0e7fab71b8 2018-06-28 09:01:33 +08:00
Redkale
a106c8ed60 2018-06-26 16:35:12 +08:00
Redkale
ae52d0ab3d 2018-06-26 16:30:47 +08:00
Redkale
c993cd5b5a Json.writeChar以'A'形式输出 2018-06-25 19:38:32 +08:00
Redkale
9bdd83cc6e 2018-06-25 18:46:53 +08:00
Redkale
1b6a23c1a9 增加APP_CONF配置项,在启动脚本中可以指定配置目录 2018-06-22 16:38:24 +08:00
Redkale
2703d94b83 修复Convert中泛型与非泛型类型并存的问题 2018-06-20 15:58:10 +08:00
Redkale
4cb51ecbe6 2018-06-20 15:48:08 +08:00
Redkale
0cf64121ae 2018-06-12 16:52:09 +08:00
Redkale
58eb3c5d64 AsyncConnection.write调整 2018-06-12 09:15:32 +08:00
Redkale
3c645b4c7f 修复Rest部分情况下获取不到参数的BUG 2018-06-09 10:15:49 +08:00
Redkale
a540eed0ed Redkale 1.9.4 开始 2018-06-09 09:48:50 +08:00
192 changed files with 9299 additions and 6103 deletions

View File

@@ -19,8 +19,6 @@
</p> </p>
&nbsp;&nbsp;&nbsp;编译RedKale 1.8.x版本需要在源码工程中的编译器选项中加入 <b>-XDignore.symbol.file=true</b>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h5>详情请访问:&nbsp;&nbsp;&nbsp;&nbsp;<a href='https://redkale.org' target='_blank'>https://redkale.org</a></h5> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h5>详情请访问:&nbsp;&nbsp;&nbsp;&nbsp;<a href='https://redkale.org' target='_blank'>https://redkale.org</a></h5>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h5>基本文档:&nbsp;&nbsp;&nbsp;&nbsp;<a href='https://redkale.org/articles.html' target='_blank'>https://redkale.org/articles.html</a></h5> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h5>基本文档:&nbsp;&nbsp;&nbsp;&nbsp;<a href='https://redkale.org/articles.html' target='_blank'>https://redkale.org/articles.html</a></h5>

View File

@@ -14,7 +14,7 @@ fi
cd "$APP_HOME" cd "$APP_HOME"
./bin/shutdown.sh "$APP_HOME"/bin/shutdown.sh
./bin/start.sh "$APP_HOME"/bin/start.sh

View File

@@ -1,7 +1,7 @@
@ECHO OFF @ECHO OFF
SET APP_HOME=%~dp0 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 -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application java -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application

View File

@@ -24,5 +24,5 @@ done
export CLASSPATH=$CLASSPATH:$lib export CLASSPATH=$CLASSPATH:$lib
echo "$APP_HOME" echo "$APP_HOME"
nohup java -DAPP_HOME="$APP_HOME" org.redkale.boot.Application > "$APP_HOME"/log.out & nohup java -DAPP_HOME="$APP_HOME" org.redkale.boot.Application > "$APP_HOME"/logs.out &

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<application port="5050"> <application port="2121">
<!-- 详细配置说明见: http://redkale.org/redkale.html#redkale_confxml --> <!-- 详细配置说明见: http://redkale.org/redkale.html#redkale_confxml -->
@@ -8,14 +8,14 @@
</resources> </resources>
<server protocol="HTTP" host="0.0.0.0" port="6060" root="root"> <server protocol="HTTP" port="6060">
<request> <request>
<remoteaddr value="request.headers.X-RemoteAddress"/> <remoteaddr value="request.headers.X-RemoteAddress"/>
</request> </request>
<response> <response>
<defcookie domain="" path=""/> <defcookie domain="" path="/"/>
<addheader name="Access-Control-Allow-Origin" value="request.headers.Origin" /> <addheader name="Access-Control-Allow-Origin" value="request.headers.Origin" />
<setheader name="Access-Control-Allow-Credentials" value="true"/> <setheader name="Access-Control-Allow-Credentials" value="true"/>
</response> </response>

View File

@@ -1,9 +1,10 @@
handlers = java.util.logging.ConsoleHandler handlers = java.util.logging.ConsoleHandler
# handlers = java.util.logging.FileHandler
############################################################ ############################################################
.level = FINER .level = FINEST
java.level = INFO java.level = INFO
javax.level = INFO javax.level = INFO
@@ -14,11 +15,11 @@ jdk.level = INFO
java.util.logging.FileHandler.level = FINER java.util.logging.FileHandler.level = FINER
#10M #10M
java.util.logging.FileHandler.limit = 10485760 java.util.logging.FileHandler.limit = 10M
java.util.logging.FileHandler.count = 10000 java.util.logging.FileHandler.count = 20
java.util.logging.FileHandler.encoding = UTF-8 java.util.logging.FileHandler.encoding = UTF-8
java.util.logging.FileHandler.pattern = ${APP_HOME}/logs-%m/log-%d.log java.util.logging.FileHandler.pattern = ${APP_HOME}/logs-%m/log-%d.log
java.util.logging.FileHandler.unusual = ${APP_HOME}/logs-%m/log-warnerr-%d.log java.util.logging.FileHandler.unusual = ${APP_HOME}/logs-%m/log-warnerr-%d.log
java.util.logging.FileHandler.append = true java.util.logging.FileHandler.append = true
java.util.logging.ConsoleHandler.level = FINER java.util.logging.ConsoleHandler.level = FINEST

View File

@@ -16,7 +16,6 @@
<shared-cache-mode>ALL</shared-cache-mode> <shared-cache-mode>ALL</shared-cache-mode>
<properties> <properties>
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:orcl"/> <property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="javax.persistence.jdbc.user" value="system"/> <property name="javax.persistence.jdbc.user" value="system"/>
<property name="javax.persistence.jdbc.password" value="1234"/> <property name="javax.persistence.jdbc.password" value="1234"/>
</properties> </properties>
@@ -25,8 +24,7 @@
<persistence-unit name="user.write" transaction-type="RESOURCE_LOCAL"> <persistence-unit name="user.write" transaction-type="RESOURCE_LOCAL">
<shared-cache-mode>ALL</shared-cache-mode> <shared-cache-mode>ALL</shared-cache-mode>
<properties> <properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/user?autoReconnect=true&amp;characterEncoding=utf8"/> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/center?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.user" value="root"/> <property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="1234"/> <property name="javax.persistence.jdbc.password" value="1234"/>
</properties> </properties>

View File

@@ -63,10 +63,10 @@
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version> <version>3.5.1</version>
<configuration> <configuration>
<compilerArgument>-parameters</compilerArgument>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<compilerArguments> <compilerArguments>
<verbose /> <verbose />
<bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
</compilerArguments> </compilerArguments>
</configuration> </configuration>
</plugin> </plugin>
@@ -113,7 +113,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version> <version>3.0.0</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>

View File

@@ -119,13 +119,13 @@
threads 线程数, 默认: CPU核数*32 threads 线程数, 默认: CPU核数*32
maxconns最大连接数, 小于1表示无限制 默认: 0 maxconns最大连接数, 小于1表示无限制 默认: 0
maxbody: request.body最大值 默认: 64K maxbody: request.body最大值 默认: 64K
bufferCapacity: ByteBuffer的初始化大小 默认: 32K; (HTTP 2.0、WebSocket必须要16k以上) bufferCapacity: ByteBuffer的初始化大小 TCP默认: 32K; (HTTP 2.0、WebSocket必须要16k以上); UDP默认: 1350B
bufferPoolSize ByteBuffer池的大小默认: 线程数*4 bufferPoolSize ByteBuffer池的大小默认: 线程数*4
responsePoolSize Response池的大小默认: 线程数*2 responsePoolSize Response池的大小默认: 线程数*2
aliveTimeoutSeconds: KeepAlive读操作超时秒数 默认30 0表示永久不超时; -1表示禁止KeepAlive aliveTimeoutSeconds: KeepAlive读操作超时秒数 默认30 0表示永久不超时; -1表示禁止KeepAlive
readTimeoutSeconds: 读操作超时秒数, 默认0 表示永久不超时 readTimeoutSeconds: 读操作超时秒数, 默认0 表示永久不超时
writeTimeoutSeconds: 写操作超时秒数, 默认0 表示永久不超时 writeTimeoutSeconds: 写操作超时秒数, 默认0 表示永久不超时
netimpl: ProtocolServer的实现类。TCP情况下值可以是aio或nio默认值为aioUDP情况下值可以是bio默认值为bio netimpl: ProtocolServer的实现类。TCP情况下值可以是aio或nio默认值为aioUDP情况下值可以是bio默认值为bio
interceptor: 启动/关闭NodeServer时被调用的拦截器实现类必须是org.redkale.boot.NodeInterceptor的子类默认为null interceptor: 启动/关闭NodeServer时被调用的拦截器实现类必须是org.redkale.boot.NodeInterceptor的子类默认为null
--> -->
<server protocol="HTTP" host="127.0.0.1" port="6060" root="root" lib=""> <server protocol="HTTP" host="127.0.0.1" port="6060" root="root" lib="">

View File

@@ -11,8 +11,8 @@ javax.level = INFO
com.sun.level = INFO com.sun.level = INFO
#java.util.logging.FileHandler.level = FINE #java.util.logging.FileHandler.level = FINE
#10M
java.util.logging.FileHandler.limit = 10485760 java.util.logging.FileHandler.limit = 20M
java.util.logging.FileHandler.count = 100 java.util.logging.FileHandler.count = 100
java.util.logging.FileHandler.encoding = UTF-8 java.util.logging.FileHandler.encoding = UTF-8
java.util.logging.FileHandler.pattern = ${APP_HOME}/logs-%m/log-%d.log java.util.logging.FileHandler.pattern = ${APP_HOME}/logs-%m/log-%d.log

View File

@@ -9,7 +9,7 @@
--> -->
<property name="javax.persistence.datasource" value="org.redkale.source.DataJdbcSource"/> <property name="javax.persistence.datasource" value="org.redkale.source.DataJdbcSource"/>
<!-- <!--
是否开启缓存(标记为@Cacheable的Entity类),值目前只支持两种: ALL: 所有开启缓存。 NONE: 关闭所有缓存 是否开启缓存(标记为@Cacheable的Entity类),值目前只支持两种: ALL: 所有开启缓存。 NONE: 关闭所有缓存 非NONE字样统一视为ALL
--> -->
<property name="javax.persistence.cachemode" value="ALL"/> <property name="javax.persistence.cachemode" value="ALL"/>
@@ -20,12 +20,15 @@
org.mariadb.jdbc.Driver —————— org.mariadb.jdbc.MySQLDataSource org.mariadb.jdbc.Driver —————— org.mariadb.jdbc.MySQLDataSource
org.postgresql.Driver —————— org.postgresql.ds.PGConnectionPoolDataSource org.postgresql.Driver —————— org.postgresql.ds.PGConnectionPoolDataSource
com.mysql.jdbc.Driver —————— com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource com.mysql.jdbc.Driver —————— com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
com.mysql.cj.jdbc.Driver —————— com.mysql.cj.jdbc.MysqlConnectionPoolDataSource
oracle.jdbc.driver.OracleDriver —————— oracle.jdbc.pool.OracleConnectionPoolDataSource oracle.jdbc.driver.OracleDriver —————— oracle.jdbc.pool.OracleConnectionPoolDataSource
com.microsoft.sqlserver.jdbc.SQLServerDriver —————— com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource com.microsoft.sqlserver.jdbc.SQLServerDriver —————— com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource
org.h2.Driver —————— org.h2.jdbcx.JdbcDataSource
因此 com.mysql.jdbc.Driver 会被自动转换成 com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource 因此 com.mysql.jdbc.Driver 会被自动转换成 com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
并且如果JDBC驱动是以上几个版本javax.persistence.jdbc.driver属性都可以省略Redkale会根据javax.persistence.jdbc.url的值来识别驱动 并且如果JDBC驱动是以上几个版本javax.persistence.jdbc.driver属性都可以省略Redkale会根据javax.persistence.jdbc.url的值来识别驱动
-->
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.source" value="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource"/>
-->
<property name="javax.persistence.jdbc.user" value="root"/> <property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="123456"/> <property name="javax.persistence.jdbc.password" value="123456"/>
@@ -47,7 +50,6 @@
<properties> <properties>
<!-- jdbc:mysql://127.0.0.1:3306/dbim?autoReconnect=true&amp;autoReconnectForPools=true&amp;characterEncoding=utf8 --> <!-- 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.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.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="123456"/> <property name="javax.persistence.jdbc.password" value="123456"/>
</properties> </properties>

View File

@@ -1,63 +0,0 @@
/** *****************************************************************************
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Linda DeMichiel - Java Persistence 2.1
* Linda DeMichiel - Java Persistence 2.0
*
***************************************************************************** */
package javax.persistence;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Provides for the specification of generation strategies for the
* values of primary keys.
*
* <p>
* The <code>GeneratedValue</code> annotation
* may be applied to a primary key property or field of an entity or
* mapped superclass in conjunction with the {@link Id} annotation.
* The use of the <code>GeneratedValue</code> annotation is only
* required to be supported for simple primary keys. Use of the
* <code>GeneratedValue</code> annotation is not supported for derived
* primary keys.
*
* <pre>
*
* Example 1:
*
* &#064;Id
* &#064;GeneratedValue(strategy=SEQUENCE, generator="CUST_SEQ")
* &#064;Column(name="CUST_ID")
* public Long getId() { return id; }
*
* Example 2:
*
* &#064;Id
* &#064;GeneratedValue(strategy=TABLE, generator="CUST_GEN")
* &#064;Column(name="CUST_ID")
* Long id;
* </pre>
*
* @see Id
*
* @since Java Persistence 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface GeneratedValue {
}

View File

@@ -45,7 +45,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* </pre> * </pre>
* *
* @see Column * @see Column
* @see GeneratedValue * see GeneratedValue
* *
* @since Java Persistence 1.0 * @since Java Persistence 1.0
*/ */

View File

@@ -10,7 +10,6 @@ module org.redkale {
requires java.logging; requires java.logging;
requires java.xml; requires java.xml;
requires java.sql; requires java.sql;
requires java.sql.rowset;
requires jdk.unsupported; //sun.misc.Unsafe requires jdk.unsupported; //sun.misc.Unsafe

View File

@@ -89,6 +89,8 @@ public final class ApiDocsService {
for (final Class rtype : action.results()) { for (final Class rtype : action.results()) {
results.add(rtype.getName()); results.add(rtype.getName());
if (typesmap.containsKey(rtype.getName())) continue; if (typesmap.containsKey(rtype.getName())) continue;
if(rtype.getName().startsWith("java.")) continue;
if(rtype.getName().startsWith("javax.")) continue;
final boolean filter = FilterBean.class.isAssignableFrom(rtype); final boolean filter = FilterBean.class.isAssignableFrom(rtype);
final Map<String, Map<String, Object>> typemap = new LinkedHashMap<>(); final Map<String, Map<String, Object>> typemap = new LinkedHashMap<>();
Class loop = rtype; Class loop = rtype;
@@ -136,6 +138,8 @@ public final class ApiDocsService {
paramsList.add(parammap); paramsList.add(parammap);
if (ptype.isPrimitive() || ptype == String.class) continue; if (ptype.isPrimitive() || ptype == String.class) continue;
if (typesmap.containsKey(ptype.getName())) continue; if (typesmap.containsKey(ptype.getName())) continue;
if(ptype.getName().startsWith("java.")) continue;
if(ptype.getName().startsWith("javax.")) continue;
final Map<String, Map<String, Object>> typemap = new LinkedHashMap<>(); final Map<String, Map<String, Object>> typemap = new LinkedHashMap<>();
Class loop = ptype; Class loop = ptype;
@@ -192,7 +196,7 @@ public final class ApiDocsService {
final FileOutputStream out = new FileOutputStream(new File(app.getHome(), "apidoc.json")); final FileOutputStream out = new FileOutputStream(new File(app.getHome(), "apidoc.json"));
out.write(json.getBytes("UTF-8")); out.write(json.getBytes("UTF-8"));
out.close(); out.close();
File doctemplate = new File(app.getHome(), "conf/apidoc-template.html"); File doctemplate = new File(app.getConfPath(), "apidoc-template.html");
InputStream in = null; InputStream in = null;
if (doctemplate.isFile() && doctemplate.canRead()) { if (doctemplate.isFile() && doctemplate.canRead()) {
in = new FileInputStream(doctemplate); in = new FileInputStream(doctemplate);

View File

@@ -61,6 +61,11 @@ public final class Application {
*/ */
public static final String RESNAME_APP_HOME = "APP_HOME"; public static final String RESNAME_APP_HOME = "APP_HOME";
/**
* 当前进程的配置目录如果不是绝对路径则视为HOME目录下的相对路径 类型String、File、Path
*/
public static final String RESNAME_APP_CONF = "APP_CONF";
/** /**
* application.xml 文件中resources节点的内容 类型: AnyValue * application.xml 文件中resources节点的内容 类型: AnyValue
*/ */
@@ -130,13 +135,16 @@ public final class Application {
//-------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------
//是否用于main方法运行 //是否用于main方法运行
private final boolean singletonrun; final boolean singletonrun;
//根WatchFactory //根WatchFactory
//private final WatchFactory watchFactory = WatchFactory.root(); //private final WatchFactory watchFactory = WatchFactory.root();
//进程根目录 //进程根目录
private final File home; private final File home;
//配置文件目录
private final File confPath;
//日志 //日志
private final Logger logger; private final Logger logger;
@@ -162,6 +170,7 @@ public final class Application {
private Application(final boolean singletonrun, final AnyValue config) { private Application(final boolean singletonrun, final AnyValue config) {
this.singletonrun = singletonrun; this.singletonrun = singletonrun;
this.config = config; this.config = config;
System.setProperty("redkale.version", Redkale.getDotedVersion());
final File root = new File(System.getProperty(RESNAME_APP_HOME)); final File root = new File(System.getProperty(RESNAME_APP_HOME));
this.resourceFactory.register(RESNAME_APP_TIME, long.class, this.startTime); this.resourceFactory.register(RESNAME_APP_TIME, long.class, this.startTime);
@@ -170,6 +179,12 @@ public final class Application {
try { try {
this.resourceFactory.register(RESNAME_APP_HOME, root.getCanonicalPath()); this.resourceFactory.register(RESNAME_APP_HOME, root.getCanonicalPath());
this.home = root.getCanonicalFile(); this.home = root.getCanonicalFile();
String confsubpath = System.getProperty(RESNAME_APP_CONF, "conf");
if (confsubpath.charAt(0) == '/' || confsubpath.indexOf(':') > 0) {
this.confPath = new File(confsubpath).getCanonicalFile();
} else {
this.confPath = new File(this.home, confsubpath).getCanonicalFile();
}
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -194,7 +209,7 @@ public final class Application {
System.setProperty(RESNAME_APP_NODE, node); System.setProperty(RESNAME_APP_NODE, node);
} }
//以下是初始化日志配置 //以下是初始化日志配置
final File logconf = new File(root, "conf/logging.properties"); final File logconf = new File(confPath, "logging.properties");
if (logconf.isFile() && logconf.canRead()) { if (logconf.isFile() && logconf.canRead()) {
try { try {
final String rootpath = root.getCanonicalPath().replace('\\', '/'); final String rootpath = root.getCanonicalPath().replace('\\', '/');
@@ -348,10 +363,22 @@ public final class Application {
return new ArrayList<>(servers); return new ArrayList<>(servers);
} }
public List<DataSource> getDataSources() {
return new ArrayList<>(dataSources);
}
public List<CacheSource> getCacheSources() {
return new ArrayList<>(cacheSources);
}
public File getHome() { public File getHome() {
return home; return home;
} }
public File getConfPath() {
return confPath;
}
public long getStartTime() { public long getStartTime() {
return startTime; return startTime;
} }
@@ -361,8 +388,6 @@ public final class Application {
} }
public void init() throws Exception { public void init() throws Exception {
System.setProperty("sun.nio.ch.internalThreadPoolSize", "" + Runtime.getRuntime().availableProcessors() * 4);
System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "" + Runtime.getRuntime().availableProcessors() * 4);
System.setProperty("net.transport.poolmaxconns", "100"); System.setProperty("net.transport.poolmaxconns", "100");
System.setProperty("net.transport.pinginterval", "30"); System.setProperty("net.transport.pinginterval", "30");
System.setProperty("net.transport.checkinterval", "30"); System.setProperty("net.transport.checkinterval", "30");
@@ -373,12 +398,21 @@ public final class Application {
System.setProperty("convert.bson.writer.buffer.defsize", "4096"); System.setProperty("convert.bson.writer.buffer.defsize", "4096");
System.setProperty("convert.json.writer.buffer.defsize", "4096"); System.setProperty("convert.json.writer.buffer.defsize", "4096");
File persist = new File(this.home, "conf/persistence.xml"); File persist = new File(this.confPath, "persistence.xml");
final String homepath = this.home.getCanonicalPath(); final String homepath = this.home.getCanonicalPath();
final String confpath = this.confPath.getCanonicalPath();
if (persist.isFile()) System.setProperty(DataSources.DATASOURCE_CONFPATH, persist.getCanonicalPath()); if (persist.isFile()) System.setProperty(DataSources.DATASOURCE_CONFPATH, persist.getCanonicalPath());
logger.log(Level.INFO, "APP_JAVA = " + System.getProperty("java.version") + "\r\n" + RESNAME_APP_ADDR + " = " + this.localAddress.getHostAddress() + "\r\n" + RESNAME_APP_HOME + " = " + homepath); String pidstr = "";
try { //JDK 9+
Class phclass = Class.forName("java.lang.ProcessHandle");
Object phobj = phclass.getMethod("current").invoke(null);
Object pid = phclass.getMethod("pid").invoke(phobj);
pidstr = "APP_PID = " + pid + "\r\n";
} catch (Throwable t) {
}
logger.log(Level.INFO, pidstr + "APP_JAVA = " + System.getProperty("java.version") + "\r\n" + RESNAME_APP_ADDR + " = " + this.localAddress.getHostAddress() + "\r\n" + RESNAME_APP_HOME + " = " + homepath + "\r\n" + RESNAME_APP_CONF + " = " + confpath);
String lib = config.getValue("lib", "${APP_HOME}/libs/*").trim().replace("${APP_HOME}", homepath); String lib = config.getValue("lib", "${APP_HOME}/libs/*").trim().replace("${APP_HOME}", homepath);
lib = lib.isEmpty() ? (homepath + "/conf") : (lib + ";" + homepath + "/conf"); lib = lib.isEmpty() ? confpath : (lib + ";" + confpath);
Server.loadLib(classLoader, logger, lib); Server.loadLib(classLoader, logger, lib);
//------------------------------------------------------------------------ //------------------------------------------------------------------------
@@ -391,13 +425,13 @@ public final class Application {
if (dfloads != null) { if (dfloads != null) {
for (String dfload : dfloads.split(";")) { for (String dfload : dfloads.split(";")) {
if (dfload.trim().isEmpty()) continue; if (dfload.trim().isEmpty()) continue;
final File df = (dfload.indexOf('/') < 0) ? new File(home, "conf/" + dfload) : new File(dfload); final File df = (dfload.indexOf('/') < 0) ? new File(confPath, "/" + dfload) : new File(dfload);
if (df.isFile()) { if (df.isFile()) {
Properties ps = new Properties(); Properties ps = new Properties();
InputStream in = new FileInputStream(df); InputStream in = new FileInputStream(df);
ps.load(in); ps.load(in);
in.close(); in.close();
ps.forEach((x, y) -> resourceFactory.register("property." + x, y)); ps.forEach((x, y) -> resourceFactory.register("property." + x, y.toString().replace("${APP_HOME}", homepath)));
} }
} }
} }
@@ -405,6 +439,7 @@ public final class Application {
String name = prop.getValue("name"); String name = prop.getValue("name");
String value = prop.getValue("value"); String value = prop.getValue("value");
if (name == null || value == null) continue; if (name == null || value == null) continue;
value = value.replace("${APP_HOME}", homepath);
if (name.startsWith("system.property.")) { if (name.startsWith("system.property.")) {
System.setProperty(name.substring("system.property.".length()), value); System.setProperty(name.substring("system.property.".length()), value);
} else if (name.startsWith("mimetype.property.")) { } else if (name.startsWith("mimetype.property.")) {
@@ -432,7 +467,7 @@ public final class Application {
try { try {
Resource res = field.getAnnotation(Resource.class); Resource res = field.getAnnotation(Resource.class);
if (res == null) return; if (res == null) return;
if (Sncp.isRemote((Service) src)) return; //远程模式不得注入 if (src instanceof Service && Sncp.isRemote((Service) src)) return; //远程模式不得注入
Class type = field.getType(); Class type = field.getType();
if (type == Application.class) { if (type == Application.class) {
field.set(src, application); field.set(src, application);
@@ -524,8 +559,8 @@ public final class Application {
public void restoreConfig() throws IOException { public void restoreConfig() throws IOException {
synchronized (this) { synchronized (this) {
File confFile = new File(this.home, "conf/application.xml"); File confFile = new File(this.confPath, "application.xml");
confFile.renameTo(new File(this.home, "conf/application_" + String.format("%1$tY%1$tm%1$td%1$tH%1$tM%1$tS", System.currentTimeMillis()) + ".xml")); confFile.renameTo(new File(this.confPath, "application_" + String.format("%1$tY%1$tm%1$td%1$tH%1$tM%1$tS", System.currentTimeMillis()) + ".xml"));
final PrintStream ps = new PrintStream(new FileOutputStream(confFile)); final PrintStream ps = new PrintStream(new FileOutputStream(confFile));
ps.append(config.toXML("application")); ps.append(config.toXML("application"));
ps.close(); ps.close();
@@ -653,19 +688,21 @@ public final class Application {
runServers(timecd, watchs); //必须在所有服务都启动后再启动WATCH服务 runServers(timecd, watchs); //必须在所有服务都启动后再启动WATCH服务
timecd.await(); timecd.await();
//if (!singletonrun) signalHandle(); //if (!singletonrun) signalHandle();
if (!singletonrun) clearPersistData(); //if (!singletonrun) clearPersistData();
logger.info(this.getClass().getSimpleName() + " started in " + (System.currentTimeMillis() - startTime) + " ms\r\n"); logger.info(this.getClass().getSimpleName() + " started in " + (System.currentTimeMillis() - startTime) + " ms\r\n");
if (!singletonrun) this.serversLatch.await(); if (!singletonrun) this.serversLatch.await();
} }
private void clearPersistData() { // private void clearPersistData() {
File cachedir = new File(home, "cache"); // File cachedir = new File(home, "cache");
if (!cachedir.isDirectory()) return; // if (!cachedir.isDirectory()) return;
for (File file : cachedir.listFiles()) { // File[] lfs = cachedir.listFiles();
if (file.getName().startsWith("persist-")) file.delete(); // if (lfs != null) {
} // for (File file : lfs) {
} // if (file.getName().startsWith("persist-")) file.delete();
// }
// }
// }
// private void signalHandle() { // private void signalHandle() {
// //http://www.comptechdoc.org/os/linux/programming/linux_pgsignals.html // //http://www.comptechdoc.org/os/linux/programming/linux_pgsignals.html
// String[] sigs = new String[]{"HUP", "TERM", "INT", "QUIT", "KILL", "TSTP", "USR1", "USR2", "STOP"}; // String[] sigs = new String[]{"HUP", "TERM", "INT", "QUIT", "KILL", "TSTP", "USR1", "USR2", "STOP"};
@@ -775,13 +812,22 @@ public final class Application {
sercdl.await(); sercdl.await();
} }
public static <T extends Service> T singleton(Class<T> serviceClass) throws Exception { public static <T extends Service> T singleton(Class<T> serviceClass, Class<? extends Service>... extServiceClasses) throws Exception {
return singleton("", serviceClass); return singleton("", serviceClass, extServiceClasses);
} }
public static <T extends Service> T singleton(String name, Class<T> serviceClass) throws Exception { public static <T extends Service> T singleton(String name, Class<T> serviceClass, Class<? extends Service>... extServiceClasses) throws Exception {
if (serviceClass == null) throw new IllegalArgumentException("serviceClass is null"); if (serviceClass == null) throw new IllegalArgumentException("serviceClass is null");
final Application application = Application.create(true); final Application application = Application.create(true);
System.setProperty("red" + "kale-singleton-serviceclass", serviceClass.getName());
if (extServiceClasses != null && extServiceClasses.length > 0) {
StringBuilder sb = new StringBuilder();
for (Class clazz : extServiceClasses) {
if (sb.length() > 0) sb.append(',');
sb.append(clazz.getName());
}
System.setProperty("red" + "kale-singleton-extserviceclasses", sb.toString());
}
application.init(); application.init();
application.start(); application.start();
for (NodeServer server : application.servers) { for (NodeServer server : application.servers) {
@@ -796,8 +842,15 @@ public final class Application {
public static Application create(final boolean singleton) throws IOException { public static Application create(final boolean singleton) throws IOException {
final String home = new File(System.getProperty(RESNAME_APP_HOME, "")).getCanonicalPath().replace('\\', '/'); final String home = new File(System.getProperty(RESNAME_APP_HOME, "")).getCanonicalPath().replace('\\', '/');
System.setProperty(RESNAME_APP_HOME, home); System.setProperty(RESNAME_APP_HOME, home);
File appfile = new File(home, "conf/application.xml"); String confsubpath = System.getProperty(RESNAME_APP_CONF, "conf");
return new Application(singleton, load(new FileInputStream(appfile))); File appfile;
if (confsubpath.charAt(0) == '/' || confsubpath.indexOf(':') > 0) {
appfile = new File(confsubpath).getCanonicalFile();
} else {
appfile = new File(new File(home), confsubpath);
}
File appconf = new File(appfile, "application.xml");
return new Application(singleton, load(new FileInputStream(appconf)));
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
@@ -834,7 +887,7 @@ public final class Application {
return null; return null;
} }
private void shutdown() throws Exception { public void shutdown() throws Exception {
for (ApplicationListener listener : this.listeners) { for (ApplicationListener listener : this.listeners) {
try { try {
listener.preShutdown(this); listener.preShutdown(this);

View File

@@ -7,10 +7,11 @@ package org.redkale.boot;
import java.io.*; import java.io.*;
import java.lang.annotation.*; import java.lang.annotation.*;
import java.lang.reflect.*; import java.lang.reflect.Modifier;
import java.net.*; import java.net.*;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.function.Predicate;
import java.util.jar.*; import java.util.jar.*;
import java.util.logging.*; import java.util.logging.*;
import java.util.regex.*; import java.util.regex.*;
@@ -30,12 +31,14 @@ public final class ClassFilter<T> {
private static final Logger logger = Logger.getLogger(ClassFilter.class.getName()); //日志对象 private static final Logger logger = Logger.getLogger(ClassFilter.class.getName()); //日志对象
private static final boolean finer = logger.isLoggable(Level.FINER); //日志级别 private static final boolean finest = logger.isLoggable(Level.FINEST); //日志级别
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 Predicate<String> expectPredicate;
private boolean refused; //是否拒绝所有数据,设置true则其他规则失效,都是拒绝. private boolean refused; //是否拒绝所有数据,设置true则其他规则失效,都是拒绝.
private Class superClass; //符合的父类型。不为空时扫描结果的class必须是superClass的子类 private Class superClass; //符合的父类型。不为空时扫描结果的class必须是superClass的子类
@@ -136,10 +139,11 @@ public final class ClassFilter<T> {
* *
* @param property AnyValue * @param property AnyValue
* @param clazzname String * @param clazzname String
* @param url URL
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final void filter(AnyValue property, String clazzname) { public final void filter(AnyValue property, String clazzname, URL url) {
filter(property, clazzname, true); filter(property, clazzname, true, url);
} }
/** /**
@@ -150,6 +154,18 @@ public final class ClassFilter<T> {
* @param autoscan 为true表示自动扫描的 false表示显著调用filter AutoLoad的注解将被忽略 * @param autoscan 为true表示自动扫描的 false表示显著调用filter AutoLoad的注解将被忽略
*/ */
public final void filter(AnyValue property, String clazzname, boolean autoscan) { public final void filter(AnyValue property, String clazzname, boolean autoscan) {
filter(property, clazzname, autoscan, null);
}
/**
* 过滤指定的class
*
* @param property application.xml中对应class节点下的property属性项
* @param clazzname class名称
* @param autoscan 为true表示自动扫描的 false表示显著调用filter AutoLoad的注解将被忽略
* @param url URL
*/
public final void filter(AnyValue property, String clazzname, boolean autoscan, URL url) {
boolean r = accept0(property, clazzname); boolean r = accept0(property, clazzname);
ClassFilter cf = r ? this : null; ClassFilter cf = r ? this : null;
if (r && ands != null) { if (r && ands != null) {
@@ -165,7 +181,7 @@ public final class ClassFilter<T> {
} }
} }
} }
if (cf == null || clazzname.startsWith("sun.")) return; if (cf == null || clazzname.startsWith("sun.") || clazzname.contains("module-info")) return;
try { try {
Class clazz = classLoader.loadClass(clazzname); Class clazz = classLoader.loadClass(clazzname);
if (!cf.accept(property, clazz, autoscan)) return; if (!cf.accept(property, clazz, autoscan)) return;
@@ -183,15 +199,16 @@ public final class ClassFilter<T> {
} }
AutoLoad auto = (AutoLoad) clazz.getAnnotation(AutoLoad.class); AutoLoad auto = (AutoLoad) clazz.getAnnotation(AutoLoad.class);
if (autoscan && auto != null && !auto.value()) { //自动扫描且被标记为@AutoLoad(false)的 if ((expectPredicate != null && expectPredicate.test(clazzname)) || (autoscan && auto != null && !auto.value())) { //自动扫描且被标记为@AutoLoad(false)的
expectEntrys.add(new FilterEntry(clazz, autoscan, true, property)); expectEntrys.add(new FilterEntry(clazz, autoscan, true, property));
} else { } else {
entrys.add(new FilterEntry(clazz, autoscan, false, property)); entrys.add(new FilterEntry(clazz, autoscan, false, property));
} }
} catch (Throwable cfe) { } catch (Throwable cfe) {
if (finer && !clazzname.startsWith("sun.") && !clazzname.startsWith("javax.") if (finest && !clazzname.startsWith("sun.") && !clazzname.startsWith("javax.")
&& !clazzname.startsWith("com.sun.") && !clazzname.startsWith("jdk.")) { && !clazzname.startsWith("com.sun.") && !clazzname.startsWith("jdk.") && !clazzname.startsWith("META-INF")
logger.log(Level.FINEST, ClassFilter.class.getSimpleName() + " filter error", cfe); && (!(cfe instanceof NoClassDefFoundError) || (cfe instanceof UnsupportedClassVersionError) || ((NoClassDefFoundError) cfe).getMessage().startsWith("java.lang.NoClassDefFoundError: java"))) {
logger.log(Level.FINEST, ClassFilter.class.getSimpleName() + " filter error for class: " + clazzname + (url == null ? "" : (" in " + url)), cfe);
} }
} }
} }
@@ -333,6 +350,14 @@ public final class ClassFilter<T> {
this.refused = refused; this.refused = refused;
} }
public Predicate<String> getExpectPredicate() {
return expectPredicate;
}
public void setExpectPredicate(Predicate<String> predicate) {
this.expectPredicate = predicate;
}
public Set<String> getPrivilegeIncludes() { public Set<String> getPrivilegeIncludes() {
return privilegeIncludes; return privilegeIncludes;
} }
@@ -347,6 +372,7 @@ public final class ClassFilter<T> {
public void setPrivilegeExcludes(Set<String> privilegeExcludes) { public void setPrivilegeExcludes(Set<String> privilegeExcludes) {
this.privilegeExcludes = privilegeExcludes == null || privilegeExcludes.isEmpty() ? null : privilegeExcludes; this.privilegeExcludes = privilegeExcludes == null || privilegeExcludes.isEmpty() ? null : privilegeExcludes;
} }
/** /**
@@ -502,7 +528,7 @@ public final class ClassFilter<T> {
classes.add(classname); classes.add(classname);
if (debug) debugstr.append(classname).append("\r\n"); if (debug) debugstr.append(classname).append("\r\n");
for (final ClassFilter filter : filters) { for (final ClassFilter filter : filters) {
if (filter != null) filter.filter(null, classname); if (filter != null) filter.filter(null, classname, url);
} }
} }
} }
@@ -511,7 +537,7 @@ public final class ClassFilter<T> {
} else { } else {
for (String classname : classes) { for (String classname : classes) {
for (final ClassFilter filter : filters) { for (final ClassFilter filter : filters) {
if (filter != null) filter.filter(null, classname); if (filter != null) filter.filter(null, classname, url);
} }
} }
} }
@@ -530,14 +556,14 @@ public final class ClassFilter<T> {
classes.add(classname); classes.add(classname);
if (debug) debugstr.append(classname).append("\r\n"); if (debug) debugstr.append(classname).append("\r\n");
for (final ClassFilter filter : filters) { for (final ClassFilter filter : filters) {
if (filter != null) filter.filter(null, classname); if (filter != null) filter.filter(null, classname, url);
} }
} }
cache.put(url, classes); cache.put(url, classes);
} else { } else {
for (String classname : classes) { for (String classname : classes) {
for (final ClassFilter filter : filters) { for (final ClassFilter filter : filters) {
if (filter != null) filter.filter(null, classname); if (filter != null) filter.filter(null, classname, url);
} }
} }
} }
@@ -550,7 +576,9 @@ public final class ClassFilter<T> {
files.add(root); files.add(root);
} else if (root.isDirectory()) { } else if (root.isDirectory()) {
if (exclude != null && exclude.equals(root)) return; if (exclude != null && exclude.equals(root)) return;
for (File f : root.listFiles()) { File[] lfs = root.listFiles();
if (lfs == null) throw new RuntimeException("File(" + root + ") cannot listFiles()");
for (File f : lfs) {
loadClassFiles(exclude, f, files); loadClassFiles(exclude, f, files);
} }
} }

View File

@@ -241,7 +241,21 @@ public class LogFileHandler extends Handler {
} }
String limitstr = manager.getProperty(cname + ".limit"); String limitstr = manager.getProperty(cname + ".limit");
try { try {
if (limitstr != null) this.limit = Math.abs(Integer.decode(limitstr)); if (limitstr != null) {
limitstr = limitstr.toUpperCase();
boolean g = limitstr.indexOf('G') > 0;
boolean m = limitstr.indexOf('M') > 0;
boolean k = limitstr.indexOf('K') > 0;
int ls = Math.abs(Integer.decode(limitstr.replace("G", "").replace("M", "").replace("K", "").replace("B", "")));
if (g) {
ls *= 1024 * 1024 * 1024;
} else if (m) {
ls *= 1024 * 1024;
} else if (k) {
ls *= 1024;
}
this.limit = ls;
}
} catch (Exception e) { } catch (Exception e) {
} }
String countstr = manager.getProperty(cname + ".count"); String countstr = manager.getProperty(cname + ".count");

View File

@@ -9,6 +9,7 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.net.*; import java.net.*;
import java.util.*; import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.logging.Level; import java.util.logging.Level;
import javax.annotation.*; import javax.annotation.*;
import static org.redkale.boot.Application.RESNAME_SNCP_ADDR; import static org.redkale.boot.Application.RESNAME_SNCP_ADDR;
@@ -191,7 +192,7 @@ public class NodeHttpServer extends NodeServer {
} }
int max = 0; int max = 0;
if (ss != null && sb != null) { if (ss != null && sb != null) {
Collections.sort(ss, (AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey())); ss.sort((AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey()));
for (AbstractMap.SimpleEntry<String, String[]> as : ss) { for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
if (as.getKey().length() > max) max = as.getKey().length(); if (as.getKey().length() > max) max = as.getKey().length();
} }
@@ -217,6 +218,7 @@ public class NodeHttpServer extends NodeServer {
if (!rest) return; if (!rest) return;
if (restConf == null) return; //不存在REST服务 if (restConf == null) return; //不存在REST服务
final long starts = System.currentTimeMillis();
String prefix0 = restConf.getValue("path", ""); String prefix0 = restConf.getValue("path", "");
if (!prefix0.isEmpty() && prefix0.charAt(prefix0.length() - 1) == '/') prefix0 = prefix0.substring(0, prefix0.length() - 1); if (!prefix0.isEmpty() && prefix0.charAt(prefix0.length() - 1) == '/') prefix0 = prefix0.substring(0, prefix0.length() - 1);
if (!prefix0.isEmpty() && prefix0.charAt(0) != '/') prefix0 = '/' + prefix0; if (!prefix0.isEmpty() && prefix0.charAt(0) != '/') prefix0 = '/' + prefix0;
@@ -243,35 +245,45 @@ public class NodeHttpServer extends NodeServer {
final ClassFilter restFilter = ClassFilter.create(null, restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues); final ClassFilter restFilter = ClassFilter.create(null, restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
final boolean finest = logger.isLoggable(Level.FINEST); final boolean finest = logger.isLoggable(Level.FINEST);
super.interceptorServices.forEach((service) -> { final CountDownLatch scdl = new CountDownLatch(super.interceptorServices.size());
final Class stype = Sncp.getServiceType(service); super.interceptorServices.stream().parallel().forEach((service) -> {
final String name = Sncp.getResourceName(service); try {
RestService rs = (RestService) stype.getAnnotation(RestService.class); final Class stype = Sncp.getServiceType(service);
if (rs == null || rs.ignore()) return; final String name = Sncp.getResourceName(service);
RestService rs = (RestService) stype.getAnnotation(RestService.class);
if (rs == null || rs.ignore()) return;
final String stypename = stype.getName(); final String stypename = stype.getName();
if (!autoload && !includeValues.contains(stypename)) return; if (!autoload && !includeValues.contains(stypename)) return;
if (!restFilter.accept(stypename)) return; if (!restFilter.accept(stypename)) return;
if (restedObjects.contains(service)) { synchronized (restedObjects) {
logger.log(Level.WARNING, stype.getName() + " repeat create rest servlet, so ignore"); if (restedObjects.contains(service)) {
return; logger.log(Level.WARNING, stype.getName() + " repeat create rest servlet, so ignore");
} return;
restedObjects.add(service); //避免重复创建Rest对象 }
HttpServlet servlet = httpServer.addRestServlet(serverClassLoader, service, userType, baseServletType, prefix); restedObjects.add(service); //避免重复创建Rest对象
if (servlet == null) return; //没有HttpMapping方法的HttpServlet调用Rest.createRestServlet就会返回null
String prefix2 = prefix;
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
if (ws != null && !ws.repair()) prefix2 = "";
resourceFactory.inject(servlet, NodeHttpServer.this);
if (finest) logger.finest(threadName + " Create RestServlet(resource.name='" + name + "') = " + servlet);
if (ss != null) {
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
for (int i = 0; i < mappings.length; i++) {
mappings[i] = prefix2 + mappings[i];
} }
ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName(), mappings)); HttpServlet servlet = httpServer.addRestServlet(serverClassLoader, service, userType, baseServletType, prefix);
if (servlet == null) return; //没有HttpMapping方法的HttpServlet调用Rest.createRestServlet就会返回null
String prefix2 = prefix;
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
if (ws != null && !ws.repair()) prefix2 = "";
resourceFactory.inject(servlet, NodeHttpServer.this);
//if (finest) logger.finest(threadName + " Create RestServlet(resource.name='" + name + "') = " + servlet);
if (ss != null) {
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
for (int i = 0; i < mappings.length; i++) {
mappings[i] = prefix2 + mappings[i];
}
synchronized (ss) {
ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName() + "(rest.name='" + name + "')", mappings));
}
}
} finally {
scdl.countDown();
} }
}); });
scdl.await();
} }
if (webSocketFilter != null) { //加载RestWebSocket if (webSocketFilter != null) { //加载RestWebSocket
final Set<String> includeValues = new HashSet<>(); final Set<String> includeValues = new HashSet<>();
@@ -328,7 +340,7 @@ public class NodeHttpServer extends NodeServer {
} }
//输出信息 //输出信息
if (ss != null && !ss.isEmpty() && sb != null) { if (ss != null && !ss.isEmpty() && sb != null) {
Collections.sort(ss, (AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey())); ss.sort((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) {
if (as.getKey().length() > max) max = as.getKey().length(); if (as.getKey().length() > max) max = as.getKey().length();
@@ -340,6 +352,7 @@ public class NodeHttpServer extends NodeServer {
} }
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR); sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
} }
sb.append(threadName).append(" All HttpServlets load cost " + (System.currentTimeMillis() - starts) + " ms" + LINE_SEPARATOR);
} }
} }
} }

View File

@@ -12,6 +12,7 @@ import java.lang.reflect.*;
import java.net.*; import java.net.*;
import java.nio.file.*; import java.nio.file.*;
import java.util.*; import java.util.*;
import java.util.AbstractMap.SimpleEntry;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.function.*; import java.util.function.*;
import java.util.logging.*; import java.util.logging.*;
@@ -153,6 +154,20 @@ public abstract class NodeServer {
} }
ClassFilter<Service> serviceFilter = createServiceClassFilter(); ClassFilter<Service> serviceFilter = createServiceClassFilter();
if (application.singletonrun) { //singleton模式下只加载指定的Service
final String ssc = System.getProperty("red" + "kale-singleton-serviceclass");
final String extssc = System.getProperty("red" + "kale-singleton-extserviceclasses");
if (ssc != null) {
final List<String> sscList = new ArrayList<>();
sscList.add(ssc);
if (extssc != null && !extssc.isEmpty()) {
for (String s : extssc.split(",")) {
if (!s.isEmpty()) sscList.add(s);
}
}
serviceFilter.setExpectPredicate(c -> !sscList.contains(c));
}
}
ClassFilter<Filter> filterFilter = createFilterClassFilter(); ClassFilter<Filter> filterFilter = createFilterClassFilter();
ClassFilter<Servlet> servletFilter = createServletClassFilter(); ClassFilter<Servlet> servletFilter = createServletClassFilter();
ClassFilter otherFilter = createOtherClassFilter(); ClassFilter otherFilter = createOtherClassFilter();
@@ -161,9 +176,10 @@ public abstract class NodeServer {
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");
loadService(serviceFilter, otherFilter); //必须在servlet之前 loadService(serviceFilter, otherFilter); //必须在servlet之前
loadFilter(filterFilter, otherFilter); if (!application.singletonrun) { //非singleton模式下才加载Filter、Servlet
loadServlet(servletFilter, otherFilter); loadFilter(filterFilter, otherFilter);
loadServlet(servletFilter, otherFilter);
}
if (this.interceptor != null) this.resourceFactory.inject(this.interceptor); if (this.interceptor != null) this.resourceFactory.inject(this.interceptor);
} }
@@ -177,19 +193,27 @@ public abstract class NodeServer {
final ResourceFactory appResFactory = application.getResourceFactory(); final ResourceFactory appResFactory = application.getResourceFactory();
final TransportFactory appSncpTranFactory = application.getSncpTransportFactory(); final TransportFactory appSncpTranFactory = application.getSncpTransportFactory();
final AnyValue resources = application.config.getAnyValue("resources"); final AnyValue resources = application.config.getAnyValue("resources");
final Map<String, AnyValue> cacheResource = new HashMap<>(); final Map<String, SimpleEntry<Class, AnyValue>> cacheResource = new HashMap<>();
final Map<String, AnyValue> dataResources = new HashMap<>(); final Map<String, SimpleEntry<Class, AnyValue>> dataResources = new HashMap<>();
if (resources != null) { if (resources != null) {
for (AnyValue sourceConf : resources.getAnyValues("source")) { for (AnyValue sourceConf : resources.getAnyValues("source")) {
try { try {
Class type = serverClassLoader.loadClass(sourceConf.getValue("value")); Class type = serverClassLoader.loadClass(sourceConf.getValue("value"));
if (type == DataSource.class) type = DataJdbcSource.class; if (type == DataSource.class) {
type = DataMemorySource.class;
for (AnyValue itemConf : sourceConf.getAnyValues("property")) {
if (itemConf.getValue("name", "").contains(DataSources.JDBC_URL)) {
type = DataJdbcSource.class;
break;
}
}
}
if (!Service.class.isAssignableFrom(type)) { if (!Service.class.isAssignableFrom(type)) {
logger.log(Level.SEVERE, "load application source resource, but not Service error: " + sourceConf); logger.log(Level.SEVERE, "load application source resource, but not Service error: " + sourceConf);
} else if (CacheSource.class.isAssignableFrom(type)) { } else if (CacheSource.class.isAssignableFrom(type)) {
cacheResource.put(sourceConf.getValue("name", ""), sourceConf); cacheResource.put(sourceConf.getValue("name", ""), new SimpleEntry(type, sourceConf));
} else if (DataSource.class.isAssignableFrom(type)) { } else if (DataSource.class.isAssignableFrom(type)) {
dataResources.put(sourceConf.getValue("name", ""), sourceConf); dataResources.put(sourceConf.getValue("name", ""), new SimpleEntry(type, sourceConf));
} else { } else {
logger.log(Level.SEVERE, "load application source resource, but not CacheSource error: " + sourceConf); logger.log(Level.SEVERE, "load application source resource, but not CacheSource error: " + sourceConf);
} }
@@ -226,26 +250,31 @@ public abstract class NodeServer {
try { try {
if (field.getAnnotation(Resource.class) == null) return; if (field.getAnnotation(Resource.class) == null) return;
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不得注入 DataSource if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不得注入 DataSource
AnyValue sourceConf = dataResources.get(resourceName); SimpleEntry<Class, AnyValue> resEntry = dataResources.get(resourceName);
AnyValue sourceConf = resEntry == null ? null : resEntry.getValue();
DataSource source = null; DataSource source = null;
boolean needinit = true; boolean needinit = true;
if (sourceConf != null) { if (sourceConf != null) {
final Class sourceType = serverClassLoader.loadClass(sourceConf.getValue("value")); final Class sourceType = resEntry.getKey();
boolean can = false; if (sourceType == DataJdbcSource.class) {
for (Constructor cr : sourceType.getConstructors()) { source = DataSources.createDataSource(resourceName, sourceConf);
if (cr.getParameterCount() == 0) { } else {
can = true; boolean can = false;
break; for (Constructor cr : sourceType.getConstructors()) {
if (cr.getParameterCount() == 0) {
can = true;
break;
}
}
if (DataSource.class.isAssignableFrom(sourceType) && can) { // 必须有空构造函数
final Service srcService = (Service) src;
SncpClient client = Sncp.getSncpClient(srcService);
final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress();
final Set<String> groups = new HashSet<>();
if (client != null && client.getSameGroup() != null) groups.add(client.getSameGroup());
if (client != null && client.getDiffGroups() != null) groups.addAll(client.getDiffGroups());
source = (DataSource) Sncp.createLocalService(serverClassLoader, resourceName, sourceType, appResFactory, appSncpTranFactory, sncpAddr, groups, Sncp.getConf(srcService));
} }
}
if (DataSource.class.isAssignableFrom(sourceType) && can) { // 必须有空构造函数
final Service srcService = (Service) src;
SncpClient client = Sncp.getSncpClient(srcService);
final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress();
final Set<String> groups = new HashSet<>();
if (client != null && client.getSameGroup() != null) groups.add(client.getSameGroup());
if (client != null && client.getDiffGroups() != null) groups.addAll(client.getDiffGroups());
source = (DataSource) Sncp.createLocalService(serverClassLoader, resourceName, sourceType, appResFactory, appSncpTranFactory, sncpAddr, groups, Sncp.getConf(srcService));
} }
} }
if (source == null) { if (source == null) {
@@ -284,6 +313,7 @@ public abstract class NodeServer {
public void load(ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) { public void load(ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) {
try { try {
if (field.getAnnotation(Resource.class) == null) return; if (field.getAnnotation(Resource.class) == null) return;
if (!(src instanceof Service)) throw new RuntimeException("CacheSource must be inject in Service, cannot " + src);
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不需要注入 CacheSource if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不需要注入 CacheSource
final Service srcService = (Service) src; final Service srcService = (Service) src;
SncpClient client = Sncp.getSncpClient(srcService); SncpClient client = Sncp.getSncpClient(srcService);
@@ -292,8 +322,12 @@ public abstract class NodeServer {
if (client != null && client.getSameGroup() != null) groups.add(client.getSameGroup()); if (client != null && client.getSameGroup() != null) groups.add(client.getSameGroup());
if (client != null && client.getDiffGroups() != null) groups.addAll(client.getDiffGroups()); if (client != null && client.getDiffGroups() != null) groups.addAll(client.getDiffGroups());
AnyValue sourceConf = cacheResource.get(resourceName); SimpleEntry<Class, AnyValue> resEntry = cacheResource.get(resourceName);
if (sourceConf == null) sourceConf = dataResources.get(resourceName); AnyValue sourceConf = resEntry == null ? null : resEntry.getValue();
if (sourceConf == null) {
SimpleEntry<Class, AnyValue> resEntry2 = dataResources.get(resourceName);
sourceConf = resEntry2 == null ? null : resEntry2.getValue();
}
final Class sourceType = sourceConf == null ? CacheMemorySource.class : serverClassLoader.loadClass(sourceConf.getValue("value")); final Class sourceType = sourceConf == null ? CacheMemorySource.class : serverClassLoader.loadClass(sourceConf.getValue("value"));
Object source = null; Object source = null;
if (CacheSource.class.isAssignableFrom(sourceType)) { // CacheSource if (CacheSource.class.isAssignableFrom(sourceType)) { // CacheSource
@@ -370,6 +404,7 @@ public abstract class NodeServer {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected void loadService(ClassFilter<? extends Service> serviceFilter, ClassFilter otherFilter) throws Exception { protected void loadService(ClassFilter<? extends Service> serviceFilter, ClassFilter otherFilter) throws Exception {
if (serviceFilter == null) return; if (serviceFilter == null) return;
final long starts = System.currentTimeMillis();
final String threadName = "[" + Thread.currentThread().getName() + "] "; final String threadName = "[" + Thread.currentThread().getName() + "] ";
final Set<FilterEntry<? extends Service>> entrys = (Set) serviceFilter.getAllFilterEntrys(); final Set<FilterEntry<? extends Service>> entrys = (Set) serviceFilter.getAllFilterEntrys();
ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : resourceFactory; ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : resourceFactory;
@@ -401,6 +436,11 @@ public abstract class NodeServer {
if (localed && (serviceImplClass.isInterface() || Modifier.isAbstract(serviceImplClass.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类 if (localed && (serviceImplClass.isInterface() || Modifier.isAbstract(serviceImplClass.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类
final ResourceFactory.ResourceLoader resourceLoader = (ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> { final ResourceFactory.ResourceLoader resourceLoader = (ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> {
try { try {
if (SncpClient.parseMethod(serviceImplClass).isEmpty() && serviceImplClass.getAnnotation(Priority.class) == null) { //class没有可用的方法且没有标记启动优先级的 通常为BaseService
if (!serviceImplClass.getName().startsWith("org.redkale.")) logger.log(Level.FINE, serviceImplClass + " cannot load because not found less one public non-final method");
return;
}
Service service; Service service;
boolean ws = src instanceof WebSocketServlet; boolean ws = src instanceof WebSocketServlet;
if (ws || localed) { //本地模式 if (ws || localed) { //本地模式
@@ -408,8 +448,6 @@ public abstract class NodeServer {
} else { } else {
service = Sncp.createRemoteService(serverClassLoader, resourceName, serviceImplClass, appSncpTransFactory, NodeServer.this.sncpAddress, groups, entry.getProperty()); service = Sncp.createRemoteService(serverClassLoader, resourceName, serviceImplClass, appSncpTransFactory, NodeServer.this.sncpAddress, groups, entry.getProperty());
} }
if (SncpClient.parseMethod(serviceImplClass).isEmpty() && serviceImplClass.getAnnotation(Priority.class) == null) return; //class没有可用的方法且没有标记启动优先级的 通常为BaseService
final Class restype = Sncp.getResourceType(service); final Class restype = Sncp.getResourceType(service);
if (rf.find(resourceName, restype) == null) { if (rf.find(resourceName, restype) == null) {
regFactory.register(resourceName, restype, service); regFactory.register(resourceName, restype, service);
@@ -460,7 +498,7 @@ public abstract class NodeServer {
} }
//----------------- init ----------------- //----------------- init -----------------
List<Service> swlist = new ArrayList<>(localServices); List<Service> swlist = new ArrayList<>(localServices);
Collections.sort(swlist, (o1, o2) -> { swlist.sort((o1, o2) -> {
Priority p1 = o1.getClass().getAnnotation(Priority.class); Priority p1 = o1.getClass().getAnnotation(Priority.class);
Priority p2 = o2.getClass().getAnnotation(Priority.class); Priority p2 = o2.getClass().getAnnotation(Priority.class);
int v = (p2 == null ? 0 : p2.value()) - (p1 == null ? 0 : p1.value()); int v = (p2 == null ? 0 : p2.value()) - (p1 == null ? 0 : p1.value());
@@ -473,24 +511,19 @@ public abstract class NodeServer {
localServices.addAll(swlist); localServices.addAll(swlist);
//this.loadPersistData(); //this.loadPersistData();
final List<String> slist = sb == null ? null : new CopyOnWriteArrayList<>(); final List<String> slist = sb == null ? null : new CopyOnWriteArrayList<>();
CountDownLatch clds = new CountDownLatch(localServices.size());
localServices.stream().forEach(y -> { localServices.stream().forEach(y -> {
try { long s = System.currentTimeMillis();
long s = System.currentTimeMillis(); y.init(Sncp.getConf(y));
y.init(Sncp.getConf(y)); long e = System.currentTimeMillis() - s;
long e = System.currentTimeMillis() - s; String serstr = Sncp.toSimpleString(y, maxNameLength, maxClassNameLength);
String serstr = Sncp.toSimpleString(y, maxNameLength, maxClassNameLength); if (slist != null) slist.add(new StringBuilder().append(threadName).append(serstr).append(" load and init in ").append(e).append(" ms").append(LINE_SEPARATOR).toString());
if (slist != null) slist.add(new StringBuilder().append(threadName).append(serstr).append(" load and init in ").append(e).append(" ms").append(LINE_SEPARATOR).toString());
} finally {
clds.countDown();
}
}); });
clds.await();
if (slist != null && sb != null) { if (slist != null && sb != null) {
List<String> wlist = new ArrayList<>(slist); //直接使用CopyOnWriteArrayList偶尔会出现莫名的异常(CopyOnWriteArrayList源码1185行) List<String> wlist = new ArrayList<>(slist); //直接使用CopyOnWriteArrayList偶尔会出现莫名的异常(CopyOnWriteArrayList源码1185行)
for (String s : wlist) { for (String s : wlist) {
sb.append(s); sb.append(s);
} }
sb.append(threadName).append("All Services load cost " + (System.currentTimeMillis() - starts) + " ms" + LINE_SEPARATOR);
} }
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

@@ -32,7 +32,7 @@ public class NodeSncpServer extends NodeServer {
private 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.addSncpServlet(x); this.consumer = sncpServer == null || application.singletonrun ? null : x -> sncpServer.addSncpServlet(x); //singleton模式下不生成SncpServlet
} }
public static NodeServer createNodeServer(Application application, AnyValue serconf) { public static NodeServer createNodeServer(Application application, AnyValue serconf) {

View File

@@ -41,7 +41,7 @@
html.push(' <tr>'); html.push(' <tr>');
html.push('<td style="color:#ff00ff;">' + action.url + '</td>'); html.push('<td style="color:#ff00ff;">' + action.url + '</td>');
html.push('<td>' + action.comment + '</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>'); html.push('<td class="s" style="width:80px;">模块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 = []; var paramshtml = [];
paramshtml.push('<table class="subtable">'); paramshtml.push('<table class="subtable">');
for (var p = 0; p < action.params.length; p++) { for (var p = 0; p < action.params.length; p++) {

View File

@@ -6,6 +6,7 @@
package org.redkale.boot.watch; package org.redkale.boot.watch;
import org.redkale.service.AbstractService; import org.redkale.service.AbstractService;
import org.redkale.util.Comment;
import org.redkale.watch.WatchService; import org.redkale.watch.WatchService;
/** /**
@@ -14,4 +15,9 @@ import org.redkale.watch.WatchService;
*/ */
public abstract class AbstractWatchService extends AbstractService implements WatchService { public abstract class AbstractWatchService extends AbstractService implements WatchService {
@Comment("缺少参数")
public static final int RET_WATCH_PARAMS_ILLEGAL = 1600_0001;
@Comment("执行异常")
public static final int RET_WATCH_RUN_EXCEPTION = 1600_0002;
} }

View File

@@ -33,7 +33,7 @@ public class FilterWatchService extends AbstractWatchService {
public static final int RET_FILTER_JAR_ILLEGAL = 1601_0005; public static final int RET_FILTER_JAR_ILLEGAL = 1601_0005;
@Resource @Resource
private Application application; protected Application application;
@RestMapping(name = "addfilter", auth = false, comment = "动态增加Filter") @RestMapping(name = "addfilter", auth = false, comment = "动态增加Filter")
public RetResult addFilter(@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar, public RetResult addFilter(@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar,
@@ -47,4 +47,34 @@ public class FilterWatchService extends AbstractWatchService {
} }
return RetResult.success(); return RetResult.success();
} }
@RestMapping(name = "test1", auth = false, comment = "预留")
public RetResult test1() {
return RetResult.success();
}
@RestMapping(name = "test2", auth = false, comment = "预留")
public RetResult test2() {
return RetResult.success();
}
@RestMapping(name = "test3", auth = false, comment = "预留")
public RetResult test3() {
return RetResult.success();
}
@RestMapping(name = "test4", auth = false, comment = "预留")
public RetResult test4() {
return RetResult.success();
}
@RestMapping(name = "test5", auth = false, comment = "预留")
public RetResult test5() {
return RetResult.success();
}
@RestMapping(name = "test6", auth = false, comment = "预留")
public RetResult test6() {
return RetResult.success();
}
} }

View File

@@ -5,7 +5,10 @@
*/ */
package org.redkale.boot.watch; package org.redkale.boot.watch;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.*; import java.util.*;
import java.util.stream.Stream;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.redkale.boot.*; import org.redkale.boot.*;
import org.redkale.net.Server; import org.redkale.net.Server;
@@ -23,18 +26,16 @@ public class ServerWatchService extends AbstractWatchService {
@Comment("不存在的Server节点") @Comment("不存在的Server节点")
public static final int RET_SERVER_NOT_EXISTS = 1602_0001; public static final int RET_SERVER_NOT_EXISTS = 1602_0001;
@Comment("更改Server监听地址端口失败")
public static final int RET_SERVER_CHANGEPORT_ERROR = 1602_0002;
@Resource @Resource
private Application application; protected Application application;
@RestMapping(name = "info", comment = "单个Server信息查询") @RestMapping(name = "info", comment = "单个Server信息查询")
public RetResult info(@RestParam(name = "#port:") int port) { public RetResult info(@RestParam(name = "#port:") final int port) {
NodeServer node = null; Stream<NodeServer> stream = application.getNodeServers().stream();
for (NodeServer ns : application.getNodeServers()) { NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == port).findFirst().orElse(null);
if (ns.getServer().getSocketAddress().getPort() == port) {
node = ns;
break;
}
}
if (node == null) return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + port + ") not found"); if (node == null) return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + port + ") not found");
return new RetResult(formatToMap(node)); return new RetResult(formatToMap(node));
} }
@@ -49,6 +50,25 @@ public class ServerWatchService extends AbstractWatchService {
return new RetResult(rs); return new RetResult(rs);
} }
@RestMapping(name = "changeaddress", comment = "更改Server的监听地址和端口")
public RetResult changeAddress(@RestParam(name = "#port:") final int oldport,
@RestParam(name = "#newhost:") final String newhost, @RestParam(name = "#newport:") final int newport) {
if (oldport < 1) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `oldport`");
if (newport < 1) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `newport`");
Stream<NodeServer> stream = application.getNodeServers().stream();
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == oldport).findFirst().orElse(null);
if (node == null) return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + oldport + ") not found");
final Server server = node.getServer();
InetSocketAddress newAddr = new InetSocketAddress(newhost == null || newhost.isEmpty() ? server.getSocketAddress().getHostString() : newhost, newport);
try {
server.changeAddress(newAddr);
} catch (IOException e) {
e.printStackTrace();
return new RetResult(RET_SERVER_CHANGEPORT_ERROR, "changeaddress error");
}
return RetResult.success();
}
private Map<String, Object> formatToMap(NodeServer node) { private Map<String, Object> formatToMap(NodeServer node) {
Server server = node.getServer(); Server server = node.getServer();
Map<String, Object> rs = new LinkedHashMap<>(); Map<String, Object> rs = new LinkedHashMap<>();

View File

@@ -5,10 +5,14 @@
*/ */
package org.redkale.boot.watch; package org.redkale.boot.watch;
import java.lang.reflect.*;
import java.util.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.redkale.boot.Application; import org.redkale.boot.*;
import org.redkale.net.TransportFactory; import org.redkale.convert.json.JsonConvert;
import org.redkale.net.http.*; import org.redkale.net.http.*;
import org.redkale.service.RetResult;
import org.redkale.util.*;
/** /**
* <p> * <p>
@@ -19,21 +23,177 @@ import org.redkale.net.http.*;
@RestService(name = "service", catalog = "watch", repair = false) @RestService(name = "service", catalog = "watch", repair = false)
public class ServiceWatchService extends AbstractWatchService { public class ServiceWatchService extends AbstractWatchService {
@Resource @Comment("没有找到目标Service")
private Application application; public static final int RET_SERVICE_DEST_NOT_EXISTS = 1603_0001;
@Resource @Resource
private TransportFactory transportFactory; protected Application application;
// @RestMapping(name = "load", auth = false, comment = "动态增加Service") @RestConvert(type = void.class)
// public RetResult loadService(String type, @RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) { @RestMapping(name = "setfield", auth = false, comment = "设置Service中指定字段的内容")
// //待开发 public RetResult setfield(@RestParam(name = "name", comment = "Service的资源名") String name,
// return RetResult.success(); @RestParam(name = "type", comment = "Service的类名") String type,
// } @RestParam(name = "field", comment = "字段名") String field,
// @RestParam(name = "value", comment = "字段值") String value) {
// @RestMapping(name = "stop", auth = false, comment = "动态停止Service") if (name == null) name = "";
// public RetResult stopService(String name, String type) { if (type == null) type = "";
// //待开发 if (field == null) field = "";
// return RetResult.success(); type = type.trim();
// } field = field.trim();
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
if (field.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
Object dest = findService(name, type);
Class clazz = dest.getClass();
Throwable t = null;
try {
Field fieldObj = null;
do {
try {
fieldObj = clazz.getDeclaredField(field);
break;
} catch (Exception e) {
if (t == null) t = e;
}
} while ((clazz = clazz.getSuperclass()) != Object.class);
if (fieldObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + String.valueOf(t) + ")");
fieldObj.setAccessible(true);
fieldObj.set(dest, JsonConvert.root().convertFrom(fieldObj.getGenericType(), value));
return RetResult.success();
} catch (Throwable t2) {
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
}
}
@RestConvert(type = void.class)
@RestMapping(name = "getfield", auth = false, comment = "查询Service中指定字段的内容")
public RetResult getfield(@RestParam(name = "name", comment = "Service的资源名") String name,
@RestParam(name = "type", comment = "Service的类名") String type,
@RestParam(name = "field", comment = "字段名") String field) {
if (name == null) name = "";
if (type == null) type = "";
if (field == null) field = "";
type = type.trim();
field = field.trim();
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
if (field.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
Object dest = findService(name, type);
Class clazz = dest.getClass();
Throwable t = null;
try {
Field fieldObj = null;
do {
try {
fieldObj = clazz.getDeclaredField(field);
break;
} catch (Exception e) {
if (t == null) t = e;
}
} while ((clazz = clazz.getSuperclass()) != Object.class);
if (fieldObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + String.valueOf(t) + ")");
fieldObj.setAccessible(true);
return new RetResult(fieldObj.get(dest));
} catch (Throwable t2) {
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
}
}
@RestConvert(type = void.class)
@RestMapping(name = "runmethod", auth = false, comment = "调用Service中指定方法")
public RetResult runmethod(@RestParam(name = "name", comment = "Service的资源名") String name,
@RestParam(name = "type", comment = "Service的类名") String type,
@RestParam(name = "method", comment = "Service的方法名") String method,
@RestParam(name = "params", comment = "方法的参数值") List<String> params,
@RestParam(name = "paramtypes", comment = "方法的参数数据类型") List<String> paramtypes) {
if (name == null) name = "";
if (type == null) type = "";
if (method == null) method = "";
type = type.trim();
method = method.trim();
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
if (method.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `method`");
Object dest = findService(name, type);
Class clazz = dest.getClass();
Throwable t = null;
final int paramcount = params == null ? 0 : params.size();
if (paramtypes != null && paramcount != paramtypes.size()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "params.size not equals to paramtypes.size");
try {
Method methodObj = null;
do {
try {
for (Method m : clazz.getDeclaredMethods()) {
if (m.getName().equals(method) && m.getParameterCount() == paramcount) {
boolean flag = true;
if (paramtypes != null) {
Class[] pts = m.getParameterTypes();
for (int i = 0; i < pts.length; i++) {
if (!pts[i].getName().endsWith(paramtypes.get(i))) {
flag = false;
break;
}
}
}
if (flag) {
methodObj = m;
break;
}
}
}
if (methodObj != null) break;
} catch (Exception e) {
if (t == null) t = e;
}
} while ((clazz = clazz.getSuperclass()) != Object.class);
if (methodObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + (t == null ? ("not found method(" + method + ")") : String.valueOf(t)) + ")");
methodObj.setAccessible(true);
if (paramcount < 1) return new RetResult(methodObj.invoke(dest));
Object[] paramObjs = new Object[paramcount];
Type[] pts = methodObj.getGenericParameterTypes();
for (int i = 0; i < paramObjs.length; i++) {
paramObjs[i] = JsonConvert.root().convertFrom(pts[i], params.get(i));
}
return new RetResult(methodObj.invoke(dest, paramObjs));
} catch (Throwable t2) {
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
}
}
protected Object findService(String name, String type) {
Object dest = null;
for (NodeServer ns : application.getNodeServers()) {
ResourceFactory resFactory = ns.getResourceFactory();
List list = resFactory.query((n, s) -> name.equals(n) && s != null && s.getClass().getName().endsWith(type));
if (list == null || list.isEmpty()) continue;
dest = list.get(0);
}
if (dest == null) return new RetResult(RET_SERVICE_DEST_NOT_EXISTS, "not found servie (name=" + name + ", type=" + type + ")");
return dest;
}
@RestMapping(name = "load", auth = false, comment = "动态增加Service")
public RetResult loadService(@RestParam(name = "type", comment = "Service的类名") String type,
@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {
//待开发
return RetResult.success();
}
@RestMapping(name = "reload", auth = false, comment = "重新加载Service")
public RetResult reloadService(@RestParam(name = "name", comment = "Service的资源名") String name,
@RestParam(name = "type", comment = "Service的类名") String type) {
//待开发
return RetResult.success();
}
@RestMapping(name = "stop", auth = false, comment = "动态停止Service")
public RetResult stopService(@RestParam(name = "name", comment = "Service的资源名") String name,
@RestParam(name = "type", comment = "Service的类名") String type) {
//待开发
return RetResult.success();
}
@RestMapping(name = "find", auth = false, comment = "查找Service")
public RetResult find(@RestParam(name = "name", comment = "Service的资源名") String name,
@RestParam(name = "type", comment = "Service的类名") String type) {
//待开发
return RetResult.success();
}
} }

View File

@@ -20,10 +20,10 @@ import org.redkale.net.http.*;
public class ServletWatchService extends AbstractWatchService { public class ServletWatchService extends AbstractWatchService {
@Resource @Resource
private Application application; protected Application application;
@Resource @Resource
private TransportFactory transportFactory; protected TransportFactory transportFactory;
// //
// @RestMapping(name = "load", auth = false, comment = "动态增加Servlet") // @RestMapping(name = "load", auth = false, comment = "动态增加Servlet")
// public RetResult loadServlet(String type, @RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) { // public RetResult loadServlet(String type, @RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {

View File

@@ -5,22 +5,118 @@
*/ */
package org.redkale.boot.watch; package org.redkale.boot.watch;
import java.io.*;
import java.lang.reflect.Method;
import java.util.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.redkale.boot.Application; import org.redkale.boot.Application;
import org.redkale.net.TransportFactory; import org.redkale.net.http.*;
import org.redkale.net.http.RestService; import org.redkale.service.*;
import org.redkale.source.*;
import org.redkale.util.*;
/** /**
* WATCH服务, 操作DataSource源
* *
* @author zhangjx * @author zhangjx
*/ */
@RestService(name = "source", catalog = "watch", repair = false) @RestService(name = "source", catalog = "watch", repair = false)
public class SourceWatchService extends AbstractWatchService { public class SourceWatchService extends AbstractWatchService {
@Resource @Comment("不存在的Source")
private Application application; public static final int RET_SOURCE_NOT_EXISTS = 1605_0001;
@Comment("Source不支持getReadPoolSource/getWritePoolSource方法")
public static final int RET_SOURCE_CHANGE_METHOD_NOT_EXISTS = 1605_0002;
@Comment("PoolSource调用change方法失败")
public static final int RET_SOURCE_METHOD_INVOKE_NOT_EXISTS = 1605_0003;
@Resource(name = "APP_HOME")
protected File home;
@Resource @Resource
private TransportFactory transportFactory; protected Application application;
@RestMapping(name = "change", auth = false, comment = "动态更改DataSource的配置")
public RetResult addNode(@RestParam(name = "name", comment = "DataSource的标识") final String name,
@RestParam(name = "properties", comment = "配置") Properties properties,
@RestParam(name = "xmlpath", comment = "配置文件路径") String xmlpath) throws IOException {
if (name == null) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param (name)");
if (properties == null && xmlpath != null) {
File f = new File(xmlpath);
if (!f.isFile()) f = new File(home, xmlpath);
if (!f.isFile()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found file (" + xmlpath + ")");
FileInputStream in = new FileInputStream(f);
Map<String, Properties> map = DataSources.loadPersistenceXml(in);
properties = map.get(name);
}
if (properties == null) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param (properties)");
DataSource source = null;
for (DataSource s : application.getDataSources()) {
String resName = ((Resourcable) s).resourceName();
if (resName == null) continue;
if (!resName.equals(name)) continue;
source = s;
break;
}
if (source == null) return new RetResult(RET_SOURCE_NOT_EXISTS, "not found source (name = " + name + ")");
Method readPoolMethod = null;
Method writePoolMethod = null;
Class stype = source.getClass();
do {
for (Method m : stype.getDeclaredMethods()) {
if (!PoolSource.class.isAssignableFrom(m.getReturnType())) continue;
if (m.getParameterCount() != 0) continue;
if (m.getName().equals("getReadPoolSource")) {
readPoolMethod = m;
} else if (m.getName().equals("getWritePoolSource")) {
writePoolMethod = m;
}
}
} while ((stype = stype.getSuperclass()) != Object.class);
if (readPoolMethod == null) return new RetResult(RET_SOURCE_CHANGE_METHOD_NOT_EXISTS, "not found source method(getReadPoolSource)");
if (writePoolMethod == null) return new RetResult(RET_SOURCE_CHANGE_METHOD_NOT_EXISTS, "not found source method(getWritePoolSource)");
readPoolMethod.setAccessible(true);
writePoolMethod.setAccessible(true);
try {
PoolSource readPoolSource = (PoolSource) readPoolMethod.invoke(source);
PoolSource writePoolSource = (PoolSource) writePoolMethod.invoke(source);
readPoolSource.change(properties);
writePoolSource.change(properties);
return RetResult.success();
} catch (Exception e) {
return new RetResult(RET_SOURCE_METHOD_INVOKE_NOT_EXISTS, "poolsource invoke method('change') error");
}
}
@RestMapping(name = "test1", auth = false, comment = "预留")
public RetResult test1() {
return RetResult.success();
}
@RestMapping(name = "test2", auth = false, comment = "预留")
public RetResult test2() {
return RetResult.success();
}
@RestMapping(name = "test3", auth = false, comment = "预留")
public RetResult test3() {
return RetResult.success();
}
@RestMapping(name = "test4", auth = false, comment = "预留")
public RetResult test4() {
return RetResult.success();
}
@RestMapping(name = "test5", auth = false, comment = "预留")
public RetResult test5() {
return RetResult.success();
}
@RestMapping(name = "test6", auth = false, comment = "预留")
public RetResult test6() {
return RetResult.success();
}
} }

View File

@@ -36,10 +36,10 @@ public class TransportWatchService extends AbstractWatchService {
public static final int RET_TRANSPORT_ADDR_EXISTS = 1606_0003; public static final int RET_TRANSPORT_ADDR_EXISTS = 1606_0003;
@Resource @Resource
private Application application; protected Application application;
@Resource @Resource
private TransportFactory transportFactory; protected TransportFactory transportFactory;
@RestMapping(name = "listnodes", auth = false, comment = "获取所有Node节点") @RestMapping(name = "listnodes", auth = false, comment = "获取所有Node节点")
public List<TransportGroupInfo> listNodes() { public List<TransportGroupInfo> listNodes() {
@@ -135,4 +135,24 @@ public class TransportWatchService extends AbstractWatchService {
} }
return RetResult.success(); return RetResult.success();
} }
@RestMapping(name = "test1", auth = false, comment = "预留")
public RetResult test1() {
return RetResult.success();
}
@RestMapping(name = "test2", auth = false, comment = "预留")
public RetResult test2() {
return RetResult.success();
}
@RestMapping(name = "test3", auth = false, comment = "预留")
public RetResult test3() {
return RetResult.success();
}
@RestMapping(name = "test4", auth = false, comment = "预留")
public RetResult test4() {
return RetResult.success();
}
} }

View File

@@ -0,0 +1,64 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.convert;
import java.lang.reflect.Type;
import java.util.*;
import org.redkale.util.*;
import org.redkale.convert.Reader.ValueType;
import static org.redkale.convert.Reader.ValueType.MAP;
/**
* 对不明类型的对象进行反序列化。 <br>
* <b>注意: 目前只支持文本格式</b> <br>
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
*/
public class AnyDecoder implements Decodeable<Reader, Object> {
private static final Type collectionObjectType = new TypeToken<Collection<Object>>() {
}.getType();
private static final Type mapObjectType = new TypeToken<Map<String, Object>>() {
}.getType();
private static final Creator<ArrayList> collectionCreator = Creator.create(ArrayList.class);
private static final Creator<HashMap> mapCreator = Creator.create(HashMap.class);
protected final Decodeable<Reader, String> stringDecoder;
protected final CollectionDecoder collectionDecoder;
protected final MapDecoder mapDecoder;
public AnyDecoder(final ConvertFactory factory) {
this.stringDecoder = factory.loadDecoder(String.class);
this.collectionDecoder = new CollectionDecoder(factory, collectionObjectType, Object.class, collectionCreator, this);
this.mapDecoder = new MapDecoder(factory, mapObjectType, String.class, Object.class, mapCreator, stringDecoder, this);
}
@Override
public Object convertFrom(Reader in) {
ValueType vt = in.readType();
if (vt == null) return null;
switch (vt) {
case ARRAY:
return this.collectionDecoder.convertFrom(in);
case MAP:
return this.mapDecoder.convertFrom(in);
}
return this.stringDecoder.convertFrom(in);
}
@Override
public Type getType() {
return void.class;
}
}

View File

@@ -42,16 +42,17 @@ public final class AnyEncoder<T> implements Encodeable<Writer, T> {
out.writeNull(); out.writeNull();
} else { } else {
int count = values.length - values.length % 2; int count = values.length - values.length % 2;
out.writeMapB(count / 2); if (out.writeMapB(count / 2, (Encodeable) this, (Encodeable) this, values) < 0) {
for (int i = 0; i < count; i += 2) { for (int i = 0; i < count; i += 2) {
if (i > 0) out.writeArrayMark(); if (i > 0) out.writeArrayMark();
this.convertTo(out, (T) values[i]); this.convertTo(out, (T) values[i]);
out.writeMapMark(); out.writeMapMark();
Object val = values[i + 1]; Object val = values[i + 1];
if (val instanceof CompletableFuture) { if (val instanceof CompletableFuture) {
this.convertTo(out, (T) ((CompletableFuture) val).join()); this.convertTo(out, (T) ((CompletableFuture) val).join());
} else { } else {
this.convertTo(out, (T) val); this.convertTo(out, (T) val);
}
} }
} }
out.writeMapE(); out.writeMapE();

View File

@@ -20,19 +20,19 @@ import java.util.*;
* @param <T> 反解析的数组元素类型 * @param <T> 反解析的数组元素类型
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> { public class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
private final Type type; protected final Type type;
private final Type componentType; protected final Type componentType;
private final Class componentClass; protected final Class componentClass;
protected final Decodeable<Reader, T> decoder; protected final Decodeable<Reader, T> componentDecoder;
private boolean inited = false; protected volatile boolean inited = false;
private final Object lock = new Object(); protected final Object lock = new Object();
public ArrayDecoder(final ConvertFactory factory, final Type type) { public ArrayDecoder(final ConvertFactory factory, final Type type) {
this.type = type; this.type = type;
@@ -51,7 +51,7 @@ public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
this.componentClass = (Class) this.componentType; this.componentClass = (Class) this.componentType;
} }
factory.register(type, this); factory.register(type, this);
this.decoder = factory.loadDecoder(this.componentType); this.componentDecoder = factory.loadDecoder(this.componentType);
} finally { } finally {
inited = true; inited = true;
synchronized (lock) { synchronized (lock) {
@@ -62,9 +62,19 @@ public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
@Override @Override
public T[] convertFrom(Reader in) { public T[] convertFrom(Reader in) {
final int len = in.readArrayB(); return convertFrom(in, null);
}
public T[] convertFrom(Reader in, DeMember member) {
byte[] typevals = new byte[1];
int len = in.readArrayB(member, typevals, componentDecoder);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NULL) return null;
if (this.decoder == null) { if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = in.readMemberContentLength(member, componentDecoder);
len = Reader.SIGN_NOLENGTH;
}
if (this.componentDecoder == null) {
if (!this.inited) { if (!this.inited) {
synchronized (lock) { synchronized (lock) {
try { try {
@@ -75,11 +85,16 @@ public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
} }
} }
} }
final Decodeable<Reader, T> localdecoder = this.decoder; final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
final List<T> result = new ArrayList(); final List<T> result = new ArrayList();
boolean first = true;
if (len == Reader.SIGN_NOLENGTH) { if (len == Reader.SIGN_NOLENGTH) {
while (in.hasNext()) { int startPosition = in.position();
result.add(localdecoder.convertFrom(in)); while (hasNext(in, member, startPosition, contentLength, first)) {
Reader itemReader = getItemReader(in, member, first);
if (itemReader == null) break;
result.add(readMemberValue(itemReader, member, localdecoder, first));
first = false;
} }
} else { } else {
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
@@ -91,9 +106,25 @@ public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
return result.toArray(rs); return result.toArray(rs);
} }
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
return in.hasNext(startPosition, contentLength);
}
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
return decoder;
}
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
return in;
}
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
return decoder.convertFrom(in);
}
@Override @Override
public String toString() { public String toString() {
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", decoder:" + this.decoder + "}"; return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", decoder:" + this.componentDecoder + "}";
} }
@Override @Override
@@ -101,4 +132,12 @@ public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
return type; return type;
} }
public Type getComponentType() {
return componentType;
}
public Decodeable<Reader, T> getComponentDecoder() {
return componentDecoder;
}
} }

View File

@@ -19,19 +19,19 @@ import java.lang.reflect.*;
* @param <T> 序列化的数组元素类型 * @param <T> 序列化的数组元素类型
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> { public class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
private final Type type; protected final Type type;
private final Type componentType; protected final Type componentType;
private final Encodeable anyEncoder; protected final Encodeable anyEncoder;
private final Encodeable<Writer, Object> encoder; protected final Encodeable<Writer, Object> componentEncoder;
private boolean inited = false; protected volatile boolean inited = false;
private final Object lock = new Object(); protected final Object lock = new Object();
public ArrayEncoder(final ConvertFactory factory, final Type type) { public ArrayEncoder(final ConvertFactory factory, final Type type) {
this.type = type; this.type = type;
@@ -45,7 +45,7 @@ public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
throw new ConvertException("(" + type + ") is not a array type"); throw new ConvertException("(" + type + ") is not a array type");
} }
factory.register(type, this); factory.register(type, this);
this.encoder = factory.loadEncoder(this.componentType); this.componentEncoder = factory.loadEncoder(this.componentType);
this.anyEncoder = factory.getAnyEncoder(); this.anyEncoder = factory.getAnyEncoder();
} finally { } finally {
inited = true; inited = true;
@@ -57,16 +57,20 @@ public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
@Override @Override
public void convertTo(Writer out, T[] value) { public void convertTo(Writer out, T[] value) {
convertTo(out, null, value);
}
public void convertTo(Writer out, EnMember member, T[] value) {
if (value == null) { if (value == null) {
out.writeNull(); out.writeNull();
return; return;
} }
if (value.length == 0) { if (value.length == 0) {
out.writeArrayB(0); out.writeArrayB(0, componentEncoder, value);
out.writeArrayE(); out.writeArrayE();
return; return;
} }
if (this.encoder == null) { if (this.componentEncoder == null) {
if (!this.inited) { if (!this.inited) {
synchronized (lock) { synchronized (lock) {
try { try {
@@ -77,24 +81,38 @@ public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
} }
} }
} }
out.writeArrayB(value.length); if (out.writeArrayB(value.length, componentEncoder, value) < 0) {
final Type comp = this.componentType; final Type comp = this.componentType;
boolean first = true; boolean first = true;
for (Object v : value) { for (Object v : value) {
if (!first) out.writeArrayMark(); if (!first) out.writeArrayMark();
((v != null && v.getClass() == comp) ? encoder : anyEncoder).convertTo(out, v); writeMemberValue(out, member, ((v != null && (v.getClass() == comp || out.specify() == comp)) ? componentEncoder : anyEncoder), v, first);
if (first) first = false; if (first) first = false;
}
} }
out.writeArrayE(); out.writeArrayE();
} }
protected void writeMemberValue(Writer out, EnMember member, Encodeable<Writer, Object> encoder, Object value, boolean first) {
encoder.convertTo(out, value);
}
@Override @Override
public String toString() { public String toString() {
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", encoder:" + this.encoder + "}"; return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", encoder:" + this.componentEncoder + "}";
} }
@Override @Override
public Type getType() { public Type getType() {
return type; return type;
} }
public Type getComponentType() {
return componentType;
}
public Encodeable<Writer, Object> getComponentEncoder() {
return componentEncoder;
}
} }

View File

@@ -8,7 +8,7 @@ package org.redkale.convert;
import org.redkale.util.Creator; import org.redkale.util.Creator;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Collection; import java.util.*;
/** /**
* Collection的反序列化操作类 <br> * Collection的反序列化操作类 <br>
@@ -21,19 +21,19 @@ import java.util.Collection;
* @param <T> 反解析的集合元素类型 * @param <T> 反解析的集合元素类型
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class CollectionDecoder<T> implements Decodeable<Reader, Collection<T>> { public class CollectionDecoder<T> implements Decodeable<Reader, Collection<T>> {
private final Type type; protected final Type type;
private final Type componentType; protected final Type componentType;
protected Creator<Collection<T>> creator; protected Creator<Collection<T>> creator;
protected final Decodeable<Reader, T> decoder; protected final Decodeable<Reader, T> componentDecoder;
private boolean inited = false; protected volatile boolean inited = false;
private final Object lock = new Object(); protected final Object lock = new Object();
public CollectionDecoder(final ConvertFactory factory, final Type type) { public CollectionDecoder(final ConvertFactory factory, final Type type) {
this.type = type; this.type = type;
@@ -43,12 +43,12 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
this.componentType = pt.getActualTypeArguments()[0]; this.componentType = pt.getActualTypeArguments()[0];
this.creator = factory.loadCreator((Class) pt.getRawType()); this.creator = factory.loadCreator((Class) pt.getRawType());
factory.register(type, this); factory.register(type, this);
this.decoder = factory.loadDecoder(this.componentType); this.componentDecoder = factory.loadDecoder(this.componentType);
} else if(factory.isReversible()){ } else if (factory.isReversible()) {
this.componentType = Object.class; this.componentType = Object.class;
this.creator = factory.loadCreator(Object.class); this.creator = factory.loadCreator(type instanceof Class ? (Class) type : Collection.class);
factory.register(type, this); factory.register(type, this);
this.decoder = factory.loadDecoder(this.componentType); this.componentDecoder = factory.loadDecoder(this.componentType);
} else { } else {
throw new ConvertException("CollectionDecoder not support the type (" + type + ")"); throw new ConvertException("CollectionDecoder not support the type (" + type + ")");
} }
@@ -60,11 +60,32 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
} }
} }
//仅供类似JsonAnyDecoder这种动态创建使用 不得调用 factory.register
public CollectionDecoder(final ConvertFactory factory, Type type, Type componentType,
Creator<Collection<T>> creator, final Decodeable<Reader, T> componentDecoder) {
Objects.requireNonNull(componentDecoder);
this.type = type;
this.componentType = componentType;
this.creator = creator;
this.componentDecoder = componentDecoder;
this.inited = true;
}
@Override @Override
public Collection<T> convertFrom(Reader in) { public Collection<T> convertFrom(Reader in) {
final int len = in.readArrayB(); return convertFrom(in, null);
}
public Collection<T> convertFrom(Reader in, DeMember member) {
byte[] typevals = new byte[1];
int len = in.readArrayB(member, typevals, componentDecoder);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NULL) return null;
if (this.decoder == null) { if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = in.readMemberContentLength(member, componentDecoder);
len = Reader.SIGN_NOLENGTH;
}
if (this.componentDecoder == null) {
if (!this.inited) { if (!this.inited) {
synchronized (lock) { synchronized (lock) {
try { try {
@@ -75,11 +96,16 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
} }
} }
} }
final Decodeable<Reader, T> localdecoder = this.decoder; final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
final Collection<T> result = this.creator.create(); final Collection<T> result = this.creator.create();
boolean first = true;
if (len == Reader.SIGN_NOLENGTH) { if (len == Reader.SIGN_NOLENGTH) {
while (in.hasNext()) { int startPosition = in.position();
result.add(localdecoder.convertFrom(in)); while (hasNext(in, member, startPosition, contentLength, first)) {
Reader itemReader = getItemReader(in, member, first);
if (itemReader == null) break;
result.add(readMemberValue(itemReader, member, localdecoder, first));
first = false;
} }
} else { } else {
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
@@ -90,9 +116,33 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
return result; return result;
} }
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
return in.hasNext(startPosition, contentLength);
}
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
return decoder;
}
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
return in;
}
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
return decoder.convertFrom(in);
}
@Override @Override
public Type getType() { public Type getType() {
return type; return type;
} }
public Type getComponentType() {
return componentType;
}
public Decodeable<Reader, T> getComponentDecoder() {
return componentDecoder;
}
} }

View File

@@ -19,15 +19,15 @@ import java.util.Collection;
* @param <T> 序列化的集合元素类型 * @param <T> 序列化的集合元素类型
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class CollectionEncoder<T> implements Encodeable<Writer, Collection<T>> { public class CollectionEncoder<T> implements Encodeable<Writer, Collection<T>> {
private final Type type; protected final Type type;
private final Encodeable<Writer, Object> encoder; protected final Encodeable<Writer, Object> componentEncoder;
private boolean inited = false; protected volatile boolean inited = false;
private final Object lock = new Object(); protected final Object lock = new Object();
public CollectionEncoder(final ConvertFactory factory, final Type type) { public CollectionEncoder(final ConvertFactory factory, final Type type) {
this.type = type; this.type = type;
@@ -35,12 +35,12 @@ public final class CollectionEncoder<T> implements Encodeable<Writer, Collection
if (type instanceof ParameterizedType) { if (type instanceof ParameterizedType) {
Type t = ((ParameterizedType) type).getActualTypeArguments()[0]; Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
if (t instanceof TypeVariable) { if (t instanceof TypeVariable) {
this.encoder = factory.getAnyEncoder(); this.componentEncoder = factory.getAnyEncoder();
} else { } else {
this.encoder = factory.loadEncoder(t); this.componentEncoder = factory.loadEncoder(t);
} }
} else { } else {
this.encoder = factory.getAnyEncoder(); this.componentEncoder = factory.getAnyEncoder();
} }
} finally { } finally {
inited = true; inited = true;
@@ -52,16 +52,20 @@ public final class CollectionEncoder<T> implements Encodeable<Writer, Collection
@Override @Override
public void convertTo(Writer out, Collection<T> value) { public void convertTo(Writer out, Collection<T> value) {
convertTo(out, null, value);
}
public void convertTo(Writer out, EnMember member, Collection<T> value) {
if (value == null) { if (value == null) {
out.writeNull(); out.writeNull();
return; return;
} }
if (value.isEmpty()) { if (value.isEmpty()) {
out.writeArrayB(0); out.writeArrayB(0, componentEncoder, value);
out.writeArrayE(); out.writeArrayE();
return; return;
} }
if (this.encoder == null) { if (this.componentEncoder == null) {
if (!this.inited) { if (!this.inited) {
synchronized (lock) { synchronized (lock) {
try { try {
@@ -72,18 +76,31 @@ public final class CollectionEncoder<T> implements Encodeable<Writer, Collection
} }
} }
} }
out.writeArrayB(value.size()); if (out.writeArrayB(value.size(), componentEncoder, value) < 0) {
boolean first = true; boolean first = true;
for (Object v : value) { for (Object v : value) {
if (!first) out.writeArrayMark(); if (!first) out.writeArrayMark();
encoder.convertTo(out, v); writeValue(out, member, v);
if (first) first = false; if (first) first = false;
}
} }
out.writeArrayE(); out.writeArrayE();
} }
protected void writeValue(Writer out, EnMember member, Object value) {
componentEncoder.convertTo(out, value);
}
@Override @Override
public Type getType() { public Type getType() {
return type; return type;
} }
public Encodeable<Writer, Object> getComponentEncoder() {
return componentEncoder;
}
public Type getComponentType() {
return componentEncoder == null ? null : componentEncoder.getType();
}
} }

View File

@@ -7,7 +7,8 @@ package org.redkale.convert;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.function.Supplier; import java.util.function.*;
import org.redkale.util.Attribute;
/** /**
* 序列化/反序列化操作类 * 序列化/反序列化操作类
@@ -31,8 +32,21 @@ public abstract class Convert<R extends Reader, W extends Writer> {
return this.factory; return this.factory;
} }
protected <S extends W> S configWrite(S writer) {
return writer;
}
protected <S extends W> S fieldFunc(S writer, BiFunction<Attribute, Object, Object> fieldFunc) {
writer.fieldFunc = fieldFunc;
return writer;
}
public abstract Convert<R, W> newConvert(final BiFunction<Attribute, Object, Object> fieldFunc);
public abstract boolean isBinary(); public abstract boolean isBinary();
public abstract <T> T convertFrom(final Type type, final byte[] bytes);
public abstract <T> T convertFrom(final Type type, final ByteBuffer... buffers); public abstract <T> T convertFrom(final Type type, final ByteBuffer... buffers);
public abstract <T> T convertFrom(final Type type, final ConvertMask mask, final ByteBuffer... buffers); public abstract <T> T convertFrom(final Type type, final ConvertMask mask, final ByteBuffer... buffers);

View File

@@ -89,4 +89,9 @@ public final class ConvertColumnEntry {
this.index = index; this.index = index;
} }
@Override
public String toString() {
return "ConvertColumnEntry{" + "index=" + index + ", name=" + name + ", ignore=" + ignore + ", convertType=" + convertType + '}';
}
} }

View File

@@ -45,6 +45,8 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
private final ConcurrentHashMap<String, Class> entitys = new ConcurrentHashMap(); private final ConcurrentHashMap<String, Class> entitys = new ConcurrentHashMap();
private final ConcurrentHashMap<Type, Map<String, SimpledCoder<R, W, ?>>> fieldCoders = new ConcurrentHashMap();
private final ConcurrentHashMap<Type, Decodeable<R, ?>> decoders = new ConcurrentHashMap(); private final ConcurrentHashMap<Type, Decodeable<R, ?>> decoders = new ConcurrentHashMap();
private final ConcurrentHashMap<Type, Encodeable<W, ?>> encoders = new ConcurrentHashMap(); private final ConcurrentHashMap<Type, Encodeable<W, ?>> encoders = new ConcurrentHashMap();
@@ -89,8 +91,11 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
this.register(Number.class, NumberSimpledCoder.instance); this.register(Number.class, NumberSimpledCoder.instance);
this.register(String.class, StringSimpledCoder.instance); this.register(String.class, StringSimpledCoder.instance);
this.register(StringWrapper.class, StringWrapperSimpledCoder.instance);
this.register(CharSequence.class, CharSequenceSimpledCoder.instance); this.register(CharSequence.class, CharSequenceSimpledCoder.instance);
this.register(StringBuilder.class, CharSequenceSimpledCoder.StringBuilderSimpledCoder.instance);
this.register(java.util.Date.class, DateSimpledCoder.instance); this.register(java.util.Date.class, DateSimpledCoder.instance);
this.register(java.time.Duration.class, DurationSimpledCoder.instance);
this.register(AtomicInteger.class, AtomicIntegerSimpledCoder.instance); this.register(AtomicInteger.class, AtomicIntegerSimpledCoder.instance);
this.register(AtomicLong.class, AtomicLongSimpledCoder.instance); this.register(AtomicLong.class, AtomicLongSimpledCoder.instance);
this.register(BigInteger.class, BigIntegerSimpledCoder.instance); this.register(BigInteger.class, BigIntegerSimpledCoder.instance);
@@ -139,10 +144,56 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
public abstract boolean isReversible(); //是否可逆的 public abstract boolean isReversible(); //是否可逆的
public abstract boolean isFieldSort(); //当ConvertColumn.index相同时是否按字段名称排序
public abstract ConvertFactory createChild(); public abstract ConvertFactory createChild();
public abstract ConvertFactory createChild(boolean tiny); public abstract ConvertFactory createChild(boolean tiny);
protected SimpledCoder createEnumSimpledCoder(Class enumClass) {
return new EnumSimpledCoder(enumClass);
}
protected ObjectDecoder createObjectDecoder(Type type) {
return new ObjectDecoder(type);
}
protected ObjectEncoder createObjectEncoder(Type type) {
return new ObjectEncoder(type);
}
protected <E> Decodeable<R, E> createMapDecoder(Type type) {
return new MapDecoder(this, type);
}
protected <E> Encodeable<W, E> createMapEncoder(Type type) {
return new MapEncoder(this, type);
}
protected <E> Decodeable<R, E> createArrayDecoder(Type type) {
return new ArrayDecoder(this, type);
}
protected <E> Encodeable<W, E> createArrayEncoder(Type type) {
return new ArrayEncoder(this, type);
}
protected <E> Decodeable<R, E> createCollectionDecoder(Type type) {
return new CollectionDecoder(this, type);
}
protected <E> Encodeable<W, E> createCollectionEncoder(Type type) {
return new CollectionEncoder(this, type);
}
protected <E> Decodeable<R, E> createStreamDecoder(Type type) {
return new StreamDecoder(this, type);
}
protected <E> Encodeable<W, E> createStreamEncoder(Type type) {
return new StreamEncoder(this, type);
}
public Convert getConvert() { public Convert getConvert() {
return convert; return convert;
} }
@@ -171,15 +222,10 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
return false; return false;
} }
public ConvertColumnEntry findRef(AccessibleObject element) { public ConvertColumnEntry findRef(Class clazz, AccessibleObject element) {
if (element == null) return null; if (element == null) return null;
ConvertColumnEntry en = this.columnEntrys.get(element); ConvertColumnEntry en = this.columnEntrys.get(element);
Set<String> onlyColumns = null; Set<String> onlyColumns = ignoreAlls.get(clazz);
if (element instanceof Method) {
onlyColumns = ignoreAlls.get(((Method) element).getDeclaringClass());
} else if (element instanceof Field) {
onlyColumns = ignoreAlls.get(((Field) element).getDeclaringClass());
}
if (en != null && onlyColumns == null) return en; if (en != null && onlyColumns == null) return en;
final ConvertType ct = this.getConvertType(); final ConvertType ct = this.getConvertType();
ConvertColumn[] ccs = element.getAnnotationsByType(ConvertColumn.class); ConvertColumn[] ccs = element.getAnnotationsByType(ConvertColumn.class);
@@ -206,8 +252,8 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
} }
for (ConvertColumn ref : ccs) { for (ConvertColumn ref : ccs) {
if (ref.type().contains(ct)) { if (ref.type().contains(ct)) {
String realName = ref.name().isEmpty() ? fieldName : ref.name();
if (onlyColumns != null && fieldName != null) { if (onlyColumns != null && fieldName != null) {
String realName = ref.name().isEmpty() ? fieldName : ref.name();
if (!onlyColumns.contains(realName)) return new ConvertColumnEntry(realName, true); if (!onlyColumns.contains(realName)) return new ConvertColumnEntry(realName, true);
} }
ConvertColumnEntry entry = new ConvertColumnEntry(ref); ConvertColumnEntry entry = new ConvertColumnEntry(ref);
@@ -215,7 +261,10 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
entry.setIgnore(false); entry.setIgnore(false);
return entry; return entry;
} }
if (skipIgnores.isEmpty()) return entry; if (skipIgnores.isEmpty()) {
if (onlyColumns != null && realName != null && onlyColumns.contains(realName)) entry.setIgnore(false);
return entry;
}
if (skipIgnores.contains(((Member) element).getDeclaringClass())) entry.setIgnore(false); if (skipIgnores.contains(((Member) element).getDeclaringClass())) entry.setIgnore(false);
return entry; return entry;
} }
@@ -358,37 +407,59 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
} }
} }
public final void registerIgnoreAll(final Class type, Collection<String> excludeColumns) {
Set<String> set = ignoreAlls.get(type);
if (set == null) {
ignoreAlls.put(type, new HashSet<>(excludeColumns));
} else {
set.addAll(new ArrayList(excludeColumns));
}
}
public final void register(final Class type, boolean ignore, String... columns) { public final void register(final Class type, boolean ignore, String... columns) {
for (String column : columns) { for (String column : columns) {
register(type, column, new ConvertColumnEntry(column, ignore)); register(type, column, new ConvertColumnEntry(column, ignore));
} }
} }
public final void register(final Class type, boolean ignore, Collection<String> columns) {
for (String column : columns) {
register(type, column, new ConvertColumnEntry(column, ignore));
}
}
public final boolean register(final Class type, String column, String alias) { public final boolean register(final Class type, String column, String alias) {
return register(type, column, new ConvertColumnEntry(alias)); return register(type, column, new ConvertColumnEntry(alias));
} }
public final boolean register(final Class type, String column, ConvertColumnEntry entry) { public final boolean register(final Class type, String column, ConvertColumnEntry entry) {
if (type == null || column == null || entry == null) return false; if (type == null || column == null || entry == null) return false;
Field field = null;
try { try {
final Field field = type.getDeclaredField(column); field = type.getDeclaredField(column);
String get = "get";
if (field.getType() == boolean.class || field.getType() == Boolean.class) get = "is";
char[] cols = column.toCharArray();
cols[0] = Character.toUpperCase(cols[0]);
String col2 = new String(cols);
try {
register(type.getMethod(get + col2), entry);
} catch (Exception ex) {
}
try {
register(type.getMethod("set" + col2, field.getType()), entry);
} catch (Exception ex) {
}
return register(field, entry);
} catch (Exception e) { } catch (Exception e) {
return false;
} }
String get = "get";
if (field != null && (field.getType() == boolean.class || field.getType() == Boolean.class)) get = "is";
char[] cols = column.toCharArray();
cols[0] = Character.toUpperCase(cols[0]);
final String bigColumn = new String(cols);
try {
register(type.getMethod(get + bigColumn), entry);
} catch (NoSuchMethodException mex) {
if (get.length() >= 3) { //get
try {
register(type.getMethod("is" + bigColumn), entry);
} catch (Exception ex) {
}
}
} catch (Exception ex) {
}
try {
register(type.getMethod("set" + bigColumn, field.getType()), entry);
} catch (Exception ex) {
}
return field == null ? true : register(field, entry);
} }
public final <E> boolean register(final AccessibleObject field, final ConvertColumnEntry entry) { public final <E> boolean register(final AccessibleObject field, final ConvertColumnEntry entry) {
@@ -449,6 +520,29 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
encoders.put(clazz, encoder); encoders.put(clazz, encoder);
} }
//coder = null表示删除该字段的指定SimpledCoder
public final <E> void register(final Class clazz, final String field, final SimpledCoder<R, W, E> coder) {
if (field == null || clazz == null) return;
try {
clazz.getDeclaredField(field);
} catch (Exception e) {
throw new RuntimeException(clazz + " not found field(" + field + ")");
}
if (coder == null) {
Map map = this.fieldCoders.get(clazz);
if (map != null) map.remove(field);
} else {
this.fieldCoders.computeIfAbsent(clazz, c -> new ConcurrentHashMap<>()).put(field, coder);
}
}
public final <E> SimpledCoder<R, W, E> findFieldCoder(final Type clazz, final String field) {
if (field == null) return null;
Map<String, SimpledCoder<R, W, ?>> map = this.fieldCoders.get(clazz);
if (map == null) return parent == null ? null : parent.findFieldCoder(clazz, field);
return (SimpledCoder) map.get(field);
}
public final <E> Decodeable<R, E> findDecoder(final Type type) { public final <E> Decodeable<R, E> findDecoder(final Type type) {
Decodeable<R, E> rs = (Decodeable<R, E>) decoders.get(type); Decodeable<R, E> rs = (Decodeable<R, E>) decoders.get(type);
if (rs != null) return rs; if (rs != null) return rs;
@@ -464,7 +558,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
public final <E> Decodeable<R, E> loadDecoder(final Type type) { public final <E> Decodeable<R, E> loadDecoder(final Type type) {
Decodeable<R, E> decoder = findDecoder(type); Decodeable<R, E> decoder = findDecoder(type);
if (decoder != null) return decoder; if (decoder != null) return decoder;
if (type instanceof GenericArrayType) return new ArrayDecoder(this, type); if (type instanceof GenericArrayType) return createArrayDecoder(type);
Class clazz; Class clazz;
if (type instanceof ParameterizedType) { if (type instanceof ParameterizedType) {
final ParameterizedType pts = (ParameterizedType) type; final ParameterizedType pts = (ParameterizedType) type;
@@ -496,8 +590,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
} else { } else {
throw new ConvertException("not support the type (" + type + ")"); throw new ConvertException("not support the type (" + type + ")");
} }
decoder = findDecoder(clazz); //此处不能再findDecoder否则type与class不一致, 如: RetResult 和 RetResult<Integer>
if (decoder != null) return decoder;
return createDecoder(type, clazz); return createDecoder(type, clazz);
} }
@@ -518,22 +611,23 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
Decodeable<R, E> decoder = null; Decodeable<R, E> decoder = null;
ObjectDecoder od = null; ObjectDecoder od = null;
if (clazz.isEnum()) { if (clazz.isEnum()) {
decoder = new EnumSimpledCoder(clazz); decoder = createEnumSimpledCoder(clazz);
} else if (clazz.isArray()) { } else if (clazz.isArray()) {
decoder = new ArrayDecoder(this, type); decoder = createArrayDecoder(type);
} else if (Collection.class.isAssignableFrom(clazz)) { } else if (Collection.class.isAssignableFrom(clazz)) {
decoder = new CollectionDecoder(this, type); decoder = createCollectionDecoder(type);
} else if (Stream.class.isAssignableFrom(clazz)) { } else if (Stream.class.isAssignableFrom(clazz)) {
decoder = new StreamDecoder(this, type); decoder = createStreamDecoder(type);
} else if (Map.class.isAssignableFrom(clazz)) { } else if (Map.class.isAssignableFrom(clazz)) {
decoder = new MapDecoder(this, type); decoder = createMapDecoder(type);
} else if (Optional.class == clazz) { } else if (Optional.class == clazz) {
decoder = new OptionalCoder(this, type); decoder = new OptionalCoder(this, type);
} else if (clazz == Object.class) { } else if (clazz == Object.class) {
od = new ObjectDecoder(type); od = createObjectDecoder(type);
decoder = od; decoder = od;
} else if (!clazz.getName().startsWith("java.") } else if (!clazz.getName().startsWith("java.")
|| java.net.HttpCookie.class == clazz || java.net.HttpCookie.class == clazz
|| java.util.AbstractMap.SimpleEntry.class == clazz
|| clazz.getName().startsWith("java.awt.geom.Point2D")) { || 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()) {
@@ -550,7 +644,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
} }
} }
if (simpleCoder == null) { if (simpleCoder == null) {
od = new ObjectDecoder(type); od = createObjectDecoder(type);
decoder = od; decoder = od;
} else { } else {
decoder = simpleCoder; decoder = simpleCoder;
@@ -565,7 +659,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
public final <E> Encodeable<W, E> loadEncoder(final Type type) { public final <E> Encodeable<W, E> loadEncoder(final Type type) {
Encodeable<W, E> encoder = findEncoder(type); Encodeable<W, E> encoder = findEncoder(type);
if (encoder != null) return encoder; if (encoder != null) return encoder;
if (type instanceof GenericArrayType) return new ArrayEncoder(this, type); if (type instanceof GenericArrayType) return createArrayEncoder(type);
Class clazz; Class clazz;
if (type instanceof ParameterizedType) { if (type instanceof ParameterizedType) {
final ParameterizedType pts = (ParameterizedType) type; final ParameterizedType pts = (ParameterizedType) type;
@@ -583,8 +677,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
} else { } else {
throw new ConvertException("not support the type (" + type + ")"); throw new ConvertException("not support the type (" + type + ")");
} }
encoder = findEncoder(clazz); //此处不能再findEncoder否则type与class不一致, 如: RetResult 和 RetResult<Integer>
if (encoder != null) return encoder;
return createEncoder(type, clazz); return createEncoder(type, clazz);
} }
@@ -605,20 +698,20 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
Encodeable<W, E> encoder = null; Encodeable<W, E> encoder = null;
ObjectEncoder oe = null; ObjectEncoder oe = null;
if (clazz.isEnum()) { if (clazz.isEnum()) {
encoder = new EnumSimpledCoder(clazz); encoder = createEnumSimpledCoder(clazz);
} else if (clazz.isArray()) { } else if (clazz.isArray()) {
encoder = new ArrayEncoder(this, type); encoder = createArrayEncoder(type);
} else if (Collection.class.isAssignableFrom(clazz)) { } else if (Collection.class.isAssignableFrom(clazz)) {
encoder = new CollectionEncoder(this, type); encoder = createCollectionEncoder(type);
} else if (Stream.class.isAssignableFrom(clazz)) { } else if (Stream.class.isAssignableFrom(clazz)) {
encoder = new StreamEncoder(this, type); encoder = createStreamEncoder(type);
} else if (Map.class.isAssignableFrom(clazz)) { } else if (Map.class.isAssignableFrom(clazz)) {
encoder = new MapEncoder(this, type); encoder = createMapEncoder(type);
} else if (Optional.class == clazz) { } else if (Optional.class == clazz) {
encoder = new OptionalCoder(this, type); encoder = new OptionalCoder(this, type);
} else if (clazz == Object.class) { } else if (clazz == Object.class) {
return (Encodeable<W, E>) this.anyEncoder; return (Encodeable<W, E>) this.anyEncoder;
} else if (!clazz.getName().startsWith("java.") || java.net.HttpCookie.class == clazz) { } else if (!clazz.getName().startsWith("java.") || java.net.HttpCookie.class == clazz || java.util.AbstractMap.SimpleEntry.class == clazz) {
Encodeable simpleCoder = null; Encodeable simpleCoder = null;
for (final Method method : clazz.getDeclaredMethods()) { for (final Method method : clazz.getDeclaredMethods()) {
if (!Modifier.isStatic(method.getModifiers())) continue; if (!Modifier.isStatic(method.getModifiers())) continue;
@@ -634,7 +727,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
} }
} }
if (simpleCoder == null) { if (simpleCoder == null) {
oe = new ObjectEncoder(type); oe = createObjectEncoder(type);
encoder = oe; encoder = oe;
} else { } else {
encoder = simpleCoder; encoder = simpleCoder;

View File

@@ -20,10 +20,12 @@ import org.redkale.util.Attribute;
* @param <F> 字段的数据类型 * @param <F> 字段的数据类型
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class DeMember<R extends Reader, T, F> implements Comparable<DeMember<R, T, F>> { public final class DeMember<R extends Reader, T, F> {
protected int index; protected int index;
protected int position; //从1开始
protected final Attribute<T, F> attribute; protected final Attribute<T, F> attribute;
protected Decodeable<R, F> decoder; protected Decodeable<R, F> decoder;
@@ -70,15 +72,23 @@ public final class DeMember<R extends Reader, T, F> implements Comparable<DeMemb
return this.attribute; return this.attribute;
} }
public Decodeable<R, F> getDecoder() {
return decoder;
}
public int getIndex() { public int getIndex() {
return this.index; return this.index;
} }
@Override public int getPosition() {
public final int compareTo(DeMember<R, T, F> o) { return this.position;
}
public int compareTo(boolean fieldSort, DeMember<R, T, F> o) {
if (o == null) return -1; if (o == null) return -1;
if (this.index != o.index) return (this.index == 0 ? Integer.MAX_VALUE : this.index) - (o.index == 0 ? Integer.MAX_VALUE : o.index); if (this.index != o.index) return (this.index == 0 ? Integer.MAX_VALUE : this.index) - (o.index == 0 ? Integer.MAX_VALUE : o.index);
return this.attribute.field().compareTo(o.attribute.field()); if (this.index != 0) throw new RuntimeException("fields (" + attribute.field() + ", " + o.attribute.field() + ") have same ConvertColumn.index(" + this.index + ") in " + attribute.declaringClass());
return fieldSort ? this.attribute.field().compareTo(o.attribute.field()) : 0;
} }
@Override @Override
@@ -86,7 +96,7 @@ public final class DeMember<R extends Reader, T, F> implements Comparable<DeMemb
if (this == obj) return true; if (this == obj) return true;
if (!(obj instanceof DeMember)) return false; if (!(obj instanceof DeMember)) return false;
DeMember other = (DeMember) obj; DeMember other = (DeMember) obj;
return compareTo(other) == 0; return compareTo(true, other) == 0;
} }
@Override @Override

View File

@@ -20,7 +20,7 @@ import org.redkale.util.Attribute;
* @param <F> 字段的数据类型 * @param <F> 字段的数据类型
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class EnMember<W extends Writer, T, F> implements Comparable<EnMember<W, T, F>> { public final class EnMember<W extends Writer, T, F> {
final Attribute<T, F> attribute; final Attribute<T, F> attribute;
@@ -33,6 +33,8 @@ public final class EnMember<W extends Writer, T, F> implements Comparable<EnMemb
protected int index; protected int index;
protected int position; //从1开始
public EnMember(Attribute<T, F> attribute, Encodeable<W, F> encoder) { public EnMember(Attribute<T, F> attribute, Encodeable<W, F> encoder) {
this.attribute = attribute; this.attribute = attribute;
this.encoder = encoder; this.encoder = encoder;
@@ -63,15 +65,35 @@ public final class EnMember<W extends Writer, T, F> implements Comparable<EnMemb
return attribute.field().equals(name); return attribute.field().equals(name);
} }
public Attribute<T, F> getAttribute() {
return attribute;
}
public Encodeable<W, F> getEncoder() {
return encoder;
}
public boolean isStringType() {
return istring;
}
public boolean isBoolType() {
return isbool;
}
public int getIndex() { public int getIndex() {
return this.index; return this.index;
} }
@Override public int getPosition() {
public final int compareTo(EnMember<W, T, F> o) { return this.position;
}
public int compareTo(boolean fieldSort, EnMember<W, T, F> o) {
if (o == null) return -1; if (o == null) return -1;
if (this.index != o.index) return (this.index == 0 ? Integer.MAX_VALUE : this.index) - (o.index == 0 ? Integer.MAX_VALUE : o.index); if (this.index != o.index) return (this.index == 0 ? Integer.MAX_VALUE : this.index) - (o.index == 0 ? Integer.MAX_VALUE : o.index);
return this.attribute.field().compareTo(o.attribute.field()); if (this.index != 0) throw new RuntimeException("fields (" + attribute.field() + ", " + o.attribute.field() + ") have same ConvertColumn.index(" + this.index + ") in " + attribute.declaringClass());
return fieldSort ? this.attribute.field().compareTo(o.attribute.field()) : 0;
} }
@Override @Override
@@ -79,7 +101,7 @@ public final class EnMember<W extends Writer, T, F> implements Comparable<EnMemb
if (this == obj) return true; if (this == obj) return true;
if (!(obj instanceof EnMember)) return false; if (!(obj instanceof EnMember)) return false;
EnMember other = (EnMember) obj; EnMember other = (EnMember) obj;
return compareTo(other) == 0; return compareTo(true, other) == 0;
} }
@Override @Override

View File

@@ -8,7 +8,7 @@ package org.redkale.convert;
import org.redkale.util.Creator; import org.redkale.util.Creator;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Map; import java.util.*;
/** /**
* Map的反序列化操作类 <br> * Map的反序列化操作类 <br>
@@ -21,13 +21,13 @@ import java.util.Map;
* @param <V> Map value的数据类型 * @param <V> Map value的数据类型
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> { public class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
private final Type type; protected final Type type;
private final Type keyType; protected final Type keyType;
private final Type valueType; protected final Type valueType;
protected Creator<Map<K, V>> creator; protected Creator<Map<K, V>> creator;
@@ -35,14 +35,21 @@ public final class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
protected final Decodeable<Reader, V> valueDecoder; protected final Decodeable<Reader, V> valueDecoder;
private boolean inited = false; protected volatile boolean inited = false;
private final Object lock = new Object(); protected final Object lock = new Object();
public MapDecoder(final ConvertFactory factory, final Type type) { public MapDecoder(final ConvertFactory factory, final Type type) {
this.type = type; this.type = type;
try { try {
if (type instanceof ParameterizedType) { if (type == java.util.Properties.class) {
this.keyType = String.class;
this.valueType = String.class;
this.creator = factory.loadCreator(java.util.Properties.class);
factory.register(type, this);
this.keyDecoder = factory.loadDecoder(String.class);
this.valueDecoder = factory.loadDecoder(String.class);
} else if (type instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) type; final ParameterizedType pt = (ParameterizedType) type;
this.keyType = pt.getActualTypeArguments()[0]; this.keyType = pt.getActualTypeArguments()[0];
this.valueType = pt.getActualTypeArguments()[1]; this.valueType = pt.getActualTypeArguments()[1];
@@ -67,8 +74,26 @@ public final class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
} }
} }
//仅供类似JsonAnyDecoder这种动态创建使用 不得调用 factory.register
public MapDecoder(final ConvertFactory factory, Type type, Type keyType, Type valueType,
Creator<Map<K, V>> creator, final Decodeable<Reader, K> keyDecoder, Decodeable<Reader, V> valueDecoder) {
Objects.requireNonNull(keyDecoder);
Objects.requireNonNull(valueDecoder);
this.type = type;
this.keyType = keyType;
this.valueType = valueType;
this.creator = creator;
this.keyDecoder = keyDecoder;
this.valueDecoder = valueDecoder;
this.inited = true;
}
@Override @Override
public Map<K, V> convertFrom(Reader in) { public Map<K, V> convertFrom(Reader in) {
return convertFrom(in, null);
}
public Map<K, V> convertFrom(Reader in, DeMember member) {
if (this.keyDecoder == null || this.valueDecoder == null) { if (this.keyDecoder == null || this.valueDecoder == null) {
if (!this.inited) { if (!this.inited) {
synchronized (lock) { synchronized (lock) {
@@ -80,31 +105,85 @@ public final class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
} }
} }
} }
final int len = in.readMapB(); byte[] typevals = new byte[2];
int len = in.readMapB(member, typevals, this.keyDecoder, this.valueDecoder);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NULL) return null;
if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = in.readMemberContentLength(member, null);
len = Reader.SIGN_NOLENGTH;
}
final Map<K, V> result = this.creator.create(); final Map<K, V> result = this.creator.create();
boolean first = true;
Decodeable<Reader, K> kdecoder = getKeyDecoder(this.keyDecoder, typevals);
Decodeable<Reader, V> vdecoder = getValueDecoder(this.valueDecoder, typevals);
if (len == Reader.SIGN_NOLENGTH) { if (len == Reader.SIGN_NOLENGTH) {
while (in.hasNext()) { int startPosition = in.position();
K key = keyDecoder.convertFrom(in); while (hasNext(in, member, startPosition, contentLength, first)) {
in.readBlank(); Reader entryReader = getEntryReader(in, member, first);
V value = valueDecoder.convertFrom(in); if (entryReader == null) break;
K key = readKeyMember(entryReader, member, kdecoder, first);
entryReader.readBlank();
V value = readValueMember(entryReader, member, vdecoder, first);
result.put(key, value); result.put(key, value);
first = false;
} }
} else { } else {
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
K key = keyDecoder.convertFrom(in); K key = readKeyMember(in, member, kdecoder, first);
in.readBlank(); in.readBlank();
V value = valueDecoder.convertFrom(in); V value = readValueMember(in, member, vdecoder, first);
result.put(key, value); result.put(key, value);
first = false;
} }
} }
in.readMapE(); in.readMapE();
return result; return result;
} }
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
return in.hasNext(startPosition, contentLength);
}
protected Decodeable<Reader, K> getKeyDecoder(Decodeable<Reader, K> decoder, byte[] typevals) {
return decoder;
}
protected Decodeable<Reader, V> getValueDecoder(Decodeable<Reader, V> decoder, byte[] typevals) {
return decoder;
}
protected Reader getEntryReader(Reader in, DeMember member, boolean first) {
return in;
}
protected K readKeyMember(Reader in, DeMember member, Decodeable<Reader, K> decoder, boolean first) {
return decoder.convertFrom(in);
}
protected V readValueMember(Reader in, DeMember member, Decodeable<Reader, V> decoder, boolean first) {
return decoder.convertFrom(in);
}
@Override @Override
public Type getType() { public Type getType() {
return this.type; return this.type;
} }
public Type getKeyType() {
return keyType;
}
public Type getValueType() {
return valueType;
}
public Decodeable<Reader, K> getKeyDecoder() {
return keyDecoder;
}
public Decodeable<Reader, V> getValueDecoder() {
return valueDecoder;
}
} }

View File

@@ -20,28 +20,28 @@ import java.util.Map;
* @param <V> Map value的数据类型 * @param <V> Map value的数据类型
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> { public class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
private final Type type; protected final Type type;
private final Encodeable<Writer, K> keyencoder; protected final Encodeable<Writer, K> keyEncoder;
private final Encodeable<Writer, V> valencoder; protected final Encodeable<Writer, V> valueEncoder;
private boolean inited = false; protected volatile boolean inited = false;
private final Object lock = new Object(); protected final Object lock = new Object();
public MapEncoder(final ConvertFactory factory, final Type type) { public MapEncoder(final ConvertFactory factory, final Type type) {
this.type = type; this.type = type;
try { try {
if (type instanceof ParameterizedType) { if (type instanceof ParameterizedType) {
final Type[] pt = ((ParameterizedType) type).getActualTypeArguments(); final Type[] pt = ((ParameterizedType) type).getActualTypeArguments();
this.keyencoder = factory.loadEncoder(pt[0]); this.keyEncoder = factory.loadEncoder(pt[0]);
this.valencoder = factory.loadEncoder(pt[1]); this.valueEncoder = factory.loadEncoder(pt[1]);
} else { } else {
this.keyencoder = factory.getAnyEncoder(); this.keyEncoder = factory.getAnyEncoder();
this.valencoder = factory.getAnyEncoder(); this.valueEncoder = factory.getAnyEncoder();
} }
} finally { } finally {
inited = true; inited = true;
@@ -53,13 +53,17 @@ public final class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
@Override @Override
public void convertTo(Writer out, Map<K, V> value) { public void convertTo(Writer out, Map<K, V> value) {
convertTo(out, null, value);
}
public void convertTo(Writer out, EnMember member, Map<K, V> value) {
final Map<K, V> values = value; final Map<K, V> values = value;
if (values == null) { if (values == null) {
out.writeNull(); out.writeNull();
return; return;
} }
if (this.keyencoder == null || this.valencoder == null) { if (this.keyEncoder == null || this.valueEncoder == null) {
if (!this.inited) { if (!this.inited) {
synchronized (lock) { synchronized (lock) {
try { try {
@@ -70,20 +74,42 @@ public final class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
} }
} }
} }
out.writeMapB(values.size()); if (out.writeMapB(values.size(), (Encodeable) keyEncoder, (Encodeable) valueEncoder, value) < 0) {
boolean first = true; boolean first = true;
for (Map.Entry<K, V> en : values.entrySet()) { for (Map.Entry<K, V> en : values.entrySet()) {
if (!first) out.writeArrayMark(); if (!first) out.writeArrayMark();
this.keyencoder.convertTo(out, en.getKey()); writeMemberValue(out, member, en.getKey(), en.getValue(), first);
out.writeMapMark(); if (first) first = false;
this.valencoder.convertTo(out, en.getValue()); }
if (first) first = false;
} }
out.writeMapE(); out.writeMapE();
} }
protected void writeMemberValue(Writer out, EnMember member, K key, V value, boolean first) {
keyEncoder.convertTo(out, key);
out.writeMapMark();
valueEncoder.convertTo(out, value);
}
@Override @Override
public Type getType() { public Type getType() {
return type; return type;
} }
public Type getKeyType() {
return keyEncoder == null ? null : keyEncoder.getType();
}
public Type getValueType() {
return valueEncoder == null ? null : valueEncoder.getType();
}
public Encodeable<Writer, K> getKeyEncoder() {
return keyEncoder;
}
public Encodeable<Writer, V> getValueEncoder() {
return valueEncoder;
}
} }

View File

@@ -7,9 +7,7 @@ package org.redkale.convert;
import org.redkale.util.Creator; import org.redkale.util.Creator;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Arrays; import java.util.*;
import java.util.HashSet;
import java.util.Set;
import org.redkale.util.*; import org.redkale.util.*;
/** /**
@@ -23,7 +21,7 @@ import org.redkale.util.*;
* @param <T> 反解析的数据类型 * @param <T> 反解析的数据类型
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T> { public class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T> {
protected final Type type; protected final Type type;
@@ -33,13 +31,13 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
protected DeMember<R, T, ?>[] creatorConstructorMembers = new DeMember[0]; protected DeMember<R, T, ?>[] creatorConstructorMembers = new DeMember[0];
protected DeMember<R, T, ?>[] members; protected DeMember[] members;
protected ConvertFactory factory; protected ConvertFactory factory;
private boolean inited = false; protected volatile boolean inited = false;
private final Object lock = new Object(); protected final Object lock = new Object();
protected ObjectDecoder(Type type) { protected ObjectDecoder(Type type) {
this.type = ((type instanceof Class) && ((Class) type).isInterface()) ? Object.class : type; this.type = ((type instanceof Class) && ((Class) type).isInterface()) ? Object.class : type;
@@ -63,7 +61,10 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
public void init(final ConvertFactory factory) { public void init(final ConvertFactory factory) {
this.factory = factory; this.factory = factory;
try { try {
if (type == Object.class) return; if (type == Object.class) {
this.creatorConstructorMembers = null;
return;
}
Class clazz = null; Class clazz = null;
if (type instanceof ParameterizedType) { if (type instanceof ParameterizedType) {
@@ -86,17 +87,21 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
this.creator = factory.loadCreator(clazz); this.creator = factory.loadCreator(clazz);
if (this.creator == null) throw new ConvertException("Cannot create a creator for " + clazz); if (this.creator == null) throw new ConvertException("Cannot create a creator for " + clazz);
} }
final Set<DeMember> list = new HashSet(); final Set<DeMember> list = new LinkedHashSet();
final String[] cps = ObjectEncoder.findConstructorProperties(this.creator); final String[] cps = ObjectEncoder.findConstructorProperties(this.creator);
try { try {
ConvertColumnEntry ref; ConvertColumnEntry ref;
for (final Field field : clazz.getFields()) { for (final Field field : clazz.getFields()) {
if (Modifier.isStatic(field.getModifiers())) continue; if (Modifier.isStatic(field.getModifiers())) continue;
if (factory.isConvertDisabled(field)) continue; if (factory.isConvertDisabled(field)) continue;
ref = factory.findRef(field); ref = factory.findRef(clazz, field);
if (ref != null && ref.ignore()) continue; if (ref != null && ref.ignore()) continue;
Type t = TypeToken.createClassType(TypeToken.getGenericType(field.getGenericType(), this.type), this.type); Decodeable<R, ?> fieldCoder = factory.findFieldCoder(clazz, field.getName());
DeMember member = new DeMember(ObjectEncoder.createAttribute(factory, clazz, field, null, null), factory.loadDecoder(t)); if (fieldCoder == null) {
Type t = TypeToken.createClassType(TypeToken.getGenericType(field.getGenericType(), this.type), this.type);
fieldCoder = factory.loadDecoder(t);
}
DeMember member = new DeMember(ObjectEncoder.createAttribute(factory, clazz, field, null, null), fieldCoder);
if (ref != null) member.index = ref.getIndex(); if (ref != null) member.index = ref.getIndex();
list.add(member); list.add(member);
} }
@@ -118,10 +123,15 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
continue; continue;
} }
} }
ref = factory.findRef(method); ref = factory.findRef(clazz, method);
if (ref != null && ref.ignore()) continue; if (ref != null && ref.ignore()) continue;
Type t = TypeToken.createClassType(TypeToken.getGenericType(method.getGenericParameterTypes()[0], this.type), this.type);
DeMember member = new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, null, method), factory.loadDecoder(t)); Decodeable<R, ?> fieldCoder = factory.findFieldCoder(clazz, ConvertFactory.readGetSetFieldName(method));
if (fieldCoder == null) {
Type t = TypeToken.createClassType(TypeToken.getGenericType(method.getGenericParameterTypes()[0], this.type), this.type);
fieldCoder = factory.loadDecoder(t);
}
DeMember member = new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, null, method), fieldCoder);
if (ref != null) member.index = ref.getIndex(); if (ref != null) member.index = ref.getIndex();
list.add(member); list.add(member);
} }
@@ -156,7 +166,20 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
} }
} }
this.members = list.toArray(new DeMember[list.size()]); this.members = list.toArray(new DeMember[list.size()]);
Arrays.sort(this.members); Arrays.sort(this.members, (a, b) -> a.compareTo(factory.isFieldSort(), b));
Set<Integer> pos = new HashSet<>();
for (int i = 0; i < this.members.length; i++) {
if (this.members[i].index > 0) pos.add(this.members[i].index);
}
int pidx = 0;
for (DeMember member : this.members) {
if (member.index > 0) {
member.position = member.index;
} else {
while (pos.contains(++pidx));
member.position = pidx;
}
}
if (cps != null) { if (cps != null) {
final String[] fields = cps; final String[] fields = cps;
@@ -190,7 +213,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
* @return 反解析后的对象结果 * @return 反解析后的对象结果
*/ */
@Override @Override
public final T convertFrom(final R in) { public T convertFrom(final R in) {
final String clazz = in.readObjectB(typeClass); final String clazz = in.readObjectB(typeClass);
if (clazz == null) return null; if (clazz == null) return null;
if (!clazz.isEmpty()) return (T) factory.loadDecoder(factory.getEntityAlias(clazz)).convertFrom(in); if (!clazz.isEmpty()) return (T) factory.loadDecoder(factory.getEntityAlias(clazz)).convertFrom(in);
@@ -209,15 +232,17 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
} }
} }
if (this.creatorConstructorMembers == null) { //空构造函数 if (this.creatorConstructorMembers == null) { //空构造函数
final T result = this.creator.create(); final T result = this.creator == null ? null : this.creator.create();
while (in.hasNext()) { boolean first = true;
while (hasNext(in, first)) {
DeMember member = in.readFieldName(members); DeMember member = in.readFieldName(members);
in.readBlank(); in.readBlank();
if (member == null) { if (member == null) {
in.skipValue(); //跳过不存在的属性的值 in.skipValue(); //跳过不存在的属性的值
} else { } else {
member.read(in, result); readMemberValue(in, member, result, first);
} }
first = false;
} }
in.readObjectE(typeClass); in.readObjectE(typeClass);
return result; return result;
@@ -226,13 +251,14 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
final Object[] constructorParams = new Object[fields.length]; final Object[] constructorParams = new Object[fields.length];
final Object[][] otherParams = new Object[this.members.length][2]; final Object[][] otherParams = new Object[this.members.length][2];
int oc = 0; int oc = 0;
while (in.hasNext()) { boolean first = true;
while (hasNext(in, first)) {
DeMember member = in.readFieldName(members); DeMember member = in.readFieldName(members);
in.readBlank(); in.readBlank();
if (member == null) { if (member == null) {
in.skipValue(); //跳过不存在的属性的值 in.skipValue(); //跳过不存在的属性的值
} else { } else {
Object val = member.read(in); Object val = readMemberValue(in, member, first);
boolean flag = true; boolean flag = true;
for (int i = 0; i < fields.length; i++) { for (int i = 0; i < fields.length; i++) {
if (member == fields[i]) { if (member == fields[i]) {
@@ -242,9 +268,12 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
} }
} }
if (flag) otherParams[oc++] = new Object[]{member.attribute, val}; if (flag) otherParams[oc++] = new Object[]{member.attribute, val};
} }
first = false;
} }
in.readObjectE(typeClass); in.readObjectE(typeClass);
if (this.creator == null) return null;
final T result = this.creator.create(constructorParams); final T result = this.creator.create(constructorParams);
for (int i = 0; i < oc; i++) { for (int i = 0; i < oc; i++) {
((Attribute) otherParams[i][0]).set(result, otherParams[i][1]); ((Attribute) otherParams[i][0]).set(result, otherParams[i][1]);
@@ -253,11 +282,27 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
} }
} }
protected boolean hasNext(R in, boolean first) {
return in.hasNext();
}
protected Object readMemberValue(R in, DeMember member, boolean first) {
return member.read(in);
}
protected void readMemberValue(R in, DeMember member, T result, boolean first) {
member.read(in, result);
}
@Override @Override
public final Type getType() { public Type getType() {
return this.type; return this.type;
} }
public DeMember[] getMembers() {
return Arrays.copyOf(members, members.length);
}
@Override @Override
public String toString() { public String toString() {
return "ObjectDecoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}'; return "ObjectDecoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';

View File

@@ -20,7 +20,7 @@ import org.redkale.util.*;
* @param <T> 序列化的数据类型 * @param <T> 序列化的数据类型
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> { public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
static final Type[] TYPEZERO = new Type[0]; static final Type[] TYPEZERO = new Type[0];
@@ -32,9 +32,9 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
protected ConvertFactory factory; protected ConvertFactory factory;
private boolean inited = false; protected volatile boolean inited = false;
private final Object lock = new Object(); protected final Object lock = new Object();
protected ObjectEncoder(Type type) { protected ObjectEncoder(Type type) {
this.type = type; this.type = type;
@@ -61,7 +61,7 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
if (type == Object.class) return; if (type == Object.class) return;
//if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class"); //if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class");
final Class clazz = this.typeClass; final Class clazz = this.typeClass;
final Set<EnMember> list = new HashSet(); final Set<EnMember> list = new LinkedHashSet();
final boolean reversible = factory.isReversible(); final boolean reversible = factory.isReversible();
Creator creator = null; Creator creator = null;
try { try {
@@ -75,10 +75,14 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
for (final Field field : clazz.getFields()) { for (final Field field : clazz.getFields()) {
if (Modifier.isStatic(field.getModifiers())) continue; if (Modifier.isStatic(field.getModifiers())) continue;
if (factory.isConvertDisabled(field)) continue; if (factory.isConvertDisabled(field)) continue;
ref = factory.findRef(field); ref = factory.findRef(clazz, field);
if (ref != null && ref.ignore()) continue; if (ref != null && ref.ignore()) continue;
Type t = TypeToken.createClassType(TypeToken.getGenericType(field.getGenericType(), this.type), this.type); Encodeable<W, ?> fieldCoder = factory.findFieldCoder(clazz, field.getName());
EnMember member = new EnMember(createAttribute(factory, clazz, field, null, null), factory.loadEncoder(t)); if (fieldCoder == null) {
Type t = TypeToken.createClassType(TypeToken.getGenericType(field.getGenericType(), this.type), this.type);
fieldCoder = factory.loadEncoder(t);
}
EnMember member = new EnMember(createAttribute(factory, clazz, field, null, null), fieldCoder);
if (ref != null) member.index = ref.getIndex(); if (ref != null) member.index = ref.getIndex();
list.add(member); list.add(member);
} }
@@ -100,15 +104,32 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
continue; continue;
} }
} }
ref = factory.findRef(method); ref = factory.findRef(clazz, method);
if (ref != null && ref.ignore()) continue; if (ref != null && ref.ignore()) continue;
Type t = TypeToken.createClassType(TypeToken.getGenericType(method.getGenericReturnType(), this.type), this.type); Encodeable<W, ?> fieldCoder = factory.findFieldCoder(clazz, ConvertFactory.readGetSetFieldName(method));
EnMember member = new EnMember(createAttribute(factory, clazz, null, method, null), factory.loadEncoder(t)); if (fieldCoder == null) {
Type t = TypeToken.createClassType(TypeToken.getGenericType(method.getGenericReturnType(), this.type), this.type);
fieldCoder = factory.loadEncoder(t);
}
EnMember member = new EnMember(createAttribute(factory, clazz, null, method, null), fieldCoder);
if (ref != null) member.index = ref.getIndex(); if (ref != null) member.index = ref.getIndex();
list.add(member); list.add(member);
} }
this.members = list.toArray(new EnMember[list.size()]); this.members = list.toArray(new EnMember[list.size()]);
Arrays.sort(this.members); Arrays.sort(this.members, (a, b) -> a.compareTo(factory.isFieldSort(), b));
Set<Integer> pos = new HashSet<>();
for (int i = 0; i < this.members.length; i++) {
if (this.members[i].index > 0) pos.add(this.members[i].index);
}
int pidx = 0;
for (EnMember member : this.members) {
if (member.index > 0) {
member.position = member.index;
} else {
while (pos.contains(++pidx));
member.position = pidx;
}
}
} catch (Exception ex) { } catch (Exception ex) {
throw new ConvertException(ex); throw new ConvertException(ex);
@@ -122,7 +143,7 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
} }
@Override @Override
public final void convertTo(W out, T value) { public void convertTo(W out, T value) {
if (value == null) { if (value == null) {
out.writeObjectNull(null); out.writeObjectNull(null);
return; return;
@@ -136,24 +157,29 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
} }
} }
} }
if (value.getClass() != this.typeClass) { if (value.getClass() != this.typeClass && !this.type.equals(out.specify())) {
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);
return; return;
} }
out.writeObjectB(value); if (out.writeObjectB(value) < 0) {
for (EnMember member : members) { for (EnMember member : members) {
out.writeObjectField(member, value); out.writeObjectField(member, value);
}
} }
out.writeObjectE(value); out.writeObjectE(value);
} }
@Override @Override
public final Type getType() { public Type getType() {
return this.type; return this.type;
} }
public EnMember[] getMembers() {
return Arrays.copyOf(members, members.length);
}
@Override @Override
public String toString() { public String toString() {
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}'; return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
@@ -227,24 +253,24 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
static Attribute createAttribute(final ConvertFactory factory, Class clazz, final Field field, final Method getter, final Method setter) { static Attribute createAttribute(final ConvertFactory factory, Class clazz, final Field field, final Method getter, final Method setter) {
String fieldalias; String fieldalias;
if (field != null) { // public field if (field != null) { // public field
ConvertColumnEntry ref = factory.findRef(field); ConvertColumnEntry ref = factory.findRef(clazz, field);
fieldalias = ref == null || ref.name().isEmpty() ? field.getName() : ref.name(); fieldalias = ref == null || ref.name().isEmpty() ? field.getName() : ref.name();
} else if (getter != null) { } else if (getter != null) {
ConvertColumnEntry ref = factory.findRef(getter); ConvertColumnEntry ref = factory.findRef(clazz, getter);
String mfieldname = ConvertFactory.readGetSetFieldName(getter); String mfieldname = ConvertFactory.readGetSetFieldName(getter);
if (ref == null) { if (ref == null) {
try { try {
ref = factory.findRef(clazz.getDeclaredField(mfieldname)); ref = factory.findRef(clazz, clazz.getDeclaredField(mfieldname));
} catch (Exception e) { } catch (Exception e) {
} }
} }
fieldalias = ref == null || ref.name().isEmpty() ? mfieldname : ref.name(); fieldalias = ref == null || ref.name().isEmpty() ? mfieldname : ref.name();
} else { // setter != null } else { // setter != null
ConvertColumnEntry ref = factory.findRef(setter); ConvertColumnEntry ref = factory.findRef(clazz, setter);
String mfieldname = ConvertFactory.readGetSetFieldName(setter); String mfieldname = ConvertFactory.readGetSetFieldName(setter);
if (ref == null) { if (ref == null) {
try { try {
ref = factory.findRef(clazz.getDeclaredField(mfieldname)); ref = factory.findRef(clazz, clazz.getDeclaredField(mfieldname));
} catch (Exception e) { } catch (Exception e) {
} }
} }

View File

@@ -30,7 +30,7 @@ public class OptionalCoder<R extends Reader, W extends Writer, T> extends Simple
protected final Encodeable<Writer, T> encoder; protected final Encodeable<Writer, T> encoder;
private boolean inited = false; protected volatile boolean inited = false;
private final Object lock = new Object(); private final Object lock = new Object();

View File

@@ -15,6 +15,10 @@ package org.redkale.convert;
*/ */
public abstract class Reader { public abstract class Reader {
public static enum ValueType {
STRING, ARRAY, MAP;
}
//当前对象字段名的游标 //当前对象字段名的游标
protected int fieldIndex; protected int fieldIndex;
@@ -22,12 +26,46 @@ public abstract class Reader {
public static final short SIGN_NOLENGTH = -2; public static final short SIGN_NOLENGTH = -2;
public static final short SIGN_NOLENBUTBYTES = -3; //目前只适合于protobuf的boolean[]...double[]类型
/** /**
* 是否还存在下个元素或字段 * 是否还存在下个元素或字段 <br>
* 注意: 主要用于Array、Collection、Stream或Map等集合对象
*
* @param startPosition 起始位置
* @param contentLength 内容大小, 不确定的传-1
* *
* @return 是否还存在下个元素或字段 * @return 是否还存在下个元素或字段
*/ */
public abstract boolean hasNext(); public abstract boolean hasNext(int startPosition, int contentLength);
/**
* 是否还存在下个元素或字段
*
*
* @return 是否还存在下个元素或字段
*/
public boolean hasNext() {
return hasNext(-1, -1);
}
/**
* 获取当前位置
*
* @return 当前位置
*/
public abstract int position();
/**
* 读取字段值内容的字节数 <br>
* 只有在readXXXB方法返回SIGN_NOLENBUTBYTES值才会调用此方法
*
* @param member DeMember
* @param decoder Decodeable
*
* @return 内容大小, 不确定返回-1
*/
public abstract int readMemberContentLength(DeMember member, Decodeable decoder);
/** /**
* 跳过值(不包含值前面的字段) * 跳过值(不包含值前面的字段)
@@ -39,6 +77,13 @@ public abstract class Reader {
*/ */
public abstract void readBlank(); public abstract void readBlank();
/**
* 读取下个值的类型
*
* @return ValueType
*/
public abstract ValueType readType();
/** /**
* 读取对象的类名, 返回 null 表示对象为null 返回空字符串表示当前class与返回的class一致返回非空字符串表示class是当前class的子类。 * 读取对象的类名, 返回 null 表示对象为null 返回空字符串表示当前class与返回的class一致返回非空字符串表示class是当前class的子类。
* *
@@ -61,9 +106,13 @@ public abstract class Reader {
/** /**
* 读取数组的开头并返回数组的长度 * 读取数组的开头并返回数组的长度
* *
* @param member DeMember
* @param typevals byte[]
* @param componentDecoder Decodeable
*
* @return 返回数组的长度 * @return 返回数组的长度
*/ */
public abstract int readArrayB(); public abstract int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder);
/** /**
* 读取数组的尾端 * 读取数组的尾端
@@ -74,9 +123,14 @@ public abstract class Reader {
/** /**
* 读取map的开头并返回map的size * 读取map的开头并返回map的size
* *
* @param member DeMember
* @param typevals byte[]
* @param keyDecoder Decodeable
* @param valueDecoder Decodeable
*
* @return 返回map的size * @return 返回map的size
*/ */
public abstract int readMapB(); public abstract int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder);
/** /**
* 读取数组的尾端 * 读取数组的尾端
@@ -107,6 +161,13 @@ public abstract class Reader {
*/ */
public abstract byte readByte(); public abstract byte readByte();
/**
* 读取byte[]
*
* @return byte[]
*/
public abstract byte[] readByteArray();
/** /**
* 读取一个char值 * 读取一个char值
* *

View File

@@ -22,7 +22,7 @@ import java.lang.reflect.Type;
*/ */
public abstract class SimpledCoder<R extends Reader, W extends Writer, T> implements Decodeable<R, T>, Encodeable<W, T> { public abstract class SimpledCoder<R extends Reader, W extends Writer, T> implements Decodeable<R, T>, Encodeable<W, T> {
private Type type; protected Type type;
@Override @Override
public abstract void convertTo(final W out, final T value); public abstract void convertTo(final W out, final T value);

View File

@@ -22,19 +22,19 @@ import java.util.stream.Stream;
* @param <T> 反解析的集合元素类型 * @param <T> 反解析的集合元素类型
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class StreamDecoder<T> implements Decodeable<Reader, Stream<T>> { public class StreamDecoder<T> implements Decodeable<Reader, Stream<T>> {
private final Type type; protected final Type type;
private final Type componentType; protected final Type componentType;
protected Creator<Stream<T>> creator; protected Creator<Stream<T>> creator;
protected final Decodeable<Reader, T> decoder; protected final Decodeable<Reader, T> componentDecoder;
private boolean inited = false; protected volatile boolean inited = false;
private final Object lock = new Object(); protected final Object lock = new Object();
public StreamDecoder(final ConvertFactory factory, final Type type) { public StreamDecoder(final ConvertFactory factory, final Type type) {
this.type = type; this.type = type;
@@ -44,7 +44,7 @@ public final class StreamDecoder<T> implements Decodeable<Reader, Stream<T>> {
this.componentType = pt.getActualTypeArguments()[0]; this.componentType = pt.getActualTypeArguments()[0];
this.creator = factory.loadCreator((Class) pt.getRawType()); this.creator = factory.loadCreator((Class) pt.getRawType());
factory.register(type, this); factory.register(type, this);
this.decoder = factory.loadDecoder(this.componentType); this.componentDecoder = factory.loadDecoder(this.componentType);
} else { } else {
throw new ConvertException("StreamDecoder not support the type (" + type + ")"); throw new ConvertException("StreamDecoder not support the type (" + type + ")");
} }
@@ -58,9 +58,19 @@ public final class StreamDecoder<T> implements Decodeable<Reader, Stream<T>> {
@Override @Override
public Stream<T> convertFrom(Reader in) { public Stream<T> convertFrom(Reader in) {
final int len = in.readArrayB(); return convertFrom(in, null);
}
public Stream<T> convertFrom(Reader in, DeMember member) {
byte[] typevals = new byte[1];
int len = in.readArrayB(member, typevals, this.componentDecoder);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NULL) return null;
if (this.decoder == null) { if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = in.readMemberContentLength(member, this.componentDecoder);
len = Reader.SIGN_NOLENGTH;
}
if (this.componentDecoder == null) {
if (!this.inited) { if (!this.inited) {
synchronized (lock) { synchronized (lock) {
try { try {
@@ -71,11 +81,16 @@ public final class StreamDecoder<T> implements Decodeable<Reader, Stream<T>> {
} }
} }
} }
final Decodeable<Reader, T> localdecoder = this.decoder; final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
final List<T> result = new ArrayList(); final List<T> result = new ArrayList();
boolean first = true;
if (len == Reader.SIGN_NOLENGTH) { if (len == Reader.SIGN_NOLENGTH) {
while (in.hasNext()) { int startPosition = in.position();
result.add(localdecoder.convertFrom(in)); while (hasNext(in, member, startPosition, contentLength, first)) {
Reader itemReader = getItemReader(in, member, first);
if (itemReader == null) break;
result.add(readMemberValue(itemReader, member, localdecoder, first));
first = false;
} }
} else { } else {
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
@@ -86,9 +101,33 @@ public final class StreamDecoder<T> implements Decodeable<Reader, Stream<T>> {
return result.stream(); return result.stream();
} }
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
return in.hasNext(startPosition, contentLength);
}
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
return decoder;
}
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
return in;
}
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
return decoder.convertFrom(in);
}
@Override @Override
public Type getType() { public Type getType() {
return type; return type;
} }
public Type getComponentType() {
return componentType;
}
public Decodeable<Reader, T> getComponentDecoder() {
return componentDecoder;
}
} }

View File

@@ -19,15 +19,15 @@ import java.util.stream.Stream;
* @param <T> 序列化的集合元素类型 * @param <T> 序列化的集合元素类型
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class StreamEncoder<T> implements Encodeable<Writer, Stream<T>> { public class StreamEncoder<T> implements Encodeable<Writer, Stream<T>> {
private final Type type; protected final Type type;
private final Encodeable<Writer, Object> encoder; protected final Encodeable<Writer, Object> componentEncoder;
private boolean inited = false; protected volatile boolean inited = false;
private final Object lock = new Object(); protected final Object lock = new Object();
public StreamEncoder(final ConvertFactory factory, final Type type) { public StreamEncoder(final ConvertFactory factory, final Type type) {
this.type = type; this.type = type;
@@ -35,12 +35,12 @@ public final class StreamEncoder<T> implements Encodeable<Writer, Stream<T>> {
if (type instanceof ParameterizedType) { if (type instanceof ParameterizedType) {
Type t = ((ParameterizedType) type).getActualTypeArguments()[0]; Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
if (t instanceof TypeVariable) { if (t instanceof TypeVariable) {
this.encoder = factory.getAnyEncoder(); this.componentEncoder = factory.getAnyEncoder();
} else { } else {
this.encoder = factory.loadEncoder(t); this.componentEncoder = factory.loadEncoder(t);
} }
} else { } else {
this.encoder = factory.getAnyEncoder(); this.componentEncoder = factory.getAnyEncoder();
} }
} finally { } finally {
inited = true; inited = true;
@@ -52,17 +52,21 @@ public final class StreamEncoder<T> implements Encodeable<Writer, Stream<T>> {
@Override @Override
public void convertTo(Writer out, Stream<T> value) { public void convertTo(Writer out, Stream<T> value) {
convertTo(out, null, value);
}
public void convertTo(Writer out, EnMember member, Stream<T> value) {
if (value == null) { if (value == null) {
out.writeNull(); out.writeNull();
return; return;
} }
Object[] array = value.toArray(); Object[] array = value.toArray();
if (array.length == 0) { if (array.length == 0) {
out.writeArrayB(0); out.writeArrayB(0, componentEncoder, array);
out.writeArrayE(); out.writeArrayE();
return; return;
} }
if (this.encoder == null) { if (this.componentEncoder == null) {
if (!this.inited) { if (!this.inited) {
synchronized (lock) { synchronized (lock) {
try { try {
@@ -73,18 +77,31 @@ public final class StreamEncoder<T> implements Encodeable<Writer, Stream<T>> {
} }
} }
} }
out.writeArrayB(array.length); if (out.writeArrayB(array.length, componentEncoder, array) < 0) {
boolean first = true; boolean first = true;
for (Object v : array) { for (Object v : array) {
if (!first) out.writeArrayMark(); if (!first) out.writeArrayMark();
encoder.convertTo(out, v); writeMemberValue(out, member, v, first);
if (first) first = false; if (first) first = false;
}
} }
out.writeArrayE(); out.writeArrayE();
} }
protected void writeMemberValue(Writer out, EnMember member, Object value, boolean first) {
componentEncoder.convertTo(out, value);
}
@Override @Override
public Type getType() { public Type getType() {
return type; return type;
} }
public Encodeable<Writer, Object> getComponentEncoder() {
return componentEncoder;
}
public Type getComponentType() {
return componentEncoder == null ? null : componentEncoder.getType();
}
} }

View File

@@ -5,7 +5,9 @@
*/ */
package org.redkale.convert; package org.redkale.convert;
import org.redkale.util.Attribute; import java.lang.reflect.*;
import java.util.function.BiFunction;
import org.redkale.util.*;
/** /**
* 序列化的数据输出流 * 序列化的数据输出流
@@ -20,6 +22,41 @@ public abstract class Writer {
//当前对象输出字段名之前是否需要分隔符, JSON字段间的分隔符为,逗号 //当前对象输出字段名之前是否需要分隔符, JSON字段间的分隔符为,逗号
protected boolean comma; protected boolean comma;
//convertTo时是否以指定Type的ObjectEncoder进行处理
protected Type specify;
//对某个字段值进行动态处理
protected BiFunction<Attribute, Object, Object> fieldFunc;
/**
* 设置specify
*
* @param value Type
*/
public void specify(Type value) {
if (value instanceof GenericArrayType) {
this.specify = ((GenericArrayType) value).getGenericComponentType();
} else if (value instanceof Class && ((Class) value).isArray()) {
this.specify = ((Class) value).getComponentType();
} else {
this.specify = value;
}
}
protected boolean recycle() {
this.fieldFunc = null;
return true;
}
/**
* 返回specify
*
* @return int
*/
public Type specify() {
return this.specify;
}
/** /**
* 当tiny=true时 字符串为空、boolean为false的字段值都会被跳过 不会输出。 * 当tiny=true时 字符串为空、boolean为false的字段值都会被跳过 不会输出。
* *
@@ -51,9 +88,12 @@ public abstract class Writer {
* 注: 覆盖此方法必须要先调用父方法 super.writeObjectB(obj); * 注: 覆盖此方法必须要先调用父方法 super.writeObjectB(obj);
* *
* @param obj 写入的对象 * @param obj 写入的对象
*
* @return 返回-1表示还没有写入对象内容大于-1表示已写入对象内容返回对象内容大小
*/ */
public void writeObjectB(Object obj) { public int writeObjectB(Object obj) {
this.comma = false; this.comma = false;
return -1;
} }
/** /**
@@ -74,8 +114,13 @@ public abstract class Writer {
* @param obj 写入的对象 * @param obj 写入的对象
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final void writeObjectField(final EnMember member, Object obj) { public void writeObjectField(final EnMember member, Object obj) {
Object value = member.attribute.get(obj); Object value;
if (fieldFunc == null) {
value = member.attribute.get(obj);
} else {
value = fieldFunc.apply(member.attribute, obj);
}
if (value == null) return; if (value == null) return;
if (tiny()) { if (tiny()) {
if (member.istring) { if (member.istring) {
@@ -84,7 +129,7 @@ public abstract class Writer {
if (!((Boolean) value)) return; if (!((Boolean) value)) return;
} }
} }
this.writeFieldName(member.attribute); this.writeFieldName(member);
member.encoder.convertTo(this, value); member.encoder.convertTo(this, value);
this.comma = true; this.comma = true;
} }
@@ -99,9 +144,13 @@ public abstract class Writer {
/** /**
* 输出一个数组前的操作 * 输出一个数组前的操作
* *
* @param size 数组长度 * @param size 数组长度
* @param componentEncoder Encodeable
* @param obj 对象, 不一定是数组、Collection对象也可能是伪Collection对象
*
* @return 返回-1表示还没有写入对象内容大于-1表示已写入对象内容返回对象内容大小
*/ */
public abstract void writeArrayB(int size); public abstract int writeArrayB(int size, Encodeable<Writer, Object> componentEncoder, Object obj);
/** /**
* 输出数组元素间的间隔符 * 输出数组元素间的间隔符
@@ -118,9 +167,14 @@ public abstract class Writer {
/** /**
* 输出一个Map前的操作 * 输出一个Map前的操作
* *
* @param size map大小 * @param size map大小
* @param keyEncoder Encodeable
* @param valueEncoder Encodeable
* @param obj 对象, 不一定是Map对象也可能是伪Map对象
*
* @return 返回-1表示还没有写入对象内容大于-1表示已写入对象内容返回对象内容大小
*/ */
public abstract void writeMapB(int size); public abstract int writeMapB(int size, Encodeable<Writer, Object> keyEncoder, Encodeable<Writer, Object> valueEncoder, Object obj);
/** /**
* 输出一个Map中key与value间的间隔符 * 输出一个Map中key与value间的间隔符
@@ -137,9 +191,9 @@ public abstract class Writer {
/** /**
* 输出一个字段名 * 输出一个字段名
* *
* @param attribute 字段的Attribute对象 * @param member 字段的EnMember对象
*/ */
public abstract void writeFieldName(Attribute attribute); public abstract void writeFieldName(EnMember member);
/** /**
* 写入一个boolean值 * 写入一个boolean值
@@ -155,6 +209,13 @@ public abstract class Writer {
*/ */
public abstract void writeByte(byte value); public abstract void writeByte(byte value);
/**
* 写入byte[]
*
* @param values byte[]
*/
public abstract void writeByteArray(byte[] values);
/** /**
* 写入一个char值 * 写入一个char值
* *
@@ -210,4 +271,11 @@ public abstract class Writer {
* @param value String值 * @param value String值
*/ */
public abstract void writeString(String value); public abstract void writeString(String value);
/**
* 写入一个StringConvertWrapper值
*
* @param value StringConvertWrapper值
*/
public abstract void writeWrapper(StringWrapper value);
} }

View File

@@ -8,6 +8,7 @@ package org.redkale.convert.bson;
import java.nio.*; import java.nio.*;
import org.redkale.convert.*; import org.redkale.convert.*;
import static org.redkale.convert.Reader.SIGN_NULL; import static org.redkale.convert.Reader.SIGN_NULL;
import org.redkale.convert.ext.ByteSimpledCoder;
import org.redkale.util.*; import org.redkale.util.*;
/** /**
@@ -48,16 +49,38 @@ public class BsonByteBufferReader extends BsonReader {
return mask == null ? currentBuffer.get(currentBuffer.position()) : mask.unmask(currentBuffer.get(currentBuffer.position())); return mask == null ? currentBuffer.get(currentBuffer.position()) : mask.unmask(currentBuffer.get(currentBuffer.position()));
} }
@Override
public int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder) {
short bt = readShort();
if (bt == Reader.SIGN_NULL) return bt;
short lt = readShort();
byte kt = readByte();
byte vt = readByte();
if (typevals != null) {
typevals[0] = kt;
typevals[1] = vt;
}
return (bt & 0xffff) << 16 | (lt & 0xffff);
}
/** /**
* 判断下一个非空白字节是否为[ * 判断下一个非空白字节是否为[
* *
* @param member DeMember
* @param typevals byte[]
* @param componentDecoder Decodeable
*
* @return 数组长度或 SIGN_NULL * @return 数组长度或 SIGN_NULL
*/ */
@Override @Override
public final int readArrayB() { public final int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder) {
short bt = readShort(); short bt = readShort();
if (bt == Reader.SIGN_NULL) return bt; if (bt == Reader.SIGN_NULL) return bt;
short lt = readShort(); short lt = readShort();
if (componentDecoder != null && componentDecoder != ByteSimpledCoder.instance) {
byte comval = readByte();
if (typevals != null) typevals[0] = comval;
}
return (bt & 0xffff) << 16 | (lt & 0xffff); return (bt & 0xffff) << 16 | (lt & 0xffff);
} }
//------------------------------------------------------------ //------------------------------------------------------------

View File

@@ -131,7 +131,9 @@ public class BsonByteBufferWriter extends BsonWriter {
@Override @Override
protected boolean recycle() { protected boolean recycle() {
super.recycle();
this.index = 0; this.index = 0;
this.specify = null;
this.buffers = null; this.buffers = null;
return false; return false;
} }

View File

@@ -37,7 +37,7 @@ import org.redkale.util.*;
* *
* @author zhangjx * @author zhangjx
*/ */
public final class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> { public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
private static final ObjectPool<BsonReader> readerPool = BsonReader.createPool(Integer.getInteger("convert.bson.pool.size", 16)); private static final ObjectPool<BsonReader> readerPool = BsonReader.createPool(Integer.getInteger("convert.bson.pool.size", 16));
@@ -59,6 +59,16 @@ public final class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
return BsonFactory.root().getConvert(); return BsonFactory.root().getConvert();
} }
@Override
public BsonConvert newConvert(final BiFunction<Attribute, Object, Object> fieldFunc) {
return new BsonConvert(getFactory(), tiny) {
@Override
protected <S extends BsonWriter> S configWrite(S writer) {
return fieldFunc(writer, fieldFunc);
}
};
}
//------------------------------ reader ----------------------------------------------------------- //------------------------------ reader -----------------------------------------------------------
public BsonReader pollBsonReader(final ByteBuffer... buffers) { public BsonReader pollBsonReader(final ByteBuffer... buffers) {
return new BsonByteBufferReader((ConvertMask) null, buffers); return new BsonByteBufferReader((ConvertMask) null, buffers);
@@ -78,11 +88,11 @@ public final class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
//------------------------------ writer ----------------------------------------------------------- //------------------------------ writer -----------------------------------------------------------
public BsonByteBufferWriter pollBsonWriter(final Supplier<ByteBuffer> supplier) { public BsonByteBufferWriter pollBsonWriter(final Supplier<ByteBuffer> supplier) {
return new BsonByteBufferWriter(tiny, supplier); return configWrite(new BsonByteBufferWriter(tiny, supplier));
} }
public BsonWriter pollBsonWriter(final OutputStream out) { public BsonWriter pollBsonWriter(final OutputStream out) {
return new BsonStreamWriter(tiny, out); return configWrite(new BsonStreamWriter(tiny, out));
} }
public BsonWriter pollBsonWriter() { public BsonWriter pollBsonWriter() {
@@ -94,6 +104,7 @@ public final class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
} }
//------------------------------ convertFrom ----------------------------------------------------------- //------------------------------ convertFrom -----------------------------------------------------------
@Override
public <T> T convertFrom(final Type type, final byte[] bytes) { public <T> T convertFrom(final Type type, final byte[] bytes) {
if (bytes == null) return null; if (bytes == null) return null;
return convertFrom(type, bytes, 0, bytes.length); return convertFrom(type, bytes, 0, bytes.length);
@@ -173,33 +184,33 @@ public final class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
public void convertTo(final OutputStream out, final Object value) { public void convertTo(final OutputStream out, final Object value) {
if (value == null) { if (value == null) {
new BsonStreamWriter(tiny, out).writeNull(); pollBsonWriter(out).writeNull();
} else { } else {
factory.loadEncoder(value.getClass()).convertTo(new BsonStreamWriter(tiny, out), value); factory.loadEncoder(value.getClass()).convertTo(pollBsonWriter(out), value);
} }
} }
public void convertTo(final OutputStream out, final Type type, final Object value) { public void convertTo(final OutputStream out, final Type type, final Object value) {
if (type == null) return; if (type == null) return;
if (value == null) { if (value == null) {
new BsonStreamWriter(tiny, out).writeNull(); pollBsonWriter(out).writeNull();
} else { } else {
factory.loadEncoder(type).convertTo(new BsonStreamWriter(tiny, out), value); factory.loadEncoder(type).convertTo(pollBsonWriter(out), value);
} }
} }
public void convertMapTo(final OutputStream out, final Object... values) { public void convertMapTo(final OutputStream out, final Object... values) {
if (values == null) { if (values == null) {
new BsonStreamWriter(tiny, out).writeNull(); pollBsonWriter(out).writeNull();
} else { } else {
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(new BsonStreamWriter(tiny, out), values); ((AnyEncoder) factory.getAnyEncoder()).convertMapTo(pollBsonWriter(out), values);
} }
} }
@Override @Override
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Object value) { public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Object value) {
if (supplier == null) return null; if (supplier == null) return null;
BsonByteBufferWriter out = new BsonByteBufferWriter(tiny, supplier); BsonByteBufferWriter out = pollBsonWriter(supplier);
if (value == null) { if (value == null) {
out.writeNull(); out.writeNull();
} else { } else {
@@ -211,7 +222,7 @@ public final class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
@Override @Override
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value) { public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value) {
if (supplier == null || type == null) return null; if (supplier == null || type == null) return null;
BsonByteBufferWriter out = new BsonByteBufferWriter(tiny, supplier); BsonByteBufferWriter out = pollBsonWriter(supplier);
if (value == null) { if (value == null) {
out.writeNull(); out.writeNull();
} else { } else {
@@ -223,7 +234,7 @@ public final class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
@Override @Override
public ByteBuffer[] convertMapTo(final Supplier<ByteBuffer> supplier, final Object... values) { public ByteBuffer[] convertMapTo(final Supplier<ByteBuffer> supplier, final Object... values) {
if (supplier == null) return null; if (supplier == null) return null;
BsonByteBufferWriter out = new BsonByteBufferWriter(tiny, supplier); BsonByteBufferWriter out = pollBsonWriter(supplier);
if (values == null) { if (values == null) {
out.writeNull(); out.writeNull();
} else { } else {

View File

@@ -6,8 +6,12 @@
package org.redkale.convert.bson; package org.redkale.convert.bson;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Type;
import java.util.*;
import java.util.stream.Stream;
import org.redkale.convert.*; import org.redkale.convert.*;
import org.redkale.util.AnyValue; import org.redkale.convert.ext.*;
import org.redkale.util.*;
/** /**
* BSON的ConvertFactory * BSON的ConvertFactory
@@ -26,6 +30,16 @@ public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
static final Encodeable objectEncoder = instance.loadEncoder(Object.class); static final Encodeable objectEncoder = instance.loadEncoder(Object.class);
static final Decodeable skipArrayDecoder = new SkipArrayDecoder(instance, Object[].class);
static final Decodeable skipCollectionDecoder = new SkipCollectionDecoder(instance, new TypeToken<Collection<Object>>() {
}.getType());
static final Decodeable skipStreamDecoder = new SkipStreamDecoder(instance, new TypeToken<Stream<Object>>() {
}.getType());
static final Decodeable skipMapDecoder = new SkipMapDecoder(instance, Map.class);
static { static {
instance.register(Serializable.class, objectDecoder); instance.register(Serializable.class, objectDecoder);
instance.register(Serializable.class, objectEncoder); instance.register(Serializable.class, objectEncoder);
@@ -84,4 +98,115 @@ public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
return true; return true;
} }
@Override
public boolean isFieldSort() {
return true;
}
protected static byte typeEnum(final Type type) {
return typeEnum(TypeToken.typeToClass(type));
}
protected static byte typeEnum(final Class type) {
Objects.requireNonNull(type);
byte typeval = 127; //字段的类型值
if (type == boolean.class || type == Boolean.class) {
typeval = 11;
} else if (type == byte.class || type == Byte.class) {
typeval = 12;
} else if (type == short.class || type == Short.class) {
typeval = 13;
} else if (type == char.class || type == Character.class) {
typeval = 14;
} else if (type == int.class || type == Integer.class) {
typeval = 15;
} else if (type == long.class || type == Long.class) {
typeval = 16;
} else if (type == float.class || type == Float.class) {
typeval = 17;
} else if (type == double.class || type == Double.class) {
typeval = 18;
} else if (type == String.class) {
typeval = 19;
} else if (type == boolean[].class || type == Boolean[].class) {
typeval = 21;
} else if (type == byte[].class || type == Byte[].class) {
typeval = 22;
} else if (type == short[].class || type == Short[].class) {
typeval = 23;
} else if (type == char[].class || type == Character[].class) {
typeval = 24;
} else if (type == int[].class || type == Integer[].class) {
typeval = 25;
} else if (type == long[].class || type == Long[].class) {
typeval = 26;
} else if (type == float[].class || type == Float[].class) {
typeval = 27;
} else if (type == double[].class || type == Double[].class) {
typeval = 28;
} else if (type == String[].class) {
typeval = 29;
} else if (type.isArray()) {
typeval = 81;
} else if (Collection.class.isAssignableFrom(type)) {
typeval = 82;
} else if (Stream.class.isAssignableFrom(type)) {
typeval = 83;
} else if (Map.class.isAssignableFrom(type)) {
typeval = 84;
}
return typeval;
}
protected static Decodeable typeEnum(final byte typeval) {
switch (typeval) {
case 11:
return BoolSimpledCoder.instance;
case 12:
return ByteSimpledCoder.instance;
case 13:
return ShortSimpledCoder.instance;
case 14:
return CharSimpledCoder.instance;
case 15:
return IntSimpledCoder.instance;
case 16:
return LongSimpledCoder.instance;
case 17:
return FloatSimpledCoder.instance;
case 18:
return DoubleSimpledCoder.instance;
case 19:
return StringSimpledCoder.instance;
case 21:
return BoolArraySimpledCoder.instance;
case 22:
return ByteArraySimpledCoder.instance;
case 23:
return ShortArraySimpledCoder.instance;
case 24:
return CharArraySimpledCoder.instance;
case 25:
return IntArraySimpledCoder.instance;
case 26:
return LongArraySimpledCoder.instance;
case 27:
return FloatArraySimpledCoder.instance;
case 28:
return DoubleArraySimpledCoder.instance;
case 29:
return StringArraySimpledCoder.instance;
case 81:
return skipArrayDecoder;
case 82:
return skipCollectionDecoder;
case 83:
return skipStreamDecoder;
case 84:
return skipMapDecoder;
case 127:
return BsonFactory.objectDecoder;
}
return null;
}
} }

View File

@@ -93,53 +93,27 @@ public class BsonReader extends Reader {
final byte val = this.typeval; final byte val = this.typeval;
this.typeval = 0; this.typeval = 0;
switch (val) { switch (val) {
case 1: readBoolean(); case 11: readBoolean();
break; break;
case 2: readByte(); case 12: readByte();
break; break;
case 3: readShort(); case 13: readShort();
break; break;
case 4: readChar(); case 14: readChar();
break; break;
case 5: readInt(); case 15: readInt();
break; break;
case 6: readLong(); case 16: readLong();
break; break;
case 7: readFloat(); case 17: readFloat();
break; break;
case 8: readDouble(); case 18: readDouble();
break; break;
case 9: readString(); case 19: readString();
break; break;
case 101: default:
BoolArraySimpledCoder.instance.convertFrom(this); Decodeable decoder = BsonFactory.typeEnum(val);
break; if (decoder != null) decoder.convertFrom(this);
case 102:
ByteArraySimpledCoder.instance.convertFrom(this);
break;
case 103:
ShortArraySimpledCoder.instance.convertFrom(this);
break;
case 104:
CharArraySimpledCoder.instance.convertFrom(this);
break;
case 105:
IntArraySimpledCoder.instance.convertFrom(this);
break;
case 106:
LongArraySimpledCoder.instance.convertFrom(this);
break;
case 107:
FloatArraySimpledCoder.instance.convertFrom(this);
break;
case 108:
DoubleArraySimpledCoder.instance.convertFrom(this);
break;
case 109:
StringArraySimpledCoder.instance.convertFrom(this);
break;
case 127:
BsonFactory.objectDecoder.convertFrom(this);
break; break;
} }
} }
@@ -171,8 +145,17 @@ public class BsonReader extends Reader {
} }
@Override @Override
public final int readMapB() { public int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder) {
return readArrayB(); short bt = readShort();
if (bt == Reader.SIGN_NULL) return bt;
int rs = (bt & 0xffff) << 16 | ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
byte kt = readByte();
byte vt = readByte();
if (typevals != null) {
typevals[0] = kt;
typevals[1] = vt;
}
return rs;
} }
@Override @Override
@@ -185,10 +168,15 @@ public class BsonReader extends Reader {
* @return 数组长度或SIGN_NULL * @return 数组长度或SIGN_NULL
*/ */
@Override @Override
public int readArrayB() { public int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder) { //componentDecoder可能为null
short bt = readShort(); short bt = readShort();
if (bt == Reader.SIGN_NULL) return bt; if (bt == Reader.SIGN_NULL) return bt;
return (bt & 0xffff) << 16 | ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff); int rs = (bt & 0xffff) << 16 | ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
if (componentDecoder != null && componentDecoder != ByteSimpledCoder.instance) {
byte comval = readByte();
if (typevals != null) typevals[0] = comval;
}
return rs;
} }
@Override @Override
@@ -202,13 +190,26 @@ public class BsonReader extends Reader {
public final void readBlank() { public final void readBlank() {
} }
@Override
public int position() {
return this.position;
}
@Override
public int readMemberContentLength(DeMember member, Decodeable decoder) {
return -1;
}
/** /**
* 判断对象是否存在下一个属性或者数组是否存在下一个元素 * 判断对象是否存在下一个属性或者数组是否存在下一个元素
* *
* @param startPosition 起始位置
* @param contentLength 内容大小, 不确定的传-1
*
* @return 是否存在 * @return 是否存在
*/ */
@Override @Override
public final boolean hasNext() { public boolean hasNext(int startPosition, int contentLength) {
byte b = readByte(); byte b = readByte();
if (b == SIGN_HASNEXT) return true; if (b == SIGN_HASNEXT) return true;
if (b != SIGN_NONEXT) throw new ConvertException("hasNext option must be (" + (SIGN_HASNEXT) if (b != SIGN_NONEXT) throw new ConvertException("hasNext option must be (" + (SIGN_HASNEXT)
@@ -248,6 +249,41 @@ public class BsonReader extends Reader {
return content[++this.position]; return content[++this.position];
} }
@Override
public final byte[] readByteArray() {
int len = readArrayB(null, null, null);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null;
if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = readMemberContentLength(null, null);
len = Reader.SIGN_NOLENGTH;
}
if (len == Reader.SIGN_NOLENGTH) {
int size = 0;
byte[] data = new byte[8];
int startPosition = position();
while (hasNext(startPosition, contentLength)) {
if (size >= data.length) {
byte[] newdata = new byte[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size);
data = newdata;
}
data[size++] = readByte();
}
readArrayE();
byte[] newdata = new byte[size];
System.arraycopy(data, 0, newdata, 0, size);
return newdata;
} else {
byte[] values = new byte[len];
for (int i = 0; i < values.length; i++) {
values[i] = readByte();
}
readArrayE();
return values;
}
}
@Override @Override
public char readChar() { public char readChar() {
return (char) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position])); return (char) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position]));
@@ -310,4 +346,9 @@ public class BsonReader extends Reader {
return value; return value;
} }
@Override
public ValueType readType() {
throw new UnsupportedOperationException("Not supported yet.");
}
} }

View File

@@ -7,6 +7,7 @@ package org.redkale.convert.bson;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.redkale.convert.*; import org.redkale.convert.*;
import org.redkale.convert.ext.ByteSimpledCoder;
import org.redkale.util.*; import org.redkale.util.*;
/** /**
@@ -96,8 +97,11 @@ public class BsonWriter extends Writer {
count += len; count += len;
} }
@Override
protected boolean recycle() { protected boolean recycle() {
super.recycle();
this.count = 0; this.count = 0;
this.specify = null;
if (this.content.length > defaultSize) { if (this.content.length > defaultSize) {
this.content = new byte[defaultSize]; this.content = new byte[defaultSize];
} }
@@ -124,6 +128,22 @@ public class BsonWriter extends Writer {
writeTo(value); writeTo(value);
} }
@Override
public final void writeByteArray(byte[] values) {
if (values == null) {
writeNull();
return;
}
writeArrayB(values.length, null, values);
boolean flag = false;
for (byte v : values) {
if (flag) writeArrayMark();
writeByte(v);
flag = true;
}
writeArrayE();
}
@Override @Override
public final void writeChar(final char value) { public final void writeChar(final char value) {
writeTo((byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF)); writeTo((byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF));
@@ -166,10 +186,11 @@ public class BsonWriter extends Writer {
} }
@Override @Override
public final void writeObjectB(Object obj) { public final int writeObjectB(Object obj) {
super.writeObjectB(obj); super.writeObjectB(obj);
writeSmallString(""); writeSmallString("");
writeShort(BsonReader.SIGN_OBJECTB); writeShort(BsonReader.SIGN_OBJECTB);
return -1;
} }
@Override @Override
@@ -179,49 +200,11 @@ public class BsonWriter extends Writer {
} }
@Override @Override
public final void writeFieldName(Attribute attribute) { public final void writeFieldName(EnMember member) {
Attribute attribute = member.getAttribute();
writeByte(BsonReader.SIGN_HASNEXT); writeByte(BsonReader.SIGN_HASNEXT);
writeSmallString(attribute.field()); writeSmallString(attribute.field());
byte typeval = 127; //字段的类型值 writeByte(BsonFactory.typeEnum(attribute.type()));
final Class type = attribute.type();
if (type == boolean.class || type == Boolean.class) {
typeval = 1;
} else if (type == byte.class || type == Byte.class) {
typeval = 2;
} else if (type == short.class || type == Short.class) {
typeval = 3;
} else if (type == char.class || type == Character.class) {
typeval = 4;
} else if (type == int.class || type == Integer.class) {
typeval = 5;
} else if (type == long.class || type == Long.class) {
typeval = 6;
} else if (type == float.class || type == Float.class) {
typeval = 7;
} else if (type == double.class || type == Double.class) {
typeval = 8;
} else if (type == String.class) {
typeval = 9;
} else if (type == boolean[].class || type == Boolean[].class) {
typeval = 101;
} else if (type == byte[].class || type == Byte[].class) {
typeval = 102;
} else if (type == short[].class || type == Short[].class) {
typeval = 103;
} else if (type == char[].class || type == Character[].class) {
typeval = 104;
} else if (type == int[].class || type == Integer[].class) {
typeval = 105;
} else if (type == long[].class || type == Long[].class) {
typeval = 106;
} else if (type == float[].class || type == Float[].class) {
typeval = 107;
} else if (type == double[].class || type == Double[].class) {
typeval = 108;
} else if (type == String[].class) {
typeval = 109;
}
writeByte(typeval);
} }
/** /**
@@ -260,14 +243,23 @@ public class BsonWriter extends Writer {
writeTo(bytes); writeTo(bytes);
} }
@Override
public final void writeWrapper(StringWrapper value) {
this.writeString(value == null ? null : value.getValue());
}
@Override @Override
public final void writeNull() { public final void writeNull() {
writeShort(Reader.SIGN_NULL); writeShort(Reader.SIGN_NULL);
} }
@Override @Override
public final void writeArrayB(int size) { public final int writeArrayB(int size, Encodeable<Writer, Object> componentEncoder, Object obj) {
writeInt(size); writeInt(size);
if (componentEncoder != null && componentEncoder != ByteSimpledCoder.instance) {
writeByte(BsonFactory.typeEnum(componentEncoder.getType()));
}
return -1;
} }
@Override @Override
@@ -279,8 +271,11 @@ public class BsonWriter extends Writer {
} }
@Override @Override
public void writeMapB(int size) { public int writeMapB(int size, Encodeable<Writer, Object> keyEncoder, Encodeable<Writer, Object> valueEncoder, Object obj) {
writeArrayB(size); writeInt(size);
writeByte(BsonFactory.typeEnum(keyEncoder.getType()));
writeByte(BsonFactory.typeEnum(valueEncoder.getType()));
return -1;
} }
@Override @Override

View File

@@ -0,0 +1,33 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.convert.bson;
import java.lang.reflect.Type;
import org.redkale.convert.*;
/**
* 数组的反序列化操作类 <br>
* 对象数组的反序列化不包含int[]、long[]这样的primitive class数组。 <br>
* 支持一定程度的泛型。 <br>
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <T> 反解析的数组元素类型
*/
public class SkipArrayDecoder<T> extends ArrayDecoder<T> {
public SkipArrayDecoder(final ConvertFactory factory, final Type type) {
super(factory, type);
}
@Override
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
return decoder;
}
}

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.convert.bson;
import java.lang.reflect.Type;
import org.redkale.convert.*;
/**
* Collection的反序列化操作类 <br>
* 支持一定程度的泛型。 <br>
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <T> 反解析的集合元素类型
*/
public class SkipCollectionDecoder<T> extends CollectionDecoder<T> {
public SkipCollectionDecoder(final ConvertFactory factory, final Type type) {
super(factory, type);
}
@Override
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
return decoder;
}
}

View File

@@ -0,0 +1,38 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.convert.bson;
import java.lang.reflect.Type;
import org.redkale.convert.*;
/**
* Map的反序列化操作类 <br>
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <K> Map key的数据类型
* @param <V> Map value的数据类型
*/
public class SkipMapDecoder<K, V> extends MapDecoder<K, V> {
public SkipMapDecoder(final ConvertFactory factory, final Type type) {
super(factory, type);
}
@Override
protected Decodeable<Reader, K> getKeyDecoder(Decodeable<Reader, K> decoder, byte[] typevals) {
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
return decoder;
}
@Override
protected Decodeable<Reader, V> getValueDecoder(Decodeable<Reader, V> decoder, byte[] typevals) {
if (typevals != null) return BsonFactory.typeEnum(typevals[1]);
return decoder;
}
}

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.convert.bson;
import java.lang.reflect.Type;
import org.redkale.convert.*;
/**
* Stream的反序列化操作类 <br>
* 支持一定程度的泛型。 <br>
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <T> 反解析的集合元素类型
*/
public class SkipStreamDecoder<T> extends StreamDecoder<T> {
public SkipStreamDecoder(final ConvertFactory factory, final Type type) {
super(factory, type);
}
@Override
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
return decoder;
}
}

View File

@@ -29,24 +29,31 @@ public final class BoolArraySimpledCoder<R extends Reader, W extends Writer> ext
out.writeNull(); out.writeNull();
return; return;
} }
out.writeArrayB(values.length); if (out.writeArrayB(values.length, BoolSimpledCoder.instance, values) < 0) {
boolean flag = false; boolean flag = false;
for (boolean v : values) { for (boolean v : values) {
if (flag) out.writeArrayMark(); if (flag) out.writeArrayMark();
out.writeBoolean(v); out.writeBoolean(v);
flag = true; flag = true;
}
} }
out.writeArrayE(); out.writeArrayE();
} }
@Override @Override
public boolean[] convertFrom(R in) { public boolean[] convertFrom(R in) {
int len = in.readArrayB(); int len = in.readArrayB(null, null, BoolSimpledCoder.instance);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NULL) return null;
if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = in.readMemberContentLength(null, BoolSimpledCoder.instance);
len = Reader.SIGN_NOLENGTH;
}
if (len == Reader.SIGN_NOLENGTH) { if (len == Reader.SIGN_NOLENGTH) {
int size = 0; int size = 0;
boolean[] data = new boolean[8]; boolean[] data = new boolean[8];
while (in.hasNext()) { int startPosition = in.position();
while (in.hasNext(startPosition, contentLength)) {
if (size >= data.length) { if (size >= data.length) {
boolean[] newdata = new boolean[data.length + 4]; boolean[] newdata = new boolean[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size); System.arraycopy(data, 0, newdata, 0, size);

View File

@@ -11,7 +11,7 @@ import org.redkale.convert.Writer;
/** /**
* byte[] 的SimpledCoder实现 * byte[] 的SimpledCoder实现
* *
* <p> * <p>
* 详情见: https://redkale.org * 详情见: https://redkale.org
* *
@@ -25,47 +25,12 @@ public final class ByteArraySimpledCoder<R extends Reader, W extends Writer> ext
@Override @Override
public void convertTo(W out, byte[] values) { public void convertTo(W out, byte[] values) {
if (values == null) { out.writeByteArray(values);
out.writeNull();
return;
}
out.writeArrayB(values.length);
boolean flag = false;
for (byte v : values) {
if (flag) out.writeArrayMark();
out.writeByte(v);
flag = true;
}
out.writeArrayE();
} }
@Override @Override
public byte[] convertFrom(R in) { public byte[] convertFrom(R in) {
int len = in.readArrayB(); return in.readByteArray();
if (len == Reader.SIGN_NULL) return null;
if (len == Reader.SIGN_NOLENGTH) {
int size = 0;
byte[] data = new byte[8];
while (in.hasNext()) {
if (size >= data.length) {
byte[] newdata = new byte[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size);
data = newdata;
}
data[size++] = in.readByte();
}
in.readArrayE();
byte[] newdata = new byte[size];
System.arraycopy(data, 0, newdata, 0, size);
return newdata;
} else {
byte[] values = new byte[len];
for (int i = 0; i < values.length; i++) {
values[i] = in.readByte();
}
in.readArrayE();
return values;
}
} }
} }

View File

@@ -30,24 +30,31 @@ public final class ByteBufferSimpledCoder<R extends Reader, W extends Writer> ex
out.writeNull(); out.writeNull();
return; return;
} }
out.writeArrayB(value.remaining()); if (out.writeArrayB(value.remaining(), ByteSimpledCoder.instance, value) < 0) {
boolean flag = false; boolean flag = false;
for (byte v : value.array()) { for (byte v : value.array()) {
if (flag) out.writeArrayMark(); if (flag) out.writeArrayMark();
out.writeByte(v); out.writeByte(v);
flag = true; flag = true;
}
} }
out.writeArrayE(); out.writeArrayE();
} }
@Override @Override
public ByteBuffer convertFrom(R in) { public ByteBuffer convertFrom(R in) {
int len = in.readArrayB(); int len = in.readArrayB(null, null, ByteSimpledCoder.instance);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NULL) return null;
if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = in.readMemberContentLength(null, ByteSimpledCoder.instance);
len = Reader.SIGN_NOLENGTH;
}
if (len == Reader.SIGN_NOLENGTH) { if (len == Reader.SIGN_NOLENGTH) {
int size = 0; int size = 0;
byte[] data = new byte[8]; byte[] data = new byte[8];
while (in.hasNext()) { int startPosition = in.position();
while (in.hasNext(startPosition, contentLength)) {
if (size >= data.length) { if (size >= data.length) {
byte[] newdata = new byte[data.length + 4]; byte[] newdata = new byte[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size); System.arraycopy(data, 0, newdata, 0, size);

View File

@@ -12,7 +12,9 @@ import org.redkale.convert.Writer;
/** /**
* char[] 的SimpledCoder实现 * char[] 的SimpledCoder实现
* *
* <p> 详情见: https://redkale.org * <p>
* 详情见: https://redkale.org
*
* @author zhangjx * @author zhangjx
* @param <R> Reader输入的子类型 * @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型 * @param <W> Writer输出的子类型
@@ -27,24 +29,31 @@ public final class CharArraySimpledCoder<R extends Reader, W extends Writer> ext
out.writeNull(); out.writeNull();
return; return;
} }
out.writeArrayB(values.length); if (out.writeArrayB(values.length, CharSimpledCoder.instance, values) < 0) {
boolean flag = false; boolean flag = false;
for (char v : values) { for (char v : values) {
if (flag) out.writeArrayMark(); if (flag) out.writeArrayMark();
out.writeChar(v); out.writeChar(v);
flag = true; flag = true;
}
} }
out.writeArrayE(); out.writeArrayE();
} }
@Override @Override
public char[] convertFrom(R in) { public char[] convertFrom(R in) {
int len = in.readArrayB(); int len = in.readArrayB(null, null, CharSimpledCoder.instance);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NULL) return null;
if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = in.readMemberContentLength(null, CharSimpledCoder.instance);
len = Reader.SIGN_NOLENGTH;
}
if (len == Reader.SIGN_NOLENGTH) { if (len == Reader.SIGN_NOLENGTH) {
int size = 0; int size = 0;
char[] data = new char[8]; char[] data = new char[8];
while (in.hasNext()) { int startPosition = in.position();
while (in.hasNext(startPosition, contentLength)) {
if (size >= data.length) { if (size >= data.length) {
char[] newdata = new char[data.length + 4]; char[] newdata = new char[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size); System.arraycopy(data, 0, newdata, 0, size);

View File

@@ -8,9 +8,11 @@ package org.redkale.convert.ext;
import org.redkale.convert.*; import org.redkale.convert.*;
/** /**
* CharSequence 的SimpledCoder实现 * CharSequence 的SimpledCoder实现
*
* <p>
* 详情见: https://redkale.org
* *
* <p> 详情见: https://redkale.org
* @author zhangjx * @author zhangjx
* @param <R> Reader输入的子类型 * @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型 * @param <W> Writer输出的子类型
@@ -28,4 +30,20 @@ public class CharSequenceSimpledCoder<R extends Reader, W extends Writer> extend
public CharSequence convertFrom(R in) { public CharSequence convertFrom(R in) {
return in.readString(); return in.readString();
} }
public static class StringBuilderSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, StringBuilder> {
public static final StringBuilderSimpledCoder instance = new StringBuilderSimpledCoder();
@Override
public void convertTo(W out, StringBuilder value) {
out.writeString(value == null ? null : value.toString());
}
@Override
public StringBuilder convertFrom(R in) {
String rs = in.readString();
return rs == null ? null : new StringBuilder(rs);
}
}
} }

View File

@@ -30,24 +30,31 @@ public final class DoubleArraySimpledCoder<R extends Reader, W extends Writer> e
out.writeNull(); out.writeNull();
return; return;
} }
out.writeArrayB(values.length); if (out.writeArrayB(values.length, DoubleSimpledCoder.instance, values) < 0) {
boolean flag = false; boolean flag = false;
for (double v : values) { for (double v : values) {
if (flag) out.writeArrayMark(); if (flag) out.writeArrayMark();
out.writeDouble(v); out.writeDouble(v);
flag = true; flag = true;
}
} }
out.writeArrayE(); out.writeArrayE();
} }
@Override @Override
public double[] convertFrom(R in) { public double[] convertFrom(R in) {
int len = in.readArrayB(); int len = in.readArrayB(null, null, DoubleSimpledCoder.instance);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NULL) return null;
if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = in.readMemberContentLength(null, DoubleSimpledCoder.instance);
len = Reader.SIGN_NOLENGTH;
}
if (len == Reader.SIGN_NOLENGTH) { if (len == Reader.SIGN_NOLENGTH) {
int size = 0; int size = 0;
double[] data = new double[8]; double[] data = new double[8];
while (in.hasNext()) { int startPosition = in.position();
while (in.hasNext(startPosition, contentLength)) {
if (size >= data.length) { if (size >= data.length) {
double[] newdata = new double[data.length + 4]; double[] newdata = new double[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size); System.arraycopy(data, 0, newdata, 0, size);

View File

@@ -0,0 +1,41 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.convert.ext;
import java.time.Duration;
import org.redkale.convert.*;
/**
* Duration 的SimpledCoder实现
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型
*/
public class DurationSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Duration> {
public static final DurationSimpledCoder instance = new DurationSimpledCoder();
@Override
public void convertTo(W out, Duration value) {
if (value == null) {
out.writeNull();
} else {
out.writeLong(value.toNanos());
}
}
@Override
public Duration convertFrom(R in) {
String value = in.readSmallString();
if (value == null) return null;
return Duration.ofNanos(Long.parseLong(value));
}
}

View File

@@ -45,4 +45,8 @@ public final class EnumSimpledCoder<R extends Reader, W extends Writer, E extend
return (E) Enum.valueOf(type, value); return (E) Enum.valueOf(type, value);
} }
@Override
public Class<E> getType() {
return type;
}
} }

View File

@@ -12,7 +12,9 @@ import org.redkale.convert.Writer;
/** /**
* float[] 的SimpledCoder实现 * float[] 的SimpledCoder实现
* *
* <p> 详情见: https://redkale.org * <p>
* 详情见: https://redkale.org
*
* @author zhangjx * @author zhangjx
* @param <R> Reader输入的子类型 * @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型 * @param <W> Writer输出的子类型
@@ -27,24 +29,31 @@ public final class FloatArraySimpledCoder<R extends Reader, W extends Writer> ex
out.writeNull(); out.writeNull();
return; return;
} }
out.writeArrayB(values.length); if (out.writeArrayB(values.length, FloatSimpledCoder.instance, values) < 0) {
boolean flag = false; boolean flag = false;
for (float v : values) { for (float v : values) {
if (flag) out.writeArrayMark(); if (flag) out.writeArrayMark();
out.writeFloat(v); out.writeFloat(v);
flag = true; flag = true;
}
} }
out.writeArrayE(); out.writeArrayE();
} }
@Override @Override
public float[] convertFrom(R in) { public float[] convertFrom(R in) {
int len = in.readArrayB(); int len = in.readArrayB(null, null, FloatSimpledCoder.instance);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NULL) return null;
if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = in.readMemberContentLength(null, FloatSimpledCoder.instance);
len = Reader.SIGN_NOLENGTH;
}
if (len == Reader.SIGN_NOLENGTH) { if (len == Reader.SIGN_NOLENGTH) {
int size = 0; int size = 0;
float[] data = new float[8]; float[] data = new float[8];
while (in.hasNext()) { int startPosition = in.position();
while (in.hasNext(startPosition, contentLength)) {
if (size >= data.length) { if (size >= data.length) {
float[] newdata = new float[data.length + 4]; float[] newdata = new float[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size); System.arraycopy(data, 0, newdata, 0, size);

View File

@@ -30,24 +30,31 @@ public final class IntArraySimpledCoder<R extends Reader, W extends Writer> exte
out.writeNull(); out.writeNull();
return; return;
} }
out.writeArrayB(values.length); if (out.writeArrayB(values.length, IntSimpledCoder.instance, values) < 0) {
boolean flag = false; boolean flag = false;
for (int v : values) { for (int v : values) {
if (flag) out.writeArrayMark(); if (flag) out.writeArrayMark();
out.writeInt(v); out.writeInt(v);
flag = true; flag = true;
}
} }
out.writeArrayE(); out.writeArrayE();
} }
@Override @Override
public int[] convertFrom(R in) { public int[] convertFrom(R in) {
int len = in.readArrayB(); int len = in.readArrayB(null, null, IntSimpledCoder.instance);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NULL) return null;
if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = in.readMemberContentLength(null, IntSimpledCoder.instance);
len = Reader.SIGN_NOLENGTH;
}
if (len == Reader.SIGN_NOLENGTH) { if (len == Reader.SIGN_NOLENGTH) {
int size = 0; int size = 0;
int[] data = new int[8]; int[] data = new int[8];
while (in.hasNext()) { int startPosition = in.position();
while (in.hasNext(startPosition, contentLength)) {
if (size >= data.length) { if (size >= data.length) {
int[] newdata = new int[data.length + 4]; int[] newdata = new int[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size); System.arraycopy(data, 0, newdata, 0, size);

View File

@@ -30,24 +30,31 @@ public final class LongArraySimpledCoder<R extends Reader, W extends Writer> ext
out.writeNull(); out.writeNull();
return; return;
} }
out.writeArrayB(values.length); if (out.writeArrayB(values.length, LongSimpledCoder.instance, values) < 0) {
boolean flag = false; boolean flag = false;
for (long v : values) { for (long v : values) {
if (flag) out.writeArrayMark(); if (flag) out.writeArrayMark();
out.writeLong(v); out.writeLong(v);
flag = true; flag = true;
}
} }
out.writeArrayE(); out.writeArrayE();
} }
@Override @Override
public long[] convertFrom(R in) { public long[] convertFrom(R in) {
int len = in.readArrayB(); int len = in.readArrayB(null, null, LongSimpledCoder.instance);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NULL) return null;
if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = in.readMemberContentLength(null, LongSimpledCoder.instance);
len = Reader.SIGN_NOLENGTH;
}
if (len == Reader.SIGN_NOLENGTH) { if (len == Reader.SIGN_NOLENGTH) {
int size = 0; int size = 0;
long[] data = new long[8]; long[] data = new long[8];
while (in.hasNext()) { int startPosition = in.position();
while (in.hasNext(startPosition, contentLength)) {
if (size >= data.length) { if (size >= data.length) {
long[] newdata = new long[data.length + 4]; long[] newdata = new long[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size); System.arraycopy(data, 0, newdata, 0, size);

View File

@@ -12,7 +12,9 @@ import org.redkale.convert.Writer;
/** /**
* short[] 的SimpledCoder实现 * short[] 的SimpledCoder实现
* *
* <p> 详情见: https://redkale.org * <p>
* 详情见: https://redkale.org
*
* @author zhangjx * @author zhangjx
* @param <R> Reader输入的子类型 * @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型 * @param <W> Writer输出的子类型
@@ -27,24 +29,31 @@ public final class ShortArraySimpledCoder<R extends Reader, W extends Writer> ex
out.writeNull(); out.writeNull();
return; return;
} }
out.writeArrayB(values.length); if (out.writeArrayB(values.length, ShortSimpledCoder.instance, values) < 0) {
boolean flag = false; boolean flag = false;
for (short v : values) { for (short v : values) {
if (flag) out.writeArrayMark(); if (flag) out.writeArrayMark();
out.writeShort(v); out.writeShort(v);
flag = true; flag = true;
}
} }
out.writeArrayE(); out.writeArrayE();
} }
@Override @Override
public short[] convertFrom(R in) { public short[] convertFrom(R in) {
int len = in.readArrayB(); int len = in.readArrayB(null, null, ShortSimpledCoder.instance);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NULL) return null;
if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = in.readMemberContentLength(null, ShortSimpledCoder.instance);
len = Reader.SIGN_NOLENGTH;
}
if (len == Reader.SIGN_NOLENGTH) { if (len == Reader.SIGN_NOLENGTH) {
int size = 0; int size = 0;
short[] data = new short[8]; short[] data = new short[8];
while (in.hasNext()) { int startPosition = in.position();
while (in.hasNext(startPosition, contentLength)) {
if (size >= data.length) { if (size >= data.length) {
short[] newdata = new short[data.length + 4]; short[] newdata = new short[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size); System.arraycopy(data, 0, newdata, 0, size);

View File

@@ -5,14 +5,14 @@
*/ */
package org.redkale.convert.ext; package org.redkale.convert.ext;
import org.redkale.convert.Reader; import org.redkale.convert.*;
import org.redkale.convert.SimpledCoder;
import org.redkale.convert.Writer;
/** /**
* String[] 的SimpledCoder实现 * String[] 的SimpledCoder实现
* *
* <p> 详情见: https://redkale.org * <p>
* 详情见: https://redkale.org
*
* @author zhangjx * @author zhangjx
* @param <R> Reader输入的子类型 * @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型 * @param <W> Writer输出的子类型
@@ -27,24 +27,35 @@ public final class StringArraySimpledCoder<R extends Reader, W extends Writer> e
out.writeNull(); out.writeNull();
return; return;
} }
out.writeArrayB(values.length); if (out.writeArrayB(values.length, StringSimpledCoder.instance, values) < 0) {
boolean flag = false; boolean flag = false;
for (String v : values) { for (String v : values) {
if (flag) out.writeArrayMark(); if (flag) out.writeArrayMark();
out.writeString(v); out.writeString(v);
flag = true; flag = true;
}
} }
out.writeArrayE(); out.writeArrayE();
} }
@Override @Override
public String[] convertFrom(R in) { public String[] convertFrom(R in) {
int len = in.readArrayB(); return convertFrom(in, null);
}
public String[] convertFrom(R in, DeMember member) {
int len = in.readArrayB(member, null, StringSimpledCoder.instance);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NULL) return null;
if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = in.readMemberContentLength(null, StringSimpledCoder.instance);
len = Reader.SIGN_NOLENGTH;
}
if (len == Reader.SIGN_NOLENGTH) { if (len == Reader.SIGN_NOLENGTH) {
int size = 0; int size = 0;
String[] data = new String[8]; String[] data = new String[8];
while (in.hasNext()) { int startPosition = in.position();
while (in.hasNext(startPosition, contentLength)) {
if (size >= data.length) { if (size >= data.length) {
String[] newdata = new String[data.length + 4]; String[] newdata = new String[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size); System.arraycopy(data, 0, newdata, 0, size);

View File

@@ -0,0 +1,35 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.convert.ext;
import org.redkale.convert.*;
import org.redkale.util.StringWrapper;
/**
* String 的SimpledCoder实现
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型
*/
public final class StringWrapperSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, StringWrapper> {
public static final StringWrapperSimpledCoder instance = new StringWrapperSimpledCoder();
@Override
public void convertTo(W out, StringWrapper value) {
out.writeWrapper(value);
}
@Override
public StringWrapper convertFrom(R in) {
return new StringWrapper(in.readString());
}
}

View File

@@ -126,21 +126,39 @@ public class JsonByteBufferReader extends JsonReader {
if (ch == '{') return ""; if (ch == '{') return "";
if (ch == 'n' && nextChar() == 'u' && nextChar() == 'l' && nextChar() == 'l') return null; if (ch == 'n' && nextChar() == 'u' && nextChar() == 'l' && nextChar() == 'l') return null;
if (ch == 'N' && nextChar() == 'U' && nextChar() == 'L' && nextChar() == 'L') return null; if (ch == 'N' && nextChar() == 'U' && nextChar() == 'L' && nextChar() == 'L') return null;
throw new ConvertException("a json object text must begin with '{' (position = " + position + ") but '" + ch + "'"); StringBuilder sb = new StringBuilder();
sb.append(ch);
char one;
try {
while ((one = nextChar()) != 0) sb.append(one);
} catch (Exception e) {
}
throw new ConvertException("a json object text must begin with '{' (position = " + position + ") but '" + ch + "' in (" + sb + ")");
} }
/** /**
* 判断下一个非空白字符是否为[ * 判断下一个非空白字符是否为[
* *
* @param member DeMember
* @param typevals byte[]
* @param decoder Decodeable
*
* @return SIGN_NOLENGTH 或 SIGN_NULL * @return SIGN_NOLENGTH 或 SIGN_NULL
*/ */
@Override @Override
public final int readArrayB() { public final int readArrayB(DeMember member, byte[] typevals, Decodeable decoder) {
char ch = nextGoodChar(); char ch = nextGoodChar();
if (ch == '[' || ch == '{') return SIGN_NOLENGTH; if (ch == '[' || ch == '{') return SIGN_NOLENGTH;
if (ch == 'n' && nextChar() == 'u' && nextChar() == 'l' && nextChar() == 'l') return SIGN_NULL; if (ch == 'n' && nextChar() == 'u' && nextChar() == 'l' && nextChar() == 'l') return SIGN_NULL;
if (ch == 'N' && nextChar() == 'U' && nextChar() == 'L' && nextChar() == 'L') return SIGN_NULL; if (ch == 'N' && nextChar() == 'U' && nextChar() == 'L' && nextChar() == 'L') return SIGN_NULL;
throw new ConvertException("a json array text must begin with '[' (position = " + position + ") but '" + ch + "'"); StringBuilder sb = new StringBuilder();
sb.append(ch);
char one;
try {
while ((one = nextChar()) != 0) sb.append(one);
} catch (Exception e) {
}
throw new ConvertException("a json array text must begin with '[' (position = " + position + ") but '" + ch + "' in (" + sb + ")");
} }
/** /**
@@ -150,16 +168,26 @@ public class JsonByteBufferReader extends JsonReader {
public final void readBlank() { public final void readBlank() {
char ch = nextGoodChar(); char ch = nextGoodChar();
if (ch == ':') return; if (ch == ':') return;
throw new ConvertException("expected a ':' but '" + ch + "'(position = " + position + ")"); StringBuilder sb = new StringBuilder();
sb.append(ch);
char one;
try {
while ((one = nextChar()) != 0) sb.append(one);
} catch (Exception e) {
}
throw new ConvertException("expected a ':' but '" + ch + "'(position = " + position + ") in (" + sb + ")");
} }
/** /**
* 判断对象是否存在下一个属性或者数组是否存在下一个元素 * 判断对象是否存在下一个属性或者数组是否存在下一个元素
* *
* @param startPosition 起始位置
* @param contentLength 内容大小, 不确定的传-1
*
* @return 是否存在 * @return 是否存在
*/ */
@Override @Override
public final boolean hasNext() { public boolean hasNext(int startPosition, int contentLength) {
char ch = nextGoodChar(); char ch = nextGoodChar();
if (ch == ',') return true; if (ch == ',') return true;
if (ch == '}' || ch == ']' || ch == 0) return false; if (ch == '}' || ch == ']' || ch == 0) return false;
@@ -272,8 +300,10 @@ public class JsonByteBufferReader extends JsonReader {
@Override @Override
public final int readInt() { public final int readInt() {
char firstchar = nextGoodChar(); char firstchar = nextGoodChar();
boolean quote = false;
if (firstchar == '"' || firstchar == '\'') { if (firstchar == '"' || firstchar == '\'') {
firstchar = nextChar(); quote = true;
firstchar = nextGoodChar();
if (firstchar == '"' || firstchar == '\'') return 0; if (firstchar == '"' || firstchar == '\'') return 0;
} }
int value = 0; int value = 0;
@@ -288,6 +318,7 @@ public class JsonByteBufferReader extends JsonReader {
if (ch >= '0' && ch <= '9') { if (ch >= '0' && ch <= '9') {
value = (value << 3) + (value << 1) + (ch - '0'); value = (value << 3) + (value << 1) + (ch - '0');
} else if (ch == '"' || ch == '\'') { } else if (ch == '"' || ch == '\'') {
} else if (quote && ch <= ' ') {
} else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') { } else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') {
backChar(ch); backChar(ch);
break; break;
@@ -306,8 +337,10 @@ public class JsonByteBufferReader extends JsonReader {
@Override @Override
public final long readLong() { public final long readLong() {
char firstchar = nextGoodChar(); char firstchar = nextGoodChar();
boolean quote = false;
if (firstchar == '"' || firstchar == '\'') { if (firstchar == '"' || firstchar == '\'') {
firstchar = nextChar(); quote = true;
firstchar = nextGoodChar();
if (firstchar == '"' || firstchar == '\'') return 0L; if (firstchar == '"' || firstchar == '\'') return 0L;
} }
long value = 0; long value = 0;
@@ -322,6 +355,7 @@ public class JsonByteBufferReader extends JsonReader {
if (ch >= '0' && ch <= '9') { if (ch >= '0' && ch <= '9') {
value = (value << 3) + (value << 1) + (ch - '0'); value = (value << 3) + (value << 1) + (ch - '0');
} else if (ch == '"' || ch == '\'') { } else if (ch == '"' || ch == '\'') {
} else if (quote && ch <= ' ') {
} else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') { } else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') {
backChar(ch); backChar(ch);
break; break;

View File

@@ -48,7 +48,9 @@ public class JsonByteBufferWriter extends JsonWriter {
@Override @Override
protected boolean recycle() { protected boolean recycle() {
super.recycle();
this.index = 0; this.index = 0;
this.specify = null;
this.charset = null; this.charset = null;
this.buffers = null; this.buffers = null;
return false; return false;

View File

@@ -21,7 +21,7 @@ import org.redkale.util.*;
* @author zhangjx * @author zhangjx
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> { public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
public static final Type TYPE_MAP_STRING_STRING = new TypeToken<java.util.HashMap<String, String>>() { public static final Type TYPE_MAP_STRING_STRING = new TypeToken<java.util.HashMap<String, String>>() {
}.getType(); }.getType();
@@ -46,6 +46,16 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
return JsonFactory.root().getConvert(); return JsonFactory.root().getConvert();
} }
@Override
public JsonConvert newConvert(final BiFunction<Attribute, Object, Object> fieldFunc) {
return new JsonConvert(getFactory(), tiny) {
@Override
protected <S extends JsonWriter> S configWrite(S writer) {
return fieldFunc(writer, fieldFunc);
}
};
}
//------------------------------ reader ----------------------------------------------------------- //------------------------------ reader -----------------------------------------------------------
public JsonReader pollJsonReader(final ByteBuffer... buffers) { public JsonReader pollJsonReader(final ByteBuffer... buffers) {
return new JsonByteBufferReader((ConvertMask) null, buffers); return new JsonByteBufferReader((ConvertMask) null, buffers);
@@ -65,26 +75,32 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
//------------------------------ writer ----------------------------------------------------------- //------------------------------ writer -----------------------------------------------------------
public JsonByteBufferWriter pollJsonWriter(final Supplier<ByteBuffer> supplier) { public JsonByteBufferWriter pollJsonWriter(final Supplier<ByteBuffer> supplier) {
return new JsonByteBufferWriter(tiny, supplier); return configWrite(new JsonByteBufferWriter(tiny, supplier));
} }
public JsonWriter pollJsonWriter(final OutputStream out) { public JsonWriter pollJsonWriter(final OutputStream out) {
return new JsonStreamWriter(tiny, out); return configWrite(new JsonStreamWriter(tiny, out));
} }
public JsonWriter pollJsonWriter(final Charset charset, final OutputStream out) { public JsonWriter pollJsonWriter(final Charset charset, final OutputStream out) {
return new JsonStreamWriter(tiny, charset, out); return configWrite(new JsonStreamWriter(tiny, charset, out));
} }
public JsonWriter pollJsonWriter() { public JsonWriter pollJsonWriter() {
return writerPool.get().tiny(tiny); return configWrite(writerPool.get().tiny(tiny));
} }
public void offerJsonWriter(final JsonWriter out) { public void offerJsonWriter(final JsonWriter writer) {
if (out != null) writerPool.accept(out); if (writer != null) writerPool.accept(writer);
} }
//------------------------------ convertFrom ----------------------------------------------------------- //------------------------------ convertFrom -----------------------------------------------------------
@Override
public <T> T convertFrom(final Type type, final byte[] bytes) {
if (bytes == null) return null;
return convertFrom(type, new String(bytes, StandardCharsets.UTF_8));
}
public <T> T convertFrom(final Type type, final String text) { public <T> T convertFrom(final Type type, final String text) {
if (text == null) return null; if (text == null) return null;
return convertFrom(type, Utility.charArray(text)); return convertFrom(type, Utility.charArray(text));
@@ -128,6 +144,52 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
return rs; return rs;
} }
//返回非null的值是由String、ArrayList、HashMap任意组合的对象
public <V> V convertFrom(final String text) {
if (text == null) return null;
return (V) convertFrom(Utility.charArray(text));
}
//返回非null的值是由String、ArrayList、HashMap任意组合的对象
public <V> V convertFrom(final char[] text) {
if (text == null) return null;
return (V) convertFrom(text, 0, text.length);
}
//返回非null的值是由String、ArrayList、HashMap任意组合的对象
public <V> V convertFrom(final char[] text, final int start, final int len) {
if (text == null) return null;
final JsonReader in = readerPool.get();
in.setText(text, start, len);
Object rs = new AnyDecoder(factory).convertFrom(in);
readerPool.accept(in);
return (V) rs;
}
//返回非null的值是由String、ArrayList、HashMap任意组合的对象
public <V> V convertFrom(final InputStream in) {
if (in == null) return null;
return (V) new AnyDecoder(factory).convertFrom(new JsonStreamReader(in));
}
//返回非null的值是由String、ArrayList、HashMap任意组合的对象
public <V> V convertFrom(final ByteBuffer... buffers) {
if (buffers == null || buffers.length == 0) return null;
return (V) new AnyDecoder(factory).convertFrom(new JsonByteBufferReader((ConvertMask) null, buffers));
}
//返回非null的值是由String、ArrayList、HashMap任意组合的对象
public <V> V convertFrom(final ConvertMask mask, final ByteBuffer... buffers) {
if (buffers == null || buffers.length == 0) return null;
return (V) new AnyDecoder(factory).convertFrom(new JsonByteBufferReader(mask, buffers));
}
//返回非null的值是由String、ArrayList、HashMap任意组合的对象
public <V> V convertFrom(final JsonReader reader) {
if (reader == null) return null;
return (V) new AnyDecoder(factory).convertFrom(reader);
}
//------------------------------ convertTo ----------------------------------------------------------- //------------------------------ convertTo -----------------------------------------------------------
@Override @Override
public String convertTo(final Object value) { public String convertTo(final Object value) {
@@ -139,26 +201,27 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
public String convertTo(final Type type, final Object value) { public String convertTo(final Type type, final Object value) {
if (type == null) return null; if (type == null) return null;
if (value == null) return "null"; if (value == null) return "null";
final JsonWriter out = writerPool.get().tiny(tiny); final JsonWriter writer = pollJsonWriter();
factory.loadEncoder(type).convertTo(out, value); writer.specify(type);
String result = out.toString(); factory.loadEncoder(type).convertTo(writer, value);
writerPool.accept(out); String result = writer.toString();
writerPool.accept(writer);
return result; return result;
} }
@Override @Override
public String convertMapTo(final Object... values) { public String convertMapTo(final Object... values) {
if (values == null) return "null"; if (values == null) return "null";
final JsonWriter out = writerPool.get().tiny(tiny); final JsonWriter writer = pollJsonWriter();
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(out, values); ((AnyEncoder) factory.getAnyEncoder()).convertMapTo(writer, values);
String result = out.toString(); String result = writer.toString();
writerPool.accept(out); writerPool.accept(writer);
return result; return result;
} }
public void convertTo(final OutputStream out, final Object value) { public void convertTo(final OutputStream out, final Object value) {
if (value == null) { if (value == null) {
new JsonStreamWriter(tiny, out).writeNull(); pollJsonWriter(out).writeNull();
} else { } else {
convertTo(out, value.getClass(), value); convertTo(out, value.getClass(), value);
} }
@@ -167,9 +230,10 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
public void convertTo(final OutputStream out, final Type type, final Object value) { public void convertTo(final OutputStream out, final Type type, final Object value) {
if (type == null) return; if (type == null) return;
if (value == null) { if (value == null) {
new JsonStreamWriter(tiny, out).writeNull(); pollJsonWriter(out).writeNull();
} else { } else {
final JsonWriter writer = writerPool.get().tiny(tiny); final JsonWriter writer = pollJsonWriter();
writer.specify(type);
factory.loadEncoder(type).convertTo(writer, value); factory.loadEncoder(type).convertTo(writer, value);
byte[] bs = writer.toBytes(); byte[] bs = writer.toBytes();
writerPool.accept(writer); writerPool.accept(writer);
@@ -183,9 +247,9 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
public void convertMapTo(final OutputStream out, final Object... values) { public void convertMapTo(final OutputStream out, final Object... values) {
if (values == null) { if (values == null) {
new JsonStreamWriter(tiny, out).writeNull(); pollJsonWriter(out).writeNull();
} else { } else {
final JsonWriter writer = writerPool.get().tiny(tiny); final JsonWriter writer = pollJsonWriter();
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(writer, values); ((AnyEncoder) factory.getAnyEncoder()).convertMapTo(writer, values);
byte[] bs = writer.toBytes(); byte[] bs = writer.toBytes();
writerPool.accept(writer); writerPool.accept(writer);
@@ -200,7 +264,7 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
@Override @Override
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Object value) { public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Object value) {
if (supplier == null) return null; if (supplier == null) return null;
JsonByteBufferWriter out = new JsonByteBufferWriter(tiny, null, supplier); JsonByteBufferWriter out = pollJsonWriter(supplier);
if (value == null) { if (value == null) {
out.writeNull(); out.writeNull();
} else { } else {
@@ -212,10 +276,11 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
@Override @Override
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value) { public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value) {
if (supplier == null || type == null) return null; if (supplier == null || type == null) return null;
JsonByteBufferWriter out = new JsonByteBufferWriter(tiny, null, supplier); JsonByteBufferWriter out = pollJsonWriter(supplier);
if (value == null) { if (value == null) {
out.writeNull(); out.writeNull();
} else { } else {
out.specify(type);
factory.loadEncoder(type).convertTo(out, value); factory.loadEncoder(type).convertTo(out, value);
} }
return out.toBuffers(); return out.toBuffers();
@@ -224,7 +289,7 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
@Override @Override
public ByteBuffer[] convertMapTo(final Supplier<ByteBuffer> supplier, final Object... values) { public ByteBuffer[] convertMapTo(final Supplier<ByteBuffer> supplier, final Object... values) {
if (supplier == null) return null; if (supplier == null) return null;
JsonByteBufferWriter out = new JsonByteBufferWriter(tiny, null, supplier); JsonByteBufferWriter out = pollJsonWriter(supplier);
if (values == null) { if (values == null) {
out.writeNull(); out.writeNull();
} else { } else {
@@ -246,6 +311,7 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
if (value == null) { if (value == null) {
writer.writeNull(); writer.writeNull();
} else { } else {
writer.specify(type);
factory.loadEncoder(type).convertTo(writer, value); factory.loadEncoder(type).convertTo(writer, value);
} }
} }
@@ -265,14 +331,15 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
public JsonWriter convertToWriter(final Type type, final Object value) { public JsonWriter convertToWriter(final Type type, final Object value) {
if (type == null) return null; if (type == null) return null;
final JsonWriter out = writerPool.get().tiny(tiny); final JsonWriter writer = pollJsonWriter();
factory.loadEncoder(type).convertTo(out, value); writer.specify(type);
return out; factory.loadEncoder(type).convertTo(writer, value);
return writer;
} }
public JsonWriter convertMapToWriter(final Object... values) { public JsonWriter convertMapToWriter(final Object... values) {
final JsonWriter out = writerPool.get().tiny(tiny); final JsonWriter writer = pollJsonWriter();
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(out, values); ((AnyEncoder) factory.getAnyEncoder()).convertMapTo(writer, values);
return out; return writer;
} }
} }

View File

@@ -85,4 +85,9 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
public boolean isReversible() { public boolean isReversible() {
return false; return false;
} }
@Override
public boolean isFieldSort() {
return true;
}
} }

View File

@@ -158,6 +158,21 @@ public class JsonReader extends Reader {
this.position--; this.position--;
} }
@Override
public final ValueType readType() {
char ch = nextGoodChar();
if (ch == '{') {
backChar(ch);
return ValueType.MAP;
}
if (ch == '[') {
backChar(ch);
return ValueType.ARRAY;
}
backChar(ch);
return ValueType.STRING;
}
/** /**
* 判断下一个非空白字符是否为{ * 判断下一个非空白字符是否为{
* *
@@ -168,6 +183,7 @@ public class JsonReader extends Reader {
@Override @Override
public String readObjectB(final Class clazz) { public String readObjectB(final Class clazz) {
this.fieldIndex = 0; //必须要重置为0 this.fieldIndex = 0; //必须要重置为0
if (this.text.length == 0) return null;
char ch = this.text[++this.position]; char ch = this.text[++this.position];
if (ch == '{') return ""; if (ch == '{') return "";
if (ch <= ' ') { if (ch <= ' ') {
@@ -189,11 +205,16 @@ public class JsonReader extends Reader {
/** /**
* 判断下一个非空白字符是否为{ * 判断下一个非空白字符是否为{
* *
* @param member DeMember
* @param typevals byte[]
* @param keyDecoder Decodeable
* @param valuedecoder Decodeable
*
* @return SIGN_NOLENGTH 或 SIGN_NULL * @return SIGN_NOLENGTH 或 SIGN_NULL
*/ */
@Override @Override
public final int readMapB() { public final int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valuedecoder) {
return readArrayB(); return readArrayB(member, typevals, keyDecoder);
} }
@Override @Override
@@ -203,10 +224,15 @@ public class JsonReader extends Reader {
/** /**
* 判断下一个非空白字符是否为[ * 判断下一个非空白字符是否为[
* *
* @param member DeMember
* @param typevals byte[]
* @param componentDecoder Decodeable
*
* @return SIGN_NOLENGTH 或 SIGN_NULL * @return SIGN_NOLENGTH 或 SIGN_NULL
*/ */
@Override @Override
public int readArrayB() { public int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder) {
if (this.text.length == 0) return SIGN_NULL;
char ch = this.text[++this.position]; char ch = this.text[++this.position];
if (ch == '[') return SIGN_NOLENGTH; if (ch == '[') return SIGN_NOLENGTH;
if (ch == '{') return SIGN_NOLENGTH; if (ch == '{') return SIGN_NOLENGTH;
@@ -244,13 +270,26 @@ public class JsonReader extends Reader {
throw new ConvertException("'" + new String(text) + "'expected a ':' but '" + ch + "'(position = " + position + ") in (" + new String(this.text) + ")"); throw new ConvertException("'" + new String(text) + "'expected a ':' but '" + ch + "'(position = " + position + ") in (" + new String(this.text) + ")");
} }
@Override
public int position() {
return this.position;
}
@Override
public int readMemberContentLength(DeMember member, Decodeable decoder) {
return -1;
}
/** /**
* 判断对象是否存在下一个属性或者数组是否存在下一个元素 * 判断对象是否存在下一个属性或者数组是否存在下一个元素
* *
* @param startPosition 起始位置
* @param contentLength 内容大小, 不确定的传-1
*
* @return 是否存在 * @return 是否存在
*/ */
@Override @Override
public boolean hasNext() { public boolean hasNext(int startPosition, int contentLength) {
char ch = this.text[++this.position]; char ch = this.text[++this.position];
if (ch == ',') return true; if (ch == ',') return true;
if (ch == '}' || ch == ']') return false; if (ch == '}' || ch == ']') return false;
@@ -314,7 +353,7 @@ public class JsonReader extends Reader {
} }
this.position = currpos - 1; this.position = currpos - 1;
if (len == 4 && text0[start] == 'n' && text0[start + 1] == 'u' && text0[start + 2] == 'l' && text0[start + 3] == 'l') return null; if (len == 4 && text0[start] == 'n' && text0[start + 1] == 'u' && text0[start + 2] == 'l' && text0[start + 3] == 'l') return null;
return new String(text0, start, len); return new String(text0, start, len == eof ? (len + 1) : len);
} }
} }
@@ -335,8 +374,16 @@ public class JsonReader extends Reader {
if (firstchar > ' ') break; if (firstchar > ' ') break;
} }
} }
boolean quote = false;
if (firstchar == '"' || firstchar == '\'') { if (firstchar == '"' || firstchar == '\'') {
quote = true;
firstchar = text0[++currpos]; firstchar = text0[++currpos];
if (firstchar <= ' ') {
for (;;) {
firstchar = text0[++currpos];
if (firstchar > ' ') break;
}
}
if (firstchar == '"' || firstchar == '\'') { if (firstchar == '"' || firstchar == '\'') {
this.position = currpos; this.position = currpos;
return 0; return 0;
@@ -352,7 +399,8 @@ public class JsonReader extends Reader {
if (currpos == eof) break; if (currpos == eof) break;
char ch = text0[++currpos]; char ch = text0[++currpos];
int val = digits[ch]; int val = digits[ch];
if (val == -3) break; if (quote && val == -3) continue;
if (val <= -3) break;
if (val == -1) throw new ConvertException("illegal escape(" + ch + ") (position = " + currpos + ") but '" + ch + "' in (" + new String(this.text) + ")"); if (val == -1) throw new ConvertException("illegal escape(" + ch + ") (position = " + currpos + ") but '" + ch + "' in (" + new String(this.text) + ")");
if (val != -2) value = value * 10 + val; if (val != -2) value = value * 10 + val;
} }
@@ -377,8 +425,16 @@ public class JsonReader extends Reader {
if (firstchar > ' ') break; if (firstchar > ' ') break;
} }
} }
boolean quote = false;
if (firstchar == '"' || firstchar == '\'') { if (firstchar == '"' || firstchar == '\'') {
quote = true;
firstchar = text0[++currpos]; firstchar = text0[++currpos];
if (firstchar <= ' ') {
for (;;) {
firstchar = text0[++currpos];
if (firstchar > ' ') break;
}
}
if (firstchar == '"' || firstchar == '\'') { if (firstchar == '"' || firstchar == '\'') {
this.position = currpos; this.position = currpos;
return 0L; return 0L;
@@ -394,7 +450,8 @@ public class JsonReader extends Reader {
if (currpos == eof) break; if (currpos == eof) break;
char ch = text0[++currpos]; char ch = text0[++currpos];
int val = digits[ch]; int val = digits[ch];
if (val == -3) break; if (quote && val == -3) continue;
if (val <= -3) break;
if (val == -1) throw new ConvertException("illegal escape(" + ch + ") (position = " + currpos + ") but '" + ch + "' in (" + new String(this.text) + ")"); if (val == -1) throw new ConvertException("illegal escape(" + ch + ") (position = " + currpos + ") but '" + ch + "' in (" + new String(this.text) + ")");
if (val != -2) value = value * 10 + val; if (val != -2) value = value * 10 + val;
} }
@@ -435,6 +492,41 @@ public class JsonReader extends Reader {
return (byte) readInt(); return (byte) readInt();
} }
@Override
public final byte[] readByteArray() {
int len = readArrayB(null, null, null);
int contentLength = -1;
if (len == Reader.SIGN_NULL) return null;
if (len == Reader.SIGN_NOLENBUTBYTES) {
contentLength = readMemberContentLength(null, null);
len = Reader.SIGN_NOLENGTH;
}
if (len == Reader.SIGN_NOLENGTH) {
int size = 0;
byte[] data = new byte[8];
int startPosition = position();
while (hasNext(startPosition, contentLength)) {
if (size >= data.length) {
byte[] newdata = new byte[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size);
data = newdata;
}
data[size++] = readByte();
}
readArrayE();
byte[] newdata = new byte[size];
System.arraycopy(data, 0, newdata, 0, size);
return newdata;
} else {
byte[] values = new byte[len];
for (int i = 0; i < values.length; i++) {
values[i] = readByte();
}
readArrayE();
return values;
}
}
@Override @Override
public final char readChar() { public final char readChar() {
return (char) readInt(); return (char) readInt();
@@ -448,6 +540,7 @@ public class JsonReader extends Reader {
@Override @Override
public final float readFloat() { public final float readFloat() {
String chars = readSmallString(); String chars = readSmallString();
if (chars != null) chars = chars.trim();
if (chars == null || chars.isEmpty()) return 0.f; if (chars == null || chars.isEmpty()) return 0.f;
return Float.parseFloat(chars); return Float.parseFloat(chars);
} }
@@ -455,6 +548,7 @@ public class JsonReader extends Reader {
@Override @Override
public final double readDouble() { public final double readDouble() {
String chars = readSmallString(); String chars = readSmallString();
if (chars != null) chars = chars.trim();
if (chars == null || chars.isEmpty()) return 0.0; if (chars == null || chars.isEmpty()) return 0.0;
return Double.parseDouble(chars); return Double.parseDouble(chars);
} }
@@ -590,7 +684,8 @@ public class JsonReader extends Reader {
digits[i] = i - 'A' + 10; digits[i] = i - 'A' + 10;
} }
digits['"'] = digits['\''] = -2; //-2 跳过 digits['"'] = digits['\''] = -2; //-2 跳过
digits[','] = digits['}'] = digits[']'] = digits[' '] = digits['\t'] = digits['\r'] = digits['\n'] = digits[':'] = -3; //-3退出 digits[' '] = digits['\t'] = digits['\r'] = digits['\n'] = -3; //-3可能跳过
digits[','] = digits['}'] = digits[']'] = digits[':'] = -4; //-4退出
} }
} }

View File

@@ -6,7 +6,7 @@
package org.redkale.convert.json; package org.redkale.convert.json;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.redkale.convert.Writer; import org.redkale.convert.*;
import org.redkale.util.*; import org.redkale.util.*;
/** /**
@@ -97,8 +97,11 @@ public class JsonWriter extends Writer {
if (quote) content[count++] = '"'; if (quote) content[count++] = '"';
} }
@Override
protected boolean recycle() { protected boolean recycle() {
super.recycle();
this.count = 0; this.count = 0;
this.specify = null;
if (this.content.length > defaultSize) { if (this.content.length > defaultSize) {
this.content = new char[defaultSize]; this.content = new char[defaultSize];
} }
@@ -156,9 +159,9 @@ public class JsonWriter extends Writer {
} }
@Override @Override
public final void writeFieldName(Attribute attribute) { public final void writeFieldName(EnMember member) {
if (this.comma) writeTo(','); if (this.comma) writeTo(',');
writeTo(true, attribute.field()); writeTo(true, member.getAttribute().field());
writeTo(':'); writeTo(':');
} }
@@ -187,6 +190,22 @@ public class JsonWriter extends Writer {
writeInt(value); writeInt(value);
} }
@Override
public final void writeByteArray(byte[] values) {
if (values == null) {
writeNull();
return;
}
writeArrayB(values.length, null, values);
boolean flag = false;
for (byte v : values) {
if (flag) writeArrayMark();
writeByte(v);
flag = true;
}
writeArrayE();
}
@Override @Override
public final void writeChar(char value) { public final void writeChar(char value) {
writeInt(value); writeInt(value);
@@ -302,6 +321,11 @@ public class JsonWriter extends Writer {
writeTo(false, String.valueOf(value)); writeTo(false, String.valueOf(value));
} }
@Override
public final void writeWrapper(StringWrapper value) {
writeTo(false, String.valueOf(value));
}
@Override @Override
public final boolean needWriteClassName() { public final boolean needWriteClassName() {
return false; return false;
@@ -312,9 +336,10 @@ public class JsonWriter extends Writer {
} }
@Override @Override
public final void writeObjectB(Object obj) { public final int writeObjectB(Object obj) {
super.writeObjectB(obj); super.writeObjectB(obj);
writeTo('{'); writeTo('{');
return -1;
} }
@Override @Override
@@ -328,8 +353,9 @@ public class JsonWriter extends Writer {
} }
@Override @Override
public final void writeArrayB(int size) { public final int writeArrayB(int size, Encodeable<Writer, Object> componentEncoder, Object obj) {
writeTo('['); writeTo('[');
return -1;
} }
@Override @Override
@@ -343,8 +369,9 @@ public class JsonWriter extends Writer {
} }
@Override @Override
public final void writeMapB(int size) { public final int writeMapB(int size, Encodeable<Writer, Object> keyEncoder, Encodeable<Writer, Object> valueEncoder, Object obj) {
writeTo('{'); writeTo('{');
return -1;
} }
@Override @Override

View File

@@ -7,13 +7,14 @@ package org.redkale.net;
import java.io.IOException; import java.io.IOException;
import java.net.*; import java.net.*;
import java.nio.ByteBuffer; import java.nio.*;
import java.nio.channels.*; import java.nio.channels.*;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.*;
import java.util.function.Consumer; import java.util.function.*;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import org.redkale.util.ObjectPool;
/** /**
* *
@@ -22,7 +23,7 @@ import javax.net.ssl.SSLContext;
* *
* @author zhangjx * @author zhangjx
*/ */
public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCloseable { public abstract class AsyncConnection implements ReadableByteChannel, WritableByteChannel, AutoCloseable {
protected SSLContext sslContext; protected SSLContext sslContext;
@@ -34,6 +35,12 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
protected volatile long writetime; protected volatile long writetime;
protected final Supplier<ByteBuffer> bufferSupplier;
protected final Consumer<ByteBuffer> bufferConsumer;
protected ByteBuffer readBuffer;
//在线数 //在线数
protected AtomicLong livingCounter; protected AtomicLong livingCounter;
@@ -42,6 +49,29 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
protected Consumer<AsyncConnection> beforeCloseListener; protected Consumer<AsyncConnection> beforeCloseListener;
//关联的事件数, 小于1表示没有事件
protected final AtomicInteger eventing = new AtomicInteger();
protected AsyncConnection(ObjectPool<ByteBuffer> bufferPool, SSLContext sslContext) {
this(bufferPool, bufferPool, sslContext);
}
protected AsyncConnection(Supplier<ByteBuffer> bufferSupplier, Consumer<ByteBuffer> bufferConsumer, SSLContext sslContext) {
Objects.requireNonNull(bufferSupplier);
Objects.requireNonNull(bufferConsumer);
this.bufferSupplier = bufferSupplier;
this.bufferConsumer = bufferConsumer;
this.sslContext = sslContext;
}
public Supplier<ByteBuffer> getBufferSupplier() {
return this.bufferSupplier;
}
public Consumer<ByteBuffer> getBufferConsumer() {
return this.bufferConsumer;
}
public final long getLastReadTime() { public final long getLastReadTime() {
return readtime; return readtime;
} }
@@ -50,6 +80,17 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
return writetime; return writetime;
} }
public final int increEventing() {
return eventing.incrementAndGet();
}
public final int decreEventing() {
return eventing.decrementAndGet();
}
@Override
public abstract boolean isOpen();
public abstract boolean isTCP(); public abstract boolean isTCP();
public abstract boolean shutdownInput(); public abstract boolean shutdownInput();
@@ -73,17 +114,14 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
public abstract void setWriteTimeoutSeconds(int writeTimeoutSeconds); public abstract void setWriteTimeoutSeconds(int writeTimeoutSeconds);
@Override @Override
public abstract Future<Integer> read(ByteBuffer dst); public abstract int read(ByteBuffer dst) throws IOException;
public abstract void read(CompletionHandler<Integer, ByteBuffer> handler);
@Override @Override
public abstract <A> void read(ByteBuffer dst, A attachment, CompletionHandler<Integer, ? super A> handler); public abstract int write(ByteBuffer src) throws IOException;
public abstract <A> void read(ByteBuffer dst, long timeout, TimeUnit unit, A attachment, CompletionHandler<Integer, ? super A> handler);
@Override
public abstract Future<Integer> write(ByteBuffer src);
@Override
public abstract <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer, ? super A> handler); public abstract <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer, ? super A> handler);
public final <A> void write(ByteBuffer[] srcs, A attachment, CompletionHandler<Integer, ? super A> handler) { public final <A> void write(ByteBuffer[] srcs, A attachment, CompletionHandler<Integer, ? super A> handler) {
@@ -92,6 +130,36 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
public abstract <A> void write(ByteBuffer[] srcs, int offset, int length, A attachment, CompletionHandler<Integer, ? super A> handler); public abstract <A> void write(ByteBuffer[] srcs, int offset, int length, A attachment, CompletionHandler<Integer, ? super A> handler);
public void setReadBuffer(Buffer buffer) {
if (this.readBuffer != null) throw new RuntimeException("repeat AsyncConnection.setReadBuffer");
this.readBuffer = (ByteBuffer) buffer;
}
public ByteBuffer pollReadBuffer() {
ByteBuffer rs = this.readBuffer;
if (rs != null) {
this.readBuffer = null;
return rs;
}
return bufferSupplier.get();
}
public void offerBuffer(Buffer buffer) {
if (buffer == null) return;
bufferConsumer.accept((ByteBuffer) buffer);
}
public void offerBuffer(Buffer... buffers) {
if (buffers == null) return;
for (Buffer buffer : buffers) {
bufferConsumer.accept((ByteBuffer) buffer);
}
}
public ByteBuffer pollWriteBuffer() {
return bufferSupplier.get();
}
public void dispose() {//同close 只是去掉throws IOException public void dispose() {//同close 只是去掉throws IOException
try { try {
this.close(); this.close();
@@ -114,11 +182,15 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
livingCounter.decrementAndGet(); livingCounter.decrementAndGet();
livingCounter = null; livingCounter = null;
} }
if (beforeCloseListener != null) if (beforeCloseListener != null) {
try { try {
beforeCloseListener.accept(this); beforeCloseListener.accept(this);
} catch (Exception io) { } catch (Exception io) {
} }
}
if (this.readBuffer != null) {
bufferConsumer.accept(this.readBuffer);
}
if (attributes == null) return; if (attributes == null) return;
try { try {
for (Object obj : attributes.values()) { for (Object obj : attributes.values()) {
@@ -163,6 +235,7 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
/** /**
* 创建TCP协议客户端连接 * 创建TCP协议客户端连接
* *
* @param bufferPool ByteBuffer对象池
* @param address 连接点子 * @param address 连接点子
* @param group 连接AsynchronousChannelGroup * @param group 连接AsynchronousChannelGroup
* @param readTimeoutSeconds 读取超时秒数 * @param readTimeoutSeconds 读取超时秒数
@@ -170,14 +243,15 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
* *
* @return 连接CompletableFuture * @return 连接CompletableFuture
*/ */
public static CompletableFuture<AsyncConnection> createTCP(final AsynchronousChannelGroup group, final SocketAddress address, public static CompletableFuture<AsyncConnection> createTCP(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousChannelGroup group,
final int readTimeoutSeconds, final int writeTimeoutSeconds) { final SocketAddress address, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
return createTCP(group, null, address, readTimeoutSeconds, writeTimeoutSeconds); return createTCP(bufferPool, group, null, address, readTimeoutSeconds, writeTimeoutSeconds);
} }
/** /**
* 创建TCP协议客户端连接 * 创建TCP协议客户端连接
* *
* @param bufferPool ByteBuffer对象池
* @param address 连接点子 * @param address 连接点子
* @param sslContext SSLContext * @param sslContext SSLContext
* @param group 连接AsynchronousChannelGroup * @param group 连接AsynchronousChannelGroup
@@ -186,7 +260,25 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
* *
* @return 连接CompletableFuture * @return 连接CompletableFuture
*/ */
public static CompletableFuture<AsyncConnection> createTCP(final AsynchronousChannelGroup group, final SSLContext sslContext, public static CompletableFuture<AsyncConnection> createTCP(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousChannelGroup group, final SSLContext sslContext,
final SocketAddress address, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
return createTCP(bufferPool, bufferPool, group, sslContext, address, readTimeoutSeconds, writeTimeoutSeconds);
}
/**
* 创建TCP协议客户端连接
*
* @param bufferSupplier ByteBuffer生产器
* @param bufferConsumer ByteBuffer回收器
* @param address 连接点子
* @param sslContext SSLContext
* @param group 连接AsynchronousChannelGroup
* @param readTimeoutSeconds 读取超时秒数
* @param writeTimeoutSeconds 写入超时秒数
*
* @return 连接CompletableFuture
*/
public static CompletableFuture<AsyncConnection> createTCP(final Supplier<ByteBuffer> bufferSupplier, Consumer<ByteBuffer> bufferConsumer, final AsynchronousChannelGroup group, final SSLContext sslContext,
final SocketAddress address, final int readTimeoutSeconds, final int writeTimeoutSeconds) { final SocketAddress address, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
final CompletableFuture<AsyncConnection> future = new CompletableFuture<>(); final CompletableFuture<AsyncConnection> future = new CompletableFuture<>();
try { try {
@@ -200,7 +292,7 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
channel.connect(address, null, new CompletionHandler<Void, Void>() { channel.connect(address, null, new CompletionHandler<Void, Void>() {
@Override @Override
public void completed(Void result, Void attachment) { public void completed(Void result, Void attachment) {
future.complete(create(channel, sslContext, address, readTimeoutSeconds, writeTimeoutSeconds)); future.complete(new TcpAioAsyncConnection(bufferSupplier, bufferConsumer, channel, sslContext, address, readTimeoutSeconds, writeTimeoutSeconds, null, null));
} }
@Override @Override
@@ -214,80 +306,80 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
return future; return future;
} }
/** // public static AsyncConnection create(final Socket socket) {
* 通常用于 ssl socket // return create(socket, null, 0, 0);
* // }
* @param socket Socket对象 // public static AsyncConnection create(final Socket socket, final SocketAddress addr0, final int readTimeoutSecond0, final int writeTimeoutSecond0) {
* // return new TcpBioAsyncConnection(socket, addr0, readTimeoutSecond0, writeTimeoutSecond0, null, null);
* @return 连接对象 // }
*/ //
public static AsyncConnection create(final Socket socket) { // public static AsyncConnection create(final Socket socket, final SocketAddress addr0, final int readTimeoutSecond0,
return create(socket, null, 0, 0); // final int writeTimeoutSecond0, final AtomicLong livingCounter, final AtomicLong closedCounter) {
} // return new TcpBioAsyncConnection(socket, addr0, readTimeoutSecond0, writeTimeoutSecond0, livingCounter, closedCounter);
// }
public static AsyncConnection create(final Socket socket, final SocketAddress addr0, final int readTimeoutSecond0, final int writeTimeoutSecond0) { //
return new TcpBioAsyncConnection(socket, addr0, readTimeoutSecond0, writeTimeoutSecond0, null, null); // public static AsyncConnection create(final SocketChannel ch, SocketAddress addr, final Selector selector,
} // final int readTimeoutSeconds0, final int writeTimeoutSeconds0) {
// return new TcpNioAsyncConnection(ch, addr, selector, readTimeoutSeconds0, writeTimeoutSeconds0, null, null);
public static AsyncConnection create(final Socket socket, final SocketAddress addr0, final int readTimeoutSecond0, // }
final int writeTimeoutSecond0, final AtomicLong livingCounter, final AtomicLong closedCounter) { //
return new TcpBioAsyncConnection(socket, addr0, readTimeoutSecond0, writeTimeoutSecond0, livingCounter, closedCounter); // public static AsyncConnection create(final SocketChannel ch, final SocketAddress addr0, final Selector selector, final Context context) {
} // return new TcpNioAsyncConnection(ch, addr0, selector, context.readTimeoutSeconds, context.writeTimeoutSeconds, null, null);
// }
public static AsyncConnection create(final SocketChannel ch, SocketAddress addr, final Selector selector, //
// public static AsyncConnection create(final SocketChannel ch, SocketAddress addr, final Selector selector,
// final int readTimeoutSeconds0, final int writeTimeoutSeconds0,
// final AtomicLong livingCounter, final AtomicLong closedCounter) {
// return new TcpNioAsyncConnection(ch, addr, selector, readTimeoutSeconds0, writeTimeoutSeconds0, livingCounter, closedCounter);
// }
public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final DatagramChannel ch,
SocketAddress addr, final boolean client0,
final int readTimeoutSeconds0, final int writeTimeoutSeconds0) { final int readTimeoutSeconds0, final int writeTimeoutSeconds0) {
return new TcpNioAsyncConnection(ch, addr, selector, readTimeoutSeconds0, writeTimeoutSeconds0, null, null); return new UdpBioAsyncConnection(bufferPool, bufferPool, ch, null, addr, client0, readTimeoutSeconds0, writeTimeoutSeconds0, null, null);
} }
public static AsyncConnection create(final SocketChannel ch, final SocketAddress addr0, final Selector selector, final Context context) { public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final DatagramChannel ch,
return new TcpNioAsyncConnection(ch, addr0, selector, context.readTimeoutSeconds, context.writeTimeoutSeconds, null, null); SocketAddress addr, final boolean client0,
}
public static AsyncConnection create(final SocketChannel ch, SocketAddress addr, final Selector selector,
final int readTimeoutSeconds0, final int writeTimeoutSeconds0, final int readTimeoutSeconds0, final int writeTimeoutSeconds0,
final AtomicLong livingCounter, final AtomicLong closedCounter) { final AtomicLong livingCounter, final AtomicLong closedCounter) {
return new TcpNioAsyncConnection(ch, addr, selector, readTimeoutSeconds0, writeTimeoutSeconds0, livingCounter, closedCounter); return new UdpBioAsyncConnection(bufferPool, bufferPool, ch, null, addr, client0, readTimeoutSeconds0, writeTimeoutSeconds0, livingCounter, closedCounter);
} }
public static AsyncConnection create(final DatagramChannel ch, SocketAddress addr, public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final DatagramChannel ch, SSLContext sslContext,
final boolean client0, final int readTimeoutSeconds0, final int writeTimeoutSeconds0) { SocketAddress addr, final boolean client0,
return new UdpBioAsyncConnection(ch, addr, client0, readTimeoutSeconds0, writeTimeoutSeconds0, null, null); final int readTimeoutSeconds0, final int writeTimeoutSeconds0) {
return new UdpBioAsyncConnection(bufferPool, bufferPool, ch, sslContext, addr, client0, readTimeoutSeconds0, writeTimeoutSeconds0, null, null);
} }
public static AsyncConnection create(final DatagramChannel ch, SocketAddress addr, public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final DatagramChannel ch, SSLContext sslContext,
final boolean client0, final int readTimeoutSeconds0, final int writeTimeoutSeconds0, SocketAddress addr, final boolean client0,
final int readTimeoutSeconds0, final int writeTimeoutSeconds0,
final AtomicLong livingCounter, final AtomicLong closedCounter) { final AtomicLong livingCounter, final AtomicLong closedCounter) {
return new UdpBioAsyncConnection(ch, addr, client0, readTimeoutSeconds0, writeTimeoutSeconds0, livingCounter, closedCounter); return new UdpBioAsyncConnection(bufferPool, bufferPool, ch, sslContext, addr, client0, readTimeoutSeconds0, writeTimeoutSeconds0, livingCounter, closedCounter);
} }
public static AsyncConnection create(final AsynchronousSocketChannel ch) { public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousSocketChannel ch) {
return create(ch, null, 0, 0); return create(bufferPool, ch, null, 0, 0);
} }
public static AsyncConnection create(final AsynchronousSocketChannel ch, final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds) { public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousSocketChannel ch,
return new TcpAioAsyncConnection(ch, null, addr0, readTimeoutSeconds, writeTimeoutSeconds, null, null); final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
return new TcpAioAsyncConnection(bufferPool, bufferPool, ch, null, addr0, readTimeoutSeconds, writeTimeoutSeconds, null, null);
} }
public static AsyncConnection create(final AsynchronousSocketChannel ch, SSLContext sslContext, final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds) { public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousSocketChannel ch, SSLContext sslContext,
return new TcpAioAsyncConnection(ch, sslContext, addr0, readTimeoutSeconds, writeTimeoutSeconds, null, null); final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
return new TcpAioAsyncConnection(bufferPool, bufferPool, ch, sslContext, addr0, readTimeoutSeconds, writeTimeoutSeconds, null, null);
} }
public static AsyncConnection create(final AsynchronousSocketChannel ch, final SocketAddress addr0, final Context context) { public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousSocketChannel ch,
return new TcpAioAsyncConnection(ch, context.sslContext, addr0, context.readTimeoutSeconds, context.writeTimeoutSeconds, null, null); final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds, final AtomicLong livingCounter, final AtomicLong closedCounter) {
return new TcpAioAsyncConnection(bufferPool, bufferPool, ch, null, addr0, readTimeoutSeconds, writeTimeoutSeconds, livingCounter, closedCounter);
} }
public static AsyncConnection create(final AsynchronousSocketChannel ch, final SocketAddress addr0, final int readTimeoutSeconds, public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousSocketChannel ch, SSLContext sslContext,
final int writeTimeoutSeconds, final AtomicLong livingCounter, final AtomicLong closedCounter) { final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds, final AtomicLong livingCounter, final AtomicLong closedCounter) {
return new TcpAioAsyncConnection(ch, null, addr0, readTimeoutSeconds, writeTimeoutSeconds, livingCounter, closedCounter); return new TcpAioAsyncConnection(bufferPool, bufferPool, ch, sslContext, addr0, readTimeoutSeconds, writeTimeoutSeconds, livingCounter, closedCounter);
} }
public static AsyncConnection create(final AsynchronousSocketChannel ch, SSLContext sslContext, final SocketAddress addr0, final int readTimeoutSeconds,
final int writeTimeoutSeconds, final AtomicLong livingCounter, final AtomicLong closedCounter) {
return new TcpAioAsyncConnection(ch, sslContext, addr0, readTimeoutSeconds, writeTimeoutSeconds, livingCounter, closedCounter);
}
public static AsyncConnection create(final AsynchronousSocketChannel ch, final SocketAddress addr0,
final Context context, final AtomicLong livingCounter, final AtomicLong closedCounter) {
return new TcpAioAsyncConnection(ch, context.sslContext, addr0, context.readTimeoutSeconds, context.writeTimeoutSeconds, livingCounter, closedCounter);
}
} }

View File

@@ -5,13 +5,9 @@
*/ */
package org.redkale.net; package org.redkale.net;
import java.io.IOException;
import java.net.*; import java.net.*;
import java.nio.*;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.charset.*; import java.nio.charset.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.function.*;
import java.util.logging.*; import java.util.logging.*;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import org.redkale.convert.bson.*; import org.redkale.convert.bson.*;
@@ -40,36 +36,9 @@ public class Context {
//ByteBuffer的容量默认8K //ByteBuffer的容量默认8K
protected final int bufferCapacity; protected final int bufferCapacity;
//ByteBuffer对象池
protected final ObjectPool<ByteBuffer> bufferPool;
//Response对象池
protected final ObjectPool<Response> responsePool;
//服务的根Servlet //服务的根Servlet
protected final PrepareServlet prepare; protected final PrepareServlet prepare;
//服务的监听地址
private final InetSocketAddress address;
//字符集
protected final Charset charset;
//最大连接数, 为0表示没限制
protected final int maxconns;
//请求内容的大小上限, 默认64K
protected final int maxbody;
//keep alive IO读取的超时时间
protected final int aliveTimeoutSeconds;
//IO读取的超时时间
protected final int readTimeoutSeconds;
//IO写入的超时时间
protected final int writeTimeoutSeconds;
//日志Logger //日志Logger
protected final Logger logger; protected final Logger logger;
@@ -82,24 +51,41 @@ public class Context {
//依赖注入工厂类 //依赖注入工厂类
protected final ResourceFactory resourceFactory; protected final ResourceFactory resourceFactory;
//最大连接数, 为0表示没限制
protected int maxconns;
//请求内容的大小上限, 默认64K
protected int maxbody;
//keep alive IO读取的超时时间
protected int aliveTimeoutSeconds;
//IO读取的超时时间
protected int readTimeoutSeconds;
//IO写入的超时时间
protected int writeTimeoutSeconds;
//服务的监听地址
protected InetSocketAddress address;
//字符集
protected Charset charset;
public Context(ContextConfig config) { public Context(ContextConfig config) {
this(config.serverStartTime, config.logger, config.executor, config.sslContext, this(config.serverStartTime, config.logger, config.executor, config.sslContext,
config.bufferCapacity, config.bufferPool, config.responsePool, config.maxconns, config.maxbody, config.bufferCapacity, config.maxconns, config.maxbody, config.charset, config.address, config.resourceFactory,
config.charset, config.address, config.resourceFactory, config.prepare, config.prepare, config.aliveTimeoutSeconds, config.readTimeoutSeconds, config.writeTimeoutSeconds);
config.aliveTimeoutSeconds, config.readTimeoutSeconds, config.writeTimeoutSeconds);
} }
public Context(long serverStartTime, Logger logger, ThreadPoolExecutor executor, SSLContext sslContext, public Context(long serverStartTime, Logger logger, ThreadPoolExecutor executor, SSLContext sslContext,
int bufferCapacity, ObjectPool<ByteBuffer> bufferPool, ObjectPool<Response> responsePool, final int maxconns, int bufferCapacity, final int maxconns, final int maxbody, Charset charset, InetSocketAddress address,
final int maxbody, Charset charset, InetSocketAddress address, ResourceFactory resourceFactory, ResourceFactory resourceFactory, PrepareServlet prepare, int aliveTimeoutSeconds, int readTimeoutSeconds, int writeTimeoutSeconds) {
final PrepareServlet prepare, final int aliveTimeoutSeconds, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
this.serverStartTime = serverStartTime; this.serverStartTime = serverStartTime;
this.logger = logger; this.logger = logger;
this.executor = executor; this.executor = executor;
this.sslContext = sslContext; this.sslContext = sslContext;
this.bufferCapacity = bufferCapacity; this.bufferCapacity = bufferCapacity;
this.bufferPool = bufferPool;
this.responsePool = responsePool;
this.maxconns = maxconns; this.maxconns = maxconns;
this.maxbody = maxbody; this.maxbody = maxbody;
this.charset = StandardCharsets.UTF_8.equals(charset) ? null : charset; this.charset = StandardCharsets.UTF_8.equals(charset) ? null : charset;
@@ -145,41 +131,22 @@ public class Context {
return executor.submit(r); return executor.submit(r);
} }
public AsynchronousChannelGroup createAsynchronousChannelGroup() throws IOException {
return AsynchronousChannelGroup.withThreadPool(executor);
}
public void runAsync(Runnable r) { public void runAsync(Runnable r) {
executor.execute(r); executor.execute(r);
} }
public int getCorePoolSize() {
return executor.getCorePoolSize();
}
public ThreadFactory getThreadFactory() {
return executor.getThreadFactory();
}
public int getBufferCapacity() { public int getBufferCapacity() {
return bufferCapacity; return bufferCapacity;
} }
public Supplier<ByteBuffer> getBufferSupplier() {
return bufferPool;
}
protected Consumer<ByteBuffer> getBufferConsumer() {
return bufferPool;
}
public ByteBuffer pollBuffer() {
return bufferPool.get();
}
protected void offerBuffer(ByteBuffer buffer) {
bufferPool.accept(buffer);
}
protected void offerBuffer(ByteBuffer... buffers) {
if (buffers == null) return;
for (ByteBuffer buffer : buffers) {
bufferPool.accept(buffer);
}
}
public Logger getLogger() { public Logger getLogger() {
return logger; return logger;
} }
@@ -218,12 +185,6 @@ public class Context {
//ByteBuffer的容量默认8K //ByteBuffer的容量默认8K
public int bufferCapacity; public int bufferCapacity;
//ByteBuffer对象池
public ObjectPool<ByteBuffer> bufferPool;
//Response对象池
public ObjectPool<Response> responsePool;
//服务的根Servlet //服务的根Servlet
public PrepareServlet prepare; public PrepareServlet prepare;

View File

@@ -5,9 +5,10 @@
*/ */
package org.redkale.net; package org.redkale.net;
import java.io.IOException;
import java.nio.*; import java.nio.*;
import java.nio.channels.*; import java.nio.channels.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.*; import java.util.logging.*;
import org.redkale.util.*; import org.redkale.util.*;
@@ -20,18 +21,21 @@ import org.redkale.util.*;
* @author zhangjx * @author zhangjx
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final class PrepareRunner implements Runnable { public class PrepareRunner implements Runnable {
private final AsyncConnection channel; private final AsyncConnection channel;
private final Context context; private final Context context;
private final ObjectPool<Response> responsePool;
private ByteBuffer data; private ByteBuffer data;
private Response response; private Response response;
public PrepareRunner(Context context, AsyncConnection channel, ByteBuffer data, Response response) { public PrepareRunner(Context context, ObjectPool<Response> responsePool, AsyncConnection channel, ByteBuffer data, Response response) {
this.context = context; this.context = context;
this.responsePool = responsePool;
this.channel = channel; this.channel = channel;
this.data = data; this.data = data;
this.response = response; this.response = response;
@@ -39,27 +43,22 @@ public final class PrepareRunner implements Runnable {
@Override @Override
public void run() { public void run() {
final boolean keepalive = response != null;
final PrepareServlet prepare = context.prepare;
final ObjectPool<? extends Response> responsePool = context.responsePool;
if (data != null) { //BIO模式的UDP连接创建AsyncConnection时已经获取到ByteBuffer数据了 if (data != null) { //BIO模式的UDP连接创建AsyncConnection时已经获取到ByteBuffer数据了
if (response == null) response = responsePool.get(); if (response == null) response = responsePool.get();
try { try {
response.init(channel); response.init(channel);
prepare.prepare(data, response.request, response); codec(data, response);
} catch (Throwable t) { } catch (Throwable t) {
context.logger.log(Level.WARNING, "prepare servlet abort, forece to close channel ", t); context.logger.log(Level.WARNING, "prepare servlet abort, force to close channel ", t);
response.finish(true); response.finish(true);
} }
return; return;
} }
if (response == null) response = responsePool.get(); if (response == null) response = responsePool.get();
final ByteBuffer buffer = response.request.pollReadBuffer();
try { try {
channel.read(buffer, keepalive ? context.getAliveTimeoutSeconds() : 0, TimeUnit.SECONDS, null, channel.read(new CompletionHandler<Integer, ByteBuffer>() {
new CompletionHandler<Integer, Void>() {
@Override @Override
public void completed(Integer count, Void attachment1) { public void completed(Integer count, ByteBuffer buffer) {
if (count < 1) { if (count < 1) {
response.request.offerReadBuffer(buffer); response.request.offerReadBuffer(buffer);
channel.dispose();// response.init(channel); 在调用之前异常 channel.dispose();// response.init(channel); 在调用之前异常
@@ -74,35 +73,121 @@ public final class PrepareRunner implements Runnable {
// System.println(new String(bs)); // System.println(new String(bs));
// } // }
buffer.flip(); buffer.flip();
response.init(channel);
try { try {
prepare.prepare(buffer, response.request, response); response.init(channel);
codec(buffer, response);
} catch (Throwable t) { //此处不可 context.offerBuffer(buffer); 以免prepare.prepare内部异常导致重复 offerBuffer } catch (Throwable t) { //此处不可 context.offerBuffer(buffer); 以免prepare.prepare内部异常导致重复 offerBuffer
context.logger.log(Level.WARNING, "prepare servlet abort, forece to close channel ", t); context.logger.log(Level.WARNING, "prepare servlet abort, force to close channel ", t);
response.finish(true); response.finish(true);
} }
} }
@Override @Override
public void failed(Throwable exc, Void attachment2) { public void failed(Throwable exc, ByteBuffer buffer) {
response.request.offerReadBuffer(buffer); response.request.offerReadBuffer(buffer);
channel.dispose();// response.init(channel); 在调用之前异常 channel.dispose();// response.init(channel); 在调用之前异常
response.removeChannel(); response.removeChannel();
response.finish(true); response.finish(true);
if (exc != null && context.logger.isLoggable(Level.FINEST)) { if (exc != null && context.logger.isLoggable(Level.FINEST)) {
context.logger.log(Level.FINEST, "Servlet Handler read channel erroneous, forece to close channel ", exc); context.logger.log(Level.FINEST, "Servlet Handler read channel erroneous, force to close channel ", exc);
} }
} }
}); });
} catch (Exception te) { } catch (Exception te) {
response.request.offerReadBuffer(buffer);
channel.dispose();// response.init(channel); 在调用之前异常 channel.dispose();// response.init(channel); 在调用之前异常
response.removeChannel(); response.removeChannel();
response.finish(true); response.finish(true);
if (te != null && context.logger.isLoggable(Level.FINEST)) { if (te != null && context.logger.isLoggable(Level.FINEST)) {
context.logger.log(Level.FINEST, "Servlet read channel erroneous, forece to close channel ", te); context.logger.log(Level.FINEST, "Servlet read channel erroneous, force to close channel ", te);
} }
} }
} }
protected void codec(final ByteBuffer buffer, final Response response) throws IOException {
final Request request = response.request;
final PrepareServlet preparer = context.prepare;
preparer.executeCounter.incrementAndGet();
final int rs = request.readHeader(buffer);
if (rs < 0) { //表示数据格式不正确
channel.offerBuffer(buffer);
if (rs != Integer.MIN_VALUE) preparer.illRequestCounter.incrementAndGet();
response.finish(true);
} else if (rs == 0) {
if (buffer.hasRemaining()) {
request.setMoredata(buffer);
} else {
response.request.offerReadBuffer(buffer);
}
preparer.prepare(request, response);
} else {
buffer.clear();
channel.setReadBuffer(buffer);
final AtomicInteger ai = new AtomicInteger(rs);
channel.read(new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
attachment.flip();
ai.addAndGet(-request.readBody(attachment));
if (ai.get() > 0) {
attachment.clear();
channel.setReadBuffer(attachment);
channel.read(this);
} else {
if (attachment.hasRemaining()) {
request.setMoredata(attachment);
} else {
response.request.offerReadBuffer(attachment);
}
try {
preparer.prepare(request, response);
} catch (Throwable t) { //此处不可 context.offerBuffer(buffer); 以免preparer.prepare内部异常导致重复 offerBuffer
context.logger.log(Level.WARNING, "prepare servlet abort, force to close channel ", t);
response.finish(true);
}
}
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
preparer.illRequestCounter.incrementAndGet();
response.request.offerReadBuffer(attachment);
response.finish(true);
if (exc != null) request.context.logger.log(Level.FINER, "Servlet read channel erroneous, force to close channel ", exc);
}
});
}
}
protected void initResponse(Response response, AsyncConnection channel) {
response.init(channel);
}
protected Response pollResponse() {
return responsePool.get();
}
protected Request pollRequest(Response response) {
return response.request;
}
protected AsyncConnection removeChannel(Response response) {
return response.removeChannel();
}
protected ByteBuffer pollReadBuffer(Request request) {
return request.pollReadBuffer();
}
protected ByteBuffer pollReadBuffer(Response response) {
return response.request.pollReadBuffer();
}
protected void offerReadBuffer(Request request, ByteBuffer buffer) {
request.offerReadBuffer(buffer);
}
protected void offerReadBuffer(Response response, ByteBuffer buffer) {
response.request.offerReadBuffer(buffer);
}
} }

View File

@@ -6,12 +6,9 @@
package org.redkale.net; package org.redkale.net;
import java.io.*; import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.*; import java.util.concurrent.atomic.*;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.logging.*;
import org.redkale.util.*; import org.redkale.util.*;
/** /**
@@ -210,55 +207,11 @@ public abstract class PrepareServlet<K extends Serializable, C extends Context,
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public abstract void addServlet(S servlet, Object attachment, AnyValue conf, K... mappings); public abstract void addServlet(S servlet, Object attachment, AnyValue conf, K... mappings);
public final void prepare(final ByteBuffer buffer, final R request, final P response) throws IOException { public final void prepare(final R request, final P response) throws IOException {
executeCounter.incrementAndGet(); request.prepare();
final int rs = request.readHeader(buffer); response.filter = this.headFilter;
if (rs < 0) { response.servlet = this;
request.offerReadBuffer(buffer); response.nextEvent();
if (rs != Integer.MIN_VALUE) illRequestCounter.incrementAndGet();
response.finish(true);
} else if (rs == 0) {
request.offerReadBuffer(buffer);
request.prepare();
response.filter = this.headFilter;
response.servlet = this;
response.nextEvent();
} else {
buffer.clear();
final AtomicInteger ai = new AtomicInteger(rs);
request.channel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
buffer.flip();
ai.addAndGet(-request.readBody(buffer));
if (ai.get() > 0) {
buffer.clear();
request.channel.read(buffer, buffer, this);
} else {
request.offerReadBuffer(buffer);
request.prepare();
try {
response.filter = PrepareServlet.this.headFilter;
response.servlet = PrepareServlet.this;
response.nextEvent();
} catch (Exception e) {
illRequestCounter.incrementAndGet();
response.finish(true);
request.context.logger.log(Level.WARNING, "prepare servlet abort, forece to close channel ", e);
}
}
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
illRequestCounter.incrementAndGet();
request.offerReadBuffer(buffer);
response.finish(true);
if (exc != null) request.context.logger.log(Level.FINER, "Servlet read channel erroneous, forece to close channel ", exc);
}
});
}
} }
protected AnyValue getServletConf(Servlet servlet) { protected AnyValue getServletConf(Servlet servlet) {

View File

@@ -43,7 +43,7 @@ public abstract class ProtocolServer {
public abstract <T> void setOption(SocketOption<T> name, T value) throws IOException; public abstract <T> void setOption(SocketOption<T> name, T value) throws IOException;
public abstract void accept() throws IOException; public abstract void accept(Server server) throws IOException;
public abstract void close() throws IOException; public abstract void close() throws IOException;
@@ -73,13 +73,13 @@ public abstract class ProtocolServer {
} else if ("aio".equalsIgnoreCase(netimpl)) { } else if ("aio".equalsIgnoreCase(netimpl)) {
return new TcpAioProtocolServer(context); return new TcpAioProtocolServer(context);
} else if ("nio".equalsIgnoreCase(netimpl)) { } else if ("nio".equalsIgnoreCase(netimpl)) {
return new TcpNioProtocolServer(context); return null;// return new TcpNioProtocolServer(context);
} }
} else if ("UDP".equalsIgnoreCase(protocol)) { } else if ("UDP".equalsIgnoreCase(protocol)) {
if (netimpl == null || netimpl.isEmpty()) { if (netimpl == null || netimpl.isEmpty()) {
return new UdpBioProtocolServer(context); return null;// return new UdpBioProtocolServer(context);
} else if ("bio".equalsIgnoreCase(netimpl)) { } else if ("bio".equalsIgnoreCase(netimpl)) {
return new UdpBioProtocolServer(context); return null;// return new UdpBioProtocolServer(context);
} }
} else if (netimpl == null || netimpl.isEmpty()) { } else if (netimpl == null || netimpl.isEmpty()) {
throw new RuntimeException("ProtocolServer not support protocol " + protocol); throw new RuntimeException("ProtocolServer not support protocol " + protocol);

View File

@@ -9,6 +9,7 @@ import java.nio.ByteBuffer;
import java.util.*; import java.util.*;
import org.redkale.convert.bson.BsonConvert; import org.redkale.convert.bson.BsonConvert;
import org.redkale.convert.json.JsonConvert; import org.redkale.convert.json.JsonConvert;
import org.redkale.util.ObjectPool;
/** /**
* 协议请求对象 * 协议请求对象
@@ -23,6 +24,8 @@ public abstract class Request<C extends Context> {
protected final C context; protected final C context;
protected final ObjectPool<ByteBuffer> bufferPool;
protected final BsonConvert bsonConvert; protected final BsonConvert bsonConvert;
protected final JsonConvert jsonConvert; protected final JsonConvert jsonConvert;
@@ -31,6 +34,10 @@ public abstract class Request<C extends Context> {
protected boolean keepAlive; protected boolean keepAlive;
protected boolean more; //pipeline模式
protected ByteBuffer moredata; //pipeline模式
protected AsyncConnection channel; protected AsyncConnection channel;
protected ByteBuffer readBuffer; protected ByteBuffer readBuffer;
@@ -43,17 +50,27 @@ public abstract class Request<C extends Context> {
protected final Map<String, Object> attributes = new HashMap<>(); protected final Map<String, Object> attributes = new HashMap<>();
protected Request(C context) { protected Request(C context, ObjectPool<ByteBuffer> bufferPool) {
this.context = context; this.context = context;
this.readBuffer = context.pollBuffer(); this.bufferPool = bufferPool;
this.bsonConvert = context.getBsonConvert(); this.bsonConvert = context.getBsonConvert();
this.jsonConvert = context.getJsonConvert(); this.jsonConvert = context.getJsonConvert();
} }
protected void setMoredata(ByteBuffer buffer) {
this.moredata = buffer;
}
protected ByteBuffer removeMoredata() {
ByteBuffer rs = this.moredata;
this.moredata = null;
return rs;
}
protected ByteBuffer pollReadBuffer() { protected ByteBuffer pollReadBuffer() {
ByteBuffer buffer = this.readBuffer; ByteBuffer buffer = this.readBuffer;
this.readBuffer = null; this.readBuffer = null;
if (buffer == null) buffer = context.pollBuffer(); if (buffer == null) buffer = bufferPool.get();
return buffer; return buffer;
} }
@@ -63,7 +80,7 @@ public abstract class Request<C extends Context> {
buffer.clear(); buffer.clear();
this.readBuffer = buffer; this.readBuffer = buffer;
} else { } else {
context.offerBuffer(buffer); bufferPool.accept(buffer);
} }
} }
@@ -90,6 +107,8 @@ public abstract class Request<C extends Context> {
protected void recycle() { protected void recycle() {
createtime = 0; createtime = 0;
keepAlive = false; keepAlive = false;
more = false;
moredata = null;
attributes.clear(); attributes.clear();
channel = null; // close it by response channel = null; // close it by response
} }

View File

@@ -10,6 +10,7 @@ import java.nio.ByteBuffer;
import java.nio.channels.CompletionHandler; import java.nio.channels.CompletionHandler;
import java.util.function.*; import java.util.function.*;
import java.util.logging.Level; import java.util.logging.Level;
import org.redkale.util.ObjectPool;
/** /**
* 协议响应对象 * 协议响应对象
@@ -26,6 +27,10 @@ public abstract class Response<C extends Context, R extends Request<C>> {
protected final C context; protected final C context;
protected final ObjectPool<ByteBuffer> bufferPool;
protected final ObjectPool<Response> responsePool;
protected final R request; protected final R request;
protected AsyncConnection channel; protected AsyncConnection channel;
@@ -34,7 +39,7 @@ public abstract class Response<C extends Context, R extends Request<C>> {
protected ByteBuffer writeBodyBuffer; protected ByteBuffer writeBodyBuffer;
private boolean inited = true; private volatile boolean inited = true;
protected Object output; //输出的结果对象 protected Object output; //输出的结果对象
@@ -66,15 +71,15 @@ public abstract class Response<C extends Context, R extends Request<C>> {
private void offerResponseBuffer(ByteBuffer attachment) { private void offerResponseBuffer(ByteBuffer attachment) {
if (writeHeadBuffer == null) { if (writeHeadBuffer == null) {
if (context.bufferPool.getRecyclerPredicate().test(attachment)) { if (bufferPool.getRecyclerPredicate().test(attachment)) {
writeHeadBuffer = attachment; writeHeadBuffer = attachment;
} }
} else if (writeBodyBuffer == null) { } else if (writeBodyBuffer == null) {
if (context.bufferPool.getRecyclerPredicate().test(attachment)) { if (bufferPool.getRecyclerPredicate().test(attachment)) {
writeBodyBuffer = attachment; writeBodyBuffer = attachment;
} }
} else { } else {
context.offerBuffer(attachment); bufferPool.accept(attachment);
} }
} }
@@ -108,31 +113,33 @@ public abstract class Response<C extends Context, R extends Request<C>> {
private void offerResponseBuffer(ByteBuffer[] attachments) { private void offerResponseBuffer(ByteBuffer[] attachments) {
int start = 0; int start = 0;
if (writeHeadBuffer == null && attachments.length > start) { if (writeHeadBuffer == null && attachments.length > start) {
if (context.bufferPool.getRecyclerPredicate().test(attachments[start])) { if (bufferPool.getRecyclerPredicate().test(attachments[start])) {
writeHeadBuffer = attachments[start]; writeHeadBuffer = attachments[start];
start++; start++;
} }
} }
if (writeBodyBuffer == null && attachments.length > start) { if (writeBodyBuffer == null && attachments.length > start) {
if (context.bufferPool.getRecyclerPredicate().test(attachments[start])) { if (bufferPool.getRecyclerPredicate().test(attachments[start])) {
writeBodyBuffer = attachments[start]; writeBodyBuffer = attachments[start];
start++; start++;
} }
} }
for (int i = start; i < attachments.length; i++) { for (int i = start; i < attachments.length; i++) {
context.offerBuffer(attachments[i]); bufferPool.accept(attachments[i]);
} }
} }
}; };
protected Response(C context, final R request) { protected Response(C context, final R request, ObjectPool<Response> responsePool) {
this.context = context; this.context = context;
this.request = request; this.request = request;
this.writeHeadBuffer = context.pollBuffer(); this.bufferPool = request.bufferPool;
this.writeBodyBuffer = context.pollBuffer(); this.responsePool = responsePool;
this.writeHeadBuffer = bufferPool.get();
this.writeBodyBuffer = bufferPool.get();
this.bodyBufferSupplier = () -> { this.bodyBufferSupplier = () -> {
ByteBuffer buffer = writeBodyBuffer; ByteBuffer buffer = writeBodyBuffer;
if (buffer == null) return context.pollBuffer(); if (buffer == null) return bufferPool.get();
writeBodyBuffer = null; writeBodyBuffer = null;
return buffer; return buffer;
}; };
@@ -141,14 +148,14 @@ public abstract class Response<C extends Context, R extends Request<C>> {
protected ByteBuffer pollWriteReadBuffer() { protected ByteBuffer pollWriteReadBuffer() {
ByteBuffer buffer = this.writeHeadBuffer; ByteBuffer buffer = this.writeHeadBuffer;
this.writeHeadBuffer = null; this.writeHeadBuffer = null;
if (buffer == null) buffer = context.pollBuffer(); if (buffer == null) buffer = bufferPool.get();
return buffer; return buffer;
} }
protected ByteBuffer pollWriteBodyBuffer() { protected ByteBuffer pollWriteBodyBuffer() {
ByteBuffer buffer = this.writeBodyBuffer; ByteBuffer buffer = this.writeBodyBuffer;
this.writeBodyBuffer = null; this.writeBodyBuffer = null;
if (buffer == null) buffer = context.pollBuffer(); if (buffer == null) buffer = bufferPool.get();
return buffer; return buffer;
} }
@@ -157,7 +164,9 @@ public abstract class Response<C extends Context, R extends Request<C>> {
} }
protected void offerBuffer(ByteBuffer... buffers) { protected void offerBuffer(ByteBuffer... buffers) {
context.offerBuffer(buffers); for (ByteBuffer buffer : buffers) {
bufferPool.accept(buffer);
}
} }
protected AsyncConnection removeChannel() { protected AsyncConnection removeChannel() {
@@ -251,24 +260,25 @@ public abstract class Response<C extends Context, R extends Request<C>> {
} }
this.recycleListener = null; this.recycleListener = null;
} }
if (request.keepAlive && channel != null) { if (request.more) removeChannel();
if (request.keepAlive && !request.more && channel != null) {
if (channel.isOpen()) { if (channel.isOpen()) {
AsyncConnection conn = removeChannel(); AsyncConnection conn = removeChannel();
this.recycle(); this.recycle();
this.prepare(); this.prepare();
new PrepareRunner(context, conn, null, this).run(); new PrepareRunner(context, this.responsePool, conn, null, this).run();
} else { } else {
channel.dispose(); channel.dispose();
} }
} else { } else {
this.context.responsePool.accept(this); this.responsePool.accept(this);
} }
} }
public void finish(final byte[] bs) { public void finish(final byte[] bs) {
if (!this.inited) return; //避免重复关闭 if (!this.inited) return; //避免重复关闭
if (this.context.bufferCapacity == bs.length) { if (this.context.bufferCapacity == bs.length) {
ByteBuffer buffer = this.context.pollBuffer(); ByteBuffer buffer = this.bufferPool.get();
buffer.put(bs); buffer.put(bs);
buffer.flip(); buffer.flip();
this.finish(buffer); this.finish(buffer);
@@ -279,24 +289,44 @@ public abstract class Response<C extends Context, R extends Request<C>> {
public void finish(ByteBuffer buffer) { public void finish(ByteBuffer buffer) {
if (!this.inited) return; //避免重复关闭 if (!this.inited) return; //避免重复关闭
this.channel.write(buffer, buffer, finishHandler); ByteBuffer data = this.request.removeMoredata();
final AsyncConnection conn = this.channel;
final boolean more = data != null && this.request.keepAlive;
this.request.more = more;
conn.write(buffer, buffer, finishHandler);
if (more) new PrepareRunner(this.context, this.responsePool, conn, data, null).run();
} }
public void finish(boolean kill, ByteBuffer buffer) { public void finish(boolean kill, ByteBuffer buffer) {
if (!this.inited) return; //避免重复关闭 if (!this.inited) return; //避免重复关闭
if (kill) refuseAlive(); if (kill) refuseAlive();
this.channel.write(buffer, buffer, finishHandler); ByteBuffer data = this.request.removeMoredata();
final AsyncConnection conn = this.channel;
final boolean more = data != null && this.request.keepAlive;
this.request.more = more;
conn.write(buffer, buffer, finishHandler);
if (more) new PrepareRunner(this.context, this.responsePool, conn, data, null).run();
} }
public void finish(ByteBuffer... buffers) { public void finish(ByteBuffer... buffers) {
if (!this.inited) return; //避免重复关闭 if (!this.inited) return; //避免重复关闭
this.channel.write(buffers, buffers, finishHandler2); final AsyncConnection conn = this.channel;
ByteBuffer data = this.request.removeMoredata();
final boolean more = data != null && this.request.keepAlive;
this.request.more = more;
conn.write(buffers, buffers, finishHandler2);
if (more) new PrepareRunner(this.context, this.responsePool, conn, data, null).run();
} }
public void finish(boolean kill, ByteBuffer... buffers) { public void finish(boolean kill, ByteBuffer... buffers) {
if (!this.inited) return; //避免重复关闭 if (!this.inited) return; //避免重复关闭
if (kill) refuseAlive(); if (kill) refuseAlive();
this.channel.write(buffers, buffers, finishHandler2); final AsyncConnection conn = this.channel;
ByteBuffer data = this.request.removeMoredata();
final boolean more = data != null && this.request.keepAlive;
this.request.more = more;
conn.write(buffers, buffers, finishHandler2);
if (more) new PrepareRunner(this.context, this.responsePool, conn, data, null).run();
} }
protected <A> void send(final ByteBuffer buffer, final A attachment, final CompletionHandler<Integer, A> handler) { protected <A> void send(final ByteBuffer buffer, final A attachment, final CompletionHandler<Integer, A> handler) {
@@ -307,14 +337,14 @@ public abstract class Response<C extends Context, R extends Request<C>> {
if (buffer.hasRemaining()) { if (buffer.hasRemaining()) {
channel.write(buffer, attachment, this); channel.write(buffer, attachment, this);
} else { } else {
context.offerBuffer(buffer); bufferPool.accept(buffer);
if (handler != null) handler.completed(result, attachment); if (handler != null) handler.completed(result, attachment);
} }
} }
@Override @Override
public void failed(Throwable exc, A attachment) { public void failed(Throwable exc, A attachment) {
context.offerBuffer(buffer); bufferPool.accept(buffer);
if (handler != null) handler.failed(exc, attachment); if (handler != null) handler.failed(exc, attachment);
} }
@@ -332,7 +362,7 @@ public abstract class Response<C extends Context, R extends Request<C>> {
index = i; index = i;
break; break;
} }
context.offerBuffer(buffers[i]); bufferPool.accept(buffers[i]);
} }
if (index == 0) { if (index == 0) {
channel.write(buffers, attachment, this); channel.write(buffers, attachment, this);
@@ -346,7 +376,7 @@ public abstract class Response<C extends Context, R extends Request<C>> {
@Override @Override
public void failed(Throwable exc, A attachment) { public void failed(Throwable exc, A attachment) {
for (ByteBuffer buffer : buffers) { for (ByteBuffer buffer : buffers) {
context.offerBuffer(buffer); bufferPool.accept(buffer);
} }
if (handler != null) handler.failed(exc, attachment); if (handler != null) handler.failed(exc, attachment);
} }

View File

@@ -7,12 +7,13 @@ package org.redkale.net;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import java.nio.ByteBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.text.*; import java.text.*;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.*;
import java.util.logging.Logger; import java.util.logging.*;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import org.redkale.util.*; import org.redkale.util.*;
@@ -126,8 +127,8 @@ public abstract class Server<K extends Serializable, C extends Context, R extend
this.writeTimeoutSeconds = config.getIntValue("writeTimeoutSeconds", 0); this.writeTimeoutSeconds = config.getIntValue("writeTimeoutSeconds", 0);
this.backlog = parseLenth(config.getValue("backlog"), 8 * 1024); this.backlog = parseLenth(config.getValue("backlog"), 8 * 1024);
this.maxbody = parseLenth(config.getValue("maxbody"), 64 * 1024); this.maxbody = parseLenth(config.getValue("maxbody"), 64 * 1024);
int bufCapacity = parseLenth(config.getValue("bufferCapacity"), 32 * 1024); int bufCapacity = parseLenth(config.getValue("bufferCapacity"), "UDP".equalsIgnoreCase(protocol) ? 1350 : 32 * 1024);
this.bufferCapacity = bufCapacity < 8 * 1024 ? 8 * 1024 : bufCapacity; this.bufferCapacity = "UDP".equalsIgnoreCase(protocol) ? bufCapacity : (bufCapacity < 8 * 1024 ? 8 * 1024 : bufCapacity);
this.threads = config.getIntValue("threads", Runtime.getRuntime().availableProcessors() * 32); this.threads = config.getIntValue("threads", Runtime.getRuntime().availableProcessors() * 32);
this.bufferPoolSize = config.getIntValue("bufferPoolSize", this.threads * 4); this.bufferPoolSize = config.getIntValue("bufferPoolSize", this.threads * 4);
this.responsePoolSize = config.getIntValue("responsePoolSize", this.threads * 2); this.responsePoolSize = config.getIntValue("responsePoolSize", this.threads * 2);
@@ -280,15 +281,96 @@ public abstract class Server<K extends Serializable, C extends Context, R extend
this.serverChannel = ProtocolServer.create(this.protocol, context, this.serverClassLoader, config == null ? null : config.getValue("netimpl")); this.serverChannel = ProtocolServer.create(this.protocol, context, this.serverClassLoader, config == null ? null : config.getValue("netimpl"));
this.serverChannel.open(config); this.serverChannel.open(config);
serverChannel.bind(address, backlog); serverChannel.bind(address, backlog);
serverChannel.accept(); serverChannel.accept(this);
final String threadName = "[" + Thread.currentThread().getName() + "] "; final String threadName = "[" + Thread.currentThread().getName() + "] ";
postStart();
logger.info(threadName + this.getClass().getSimpleName() + ("TCP".equalsIgnoreCase(protocol) ? "" : ("." + protocol)) + " listen: " + address logger.info(threadName + this.getClass().getSimpleName() + ("TCP".equalsIgnoreCase(protocol) ? "" : ("." + protocol)) + " listen: " + address
+ ", threads: " + threads + ", maxbody: " + formatLenth(context.maxbody) + ", bufferCapacity: " + formatLenth(bufferCapacity) + ", bufferPoolSize: " + bufferPoolSize + ", responsePoolSize: " + responsePoolSize + ", threads: " + threads + ", maxbody: " + formatLenth(context.maxbody) + ", bufferCapacity: " + formatLenth(bufferCapacity) + ", bufferPoolSize: " + bufferPoolSize + ", responsePoolSize: " + responsePoolSize
+ ", started in " + (System.currentTimeMillis() - context.getServerStartTime()) + " ms"); + ", started in " + (System.currentTimeMillis() - context.getServerStartTime()) + " ms");
} }
protected void postStart() {
}
public void changeAddress(final InetSocketAddress addr) throws IOException {
long s = System.currentTimeMillis();
Objects.requireNonNull(addr);
final InetSocketAddress oldAddress = context.address;
final ProtocolServer oldServerChannel = this.serverChannel;
context.address = addr;
ProtocolServer newServerChannel = null;
try {
newServerChannel = ProtocolServer.create(this.protocol, context, this.serverClassLoader, config == null ? null : config.getValue("netimpl"));
newServerChannel.open(config);
newServerChannel.bind(addr, backlog);
newServerChannel.accept(this);
} catch (IOException e) {
context.address = oldAddress;
throw e;
}
this.address = context.address;
this.serverChannel = newServerChannel;
final String threadName = "[" + Thread.currentThread().getName() + "] ";
logger.info(threadName + this.getClass().getSimpleName() + ("TCP".equalsIgnoreCase(protocol) ? "" : ("." + protocol))
+ " change address listen: " + address + ", started in " + (System.currentTimeMillis() - s) + " ms");
if (oldServerChannel != null) {
new Thread() {
@Override
public void run() {
try {
Thread.sleep(10_000);
oldServerChannel.close();
} catch (Exception e) {
logger.log(Level.WARNING, "Server.changeInetSocketAddress(addr=" + addr + ") error", e);
}
}
}.start();
}
}
public void changeMaxconns(final int newmaxconns) {
this.maxconns = newmaxconns;
if (this.context != null) this.context.maxconns = newmaxconns;
if (this.serverChannel != null) this.serverChannel.maxconns = newmaxconns;
}
public void changeCharset(final Charset newcharset) {
this.charset = newcharset;
if (this.context != null) this.context.charset = newcharset;
}
public void changeMaxbody(final int newmaxbody) {
this.maxbody = newmaxbody;
if (this.context != null) this.context.maxbody = newmaxbody;
}
public void changeReadTimeoutSeconds(final int newReadTimeoutSeconds) {
this.readTimeoutSeconds = newReadTimeoutSeconds;
if (this.context != null) this.context.readTimeoutSeconds = newReadTimeoutSeconds;
}
public void changeWriteTimeoutSeconds(final int newWriteTimeoutSeconds) {
this.writeTimeoutSeconds = newWriteTimeoutSeconds;
if (this.context != null) this.context.writeTimeoutSeconds = newWriteTimeoutSeconds;
}
public void changeAliveTimeoutSeconds(final int newAliveTimeoutSeconds) {
this.aliveTimeoutSeconds = newAliveTimeoutSeconds;
if (this.context != null) this.context.aliveTimeoutSeconds = newAliveTimeoutSeconds;
}
protected abstract C createContext(); protected abstract C createContext();
//必须在 createContext()之后调用
protected abstract ObjectPool<ByteBuffer> createBufferPool(AtomicLong createCounter, AtomicLong cycleCounter, int bufferPoolSize);
//必须在 createContext()之后调用
protected abstract ObjectPool<Response> createResponsePool(AtomicLong createCounter, AtomicLong cycleCounter, int responsePoolSize);
//必须在 createResponsePool()之后调用
protected abstract Creator<Response> createResponseCreator(ObjectPool<ByteBuffer> bufferPool, ObjectPool<Response> responsePool);
public void shutdown() throws IOException { public void shutdown() throws IOException {
long s = System.currentTimeMillis(); long s = System.currentTimeMillis();
logger.info(this.getClass().getSimpleName() + "-" + this.protocol + " shutdowning"); logger.info(this.getClass().getSimpleName() + "-" + this.protocol + " shutdowning");
@@ -396,7 +478,9 @@ public abstract class Server<K extends Serializable, C extends Context, R extend
if (s.endsWith("*")) { if (s.endsWith("*")) {
File root = new File(s.substring(0, s.length() - 1)); File root = new File(s.substring(0, s.length() - 1));
if (root.isDirectory()) { if (root.isDirectory()) {
for (File f : root.listFiles()) { File[] lfs = root.listFiles();
if (lfs == null) throw new RuntimeException("File(" + root + ") cannot listFiles()");
for (File f : lfs) {
set.add(f.toURI().toURL()); set.add(f.toURI().toURL());
} }
} }
@@ -410,7 +494,7 @@ public abstract class Server<K extends Serializable, C extends Context, R extend
classLoader.addURL(url); classLoader.addURL(url);
} }
List<URL> list = new ArrayList<>(set); List<URL> list = new ArrayList<>(set);
Collections.sort(list, (URL o1, URL o2) -> o1.getFile().compareTo(o2.getFile())); list.sort((URL o1, URL o2) -> o1.getFile().compareTo(o2.getFile()));
return list.toArray(new URL[list.size()]); return list.toArray(new URL[list.size()]);
} }

View File

@@ -23,11 +23,13 @@ public abstract class Servlet<C extends Context, R extends Request<C>, P extends
AnyValue _conf; //当前Servlet的配置 AnyValue _conf; //当前Servlet的配置
//Server执行start时运行此方法
public void init(C context, AnyValue config) { public void init(C context, AnyValue config) {
} }
public abstract void execute(R request, P response) throws IOException; public abstract void execute(R request, P response) throws IOException;
//Server执行shutdown后运行此方法
public void destroy(C context, AnyValue config) { public void destroy(C context, AnyValue config) {
} }

View File

@@ -12,6 +12,7 @@ import java.nio.channels.*;
import java.util.Set; import java.util.Set;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.function.*;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
/** /**
@@ -23,6 +24,8 @@ import javax.net.ssl.SSLContext;
*/ */
public class TcpAioAsyncConnection extends AsyncConnection { public class TcpAioAsyncConnection extends AsyncConnection {
private final Semaphore semaphore = new Semaphore(1);
private int readTimeoutSeconds; private int readTimeoutSeconds;
private int writeTimeoutSeconds; private int writeTimeoutSeconds;
@@ -31,11 +34,14 @@ public class TcpAioAsyncConnection extends AsyncConnection {
private final SocketAddress remoteAddress; private final SocketAddress remoteAddress;
public TcpAioAsyncConnection(final AsynchronousSocketChannel ch, SSLContext sslContext, private BlockingQueue<WriteEntry> writeQueue;
final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds,
public TcpAioAsyncConnection(Supplier<ByteBuffer> bufferSupplier, Consumer<ByteBuffer> bufferConsumer,
final AsynchronousSocketChannel ch, final SSLContext sslContext, final SocketAddress addr0,
final int readTimeoutSeconds, final int writeTimeoutSeconds,
final AtomicLong livingCounter, final AtomicLong closedCounter) { final AtomicLong livingCounter, final AtomicLong closedCounter) {
super(bufferSupplier, bufferConsumer, sslContext);
this.channel = ch; this.channel = ch;
this.sslContext = sslContext;
this.readTimeoutSeconds = readTimeoutSeconds; this.readTimeoutSeconds = readTimeoutSeconds;
this.writeTimeoutSeconds = writeTimeoutSeconds; this.writeTimeoutSeconds = writeTimeoutSeconds;
SocketAddress addr = addr0; SocketAddress addr = addr0;
@@ -87,48 +93,108 @@ public class TcpAioAsyncConnection extends AsyncConnection {
} }
@Override @Override
public <A> void read(ByteBuffer dst, A attachment, CompletionHandler<Integer, ? super A> handler) { public void read(CompletionHandler<Integer, ByteBuffer> handler) {
this.readtime = System.currentTimeMillis(); this.readtime = System.currentTimeMillis();
ByteBuffer dst = pollReadBuffer();
if (readTimeoutSeconds > 0) { if (readTimeoutSeconds > 0) {
channel.read(dst, readTimeoutSeconds, TimeUnit.SECONDS, attachment, handler); channel.read(dst, readTimeoutSeconds, TimeUnit.SECONDS, dst, handler);
} else { } else {
channel.read(dst, attachment, handler); channel.read(dst, dst, handler);
}
}
private <A> void nextWrite(Throwable exc, A attachment) {
BlockingQueue<WriteEntry> queue = this.writeQueue;
if (queue != null && exc != null && !isOpen()) {
WriteEntry entry;
while ((entry = queue.poll()) != null) {
try {
entry.writeHandler.failed(exc, entry.writeAttachment);
} catch (Throwable e) {
e.printStackTrace(System.err);
}
}
return;
}
WriteEntry entry = queue == null ? null : queue.poll();
if (entry != null) {
try {
if (entry.writeOneBuffer == null) {
write(false, entry.writeBuffers, entry.writeOffset, entry.writeLength, entry.writeAttachment, entry.writeHandler);
} else {
write(false, entry.writeOneBuffer, entry.writeAttachment, entry.writeHandler);
}
} catch (Exception e) {
entry.writeHandler.failed(e, entry.writeAttachment);
}
} else {
semaphore.release();
} }
} }
@Override @Override
public <A> void read(ByteBuffer dst, long timeout, TimeUnit unit, A attachment, CompletionHandler<Integer, ? super A> handler) { public <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer, ? super A> handler) {
this.readtime = System.currentTimeMillis(); write(true, src, attachment, handler);
channel.read(dst, timeout < 0 ? 0 : timeout, unit, attachment, handler);
} }
@Override private <A> void write(boolean acquire, ByteBuffer src, A attachment, CompletionHandler<Integer, ? super A> handler) {
public <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer, ? super A> handler) { if (acquire && !semaphore.tryAcquire()) {
if (this.writeQueue == null) {
synchronized (semaphore) {
if (this.writeQueue == null) {
this.writeQueue = new LinkedBlockingDeque<>();
}
}
}
this.writeQueue.add(new WriteEntry(src, attachment, handler));
return;
}
WriteOneCompletionHandler newHandler = new WriteOneCompletionHandler(src, handler);
if (!channel.isOpen()) {
newHandler.failed(new ClosedChannelException(), attachment);
return;
}
this.writetime = System.currentTimeMillis(); this.writetime = System.currentTimeMillis();
if (writeTimeoutSeconds > 0) { try {
channel.write(src, writeTimeoutSeconds, TimeUnit.SECONDS, attachment, handler); if (writeTimeoutSeconds > 0) {
} else { channel.write(src, writeTimeoutSeconds, TimeUnit.SECONDS, attachment, newHandler);
channel.write(src, attachment, handler); } else {
channel.write(src, attachment, newHandler);
}
} catch (Exception e) {
newHandler.failed(e, attachment);
} }
} }
@Override @Override
public <A> void write(ByteBuffer[] srcs, int offset, int length, A attachment, final CompletionHandler<Integer, ? super A> handler) { public <A> void write(ByteBuffer[] srcs, int offset, int length, A attachment, final CompletionHandler<Integer, ? super A> handler) {
write(true, srcs, offset, length, attachment, handler);
}
private <A> void write(boolean acquire, ByteBuffer[] srcs, int offset, int length, A attachment, final CompletionHandler<Integer, ? super A> handler) {
if (acquire && !semaphore.tryAcquire()) {
if (this.writeQueue == null) {
synchronized (semaphore) {
if (this.writeQueue == null) {
this.writeQueue = new LinkedBlockingDeque<>();
}
}
}
this.writeQueue.add(new WriteEntry(srcs, offset, length, attachment, handler));
return;
}
WriteMoreCompletionHandler newHandler = new WriteMoreCompletionHandler(srcs, offset, length, handler);
if (!channel.isOpen()) {
newHandler.failed(new ClosedChannelException(), attachment);
return;
}
this.writetime = System.currentTimeMillis(); this.writetime = System.currentTimeMillis();
channel.write(srcs, offset, length, writeTimeoutSeconds > 0 ? writeTimeoutSeconds : 60, TimeUnit.SECONDS, try {
attachment, new CompletionHandler<Long, A>() { channel.write(srcs, offset, length, writeTimeoutSeconds > 0 ? writeTimeoutSeconds : 60, TimeUnit.SECONDS, attachment, newHandler);
} catch (Exception e) {
@Override newHandler.failed(e, attachment);
public void completed(Long result, A attachment) { }
handler.completed(result.intValue(), attachment);
}
@Override
public void failed(Throwable exc, A attachment) {
handler.failed(exc, attachment);
}
});
} }
@Override @Override
@@ -166,19 +232,38 @@ public class TcpAioAsyncConnection extends AsyncConnection {
} }
@Override @Override
public final Future<Integer> read(ByteBuffer dst) { public final int read(ByteBuffer dst) throws IOException {
return channel.read(dst); try {
return channel.read(dst).get();
} catch (InterruptedException | ExecutionException e) {
throw new IOException(e);
}
} }
@Override @Override
public final Future<Integer> write(ByteBuffer src) { public final int write(ByteBuffer src) throws IOException {
return channel.write(src); try {
return channel.write(src).get();
} catch (InterruptedException | ExecutionException e) {
throw new IOException(e);
}
} }
@Override @Override
public final void close() throws IOException { public final void close() throws IOException {
super.close(); super.close();
channel.close(); channel.close();
BlockingQueue<WriteEntry> queue = this.writeQueue;
if (queue == null) return;
WriteEntry entry;
Exception ex = null;
while ((entry = queue.poll()) != null) {
if (ex == null) ex = new ClosedChannelException();
try {
entry.writeHandler.failed(ex, entry.writeAttachment);
} catch (Exception e) {
}
}
} }
@Override @Override
@@ -191,4 +276,141 @@ public class TcpAioAsyncConnection extends AsyncConnection {
return true; return true;
} }
private class WriteMoreCompletionHandler<A> implements CompletionHandler<Long, A> {
private final CompletionHandler<Integer, A> writeHandler;
private final ByteBuffer[] writeBuffers;
private int writeOffset;
private int writeLength;
private int writeCount;
public WriteMoreCompletionHandler(ByteBuffer[] buffers, int offset, int length, CompletionHandler handler) {
this.writeBuffers = buffers;
this.writeOffset = offset;
this.writeLength = length;
this.writeHandler = handler;
}
@Override
public void completed(Long result, A attachment) {
if (result >= 0) {
writeCount += result;
try {
int index = -1;
for (int i = writeOffset; i < (writeOffset + writeLength); i++) {
if (writeBuffers[i].hasRemaining()) {
index = i;
break;
}
}
if (index >= 0) {
writeOffset += index;
writeLength -= index;
channel.write(writeBuffers, writeOffset, writeLength, writeTimeoutSeconds > 0 ? writeTimeoutSeconds : 60, TimeUnit.SECONDS, attachment, this);
return;
}
} catch (Exception e) {
failed(e, attachment);
return;
}
try {
writeHandler.completed(writeCount, attachment);
} finally {
nextWrite(null, attachment);
}
} else {
try {
writeHandler.completed(result.intValue(), attachment);
} finally {
nextWrite(null, attachment);
}
}
}
@Override
public void failed(Throwable exc, A attachment) {
try {
writeHandler.failed(exc, attachment);
} finally {
nextWrite(exc, attachment);
}
}
}
private class WriteOneCompletionHandler<A> implements CompletionHandler<Integer, A> {
private final CompletionHandler writeHandler;
private final ByteBuffer writeOneBuffer;
public WriteOneCompletionHandler(ByteBuffer buffer, CompletionHandler handler) {
this.writeOneBuffer = buffer;
this.writeHandler = handler;
}
@Override
public void completed(Integer result, A attachment) {
try {
if (writeOneBuffer.hasRemaining()) {
channel.write(writeOneBuffer, attachment, this);
return;
}
} catch (Exception e) {
failed(e, attachment);
return;
}
try {
writeHandler.completed(result, attachment);
} finally {
nextWrite(null, attachment);
}
}
@Override
public void failed(Throwable exc, A attachment) {
try {
writeHandler.failed(exc, attachment);
} finally {
nextWrite(exc, attachment);
}
}
}
private static class WriteEntry {
ByteBuffer writeOneBuffer;
ByteBuffer[] writeBuffers;
int writingCount;
int writeOffset;
int writeLength;
Object writeAttachment;
CompletionHandler writeHandler;
public WriteEntry(ByteBuffer writeOneBuffer, Object writeAttachment, CompletionHandler writeHandler) {
this.writeOneBuffer = writeOneBuffer;
this.writeAttachment = writeAttachment;
this.writeHandler = writeHandler;
}
public WriteEntry(ByteBuffer[] writeBuffers, int writeOffset, int writeLength, Object writeAttachment, CompletionHandler writeHandler) {
this.writeBuffers = writeBuffers;
this.writeOffset = writeOffset;
this.writeLength = writeLength;
this.writeAttachment = writeAttachment;
this.writeHandler = writeHandler;
}
}
} }

View File

@@ -7,10 +7,12 @@ package org.redkale.net;
import java.io.IOException; import java.io.IOException;
import java.net.*; import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.*; import java.nio.channels.*;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level; import java.util.logging.Level;
import org.redkale.util.AnyValue; import org.redkale.util.*;
/** /**
* 协议底层Server * 协议底层Server
@@ -32,7 +34,8 @@ public class TcpAioProtocolServer extends ProtocolServer {
@Override @Override
public void open(AnyValue config) throws IOException { public void open(AnyValue config) throws IOException {
group = AsynchronousChannelGroup.withThreadPool(context.executor); //group = AsynchronousChannelGroup.withThreadPool(context.executor);
group = AsynchronousChannelGroup.withFixedThreadPool(context.executor.getCorePoolSize(), context.executor.getThreadFactory());
this.serverChannel = AsynchronousServerSocketChannel.open(group); this.serverChannel = AsynchronousServerSocketChannel.open(group);
final Set<SocketOption<?>> options = this.serverChannel.supportedOptions(); final Set<SocketOption<?>> options = this.serverChannel.supportedOptions();
@@ -69,7 +72,14 @@ public class TcpAioProtocolServer extends ProtocolServer {
} }
@Override @Override
public void accept() throws IOException { public void accept(Server server) throws IOException {
AtomicLong createBufferCounter = new AtomicLong();
AtomicLong cycleBufferCounter = new AtomicLong();
ObjectPool<ByteBuffer> bufferPool = server.createBufferPool(createBufferCounter, cycleBufferCounter, server.bufferPoolSize);
AtomicLong createResponseCounter = new AtomicLong();
AtomicLong cycleResponseCounter = new AtomicLong();
ObjectPool<Response> responsePool = server.createResponsePool(createResponseCounter, cycleResponseCounter, server.responsePoolSize);
responsePool.setCreator(server.createResponseCreator(bufferPool, responsePool));
final AsynchronousServerSocketChannel serchannel = this.serverChannel; final AsynchronousServerSocketChannel serchannel = this.serverChannel;
serchannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() { serchannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
@@ -91,13 +101,13 @@ public class TcpAioProtocolServer extends ProtocolServer {
channel.setOption(StandardSocketOptions.SO_REUSEADDR, true); channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
channel.setOption(StandardSocketOptions.SO_RCVBUF, 16 * 1024); channel.setOption(StandardSocketOptions.SO_RCVBUF, 16 * 1024);
channel.setOption(StandardSocketOptions.SO_SNDBUF, 16 * 1024); channel.setOption(StandardSocketOptions.SO_SNDBUF, 16 * 1024);
} catch (IOException e) {
context.logger.log(Level.INFO, channel + " setOption error", e); AsyncConnection conn = new TcpAioAsyncConnection(bufferPool, bufferPool, channel,
context.getSSLContext(), null, context.readTimeoutSeconds, context.writeTimeoutSeconds, livingCounter, closedCounter);
context.runAsync(new PrepareRunner(context, responsePool, conn, null, null));
} catch (Throwable e) {
context.logger.log(Level.INFO, channel + " accept error", e);
} }
AsyncConnection conn = new TcpAioAsyncConnection(channel, context.sslContext, null, context.readTimeoutSeconds, context.writeTimeoutSeconds, null, null);
conn.livingCounter = livingCounter;
conn.closedCounter = closedCounter;
context.runAsync(new PrepareRunner(context, conn, null, null));
} }
@Override @Override

View File

@@ -1,240 +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.net;
import java.io.IOException;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
/**
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
*/
public class TcpBioAsyncConnection extends AsyncConnection {
static final Set<SocketOption<?>> defaultOptions = defaultOptions();
private static Set<SocketOption<?>> defaultOptions() {
HashSet<SocketOption<?>> set = new HashSet<>(5);
set.add(StandardSocketOptions.SO_SNDBUF);
set.add(StandardSocketOptions.SO_RCVBUF);
set.add(StandardSocketOptions.SO_KEEPALIVE);
set.add(StandardSocketOptions.SO_REUSEADDR);
set.add(StandardSocketOptions.TCP_NODELAY);
return Collections.unmodifiableSet(set);
}
private int readTimeoutSeconds;
private int writeTimeoutSeconds;
private final Socket socket;
private final ReadableByteChannel readChannel;
private final WritableByteChannel writeChannel;
private final SocketAddress remoteAddress;
public TcpBioAsyncConnection(final Socket socket, final SocketAddress addr0, final int readTimeoutSeconds0, final int writeTimeoutSeconds0,
final AtomicLong livingCounter, final AtomicLong closedCounter) {
this.socket = socket;
ReadableByteChannel rc = null;
WritableByteChannel wc = null;
try {
socket.setSoTimeout(Math.max(readTimeoutSeconds0, writeTimeoutSeconds0));
rc = Channels.newChannel(socket.getInputStream());
wc = Channels.newChannel(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
this.readChannel = rc;
this.writeChannel = wc;
this.readTimeoutSeconds = readTimeoutSeconds0;
this.writeTimeoutSeconds = writeTimeoutSeconds0;
SocketAddress addr = addr0;
if (addr == null) {
try {
addr = socket.getRemoteSocketAddress();
} catch (Exception e) {
//do nothing
}
}
this.remoteAddress = addr;
this.livingCounter = livingCounter;
this.closedCounter = closedCounter;
}
@Override
public boolean isTCP() {
return true;
}
@Override
public SocketAddress getRemoteAddress() {
return remoteAddress;
}
@Override
public SocketAddress getLocalAddress() {
return socket.getLocalSocketAddress();
}
@Override
public int getReadTimeoutSeconds() {
return readTimeoutSeconds;
}
@Override
public int getWriteTimeoutSeconds() {
return writeTimeoutSeconds;
}
@Override
public void setReadTimeoutSeconds(int readTimeoutSeconds) {
this.readTimeoutSeconds = readTimeoutSeconds;
}
@Override
public void setWriteTimeoutSeconds(int writeTimeoutSeconds) {
this.writeTimeoutSeconds = writeTimeoutSeconds;
}
@Override
public boolean shutdownInput() {
try {
this.socket.shutdownInput();
return true;
} catch (IOException e) {
return false;
}
}
@Override
public boolean shutdownOutput() {
try {
this.socket.shutdownOutput();
return true;
} catch (IOException e) {
return false;
}
}
@Override
public <T> boolean setOption(SocketOption<T> name, T value) {
try {
if (StandardSocketOptions.SO_REUSEADDR == name) {
this.socket.setReuseAddress((Boolean) value);
return true;
}
if (StandardSocketOptions.SO_KEEPALIVE == name) {
this.socket.setKeepAlive((Boolean) value);
return true;
}
if (StandardSocketOptions.TCP_NODELAY == name) {
this.socket.setTcpNoDelay((Boolean) value);
return true;
}
if (StandardSocketOptions.SO_RCVBUF == name) {
this.socket.setReceiveBufferSize((Integer) value);
return true;
}
if (StandardSocketOptions.SO_SNDBUF == name) {
this.socket.setSendBufferSize((Integer) value);
return true;
}
} catch (IOException e) {
return false;
}
return false;
}
@Override
public Set<SocketOption<?>> supportedOptions() {
return defaultOptions;
}
@Override
public <A> void write(ByteBuffer[] srcs, int offset, int length, A attachment, CompletionHandler<Integer, ? super A> handler) {
try {
int rs = 0;
for (int i = offset; i < offset + length; i++) {
rs += writeChannel.write(srcs[i]);
}
this.writetime = System.currentTimeMillis();
if (handler != null) handler.completed(rs, attachment);
} catch (IOException e) {
if (handler != null) handler.failed(e, attachment);
}
}
@Override
public <A> void read(ByteBuffer dst, A attachment, CompletionHandler<Integer, ? super A> handler) {
try {
int rs = readChannel.read(dst);
this.readtime = System.currentTimeMillis();
if (handler != null) handler.completed(rs, attachment);
} catch (IOException e) {
if (handler != null) handler.failed(e, attachment);
}
}
@Override
public <A> void read(ByteBuffer dst, long timeout, TimeUnit unit, A attachment, CompletionHandler<Integer, ? super A> handler) {
read(dst, attachment, handler);
}
@Override
public Future<Integer> read(ByteBuffer dst) {
try {
int rs = readChannel.read(dst);
this.readtime = System.currentTimeMillis();
return CompletableFuture.completedFuture(rs);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer, ? super A> handler) {
try {
int rs = writeChannel.write(src);
this.writetime = System.currentTimeMillis();
if (handler != null) handler.completed(rs, attachment);
} catch (IOException e) {
if (handler != null) handler.failed(e, attachment);
}
}
@Override
public Future<Integer> write(ByteBuffer src) {
try {
int rs = writeChannel.write(src);
this.writetime = System.currentTimeMillis();
return CompletableFuture.completedFuture(rs);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void close() throws IOException {
super.close();
this.socket.close();
}
@Override
public boolean isOpen() {
return !socket.isClosed();
}
}

View File

@@ -1,365 +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.net;
import java.io.IOException;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Set;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
/**
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
*/
public class TcpNioAsyncConnection extends AsyncConnection {
private int readTimeoutSeconds;
private int writeTimeoutSeconds;
private final Selector selector;
private SelectionKey key;
private final SocketChannel channel;
private final SocketAddress remoteAddress;
ByteBuffer readBuffer;
Object readAttachment;
CompletionHandler readHandler;
ByteBuffer writeOneBuffer;
ByteBuffer[] writeBuffers;
int writingCount;
int writeOffset;
int writeLength;
Object writeAttachment;
CompletionHandler writeHandler;
public TcpNioAsyncConnection(final SocketChannel ch, SocketAddress addr0,
final Selector selector,
final int readTimeoutSeconds0, final int writeTimeoutSeconds0,
final AtomicLong livingCounter, final AtomicLong closedCounter) {
this.channel = ch;
this.selector = selector;
this.readTimeoutSeconds = readTimeoutSeconds0;
this.writeTimeoutSeconds = writeTimeoutSeconds0;
SocketAddress addr = addr0;
if (addr == null) {
try {
addr = ch.getRemoteAddress();
} catch (Exception e) {
//do nothing
}
}
this.remoteAddress = addr;
this.livingCounter = livingCounter;
this.closedCounter = closedCounter;
}
@Override
public void setReadTimeoutSeconds(int readTimeoutSeconds) {
this.readTimeoutSeconds = readTimeoutSeconds;
}
@Override
public void setWriteTimeoutSeconds(int writeTimeoutSeconds) {
this.writeTimeoutSeconds = writeTimeoutSeconds;
}
@Override
public int getReadTimeoutSeconds() {
return this.readTimeoutSeconds;
}
@Override
public int getWriteTimeoutSeconds() {
return this.writeTimeoutSeconds;
}
@Override
public final SocketAddress getRemoteAddress() {
return remoteAddress;
}
@Override
public SocketAddress getLocalAddress() {
try {
return channel.getLocalAddress();
} catch (IOException e) {
return null;
}
}
@Override
public boolean shutdownInput() {
try {
this.channel.shutdownInput();
return true;
} catch (IOException e) {
return false;
}
}
@Override
public boolean shutdownOutput() {
try {
this.channel.shutdownOutput();
return true;
} catch (IOException e) {
return false;
}
}
@Override
public <T> boolean setOption(SocketOption<T> name, T value) {
try {
this.channel.setOption(name, value);
return true;
} catch (IOException e) {
return false;
}
}
@Override
public Set<SocketOption<?>> supportedOptions() {
return this.channel.supportedOptions();
}
CompletionHandler removeReadHandler() {
CompletionHandler handler = this.readHandler;
this.readHandler = null;
return handler;
}
ByteBuffer removeReadBuffer() {
ByteBuffer buffer = this.readBuffer;
this.readBuffer = null;
return buffer;
}
Object removeReadAttachment() {
Object attach = this.readAttachment;
this.readAttachment = null;
return attach;
}
void completeRead(int rs) {
Object attach = this.readAttachment;
CompletionHandler handler = this.readHandler;
this.readBuffer = null;
this.readAttachment = null;
this.readHandler = null;
handler.completed(rs, attach);
}
void faileRead(Throwable t) {
Object attach = this.readAttachment;
CompletionHandler handler = this.readHandler;
this.readBuffer = null;
this.readAttachment = null;
this.readHandler = null;
handler.failed(t, attach);
}
CompletionHandler removeWriteHandler() {
CompletionHandler handler = this.writeHandler;
this.writeHandler = null;
return handler;
}
ByteBuffer removeWriteOneBuffer() {
ByteBuffer buffer = this.writeOneBuffer;
this.writeOneBuffer = null;
return buffer;
}
ByteBuffer[] removeWriteBuffers() {
ByteBuffer[] buffers = this.writeBuffers;
this.writeBuffers = null;
return buffers;
}
int removeWritingCount() {
int rs = this.writingCount;
this.writingCount = 0;
return rs;
}
int removeWriteOffset() {
int rs = this.writeOffset;
this.writeOffset = 0;
return rs;
}
int removeWriteLength() {
int rs = this.writeLength;
this.writeLength = 0;
return rs;
}
Object removeWriteAttachment() {
Object attach = this.writeAttachment;
this.writeAttachment = null;
return attach;
}
void completeWrite(int rs) {
Object attach = this.writeAttachment;
CompletionHandler handler = this.writeHandler;
this.writeOneBuffer = null;
this.writeBuffers = null;
this.writeOffset = 0;
this.writeLength = 0;
this.writeAttachment = null;
this.writeHandler = null;
handler.completed(rs, attach);
}
void faileWrite(Throwable t) {
Object attach = this.writeAttachment;
CompletionHandler handler = this.writeHandler;
this.writeOneBuffer = null;
this.writeBuffers = null;
this.writeOffset = 0;
this.writeLength = 0;
this.writeAttachment = null;
this.writeHandler = null;
handler.failed(t, attach);
}
@Override
public <A> void read(ByteBuffer dst, A attachment, CompletionHandler<Integer, ? super A> handler) {
if (this.readHandler != null) throw new RuntimeException("pending read");
try {
this.readBuffer = dst;
this.readAttachment = attachment;
this.readHandler = handler;
if (key == null) {
key = channel.register(selector, SelectionKey.OP_READ);
key.attach(this);
} else {
key.interestOps(SelectionKey.OP_READ);
}
selector.wakeup();
} catch (Exception e) {
faileRead(e);
}
}
@Override
public <A> void read(ByteBuffer dst, long timeout, TimeUnit unit, A attachment, CompletionHandler<Integer, ? super A> handler) {
read(dst, attachment, handler);
}
@Override
public Future<Integer> read(ByteBuffer dst) {
CompletableFuture future = new CompletableFuture();
read(dst, null, new CompletionHandler<Integer, Void>() {
@Override
public void completed(Integer result, Void attachment) {
future.complete(result);
}
@Override
public void failed(Throwable exc, Void attachment) {
future.completeExceptionally(exc);
}
});
return future;
}
@Override
public <A> void write(ByteBuffer[] srcs, int offset, int length, A attachment, CompletionHandler<Integer, ? super A> handler) {
if (this.writeHandler != null) throw new RuntimeException("pending write");
try {
this.writeBuffers = srcs;
this.writeOffset = offset;
this.writeLength = length;
this.writingCount = 0;
this.writeAttachment = attachment;
this.writeHandler = handler;
if (key == null) {
key = channel.register(selector, SelectionKey.OP_WRITE);
key.attach(this);
} else {
key.interestOps(SelectionKey.OP_WRITE);
}
selector.wakeup();
} catch (Exception e) {
faileWrite(e);
}
}
@Override
public <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer, ? super A> handler) {
if (this.writeHandler != null) throw new RuntimeException("pending write");
try {
this.writeOneBuffer = src;
this.writingCount = 0;
this.writeAttachment = attachment;
this.writeHandler = handler;
if (key == null) {
key = channel.register(selector, SelectionKey.OP_WRITE);
key.attach(this);
} else {
key.interestOps(SelectionKey.OP_WRITE);
}
selector.wakeup();
} catch (Exception e) {
faileWrite(e);
}
}
@Override
public Future<Integer> write(ByteBuffer src) {
CompletableFuture future = new CompletableFuture();
write(src, null, new CompletionHandler<Integer, Void>() {
@Override
public void completed(Integer result, Void attachment) {
future.complete(result);
}
@Override
public void failed(Throwable exc, Void attachment) {
future.completeExceptionally(exc);
}
});
return future;
}
@Override
public final void close() throws IOException {
super.close();
channel.close();
key.cancel();
}
@Override
public final boolean isOpen() {
return channel.isOpen();
}
@Override
public final boolean isTCP() {
return true;
}
}

View File

@@ -1,309 +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.net;
import java.io.IOException;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import org.redkale.util.AnyValue;
/**
* 协议底层Server
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
*/
public class TcpNioProtocolServer extends ProtocolServer {
private Selector acceptSelector;
private ServerSocketChannel serverChannel;
private NIOThreadWorker[] workers;
private NIOThreadWorker currWorker;
private boolean running;
public TcpNioProtocolServer(Context context) {
super(context);
}
@Override
public void open(AnyValue config) throws IOException {
acceptSelector = Selector.open();
this.serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
ServerSocket socket = serverChannel.socket();
socket.setReceiveBufferSize(16 * 1024);
socket.setReuseAddress(true);
final Set<SocketOption<?>> options = this.serverChannel.supportedOptions();
if (options.contains(StandardSocketOptions.TCP_NODELAY)) {
this.serverChannel.setOption(StandardSocketOptions.TCP_NODELAY, true);
}
if (options.contains(StandardSocketOptions.SO_KEEPALIVE)) {
this.serverChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
}
if (options.contains(StandardSocketOptions.SO_REUSEADDR)) {
this.serverChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
}
if (options.contains(StandardSocketOptions.SO_RCVBUF)) {
this.serverChannel.setOption(StandardSocketOptions.SO_RCVBUF, 16 * 1024);
}
if (options.contains(StandardSocketOptions.SO_SNDBUF)) {
this.serverChannel.setOption(StandardSocketOptions.SO_SNDBUF, 16 * 1024);
}
}
@Override
public void bind(SocketAddress local, int backlog) throws IOException {
this.serverChannel.bind(local, backlog);
}
@Override
public <T> Set<SocketOption<?>> supportedOptions() {
return this.serverChannel.supportedOptions();
}
@Override
public <T> void setOption(SocketOption<T> name, T value) throws IOException {
this.serverChannel.setOption(name, value);
}
@Override
public void accept() throws IOException {
this.serverChannel.register(acceptSelector, SelectionKey.OP_ACCEPT);
final CountDownLatch cdl = new CountDownLatch(1);
this.running = true;
this.workers = new NIOThreadWorker[Runtime.getRuntime().availableProcessors()];
for (int i = 0; i < workers.length; i++) {
workers[i] = new NIOThreadWorker();
workers[i].setDaemon(true);
workers[i].start();
}
for (int i = 0; i < workers.length - 1; i++) { //构成环形
workers[i].next = workers[i + 1];
}
workers[workers.length - 1].next = workers[0];
currWorker = workers[0];
new Thread() {
@Override
public void run() {
cdl.countDown();
while (running) {
try {
acceptSelector.select();
Set<SelectionKey> selectedKeys = acceptSelector.selectedKeys();
synchronized (selectedKeys) {
Iterator<?> iter = selectedKeys.iterator();
while (iter.hasNext()) {
SelectionKey key = (SelectionKey) iter.next();
iter.remove();
if (key.isAcceptable()) {
try {
SocketChannel channel = ((ServerSocketChannel) key.channel()).accept();
channel.configureBlocking(false);
channel.setOption(StandardSocketOptions.TCP_NODELAY, true);
channel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
channel.setOption(StandardSocketOptions.SO_RCVBUF, 16 * 1024);
channel.setOption(StandardSocketOptions.SO_SNDBUF, 16 * 1024);
createCounter.incrementAndGet();
livingCounter.incrementAndGet();
currWorker.addChannel(channel);
currWorker = currWorker.next;
} catch (IOException io) {
io.printStackTrace();
}
}
}
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}.start();
try {
cdl.await();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void close() throws IOException {
if (!this.running) return;
this.running = false;
serverChannel.close();
acceptSelector.close();
for (NIOThreadWorker worker : workers) {
worker.interrupt();
}
}
class NIOThreadWorker extends Thread {
final Selector selector;
NIOThreadWorker next;
public NIOThreadWorker() {
try {
this.selector = Selector.open();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void addChannel(SocketChannel channel) throws IOException {
AsyncConnection conn = new TcpNioAsyncConnection(channel, null, selector, context.readTimeoutSeconds, context.writeTimeoutSeconds, null, null);
context.runAsync(new PrepareRunner(context, conn, null, null));
}
@Override
public void run() {
while (running) {
try {
selector.select(50);
} catch (IOException e) {
e.printStackTrace();
}
try {
Set<SelectionKey> selectedKeys = selector.selectedKeys();
synchronized (selectedKeys) {
Iterator<?> iter = selectedKeys.iterator();
while (iter.hasNext()) {
SelectionKey key = (SelectionKey) iter.next();
iter.remove();
processKey(key);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void processKey(SelectionKey key) {
if (key == null || !key.isValid()) return;
SocketChannel socket = (SocketChannel) key.channel();
TcpNioAsyncConnection conn = (TcpNioAsyncConnection) key.attachment();
if (!socket.isOpen()) {
if (conn == null) {
key.cancel();
} else {
conn.dispose();
}
return;
}
if (conn == null) return;
if (key.isWritable()) {
if (conn.writeHandler != null) writeOP(key, socket, conn);
} else if (key.isReadable()) {
if (conn.readHandler != null) readOP(key, socket, conn);
}
}
private void readOP(SelectionKey key, SocketChannel socket, TcpNioAsyncConnection conn) {
final CompletionHandler handler = conn.removeReadHandler();
final ByteBuffer buffer = conn.removeReadBuffer();
final Object attach = conn.removeReadAttachment();
//System.out.println(conn + "------readbuf:" + buffer + "-------handler:" + handler);
if (handler == null || buffer == null) return;
try {
final int rs = socket.read(buffer);
{ //测试
buffer.flip();
byte[] bs = new byte[buffer.remaining()];
buffer.get(bs);
//System.out.println(conn + "------readbuf:" + buffer + "-------handler:" + handler + "-------读内容: " + new String(bs));
}
//System.out.println(conn + "------readbuf:" + buffer + "-------handler:" + handler + "-------read: " + rs);
context.runAsync(() -> {
try {
handler.completed(rs, attach);
} catch (Throwable e) {
handler.failed(e, attach);
}
});
} catch (Throwable t) {
context.runAsync(() -> handler.failed(t, attach));
}
}
private void writeOP(SelectionKey key, SocketChannel socket, TcpNioAsyncConnection conn) {
final CompletionHandler handler = conn.writeHandler;
final ByteBuffer oneBuffer = conn.removeWriteOneBuffer();
final ByteBuffer[] buffers = conn.removeWriteBuffers();
final Object attach = conn.removeWriteAttachment();
final int writingCount = conn.removeWritingCount();
final int writeOffset = conn.removeWriteOffset();
final int writeLength = conn.removeWriteLength();
if (handler == null || (oneBuffer == null && buffers == null)) return;
//System.out.println(conn + "------buffers:" + Arrays.toString(buffers) + "---onebuf:" + oneBuffer + "-------handler:" + handler);
try {
int rs = 0;
if (oneBuffer == null) {
int offset = writeOffset;
int length = writeLength;
rs = (int) socket.write(buffers, offset, length);
boolean over = true;
int end = offset + length;
for (int i = offset; i < end; i++) {
if (buffers[i].hasRemaining()) {
over = false;
length -= i - offset;
offset = i;
}
}
if (!over) {
conn.writingCount += rs;
conn.writeHandler = handler;
conn.writeAttachment = attach;
conn.writeBuffers = buffers;
conn.writeOffset = offset;
conn.writeLength = length;
key.interestOps(SelectionKey.OP_READ + SelectionKey.OP_WRITE);
key.selector().wakeup();
return;
}
} else {
rs = socket.write(oneBuffer);
if (oneBuffer.hasRemaining()) {
conn.writingCount += rs;
conn.writeHandler = handler;
conn.writeAttachment = attach;
conn.writeOneBuffer = oneBuffer;
key.interestOps(SelectionKey.OP_READ + SelectionKey.OP_WRITE);
key.selector().wakeup();
return;
}
}
conn.removeWriteHandler();
key.interestOps(SelectionKey.OP_READ); //OP_CONNECT
final int rs0 = rs + writingCount;
//System.out.println(conn + "------buffers:" + Arrays.toString(buffers) + "---onebuf:" + oneBuffer + "-------handler:" + handler + "-------write: " + rs);
context.runAsync(() -> {
try {
handler.completed(rs0, attach);
} catch (Throwable e) {
handler.failed(e, attach);
}
});
} catch (Throwable t) {
context.runAsync(() -> handler.failed(t, attach));
}
}
}
}

View File

@@ -29,41 +29,41 @@ import org.redkale.util.*;
* @author zhangjx * @author zhangjx
*/ */
public final class Transport { public final class Transport {
public static final String DEFAULT_PROTOCOL = "TCP"; public static final String DEFAULT_PROTOCOL = "TCP";
protected final AtomicInteger seq = new AtomicInteger(-1); protected final AtomicInteger seq = new AtomicInteger(-1);
protected final TransportFactory factory; protected final TransportFactory factory;
protected final String name; //即<group>的name属性 protected final String name; //即<group>的name属性
protected final String subprotocol; //即<group>的subprotocol属性 protected final String subprotocol; //即<group>的subprotocol属性
protected final boolean tcp; protected final boolean tcp;
protected final String protocol; protected final String protocol;
protected final AsynchronousChannelGroup group; protected final AsynchronousChannelGroup group;
protected final InetSocketAddress clientAddress; protected final InetSocketAddress clientAddress;
//不可能为null //不可能为null
protected TransportNode[] transportNodes = new TransportNode[0]; protected TransportNode[] transportNodes = new TransportNode[0];
protected final ObjectPool<ByteBuffer> bufferPool; protected final ObjectPool<ByteBuffer> bufferPool;
protected final SSLContext sslContext; protected final SSLContext sslContext;
//负载均衡策略 //负载均衡策略
protected final TransportStrategy strategy; protected final TransportStrategy strategy;
protected Transport(String name, String subprotocol, TransportFactory factory, final ObjectPool<ByteBuffer> transportBufferPool, protected Transport(String name, String subprotocol, TransportFactory factory, final ObjectPool<ByteBuffer> transportBufferPool,
final AsynchronousChannelGroup transportChannelGroup, final SSLContext sslContext, final InetSocketAddress clientAddress, final AsynchronousChannelGroup transportChannelGroup, final SSLContext sslContext, final InetSocketAddress clientAddress,
final Collection<InetSocketAddress> addresses, final TransportStrategy strategy) { final Collection<InetSocketAddress> addresses, final TransportStrategy strategy) {
this(name, DEFAULT_PROTOCOL, subprotocol, factory, transportBufferPool, transportChannelGroup, sslContext, clientAddress, addresses, strategy); this(name, DEFAULT_PROTOCOL, subprotocol, factory, transportBufferPool, transportChannelGroup, sslContext, clientAddress, addresses, strategy);
} }
protected Transport(String name, String protocol, String subprotocol, protected Transport(String name, String protocol, String subprotocol,
final TransportFactory factory, final ObjectPool<ByteBuffer> transportBufferPool, final TransportFactory factory, final ObjectPool<ByteBuffer> transportBufferPool,
final AsynchronousChannelGroup transportChannelGroup, final SSLContext sslContext, final InetSocketAddress clientAddress, final AsynchronousChannelGroup transportChannelGroup, final SSLContext sslContext, final InetSocketAddress clientAddress,
@@ -81,7 +81,7 @@ public final class Transport {
this.strategy = strategy; this.strategy = strategy;
updateRemoteAddresses(addresses); updateRemoteAddresses(addresses);
} }
public final InetSocketAddress[] updateRemoteAddresses(final Collection<InetSocketAddress> addresses) { public final InetSocketAddress[] updateRemoteAddresses(final Collection<InetSocketAddress> addresses) {
final TransportNode[] oldNodes = this.transportNodes; final TransportNode[] oldNodes = this.transportNodes;
synchronized (this) { synchronized (this) {
@@ -109,7 +109,7 @@ public final class Transport {
} }
return rs; return rs;
} }
public final boolean addRemoteAddresses(final InetSocketAddress addr) { public final boolean addRemoteAddresses(final InetSocketAddress addr) {
if (addr == null) return false; if (addr == null) return false;
if (clientAddress != null && clientAddress.equals(addr)) return false; if (clientAddress != null && clientAddress.equals(addr)) return false;
@@ -125,7 +125,7 @@ public final class Transport {
return true; return true;
} }
} }
public final boolean removeRemoteAddresses(InetSocketAddress addr) { public final boolean removeRemoteAddresses(InetSocketAddress addr) {
if (addr == null) return false; if (addr == null) return false;
synchronized (this) { synchronized (this) {
@@ -133,15 +133,15 @@ public final class Transport {
} }
return true; return true;
} }
public String getName() { public String getName() {
return name; return name;
} }
public String getSubprotocol() { public String getSubprotocol() {
return subprotocol; return subprotocol;
} }
public void close() { public void close() {
TransportNode[] nodes = this.transportNodes; TransportNode[] nodes = this.transportNodes;
if (nodes == null) return; if (nodes == null) return;
@@ -149,22 +149,22 @@ public final class Transport {
if (node != null) node.dispose(); if (node != null) node.dispose();
} }
} }
public InetSocketAddress getClientAddress() { public InetSocketAddress getClientAddress() {
return clientAddress; return clientAddress;
} }
public TransportNode[] getTransportNodes() { public TransportNode[] getTransportNodes() {
return transportNodes; return transportNodes;
} }
public TransportNode findTransportNode(SocketAddress addr) { public TransportNode findTransportNode(SocketAddress addr) {
for (TransportNode node : this.transportNodes) { for (TransportNode node : this.transportNodes) {
if (node.address.equals(addr)) return node; if (node.address.equals(addr)) return node;
} }
return null; return null;
} }
public InetSocketAddress[] getRemoteAddresses() { public InetSocketAddress[] getRemoteAddresses() {
InetSocketAddress[] rs = new InetSocketAddress[transportNodes.length]; InetSocketAddress[] rs = new InetSocketAddress[transportNodes.length];
for (int i = 0; i < rs.length; i++) { for (int i = 0; i < rs.length; i++) {
@@ -172,36 +172,36 @@ public final class Transport {
} }
return rs; return rs;
} }
@Override @Override
public String toString() { public String toString() {
return Transport.class.getSimpleName() + "{name = " + name + ", protocol = " + protocol + ", clientAddress = " + clientAddress + ", remoteNodes = " + Arrays.toString(transportNodes) + "}"; return Transport.class.getSimpleName() + "{name = " + name + ", protocol = " + protocol + ", clientAddress = " + clientAddress + ", remoteNodes = " + Arrays.toString(transportNodes) + "}";
} }
public ByteBuffer pollBuffer() { public ByteBuffer pollBuffer() {
return bufferPool.get(); return bufferPool.get();
} }
public Supplier<ByteBuffer> getBufferSupplier() { public Supplier<ByteBuffer> getBufferSupplier() {
return bufferPool; return bufferPool;
} }
public void offerBuffer(ByteBuffer buffer) { public void offerBuffer(ByteBuffer buffer) {
bufferPool.accept(buffer); bufferPool.accept(buffer);
} }
public void offerBuffer(ByteBuffer... buffers) { public void offerBuffer(ByteBuffer... buffers) {
for (ByteBuffer buffer : buffers) offerBuffer(buffer); for (ByteBuffer buffer : buffers) offerBuffer(buffer);
} }
public AsynchronousChannelGroup getTransportChannelGroup() { public AsynchronousChannelGroup getTransportChannelGroup() {
return group; return group;
} }
public boolean isTCP() { public boolean isTCP() {
return tcp; return tcp;
} }
public CompletableFuture<AsyncConnection> pollConnection(SocketAddress addr0) { public CompletableFuture<AsyncConnection> pollConnection(SocketAddress addr0) {
if (this.strategy != null) return strategy.pollConnection(addr0, this); if (this.strategy != null) return strategy.pollConnection(addr0, this);
final TransportNode[] nodes = this.transportNodes; final TransportNode[] nodes = this.transportNodes;
@@ -215,12 +215,12 @@ public final class Transport {
DatagramChannel channel = DatagramChannel.open(); DatagramChannel channel = DatagramChannel.open();
channel.configureBlocking(true); channel.configureBlocking(true);
channel.connect(udpaddr); channel.connect(udpaddr);
return CompletableFuture.completedFuture(AsyncConnection.create(channel, udpaddr, true, factory.readTimeoutSeconds, factory.writeTimeoutSeconds)); return CompletableFuture.completedFuture(AsyncConnection.create(bufferPool, channel, sslContext, udpaddr, true, factory.readTimeoutSeconds, factory.writeTimeoutSeconds));
} }
if (!rand) { //指定地址 if (!rand) { //指定地址
TransportNode node = findTransportNode(addr); TransportNode node = findTransportNode(addr);
if (node == null) { if (node == null) {
return AsyncConnection.createTCP(group, sslContext, addr, factory.readTimeoutSeconds, factory.writeTimeoutSeconds); return AsyncConnection.createTCP(bufferPool, group, sslContext, addr, factory.readTimeoutSeconds, factory.writeTimeoutSeconds);
} }
final BlockingQueue<AsyncConnection> queue = node.conns; final BlockingQueue<AsyncConnection> queue = node.conns;
if (!queue.isEmpty()) { if (!queue.isEmpty()) {
@@ -233,7 +233,7 @@ public final class Transport {
} }
} }
} }
return AsyncConnection.createTCP(group, sslContext, addr, factory.readTimeoutSeconds, factory.writeTimeoutSeconds); return AsyncConnection.createTCP(bufferPool, group, sslContext, addr, factory.readTimeoutSeconds, factory.writeTimeoutSeconds);
} }
//---------------------随机取地址------------------------ //---------------------随机取地址------------------------
@@ -266,14 +266,14 @@ public final class Transport {
@Override @Override
public void completed(Void result, TransportNode attachment) { public void completed(Void result, TransportNode attachment) {
attachment.disabletime = 0; attachment.disabletime = 0;
AsyncConnection asyncConn = AsyncConnection.create(channel, attachment.address, factory.readTimeoutSeconds, factory.writeTimeoutSeconds); AsyncConnection asyncConn = AsyncConnection.create(bufferPool, channel, attachment.address, factory.readTimeoutSeconds, factory.writeTimeoutSeconds);
if (future.isDone()) { if (future.isDone()) {
if (!attachment.conns.offer(asyncConn)) asyncConn.dispose(); if (!attachment.conns.offer(asyncConn)) asyncConn.dispose();
} else { } else {
future.complete(asyncConn); future.complete(asyncConn);
} }
} }
@Override @Override
public void failed(Throwable exc, TransportNode attachment) { public void failed(Throwable exc, TransportNode attachment) {
attachment.disabletime = now; attachment.disabletime = now;
@@ -289,7 +289,7 @@ public final class Transport {
future.complete(r); future.complete(r);
} }
}); });
} catch (Exception e) { } catch (Exception e) {
future.completeExceptionally(e); future.completeExceptionally(e);
} }
@@ -302,7 +302,7 @@ public final class Transport {
throw new RuntimeException("transport address = " + addr, ex); throw new RuntimeException("transport address = " + addr, ex);
} }
} }
private CompletableFuture<AsyncConnection> pollConnection0(TransportNode[] nodes, TransportNode exclude, long now) throws IOException { private CompletableFuture<AsyncConnection> pollConnection0(TransportNode[] nodes, TransportNode exclude, long now) throws IOException {
//从可用/不可用的地址列表中创建连接 //从可用/不可用的地址列表中创建连接
AtomicInteger count = new AtomicInteger(nodes.length); AtomicInteger count = new AtomicInteger(nodes.length);
@@ -319,17 +319,17 @@ public final class Transport {
public void completed(Void result, TransportNode attachment) { public void completed(Void result, TransportNode attachment) {
try { try {
attachment.disabletime = 0; attachment.disabletime = 0;
AsyncConnection asyncConn = AsyncConnection.create(channel, attachment.address, factory.readTimeoutSeconds, factory.writeTimeoutSeconds); AsyncConnection asyncConn = AsyncConnection.create(bufferPool, channel, attachment.address, factory.readTimeoutSeconds, factory.writeTimeoutSeconds);
if (future.isDone()) { if (future.isDone()) {
if (!attachment.conns.offer(asyncConn)) asyncConn.dispose(); if (!attachment.conns.offer(asyncConn)) asyncConn.dispose();
} else { } else {
future.complete(asyncConn); future.complete(asyncConn);
} }
} catch (Exception e) { } catch (Exception e) {
failed(e, attachment); failed(e, attachment);
} }
} }
@Override @Override
public void failed(Throwable exc, TransportNode attachment) { public void failed(Throwable exc, TransportNode attachment) {
attachment.disabletime = now; attachment.disabletime = now;
@@ -345,7 +345,7 @@ public final class Transport {
} }
return future; return future;
} }
public void offerConnection(final boolean forceClose, AsyncConnection conn) { public void offerConnection(final boolean forceClose, AsyncConnection conn) {
if (this.strategy != null && strategy.offerConnection(forceClose, conn)) return; if (this.strategy != null && strategy.offerConnection(forceClose, conn)) return;
if (!forceClose && conn.isTCP()) { if (!forceClose && conn.isTCP()) {
@@ -359,7 +359,7 @@ public final class Transport {
conn.dispose(); conn.dispose();
} }
} }
public <A> void async(SocketAddress addr, final ByteBuffer buffer, A att, final CompletionHandler<Integer, A> handler) { public <A> void async(SocketAddress addr, final ByteBuffer buffer, A att, final CompletionHandler<Integer, A> handler) {
pollConnection(addr).whenComplete((conn, ex) -> { pollConnection(addr).whenComplete((conn, ex) -> {
if (ex != null) { if (ex != null) {
@@ -367,118 +367,119 @@ public final class Transport {
return; return;
} }
conn.write(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() { conn.write(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override @Override
public void completed(Integer result, ByteBuffer attachment) { public void completed(Integer result, ByteBuffer attachment) {
buffer.clear(); buffer.clear();
conn.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() { conn.setReadBuffer(buffer);
conn.read(new CompletionHandler<Integer, ByteBuffer>() {
@Override @Override
public void completed(Integer result, ByteBuffer attachment) { public void completed(Integer result, ByteBuffer attachment) {
if (handler != null) handler.completed(result, att); if (handler != null) handler.completed(result, att);
offerBuffer(buffer); conn.offerBuffer(attachment);
offerConnection(false, conn); offerConnection(false, conn);
} }
@Override @Override
public void failed(Throwable exc, ByteBuffer attachment) { public void failed(Throwable exc, ByteBuffer attachment) {
offerBuffer(buffer); conn.offerBuffer(attachment);
offerConnection(true, conn); offerConnection(true, conn);
} }
}); });
} }
@Override @Override
public void failed(Throwable exc, ByteBuffer attachment) { public void failed(Throwable exc, ByteBuffer attachment) {
offerBuffer(buffer); conn.offerBuffer(attachment);
offerConnection(true, conn); offerConnection(true, conn);
} }
}); });
}); });
} }
public static class TransportNode { public static class TransportNode {
protected InetSocketAddress address; protected InetSocketAddress address;
protected volatile long disabletime; //不可用时的时间, 为0表示可用 protected volatile long disabletime; //不可用时的时间, 为0表示可用
protected final BlockingQueue<AsyncConnection> conns; protected final BlockingQueue<AsyncConnection> conns;
protected final ConcurrentHashMap<String, Object> attributes = new ConcurrentHashMap<>(); protected final ConcurrentHashMap<String, Object> attributes = new ConcurrentHashMap<>();
public TransportNode(int poolmaxconns, InetSocketAddress address) { public TransportNode(int poolmaxconns, InetSocketAddress address) {
this.address = address; this.address = address;
this.disabletime = 0; this.disabletime = 0;
this.conns = new ArrayBlockingQueue<>(poolmaxconns); this.conns = new ArrayBlockingQueue<>(poolmaxconns);
} }
@ConstructorParameters({"poolmaxconns", "address", "disabletime"}) @ConstructorParameters({"poolmaxconns", "address", "disabletime"})
public TransportNode(int poolmaxconns, InetSocketAddress address, long disabletime) { public TransportNode(int poolmaxconns, InetSocketAddress address, long disabletime) {
this.address = address; this.address = address;
this.disabletime = disabletime; this.disabletime = disabletime;
this.conns = new LinkedBlockingQueue<>(poolmaxconns); this.conns = new LinkedBlockingQueue<>(poolmaxconns);
} }
public int getPoolmaxconns() { public int getPoolmaxconns() {
return this.conns.remainingCapacity() + this.conns.size(); return this.conns.remainingCapacity() + this.conns.size();
} }
public <T> T setAttribute(String name, T value) { public <T> T setAttribute(String name, T value) {
attributes.put(name, value); attributes.put(name, value);
return value; return value;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T getAttribute(String name) { public <T> T getAttribute(String name) {
return (T) attributes.get(name); return (T) attributes.get(name);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T removeAttribute(String name) { public <T> T removeAttribute(String name) {
return (T) attributes.remove(name); return (T) attributes.remove(name);
} }
public TransportNode clearAttributes() { public TransportNode clearAttributes() {
attributes.clear(); attributes.clear();
return this; return this;
} }
public ConcurrentHashMap<String, Object> getAttributes() { public ConcurrentHashMap<String, Object> getAttributes() {
return attributes; return attributes;
} }
public void setAttributes(ConcurrentHashMap<String, Object> map) { public void setAttributes(ConcurrentHashMap<String, Object> map) {
attributes.clear(); attributes.clear();
if (map != null) attributes.putAll(map); if (map != null) attributes.putAll(map);
} }
public InetSocketAddress getAddress() { public InetSocketAddress getAddress() {
return address; return address;
} }
public long getDisabletime() { public long getDisabletime() {
return disabletime; return disabletime;
} }
@ConvertDisabled @ConvertDisabled
public BlockingQueue<AsyncConnection> getConns() { public BlockingQueue<AsyncConnection> getConns() {
return conns; return conns;
} }
public void dispose() { public void dispose() {
AsyncConnection conn; AsyncConnection conn;
while ((conn = conns.poll()) != null) { while ((conn = conns.poll()) != null) {
conn.dispose(); conn.dispose();
} }
} }
@Override @Override
public int hashCode() { public int hashCode() {
return this.address.hashCode(); return this.address.hashCode();
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) return true; if (this == obj) return true;
@@ -487,7 +488,7 @@ public final class Transport {
final TransportNode other = (TransportNode) obj; final TransportNode other = (TransportNode) obj;
return this.address.equals(other.address); return this.address.equals(other.address);
} }
@Override @Override
public String toString() { public String toString() {
return JsonConvert.root().convertTo(this); return JsonConvert.root().convertTo(this);

View File

@@ -393,33 +393,34 @@ public class TransportFactory {
final BlockingQueue<AsyncConnection> localqueue = queue; final BlockingQueue<AsyncConnection> localqueue = queue;
localconn.write(sendBuffer, sendBuffer, new CompletionHandler<Integer, ByteBuffer>() { localconn.write(sendBuffer, sendBuffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override @Override
public void completed(Integer result, ByteBuffer buffer) { public void completed(Integer result, ByteBuffer wbuffer) {
if (buffer.hasRemaining()) { if (wbuffer.hasRemaining()) {
localconn.write(buffer, buffer, this); localconn.write(wbuffer, wbuffer, this);
return; return;
} }
ByteBuffer pongBuffer = bufferPool.get(); localconn.read(new CompletionHandler<Integer, ByteBuffer>() {
localconn.read(pongBuffer, pongBuffer, new CompletionHandler<Integer, ByteBuffer>() {
int counter = 0; int counter = 0;
@Override @Override
public void completed(Integer result, ByteBuffer attachment) { public void completed(Integer result, ByteBuffer pongBuffer) {
if (counter > 3) { if (counter > 3) {
bufferPool.accept(attachment); localconn.offerBuffer(pongBuffer);
localconn.dispose(); localconn.dispose();
return; return;
} }
if (pongLength > 0 && attachment.position() < pongLength) { if (pongLength > 0 && pongBuffer.position() < pongLength) {
counter++; counter++;
localconn.read(pongBuffer, pongBuffer, this); localconn.setReadBuffer(pongBuffer);
localconn.read(this);
return; return;
} }
bufferPool.accept(attachment); localconn.offerBuffer(pongBuffer);
localqueue.offer(localconn); localqueue.offer(localconn);
} }
@Override @Override
public void failed(Throwable exc, ByteBuffer attachment) { public void failed(Throwable exc, ByteBuffer pongBuffer) {
localconn.offerBuffer(pongBuffer);
localconn.dispose(); localconn.dispose();
} }
}); });

View File

@@ -10,8 +10,9 @@ import java.net.*;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.*; import java.nio.channels.*;
import java.util.Set; import java.util.Set;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.function.*;
import javax.net.ssl.SSLContext;
/** /**
* *
@@ -32,9 +33,11 @@ public class UdpBioAsyncConnection extends AsyncConnection {
private final boolean client; private final boolean client;
public UdpBioAsyncConnection(final DatagramChannel ch, SocketAddress addr0, public UdpBioAsyncConnection(Supplier<ByteBuffer> bufferSupplier, Consumer<ByteBuffer> bufferConsumer,
final boolean client0, final int readTimeoutSeconds0, final int writeTimeoutSeconds0, final DatagramChannel ch, final SSLContext sslContext, SocketAddress addr0, final boolean client0,
final int readTimeoutSeconds0, final int writeTimeoutSeconds0,
final AtomicLong livingCounter, final AtomicLong closedCounter) { final AtomicLong livingCounter, final AtomicLong closedCounter) {
super(bufferSupplier, bufferConsumer, sslContext);
this.channel = ch; this.channel = ch;
this.client = client0; this.client = client0;
this.readTimeoutSeconds = readTimeoutSeconds0; this.readTimeoutSeconds = readTimeoutSeconds0;
@@ -127,30 +130,22 @@ public class UdpBioAsyncConnection extends AsyncConnection {
} }
@Override @Override
public <A> void read(ByteBuffer dst, A attachment, CompletionHandler<Integer, ? super A> handler) { public void read(CompletionHandler<Integer, ByteBuffer> handler) {
ByteBuffer dst = pollReadBuffer();
try { try {
int rs = channel.read(dst); int rs = channel.read(dst);
this.readtime = System.currentTimeMillis(); this.readtime = System.currentTimeMillis();
if (handler != null) handler.completed(rs, attachment); if (handler != null) handler.completed(rs, dst);
} catch (IOException e) { } catch (IOException e) {
if (handler != null) handler.failed(e, attachment); if (handler != null) handler.failed(e, dst);
} }
} }
@Override @Override
public <A> void read(ByteBuffer dst, long timeout, TimeUnit unit, A attachment, CompletionHandler<Integer, ? super A> handler) { public int read(ByteBuffer dst) throws IOException {
read(dst, attachment, handler); int rs = channel.read(dst);
} this.readtime = System.currentTimeMillis();
return rs;
@Override
public Future<Integer> read(ByteBuffer dst) {
try {
int rs = channel.read(dst);
this.readtime = System.currentTimeMillis();
return CompletableFuture.completedFuture(rs);
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
@Override @Override
@@ -165,14 +160,10 @@ public class UdpBioAsyncConnection extends AsyncConnection {
} }
@Override @Override
public Future<Integer> write(ByteBuffer src) { public int write(ByteBuffer src) throws IOException {
try { int rs = channel.send(src, remoteAddress);
int rs = channel.send(src, remoteAddress); this.writetime = System.currentTimeMillis();
this.writetime = System.currentTimeMillis(); return rs;
return CompletableFuture.completedFuture(rs);
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
@Override @Override

View File

@@ -11,7 +11,8 @@ import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel; import java.nio.channels.DatagramChannel;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import org.redkale.util.AnyValue; import java.util.concurrent.atomic.AtomicLong;
import org.redkale.util.*;
/** /**
* 协议底层Server * 协议底层Server
@@ -70,7 +71,14 @@ public class UdpBioProtocolServer extends ProtocolServer {
} }
@Override @Override
public void accept() throws IOException { public void accept(Server server) throws IOException {
AtomicLong createBufferCounter = new AtomicLong();
AtomicLong cycleBufferCounter = new AtomicLong();
ObjectPool<ByteBuffer> bufferPool = server.createBufferPool(createBufferCounter, cycleBufferCounter, server.bufferPoolSize);
AtomicLong createResponseCounter = new AtomicLong();
AtomicLong cycleResponseCounter = new AtomicLong();
ObjectPool<Response> responsePool = server.createResponsePool(createResponseCounter, cycleResponseCounter, server.responsePoolSize);
responsePool.setCreator(server.createResponseCreator(bufferPool, responsePool));
final DatagramChannel serchannel = this.serverChannel; final DatagramChannel serchannel = this.serverChannel;
final int readTimeoutSeconds = this.context.readTimeoutSeconds; final int readTimeoutSeconds = this.context.readTimeoutSeconds;
final int writeTimeoutSeconds = this.context.writeTimeoutSeconds; final int writeTimeoutSeconds = this.context.writeTimeoutSeconds;
@@ -81,14 +89,15 @@ public class UdpBioProtocolServer extends ProtocolServer {
public void run() { public void run() {
cdl.countDown(); cdl.countDown();
while (running) { while (running) {
final ByteBuffer buffer = context.pollBuffer(); final ByteBuffer buffer = bufferPool.get();
try { try {
SocketAddress address = serchannel.receive(buffer); SocketAddress address = serchannel.receive(buffer);
buffer.flip(); buffer.flip();
AsyncConnection conn = new UdpBioAsyncConnection(serchannel, address, false, readTimeoutSeconds, writeTimeoutSeconds, null, null); AsyncConnection conn = new UdpBioAsyncConnection(bufferPool, bufferPool, serchannel,
context.runAsync(new PrepareRunner(context, conn, buffer, null)); context.getSSLContext(), address, false, readTimeoutSeconds, writeTimeoutSeconds, null, null);
context.runAsync(new PrepareRunner(context, responsePool, conn, buffer, null));
} catch (Exception e) { } catch (Exception e) {
context.offerBuffer(buffer); bufferPool.accept(buffer);
} }
} }
} }

View File

@@ -17,6 +17,8 @@ import java.util.concurrent.*;
*/ */
public class WorkThread extends Thread { public class WorkThread extends Thread {
protected Thread localThread;
private final ExecutorService executor; private final ExecutorService executor;
public WorkThread(ExecutorService executor, Runnable runner) { public WorkThread(ExecutorService executor, Runnable runner) {
@@ -32,4 +34,19 @@ public class WorkThread extends Thread {
public ExecutorService getExecutor() { public ExecutorService getExecutor() {
return executor; return executor;
} }
@Override
public void run() {
this.localThread = Thread.currentThread();
super.run();
}
public boolean inSameThread() {
return this.localThread == Thread.currentThread();
}
public boolean inSameThread(Thread thread) {
return this.localThread == thread;
}
} }

View File

@@ -5,12 +5,10 @@
*/ */
package org.redkale.net.http; package org.redkale.net.http;
import java.nio.ByteBuffer;
import org.redkale.asm.MethodDebugVisitor; import org.redkale.asm.MethodDebugVisitor;
import java.nio.channels.CompletionHandler; import java.nio.channels.CompletionHandler;
import java.security.*; import java.security.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.function.*;
import org.redkale.asm.*; import org.redkale.asm.*;
import static org.redkale.asm.Opcodes.*; import static org.redkale.asm.Opcodes.*;
import org.redkale.net.*; import org.redkale.net.*;
@@ -30,6 +28,8 @@ public class HttpContext extends Context {
protected final ConcurrentHashMap<Class, Creator> asyncHandlerCreators = new ConcurrentHashMap<>(); protected final ConcurrentHashMap<Class, Creator> asyncHandlerCreators = new ConcurrentHashMap<>();
protected String remoteAddrHeader;
public HttpContext(HttpContextConfig config) { public HttpContext(HttpContextConfig config) {
super(config); super(config);
random.setSeed(Math.abs(System.nanoTime())); random.setSeed(Math.abs(System.nanoTime()));
@@ -45,25 +45,6 @@ public class HttpContext extends Context {
return executor; return executor;
} }
protected ObjectPool<Response> getResponsePool() {
return responsePool;
}
@Override
protected Consumer<ByteBuffer> getBufferConsumer() {
return super.getBufferConsumer();
}
@Override
protected void offerBuffer(ByteBuffer buffer) {
super.offerBuffer(buffer);
}
@Override
protected void offerBuffer(ByteBuffer... buffers) {
super.offerBuffer(buffers);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected <H extends CompletionHandler> Creator<H> loadAsyncHandlerCreator(Class<H> handlerClass) { protected <H extends CompletionHandler> Creator<H> loadAsyncHandlerCreator(Class<H> handlerClass) {
Creator<H> creator = asyncHandlerCreators.get(handlerClass); Creator<H> creator = asyncHandlerCreators.get(handlerClass);
@@ -179,5 +160,6 @@ public class HttpContext extends Context {
public static class HttpContextConfig extends ContextConfig { public static class HttpContextConfig extends ContextConfig {
public String remoteAddrHeader;
} }
} }

Some files were not shown because too many files have changed in this diff Show More