347 Commits
1.1.0 ... 1.6.0

Author SHA1 Message Date
Redkale
3439fab690 2017-03-17 16:07:41 +08:00
Redkale
14274c8d04 2017-03-17 15:57:49 +08:00
Redkale
b3cbd9be71 2017-03-17 15:21:35 +08:00
Redkale
b1d810188c 2017-03-17 14:54:00 +08:00
Redkale
4b48f85162 2017-03-17 13:20:26 +08:00
Redkale
738b02e1b9 优化DataSource的异步接口 2017-03-17 13:09:28 +08:00
Redkale
dc487f9226 2017-03-17 12:03:42 +08:00
Redkale
bb2f43c317 2017-03-17 09:26:44 +08:00
Redkale
be61aef123 Service、DataSource、CacheSource增加异步接口 2017-03-16 20:04:20 +08:00
Redkale
6ad7888e85 2017-03-16 20:02:34 +08:00
Redkale
242adb3c9e 2017-03-16 17:46:38 +08:00
Redkale
8654c69d0c 2017-03-16 17:38:18 +08:00
Redkale
a7999ff160 2017-03-14 17:03:29 +08:00
Redkale
9c04b8aab0 2017-03-10 18:59:36 +08:00
Redkale
3643fefc9c 2017-03-09 17:22:02 +08:00
Redkale
47189901e5 2017-03-09 15:44:43 +08:00
Redkale
2577684897 2017-03-09 15:08:36 +08:00
Redkale
77396df8fd 2017-03-09 14:04:36 +08:00
Redkale
c517a1d469 增加javadoc注释 2017-03-09 11:44:12 +08:00
Redkale
b7d7e6567b 2017-03-09 11:19:13 +08:00
Redkale
67807e913e 2017-03-09 09:49:14 +08:00
Redkale
19a950dab5 2017-03-08 20:04:09 +08:00
Redkale
79b91f8386 @WebAction替换成@WebMapping 2017-03-08 18:56:07 +08:00
Redkale
0359a4b7e9 2017-03-08 17:28:33 +08:00
Redkale
d89f410749 2017-03-08 17:22:56 +08:00
Redkale
850f6dd060 2017-03-08 17:05:21 +08:00
Redkale
d891c6c8dc 2017-03-08 14:25:03 +08:00
Redkale
0a4a88ed5a 2017-03-08 14:03:05 +08:00
Redkale
3c02219da0 2017-03-08 09:57:08 +08:00
Redkale
65efc3372e 2017-03-07 17:44:50 +08:00
Redkale
3acea66788 2017-03-07 15:47:39 +08:00
Redkale
b448514e40 2017-03-07 11:58:27 +08:00
Redkale
024147344b 2017-03-07 10:09:26 +08:00
Redkale
52a34d3871 2017-03-07 09:42:03 +08:00
Redkale
1ada26e4dd 2017-03-07 09:39:16 +08:00
Redkale
94d1b61f81 2017-03-06 15:18:50 +08:00
Redkale
29299edb90 2017-03-06 14:45:35 +08:00
Redkale
a2e2c5e178 2017-03-06 12:02:00 +08:00
Redkale
8ae39df2e8 2017-03-06 09:29:25 +08:00
Redkale
508b269a82 2017-03-03 18:40:45 +08:00
Redkale
a8627b6105 2017-03-03 18:21:09 +08:00
Redkale
8fee6b2c68 2017-03-03 18:05:11 +08:00
Redkale
dd58571ffd 2017-03-03 17:50:50 +08:00
Redkale
8c25683cc5 增加javadoc注释 2017-03-03 14:49:32 +08:00
Redkale
a96f003b8c 2017-03-03 11:45:55 +08:00
Redkale
ff01443246 2017-03-02 19:59:42 +08:00
Redkale
e915a253f8 2017-03-02 16:03:29 +08:00
Redkale
b463389733 2017-03-02 15:43:34 +08:00
Redkale
41c97b92c7 删除DataSource.updateColumns方法,使用 DataSource.updateColumn代替 2017-03-02 14:21:47 +08:00
Redkale
1142f81e9c 删掉HttpResponse.finishJsResult方法 2017-03-02 14:13:29 +08:00
Redkale
5bc9f77b7b 修复HttpRequest.getBody由于URLDecode导致的BUG 2017-03-02 12:35:14 +08:00
Redkale
c5d0582807 修复HttpRequest.getBody由于URLDecode导致内容多余的BUG 2017-03-02 11:52:22 +08:00
Redkale
525e65d152 增加javadoc注释 2017-03-02 10:41:15 +08:00
Redkale
d948c7af47 增加javadoc注释 2017-03-02 10:02:45 +08:00
Redkale
11a29b4ed6 2017-03-01 20:59:00 +08:00
Redkale
e31c4a3041 DataSource增加支持Blob(byte[])类型字段功能 2017-02-28 13:37:38 +08:00
Redkale
2928d5fc93 2017-02-28 10:01:13 +08:00
Redkale
12fc6f7f10 2017-02-27 17:30:03 +08:00
Redkale
4bd8c207b4 增加javadoc注释 2017-02-27 17:15:14 +08:00
Redkale
be030a3640 增加javadoc注释 2017-02-27 17:11:23 +08:00
Redkale
ebaa250f7b 增加javadoc注释 2017-02-27 17:07:00 +08:00
Redkale
826a2d7ee6 增加javadoc注释 2017-02-27 15:06:31 +08:00
Redkale
e476cf8176 2017-02-27 13:54:23 +08:00
Redkale
03115694f9 增加javadoc注释 2017-02-27 12:01:39 +08:00
Redkale
26ffb04834 增加javadoc注释 2017-02-27 11:56:18 +08:00
Redkale
2979fcc33d 增加javadoc注释 2017-02-27 11:19:40 +08:00
Redkale
9a29a11e22 2017-02-25 12:53:54 +08:00
Redkale
d73a27be71 2017-02-25 12:44:24 +08:00
Redkale
d77f424504 2017-02-25 12:27:19 +08:00
Redkale
3142ad6041 2017-02-24 15:46:00 +08:00
Redkale
6044f014c7 2017-02-24 09:04:16 +08:00
Redkale
d1cfdfa14f 2017-02-23 20:33:03 +08:00
Redkale
8f9bfc3f28 兼容javax.persistence.jdbc.driver为空的情况 2017-02-23 20:16:58 +08:00
Redkale
9ae847d392 FilterFuncColumn支持多字段名 2017-02-23 19:26:13 +08:00
Redkale
178226b730 DataSource增加getNumberMap方法,用于查询多个字段的统计值 2017-02-23 19:06:40 +08:00
Redkale
801e45abce 2017-02-23 17:45:01 +08:00
Redkale
cd54a7040a 2017-02-23 15:40:17 +08:00
Redkale
3bd880b061 2017-02-23 15:29:04 +08:00
Redkale
bf355cce28 2017-02-23 15:15:43 +08:00
Redkale
58d08c5787 @Cacheable增加定时更新缓存功能 2017-02-22 20:57:13 +08:00
Redkale
a778af73d8 修复HttpRequest.getRemoteAddress()方法中channel已关闭会抛空指针异常的BUG 2017-02-22 16:06:40 +08:00
Redkale
7ca95c3549 2017-02-22 09:10:40 +08:00
Redkale
54933ac3ac Utility增加 删除掉字符串数组中包含指定的字符串 方法 2017-02-21 20:27:19 +08:00
Redkale
255048bf5b Response增加output字段,便于RecycleListener获取输出结果 2017-02-21 16:35:08 +08:00
Redkale
206fa19f3e 2017-02-17 14:12:33 +08:00
Redkale
f0e9047f8c 2017-02-17 14:02:24 +08:00
Redkale
698966d551 删掉 DistributeGenerator 功能 2017-02-16 11:29:49 +08:00
Redkale
fc6b5cb458 2017-02-15 20:56:28 +08:00
Redkale
9eee3bfa58 增加 java.util.logging.FileHandler.unusual 特性 2017-02-15 20:46:30 +08:00
Redkale
0adc0845fd 2017-02-15 20:07:30 +08:00
Redkale
92f98eff5f 2017-02-15 09:57:10 +08:00
Redkale
d97f8acf23 2017-02-10 20:08:47 +08:00
Redkale
47e14bf2ec 2017-02-10 17:38:51 +08:00
Redkale
8eed4083bc 2017-02-10 16:55:39 +08:00
Redkale
9ef7641cd1 2017-02-09 16:44:31 +08:00
Redkale
bafb6065c8 2017-02-09 14:53:16 +08:00
Redkale
8b2460b8ab 2017-02-09 13:38:24 +08:00
Redkale
827172e743 2017-02-09 11:52:04 +08:00
Redkale
fa9bd30de5 2017-02-04 15:01:39 +08:00
Redkale
78e66ff74b 2017-02-04 14:59:10 +08:00
Redkale
7e8d1c3567 2017-02-04 09:04:35 +08:00
Redkale
c3a7603674 2017-02-03 17:25:56 +08:00
Redkale
4b8cfbba00 2017-02-03 16:52:57 +08:00
Redkale
30771e5366 2017-02-03 16:43:12 +08:00
Redkale
313c7f4ba1 2017-02-03 16:37:08 +08:00
Redkale
ece4215a8a 2017-02-03 15:03:11 +08:00
Redkale
7ea740edf1 Update RestParam.java 2017-02-02 17:23:02 +08:00
Redkale
716f4e6934 Update RestParam.java 2017-02-02 17:21:43 +08:00
Redkale
90ab302667 2017-01-18 22:55:29 +08:00
Redkale
4695949362 2017-01-18 19:04:57 +08:00
Redkale
4827893a0d 2017-01-18 10:54:02 +08:00
Redkale
9276f220b0 2017-01-17 20:12:38 +08:00
Redkale
4071a5d165 2017-01-17 13:37:34 +08:00
Redkale
da0ff24af6 2017-01-17 13:28:23 +08:00
Redkale
afef635146 2017-01-17 13:23:11 +08:00
Redkale
eda9d1c780 2017-01-16 14:11:35 +08:00
Redkale
4b5749bc60 2017-01-16 11:50:19 +08:00
Redkale
6bb23008c2 2017-01-11 10:37:53 +08:00
Redkale
7746971b60 2017-01-11 10:35:56 +08:00
Redkale
bc20c82fef 2017-01-11 10:24:49 +08:00
Redkale
fff70ed241 2017-01-11 10:03:43 +08:00
Redkale
c590d45ce0 2017-01-10 20:01:09 +08:00
Redkale
8bab9ad22b 2017-01-10 18:10:02 +08:00
Redkale
3c457dad2a 2017-01-10 16:42:41 +08:00
Redkale
eaae598234 2017-01-09 15:05:14 +08:00
Redkale
606faf1bf8 2017-01-09 10:38:34 +08:00
Redkale
ae9aa94323 2017-01-09 10:27:13 +08:00
Redkale
2e41e44294 2016-12-29 11:15:21 +08:00
Redkale
d806d9d6ff 2016-12-29 10:34:43 +08:00
Redkale
1260736c14 2016-12-26 17:31:34 +08:00
Redkale
08c5cbbbf3 2016-12-26 15:16:20 +08:00
Redkale
af0726cd79 2016-12-25 15:47:46 +08:00
Redkale
ce2279030d 2016-12-25 15:45:41 +08:00
Redkale
83aba2ebee 2016-12-23 18:20:04 +08:00
Redkale
5c11742b51 2016-12-17 17:14:22 +08:00
Redkale
5295e04275 2016-12-15 14:38:33 +08:00
Redkale
47f723e63b 2016-12-15 09:54:23 +08:00
Redkale
54956e47d2 2016-12-15 09:11:28 +08:00
Redkale
b2cbdf6642 2016-12-14 20:43:41 +08:00
Redkale
989d1c6db9 解决updateColumn多表关联更新的BUG 2016-12-11 20:40:29 +08:00
Redkale
e139b0cc5d 2016-12-11 19:56:33 +08:00
Redkale
66261e98b5 2016-12-11 19:22:12 +08:00
Redkale
d9a268d30a 2016-12-11 19:10:51 +08:00
Redkale
a8bc50a947 2016-12-09 17:06:26 +08:00
Redkale
6aa96daae2 2016-12-09 14:17:16 +08:00
Redkale
293805a55e 2016-12-09 11:17:03 +08:00
Redkale
8b6319888c Update README.md 2016-12-02 11:10:54 +08:00
Redkale
408676e97a Update README.md 2016-12-02 11:09:15 +08:00
Redkale
1fabbae4f6 2016-11-28 10:43:38 +08:00
Redkale
09a5b41d96 2016-11-25 17:20:45 +08:00
Redkale
9d85a4dcaf 2016-11-25 17:06:03 +08:00
Redkale
9bc60c1c47 2016-11-25 15:53:37 +08:00
Redkale
92aff864ef 2016-11-25 11:40:49 +08:00
Redkale
254e2e8ccd 2016-11-25 11:28:11 +08:00
Redkale
2480d127ac 2016-11-25 10:16:58 +08:00
Redkale
cc3d82e864 2016-11-25 10:09:06 +08:00
Redkale
ee712c55a0 2016-11-24 15:24:14 +08:00
Redkale
79f70266e4 2016-11-24 12:05:17 +08:00
Redkale
3ffb8d510d 2016-11-24 11:59:35 +08:00
Redkale
e55fc1a421 2016-11-14 15:49:03 +08:00
Redkale
ee9fb4a9b8 2016-11-13 10:54:12 +08:00
Redkale
ef3536beed 2016-11-11 11:37:19 +08:00
Redkale
fbababaf40 2016-11-11 10:43:16 +08:00
Redkale
4548cf78d6 2016-11-10 16:29:42 +08:00
Redkale
86a219e3e1 2016-11-10 16:27:41 +08:00
Redkale
9e0876dee2 2016-11-10 16:22:04 +08:00
Redkale
e9096372d3 2016-11-09 13:15:00 +08:00
Redkale
cef367c693 2016-11-08 16:25:26 +08:00
Redkale
2634524439 2016-11-08 09:40:54 +08:00
Redkale
10d27bf78c 2016-11-07 21:07:56 +08:00
Redkale
5b7739b26b 2016-11-07 19:15:27 +08:00
Redkale
11f895a0ca 2016-11-07 14:12:44 +08:00
Redkale
63099b72be 2016-11-07 12:42:02 +08:00
Redkale
0d8f7a4fa2 2016-11-07 12:28:26 +08:00
Redkale
83f460660b 2016-11-07 09:28:23 +08:00
Redkale
786d25678b 2016-11-04 09:29:30 +08:00
Redkale
f57d8325b3 2016-10-31 16:43:47 +08:00
Redkale
22adab4f93 2016-10-31 16:28:24 +08:00
Redkale
805e3910c4 增加ColumnValue功能 2016-10-31 14:09:21 +08:00
Redkale
ecd827e3b4 增加ColumnValue功能 2016-10-31 14:04:45 +08:00
Redkale
19150e9f9c 增加ColumnValue功能 2016-10-31 13:32:08 +08:00
Redkale
de5a725acc 2016-10-31 09:35:28 +08:00
Redkale
aae2305274 2016-10-28 11:54:10 +08:00
Redkale
00ba1ecee9 2016-10-28 09:32:27 +08:00
Redkale
e59465eaf9 2016-10-27 19:36:39 +08:00
Redkale
6f0b4604fc 2016-10-27 16:43:55 +08:00
Redkale
9f97f81bae 2016-10-24 11:46:48 +08:00
Redkale
ffcd04a626 2016-10-22 10:23:53 +08:00
Redkale
ecf102aff3 2016-10-21 10:53:37 +08:00
Redkale
c16b0b520d 2016-10-21 10:35:19 +08:00
Redkale
2f25ee1c05 2016-10-21 10:11:32 +08:00
Redkale
b5011fa069 2016-10-19 17:37:37 +08:00
Redkale
55e2109764 2016-10-19 10:09:44 +08:00
Redkale
5cf4c8a95a 2016-10-19 10:08:09 +08:00
Redkale
6b319caa28 2016-10-18 14:45:11 +08:00
Redkale
b97a23930a 2016-10-18 13:34:12 +08:00
Redkale
6c918a6c95 2016-10-18 10:49:36 +08:00
Redkale
20ba119f93 2016-10-18 10:48:36 +08:00
Redkale
95ca74f9f9 2016-10-17 18:11:03 +08:00
Redkale
f28cbb4ac5 2016-10-14 14:31:56 +08:00
Redkale
e3f851ed1f 2016-10-13 17:35:05 +08:00
Redkale
d3cf414c51 2016-10-13 16:43:55 +08:00
Redkale
ea98bb814f 2016-10-11 12:30:02 +08:00
Redkale
515e8256cc Update README.md 2016-10-10 20:33:42 +08:00
Redkale
903c58b239 2016-10-10 20:28:04 +08:00
Redkale
1c59c86ba2 2016-10-10 19:20:19 +08:00
Redkale
b2c6dd2db2 2016-10-10 19:19:56 +08:00
Redkale
beffe53d4d 2016-10-10 19:02:35 +08:00
Redkale
4eb5edaef2 2016-10-10 17:53:18 +08:00
Redkale
ba07d343ae 2016-10-10 17:52:15 +08:00
Redkale
c887a9dc4c 2016-10-10 17:44:57 +08:00
Redkale
689cdca004 2016-10-10 17:15:51 +08:00
Redkale
54b7863be6 2016-10-10 16:40:41 +08:00
Redkale
26453fe4c5 2016-10-10 16:40:00 +08:00
Redkale
036b248092 2016-10-10 15:48:57 +08:00
Redkale
8ca79face5 2016-10-10 15:45:13 +08:00
Redkale
6fd3250fba 2016-10-10 15:33:18 +08:00
Redkale
93a213448a 2016-10-10 15:23:58 +08:00
Redkale
e12cf185d9 2016-10-10 15:17:32 +08:00
Redkale
ca6c90eacd 2016-10-10 14:35:04 +08:00
Redkale
8901dd9a07 2016-10-10 14:20:49 +08:00
Redkale
93fef97c56 2016-10-10 13:52:20 +08:00
Redkale
ddef9018e2 2016-10-10 09:50:56 +08:00
Redkale
fb51997c6b 2016-10-08 18:42:01 +08:00
Redkale
65da7118fc 2016-10-08 17:35:37 +08:00
Redkale
fc2dfa1a8a 2016-10-08 12:30:45 +08:00
Redkale
68db4e37e2 2016-09-28 21:36:15 +08:00
Redkale
28c9b2606a 2016-09-26 20:51:01 +08:00
Redkale
d47b63e47b 2016-09-26 20:21:14 +08:00
Redkale
7f86972fa1 2016-09-26 19:48:38 +08:00
Redkale
92eefc872a 2016-09-26 14:01:20 +08:00
Redkale
c43e516d14 2016-09-26 13:51:14 +08:00
Redkale
8884fabf90 2016-09-26 13:41:35 +08:00
Redkale
1720470424 2016-09-26 13:19:09 +08:00
Redkale
1da2e95f46 2016-09-26 10:22:46 +08:00
Redkale
940af0b251 2016-09-26 10:18:21 +08:00
Redkale
43102b9d35 2016-09-26 09:41:40 +08:00
Redkale
fa601c69e7 2016-09-26 09:23:35 +08:00
Redkale
b365b18be0 2016-09-26 09:05:44 +08:00
Redkale
bc8a52eef8 2016-09-25 14:11:42 +08:00
Redkale
afa45498d4 2016-09-24 18:22:01 +08:00
Redkale
6f056bbcb6 2016-09-23 10:03:49 +08:00
Redkale
4fb218fd18 2016-09-18 19:51:34 +08:00
Redkale
1e7575c7b7 2016-09-18 19:50:17 +08:00
Redkale
02fd74f6de 2016-09-18 10:53:16 +08:00
Redkale
77732347d0 2016-09-18 10:41:54 +08:00
Redkale
53eaad17ea 2016-09-18 09:01:14 +08:00
Redkale
4cdc1f82c5 2016-09-14 14:41:30 +08:00
Redkale
77c2f72b42 2016-09-14 14:39:15 +08:00
Redkale
469069d2ac 2016-09-14 14:04:39 +08:00
Redkale
d7542a0c0a 2016-09-14 14:03:05 +08:00
Redkale
15d36735da 2016-09-14 13:11:08 +08:00
Redkale
d3163a6e0d 2016-09-14 12:08:10 +08:00
Redkale
23fd664eef 2016-09-14 11:32:05 +08:00
Redkale
f21cb2c233 2016-09-14 11:22:25 +08:00
Redkale
0a2a9f0e80 2016-09-14 10:48:16 +08:00
Redkale
9b74f46b22 2016-09-14 10:44:54 +08:00
Redkale
59ca4afd8b 2016-09-14 10:41:15 +08:00
Redkale
bc1c749152 2016-09-14 10:39:56 +08:00
Redkale
d35987612d 2016-09-14 10:24:24 +08:00
Redkale
04b5b361ad 2016-09-14 10:08:16 +08:00
Redkale
a81c9f7d21 2016-09-14 09:36:33 +08:00
Redkale
2c75c04b7e 2016-09-13 17:38:46 +08:00
Redkale
9bf5044654 2016-09-13 17:19:18 +08:00
Redkale
e99fd3c049 2016-09-13 16:09:50 +08:00
Redkale
4e9b3f45fc 2016-09-13 16:07:26 +08:00
Redkale
95f4cd0634 2016-09-12 21:08:10 +08:00
Redkale
a43f9a0121 2016-09-09 15:21:57 +08:00
Redkale
6f6952ad2c 2016-09-09 11:59:10 +08:00
Redkale
21cfbebe26 2016-09-08 09:21:28 +08:00
Redkale
f16beca680 2016-09-08 09:18:46 +08:00
Redkale
1341e81361 2016-09-08 09:18:18 +08:00
Redkale
f08a29b15a 2016-09-07 22:22:09 +08:00
Redkale
fea5123915 2016-09-07 21:32:41 +08:00
Redkale
cd45cafec5 2016-09-07 19:16:30 +08:00
Redkale
bed86d44a1 2016-09-07 18:33:32 +08:00
Redkale
bd3ae4bb41 2016-09-07 18:01:37 +08:00
Redkale
589d34d8a4 2016-09-07 17:29:58 +08:00
Redkale
a455795703 2016-09-07 16:32:11 +08:00
Redkale
fbb9cdefe1 2016-09-07 16:19:14 +08:00
Redkale
d202b2fbad 2016-09-07 13:53:33 +08:00
Redkale
9d82ca84a4 2016-09-06 14:34:55 +08:00
Redkale
1f0e0accb1 2016-09-06 13:45:56 +08:00
Redkale
fa8e40f6c0 2016-09-06 12:21:30 +08:00
Redkale
1a22cd0fe1 2016-09-06 12:00:49 +08:00
Redkale
8422173411 2016-09-06 09:46:37 +08:00
Redkale
c63248ba7f 2016-09-06 08:40:39 +08:00
Redkale
de4dda7c73 2016-09-06 08:37:00 +08:00
Redkale
e546ff74a5 2016-09-06 08:29:44 +08:00
Redkale
506f930320 2016-09-06 08:23:10 +08:00
Redkale
09beaedee8 2016-09-05 21:26:32 +08:00
Redkale
40845f5f60 2016-09-05 18:29:50 +08:00
Redkale
f3f001d72d 2016-09-05 18:29:21 +08:00
Redkale
b49a4d2c83 2016-09-05 15:07:57 +08:00
Redkale
90884f4621 2016-09-04 08:19:13 +08:00
Redkale
c2fd7be5e2 2016-09-02 19:41:26 +08:00
Redkale
b1773107a1 2016-09-02 19:27:05 +08:00
Redkale
f6aa646ea4 2016-09-02 18:07:04 +08:00
Redkale
72887106ea 2016-09-02 17:56:14 +08:00
Redkale
aa6126ddec 2016-09-02 10:16:14 +08:00
Redkale
a98a35b4af 2016-09-01 10:00:28 +08:00
Redkale
07253b1f17 2016-08-31 19:10:20 +08:00
Redkale
48a4c6d53c 2016-08-31 19:06:57 +08:00
Redkale
d78c08878c 2016-08-31 13:42:32 +08:00
Redkale
d40ea81fc3 2016-08-31 09:21:12 +08:00
Redkale
78ac88b57c 2016-08-31 09:20:49 +08:00
Redkale
3595f8b6bc 2016-08-30 15:06:56 +08:00
Redkale
1421b83e49 2016-08-30 14:22:11 +08:00
Redkale
90361edba1 2016-08-30 13:01:03 +08:00
Redkale
3d3347b64f 2016-08-30 08:59:06 +08:00
Redkale
f8a439e21f 2016-08-30 02:16:33 +08:00
Redkale
9d76e693fb 2016-08-30 02:14:59 +08:00
Redkale
a206ecd76b 2016-08-30 02:13:56 +08:00
Redkale
81f386dcdb 2016-08-29 20:27:54 +08:00
Redkale
e8e6459679 2016-08-29 17:21:02 +08:00
Redkale
9f5ab4b068 2016-08-29 14:48:29 +08:00
Redkale
1ea816a60e 2016-08-29 13:50:05 +08:00
Redkale
2c5876ba3e 2016-08-27 15:29:40 +08:00
Redkale
cffe181344 删除Source异步版接口 2016-08-27 15:25:03 +08:00
Redkale
4647545ff5 2016-08-27 15:07:34 +08:00
Redkale
bfe78a805e 2016-08-27 14:52:34 +08:00
Redkale
c480b2b18e 2016-08-27 14:30:25 +08:00
Redkale
7e9885de2e 2016-08-27 14:25:57 +08:00
Redkale
db32656c8a 2016-08-27 13:50:24 +08:00
Redkale
b981307768 2016-08-26 21:38:24 +08:00
Redkale
b0e0a341ec 2016-08-26 14:12:28 +08:00
Redkale
40ef40b813 2016-08-26 09:51:36 +08:00
Redkale
dfacd49a70 2016-08-26 08:09:03 +08:00
Redkale
470a82b6e6 2016-08-26 07:16:47 +08:00
Redkale
d5a752dea0 2016-08-26 06:51:06 +08:00
Redkale
554932201b 2016-08-26 06:37:47 +08:00
Redkale
54462e8c26 2016-08-25 14:21:09 +08:00
Redkale
d9807148db 2016-08-25 13:50:13 +08:00
Redkale
66a5fc2447 2016-08-25 12:32:41 +08:00
Redkale
4f9c8ce145 2016-08-25 09:13:20 +08:00
Redkale
884cc930c8 2016-08-25 09:00:20 +08:00
Redkale
cd4b18ad45 2016-08-25 08:52:51 +08:00
Redkale
707fc783b5 2016-08-25 08:52:18 +08:00
Redkale
3ca6ad6e12 2016-08-25 07:22:48 +08:00
Redkale
4972f5804e 2016-08-24 22:34:31 +08:00
Redkale
aec69d2973 2016-08-24 22:27:27 +08:00
Redkale
3f2a7f684f 2016-08-24 22:00:48 +08:00
Redkale
ce9f517244 2016-08-24 21:53:07 +08:00
Redkale
192e52f18f 2016-08-24 18:25:49 +08:00
Redkale
cdbe53d3d9 2016-08-24 17:50:30 +08:00
Redkale
58f4f28e14 2016-08-24 17:39:53 +08:00
Redkale
bc19d75422 2016-08-24 17:34:17 +08:00
254 changed files with 11992 additions and 2967 deletions

View File

@@ -8,17 +8,17 @@
<li>提供HTTP服务同时内置JSON功能与限时缓存功能</li>
<li>TCP层完全使用NIO.2并统一TCP与UDP的接口换</li>
<li>提供分布式与集中式部署的无缝切换</li>
<li>提供类似JPA功能包含数据缓存自动同步与简洁的数据层操作接口</li>
<li>提供类似JPA功能包含数据缓存自动同步、分表分库与简洁的数据层操作接口</li>
<li>可以动态修改已依赖注入的资源</li>
</ol>
<strong>Redkale 设计理念</strong>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;作为一个全新的微服务框架,不仅是使用了Java8的新语法,更多是设计上与主流框架有不同。Redkale是按组件形式设计的而非以容器为主几乎每个子包都是能提供独立功能的组件。如Tomcat是按容器设计的所有web资源/配置由Tomcat控制开发者很能难控制到Tomcat内部而Redkale的HTTP服务只是个组件开发者既可以自己启动和配置HttpServer也可以把Redkale当成容器通过Redkale进程来初始化服务。Spring的Ioc容器也是如此Redkale提供的依赖注入仅通过ResouceFactory一个类来控制非常轻量而且也可以动态更改已注入的资源。Spring提倡控制反转思想偏偏自身的容器却让开发者很难控制。Redkale是一个既能以组件形式也能以容器形式存在的框架。从整体上看Redkale的架构分两层接口和默认实现。开发者不想使用Redkale内置的HTTP服务而使用符合JavaEE规范的HttpServlet, 可以采用自定义协议基于JSR 340(Servlet 3.1)来实现自己的HTTP服务开发者想使用Hibernate作为数据库操作可以写一个自己的DataSource实现类JSON的序列化和反序列化也可以使用第三方的实现。这其实包含了控制反转的思想让框架里的零件可以让开发者控制。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;与主流框架比功能上Redkale显得很简单也是Redkale的一个特点并非不足,从一个良好的设计习惯或架构上来看,有些常用功能是不需要提供的,如Redkale的HTTP服务不支持HTTPS和JSPHTTPS比HTTP多了一层加密解密这种密集的数字计算不是Java的专长同时一个稍好的提供HTTP服务的架构不会将Java动态服务器放在最前端通常前面会放nginx或apache除了负载均衡还能静动分离既然Java服务器前面有C写的服务器那么HTTPS的加解密就应该交给前面的服务器处理。Redkale再提供HTTPS服务就显得鸡肋。JSP其实算是一个落后的技术现在是一个多样化终端的时代终端不只局限于桌面程序和PC浏览器还有原生App、混合式App、微信端、移动H5、提供第三方接口等各种形式的终端这些都不是JSP能兼顾的而HTTP+JSON作为通用性接口可以避免重复开发模版引擎的功能加上各种强大的JS框架足以取代JSP(如果初级程序员还花大量时间去学习基于JSP的Struts或Spring MVC框架就有点跟不上时代了)。Redkale在功能上做了筛选不会只因为迎合主流而提供,而是以良好的设计思想为指导。这是Redkale很重要的一个思想
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;作为一个全新的微服务框架,Redkale在接口定义上使用了Java 8大量的新语法,接口有默认实现、接口带静态方法、重复注解等特性,同时在设计上与主流框架有很大不同。Redkale是按组件形式设计的而非以容器为主几乎每个子包都是能提供独立功能的组件。如Tomcat是按容器设计的所有web资源/配置由Tomcat控制开发者很能难控制到Tomcat内部而Redkale的HTTP服务只是个组件开发者既可以自己启动和配置HttpServer也可以把Redkale当成容器通过Redkale进程来初始化服务。Spring的Ioc容器也是如此Redkale提供的依赖注入仅通过ResouceFactory一个类来控制非常轻量并且可动态更改已注入的资源。Spring提倡控制反转思想自身的容器却让开发者很难控制。Redkale是一个既能以组件形式也能以容器形式存在的框架。从整体上看Redkale的架构分两层接口和默认实现。开发者若想替换掉Redkale内置的HTTP服务而使用符合JavaEE规范的HttpServlet, 可以采用自定义协议基于JSR 340(Servlet 3.1)来实现自己的HTTP服务若想使用Hibernate作为数据库操作可以写一个自己的DataSource实现类JSON的序列化和反序列化也可以使用第三方的实现Memcached或Redis也可以作为另一个CacheSource的实现替换Redkale的默认实现。这其实包含了控制反转的思想,让框架里的各个组件均可让开发者控制。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;与主流框架比功能上Redkale显得很简单体现了Redkale的简易性,而并非不足从一个良好的设计习惯或架构上来看有些常用功能是不需要提供的如Redkale的HTTP服务不支持HTTPS和JSPHTTPS比HTTP多了一层加密解密这种密集的计算不是Java的专长通常提供HTTP服务的架构不会将Java动态服务器放在最前端而是在前方会放nginx或apache除了负载均衡还能静动分离因此HTTPS的加解密应交给nginx这样的高性能服务器处理。Redkale再提供HTTPS服务就显得鸡肋。JSP其实算是一个落后的技术现在是一个多样化终端的时代终端不只局限于桌面程序和PC浏览器还有原生App、混合式App、微信端、移动H5、提供第三方接口等各种形式的终端这些都不是JSP能方便兼顾的而HTTP+JSON作为通用性接口可以避免重复开发模版引擎的功能加上各种强大的JS框架足以取代JSP。Redkale在功能上做了筛选不会为迎合主流而提供而是以良好的设计思想为指导。这是Redkale的主导思维
</p>
&nbsp;&nbsp;&nbsp;由于RedKale使用了JDK 8 内置的ASM包所以需要在源码工程中的编译器选项中加入 <b>-XDignore.symbol.file=true</b>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h5>详情请访问:&nbsp;&nbsp;&nbsp;&nbsp;<a href='http://redkale.org' target='_blank'>http://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>

7
bin/apidoc.bat Normal file
View File

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

18
bin/apidoc.sh Normal file
View File

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

View File

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

View File

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

296
pom.xml
View File

@@ -1,158 +1,140 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.redkale</groupId>
<artifactId>redkale</artifactId>
<name>Redkale</name>
<packaging>jar</packaging>
<url>http://redkale.org</url>
<!-- -SNAPSHOT
mvn clean deploy -P release -Dgpg.passphrase=password
mvn release:clean release:prepare release:perform
-->
<version>1.0.0-rc1</version>
<description>Redkale is a Microservices Framework written in Java</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<encoding>UTF-8</encoding>
<compilerArguments>
<verbose />
<bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<mainClass>org.redkale.boot.Application</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
<configuration>
<charset>${file_encoding}</charset>
<encoding>${file_encoding}</encoding>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-javac</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.0.22</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>release-sign-artifacts</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<scm>
<url>https://github.com/redkale/redkale/tags/redkale-1.0.0-rc1</url>
<connection>scm:svn:https://github.com/redkale/redkale/tags/redkale-1.0.0-rc1</connection>
</scm>
<developers>
<developer>
<id>redkale</id>
<name>redkale</name>
<email>redkale@qq.com</email>
</developer>
</developers>
<licenses>
<license>
<name>Apache 2</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
<comments>A business-friendly OSS license</comments>
</license>
</licenses>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.redkale</groupId>
<artifactId>redkale</artifactId>
<packaging>jar</packaging>
<url>http://redkale.org</url>
<description>redkale -- java framework</description>
<version>1.4.0-SNAPSHOT</version>
<licenses>
<license>
<name>Apache 2</name>
<url>http://www.apache.org/licenses/</url>
<distribution>repo</distribution>
<comments>Apache License</comments>
</license>
</licenses>
<developers>
<developer>
<id>Redkale</id>
<name>redkale</name>
<email>redkale@qq.com</email>
<url>http://redkale.org</url>
<roles>
<role>Project Manager</role>
<role>Architect</role>
</roles>
<organization>redkale</organization>
<organizationUrl>http://redkale.org</organizationUrl>
<properties>
<dept>No</dept>
</properties>
<timezone>8</timezone>
</developer>
</developers>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<name>Redkale</name>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<scm>
<url>https://github.com/redkale/redkale</url>
<connection>scm:git:git@github.com/redkale/redkale.git</connection>
<developerConnection>scm:git:git@github.com:redkale/redkale.git</developerConnection>
</scm>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<encoding>UTF-8</encoding>
<compilerArguments>
<verbose />
<bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<mainClass>org.redkale.boot.Application</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-javac</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.0.22</version>
</dependency>
</dependencies>
</project>

View File

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

View File

@@ -16,6 +16,8 @@ java.util.logging.FileHandler.limit = 10485760
java.util.logging.FileHandler.count = 100
java.util.logging.FileHandler.encoding = UTF-8
java.util.logging.FileHandler.pattern = ${APP_HOME}/logs-%m/log-%u.log
#java.util.logging.FileHandler.unusual \u5c5e\u6027\u8868\u793a\u5c06 WARNING\u3001SEVERE \u7ea7\u522b\u7684\u65e5\u5fd7\u590d\u5236\u5199\u5165\u5355\u72ec\u7684\u6587\u4ef6\u4e2d
#java.util.logging.FileHandler.unusual = ${APP_HOME}/logs-%m/log-error-%u.log
java.util.logging.FileHandler.append = true
#java.util.logging.ConsoleHandler.level = FINE

View File

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

View File

@@ -1,4 +1,4 @@
/*******************************************************************************
/** *****************************************************************************
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -12,7 +12,7 @@
* Linda DeMichiel - Java Persistence 2.1
* Linda DeMichiel - Java Persistence 2.0
*
******************************************************************************/
***************************************************************************** */
package javax.persistence;
import static java.lang.annotation.ElementType.TYPE;
@@ -27,19 +27,28 @@ import java.lang.annotation.Target;
* The value of the <code>Cacheable</code> annotation is inherited by
* subclasses; it can be overridden by specifying
* <code>Cacheable</code> on a subclass.
*
* <p> <code>Cacheable(false)</code> means that the entity and its state must
*
* <p>
* <code>Cacheable(false)</code> means that the entity and its state must
* not be cached by the provider.
*
*
* @since Java Persistence 2.0
*/
@Target( { TYPE })
@Target({TYPE})
@Retention(RUNTIME)
public @interface Cacheable {
/**
* (Optional) Whether or not the entity should be cached.
*
* @return boolean
*/
boolean value() default true;
/**
* (Optional) 定时自动更新缓存的周期秒数为0表示不做定时更新 大于0表示每经过interval秒后会自动从数据库中拉取数据更新Cache
*
* @return int
*/
int interval() default 0;
}

View File

@@ -61,6 +61,13 @@ public @interface Column {
*/
String name() default "";
/**
* (Optional) The comment of the column.
*
* @return String
*/
String comment() default "";
/**
* (Optional) Whether the column is a unique key. This is a
* shortcut for the <code>UniqueConstraint</code> annotation at the table
@@ -96,17 +103,6 @@ public @interface Column {
*/
boolean updatable() default true;
/**
* (Optional) The SQL fragment that is used when
* generating the DDL for the column.
* <p>
* Defaults to the generated SQL to create a
* column of the inferred type.
*
* @return String
*/
String columnDefinition() default "";
/**
* (Optional) The name of the table that contains the column.
* If absent the column is assumed to be in the primary table.

View File

@@ -40,4 +40,11 @@ public @interface Entity {
* @return String
*/
String name() default "";
/**
* (Optional) The comment of the entity.
*
* @return String
*/
String comment() default "";
}

View File

@@ -1,4 +1,4 @@
/*******************************************************************************
/** *****************************************************************************
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -12,7 +12,7 @@
* Linda DeMichiel - Java Persistence 2.1
* Linda DeMichiel - Java Persistence 2.0
*
******************************************************************************/
***************************************************************************** */
package javax.persistence;
import java.lang.annotation.Target;
@@ -23,13 +23,14 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Provides for the specification of generation strategies for the
* values of primary keys.
* values of primary keys.
*
* <p> The <code>GeneratedValue</code> annotation
* <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
* required to be supported for simple primary keys. Use of the
* <code>GeneratedValue</code> annotation is not supported for derived
* primary keys.
*
@@ -58,22 +59,5 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
public @interface GeneratedValue {
/**
* (Optional) The primary key generation strategy
* that the persistence provider must use to
* generate the annotated entity primary key.
* @return GenerationType
*/
@Deprecated
GenerationType strategy() default GenerationType.AUTO;
/**
* (Optional) The name of the primary key generator
* to use as specified in the SequenceGenerator
* or TableGenerator annotation.
* <p> Defaults to the id generator supplied by persistence provider.
* @return String
*/
@Deprecated
String generator() default "";
}

View File

@@ -1,56 +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;
/**
* Defines the types of primary key generation strategies.
*
* @see GeneratedValue
*
* @since Java Persistence 1.0
*/
public enum GenerationType {
/**
* Indicates that the persistence provider must assign
* primary keys for the entity using an underlying
* database table to ensure uniqueness.
*/
TABLE,
/**
* Indicates that the persistence provider must assign
* primary keys for the entity using a database sequence.
*/
SEQUENCE,
/**
* Indicates that the persistence provider must assign
* primary keys for the entity using a database identity column.
*/
IDENTITY,
/**
* Indicates that the persistence provider should pick an
* appropriate strategy for the particular database. The
* <code>AUTO</code> generation strategy may expect a database
* resource to exist, or it may attempt to create one. A vendor
* may provide documentation on how to create such resources
* in the event that it does not support schema generation
* or cannot create the schema resource at runtime.
*/
AUTO
}

View File

@@ -0,0 +1,69 @@
/** *****************************************************************************
* Copyright (c) 2011 - 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
*
***************************************************************************** */
package javax.persistence;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Used in schema generation to specify creation of an index.
* <p>
* Note that it is not necessary to specify an index for a primary key,
* as the primary key index will be created automatically.
*
* <p>
* The syntax of the <code>columnList</code> element is a
* <code>column_list</code>, as follows:
*
* <pre>
* column::= index_column [,index_column]*
* index_column::= column_name [ASC | DESC]
* </pre>
*
* <p>
* If <code>ASC</code> or <code>DESC</code> is not specified,
* <code>ASC</code> (ascending order) is assumed.
*
* @since Java Persistence 2.1
*
*/
@Target({})
@Retention(RUNTIME)
public @interface Index {
/**
* (Optional) The name of the index; defaults to a provider-generated name.
*
* @return String
*/
String name() default "";
/**
* (Required) The names of the columns to be included in the index,
* in order.
*
* @return String
*/
String columnList();
/**
* (Optional) Whether the index is unique.
*
* @return boolean
*/
boolean unique() default false;
}

View File

@@ -1,4 +1,4 @@
/*******************************************************************************
/** *****************************************************************************
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -12,7 +12,7 @@
* Linda DeMichiel - Java Persistence 2.1
* Linda DeMichiel - Java Persistence 2.0
*
******************************************************************************/
***************************************************************************** */
package javax.persistence;
import java.lang.annotation.Target;
@@ -22,9 +22,10 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Specifies the primary table for the annotated entity. Additional
* tables may be specified using SecondaryTable or SecondaryTables annotation.
* tables may be specified using SecondaryTable or SecondaryTables annotation.
*
* <p> If no <code>Table</code> annotation is specified for an entity
* <p>
* If no <code>Table</code> annotation is specified for an entity
* class, the default values apply.
*
* <pre>
@@ -37,27 +38,50 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
*
* @since Java Persistence 1.0
*/
@Target(TYPE)
@Target(TYPE)
@Retention(RUNTIME)
public @interface Table {
/**
* (Optional) The name of the table.
* <p> Defaults to the entity name.
* <p>
* Defaults to the entity name.
*
* @return String
*/
String name() default "";
/** (Optional) The catalog of the table.
* <p> Defaults to the default catalog.
* <p>
* Defaults to the default catalog.
*
* @return String
*/
String catalog() default "";
/** (Optional) The schema of the table.
* <p> Defaults to the default schema for user.
* @return String
/**
* (Optional) Unique constraints that are to be placed on
* the table. These are only used if table generation is in
* effect. These constraints apply in addition to any constraints
* specified by the <code>Column</code> and <code>JoinColumn</code>
* annotations and constraints entailed by primary key mappings.
* <p>
* Defaults to no additional constraints.
* @return UniqueConstraint[]
*/
String schema() default "";
UniqueConstraint[] uniqueConstraints() default {};
/**
* (Optional) Indexes for the table. These are only used if
* table generation is in effect. Note that it is not necessary
* to specify an index for a primary key, as the primary key
* index will be created automatically.
*
* @return indexes
* @since Java Persistence 2.1
*/
Index[] indexes() default {};
String comment() default "";
}

View File

@@ -0,0 +1,56 @@
/** *****************************************************************************
* 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.RetentionPolicy.RUNTIME;
/**
* Specifies that a unique constraint is to be included in
* the generated DDL for a primary or secondary table.
*
* <pre>
* Example:
* &#064;Entity
* &#064;Table(
* name="EMPLOYEE",
* uniqueConstraints=
* &#064;UniqueConstraint(columnNames={"EMP_ID", "EMP_NAME"})
* )
* public class Employee { ... }
* </pre>
*
* @since Java Persistence 1.0
*/
@Target({})
@Retention(RUNTIME)
public @interface UniqueConstraint {
/** (Optional) Constraint name. A provider-chosen name will be chosen
* if a name is not specified.
*
* @return String
* @since Java Persistence 2.0
*/
String name() default "";
/** (Required) An array of the column names that make up the constraint.
*
* @return String[]
*/
String[] columnNames();
}

View File

@@ -0,0 +1,211 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.boot;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import javax.persistence.*;
import org.redkale.convert.json.JsonConvert;
import org.redkale.net.http.*;
import org.redkale.source.*;
import org.redkale.util.*;
/**
* API接口文档生成类作用生成Application实例中所有HttpServer的可用HttpServlet的API接口方法 <br>
继承 HttpBaseServlet 是为了获取 WebMapping 信息
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
*/
public class ApiDocs extends HttpBaseServlet {
private final Application app; //Application全局对象
public ApiDocs(Application app) {
this.app = app;
}
public void run() throws Exception {
List<Map> serverList = new ArrayList<>();
Map<String, Map<String, Map<String, Object>>> typesmap = new LinkedHashMap<>();
for (NodeServer node : app.servers) {
if (!(node instanceof NodeHttpServer)) continue;
final Map<String, Object> map = new LinkedHashMap<>();
serverList.add(map);
HttpServer server = node.getServer();
map.put("address", server.getSocketAddress());
List<Map<String, Object>> servletsList = new ArrayList<>();
map.put("servlets", servletsList);
for (HttpServlet servlet : server.getPrepareServlet().getServlets()) {
if (!(servlet instanceof HttpServlet)) continue;
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
if (ws == null) {
System.err.println(servlet + " not found @WebServlet");
continue;
}
final Map<String, Object> servletmap = new LinkedHashMap<>();
String prefix = _prefix(servlet);
String[] mappings = ws.value();
if (prefix != null && !prefix.isEmpty()) {
for (int i = 0; i < mappings.length; i++) {
mappings[i] = prefix + mappings[i];
}
}
servletmap.put("mappings", mappings);
servletmap.put("moduleid", ws.moduleid());
servletmap.put("name", ws.name());
servletmap.put("comment", ws.comment());
List<Map> mappingsList = new ArrayList<>();
servletmap.put("mappings", mappingsList);
final Class selfClz = servlet.getClass();
Class clz = servlet.getClass();
HashSet<String> actionurls = new HashSet<>();
do {
if (Modifier.isAbstract(clz.getModifiers())) break;
for (Method method : clz.getMethods()) {
if (method.getParameterCount() != 2) continue;
WebMapping action = method.getAnnotation(WebMapping.class);
if (action == null) continue;
if (!action.inherited() && selfClz != clz) continue; //忽略不被继承的方法
final Map<String, Object> mappingmap = new LinkedHashMap<>();
if (actionurls.contains(action.url())) continue;
mappingmap.put("url", prefix + action.url());
actionurls.add(action.url());
mappingmap.put("auth", method.getAnnotation(AuthIgnore.class) == null);
mappingmap.put("actionid", action.actionid());
mappingmap.put("comment", action.comment());
List<Map> paramsList = new ArrayList<>();
mappingmap.put("params", paramsList);
List<String> results = new ArrayList<>();
for (final Class rtype : action.results()) {
results.add(rtype.getName());
if (typesmap.containsKey(rtype.getName())) continue;
final boolean filter = FilterBean.class.isAssignableFrom(rtype);
final Map<String, Map<String, Object>> typemap = new LinkedHashMap<>();
Class loop = rtype;
do {
if (loop == null || loop.isInterface()) break;
for (Field field : loop.getDeclaredFields()) {
if (Modifier.isFinal(field.getModifiers())) continue;
if (Modifier.isStatic(field.getModifiers())) continue;
Map<String, Object> fieldmap = new LinkedHashMap<>();
fieldmap.put("type", field.getType().isArray() ? (field.getType().getComponentType().getName() + "[]") : field.getGenericType().getTypeName());
Comment comment = field.getAnnotation(Comment.class);
Column col = field.getAnnotation(Column.class);
FilterColumn fc = field.getAnnotation(FilterColumn.class);
if (comment != null) {
fieldmap.put("comment", comment.value());
} else if (col != null) {
fieldmap.put("comment", col.comment());
} else if (fc != null) {
fieldmap.put("comment", fc.comment());
}
fieldmap.put("primary", !filter && (field.getAnnotation(Id.class) != null));
fieldmap.put("updatable", (filter || col == null || col.updatable()));
if (servlet.getClass().getAnnotation(Rest.RestDynamic.class) != null) {
if (field.getAnnotation(RestAddress.class) != null) continue;
}
typemap.put(field.getName(), fieldmap);
}
} while ((loop = loop.getSuperclass()) != Object.class);
typesmap.put(rtype.getName(), typemap);
}
mappingmap.put("results", results);
for (WebParam param : method.getAnnotationsByType(WebParam.class)) {
final Map<String, Object> parammap = new LinkedHashMap<>();
final boolean isarray = param.type().isArray();
final Class ptype = isarray ? param.type().getComponentType() : param.type();
parammap.put("name", param.name());
parammap.put("radix", param.radix());
parammap.put("type", ptype.getName() + (isarray ? "[]" : ""));
parammap.put("src", param.src());
parammap.put("comment", param.comment());
parammap.put("required", param.required());
paramsList.add(parammap);
if (ptype.isPrimitive() || ptype == String.class) continue;
if (typesmap.containsKey(ptype.getName())) continue;
final Map<String, Map<String, Object>> typemap = new LinkedHashMap<>();
Class loop = ptype;
final boolean filter = FilterBean.class.isAssignableFrom(loop);
do {
if (loop == null || loop.isInterface()) break;
for (Field field : loop.getDeclaredFields()) {
if (Modifier.isFinal(field.getModifiers())) continue;
if (Modifier.isStatic(field.getModifiers())) continue;
Map<String, Object> fieldmap = new LinkedHashMap<>();
fieldmap.put("type", field.getType().isArray() ? (field.getType().getComponentType().getName() + "[]") : field.getGenericType().getTypeName());
Column col = field.getAnnotation(Column.class);
FilterColumn fc = field.getAnnotation(FilterColumn.class);
Comment comment = field.getAnnotation(Comment.class);
if (comment != null) {
fieldmap.put("comment", comment.value());
} else if (col != null) {
fieldmap.put("comment", col.comment());
} else if (fc != null) {
fieldmap.put("comment", fc.comment());
}
fieldmap.put("primary", !filter && (field.getAnnotation(Id.class) != null));
fieldmap.put("updatable", (filter || col == null || col.updatable()));
if (servlet.getClass().getAnnotation(Rest.RestDynamic.class) != null) {
if (field.getAnnotation(RestAddress.class) != null) continue;
}
typemap.put(field.getName(), fieldmap);
}
} while ((loop = loop.getSuperclass()) != Object.class);
typesmap.put(ptype.getName(), typemap);
}
mappingmap.put("result", action.result());
mappingsList.add(mappingmap);
}
} while ((clz = clz.getSuperclass()) != HttpServlet.class);
mappingsList.sort((o1, o2) -> ((String) o1.get("url")).compareTo((String) o2.get("url")));
servletsList.add(servletmap);
}
servletsList.sort((o1, o2) -> {
String[] mappings1 = (String[]) o1.get("mappings");
String[] mappings2 = (String[]) o2.get("mappings");
return mappings1.length > 0 ? (mappings2.length > 0 ? mappings1[0].compareTo(mappings2[0]) : 1) : -1;
});
}
Map<String, Object> resultmap = new LinkedHashMap<>();
resultmap.put("servers", serverList);
resultmap.put("types", typesmap);
final String json = JsonConvert.root().convertTo(resultmap);
final FileOutputStream out = new FileOutputStream(new File(app.getHome(), "apidoc.json"));
out.write(json.getBytes("UTF-8"));
out.close();
File doctemplate = new File(app.getHome(), "conf/apidoc-template.html");
InputStream in = null;
if (doctemplate.isFile() && doctemplate.canRead()) {
in = new FileInputStream(doctemplate);
}
if (in == null) in = ApiDocs.class.getResourceAsStream("apidoc-template.html");
String content = Utility.read(in).replace("'${content}'", json);
in.close();
FileOutputStream outhtml = new FileOutputStream(new File(app.getHome(), "apidoc.html"));
outhtml.write(content.getBytes("UTF-8"));
outhtml.close();
}
@Override
public boolean authenticate(int moduleid, int actionid, HttpRequest request, HttpResponse response) throws IOException {
return true;
}
}

View File

@@ -6,6 +6,7 @@
package org.redkale.boot;
import java.io.*;
import java.lang.reflect.Modifier;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;
@@ -29,77 +30,117 @@ import org.redkale.watch.WatchFactory;
import org.w3c.dom.*;
/**
*
* 进程启动类,全局对象。 <br>
* <pre>
* 程序启动执行步骤:
* 1、读取application.xml
* 2、进行classpath扫描动态加载Service与Servlet
* 3、优先加载所有SNCP协议的服务再加载其他协议服务
* 4、最后进行Service、Servlet与其他资源之间的依赖注入
* </pre>
* <p>
* 编译时需要加入: -XDignore.symbol.file=true
* <p>
* 进程启动类程序启动后读取application.xml,进行classpath扫描动态加载Service与Servlet 优先加载所有SNCP协议的服务 再加载其他协议服务, 最后进行Service、Servlet与其他资源之间的依赖注入。
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/
public final class Application {
//当前进程启动的时间, 类型: long
/**
* 当前进程启动的时间, 类型: long
*/
public static final String RESNAME_APP_TIME = "APP_TIME";
//当前进程的根目录, 类型String、File、Path
/**
* 当前进程的根目录, 类型String、File、Path
*/
public static final String RESNAME_APP_HOME = "APP_HOME";
//application.xml 文件中resources节点的内容 类型: AnyValue
/**
* application.xml 文件中resources节点的内容 类型: AnyValue
*/
public static final String RESNAME_APP_GRES = "APP_GRES";
//当前进程节点的name 类型String
/**
* 当前进程节点的name 类型String
*/
public static final String RESNAME_APP_NODE = "APP_NODE";
//当前进程节点的IP地址 类型InetAddress、String
/**
* 当前进程节点的IP地址 类型InetAddress、String
*/
public static final String RESNAME_APP_ADDR = "APP_ADDR";
//当前Service的IP地址+端口 类型: SocketAddress、InetSocketAddress、String
/**
* 当前Service的IP地址+端口 类型: SocketAddress、InetSocketAddress、String
*/
public static final String RESNAME_SERVER_ADDR = "SERVER_ADDR";
//当前SNCP Server所属的组 类型: String
/**
* 当前SNCP Server所属的组 类型: String
*/
public static final String RESNAME_SERVER_GROUP = "SERVER_GROUP";
//当前Server的ROOT目录 类型String、File、Path
/**
* 当前Server的ROOT目录 类型String、File、Path
*/
public static final String RESNAME_SERVER_ROOT = Server.RESNAME_SERVER_ROOT;
//每个地址对应的Group名
final Map<InetSocketAddress, String> globalNodes = new HashMap<>();
final Map<String, Set<InetSocketAddress>> globalGroups = new HashMap<>();
final Map<String, String> globalGroupProtocols = new HashMap<>();
//协议地址的Group集合
final Map<String, GroupInfo> globalGroups = new HashMap<>();
//本地IP地址
final InetAddress localAddress;
//CacheSource 资源
final List<CacheSource> cacheSources = new CopyOnWriteArrayList<>();
//DataSource 资源
final List<DataSource> dataSources = new CopyOnWriteArrayList<>();
//NodeServer 资源
final List<NodeServer> servers = new CopyOnWriteArrayList<>();
CountDownLatch servicecdl; //会出现两次赋值
//传输端的ByteBuffer对象池
final ObjectPool<ByteBuffer> transportBufferPool;
//传输端的线程池
final ExecutorService transportExecutor;
//传输端的ChannelGroup
final AsynchronousChannelGroup transportChannelGroup;
//全局根ResourceFactory
final ResourceFactory resourceFactory = ResourceFactory.root();
//临时计数器
CountDownLatch servicecdl; //会出现两次赋值
//--------------------------------------------------------------------------------------------
//是否用于main方法运行
private final boolean singletonrun;
//根WatchFactory
private final WatchFactory watchFactory = WatchFactory.root();
//进程根目录
private final File home;
//日志
private final Logger logger;
//服务配置项
private final AnyValue config;
//服务启动时间
private final long startTime = System.currentTimeMillis();
//Server启动的计数器用于确保所有Server都启动完后再进行下一步处理
private final CountDownLatch serversLatch;
private Application(final AnyValue config) {
@@ -165,7 +206,8 @@ public final class Application {
Properties prop = new Properties();
final String handlers = properties.getProperty("handlers");
if (handlers != null && handlers.contains("java.util.logging.FileHandler")) {
prop.setProperty("handlers", handlers.replace("java.util.logging.FileHandler", fileHandlerClass));
//singletonrun模式下不输出文件日志
prop.setProperty("handlers", handlers.replace("java.util.logging.FileHandler", singletonrun ? "" : fileHandlerClass));
}
if (!prop.isEmpty()) {
String prefix = fileHandlerClass + ".";
@@ -190,6 +232,7 @@ public final class Application {
}
this.logger = Logger.getLogger(this.getClass().getSimpleName());
this.serversLatch = new CountDownLatch(config.getAnyValues("server").length + 1);
logger.log(Level.INFO, "------------------------------- Redkale -------------------------------");
//------------------配置 <transport> 节点 ------------------
ObjectPool<ByteBuffer> transportPool = null;
ExecutorService transportExec = null;
@@ -331,15 +374,14 @@ public final class Application {
if (!"TCP".equalsIgnoreCase(protocol) && !"UDP".equalsIgnoreCase(protocol)) {
throw new RuntimeException("Not supported Transport Protocol " + conf.getValue("protocol"));
}
Set<InetSocketAddress> addrs = globalGroups.get(group);
if (addrs == null) {
addrs = new LinkedHashSet<>();
globalGroupProtocols.put(group, protocol);
globalGroups.put(group, addrs);
GroupInfo ginfo = globalGroups.get(group);
if (ginfo == null) {
ginfo = new GroupInfo(group, protocol, conf.getValue("subprotocol", ""), new LinkedHashSet<>());
globalGroups.put(group, ginfo);
}
for (AnyValue node : conf.getAnyValues("node")) {
final InetSocketAddress addr = new InetSocketAddress(node.getValue("addr"), node.getIntValue("port"));
addrs.add(addr);
ginfo.addrs.add(addr);
String oldgroup = globalNodes.get(addr);
if (oldgroup != null) throw new RuntimeException(addr + " had one more group " + (globalNodes.get(addr)));
globalNodes.put(addr, group);
@@ -362,7 +404,7 @@ public final class Application {
final DatagramChannel channel = DatagramChannel.open();
channel.configureBlocking(true);
channel.socket().setSoTimeout(3000);
channel.bind(new InetSocketAddress(config.getValue("host", "127.0.0.1"), config.getIntValue("port")));
channel.bind(new InetSocketAddress("127.0.0.1", config.getIntValue("port")));
boolean loop = true;
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
while (loop) {
@@ -391,6 +433,19 @@ public final class Application {
buffer.flip();
channel.send(buffer, address);
}
} else if ("APIDOC".equalsIgnoreCase(new String(bytes))) {
try {
new ApiDocs(application).run();
buffer.clear();
buffer.put("APIDOC OK".getBytes());
buffer.flip();
channel.send(buffer, address);
} catch (Exception ex) {
buffer.clear();
buffer.put("APIDOC FAIL".getBytes());
buffer.flip();
channel.send(buffer, address);
}
}
}
} catch (Exception e) {
@@ -401,23 +456,37 @@ public final class Application {
}.start();
}
private void sendShutDown() throws Exception {
private void sendCommand(String command) throws Exception {
final DatagramChannel channel = DatagramChannel.open();
channel.configureBlocking(true);
channel.connect(new InetSocketAddress(config.getValue("host", "127.0.0.1"), config.getIntValue("port")));
channel.connect(new InetSocketAddress("127.0.0.1", config.getIntValue("port")));
ByteBuffer buffer = ByteBuffer.allocate(128);
buffer.put("SHUTDOWN".getBytes());
buffer.put(command.getBytes());
buffer.flip();
channel.write(buffer);
buffer.clear();
channel.configureBlocking(false);
channel.read(buffer);
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
channel.close();
logger.info(new String(bytes));
Thread.sleep(500);
try {
channel.read(buffer);
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
channel.close();
logger.info(new String(bytes));
Thread.sleep(500);
} catch (Exception e) {
if (e instanceof PortUnreachableException) {
if ("APIDOC".equalsIgnoreCase(command)) {
final Application application = Application.create(true);
application.init();
application.start();
new ApiDocs(application).run();
logger.info("APIDOC OK");
return;
}
}
throw e;
}
}
public void start() throws Exception {
@@ -451,7 +520,7 @@ public final class Application {
for (final AnyValue serconf : serconfs) {
Thread thread = new Thread() {
{
String host = serconf.getValue("host", "").replace("0.0.0.0", "[0]");
String host = serconf.getValue("host", "0.0.0.0").replace("0.0.0.0", "*");
setName(serconf.getValue("protocol", "Server").toUpperCase() + "-" + host + ":" + serconf.getIntValue("port") + "-Thread");
this.setDaemon(true);
}
@@ -464,15 +533,15 @@ public final class Application {
final String protocol = serconf.getValue("protocol", "").replaceFirst("\\..+", "").toUpperCase();
NodeServer server = null;
if ("SNCP".equals(protocol)) {
server = new NodeSncpServer(Application.this, serconf);
} else if ("HTTP".equals(protocol)) {
server = NodeSncpServer.createNodeServer(Application.this, serconf);
} else if ("HTTP".equalsIgnoreCase(protocol)) {
server = new NodeHttpServer(Application.this, serconf);
} else {
if (!inited.get()) {
synchronized (nodeClasses) {
if (!inited.getAndSet(true)) { //加载自定义的协议SOCKS
ClassFilter profilter = new ClassFilter(NodeProtocol.class, NodeServer.class);
ClassFilter.Loader.load(home, profilter);
ClassFilter.Loader.load(home, serconf.getValue("excludelibs", "").split(";"), profilter);
final Set<FilterEntry<NodeServer>> entrys = profilter.getFilterEntrys();
for (FilterEntry<NodeServer> entry : entrys) {
final Class<? extends NodeServer> type = entry.getType();
@@ -516,6 +585,7 @@ public final class Application {
}
public static <T extends Service> T singleton(String name, Class<T> serviceClass) throws Exception {
if (serviceClass == null) throw new IllegalArgumentException("serviceClass is null");
final Application application = Application.create(true);
application.init();
application.start();
@@ -523,7 +593,9 @@ public final class Application {
T service = server.resourceFactory.find(name, serviceClass);
if (service != null) return service;
}
return null;
if (Modifier.isAbstract(serviceClass.getModifiers())) throw new IllegalArgumentException("abstract class not allowed");
if (serviceClass.isInterface()) throw new IllegalArgumentException("interface class not allowed");
throw new IllegalArgumentException(serviceClass.getName() + " maybe have zero not-final public method");
}
public static Application create(final boolean singleton) throws IOException {
@@ -537,8 +609,11 @@ public final class Application {
Utility.midnight(); //先初始化一下Utility
//运行主程序
final Application application = Application.create(false);
if (System.getProperty("SHUTDOWN") != null) {
application.sendShutDown();
if (System.getProperty("CMD") != null) {
application.sendCommand(System.getProperty("CMD"));
return;
} else if (System.getProperty("SHUTDOWN") != null) { //兼容旧接口
application.sendCommand("SHUTDOWN");
return;
}
application.init();
@@ -572,15 +647,9 @@ public final class Application {
return null;
}
String findGroupProtocol(String group) {
GroupInfo findGroupInfo(String group) {
if (group == null) return null;
return globalGroupProtocols.get(group);
}
Set<InetSocketAddress> findGlobalGroup(String group) {
if (group == null) return null;
Set<InetSocketAddress> set = globalGroups.get(group);
return set == null ? null : new LinkedHashSet<>(set);
return globalGroups.get(group);
}
private void shutdown() throws Exception {

View File

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

View File

@@ -0,0 +1,80 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.boot;
import java.net.InetSocketAddress;
import java.util.*;
import org.redkale.convert.json.JsonConvert;
/**
* 协议地址组合对象, 对应application.xml 中 resources-&#62;group 节点信息
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
*/
public class GroupInfo {
protected String name; //地址
protected String protocol; //协议 取值范围: TCP、UDP
protected String subprotocol; //子协议,预留使用
protected Set<InetSocketAddress> addrs; //地址列表, 对应 resources-&#62;group-&#62;node节点信息
public GroupInfo() {
}
public GroupInfo(String name, String protocol, String subprotocol, Set<InetSocketAddress> addrs) {
this.name = name;
this.protocol = protocol;
this.subprotocol = subprotocol;
this.addrs = addrs;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getSubprotocol() {
return subprotocol;
}
public void setSubprotocol(String subprotocol) {
this.subprotocol = subprotocol;
}
public Set<InetSocketAddress> getAddrs() {
return addrs;
}
public Set<InetSocketAddress> copyAddrs() {
return addrs == null ? null : new LinkedHashSet<>(addrs);
}
public void setAddrs(Set<InetSocketAddress> addrs) {
this.addrs = addrs;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

View File

@@ -18,7 +18,7 @@ import java.util.logging.Formatter;
/**
* 自定义的日志输出类
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/
@@ -70,12 +70,12 @@ public class LogFileHandler extends Handler {
throwable = sw.toString();
}
return String.format(format,
System.currentTimeMillis(),
source,
record.getLoggerName(),
record.getLevel().getName(),
message,
throwable);
System.currentTimeMillis(),
source,
record.getLoggerName(),
record.getLevel().getName(),
message,
throwable);
}
}
@@ -84,9 +84,13 @@ public class LogFileHandler extends Handler {
private String pattern;
private String unusual; //不为null表示将 WARNING、SEVERE 级别的日志写入单独的文件中
private int limit; //文件大小限制
private final AtomicInteger index = new AtomicInteger();
private final AtomicInteger logindex = new AtomicInteger();
private final AtomicInteger logunusualindex = new AtomicInteger();
private int count = 1; //文件限制
@@ -94,11 +98,17 @@ public class LogFileHandler extends Handler {
private boolean append;
private final AtomicLong length = new AtomicLong();
private final AtomicLong loglength = new AtomicLong();
private final AtomicLong logunusuallength = new AtomicLong();
private File logfile;
private OutputStream stream;
private File logunusualfile;
private OutputStream logstream;
private OutputStream logunusualstream;
public LogFileHandler() {
updateTomorrow();
@@ -114,7 +124,7 @@ public class LogFileHandler extends Handler {
cal.set(Calendar.MILLISECOND, 0);
cal.add(Calendar.DAY_OF_YEAR, 1);
long t = cal.getTimeInMillis();
if (this.tomorrow != t) index.set(0);
if (this.tomorrow != t) logindex.set(0);
this.tomorrow = t;
}
@@ -131,35 +141,59 @@ public class LogFileHandler extends Handler {
while (true) {
try {
LogRecord record = records.take();
final boolean bigger = (limit > 0 && limit <= length.get());
if (bigger || tomorrow <= record.getMillis()) {
final boolean bigger = (limit > 0 && limit <= loglength.get());
final boolean changeday = tomorrow <= record.getMillis();
if (bigger || changeday) {
updateTomorrow();
if (stream != null) {
stream.close();
if (logstream != null) {
logstream.close();
if (bigger) {
for (int i = Math.min(count - 2, index.get() - 1); i > 0; i--) {
for (int i = Math.min(count - 2, logindex.get() - 1); i > 0; i--) {
File greater = new File(logfile.getPath() + "." + i);
if (greater.exists()) Files.move(greater.toPath(), new File(logfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
}
Files.move(logfile.toPath(), new File(logfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
}
stream = null;
logstream = null;
}
}
if (stream == null) {
index.incrementAndGet();
if (unusual != null && changeday && logunusualstream != null) {
logunusualstream.close();
if (limit > 0 && limit <= logunusuallength.get()) {
for (int i = Math.min(count - 2, logunusualindex.get() - 1); i > 0; i--) {
File greater = new File(logunusualfile.getPath() + "." + i);
if (greater.exists()) Files.move(greater.toPath(), new File(logunusualfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
}
Files.move(logunusualfile.toPath(), new File(logunusualfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
}
logunusualstream = null;
}
if (logstream == null) {
logindex.incrementAndGet();
java.time.LocalDate date = LocalDate.now();
logfile = new File(pattern.replace("%m", String.valueOf((date.getYear() * 100 + date.getMonthValue()))).replace("%d", String.valueOf((date.getYear() * 10000 + date.getMonthValue() * 100 + date.getDayOfMonth()))));
logfile.getParentFile().mkdirs();
length.set(logfile.length());
stream = new FileOutputStream(logfile, append);
loglength.set(logfile.length());
logstream = new FileOutputStream(logfile, append);
}
if (unusual != null && logunusualstream == null) {
logunusualindex.incrementAndGet();
java.time.LocalDate date = LocalDate.now();
logunusualfile = new File(unusual.replace("%m", String.valueOf((date.getYear() * 100 + date.getMonthValue()))).replace("%d", String.valueOf((date.getYear() * 10000 + date.getMonthValue() * 100 + date.getDayOfMonth()))));
logunusualfile.getParentFile().mkdirs();
logunusuallength.set(logunusualfile.length());
logunusualstream = new FileOutputStream(logunusualfile, append);
}
//----------------------写日志-------------------------
String message = getFormatter().format(record);
String encoding = getEncoding();
byte[] bytes = encoding == null ? message.getBytes() : message.getBytes(encoding);
stream.write(bytes);
length.addAndGet(bytes.length);
logstream.write(bytes);
loglength.addAndGet(bytes.length);
if (unusual != null && (record.getLevel() == Level.WARNING || record.getLevel() == Level.SEVERE)) {
logunusualstream.write(bytes);
logunusuallength.addAndGet(bytes.length);
}
} catch (Exception e) {
ErrorManager err = getErrorManager();
if (err != null) err.error(null, e, ErrorManager.WRITE_FAILURE);
@@ -177,30 +211,39 @@ public class LogFileHandler extends Handler {
private void configure() {
LogManager manager = LogManager.getLogManager();
String cname = LogFileHandler.class.getName();
pattern = manager.getProperty(cname + ".pattern");
if (pattern == null) {
pattern = "logs-%m/" + getPrefix() + "log-%d.log";
this.pattern = manager.getProperty(cname + ".pattern");
if (this.pattern == null) {
this.pattern = "logs-%m/" + getPrefix() + "log-%d.log";
} else {
int pos = pattern.lastIndexOf('/');
int pos = this.pattern.lastIndexOf('/');
if (pos > 0) {
pattern = pattern.substring(0, pos + 1) + getPrefix() + pattern.substring(pos + 1);
this.pattern = this.pattern.substring(0, pos + 1) + getPrefix() + this.pattern.substring(pos + 1);
} else {
pattern = getPrefix() + pattern;
this.pattern = getPrefix() + this.pattern;
}
}
String unusualstr = manager.getProperty(cname + ".unusual");
if (unusualstr != null) {
int pos = unusualstr.lastIndexOf('/');
if (pos > 0) {
this.unusual = unusualstr.substring(0, pos + 1) + getPrefix() + unusualstr.substring(pos + 1);
} else {
this.unusual = getPrefix() + unusualstr;
}
}
String limitstr = manager.getProperty(cname + ".limit");
try {
if (limitstr != null) limit = Math.abs(Integer.decode(limitstr));
if (limitstr != null) this.limit = Math.abs(Integer.decode(limitstr));
} catch (Exception e) {
}
String countstr = manager.getProperty(cname + ".count");
try {
if (countstr != null) count = Math.max(1, Math.abs(Integer.decode(countstr)));
if (countstr != null) this.count = Math.max(1, Math.abs(Integer.decode(countstr)));
} catch (Exception e) {
}
String appendstr = manager.getProperty(cname + ".append");
try {
if (appendstr != null) append = "true".equalsIgnoreCase(appendstr) || "1".equals(appendstr);
if (appendstr != null) this.append = "true".equalsIgnoreCase(appendstr) || "1".equals(appendstr);
} catch (Exception e) {
}
String levelstr = manager.getProperty(cname + ".level");
@@ -256,7 +299,7 @@ public class LogFileHandler extends Handler {
@Override
public void flush() {
try {
if (stream != null) stream.flush();
if (logstream != null) logstream.flush();
} catch (Exception e) {
ErrorManager err = getErrorManager();
if (err != null) err.error(null, e, ErrorManager.FLUSH_FAILURE);
@@ -266,7 +309,7 @@ public class LogFileHandler extends Handler {
@Override
public void close() throws SecurityException {
try {
if (stream != null) stream.close();
if (logstream != null) logstream.close();
} catch (Exception e) {
ErrorManager err = getErrorManager();
if (err != null) err.error(null, e, ErrorManager.CLOSE_FAILURE);

View File

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

View File

@@ -9,18 +9,31 @@ import java.util.Objects;
import org.redkale.service.Service;
/**
* NodeServer的拦截类
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/
public class NodeInterceptor {
/** *
* Server.start之前调用 <br>
* NodeServer.start的部署是先执行NodeInterceptor.preStart再执行 Server.start 方法
*
* @param server NodeServer
*/
public void preStart(NodeServer server) {
}
/**
* Server.shutdown之前调用 <br>
* NodeServer.shutdown的部署是先执行NodeInterceptor.preShutdown再执行 Server.sshutdown 方法
*
* @param server NodeServer
*/
public void preShutdown(NodeServer server) {
}

View File

@@ -8,10 +8,10 @@ package org.redkale.boot;
import java.lang.annotation.*;
/**
* 根据application.xml中的server节点中的protocol值来适配Server的加载逻辑
* 根据application.xml中的server节点中的protocol值来适配Server的加载逻辑, 只能注解在NodeServer子类上
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/

View File

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

View File

@@ -13,21 +13,30 @@ import org.redkale.net.sncp.*;
import org.redkale.util.*;
/**
* SNCP Server节点的配置Server
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/
@NodeProtocol({"SNCP"})
public final class NodeSncpServer extends NodeServer {
public class NodeSncpServer extends NodeServer {
private final SncpServer sncpServer;
protected final SncpServer sncpServer;
public NodeSncpServer(Application application, AnyValue serconf) {
private NodeSncpServer(Application application, AnyValue serconf) {
super(application, createServer(application, serconf));
this.sncpServer = (SncpServer) this.server;
this.consumer = sncpServer == null ? null : x -> sncpServer.addService(x);
this.consumer = sncpServer == null ? null : x -> sncpServer.addSncpServlet(x);
}
public static NodeServer createNodeServer(Application application, AnyValue serconf) {
if (serconf != null && serconf.getAnyValue("rest") != null) {
((AnyValue.DefaultAnyValue) serconf).addValue("_$sncp", "true");
return new NodeHttpServer(application, serconf);
}
return new NodeSncpServer(application, serconf);
}
private static Server createServer(Application application, AnyValue serconf) {
@@ -53,7 +62,7 @@ public final class NodeSncpServer extends NodeServer {
List<SncpServlet> servlets = sncpServer.getSncpServlets();
Collections.sort(servlets);
for (SncpServlet en : servlets) {
if (sb != null) sb.append(threadName).append(" Loaded ").append(en).append(LINE_SEPARATOR);
if (sb != null) sb.append(threadName).append(" Load ").append(en).append(LINE_SEPARATOR);
}
if (sb != null && sb.length() > 0) logger.log(Level.FINE, sb.toString());
}

View File

@@ -0,0 +1,110 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8"><title>接口文档(apidoc生成)</title>
<style type="text/css">
body {text-align: center;margin:auto;}
a{text-decoration: none;}
.table {margin: auto;border-collapse: collapse;border-spacing: 0;display: block;width: 100%;overflow: auto;word-break: normal;word-break: keep-all;}
.table td,.table th{padding: 0.2rem 0.8rem 0.2rem 0.8rem;border: 1px solid #aaa;}
.table td {text-align: left;}
.s {font-size: 0.8rem; vertical-align: middle;}
.subtable {border-spacing: 0;border: 0;margin:0;}
.subtable td{border: 0;padding: 0 0 0 10px;}
.typetable {border-spacing: 0;border: 0;margin:0;}
.typetable td{border: 0;padding: 2px 20px 2px 10px;}
.typetable .l{border-bottom: 1px solid red;}
</style>
</head>
<body>
<script>
var createhtml = function (jsoncontent) {
var classmap = jsoncontent.types;
var html = [];
html.push('<div style="width:' + Math.floor(window.screen.width * 0.9) + 'px;margin:0 auto;text-align: center;">');
html.push('<br/><br/><table class="table" align="center">');
for (var i = 0; i < jsoncontent.servers.length; i++) {
var servlets = jsoncontent.servers[i].servlets;
if (servlets.length && (servlets[0].comment || "").indexOf("【") === 0) {
servlets.sort(function (a, b) {
return a.comment > b.comment ? -1 : (a.comment == b.comment ? 0 : 1);
});
}
for (var j = 0; j < servlets.length; j++) {
var servlet = servlets[j];
if (html.length > 2) html.push(' <tr><th colspan="5" style="border-bottom:0;">&nbsp;</th></tr>');
html.push(' <tr><th colspan="5" style="border-top:' + ((html.length > 2) ? 0 : 1) + ';">' + (servlet.comment || '未知模块') + '</th></tr>');
html.push(' <tr><th>请求URL</th><th>描 述</th><th>鉴 权</th><th>参 数 <span style="font-size:12px;">(粗体: 必填项; 红色: Header; 蓝色: Cookie)</span></th><th>输 出</th></tr>');
for (var k = 0; k < servlet.mappings.length; k++) {
var action = servlet.mappings[k];
html.push(' <tr>');
html.push('<td style="color:#ff00ff;">' + action.url + '</td>');
html.push('<td>' + action.comment + '</td>');
html.push('<td class="s">模块ID: ' + servlet.moduleid + '<br/>操作ID: ' + action.actionid + '<br/>需鉴权: ' + (action.auth ? '<font style="font-weight:bold;color:green;">true</font>' : '<font color=red>false</font>') + '</td>');
var paramshtml = [];
paramshtml.push('<table class="subtable">');
for (var p = 0; p < action.params.length; p++) {
var param = action.params[p];
var t = param.type.substring(param.type.lastIndexOf('.') + 1);
if (classmap[param.type.replace('[]', '')]) {
t = '<a href="#' + param.type.replace('[]', '') + '">' + t + '</a>';
}
if (param.name == '&') {
paramshtml.push('<tr><td style="font-size:12px;">内置 </td><td> ' + t + '</td><td> 当前用户</td></tr>');
} else {
var w = param.required ? "font-weight:bold;" : "";
var c = ' style="' + w + '"';
if (param.src == "HEADER") c = ' style="color:red;' + w + '"';
if (param.src == "COOKIE") c = ' style="color:blue;' + w + '"';
paramshtml.push('<tr><td ' + c + '> ' + param.name + ' </td><td> ' + t + '</td><td> ' + param.comment + '</td></tr>');
}
}
paramshtml.push('</table>');
html.push('<td class="s" style="padding:0 5px;">' + paramshtml.join('') + '</td>');
var rs = [];
rs.push(action.result.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/([a-zA-Z0-9_\$]+\.)+/g, ""));
var results = action.results || [];
for (var r = 0; r < results.length; r++) {
rs.push('<a href="#' + results[r].replace('[]', '') + '">' + results[r].replace(/([a-zA-Z0-9_\$]+\.)+/g, "") + '</a>');
}
html.push('<td>' + rs.join("<br/>") + '</td>');
html.push('</tr>');
}
}
}
for (var type in classmap) {
html.push(' <tr><th colspan="5" style="border-bottom:0;">&nbsp;</th></tr>');
html.push(' <tr id="' + type + '"><th colspan="5" style="border-top:0;">' + type + '</th></tr>');
html.push(' <tr><td colspan="5"><table class="typetable">');
for (var fieldname in classmap[type]) {
var field = classmap[type][fieldname];
var t = field.type.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\$/g, ".").replace(/([a-zA-Z0-9_\$]+\.)+/g, "");
if (t == 'boolean' || t == 'short' || t == 'int' || t == 'long' || t == 'float' || t == 'double'
|| t == 'boolean[]' || t == 'short[]' || t == 'int[]' || t == 'long[]' || t == 'float[]' || t == 'double[]') {
t = '<font color=blue>' + t + '</font>';
} else if (t == 'String' || t == 'String[]' || t == 'LongRange' || t.indexOf('Map&lt;') === 0) {
t = '<font color=red>' + t + '</font>';
}
var c = (field.comment || '');
if (field.primary) {
c = '【主键】 ' + c;
} else if (!field.updatable) {
c = '【只读】 ' + c;
}
html.push(' <tr class="l"><td>' + fieldname + '</td><td>' + t + '</td><td colspan="2">' + c + '</td></tr>');
}
html.push(' </table></td></tr>');
}
html.push('</table><br/><br/><br/>');
html.push('</div>');
return html.join('');
};
</script>
<script>
var jsoncontent = '${content}'; //这里必须要用单引号引起来
document.write(createhtml(jsoncontent));
</script>
</body>
</html>

View File

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

View File

@@ -10,7 +10,7 @@ import java.lang.reflect.Type;
/**
* 对不明类型的对象进行序列化; BSON序列化时将对象的类名写入WriterJSON则不写入。
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <T> 序列化的泛型类型

View File

@@ -9,12 +9,12 @@ import java.lang.reflect.*;
import java.util.*;
/**
* 对象数组的序列化不包含int[]、long[]这样的primitive class数组.
* 数组长度不能超过 32767。 在BSON中数组长度设定的是short对于大于32767长度的数组传输会影响性能所以没有采用int存储。
* 支持一定程度的泛型。
* 数组的序列化操作类 <br>
* 对象数组的反序列化不包含int[]、long[]这样的primitive class数组。 <br>
* 支持一定程度的泛型。 <br>
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <T> 反解析的数组元素类型
@@ -28,31 +28,53 @@ public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
private final Class componentClass;
private final Decodeable<Reader, T> decoder;
protected final Decodeable<Reader, T> decoder;
private boolean inited = false;
private final Object lock = new Object();
public ArrayDecoder(final ConvertFactory factory, final Type type) {
this.type = type;
if (type instanceof GenericArrayType) {
Type t = ((GenericArrayType) type).getGenericComponentType();
this.componentType = t instanceof TypeVariable ? Object.class : t;
} else if ((type instanceof Class) && ((Class) type).isArray()) {
this.componentType = ((Class) type).getComponentType();
} else {
throw new ConvertException("(" + type + ") is not a array type");
try {
if (type instanceof GenericArrayType) {
Type t = ((GenericArrayType) type).getGenericComponentType();
this.componentType = t instanceof TypeVariable ? Object.class : t;
} else if ((type instanceof Class) && ((Class) type).isArray()) {
this.componentType = ((Class) type).getComponentType();
} else {
throw new ConvertException("(" + type + ") is not a array type");
}
if (this.componentType instanceof ParameterizedType) {
this.componentClass = (Class) ((ParameterizedType) this.componentType).getRawType();
} else {
this.componentClass = (Class) this.componentType;
}
factory.register(type, this);
this.decoder = factory.loadDecoder(this.componentType);
} finally {
inited = true;
synchronized (lock) {
lock.notifyAll();
}
}
if (this.componentType instanceof ParameterizedType) {
this.componentClass = (Class) ((ParameterizedType) this.componentType).getRawType();
} else {
this.componentClass = (Class) this.componentType;
}
factory.register(type, this);
this.decoder = factory.loadDecoder(this.componentType);
}
@Override
public T[] convertFrom(Reader in) {
final int len = in.readArrayB();
if (len == Reader.SIGN_NULL) return null;
if (this.decoder == null) {
if (!this.inited) {
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
final Decodeable<Reader, T> localdecoder = this.decoder;
final List<T> result = new ArrayList();
if (len == Reader.SIGN_NOLENGTH) {

View File

@@ -8,12 +8,12 @@ package org.redkale.convert;
import java.lang.reflect.*;
/**
* 对象数组的序列化不包含int[]、long[]这样的primitive class数组.
* 数组长度不能超过 32767。 在BSON中数组长度设定的是short对于大于32767长度的数组传输会影响性能所以没有必要采用int存储。
* 支持一定程度的泛型。
* 数组的序列化操作类 <br>
* 对象数组的序列化不包含int[]、long[]这样的primitive class数组。 <br>
* 支持一定程度的泛型。 <br>
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <T> 序列化的数组元素类型
@@ -29,19 +29,30 @@ public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
private final Encodeable<Writer, Object> encoder;
private boolean inited = false;
private final Object lock = new Object();
public ArrayEncoder(final ConvertFactory factory, final Type type) {
this.type = type;
if (type instanceof GenericArrayType) {
Type t = ((GenericArrayType) type).getGenericComponentType();
this.componentType = t instanceof TypeVariable ? Object.class : t;
} else if ((type instanceof Class) && ((Class) type).isArray()) {
this.componentType = ((Class) type).getComponentType();
} else {
throw new ConvertException("(" + type + ") is not a array type");
try {
if (type instanceof GenericArrayType) {
Type t = ((GenericArrayType) type).getGenericComponentType();
this.componentType = t instanceof TypeVariable ? Object.class : t;
} else if ((type instanceof Class) && ((Class) type).isArray()) {
this.componentType = ((Class) type).getComponentType();
} else {
throw new ConvertException("(" + type + ") is not a array type");
}
factory.register(type, this);
this.encoder = factory.loadEncoder(this.componentType);
this.anyEncoder = factory.getAnyEncoder();
} finally {
inited = true;
synchronized (lock) {
lock.notifyAll();
}
}
factory.register(type, this);
this.encoder = factory.loadEncoder(this.componentType);
this.anyEncoder = factory.getAnyEncoder();
}
@Override
@@ -55,6 +66,17 @@ public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
out.writeArrayE();
return;
}
if (this.encoder == null) {
if (!this.inited) {
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
out.writeArrayB(value.length);
final Type comp = this.componentType;
boolean first = true;

View File

@@ -11,12 +11,11 @@ import java.lang.reflect.Type;
import java.util.Collection;
/**
* 对象集合的反序列化.
* 集合大小不能超过 32767。 在BSON中集合大小设定的是short对于大于32767长度的集合传输会影响性能所以没有采用int存储。
* 支持一定程度的泛型。
* Collection的反序列化操作类 <br>
* 支持一定程度的泛型。 <br>
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <T> 反解析的集合元素类型
@@ -30,18 +29,29 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
protected Creator<Collection<T>> creator;
private final Decodeable<Reader, T> decoder;
protected final Decodeable<Reader, T> decoder;
private boolean inited = false;
private final Object lock = new Object();
public CollectionDecoder(final ConvertFactory factory, final Type type) {
this.type = type;
if (type instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) type;
this.componentType = pt.getActualTypeArguments()[0];
this.creator = factory.loadCreator((Class) pt.getRawType());
factory.register(type, this);
this.decoder = factory.loadDecoder(this.componentType);
} else {
throw new ConvertException("collectiondecoder not support the type (" + type + ")");
try {
if (type instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) type;
this.componentType = pt.getActualTypeArguments()[0];
this.creator = factory.loadCreator((Class) pt.getRawType());
factory.register(type, this);
this.decoder = factory.loadDecoder(this.componentType);
} else {
throw new ConvertException("collectiondecoder not support the type (" + type + ")");
}
} finally {
inited = true;
synchronized (lock) {
lock.notifyAll();
}
}
}
@@ -49,6 +59,17 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
public Collection<T> convertFrom(Reader in) {
final int len = in.readArrayB();
if (len == Reader.SIGN_NULL) return null;
if (this.decoder == null) {
if (!this.inited) {
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
final Decodeable<Reader, T> localdecoder = this.decoder;
final Collection<T> result = this.creator.create();
if (len == Reader.SIGN_NOLENGTH) {

View File

@@ -9,11 +9,12 @@ import java.lang.reflect.*;
import java.util.Collection;
/**
* 对象集合的序列化.
* 集合大小不能超过 32767。 在BSON中集合大小设定的是short对于大于32767长度的集合传输会影响性能所以没有采用int存储。
* 支持一定程度的泛型。
* Collection的序列化操作类 <br>
* 支持一定程度的泛型。 <br>
*
* <p>
* 详情见: https://redkale.org
*
* <p> 详情见: http://redkale.org
* @author zhangjx
* @param <T> 序列化的集合元素类型
*/
@@ -24,17 +25,28 @@ public final class CollectionEncoder<T> implements Encodeable<Writer, Collection
private final Encodeable<Writer, Object> encoder;
private boolean inited = false;
private final Object lock = new Object();
public CollectionEncoder(final ConvertFactory factory, final Type type) {
this.type = type;
if (type instanceof ParameterizedType) {
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
if (t instanceof TypeVariable) {
this.encoder = factory.getAnyEncoder();
try {
if (type instanceof ParameterizedType) {
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
if (t instanceof TypeVariable) {
this.encoder = factory.getAnyEncoder();
} else {
this.encoder = factory.loadEncoder(t);
}
} else {
this.encoder = factory.loadEncoder(t);
this.encoder = factory.getAnyEncoder();
}
} finally {
inited = true;
synchronized (lock) {
lock.notifyAll();
}
} else {
this.encoder = factory.getAnyEncoder();
}
}
@@ -49,6 +61,17 @@ public final class CollectionEncoder<T> implements Encodeable<Writer, Collection
out.writeArrayE();
return;
}
if (this.encoder == null) {
if (!this.inited) {
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
out.writeArrayB(value.size());
boolean first = true;
for (Object v : value) {

View File

@@ -6,10 +6,10 @@
package org.redkale.convert;
/**
* 序列化操作类
* 序列化/反序列化操作类
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类

View File

@@ -13,7 +13,7 @@ import static java.lang.annotation.RetentionPolicy.*;
* 依附在setter、getter方法、字段进行简单的配置
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/

View File

@@ -8,7 +8,7 @@ package org.redkale.convert;
/**
* ConvertColumn 对应的实体类
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
*/
public final class ConvertColumnEntry {

View File

@@ -12,7 +12,7 @@ import static java.lang.annotation.RetentionPolicy.*;
/**
* ConvertColumn 的多用类
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
*/
@Inherited

View File

@@ -10,11 +10,12 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
/**
* 用于类名的别名 类似javax.persistence.Table
* 该值必须是全局唯一
* 使用场景: 当BSON序列化为了不指定class可以使用@ConvertEntity来取个别名。关联方法: Reader.readClassName() 和 Writer.writeClassName(String value) 。
* 用于类名的别名, 该值必须是全局唯一 <br>
* 使用场景: 当BSON序列化为了不指定class可以使用@ConvertEntity来取个别名。关联方法: Reader.readClassName() 和 Writer.writeClassName(String value) 。
*
* <p>
* 详情见: https://redkale.org
*
* <p> 详情见: http://redkale.org
* @author zhangjx
*/
@Inherited
@@ -23,5 +24,10 @@ import java.lang.annotation.*;
@Retention(RUNTIME)
public @interface ConvertEntity {
/**
* 别名值
*
* @return String
*/
String value();
}

View File

@@ -5,8 +5,11 @@
package org.redkale.convert;
/**
* 序列化自定义异常类
*
* <p>
* 详情见: https://redkale.org
*
* <p> 详情见: http://redkale.org
* @author zhangjx
*/
public class ConvertException extends RuntimeException {

View File

@@ -17,9 +17,10 @@ import org.redkale.convert.ext.*;
import org.redkale.util.*;
/**
* 序列化模块的工厂类用于注册自定义的序列化类型获取Convert
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类
@@ -91,6 +92,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
this.register(InetSocketAddress.class, InetSocketAddressSimpledCoder.instance);
this.register(Pattern.class, PatternSimpledCoder.instance);
this.register(CompletionHandler.class, CompletionHandlerSimpledCoder.instance);
this.register(AsyncHandler.class, AsyncHandlerSimpledCoder.instance);
this.register(URL.class, URLSimpledCoder.instance);
this.register(URI.class, URISimpledCoder.instance);
//---------------------------------------------------------
@@ -104,6 +106,15 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
this.register(double[].class, DoubleArraySimpledCoder.instance);
this.register(String[].class, StringArraySimpledCoder.instance);
//---------------------------------------------------------
this.register(AnyValue.class, Creator.create(AnyValue.DefaultAnyValue.class));
this.register(HttpCookie.class, new Creator<HttpCookie>() {
@Override
@Creator.ConstructorParameters({"name", "value"})
public HttpCookie create(Object... params) {
return new HttpCookie((String) params[0], (String) params[1]);
}
});
}
}
@@ -204,7 +215,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
/**
* 使所有类的所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false
*
* @param skipIgnore
* @param skipIgnore 忽略ignore
*
* @return 自身
*/
@@ -387,7 +398,9 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
} else if (clazz == Object.class) {
od = new ObjectDecoder(type);
decoder = od;
} else if (!clazz.getName().startsWith("java.") || clazz.getName().startsWith("java.awt.geom.Point2D")) {
} else if (!clazz.getName().startsWith("java.")
|| java.net.HttpCookie.class == clazz
|| clazz.getName().startsWith("java.awt.geom.Point2D")) {
Decodeable simpleCoder = null;
for (final Method method : clazz.getDeclaredMethods()) {
if (!Modifier.isStatic(method.getModifiers())) continue;
@@ -467,7 +480,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
encoder = new MapEncoder(this, type);
} else if (clazz == Object.class) {
return (Encodeable<W, E>) this.anyEncoder;
} else if (!clazz.getName().startsWith("java.")) {
} else if (!clazz.getName().startsWith("java.") || java.net.HttpCookie.class == clazz) {
Encodeable simpleCoder = null;
for (final Method method : clazz.getDeclaredMethods()) {
if (!Modifier.isStatic(method.getModifiers())) continue;

View File

@@ -6,8 +6,11 @@
package org.redkale.convert;
/**
* 序列化类型枚举,结合&#64;ConvertColumn使用
*
* <p>
* 详情见: https://redkale.org
*
* <p> 详情见: http://redkale.org
* @author zhangjx
*/
public enum ConvertType {

View File

@@ -9,9 +9,10 @@ import java.lang.reflect.*;
import org.redkale.util.Attribute;
/**
* 字段的反序列化操作类
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类
@@ -88,6 +89,6 @@ public final class DeMember<R extends Reader, T, F> implements Comparable<DeMemb
@Override
public String toString() {
return "DeMember{" + "attribute=" + attribute.field() + ", decoder=" + decoder + '}';
return "DeMember{" + "attribute=" + attribute.field() + ", decoder=" + (decoder == null ? null : decoder.getClass().getName()) + '}';
}
}

View File

@@ -8,9 +8,10 @@ package org.redkale.convert;
import java.lang.reflect.Type;
/**
* 反序列化操作类
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类

View File

@@ -9,9 +9,10 @@ import java.lang.reflect.*;
import org.redkale.util.Attribute;
/**
* 字段的序列化操作类
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <W> Writer输出的子类
@@ -81,6 +82,6 @@ public final class EnMember<W extends Writer, T, F> implements Comparable<EnMemb
@Override
public String toString() {
return "EnMember{" + "attribute=" + attribute.field() + ", encoder=" + encoder + '}';
return "EnMember{" + "attribute=" + attribute.field() + ", encoder=" + (encoder == null ? null : encoder.getClass().getName()) + '}';
}
}

View File

@@ -8,9 +8,10 @@ package org.redkale.convert;
import java.lang.reflect.Type;
/**
* 序列化操作类
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <W> Writer输出的子类

View File

@@ -11,8 +11,11 @@ import java.lang.reflect.Type;
import java.util.Map;
/**
* Map的反序列化操作类
*
* <p>
* 详情见: https://redkale.org
*
* <p> 详情见: http://redkale.org
* @author zhangjx
* @param <K> Map key的数据类型
* @param <V> Map value的数据类型
@@ -28,27 +31,49 @@ public final class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
protected Creator<Map<K, V>> creator;
private final Decodeable<Reader, K> keyDecoder;
protected final Decodeable<Reader, K> keyDecoder;
private final Decodeable<Reader, V> valueDecoder;
protected final Decodeable<Reader, V> valueDecoder;
private boolean inited = false;
private final Object lock = new Object();
public MapDecoder(final ConvertFactory factory, final Type type) {
this.type = type;
if (type instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) type;
this.keyType = pt.getActualTypeArguments()[0];
this.valueType = pt.getActualTypeArguments()[1];
this.creator = factory.loadCreator((Class) pt.getRawType());
factory.register(type, this);
this.keyDecoder = factory.loadDecoder(this.keyType);
this.valueDecoder = factory.loadDecoder(this.valueType);
} else {
throw new ConvertException("mapdecoder not support the type (" + type + ")");
try {
if (type instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) type;
this.keyType = pt.getActualTypeArguments()[0];
this.valueType = pt.getActualTypeArguments()[1];
this.creator = factory.loadCreator((Class) pt.getRawType());
factory.register(type, this);
this.keyDecoder = factory.loadDecoder(this.keyType);
this.valueDecoder = factory.loadDecoder(this.valueType);
} else {
throw new ConvertException("mapdecoder not support the type (" + type + ")");
}
} finally {
inited = true;
synchronized (lock) {
lock.notifyAll();
}
}
}
@Override
public Map<K, V> convertFrom(Reader in) {
if (this.keyDecoder == null || this.valueDecoder == null) {
if (!this.inited) {
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
final int len = in.readMapB();
if (len == Reader.SIGN_NULL) return null;
final Map<K, V> result = this.creator.create();

View File

@@ -10,9 +10,10 @@ import java.lang.reflect.Type;
import java.util.Map;
/**
* Map的序列化操作类
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <K> Map key的数据类型
@@ -27,15 +28,26 @@ public final class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
private final Encodeable<Writer, V> valencoder;
private boolean inited = false;
private final Object lock = new Object();
public MapEncoder(final ConvertFactory factory, final Type type) {
this.type = type;
if (type instanceof ParameterizedType) {
final Type[] pt = ((ParameterizedType) type).getActualTypeArguments();
this.keyencoder = factory.loadEncoder(pt[0]);
this.valencoder = factory.loadEncoder(pt[1]);
} else {
this.keyencoder = factory.getAnyEncoder();
this.valencoder = factory.getAnyEncoder();
try {
if (type instanceof ParameterizedType) {
final Type[] pt = ((ParameterizedType) type).getActualTypeArguments();
this.keyencoder = factory.loadEncoder(pt[0]);
this.valencoder = factory.loadEncoder(pt[1]);
} else {
this.keyencoder = factory.getAnyEncoder();
this.valencoder = factory.getAnyEncoder();
}
} finally {
inited = true;
synchronized (lock) {
lock.notifyAll();
}
}
}
@@ -46,6 +58,18 @@ public final class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
out.writeNull();
return;
}
if (this.keyencoder == null || this.valencoder == null) {
if (!this.inited) {
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
out.writeMapB(values.size());
boolean first = true;
for (Map.Entry<K, V> en : values.entrySet()) {

View File

@@ -13,9 +13,10 @@ import java.util.Set;
import org.redkale.util.*;
/**
* 自定义对象的反序列化操作类
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类
@@ -66,7 +67,8 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
clazz = (Class) type;
}
this.creator = factory.loadCreator(clazz);
if (this.creator == null) throw new ConvertException("Cannot create a creator for " + clazz);
final Set<DeMember> list = new HashSet();
final String[] cps = ObjectEncoder.findConstructorProperties(this.creator);
try {
@@ -75,7 +77,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
if (Modifier.isStatic(field.getModifiers())) continue;
ref = factory.findRef(field);
if (ref != null && ref.ignore()) continue;
Type t = ObjectEncoder.createClassType(field.getGenericType(), this.type);
Type t = TypeToken.createClassType(field.getGenericType(), this.type);
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, field, null, null), factory.loadDecoder(t)));
}
final boolean reversible = factory.isReversible();
@@ -85,6 +87,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
if (method.isSynthetic()) continue;
if (method.getName().length() < 4) continue;
if (!method.getName().startsWith("set")) continue;
if (method.getAnnotation(java.beans.Transient.class) != null) continue;
if (method.getParameterTypes().length != 1) continue;
if (method.getReturnType() != void.class) continue;
if (reversible && (cps == null || !ObjectEncoder.contains(cps, ConvertFactory.readGetSetFieldName(method)))) {
@@ -97,7 +100,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
}
ref = factory.findRef(method);
if (ref != null && ref.ignore()) continue;
Type t = ObjectEncoder.createClassType(method.getGenericParameterTypes()[0], this.type);
Type t = TypeToken.createClassType(method.getGenericParameterTypes()[0], this.type);
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, null, method), factory.loadDecoder(t)));
}
if (cps != null) { //可能存在某些构造函数中的字段名不存在setter方法
@@ -113,7 +116,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
//不存在setter方法
try {
Field f = clazz.getDeclaredField(constructorField);
Type t = ObjectEncoder.createClassType(f.getGenericType(), this.type);
Type t = TypeToken.createClassType(f.getGenericType(), this.type);
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, f, null, null), factory.loadDecoder(t)));
} catch (NoSuchFieldException nsfe) { //不存在field 可能存在getter方法
char[] fs = constructorField.toCharArray();
@@ -125,7 +128,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
} catch (NoSuchMethodException ex) {
getter = clazz.getMethod("is" + mn);
}
Type t = ObjectEncoder.createClassType(getter.getGenericParameterTypes()[0], this.type);
Type t = TypeToken.createClassType(getter.getGenericParameterTypes()[0], this.type);
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, getter, null), factory.loadDecoder(t)));
}
}

View File

@@ -10,9 +10,10 @@ import java.util.*;
import org.redkale.util.*;
/**
* 自定义对象的序列化操作类
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <W> Writer输出的子类
@@ -67,7 +68,7 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
if (Modifier.isStatic(field.getModifiers())) continue;
ref = factory.findRef(field);
if (ref != null && ref.ignore()) continue;
Type t = createClassType(field.getGenericType(), this.type);
Type t = TypeToken.createClassType(field.getGenericType(), this.type);
list.add(new EnMember(createAttribute(factory, clazz, field, null, null), factory.loadEncoder(t)));
}
for (final Method method : clazz.getMethods()) {
@@ -77,6 +78,7 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
if (method.getName().length() < 3) continue;
if (method.getName().equals("getClass")) continue;
if (!method.getName().startsWith("is") && !method.getName().startsWith("get")) continue;
if (method.getAnnotation(java.beans.Transient.class) != null) continue;
if (method.getParameterTypes().length != 0) continue;
if (method.getReturnType() == void.class) continue;
if (reversible && (cps == null || !contains(cps, ConvertFactory.readGetSetFieldName(method)))) {
@@ -89,7 +91,7 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
}
ref = factory.findRef(method);
if (ref != null && ref.ignore()) continue;
Type t = createClassType(method.getGenericReturnType(), this.type);
Type t = TypeToken.createClassType(method.getGenericReturnType(), this.type);
list.add(new EnMember(createAttribute(factory, clazz, null, method, null), factory.loadEncoder(t)));
}
this.members = list.toArray(new EnMember[list.size()]);
@@ -121,7 +123,7 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
}
}
}
if (value != null && value.getClass() != this.typeClass) {
if (value.getClass() != this.typeClass) {
final Class clz = value.getClass();
if (out.needWriteClassName()) out.writeClassName(factory.getEntityAlias(clz));
factory.loadEncoder(clz).convertTo(out, value);
@@ -144,42 +146,6 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
}
static Type createClassType(final Type type, final Type declaringType0) {
if (TypeToken.isClassType(type)) return type;
if (type instanceof ParameterizedType) { // e.g. Map<String, String>
final ParameterizedType pt = (ParameterizedType) type;
final Type[] paramTypes = pt.getActualTypeArguments();
for (int i = 0; i < paramTypes.length; i++) {
paramTypes[i] = createClassType(paramTypes[i], declaringType0);
}
return TypeToken.createParameterizedType(pt.getOwnerType(), pt.getRawType(), paramTypes);
}
Type declaringType = declaringType0;
if (declaringType instanceof Class) {
do {
declaringType = ((Class) declaringType).getGenericSuperclass();
if (declaringType == Object.class) return Object.class;
} while (declaringType instanceof Class);
}
//存在通配符则declaringType 必须是 ParameterizedType
if (!(declaringType instanceof ParameterizedType)) return Object.class;
final ParameterizedType declaringPType = (ParameterizedType) declaringType;
final Type[] virTypes = ((Class) declaringPType.getRawType()).getTypeParameters();
final Type[] desTypes = declaringPType.getActualTypeArguments();
if (type instanceof WildcardType) { // e.g. <? extends Serializable>
final WildcardType wt = (WildcardType) type;
for (Type f : wt.getUpperBounds()) {
for (int i = 0; i < virTypes.length; i++) {
if (virTypes[i].equals(f)) return desTypes.length <= i ? Object.class : desTypes[i];
}
}
} else if (type instanceof TypeVariable) { // e.g. <? extends E>
for (int i = 0; i < virTypes.length; i++) {
if (virTypes[i].equals(type)) return desTypes.length <= i ? Object.class : desTypes[i];
}
}
return type;
}
//
// static Type makeGenericType(final Type type, final Type[] virGenericTypes, final Type[] realGenericTypes) {
// if (type instanceof Class) { //e.g. String
@@ -228,7 +194,6 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
// }
// return type;
// }
static boolean contains(String[] values, String value) {
for (String str : values) {
if (str.equals(value)) return true;

View File

@@ -6,9 +6,10 @@
package org.redkale.convert;
/**
* 反序列化的数据读取流
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/
@@ -42,6 +43,7 @@ public abstract class Reader {
* 读取对象的类名, 返回 null 表示对象为null 返回空字符串表示当前class与返回的class一致返回非空字符串表示class是当前class的子类。
*
* @param clazz 类名
*
* @return 返回字段数
*/
public String readObjectB(final Class clazz) {
@@ -86,6 +88,7 @@ public abstract class Reader {
* 根据字段读取字段对应的DeMember
*
* @param members DeMember的全量集合
*
* @return 匹配的DeMember
*/
public abstract DeMember readFieldName(final DeMember[] members);

View File

@@ -9,9 +9,11 @@ import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* 简易类的序列化和反序列化操作类 <br>
* 能序列化为Boolean、Number或者字符串的类视为简易类 <br>
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类

View File

@@ -8,9 +8,10 @@ package org.redkale.convert;
import org.redkale.util.Attribute;
/**
* 序列化的数据输出流
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/
@@ -37,7 +38,7 @@ public abstract class Writer {
* @return boolean
*/
public abstract boolean needWriteClassName();
/**
* 写入类名
*

View File

@@ -11,6 +11,9 @@ import static org.redkale.convert.Reader.SIGN_NULL;
import org.redkale.util.*;
/**
* 以ByteBuffer为数据载体的BsonReader
*
* 详情见: https://redkale.org
*
* @author zhangjx
*/
@@ -121,13 +124,13 @@ public class BsonByteBufferReader extends BsonReader {
}
}
return ((((long) readByte() & 0xff) << 56)
| (((long) readByte() & 0xff) << 48)
| (((long) readByte() & 0xff) << 40)
| (((long) readByte() & 0xff) << 32)
| (((long) readByte() & 0xff) << 24)
| (((long) readByte() & 0xff) << 16)
| (((long) readByte() & 0xff) << 8)
| (((long) readByte() & 0xff)));
| (((long) readByte() & 0xff) << 48)
| (((long) readByte() & 0xff) << 40)
| (((long) readByte() & 0xff) << 32)
| (((long) readByte() & 0xff) << 24)
| (((long) readByte() & 0xff) << 16)
| (((long) readByte() & 0xff) << 8)
| (((long) readByte() & 0xff)));
}
protected byte[] read(final int len) {

View File

@@ -7,11 +7,13 @@ package org.redkale.convert.bson;
import java.nio.*;
import java.util.function.*;
import org.redkale.util.Utility;
/**
* 以ByteBuffer为数据载体的BsonWriter
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/
@@ -78,20 +80,14 @@ public class BsonByteBufferWriter extends BsonWriter {
if (!buffer.hasRemaining()) {
buffer.flip();
buffer = supplier.get();
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
bufs[this.buffers.length] = buffer;
this.buffers = bufs;
this.buffers = Utility.append(this.buffers, buffer);
this.index++;
}
int len = buffer.remaining();
int size = 0;
while (len < byteLength) {
buffer = supplier.get();
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
bufs[this.buffers.length] = buffer;
this.buffers = bufs;
this.buffers = Utility.append(this.buffers, buffer);
len += buffer.remaining();
size++;
}

View File

@@ -15,25 +15,25 @@ import org.redkale.util.*;
/**
* <blockquote><pre>
* BSON协议格式:
* 1). 基本数据类型: 直接转换成byte[]
* 2). SmallString(无特殊字符且长度小于256的字符串): length(1 byte) + byte[](utf8); 通常用于类名、字段名、枚举。
* 3). String: length(4 bytes) + byte[](utf8);
* 4). 数组: length(4 bytes) + byte[]...
* 5). Object:
* 1. realclass (SmallString) (如果指定格式化的class与实体对象的class不一致才会有该值, 该值可以使用@ConvertEntity给其取个别名)
* 2. 空字符串(SmallString)
* 3. SIGN_OBJECTB 标记位值固定为0xBB (short)
* 4. 循环字段值:
* 1) 基本数据类型: 直接转换成byte[]
* 2) SmallString(无特殊字符且长度小于256的字符串): length(1 byte) + byte[](utf8); 通常用于类名、字段名、枚举。
* 3) String: length(4 bytes) + byte[](utf8);
* 4) 数组: length(4 bytes) + byte[]...
* 5) Object:
* 1 realclass (SmallString) (如果指定格式化的class与实体对象的class不一致才会有该值, 该值可以使用@ConvertEntity给其取个别名)
* 2 空字符串(SmallString)
* 3 SIGN_OBJECTB 标记位值固定为0xBB (short)
* 4 循环字段值:
* 4.1 SIGN_HASNEXT 标记位值固定为1 (byte)
* 4.2 字段类型; 1-9为基本类型和字符串; 101-109为基本类型和字符串的数组; 127为Object
* 4.3 字段名 (SmallString)
* 4.4 字段的值Object
* 5. SIGN_NONEXT 标记位值固定为0 (byte)
* 6. SIGN_OBJECTE 标记位值固定为0xEE (short)
* 5 SIGN_NONEXT 标记位值固定为0 (byte)
* 6 SIGN_OBJECTE 标记位值固定为0xEE (short)
*
* </pre></blockquote>
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/

View File

@@ -7,11 +7,13 @@ package org.redkale.convert.bson;
import java.io.Serializable;
import org.redkale.convert.*;
import org.redkale.util.AnyValue;
/**
* BSON的ConvertFactory
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/
@@ -27,6 +29,9 @@ public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
static {
instance.register(Serializable.class, objectDecoder);
instance.register(Serializable.class, objectEncoder);
instance.register(AnyValue.class, instance.loadDecoder(AnyValue.DefaultAnyValue.class));
instance.register(AnyValue.class, instance.loadEncoder(AnyValue.DefaultAnyValue.class));
}
private BsonFactory(BsonFactory parent, boolean tiny) {

View File

@@ -5,16 +5,16 @@
*/
package org.redkale.convert.bson;
import java.util.function.*;
import org.redkale.convert.*;
import static org.redkale.convert.Reader.SIGN_NULL;
import org.redkale.convert.ext.*;
import org.redkale.util.*;
/**
* BSON数据源
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/
@@ -42,19 +42,7 @@ public class BsonReader extends Reader {
}
public static ObjectPool<BsonReader> createPool(int max) {
return new ObjectPool<BsonReader>(max, new Creator<BsonReader>() {
@Override
public BsonReader create(Object... params) {
return new BsonReader();
}
}, null, new Predicate<BsonReader>() {
@Override
public boolean test(BsonReader t) {
return t.recycle();
}
});
return new ObjectPool<>(max, (Object... params) -> new BsonReader(), null, (t) -> t.recycle());
}
public BsonReader(byte[] bytes) {
@@ -164,7 +152,7 @@ public class BsonReader extends Reader {
if (bt == Reader.SIGN_NULL) return null;
if (bt != SIGN_OBJECTB) {
throw new ConvertException("a bson object must begin with " + (SIGN_OBJECTB)
+ " (position = " + position + ") but '" + currentByte() + "'");
+ " (position = " + position + ") but '" + currentByte() + "'");
}
return "";
}
@@ -173,7 +161,7 @@ public class BsonReader extends Reader {
public final void readObjectE(final Class clazz) {
if (readShort() != SIGN_OBJECTE) {
throw new ConvertException("a bson object must end with " + (SIGN_OBJECTE)
+ " (position = " + position + ") but '" + currentByte() + "'");
+ " (position = " + position + ") but '" + currentByte() + "'");
}
}
@@ -223,7 +211,7 @@ public class BsonReader extends Reader {
byte b = readByte();
if (b == SIGN_HASNEXT) return true;
if (b != SIGN_NONEXT) throw new ConvertException("hasNext option must be (" + (SIGN_HASNEXT)
+ " or " + (SIGN_NONEXT) + ") but '" + b + "' at position(" + this.position + ")");
+ " or " + (SIGN_NONEXT) + ") but '" + b + "' at position(" + this.position + ")");
return false;
}
@@ -272,19 +260,19 @@ public class BsonReader extends Reader {
@Override
public int readInt() {
return ((content[++this.position] & 0xff) << 24) | ((content[++this.position] & 0xff) << 16)
| ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
| ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
}
@Override
public long readLong() {
return ((((long) content[++this.position] & 0xff) << 56)
| (((long) content[++this.position] & 0xff) << 48)
| (((long) content[++this.position] & 0xff) << 40)
| (((long) content[++this.position] & 0xff) << 32)
| (((long) content[++this.position] & 0xff) << 24)
| (((long) content[++this.position] & 0xff) << 16)
| (((long) content[++this.position] & 0xff) << 8)
| (((long) content[++this.position] & 0xff)));
| (((long) content[++this.position] & 0xff) << 48)
| (((long) content[++this.position] & 0xff) << 40)
| (((long) content[++this.position] & 0xff) << 32)
| (((long) content[++this.position] & 0xff) << 24)
| (((long) content[++this.position] & 0xff) << 16)
| (((long) content[++this.position] & 0xff) << 8)
| (((long) content[++this.position] & 0xff)));
}
@Override

View File

@@ -10,7 +10,7 @@ import org.redkale.convert.SimpledCoder;
/**
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <T> 序列化/反解析的数据类型

View File

@@ -9,6 +9,8 @@ import java.io.*;
import org.redkale.convert.*;
/**
*
* 详情见: https://redkale.org
*
* @author zhangjx
*/

View File

@@ -9,6 +9,8 @@ import java.io.*;
import org.redkale.convert.*;
/**
*
* 详情见: https://redkale.org
*
* @author zhangjx
*/

View File

@@ -6,14 +6,13 @@
package org.redkale.convert.bson;
import java.nio.ByteBuffer;
import java.util.function.Predicate;
import org.redkale.convert.*;
import org.redkale.util.*;
/**
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/
@@ -28,19 +27,7 @@ public class BsonWriter extends Writer {
protected boolean tiny;
public static ObjectPool<BsonWriter> createPool(int max) {
return new ObjectPool<BsonWriter>(max, new Creator<BsonWriter>() {
@Override
public BsonWriter create(Object... params) {
return new BsonWriter();
}
}, null, new Predicate<BsonWriter>() {
@Override
public boolean test(BsonWriter t) {
return t.recycle();
}
});
return new ObjectPool<>(max, (Object... params) -> new BsonWriter(), null, (t) -> t.recycle());
}
public byte[] toArray() {
@@ -82,6 +69,7 @@ public class BsonWriter extends Writer {
* 扩充指定长度的缓冲区
*
* @param len 扩容长度
*
* @return 固定0
*/
protected int expand(int len) {

View File

@@ -0,0 +1,36 @@
/*
* 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.AsyncHandler;
/**
* AsyncHandlerSimpledCoder 的SimpledCoder实现, 只输出null
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型
*/
public final class AsyncHandlerSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, AsyncHandler> {
public static final AsyncHandlerSimpledCoder instance = new AsyncHandlerSimpledCoder();
@Override
public void convertTo(W out, AsyncHandler value) {
out.writeObjectNull(AsyncHandler.class);
}
@Override
public AsyncHandler convertFrom(R in) {
in.readObjectB(AsyncHandler.class);
return null;
}
}

View File

@@ -14,7 +14,7 @@ import java.math.BigInteger;
* BigInteger 的SimpledCoder实现
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
* boolean[] 的SimpledCoder实现
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
* boolean 的SimpledCoder实现
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
* byte[] 的SimpledCoder实现
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
* byte 的SimpledCoder实现
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
/**
* char[] 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -10,7 +10,7 @@ import org.redkale.convert.*;
/**
* CharSequence 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
/**
* char 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -12,7 +12,7 @@ import org.redkale.convert.*;
* java.nio.channels.CompletionHandler 的SimpledCoder实现, 只输出null
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -14,7 +14,7 @@ import org.redkale.util.*;
* Dlong 的SimpledCoder实现
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -14,7 +14,7 @@ import java.util.Date;
* Date 的SimpledCoder实现
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
/**
* double[] 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
/**
* double 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
* 枚举 的SimpledCoder实现
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
/**
* float[] 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
/**
* float 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -14,7 +14,7 @@ import java.net.*;
* InetAddress 的SimpledCoder实现
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
/**
* int[] 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
/**
* int 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
* long[] 的SimpledCoder实现
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
/**
* long 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
* Number 的SimpledCoder实现
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -11,7 +11,7 @@ import org.redkale.convert.*;
/**
* Pattern 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
/**
* short[] 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
/**
* short 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
/**
* String[] 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
/**
* String 的SimpledCoder实现
*
* <p> 详情见: http://redkale.org
* <p> 详情见: https://redkale.org
* @author zhangjx
* @param <R> Reader输入的子类型
* @param <W> Writer输出的子类型

View File

@@ -13,7 +13,7 @@ import org.redkale.convert.SimpledCoder;
* Type 的SimpledCoder实现 只支持Type的子类Class
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -11,7 +11,7 @@ import org.redkale.convert.*;
/**
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -11,7 +11,7 @@ import org.redkale.convert.*;
/**
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <R> Reader输入的子类型

View File

@@ -11,8 +11,12 @@ import org.redkale.convert.*;
import static org.redkale.convert.Reader.*;
/**
* 以ByteBuffer为数据载体的JsonReader <br>
*
* 只支持UTF-8格式
*
* 详情见: https://redkale.org
*
* @author zhangjx
*/
public class JsonByteBufferReader extends JsonReader {

View File

@@ -13,9 +13,10 @@ import org.redkale.convert.*;
import org.redkale.util.*;
/**
* 以ByteBuffer为数据载体的JsonWriter
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/
@@ -84,20 +85,14 @@ public class JsonByteBufferWriter extends JsonWriter {
if (!buffer.hasRemaining()) {
buffer.flip();
buffer = supplier.get();
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
bufs[this.buffers.length] = buffer;
this.buffers = bufs;
this.buffers = Utility.append(this.buffers, buffer);
this.index++;
}
int len = buffer.remaining();
int size = 0;
while (len < byteLength) {
buffer = supplier.get();
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
bufs[this.buffers.length] = buffer;
this.buffers = bufs;
this.buffers = Utility.append(this.buffers, buffer);
len += buffer.remaining();
size++;
}

View File

@@ -16,7 +16,7 @@ import org.redkale.util.*;
/**
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/

View File

@@ -10,12 +10,13 @@ import java.math.BigInteger;
import java.net.*;
import org.redkale.convert.*;
import org.redkale.convert.ext.*;
import org.redkale.util.DLong;
import org.redkale.util.*;
/**
* JSON的ConvertFactory
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/
@@ -29,6 +30,9 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
instance.register(DLong.class, DLongSimpledCoder.DLongJsonSimpledCoder.instance);
instance.register(BigInteger.class, BigIntegerSimpledCoder.BigIntegerJsonSimpledCoder.instance);
instance.register(Serializable.class, instance.loadEncoder(Object.class));
instance.register(AnyValue.class, instance.loadDecoder(AnyValue.DefaultAnyValue.class));
instance.register(AnyValue.class, instance.loadEncoder(AnyValue.DefaultAnyValue.class));
}
private JsonFactory(JsonFactory parent, boolean tiny) {

View File

@@ -10,9 +10,10 @@ import static org.redkale.convert.Reader.*;
import org.redkale.util.*;
/**
* JSON数据源
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
*/

View File

@@ -10,7 +10,7 @@ import org.redkale.convert.SimpledCoder;
/**
*
* <p>
* 详情见: http://redkale.org
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <T> 序列化/反解析的数据类型

View File

@@ -10,6 +10,8 @@ import org.redkale.convert.*;
/**
*
* 详情见: https://redkale.org
*
* @author zhangjx
*/
class JsonStreamReader extends JsonByteBufferReader {

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