Compare commits
298 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9f2e080da | ||
|
|
027fa3a18b | ||
|
|
d9f50d63f0 | ||
|
|
181486c348 | ||
|
|
74adfdfc99 | ||
|
|
c3783eb041 | ||
|
|
77451561e6 | ||
|
|
59d30b05f2 | ||
|
|
2fcf0bb644 | ||
|
|
71ab9c9728 | ||
|
|
09165127e3 | ||
|
|
c28310e0df | ||
|
|
51435a1c33 | ||
|
|
83c70b9767 | ||
|
|
5534dcd476 | ||
|
|
d18a55deaf | ||
|
|
ae2d64991c | ||
|
|
ecb6b80e5e | ||
|
|
cf332fa67a | ||
|
|
ffa80c9212 | ||
|
|
7463a8f6b5 | ||
|
|
a168897784 | ||
|
|
d39b3856ca | ||
|
|
ca9f74185b | ||
|
|
c35e421ba3 | ||
|
|
65755e0787 | ||
|
|
366c3becc4 | ||
|
|
a1ac6ec543 | ||
|
|
b27bbb7836 | ||
|
|
a57574dd10 | ||
|
|
a7dd22569c | ||
|
|
0bc0755fb3 | ||
|
|
c2edb60218 | ||
|
|
60c1a82a62 | ||
|
|
e3205128b4 | ||
|
|
a9dff0360f | ||
|
|
1e871cbee5 | ||
|
|
41aadf33f3 | ||
|
|
679567c85a | ||
|
|
b77050250c | ||
|
|
e178d1120b | ||
|
|
eca138b671 | ||
|
|
0366aef672 | ||
|
|
30103e5c8f | ||
|
|
cbba7701d8 | ||
|
|
da53bd7db9 | ||
|
|
9e7999da0f | ||
|
|
2c96f991d5 | ||
|
|
67f8127452 | ||
|
|
bce498885e | ||
|
|
eb57a25698 | ||
|
|
4e83e5bf71 | ||
|
|
19a44ce8cf | ||
|
|
0bd0df3245 | ||
|
|
4f0163736f | ||
|
|
8d03f52f09 | ||
|
|
815267a590 | ||
|
|
77f8d442b2 | ||
|
|
aacda5d35e | ||
|
|
58d02f6471 | ||
|
|
c735874cff | ||
|
|
045029b4a9 | ||
|
|
f6b5882cd4 | ||
|
|
63a9005e6b | ||
|
|
c4923f317b | ||
|
|
15e03c0459 | ||
|
|
74f4ddf50b | ||
|
|
fdc868641d | ||
|
|
910eb88c55 | ||
|
|
b597131de4 | ||
|
|
56d5f97556 | ||
|
|
b364dd5811 | ||
|
|
4fec27498c | ||
|
|
7a195ecf23 | ||
|
|
95b7e819cd | ||
|
|
73d243aaf1 | ||
|
|
998fecdd51 | ||
|
|
b1ddc0e3a5 | ||
|
|
641ff4709d | ||
|
|
13f2fbf7d6 | ||
|
|
62f9882314 | ||
|
|
7f270eb9d7 | ||
|
|
974a6bfeaa | ||
|
|
4958b454af | ||
|
|
3531d0963d | ||
|
|
41e6497a2e | ||
|
|
3439fab690 | ||
|
|
14274c8d04 | ||
|
|
b3cbd9be71 | ||
|
|
b1d810188c | ||
|
|
4b48f85162 | ||
|
|
738b02e1b9 | ||
|
|
dc487f9226 | ||
|
|
bb2f43c317 | ||
|
|
be61aef123 | ||
|
|
6ad7888e85 | ||
|
|
242adb3c9e | ||
|
|
8654c69d0c | ||
|
|
a7999ff160 | ||
|
|
9c04b8aab0 | ||
|
|
3643fefc9c | ||
|
|
47189901e5 | ||
|
|
2577684897 | ||
|
|
77396df8fd | ||
|
|
c517a1d469 | ||
|
|
b7d7e6567b | ||
|
|
67807e913e | ||
|
|
19a950dab5 | ||
|
|
79b91f8386 | ||
|
|
0359a4b7e9 | ||
|
|
d89f410749 | ||
|
|
850f6dd060 | ||
|
|
d891c6c8dc | ||
|
|
0a4a88ed5a | ||
|
|
3c02219da0 | ||
|
|
65efc3372e | ||
|
|
3acea66788 | ||
|
|
b448514e40 | ||
|
|
024147344b | ||
|
|
52a34d3871 | ||
|
|
1ada26e4dd | ||
|
|
94d1b61f81 | ||
|
|
29299edb90 | ||
|
|
a2e2c5e178 | ||
|
|
8ae39df2e8 | ||
|
|
508b269a82 | ||
|
|
a8627b6105 | ||
|
|
8fee6b2c68 | ||
|
|
dd58571ffd | ||
|
|
8c25683cc5 | ||
|
|
a96f003b8c | ||
|
|
ff01443246 | ||
|
|
e915a253f8 | ||
|
|
b463389733 | ||
|
|
41c97b92c7 | ||
|
|
1142f81e9c | ||
|
|
5bc9f77b7b | ||
|
|
c5d0582807 | ||
|
|
525e65d152 | ||
|
|
d948c7af47 | ||
|
|
11a29b4ed6 | ||
|
|
e31c4a3041 | ||
|
|
2928d5fc93 | ||
|
|
12fc6f7f10 | ||
|
|
4bd8c207b4 | ||
|
|
be030a3640 | ||
|
|
ebaa250f7b | ||
|
|
826a2d7ee6 | ||
|
|
e476cf8176 | ||
|
|
03115694f9 | ||
|
|
26ffb04834 | ||
|
|
2979fcc33d | ||
|
|
9a29a11e22 | ||
|
|
d73a27be71 | ||
|
|
d77f424504 | ||
|
|
3142ad6041 | ||
|
|
6044f014c7 | ||
|
|
d1cfdfa14f | ||
|
|
8f9bfc3f28 | ||
|
|
9ae847d392 | ||
|
|
178226b730 | ||
|
|
801e45abce | ||
|
|
cd54a7040a | ||
|
|
3bd880b061 | ||
|
|
bf355cce28 | ||
|
|
58d08c5787 | ||
|
|
a778af73d8 | ||
|
|
7ca95c3549 | ||
|
|
54933ac3ac | ||
|
|
255048bf5b | ||
|
|
206fa19f3e | ||
|
|
f0e9047f8c | ||
|
|
698966d551 | ||
|
|
fc6b5cb458 | ||
|
|
9eee3bfa58 | ||
|
|
0adc0845fd | ||
|
|
92f98eff5f | ||
|
|
d97f8acf23 | ||
|
|
47e14bf2ec | ||
|
|
8eed4083bc | ||
|
|
9ef7641cd1 | ||
|
|
bafb6065c8 | ||
|
|
8b2460b8ab | ||
|
|
827172e743 | ||
|
|
fa9bd30de5 | ||
|
|
78e66ff74b | ||
|
|
7e8d1c3567 | ||
|
|
c3a7603674 | ||
|
|
4b8cfbba00 | ||
|
|
30771e5366 | ||
|
|
313c7f4ba1 | ||
|
|
ece4215a8a | ||
|
|
7ea740edf1 | ||
|
|
716f4e6934 | ||
|
|
90ab302667 | ||
|
|
4695949362 | ||
|
|
4827893a0d | ||
|
|
9276f220b0 | ||
|
|
4071a5d165 | ||
|
|
da0ff24af6 | ||
|
|
afef635146 | ||
|
|
eda9d1c780 | ||
|
|
4b5749bc60 | ||
|
|
6bb23008c2 | ||
|
|
7746971b60 | ||
|
|
bc20c82fef | ||
|
|
fff70ed241 | ||
|
|
c590d45ce0 | ||
|
|
8bab9ad22b | ||
|
|
3c457dad2a | ||
|
|
eaae598234 | ||
|
|
606faf1bf8 | ||
|
|
ae9aa94323 | ||
|
|
2e41e44294 | ||
|
|
d806d9d6ff | ||
|
|
1260736c14 | ||
|
|
08c5cbbbf3 | ||
|
|
af0726cd79 | ||
|
|
ce2279030d | ||
|
|
83aba2ebee | ||
|
|
5c11742b51 | ||
|
|
5295e04275 | ||
|
|
47f723e63b | ||
|
|
54956e47d2 | ||
|
|
b2cbdf6642 | ||
|
|
989d1c6db9 | ||
|
|
e139b0cc5d | ||
|
|
66261e98b5 | ||
|
|
d9a268d30a | ||
|
|
a8bc50a947 | ||
|
|
6aa96daae2 | ||
|
|
293805a55e | ||
|
|
8b6319888c | ||
|
|
408676e97a | ||
|
|
1fabbae4f6 | ||
|
|
09a5b41d96 | ||
|
|
9d85a4dcaf | ||
|
|
9bc60c1c47 | ||
|
|
92aff864ef | ||
|
|
254e2e8ccd | ||
|
|
2480d127ac | ||
|
|
cc3d82e864 | ||
|
|
ee712c55a0 | ||
|
|
79f70266e4 | ||
|
|
3ffb8d510d | ||
|
|
e55fc1a421 | ||
|
|
ee9fb4a9b8 | ||
|
|
ef3536beed | ||
|
|
fbababaf40 | ||
|
|
4548cf78d6 | ||
|
|
86a219e3e1 | ||
|
|
9e0876dee2 | ||
|
|
e9096372d3 | ||
|
|
cef367c693 | ||
|
|
2634524439 | ||
|
|
10d27bf78c | ||
|
|
5b7739b26b | ||
|
|
11f895a0ca | ||
|
|
63099b72be | ||
|
|
0d8f7a4fa2 | ||
|
|
83f460660b | ||
|
|
786d25678b | ||
|
|
f57d8325b3 | ||
|
|
22adab4f93 | ||
|
|
805e3910c4 | ||
|
|
ecd827e3b4 | ||
|
|
19150e9f9c | ||
|
|
de5a725acc | ||
|
|
aae2305274 | ||
|
|
00ba1ecee9 | ||
|
|
e59465eaf9 | ||
|
|
6f0b4604fc | ||
|
|
9f97f81bae | ||
|
|
ffcd04a626 | ||
|
|
ecf102aff3 | ||
|
|
c16b0b520d | ||
|
|
2f25ee1c05 | ||
|
|
b5011fa069 | ||
|
|
55e2109764 | ||
|
|
5cf4c8a95a | ||
|
|
6b319caa28 | ||
|
|
b97a23930a | ||
|
|
6c918a6c95 | ||
|
|
20ba119f93 | ||
|
|
95ca74f9f9 | ||
|
|
f28cbb4ac5 | ||
|
|
e3f851ed1f | ||
|
|
d3cf414c51 | ||
|
|
ea98bb814f | ||
|
|
515e8256cc | ||
|
|
903c58b239 | ||
|
|
1c59c86ba2 | ||
|
|
b2c6dd2db2 | ||
|
|
beffe53d4d | ||
|
|
4eb5edaef2 | ||
|
|
ba07d343ae | ||
|
|
c887a9dc4c | ||
|
|
689cdca004 |
@@ -8,17 +8,17 @@
|
|||||||
<li>提供HTTP服务,同时内置JSON功能与限时缓存功能</li>
|
<li>提供HTTP服务,同时内置JSON功能与限时缓存功能</li>
|
||||||
<li>TCP层完全使用NIO.2,并统一TCP与UDP的接口换</li>
|
<li>TCP层完全使用NIO.2,并统一TCP与UDP的接口换</li>
|
||||||
<li>提供分布式与集中式部署的无缝切换</li>
|
<li>提供分布式与集中式部署的无缝切换</li>
|
||||||
<li>提供类似JPA功能,并包含数据缓存自动同步与简洁的数据层操作接口</li>
|
<li>提供类似JPA功能,包含数据缓存自动同步、分表分库与简洁的数据层操作接口</li>
|
||||||
<li>可以动态修改已依赖注入的资源</li>
|
<li>可以动态修改已依赖注入的资源</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<strong>Redkale 设计理念</strong>
|
<strong>Redkale 设计理念</strong>
|
||||||
<p>
|
<p>
|
||||||
作为一个全新的微服务框架,不仅是使用了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/>
|
作为一个全新的微服务框架,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/>
|
||||||
与主流框架比,功能上Redkale显得很简单,这也是Redkale的一个特点并非不足,从一个良好的设计习惯或架构上来看,有些常用功能是不需要提供的,比如Redkale的HTTP服务不支持HTTPS和JSP,HTTPS比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很重要的一个思想。
|
与主流框架比,功能上Redkale显得很简单,这体现了Redkale的简易性,而并非是不足,从一个良好的设计习惯或架构上来看,有些常用功能是不需要提供的,如Redkale的HTTP服务不支持HTTPS和JSP,HTTPS比HTTP多了一层加密解密,这种密集型的计算不是Java的专长,通常提供HTTP服务的架构不会将Java动态服务器放在最前端,而是在前方会放nginx或apache,除了负载均衡还能静动分离,因此HTTPS的加解密应交给nginx这样的高性能服务器处理。Redkale再提供HTTPS服务就显得鸡肋。JSP其实算是一个落后的技术,现在是一个多样化终端的时代,终端不只局限于桌面程序和PC浏览器,还有原生App、混合式App、微信端、移动H5、提供第三方接口等各种形式的终端,这些都不是JSP能方便兼顾的,而HTTP+JSON作为通用性接口可以避免重复开发,模版引擎的功能加上各种强大的JS框架足以取代JSP。Redkale在功能上做了筛选,不会为了迎合主流而提供,而是以良好的设计思想为指导。这是Redkale的主导思维。
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
由于RedKale使用了JDK 8 内置的ASM包,所以需要在源码工程中的编译器选项中加入: <b>-XDignore.symbol.file=true</b>
|
由于RedKale使用了JDK 8 内置的ASM包,所以需要在源码工程中的编译器选项中加入: <b>-XDignore.symbol.file=true</b>
|
||||||
|
|
||||||
<h5>详情请访问: <a href='http://redkale.org' target='_blank'>http://redkale.org</a></h5>
|
<h5>详情请访问: <a href='https://redkale.org' target='_blank'>https://redkale.org</a></h5>
|
||||||
|
|||||||
32
assembly.xml
Normal file
32
assembly.xml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
|
||||||
|
<id>redkale</id>
|
||||||
|
<formats>
|
||||||
|
<format>tar.gz</format>
|
||||||
|
</formats>
|
||||||
|
<includeBaseDirectory>false</includeBaseDirectory>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${project.basedir}/bin</directory>
|
||||||
|
<outputDirectory>bin</outputDirectory>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${project.basedir}/conf</directory>
|
||||||
|
<outputDirectory>conf</outputDirectory>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${project.basedir}/logs</directory>
|
||||||
|
<outputDirectory>logs</outputDirectory>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
<dependencySets>
|
||||||
|
<dependencySet>
|
||||||
|
<useProjectArtifact>true</useProjectArtifact>
|
||||||
|
<useTransitiveDependencies>false</useTransitiveDependencies>
|
||||||
|
<outputDirectory>lib</outputDirectory>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependencySet>
|
||||||
|
</dependencySets>
|
||||||
|
</assembly>
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<application port="5050">
|
<application port="5050">
|
||||||
|
|
||||||
|
<!-- 详细配置说明见: http://redkale.org/redkale.html#redkale_confxml -->
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<!--
|
<!--
|
||||||
<properties>
|
<properties>
|
||||||
@@ -8,7 +11,8 @@
|
|||||||
</properties>
|
</properties>
|
||||||
-->
|
-->
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
|
||||||
<server protocol="HTTP" host="0.0.0.0" port="6060" root="root">
|
<server protocol="HTTP" host="0.0.0.0" port="6060" root="root">
|
||||||
<!--
|
<!--
|
||||||
<request>
|
<request>
|
||||||
|
|||||||
306
pom.xml
306
pom.xml
@@ -1,158 +1,150 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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">
|
<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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.redkale</groupId>
|
<groupId>org.redkale</groupId>
|
||||||
<artifactId>redkale</artifactId>
|
<artifactId>redkale</artifactId>
|
||||||
<name>Redkale</name>
|
<packaging>jar</packaging>
|
||||||
<packaging>jar</packaging>
|
<url>http://redkale.org</url>
|
||||||
<url>http://redkale.org</url>
|
<description>redkale -- java framework</description>
|
||||||
<!-- -SNAPSHOT
|
<version>1.6.2</version>
|
||||||
mvn clean deploy -P release -Dgpg.passphrase=password
|
<licenses>
|
||||||
mvn release:clean release:prepare release:perform
|
<license>
|
||||||
-->
|
<name>Apache 2</name>
|
||||||
<version>1.0.0-rc1</version>
|
<url>http://www.apache.org/licenses/</url>
|
||||||
|
<distribution>repo</distribution>
|
||||||
<description>Redkale is a Microservices Framework written in Java</description>
|
<comments>Apache License</comments>
|
||||||
<properties>
|
</license>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
</licenses>
|
||||||
<maven.compiler.source>1.8</maven.compiler.source>
|
|
||||||
<maven.compiler.target>1.8</maven.compiler.target>
|
<developers>
|
||||||
</properties>
|
<developer>
|
||||||
|
<id>Redkale</id>
|
||||||
<build>
|
<name>redkale</name>
|
||||||
<plugins>
|
<email>redkale@qq.com</email>
|
||||||
<plugin>
|
<url>http://redkale.org</url>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<roles>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<role>Project Manager</role>
|
||||||
<version>3.5.1</version>
|
<role>Architect</role>
|
||||||
<configuration>
|
</roles>
|
||||||
<encoding>UTF-8</encoding>
|
<organization>redkale</organization>
|
||||||
<compilerArguments>
|
<organizationUrl>http://redkale.org</organizationUrl>
|
||||||
<verbose />
|
<properties>
|
||||||
<bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
|
<dept>No</dept>
|
||||||
</compilerArguments>
|
</properties>
|
||||||
</configuration>
|
<timezone>8</timezone>
|
||||||
</plugin>
|
</developer>
|
||||||
|
</developers>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<properties>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<version>2.6</version>
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
<configuration>
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
<archive>
|
</properties>
|
||||||
<manifest>
|
<name>Redkale</name>
|
||||||
<mainClass>org.redkale.boot.Application</mainClass>
|
<distributionManagement>
|
||||||
</manifest>
|
<snapshotRepository>
|
||||||
</archive>
|
<id>ossrh</id>
|
||||||
</configuration>
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
</plugin>
|
</snapshotRepository>
|
||||||
|
<repository>
|
||||||
<plugin>
|
<id>ossrh</id>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||||
<artifactId>maven-source-plugin</artifactId>
|
</repository>
|
||||||
<version>3.0.0</version>
|
</distributionManagement>
|
||||||
<executions>
|
<scm>
|
||||||
<execution>
|
<url>https://github.com/redkale/redkale</url>
|
||||||
<goals>
|
<connection>scm:git:git@github.com/redkale/redkale.git</connection>
|
||||||
<goal>jar</goal>
|
<developerConnection>scm:git:git@github.com:redkale/redkale.git</developerConnection>
|
||||||
</goals>
|
</scm>
|
||||||
</execution>
|
<build>
|
||||||
</executions>
|
<plugins>
|
||||||
</plugin>
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<plugin>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<version>3.5.1</version>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<configuration>
|
||||||
<version>2.10.3</version>
|
<encoding>UTF-8</encoding>
|
||||||
<configuration>
|
<compilerArguments>
|
||||||
<charset>${file_encoding}</charset>
|
<verbose />
|
||||||
<encoding>${file_encoding}</encoding>
|
<bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
|
||||||
</configuration>
|
</compilerArguments>
|
||||||
<executions>
|
</configuration>
|
||||||
<execution>
|
</plugin>
|
||||||
<id>attach-javadocs</id>
|
|
||||||
<goals>
|
<plugin>
|
||||||
<goal>jar</goal>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
</goals>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
</execution>
|
<version>2.6</version>
|
||||||
</executions>
|
<configuration>
|
||||||
</plugin>
|
<archive>
|
||||||
</plugins>
|
<manifest>
|
||||||
</build>
|
<mainClass>org.redkale.boot.Application</mainClass>
|
||||||
|
</manifest>
|
||||||
<dependencies>
|
</archive>
|
||||||
<dependency>
|
</configuration>
|
||||||
<groupId>org.codehaus.plexus</groupId>
|
</plugin>
|
||||||
<artifactId>plexus-compiler-javac</artifactId>
|
|
||||||
<version>2.7</version>
|
<plugin>
|
||||||
</dependency>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<dependency>
|
<artifactId>maven-gpg-plugin</artifactId>
|
||||||
<groupId>org.codehaus.plexus</groupId>
|
<version>1.6</version>
|
||||||
<artifactId>plexus-utils</artifactId>
|
<executions>
|
||||||
<version>3.0.22</version>
|
<execution>
|
||||||
</dependency>
|
<id>sign-artifacts</id>
|
||||||
</dependencies>
|
<phase>verify</phase>
|
||||||
|
<goals>
|
||||||
<profiles>
|
<goal>sign</goal>
|
||||||
<profile>
|
</goals>
|
||||||
<id>release-sign-artifacts</id>
|
</execution>
|
||||||
<activation>
|
</executions>
|
||||||
<property>
|
</plugin>
|
||||||
<name>performRelease</name>
|
<plugin>
|
||||||
<value>true</value>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
</property>
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
</activation>
|
<version>3.0.0</version>
|
||||||
<build>
|
<executions>
|
||||||
<plugins>
|
<execution>
|
||||||
<plugin>
|
<goals>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<goal>jar</goal>
|
||||||
<artifactId>maven-gpg-plugin</artifactId>
|
</goals>
|
||||||
<version>1.6</version>
|
</execution>
|
||||||
<executions>
|
</executions>
|
||||||
<execution>
|
</plugin>
|
||||||
<id>sign-artifacts</id>
|
<plugin>
|
||||||
<phase>verify</phase>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<goals>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<goal>sign</goal>
|
<version>2.10.3</version>
|
||||||
</goals>
|
<executions>
|
||||||
</execution>
|
<execution>
|
||||||
</executions>
|
<goals>
|
||||||
</plugin>
|
<goal>jar</goal>
|
||||||
</plugins>
|
</goals>
|
||||||
</build>
|
</execution>
|
||||||
</profile>
|
</executions>
|
||||||
</profiles>
|
</plugin>
|
||||||
|
|
||||||
<scm>
|
<plugin>
|
||||||
<url>https://github.com/redkale/redkale/tags/redkale-1.0.0-rc1</url>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<connection>scm:svn:https://github.com/redkale/redkale/tags/redkale-1.0.0-rc1</connection>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
</scm>
|
<version>3.0.0</version>
|
||||||
|
<configuration>
|
||||||
<developers>
|
<appendAssemblyId>false</appendAssemblyId>
|
||||||
<developer>
|
<descriptors>
|
||||||
<id>redkale</id>
|
<descriptor>assembly.xml</descriptor>
|
||||||
<name>redkale</name>
|
</descriptors>
|
||||||
<email>redkale@qq.com</email>
|
</configuration>
|
||||||
</developer>
|
<executions>
|
||||||
</developers>
|
<execution>
|
||||||
|
<id>redkale</id>
|
||||||
<licenses>
|
<phase>package</phase>
|
||||||
<license>
|
<goals>
|
||||||
<name>Apache 2</name>
|
<goal>single</goal>
|
||||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
</goals>
|
||||||
<distribution>repo</distribution>
|
</execution>
|
||||||
<comments>A business-friendly OSS license</comments>
|
</executions>
|
||||||
</license>
|
</plugin>
|
||||||
</licenses>
|
|
||||||
|
</plugins>
|
||||||
<distributionManagement>
|
</build>
|
||||||
<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>
|
|
||||||
</project>
|
</project>
|
||||||
@@ -23,12 +23,12 @@
|
|||||||
port: required 程序的管理Server的端口,用于关闭或者与监管系统进行数据交互
|
port: required 程序的管理Server的端口,用于关闭或者与监管系统进行数据交互
|
||||||
lib: 加上额外的lib路径,多个路径用分号;隔开; 默认为空。 例如: ${APP_HOME}/lib/a.jar;${APP_HOME}/lib2/b.jar;
|
lib: 加上额外的lib路径,多个路径用分号;隔开; 默认为空。 例如: ${APP_HOME}/lib/a.jar;${APP_HOME}/lib2/b.jar;
|
||||||
-->
|
-->
|
||||||
<application port="6560" lib="">
|
<application port="6560" lib="">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
【节点全局唯一】
|
【节点全局唯一】
|
||||||
所有服务所需的资源
|
所有服务所需的资源
|
||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
<!--
|
<!--
|
||||||
【节点全局唯一】
|
【节点全局唯一】
|
||||||
@@ -42,8 +42,8 @@
|
|||||||
一个组包含多个NODE, 同一Service服务可以由多个进程提供,这些进程称为一个GROUP,且同一GROUP内的进程必须在同一机房或局域网内
|
一个组包含多个NODE, 同一Service服务可以由多个进程提供,这些进程称为一个GROUP,且同一GROUP内的进程必须在同一机房或局域网内
|
||||||
一个group节点对应一个 Transport 对象。
|
一个group节点对应一个 Transport 对象。
|
||||||
name: 服务组ID,长度不能超过11个字节. 默认为空字符串。 注意: name不能包含$符号。
|
name: 服务组ID,长度不能超过11个字节. 默认为空字符串。 注意: name不能包含$符号。
|
||||||
protocol:值只能是UDP TCP, 默认TCP
|
protocol:值范围:UDP TCP, 默认TCP
|
||||||
kind: 与SNCP服务连接时的数据传输类型;可选值有:rest(不区分大小写);值为空或空字符串表示按SNCP协议传输; 为rest表示按REST传输。默认值为空
|
subprotocol: 子协议,预留字段。默认值为空
|
||||||
注意: 一个node只能所属一个group。只要存在protocol=SNCP的Server节点信息, 就必须有group节点信息。
|
注意: 一个node只能所属一个group。只要存在protocol=SNCP的Server节点信息, 就必须有group节点信息。
|
||||||
-->
|
-->
|
||||||
<group name="" protocol="TCP">
|
<group name="" protocol="TCP">
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
</group>
|
</group>
|
||||||
<!--
|
<!--
|
||||||
【节点全局唯一】
|
【节点全局唯一】
|
||||||
全局的参数配置, 可以通过@Resource(name="property.xxxxxx") 进行注入, 被注解的字段类型只能是String、primitive class
|
全局的参数配置, 可以通过@Resource(name="property.xxxxxx") 进行注入<property>的信息, 被注解的字段类型只能是String、primitive class
|
||||||
如果name是system.property.开头的值将会在进程启动时进行System.setProperty("yyyy", "YYYYYY")操作。
|
如果name是system.property.开头的值将会在进程启动时进行System.setProperty("yyyy", "YYYYYY")操作。
|
||||||
如果name是mimetype.property.开头的值将会在进程启动时进行MimeType.add("yyyy", "YYYYYY")操作。
|
如果name是mimetype.property.开头的值将会在进程启动时进行MimeType.add("yyyy", "YYYYYY")操作。
|
||||||
load: 加载文件,多个用;隔开。
|
load: 加载文件,多个用;隔开。
|
||||||
@@ -70,6 +70,8 @@
|
|||||||
System.setProperty("convert.bson.pool.size", "128");
|
System.setProperty("convert.bson.pool.size", "128");
|
||||||
System.setProperty("convert.json.writer.buffer.defsize", "4096");
|
System.setProperty("convert.json.writer.buffer.defsize", "4096");
|
||||||
System.setProperty("convert.bson.writer.buffer.defsize", "4096");
|
System.setProperty("convert.bson.writer.buffer.defsize", "4096");
|
||||||
|
|
||||||
|
<properties>节点下也可包含非<property>节点,其节点可以通过@Resource(name="properties.xxxxxx")进行注入, 被注解的字段类型只能是AnyValue、AnyValue[]
|
||||||
-->
|
-->
|
||||||
<properties load="config.properties">
|
<properties load="config.properties">
|
||||||
<property name="system.property.yyyy" value="YYYYYY"/>
|
<property name="system.property.yyyy" value="YYYYYY"/>
|
||||||
@@ -77,6 +79,7 @@
|
|||||||
<property name="xxxxxx" value="XXXXXXXX"/>
|
<property name="xxxxxx" value="XXXXXXXX"/>
|
||||||
<property name="xxxxxx" value="XXXXXXXX"/>
|
<property name="xxxxxx" value="XXXXXXXX"/>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
<!--
|
<!--
|
||||||
protocol: required server所启动的协议,Redkale内置的有HTTP、SNCP,SNCP使用TCP实现;
|
protocol: required server所启动的协议,Redkale内置的有HTTP、SNCP,SNCP使用TCP实现;
|
||||||
@@ -137,7 +140,7 @@
|
|||||||
includes:当autoload="true", 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
|
includes:当autoload="true", 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
|
||||||
excludes:当autoload="true", 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
|
excludes:当autoload="true", 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
|
||||||
-->
|
-->
|
||||||
<rest base="org.redkale.net.http.DefaultRestServlet" mustsign="false" autoload="true" includes="" excludes="">
|
<rest base="org.redkale.net.http.DefaultRestServlet" mustsign="true" autoload="true" includes="" excludes="">
|
||||||
<!--
|
<!--
|
||||||
value: Service类名,列出的表示必须被加载的Service对象
|
value: Service类名,列出的表示必须被加载的Service对象
|
||||||
ignore: 是否忽略,设置为true则不会加载该Service对象,默认值为false
|
ignore: 是否忽略,设置为true则不会加载该Service对象,默认值为false
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ java.util.logging.FileHandler.limit = 10485760
|
|||||||
java.util.logging.FileHandler.count = 100
|
java.util.logging.FileHandler.count = 100
|
||||||
java.util.logging.FileHandler.encoding = UTF-8
|
java.util.logging.FileHandler.encoding = UTF-8
|
||||||
java.util.logging.FileHandler.pattern = ${APP_HOME}/logs-%m/log-%u.log
|
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.FileHandler.append = true
|
||||||
|
|
||||||
#java.util.logging.ConsoleHandler.level = FINE
|
#java.util.logging.ConsoleHandler.level = FINE
|
||||||
|
|||||||
@@ -6,15 +6,22 @@
|
|||||||
<!-- 为NONE表示不启动缓存,@Cacheable 失效; 非NONE值(通常用ALL)表示开启缓存。 -->
|
<!-- 为NONE表示不启动缓存,@Cacheable 失效; 非NONE值(通常用ALL)表示开启缓存。 -->
|
||||||
<shared-cache-mode>NONE</shared-cache-mode>
|
<shared-cache-mode>NONE</shared-cache-mode>
|
||||||
<properties>
|
<properties>
|
||||||
|
<!--
|
||||||
|
DataSource的实现类,没有设置默认为org.redkale.source.DataJdbcSource的实现,使用常规基于JDBC的数据库驱动一般无需设置
|
||||||
|
-->
|
||||||
|
<property name="javax.persistence.datasource" value="org.redkale.source.DataJdbcSource"/>
|
||||||
|
|
||||||
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/dbuser?characterEncoding=utf8"/>
|
<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的子类。
|
javax.persistence.jdbc.driver在JPA的值是JDBC驱动,Redkale有所不同,值应该是javax.sql.DataSource的子类。
|
||||||
为了兼容用户习惯,Redkale内置常见JDBC驱动到javax.sql.DataSource的映射关系:
|
为了兼容用户习惯,Redkale内置常见JDBC驱动到javax.sql.DataSource的映射关系:
|
||||||
com.mysql.jdbc.Driver —————— com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
|
|
||||||
org.mariadb.jdbc.Driver —————— org.mariadb.jdbc.MySQLDataSource
|
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
|
oracle.jdbc.driver.OracleDriver —————— oracle.jdbc.pool.OracleConnectionPoolDataSource
|
||||||
com.microsoft.sqlserver.jdbc.SQLServerDriver —————— com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource
|
com.microsoft.sqlserver.jdbc.SQLServerDriver —————— com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource
|
||||||
因此 com.mysql.jdbc.Driver 会被自动转换成 com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
|
因此 com.mysql.jdbc.Driver 会被自动转换成 com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
|
||||||
|
并且如果JDBC驱动是以上几个版本,javax.persistence.jdbc.driver属性都可以省略,Redkale会根据javax.persistence.jdbc.url的值来识别驱动
|
||||||
-->
|
-->
|
||||||
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
||||||
<property name="javax.persistence.jdbc.user" value="root"/>
|
<property name="javax.persistence.jdbc.user" value="root"/>
|
||||||
@@ -23,13 +30,13 @@
|
|||||||
<!-- 最大连接数,默认值:CPU数*16 -->
|
<!-- 最大连接数,默认值:CPU数*16 -->
|
||||||
<property name="javax.persistence.connections.limit" value="32"/>
|
<property name="javax.persistence.connections.limit" value="32"/>
|
||||||
|
|
||||||
<!-- 包含的SQL模板,相当于反向LIKE,不同的JDBC驱动的SQL语句不一样,Redkale内置了MySQL、Oracle、Sqlserver的语句 -->
|
<!-- 包含的SQL模板,相当于反向LIKE,不同的JDBC驱动的SQL语句不一样,Redkale内置了MySQL的语句 -->
|
||||||
<property name="javax.persistence.contain.sqltemplate" value="LOCATE(${keystr}, ${column}) > 0"/>
|
<property name="javax.persistence.contain.sqltemplate" value="LOCATE(${keystr}, ${column}) > 0"/>
|
||||||
<property name="javax.persistence.notcontain.sqltemplate" value="LOCATE(${keystr}, ${column}) = 0"/>
|
<property name="javax.persistence.notcontain.sqltemplate" value="LOCATE(${keystr}, ${column}) = 0"/>
|
||||||
|
|
||||||
<!-- 复制表结构的SQL模板,Redkale内置了MySQL的语句 -->
|
<!-- 复制表结构的SQL模板,Redkale内置了MySQL的语句 -->
|
||||||
<property name="javax.persistence.tablenotexist.sqlstates" value="42000;42S02"/>
|
<property name="javax.persistence.tablenotexist.sqlstates" value="42000;42S02"/>
|
||||||
<property name="javax.persistence.tablecopy.sqltemplate" value="CREATE TABLE ${newtable} LIKE ${oldtable}"/>
|
<property name="javax.persistence.tablecopy.sqltemplate" value="CREATE TABLE ${newtable} LIKE ${oldtable}"/>
|
||||||
|
|
||||||
</properties>
|
</properties>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/*******************************************************************************
|
/** *****************************************************************************
|
||||||
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
|
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program and the accompanying materials are made available under the
|
* 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.1
|
||||||
* Linda DeMichiel - Java Persistence 2.0
|
* Linda DeMichiel - Java Persistence 2.0
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
***************************************************************************** */
|
||||||
package javax.persistence;
|
package javax.persistence;
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.TYPE;
|
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
|
* The value of the <code>Cacheable</code> annotation is inherited by
|
||||||
* subclasses; it can be overridden by specifying
|
* subclasses; it can be overridden by specifying
|
||||||
* <code>Cacheable</code> on a subclass.
|
* <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.
|
* not be cached by the provider.
|
||||||
*
|
*
|
||||||
* @since Java Persistence 2.0
|
* @since Java Persistence 2.0
|
||||||
*/
|
*/
|
||||||
@Target( { TYPE })
|
@Target({TYPE})
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public @interface Cacheable {
|
public @interface Cacheable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (Optional) Whether or not the entity should be cached.
|
* (Optional) Whether or not the entity should be cached.
|
||||||
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
boolean value() default true;
|
boolean value() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Optional) 定时自动更新缓存的周期秒数,为0表示不做定时更新, 大于0表示每经过interval秒后会自动从数据库中拉取数据更新Cache
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int interval() default 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,13 @@ public @interface Column {
|
|||||||
*/
|
*/
|
||||||
String name() default "";
|
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
|
* (Optional) Whether the column is a unique key. This is a
|
||||||
* shortcut for the <code>UniqueConstraint</code> annotation at the table
|
* shortcut for the <code>UniqueConstraint</code> annotation at the table
|
||||||
@@ -96,17 +103,6 @@ public @interface Column {
|
|||||||
*/
|
*/
|
||||||
boolean updatable() default true;
|
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.
|
* (Optional) The name of the table that contains the column.
|
||||||
* If absent the column is assumed to be in the primary table.
|
* If absent the column is assumed to be in the primary table.
|
||||||
|
|||||||
@@ -40,4 +40,11 @@ public @interface Entity {
|
|||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
String name() default "";
|
String name() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Optional) The comment of the entity.
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
String comment() default "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/*******************************************************************************
|
/** *****************************************************************************
|
||||||
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
|
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program and the accompanying materials are made available under the
|
* 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.1
|
||||||
* Linda DeMichiel - Java Persistence 2.0
|
* Linda DeMichiel - Java Persistence 2.0
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
***************************************************************************** */
|
||||||
package javax.persistence;
|
package javax.persistence;
|
||||||
|
|
||||||
import java.lang.annotation.Target;
|
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
|
* 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
|
* may be applied to a primary key property or field of an entity or
|
||||||
* mapped superclass in conjunction with the {@link Id} annotation.
|
* mapped superclass in conjunction with the {@link Id} annotation.
|
||||||
* The use of the <code>GeneratedValue</code> annotation is only
|
* 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
|
* <code>GeneratedValue</code> annotation is not supported for derived
|
||||||
* primary keys.
|
* primary keys.
|
||||||
*
|
*
|
||||||
@@ -58,22 +59,5 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
|
|
||||||
public @interface GeneratedValue {
|
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 "";
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
69
src/javax/persistence/Index.java
Normal file
69
src/javax/persistence/Index.java
Normal 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;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/*******************************************************************************
|
/** *****************************************************************************
|
||||||
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
|
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program and the accompanying materials are made available under the
|
* 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.1
|
||||||
* Linda DeMichiel - Java Persistence 2.0
|
* Linda DeMichiel - Java Persistence 2.0
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
***************************************************************************** */
|
||||||
package javax.persistence;
|
package javax.persistence;
|
||||||
|
|
||||||
import java.lang.annotation.Target;
|
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
|
* 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.
|
* class, the default values apply.
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
@@ -37,27 +38,50 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|||||||
*
|
*
|
||||||
* @since Java Persistence 1.0
|
* @since Java Persistence 1.0
|
||||||
*/
|
*/
|
||||||
@Target(TYPE)
|
@Target(TYPE)
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public @interface Table {
|
public @interface Table {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (Optional) The name of the table.
|
* (Optional) The name of the table.
|
||||||
* <p> Defaults to the entity name.
|
* <p>
|
||||||
|
* Defaults to the entity name.
|
||||||
|
*
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
String name() default "";
|
String name() default "";
|
||||||
|
|
||||||
/** (Optional) The catalog of the table.
|
/** (Optional) The catalog of the table.
|
||||||
* <p> Defaults to the default catalog.
|
* <p>
|
||||||
|
* Defaults to the default catalog.
|
||||||
|
*
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
String catalog() default "";
|
String catalog() default "";
|
||||||
|
|
||||||
/** (Optional) The schema of the table.
|
/**
|
||||||
* <p> Defaults to the default schema for user.
|
* (Optional) Unique constraints that are to be placed on
|
||||||
* @return String
|
* 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 "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
56
src/javax/persistence/UniqueConstraint.java
Normal file
56
src/javax/persistence/UniqueConstraint.java
Normal 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:
|
||||||
|
* @Entity
|
||||||
|
* @Table(
|
||||||
|
* name="EMPLOYEE",
|
||||||
|
* uniqueConstraints=
|
||||||
|
* @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();
|
||||||
|
}
|
||||||
@@ -8,18 +8,24 @@ package org.redkale.boot;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import javax.persistence.*;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
import org.redkale.net.http.*;
|
import org.redkale.net.http.*;
|
||||||
|
import org.redkale.source.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 继承 HttpBaseServlet 是为了获取 WebAction 信息
|
* API接口文档生成类,作用:生成Application实例中所有HttpServer的可用HttpServlet的API接口方法 <br>
|
||||||
|
* 继承 HttpBaseServlet 是为了获取 WebMapping 信息
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class ApiDocs extends HttpBaseServlet {
|
public class ApiDocs extends HttpBaseServlet {
|
||||||
|
|
||||||
private final Application app;
|
private final Application app; //Application全局对象
|
||||||
|
|
||||||
public ApiDocs(Application app) {
|
public ApiDocs(Application app) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
@@ -28,7 +34,7 @@ public class ApiDocs extends HttpBaseServlet {
|
|||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
List<Map> serverList = new ArrayList<>();
|
List<Map> serverList = new ArrayList<>();
|
||||||
|
|
||||||
Map<String, Map<String, Map<String, String>>> typesmap = new LinkedHashMap<>();
|
Map<String, Map<String, Map<String, Object>>> typesmap = new LinkedHashMap<>();
|
||||||
for (NodeServer node : app.servers) {
|
for (NodeServer node : app.servers) {
|
||||||
if (!(node instanceof NodeHttpServer)) continue;
|
if (!(node instanceof NodeHttpServer)) continue;
|
||||||
final Map<String, Object> map = new LinkedHashMap<>();
|
final Map<String, Object> map = new LinkedHashMap<>();
|
||||||
@@ -46,77 +52,136 @@ public class ApiDocs extends HttpBaseServlet {
|
|||||||
}
|
}
|
||||||
final Map<String, Object> servletmap = new LinkedHashMap<>();
|
final Map<String, Object> servletmap = new LinkedHashMap<>();
|
||||||
String prefix = _prefix(servlet);
|
String prefix = _prefix(servlet);
|
||||||
String[] mappings = ws.value();
|
String[] urlregs = ws.value();
|
||||||
if (prefix != null && !prefix.isEmpty()) {
|
if (prefix != null && !prefix.isEmpty()) {
|
||||||
for (int i = 0; i < mappings.length; i++) {
|
for (int i = 0; i < urlregs.length; i++) {
|
||||||
mappings[i] = prefix + mappings[i];
|
urlregs[i] = prefix + urlregs[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
servletmap.put("mappings", mappings);
|
servletmap.put("urlregs", urlregs);
|
||||||
servletmap.put("moduleid", ws.moduleid());
|
servletmap.put("moduleid", ws.moduleid());
|
||||||
servletmap.put("name", ws.name());
|
servletmap.put("name", ws.name());
|
||||||
servletmap.put("comment", ws.comment());
|
servletmap.put("comment", ws.comment());
|
||||||
|
|
||||||
List<Map> actionsList = new ArrayList<>();
|
List<Map> mappingsList = new ArrayList<>();
|
||||||
servletmap.put("actions", actionsList);
|
servletmap.put("mappings", mappingsList);
|
||||||
for (Method method : servlet.getClass().getMethods()) {
|
final Class selfClz = servlet.getClass();
|
||||||
if (method.getParameterCount() != 2) continue;
|
Class clz = servlet.getClass();
|
||||||
WebAction action = method.getAnnotation(WebAction.class);
|
HashSet<String> actionurls = new HashSet<>();
|
||||||
if (action == null) continue;
|
do {
|
||||||
final Map<String, Object> actionmap = new LinkedHashMap<>();
|
if (Modifier.isAbstract(clz.getModifiers())) break;
|
||||||
actionmap.put("url", prefix + action.url());
|
for (Method method : clz.getMethods()) {
|
||||||
actionmap.put("auth", method.getAnnotation(AuthIgnore.class) == null);
|
if (method.getParameterCount() != 2) continue;
|
||||||
actionmap.put("actionid", action.actionid());
|
WebMapping action = method.getAnnotation(WebMapping.class);
|
||||||
actionmap.put("comment", action.comment());
|
if (action == null) continue;
|
||||||
List<Map> paramsList = new ArrayList<>();
|
if (!action.inherited() && selfClz != clz) continue; //忽略不被继承的方法
|
||||||
actionmap.put("params", paramsList);
|
final Map<String, Object> mappingmap = new LinkedHashMap<>();
|
||||||
for (WebParam param : method.getAnnotationsByType(WebParam.class)) {
|
if (actionurls.contains(action.url())) continue;
|
||||||
final Map<String, Object> parammap = new LinkedHashMap<>();
|
mappingmap.put("url", prefix + action.url());
|
||||||
final boolean isarray = param.type().isArray();
|
actionurls.add(action.url());
|
||||||
final Class ptype = isarray ? param.type().getComponentType() : param.type();
|
mappingmap.put("auth", method.getAnnotation(AuthIgnore.class) == null);
|
||||||
parammap.put("name", param.name());
|
mappingmap.put("actionid", action.actionid());
|
||||||
parammap.put("radix", param.radix());
|
mappingmap.put("comment", action.comment());
|
||||||
parammap.put("type", ptype.getName() + (isarray ? "[]" : ""));
|
List<Map> paramsList = new ArrayList<>();
|
||||||
parammap.put("src", param.src());
|
mappingmap.put("params", paramsList);
|
||||||
parammap.put("comment", param.comment());
|
List<String> results = new ArrayList<>();
|
||||||
paramsList.add(parammap);
|
for (final Class rtype : action.results()) {
|
||||||
if (ptype.isPrimitive() || ptype == String.class) continue;
|
results.add(rtype.getName());
|
||||||
if (typesmap.containsKey(ptype.getName())) continue;
|
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;
|
||||||
|
|
||||||
final Map<String, Map<String, String>> typemap = new LinkedHashMap<>();
|
Map<String, Object> fieldmap = new LinkedHashMap<>();
|
||||||
Class loop = ptype;
|
fieldmap.put("type", field.getType().isArray() ? (field.getType().getComponentType().getName() + "[]") : field.getGenericType().getTypeName());
|
||||||
do {
|
|
||||||
if (loop == null || loop.isInterface()) break;
|
|
||||||
for (Field field : loop.getDeclaredFields()) {
|
|
||||||
if (Modifier.isFinal(field.getModifiers())) continue;
|
|
||||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
|
||||||
|
|
||||||
Map<String, String> fieldmap = new LinkedHashMap<>();
|
Comment comment = field.getAnnotation(Comment.class);
|
||||||
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);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
Comment comment = field.getAnnotation(Comment.class);
|
typemap.put(field.getName(), fieldmap);
|
||||||
if (comment != null) fieldmap.put("comment", comment.value());
|
|
||||||
|
|
||||||
if (servlet.getClass().getAnnotation(Rest.RestDynamic.class) != null) {
|
|
||||||
if (field.getAnnotation(RestAddress.class) != null) continue;
|
|
||||||
}
|
}
|
||||||
|
} 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;
|
||||||
|
|
||||||
typemap.put(field.getName(), fieldmap);
|
final Map<String, Map<String, Object>> typemap = new LinkedHashMap<>();
|
||||||
}
|
Class loop = ptype;
|
||||||
} while ((loop = loop.getSuperclass()) != Object.class);
|
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;
|
||||||
|
|
||||||
typesmap.put(ptype.getName(), typemap);
|
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);
|
||||||
}
|
}
|
||||||
actionmap.put("result", action.result());
|
} while ((clz = clz.getSuperclass()) != HttpServlet.class);
|
||||||
actionsList.add(actionmap);
|
mappingsList.sort((o1, o2) -> ((String) o1.get("url")).compareTo((String) o2.get("url")));
|
||||||
}
|
|
||||||
actionsList.sort((o1, o2) -> ((String) o1.get("url")).compareTo((String) o2.get("url")));
|
|
||||||
servletsList.add(servletmap);
|
servletsList.add(servletmap);
|
||||||
}
|
}
|
||||||
servletsList.sort((o1, o2) -> {
|
servletsList.sort((o1, o2) -> {
|
||||||
String[] mappings1 = (String[]) o1.get("mappings");
|
String[] urlregs1 = (String[]) o1.get("urlregs");
|
||||||
String[] mappings2 = (String[]) o2.get("mappings");
|
String[] urlregs2 = (String[]) o2.get("urlregs");
|
||||||
return mappings1.length > 0 ? (mappings2.length > 0 ? mappings1[0].compareTo(mappings2[0]) : 1) : -1;
|
return urlregs1.length > 0 ? (urlregs2.length > 0 ? urlregs1[0].compareTo(urlregs2[0]) : 1) : -1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Map<String, Object> resultmap = new LinkedHashMap<>();
|
Map<String, Object> resultmap = new LinkedHashMap<>();
|
||||||
@@ -132,7 +197,7 @@ public class ApiDocs extends HttpBaseServlet {
|
|||||||
in = new FileInputStream(doctemplate);
|
in = new FileInputStream(doctemplate);
|
||||||
}
|
}
|
||||||
if (in == null) in = ApiDocs.class.getResourceAsStream("apidoc-template.html");
|
if (in == null) in = ApiDocs.class.getResourceAsStream("apidoc-template.html");
|
||||||
String content = Utility.read(in).replace("${content}", json);
|
String content = Utility.read(in).replace("'${content}'", json);
|
||||||
in.close();
|
in.close();
|
||||||
FileOutputStream outhtml = new FileOutputStream(new File(app.getHome(), "apidoc.html"));
|
FileOutputStream outhtml = new FileOutputStream(new File(app.getHome(), "apidoc.html"));
|
||||||
outhtml.write(content.getBytes("UTF-8"));
|
outhtml.write(content.getBytes("UTF-8"));
|
||||||
@@ -140,7 +205,7 @@ public class ApiDocs extends HttpBaseServlet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean authenticate(int module, int actionid, HttpRequest request, HttpResponse response) throws IOException {
|
public void authenticate(int moduleid, int actionid, HttpRequest request, HttpResponse response, HttpServlet next) throws IOException {
|
||||||
return true;
|
next.execute(request, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.redkale.boot;
|
package org.redkale.boot;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.*;
|
import java.nio.channels.*;
|
||||||
@@ -29,75 +30,117 @@ import org.redkale.watch.WatchFactory;
|
|||||||
import org.w3c.dom.*;
|
import org.w3c.dom.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
|
* 进程启动类,全局对象。 <br>
|
||||||
|
* <pre>
|
||||||
|
* 程序启动执行步骤:
|
||||||
|
* 1、读取application.xml
|
||||||
|
* 2、进行classpath扫描动态加载Service与Servlet
|
||||||
|
* 3、优先加载所有SNCP协议的服务,再加载其他协议服务
|
||||||
|
* 4、最后进行Service、Servlet与其他资源之间的依赖注入
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
* 编译时需要加入: -XDignore.symbol.file=true
|
* 编译时需要加入: -XDignore.symbol.file=true
|
||||||
* <p>
|
* <p>
|
||||||
* 进程启动类,程序启动后读取application.xml,进行classpath扫描动态加载Service与Servlet 优先加载所有SNCP协议的服务, 再加载其他协议服务, 最后进行Service、Servlet与其他资源之间的依赖注入。
|
* 详情见: https://redkale.org
|
||||||
* <p>
|
|
||||||
* 详情见: http://redkale.org
|
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public final class Application {
|
public final class Application {
|
||||||
|
|
||||||
//当前进程启动的时间, 类型: long
|
/**
|
||||||
|
* 当前进程启动的时间, 类型: long
|
||||||
|
*/
|
||||||
public static final String RESNAME_APP_TIME = "APP_TIME";
|
public static final String RESNAME_APP_TIME = "APP_TIME";
|
||||||
|
|
||||||
//当前进程的根目录, 类型:String、File、Path
|
/**
|
||||||
|
* 当前进程的根目录, 类型:String、File、Path
|
||||||
|
*/
|
||||||
public static final String RESNAME_APP_HOME = "APP_HOME";
|
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";
|
public static final String RESNAME_APP_GRES = "APP_GRES";
|
||||||
|
|
||||||
//当前进程节点的name, 类型:String
|
/**
|
||||||
|
* 当前进程节点的name, 类型:String
|
||||||
|
*/
|
||||||
public static final String RESNAME_APP_NODE = "APP_NODE";
|
public static final String RESNAME_APP_NODE = "APP_NODE";
|
||||||
|
|
||||||
//当前进程节点的IP地址, 类型:InetAddress、String
|
/**
|
||||||
|
* 当前进程节点的IP地址, 类型:InetAddress、String
|
||||||
|
*/
|
||||||
public static final String RESNAME_APP_ADDR = "APP_ADDR";
|
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";
|
public static final String RESNAME_SERVER_ADDR = "SERVER_ADDR";
|
||||||
|
|
||||||
//当前SNCP Server所属的组 类型: String
|
/**
|
||||||
|
* 当前SNCP Server所属的组 类型: String
|
||||||
|
*/
|
||||||
public static final String RESNAME_SERVER_GROUP = "SERVER_GROUP";
|
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;
|
public static final String RESNAME_SERVER_ROOT = Server.RESNAME_SERVER_ROOT;
|
||||||
|
|
||||||
|
//每个地址对应的Group名
|
||||||
final Map<InetSocketAddress, String> globalNodes = new HashMap<>();
|
final Map<InetSocketAddress, String> globalNodes = new HashMap<>();
|
||||||
|
|
||||||
|
//协议地址的Group集合
|
||||||
final Map<String, GroupInfo> globalGroups = new HashMap<>();
|
final Map<String, GroupInfo> globalGroups = new HashMap<>();
|
||||||
|
|
||||||
|
//本地IP地址
|
||||||
final InetAddress localAddress;
|
final InetAddress localAddress;
|
||||||
|
|
||||||
|
//CacheSource 资源
|
||||||
final List<CacheSource> cacheSources = new CopyOnWriteArrayList<>();
|
final List<CacheSource> cacheSources = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
//DataSource 资源
|
||||||
final List<DataSource> dataSources = new CopyOnWriteArrayList<>();
|
final List<DataSource> dataSources = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
//NodeServer 资源
|
||||||
final List<NodeServer> servers = new CopyOnWriteArrayList<>();
|
final List<NodeServer> servers = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
//传输端的ByteBuffer对象池
|
||||||
final ObjectPool<ByteBuffer> transportBufferPool;
|
final ObjectPool<ByteBuffer> transportBufferPool;
|
||||||
|
|
||||||
|
//传输端的线程池
|
||||||
final ExecutorService transportExecutor;
|
final ExecutorService transportExecutor;
|
||||||
|
|
||||||
|
//传输端的ChannelGroup
|
||||||
final AsynchronousChannelGroup transportChannelGroup;
|
final AsynchronousChannelGroup transportChannelGroup;
|
||||||
|
|
||||||
|
//全局根ResourceFactory
|
||||||
final ResourceFactory resourceFactory = ResourceFactory.root();
|
final ResourceFactory resourceFactory = ResourceFactory.root();
|
||||||
|
|
||||||
|
//服务配置项
|
||||||
|
final AnyValue config;
|
||||||
|
|
||||||
|
//临时计数器
|
||||||
CountDownLatch servicecdl; //会出现两次赋值
|
CountDownLatch servicecdl; //会出现两次赋值
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------
|
||||||
|
//是否用于main方法运行
|
||||||
private final boolean singletonrun;
|
private final boolean singletonrun;
|
||||||
|
|
||||||
|
//根WatchFactory
|
||||||
private final WatchFactory watchFactory = WatchFactory.root();
|
private final WatchFactory watchFactory = WatchFactory.root();
|
||||||
|
|
||||||
|
//进程根目录
|
||||||
private final File home;
|
private final File home;
|
||||||
|
|
||||||
|
//日志
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
|
|
||||||
private final AnyValue config;
|
//服务启动时间
|
||||||
|
|
||||||
private final long startTime = System.currentTimeMillis();
|
private final long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
//Server启动的计数器,用于确保所有Server都启动完后再进行下一步处理
|
||||||
private final CountDownLatch serversLatch;
|
private final CountDownLatch serversLatch;
|
||||||
|
|
||||||
private Application(final AnyValue config) {
|
private Application(final AnyValue config) {
|
||||||
@@ -163,7 +206,8 @@ public final class Application {
|
|||||||
Properties prop = new Properties();
|
Properties prop = new Properties();
|
||||||
final String handlers = properties.getProperty("handlers");
|
final String handlers = properties.getProperty("handlers");
|
||||||
if (handlers != null && handlers.contains("java.util.logging.FileHandler")) {
|
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()) {
|
if (!prop.isEmpty()) {
|
||||||
String prefix = fileHandlerClass + ".";
|
String prefix = fileHandlerClass + ".";
|
||||||
@@ -188,6 +232,7 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
this.logger = Logger.getLogger(this.getClass().getSimpleName());
|
this.logger = Logger.getLogger(this.getClass().getSimpleName());
|
||||||
this.serversLatch = new CountDownLatch(config.getAnyValues("server").length + 1);
|
this.serversLatch = new CountDownLatch(config.getAnyValues("server").length + 1);
|
||||||
|
logger.log(Level.INFO, "------------------------------- Redkale -------------------------------");
|
||||||
//------------------配置 <transport> 节点 ------------------
|
//------------------配置 <transport> 节点 ------------------
|
||||||
ObjectPool<ByteBuffer> transportPool = null;
|
ObjectPool<ByteBuffer> transportPool = null;
|
||||||
ExecutorService transportExec = null;
|
ExecutorService transportExec = null;
|
||||||
@@ -262,7 +307,7 @@ public final class Application {
|
|||||||
|
|
||||||
File persist = new File(this.home, "conf/persistence.xml");
|
File persist = new File(this.home, "conf/persistence.xml");
|
||||||
final String homepath = this.home.getCanonicalPath();
|
final String homepath = this.home.getCanonicalPath();
|
||||||
if (persist.isFile()) System.setProperty(DataDefaultSource.DATASOURCE_CONFPATH, persist.getCanonicalPath());
|
if (persist.isFile()) System.setProperty(DataSources.DATASOURCE_CONFPATH, persist.getCanonicalPath());
|
||||||
logger.log(Level.INFO, RESNAME_APP_HOME + "= " + homepath + "\r\n" + RESNAME_APP_ADDR + "= " + this.localAddress.getHostAddress());
|
logger.log(Level.INFO, RESNAME_APP_HOME + "= " + homepath + "\r\n" + RESNAME_APP_ADDR + "= " + this.localAddress.getHostAddress());
|
||||||
String lib = config.getValue("lib", "").trim().replace("${APP_HOME}", homepath);
|
String lib = config.getValue("lib", "").trim().replace("${APP_HOME}", homepath);
|
||||||
lib = lib.isEmpty() ? (homepath + "/conf") : (lib + ";" + homepath + "/conf");
|
lib = lib.isEmpty() ? (homepath + "/conf") : (lib + ";" + homepath + "/conf");
|
||||||
@@ -293,6 +338,7 @@ public final class Application {
|
|||||||
String name = prop.getValue("name");
|
String name = prop.getValue("name");
|
||||||
String value = prop.getValue("value");
|
String value = prop.getValue("value");
|
||||||
if (name == null || value == null) continue;
|
if (name == null || value == null) continue;
|
||||||
|
value = value.replace("${APP_HOME}", home.getCanonicalPath()).replace('\\', '/');
|
||||||
if (name.startsWith("system.property.")) {
|
if (name.startsWith("system.property.")) {
|
||||||
System.setProperty(name.substring("system.property.".length()), value);
|
System.setProperty(name.substring("system.property.".length()), value);
|
||||||
} else if (name.startsWith("mimetype.property.")) {
|
} else if (name.startsWith("mimetype.property.")) {
|
||||||
@@ -305,11 +351,6 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.localAddress != null && this.resourceFactory.find("property.datasource.nodeid", String.class) == null) {
|
|
||||||
byte[] bs = this.localAddress.getAddress();
|
|
||||||
int v = (0xff & bs[bs.length - 2]) % 10 * 100 + (0xff & bs[bs.length - 1]);
|
|
||||||
this.resourceFactory.register("property.datasource.nodeid", "" + v);
|
|
||||||
}
|
|
||||||
this.resourceFactory.register(BsonFactory.root());
|
this.resourceFactory.register(BsonFactory.root());
|
||||||
this.resourceFactory.register(JsonFactory.root());
|
this.resourceFactory.register(JsonFactory.root());
|
||||||
this.resourceFactory.register(BsonFactory.root().getConvert());
|
this.resourceFactory.register(BsonFactory.root().getConvert());
|
||||||
@@ -331,7 +372,7 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
GroupInfo ginfo = globalGroups.get(group);
|
GroupInfo ginfo = globalGroups.get(group);
|
||||||
if (ginfo == null) {
|
if (ginfo == null) {
|
||||||
ginfo = new GroupInfo(group, protocol, conf.getValue("kind", ""), new LinkedHashSet<>());
|
ginfo = new GroupInfo(group, protocol, conf.getValue("subprotocol", ""), new LinkedHashSet<>());
|
||||||
globalGroups.put(group, ginfo);
|
globalGroups.put(group, ginfo);
|
||||||
}
|
}
|
||||||
for (AnyValue node : conf.getAnyValues("node")) {
|
for (AnyValue node : conf.getAnyValues("node")) {
|
||||||
@@ -421,13 +462,27 @@ public final class Application {
|
|||||||
channel.write(buffer);
|
channel.write(buffer);
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
channel.configureBlocking(false);
|
channel.configureBlocking(false);
|
||||||
channel.read(buffer);
|
try {
|
||||||
buffer.flip();
|
channel.read(buffer);
|
||||||
byte[] bytes = new byte[buffer.remaining()];
|
buffer.flip();
|
||||||
buffer.get(bytes);
|
byte[] bytes = new byte[buffer.remaining()];
|
||||||
channel.close();
|
buffer.get(bytes);
|
||||||
logger.info(new String(bytes));
|
channel.close();
|
||||||
Thread.sleep(500);
|
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 {
|
public void start() throws Exception {
|
||||||
@@ -461,7 +516,7 @@ public final class Application {
|
|||||||
for (final AnyValue serconf : serconfs) {
|
for (final AnyValue serconf : serconfs) {
|
||||||
Thread thread = new Thread() {
|
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");
|
setName(serconf.getValue("protocol", "Server").toUpperCase() + "-" + host + ":" + serconf.getIntValue("port") + "-Thread");
|
||||||
this.setDaemon(true);
|
this.setDaemon(true);
|
||||||
}
|
}
|
||||||
@@ -526,6 +581,7 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Service> T singleton(String name, Class<T> serviceClass) throws Exception {
|
public static <T extends Service> T singleton(String name, Class<T> serviceClass) throws Exception {
|
||||||
|
if (serviceClass == null) throw new IllegalArgumentException("serviceClass is null");
|
||||||
final Application application = Application.create(true);
|
final Application application = Application.create(true);
|
||||||
application.init();
|
application.init();
|
||||||
application.start();
|
application.start();
|
||||||
@@ -533,7 +589,9 @@ public final class Application {
|
|||||||
T service = server.resourceFactory.find(name, serviceClass);
|
T service = server.resourceFactory.find(name, serviceClass);
|
||||||
if (service != null) return service;
|
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 {
|
public static Application create(final boolean singleton) throws IOException {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import org.redkale.util.AnyValue.DefaultAnyValue;
|
|||||||
/**
|
/**
|
||||||
* class过滤器, 符合条件的class会保留下来存入FilterEntry。
|
* class过滤器, 符合条件的class会保留下来存入FilterEntry。
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 泛型
|
* @param <T> 泛型
|
||||||
@@ -28,9 +28,9 @@ import org.redkale.util.AnyValue.DefaultAnyValue;
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class ClassFilter<T> {
|
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<>(); //符合条件的结果
|
||||||
|
|
||||||
|
|||||||
@@ -7,31 +7,33 @@ package org.redkale.boot;
|
|||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import org.redkale.convert.json.JsonConvert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 协议地址组合对象, 对应application.xml 中 resources->group 节点信息
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class GroupInfo {
|
public class GroupInfo {
|
||||||
|
|
||||||
protected String name;
|
protected String name; //地址
|
||||||
|
|
||||||
protected String protocol;
|
protected String protocol; //协议 取值范围: TCP、UDP
|
||||||
|
|
||||||
protected String kind;
|
protected String subprotocol; //子协议,预留使用
|
||||||
|
|
||||||
protected Set<InetSocketAddress> addrs;
|
protected Set<InetSocketAddress> addrs; //地址列表, 对应 resources->group->node节点信息
|
||||||
|
|
||||||
public GroupInfo() {
|
public GroupInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public GroupInfo(String name, String protocol, String kind, Set<InetSocketAddress> addrs) {
|
public GroupInfo(String name, String protocol, String subprotocol, Set<InetSocketAddress> addrs) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.protocol = protocol;
|
this.protocol = protocol;
|
||||||
this.kind = kind;
|
this.subprotocol = subprotocol;
|
||||||
this.addrs = addrs;
|
this.addrs = addrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,12 +53,12 @@ public class GroupInfo {
|
|||||||
this.protocol = protocol;
|
this.protocol = protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getKind() {
|
public String getSubprotocol() {
|
||||||
return kind;
|
return subprotocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKind(String kind) {
|
public void setSubprotocol(String subprotocol) {
|
||||||
this.kind = kind;
|
this.subprotocol = subprotocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<InetSocketAddress> getAddrs() {
|
public Set<InetSocketAddress> getAddrs() {
|
||||||
@@ -71,4 +73,8 @@ public class GroupInfo {
|
|||||||
this.addrs = addrs;
|
this.addrs = addrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return JsonConvert.root().convertTo(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import java.util.logging.Formatter;
|
|||||||
/**
|
/**
|
||||||
* 自定义的日志输出类
|
* 自定义的日志输出类
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@@ -70,12 +70,12 @@ public class LogFileHandler extends Handler {
|
|||||||
throwable = sw.toString();
|
throwable = sw.toString();
|
||||||
}
|
}
|
||||||
return String.format(format,
|
return String.format(format,
|
||||||
System.currentTimeMillis(),
|
System.currentTimeMillis(),
|
||||||
source,
|
source,
|
||||||
record.getLoggerName(),
|
record.getLoggerName(),
|
||||||
record.getLevel().getName(),
|
record.getLevel().getName(),
|
||||||
message,
|
message,
|
||||||
throwable);
|
throwable);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -84,9 +84,13 @@ public class LogFileHandler extends Handler {
|
|||||||
|
|
||||||
private String pattern;
|
private String pattern;
|
||||||
|
|
||||||
|
private String unusual; //不为null表示将 WARNING、SEVERE 级别的日志写入单独的文件中
|
||||||
|
|
||||||
private int limit; //文件大小限制
|
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; //文件限制
|
private int count = 1; //文件限制
|
||||||
|
|
||||||
@@ -94,11 +98,17 @@ public class LogFileHandler extends Handler {
|
|||||||
|
|
||||||
private boolean append;
|
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 File logfile;
|
||||||
|
|
||||||
private OutputStream stream;
|
private File logunusualfile;
|
||||||
|
|
||||||
|
private OutputStream logstream;
|
||||||
|
|
||||||
|
private OutputStream logunusualstream;
|
||||||
|
|
||||||
public LogFileHandler() {
|
public LogFileHandler() {
|
||||||
updateTomorrow();
|
updateTomorrow();
|
||||||
@@ -114,7 +124,7 @@ public class LogFileHandler extends Handler {
|
|||||||
cal.set(Calendar.MILLISECOND, 0);
|
cal.set(Calendar.MILLISECOND, 0);
|
||||||
cal.add(Calendar.DAY_OF_YEAR, 1);
|
cal.add(Calendar.DAY_OF_YEAR, 1);
|
||||||
long t = cal.getTimeInMillis();
|
long t = cal.getTimeInMillis();
|
||||||
if (this.tomorrow != t) index.set(0);
|
if (this.tomorrow != t) logindex.set(0);
|
||||||
this.tomorrow = t;
|
this.tomorrow = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,35 +141,59 @@ public class LogFileHandler extends Handler {
|
|||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
LogRecord record = records.take();
|
LogRecord record = records.take();
|
||||||
final boolean bigger = (limit > 0 && limit <= length.get());
|
final boolean bigger = (limit > 0 && limit <= loglength.get());
|
||||||
if (bigger || tomorrow <= record.getMillis()) {
|
final boolean changeday = tomorrow <= record.getMillis();
|
||||||
|
if (bigger || changeday) {
|
||||||
updateTomorrow();
|
updateTomorrow();
|
||||||
if (stream != null) {
|
if (logstream != null) {
|
||||||
stream.close();
|
logstream.close();
|
||||||
if (bigger) {
|
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);
|
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);
|
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);
|
Files.move(logfile.toPath(), new File(logfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||||
}
|
}
|
||||||
stream = null;
|
logstream = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stream == null) {
|
if (unusual != null && changeday && logunusualstream != null) {
|
||||||
index.incrementAndGet();
|
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();
|
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 = 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();
|
logfile.getParentFile().mkdirs();
|
||||||
length.set(logfile.length());
|
loglength.set(logfile.length());
|
||||||
stream = new FileOutputStream(logfile, append);
|
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 message = getFormatter().format(record);
|
||||||
String encoding = getEncoding();
|
String encoding = getEncoding();
|
||||||
byte[] bytes = encoding == null ? message.getBytes() : message.getBytes(encoding);
|
byte[] bytes = encoding == null ? message.getBytes() : message.getBytes(encoding);
|
||||||
stream.write(bytes);
|
logstream.write(bytes);
|
||||||
length.addAndGet(bytes.length);
|
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) {
|
} catch (Exception e) {
|
||||||
ErrorManager err = getErrorManager();
|
ErrorManager err = getErrorManager();
|
||||||
if (err != null) err.error(null, e, ErrorManager.WRITE_FAILURE);
|
if (err != null) err.error(null, e, ErrorManager.WRITE_FAILURE);
|
||||||
@@ -177,30 +211,39 @@ public class LogFileHandler extends Handler {
|
|||||||
private void configure() {
|
private void configure() {
|
||||||
LogManager manager = LogManager.getLogManager();
|
LogManager manager = LogManager.getLogManager();
|
||||||
String cname = LogFileHandler.class.getName();
|
String cname = LogFileHandler.class.getName();
|
||||||
pattern = manager.getProperty(cname + ".pattern");
|
this.pattern = manager.getProperty(cname + ".pattern");
|
||||||
if (pattern == null) {
|
if (this.pattern == null) {
|
||||||
pattern = "logs-%m/" + getPrefix() + "log-%d.log";
|
this.pattern = "logs-%m/" + getPrefix() + "log-%d.log";
|
||||||
} else {
|
} else {
|
||||||
int pos = pattern.lastIndexOf('/');
|
int pos = this.pattern.lastIndexOf('/');
|
||||||
if (pos > 0) {
|
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 {
|
} 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");
|
String limitstr = manager.getProperty(cname + ".limit");
|
||||||
try {
|
try {
|
||||||
if (limitstr != null) limit = Math.abs(Integer.decode(limitstr));
|
if (limitstr != null) this.limit = Math.abs(Integer.decode(limitstr));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
String countstr = manager.getProperty(cname + ".count");
|
String countstr = manager.getProperty(cname + ".count");
|
||||||
try {
|
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) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
String appendstr = manager.getProperty(cname + ".append");
|
String appendstr = manager.getProperty(cname + ".append");
|
||||||
try {
|
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) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
String levelstr = manager.getProperty(cname + ".level");
|
String levelstr = manager.getProperty(cname + ".level");
|
||||||
@@ -256,7 +299,7 @@ public class LogFileHandler extends Handler {
|
|||||||
@Override
|
@Override
|
||||||
public void flush() {
|
public void flush() {
|
||||||
try {
|
try {
|
||||||
if (stream != null) stream.flush();
|
if (logstream != null) logstream.flush();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ErrorManager err = getErrorManager();
|
ErrorManager err = getErrorManager();
|
||||||
if (err != null) err.error(null, e, ErrorManager.FLUSH_FAILURE);
|
if (err != null) err.error(null, e, ErrorManager.FLUSH_FAILURE);
|
||||||
@@ -266,7 +309,7 @@ public class LogFileHandler extends Handler {
|
|||||||
@Override
|
@Override
|
||||||
public void close() throws SecurityException {
|
public void close() throws SecurityException {
|
||||||
try {
|
try {
|
||||||
if (stream != null) stream.close();
|
if (logstream != null) logstream.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ErrorManager err = getErrorManager();
|
ErrorManager err = getErrorManager();
|
||||||
if (err != null) err.error(null, e, ErrorManager.CLOSE_FAILURE);
|
if (err != null) err.error(null, e, ErrorManager.CLOSE_FAILURE);
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ import org.redkale.util.*;
|
|||||||
* HTTP Server节点的配置Server
|
* HTTP Server节点的配置Server
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@NodeProtocol({"HTTP"})
|
@NodeProtocol({"HTTP"})
|
||||||
public class NodeHttpServer extends NodeServer {
|
public class NodeHttpServer extends NodeServer {
|
||||||
|
|
||||||
protected final boolean rest;
|
protected final boolean rest; //是否加载REST服务, 为true加载rest节点信息并将所有可REST化的Service生成RestHttpServlet
|
||||||
|
|
||||||
protected final HttpServer httpServer;
|
protected final HttpServer httpServer;
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
synchronized (regFactory) {
|
synchronized (regFactory) {
|
||||||
Service nodeService = (Service) rf.find(resourceName, WebSocketNode.class);
|
Service nodeService = (Service) rf.find(resourceName, WebSocketNode.class);
|
||||||
if (nodeService == null) {
|
if (nodeService == null) {
|
||||||
nodeService = Sncp.createLocalService(resourceName, getExecutor(), application.getResourceFactory(), WebSocketNodeService.class, (InetSocketAddress) null, (Transport) null, (Collection<Transport>) null);
|
nodeService = Sncp.createLocalService(resourceName, getExecutor(), application.getResourceFactory(), WebSocketNodeService.class, (InetSocketAddress) null, (String) null, (Set<String>) null, (AnyValue) null, (Transport) null, (Collection<Transport>) null);
|
||||||
regFactory.register(resourceName, WebSocketNode.class, nodeService);
|
regFactory.register(resourceName, WebSocketNode.class, nodeService);
|
||||||
resourceFactory.inject(nodeService, self);
|
resourceFactory.inject(nodeService, self);
|
||||||
logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + nodeService);
|
logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + nodeService);
|
||||||
@@ -109,13 +109,6 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
final String[] mappings = ws.value();
|
final String[] mappings = ws.value();
|
||||||
String pref = ws.repair() ? prefix : "";
|
String pref = ws.repair() ? prefix : "";
|
||||||
DefaultAnyValue servletConf = (DefaultAnyValue) en.getProperty();
|
DefaultAnyValue servletConf = (DefaultAnyValue) en.getProperty();
|
||||||
WebInitParam[] webparams = ws.initParams();
|
|
||||||
if (webparams.length > 0) {
|
|
||||||
if (servletConf == null) servletConf = new DefaultAnyValue();
|
|
||||||
for (WebInitParam webparam : webparams) {
|
|
||||||
servletConf.addValue(webparam.name(), webparam.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.httpServer.addHttpServlet(servlet, pref, servletConf, mappings);
|
this.httpServer.addHttpServlet(servlet, pref, servletConf, mappings);
|
||||||
if (ss != null) {
|
if (ss != null) {
|
||||||
for (int i = 0; i < mappings.length; i++) {
|
for (int i = 0; i < mappings.length; i++) {
|
||||||
@@ -124,32 +117,31 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
ss.add(new AbstractMap.SimpleEntry<>(clazz.getName(), mappings));
|
ss.add(new AbstractMap.SimpleEntry<>(clazz.getName(), mappings));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int max = 0;
|
||||||
if (ss != null && sb != null) {
|
if (ss != null && sb != null) {
|
||||||
Collections.sort(ss, (AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey()));
|
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) {
|
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
||||||
if (as.getKey().length() > max) max = as.getKey().length();
|
if (as.getKey().length() > max) max = as.getKey().length();
|
||||||
}
|
}
|
||||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
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++) {
|
for (int i = 0; i < max - as.getKey().length(); i++) {
|
||||||
sb.append(' ');
|
sb.append(' ');
|
||||||
}
|
}
|
||||||
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
|
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) {
|
if (rest && serverConf != null) {
|
||||||
for (AnyValue restConf : serverConf.getAnyValues("rest")) {
|
for (AnyValue restConf : serverConf.getAnyValues("rest")) {
|
||||||
loadRestServlet(prefix, restConf);
|
loadRestServlet(prefix, restConf, sb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void loadRestServlet(final String prefix, final AnyValue restConf) throws Exception {
|
protected void loadRestServlet(final String prefix, final AnyValue restConf, final StringBuilder sb) throws Exception {
|
||||||
if (!rest) return;
|
if (!rest) return;
|
||||||
if (restConf == null) return; //不存在REST服务
|
if (restConf == null) return; //不存在REST服务
|
||||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
|
||||||
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
||||||
final List<AbstractMap.SimpleEntry<String, String[]>> ss = sb == null ? null : new ArrayList<>();
|
final List<AbstractMap.SimpleEntry<String, String[]>> ss = sb == null ? null : new ArrayList<>();
|
||||||
|
|
||||||
@@ -170,8 +162,9 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
|
|
||||||
final ClassFilter restFilter = ClassFilter.create(restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
|
final ClassFilter restFilter = ClassFilter.create(restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
|
||||||
|
|
||||||
super.interceptorServiceWrappers.forEach((wrapper) -> {
|
super.interceptorServices.forEach((service) -> {
|
||||||
final Class stype = wrapper.getType();
|
final Class stype = Sncp.getServiceType(service);
|
||||||
|
final String name = Sncp.getResourceName(service);
|
||||||
RestService rs = (RestService) stype.getAnnotation(RestService.class);
|
RestService rs = (RestService) stype.getAnnotation(RestService.class);
|
||||||
if (rs != null && rs.ignore()) return;
|
if (rs != null && rs.ignore()) return;
|
||||||
if (mustsign && rs == null) return;
|
if (mustsign && rs == null) return;
|
||||||
@@ -181,9 +174,9 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
if (!autoload && !includeValues.contains(stypename)) return;
|
if (!autoload && !includeValues.contains(stypename)) return;
|
||||||
if (!restFilter.accept(stypename)) return;
|
if (!restFilter.accept(stypename)) return;
|
||||||
|
|
||||||
RestHttpServlet servlet = httpServer.addRestServlet(wrapper.getName(), stype, wrapper.getService(), baseServletClass, prefix, (AnyValue) null);
|
RestHttpServlet servlet = httpServer.addRestServlet(name, stype, service, baseServletClass, prefix, (AnyValue) null);
|
||||||
resourceFactory.inject(servlet, NodeHttpServer.this);
|
resourceFactory.inject(servlet, NodeHttpServer.this);
|
||||||
if (finest) logger.finest("Create RestServlet[resource=" + wrapper.getName() + "] = " + servlet);
|
if (finest) logger.finest(threadName + " Create RestServlet(resource.name='" + name + "') = " + servlet);
|
||||||
if (ss != null) {
|
if (ss != null) {
|
||||||
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
|
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
|
||||||
for (int i = 0; i < mappings.length; i++) {
|
for (int i = 0; i < mappings.length; i++) {
|
||||||
@@ -199,14 +192,14 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
||||||
if (as.getKey().length() > max) max = as.getKey().length();
|
if (as.getKey().length() > max) max = as.getKey().length();
|
||||||
}
|
}
|
||||||
|
sb.append(threadName).append(" ").append(LINE_SEPARATOR);
|
||||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
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++) {
|
for (int i = 0; i < max - as.getKey().length(); i++) {
|
||||||
sb.append(' ');
|
sb.append(' ');
|
||||||
}
|
}
|
||||||
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
|
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,83 +5,34 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.boot;
|
package org.redkale.boot;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import org.redkale.service.Service;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* NodeServer的拦截类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class NodeInterceptor {
|
public class NodeInterceptor {
|
||||||
|
|
||||||
|
/** *
|
||||||
|
* Server.start之前调用 <br>
|
||||||
|
* NodeServer.start的部署是先执行NodeInterceptor.preStart,再执行 Server.start 方法
|
||||||
|
*
|
||||||
|
* @param server NodeServer
|
||||||
|
*/
|
||||||
public void preStart(NodeServer server) {
|
public void preStart(NodeServer server) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server.shutdown之前调用 <br>
|
||||||
|
* NodeServer.shutdown的部署是先执行NodeInterceptor.preShutdown,再执行 Server.sshutdown 方法
|
||||||
|
*
|
||||||
|
* @param server NodeServer
|
||||||
|
*/
|
||||||
public void preShutdown(NodeServer server) {
|
public void preShutdown(NodeServer server) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class InterceptorServiceWrapper<T extends Service> {
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
private Class<T> type;
|
|
||||||
|
|
||||||
private T service;
|
|
||||||
|
|
||||||
public InterceptorServiceWrapper() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public InterceptorServiceWrapper(String name, Class<T> type, T service) {
|
|
||||||
this.name = name;
|
|
||||||
this.type = type;
|
|
||||||
this.service = service;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<T> getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setType(Class<T> type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getService() {
|
|
||||||
return service;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setService(T service) {
|
|
||||||
this.service = service;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int hash = 7;
|
|
||||||
hash = 97 * hash + Objects.hashCode(this.name);
|
|
||||||
hash = 97 * hash + Objects.hashCode(this.type);
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) return true;
|
|
||||||
if (obj == null) return false;
|
|
||||||
if (getClass() != obj.getClass()) return false;
|
|
||||||
final InterceptorServiceWrapper<?> other = (InterceptorServiceWrapper<?>) obj;
|
|
||||||
return Objects.equals(this.name, other.name) && Objects.equals(this.type, other.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ package org.redkale.boot;
|
|||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据application.xml中的server节点中的protocol值来适配Server的加载逻辑
|
* 根据application.xml中的server节点中的protocol值来适配Server的加载逻辑, 只能注解在NodeServer子类上
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import org.redkale.util.*;
|
|||||||
* Server节点的初始化配置类
|
* Server节点的初始化配置类
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@@ -69,7 +69,7 @@ public abstract class NodeServer {
|
|||||||
private InetSocketAddress sncpAddress;
|
private InetSocketAddress sncpAddress;
|
||||||
|
|
||||||
//加载Service时的处理函数
|
//加载Service时的处理函数
|
||||||
protected Consumer<ServiceWrapper> consumer;
|
protected Consumer<Service> consumer;
|
||||||
|
|
||||||
//server节点的配置
|
//server节点的配置
|
||||||
protected AnyValue serverConf;
|
protected AnyValue serverConf;
|
||||||
@@ -78,13 +78,17 @@ public abstract class NodeServer {
|
|||||||
protected NodeInterceptor interceptor;
|
protected NodeInterceptor interceptor;
|
||||||
|
|
||||||
//供interceptor使用的Service对象集合
|
//供interceptor使用的Service对象集合
|
||||||
protected final Set<NodeInterceptor.InterceptorServiceWrapper> interceptorServiceWrappers = new LinkedHashSet<>();
|
protected final Set<Service> interceptorServices = new LinkedHashSet<>();
|
||||||
|
|
||||||
//本地模式的Service对象集合
|
//本地模式的Service对象集合
|
||||||
protected final Set<ServiceWrapper> localServiceWrappers = new LinkedHashSet<>();
|
protected final Set<Service> localServices = new LinkedHashSet<>();
|
||||||
|
|
||||||
//远程模式的Service对象集合
|
//远程模式的Service对象集合
|
||||||
protected final Set<ServiceWrapper> remoteServiceWrappers = new LinkedHashSet<>();
|
protected final Set<Service> remoteServices = new LinkedHashSet<>();
|
||||||
|
|
||||||
|
private volatile int maxClassNameLength = 0;
|
||||||
|
|
||||||
|
private volatile int maxNameLength = 0;
|
||||||
|
|
||||||
public NodeServer(Application application, Server server) {
|
public NodeServer(Application application, Server server) {
|
||||||
this.application = application;
|
this.application = application;
|
||||||
@@ -116,7 +120,7 @@ public abstract class NodeServer {
|
|||||||
if (context == null) {
|
if (context == null) {
|
||||||
t.run();
|
t.run();
|
||||||
} else {
|
} else {
|
||||||
context.submit(t);
|
context.submitAsync(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +169,7 @@ public abstract class NodeServer {
|
|||||||
initResource(); //给 DataSource、CacheSource 注册依赖注入时的监听回调事件。
|
initResource(); //给 DataSource、CacheSource 注册依赖注入时的监听回调事件。
|
||||||
String interceptorClass = this.serverConf.getValue("interceptor", "");
|
String interceptorClass = this.serverConf.getValue("interceptor", "");
|
||||||
if (!interceptorClass.isEmpty()) {
|
if (!interceptorClass.isEmpty()) {
|
||||||
Class clazz = Class.forName(interceptorClass);
|
Class clazz = Class.forName(interceptorClass);
|
||||||
this.interceptor = (NodeInterceptor) clazz.newInstance();
|
this.interceptor = (NodeInterceptor) clazz.newInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,11 +195,36 @@ public abstract class NodeServer {
|
|||||||
final NodeServer self = this;
|
final NodeServer self = this;
|
||||||
//---------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------
|
||||||
final ResourceFactory appResFactory = application.getResourceFactory();
|
final ResourceFactory appResFactory = application.getResourceFactory();
|
||||||
|
//------------------------------------- 注册Resource --------------------------------------------------------
|
||||||
|
resourceFactory.register((ResourceFactory rf, final Object src, String resourceName, Field field, final Object attachment) -> {
|
||||||
|
try {
|
||||||
|
Resource res = field.getAnnotation(Resource.class);
|
||||||
|
if (res == null || !res.name().startsWith("properties.")) return;
|
||||||
|
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不得注入 DataSource
|
||||||
|
Class type = field.getType();
|
||||||
|
if (type != AnyValue.class && type != AnyValue[].class) return;
|
||||||
|
Object resource = null;
|
||||||
|
final AnyValue resources = application.config.getAnyValue("resources");
|
||||||
|
final AnyValue properties = resources == null ? null : resources.getAnyValue("properties");
|
||||||
|
if (properties != null && type == AnyValue.class) {
|
||||||
|
resource = properties.getAnyValue(res.name().substring("properties.".length()));
|
||||||
|
appResFactory.register(resourceName, AnyValue.class, resource);
|
||||||
|
} else if (properties != null && type == AnyValue[].class) {
|
||||||
|
resource = properties.getAnyValues(res.name().substring("properties.".length()));
|
||||||
|
appResFactory.register(resourceName, AnyValue[].class, resource);
|
||||||
|
}
|
||||||
|
field.set(src, resource);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.SEVERE, "Resource inject error", e);
|
||||||
|
}
|
||||||
|
}, AnyValue.class, AnyValue[].class);
|
||||||
|
|
||||||
|
//------------------------------------- 注册DataSource --------------------------------------------------------
|
||||||
resourceFactory.register((ResourceFactory rf, final Object src, String resourceName, Field field, final Object attachment) -> {
|
resourceFactory.register((ResourceFactory rf, final Object src, String resourceName, Field field, final Object attachment) -> {
|
||||||
try {
|
try {
|
||||||
if (field.getAnnotation(Resource.class) == null) return;
|
if (field.getAnnotation(Resource.class) == null) return;
|
||||||
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不得注入 DataSource
|
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不得注入 DataSource
|
||||||
DataSource source = new DataDefaultSource(resourceName);
|
DataSource source = DataSources.createDataSource(resourceName);
|
||||||
application.dataSources.add(source);
|
application.dataSources.add(source);
|
||||||
appResFactory.register(resourceName, DataSource.class, source);
|
appResFactory.register(resourceName, DataSource.class, source);
|
||||||
|
|
||||||
@@ -203,34 +232,35 @@ public abstract class NodeServer {
|
|||||||
Transport sameGroupTransport = Sncp.getSameGroupTransport((Service) src);
|
Transport sameGroupTransport = Sncp.getSameGroupTransport((Service) src);
|
||||||
List<Transport> diffGroupTransports = Arrays.asList(Sncp.getDiffGroupTransports((Service) src));
|
List<Transport> diffGroupTransports = Arrays.asList(Sncp.getDiffGroupTransports((Service) src));
|
||||||
final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress();
|
final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress();
|
||||||
if ((src instanceof DataSource) && sncpAddr != null && resourceFactory.find(resourceName, DataCacheListener.class) == null) { //只有DataSourceService 才能赋值 DataCacheListener
|
if ((src instanceof DataSource) && sncpAddr != null && resourceFactory.find(resourceName, DataCacheListener.class) == null) { //只有DataSourceService 才能赋值 DataCacheListener
|
||||||
Service cacheListenerService = Sncp.createLocalService(resourceName, getExecutor(), appResFactory, DataCacheListenerService.class, sncpAddr, sameGroupTransport, diffGroupTransports);
|
|
||||||
appResFactory.register(resourceName, DataCacheListener.class, cacheListenerService);
|
|
||||||
final NodeSncpServer sncpServer = application.findNodeSncpServer(sncpAddr);
|
final NodeSncpServer sncpServer = application.findNodeSncpServer(sncpAddr);
|
||||||
Set<String> gs = application.findSncpGroups(sameGroupTransport, diffGroupTransports);
|
Set<String> gs = application.findSncpGroups(sameGroupTransport, diffGroupTransports);
|
||||||
ServiceWrapper wrapper = new ServiceWrapper(DataCacheListenerService.class, cacheListenerService, resourceName, sncpServer.getSncpGroup(), gs, null);
|
Service cacheListenerService = Sncp.createLocalService(resourceName, getExecutor(), appResFactory, DataCacheListenerService.class, sncpAddr, sncpServer.getSncpGroup(), gs, Sncp.getConf((Service) src), sameGroupTransport, diffGroupTransports);
|
||||||
localServiceWrappers.add(wrapper);
|
appResFactory.register(resourceName, DataCacheListener.class, cacheListenerService);
|
||||||
sncpServer.consumerAccept(wrapper);
|
localServices.add(cacheListenerService);
|
||||||
|
sncpServer.consumerAccept(cacheListenerService);
|
||||||
rf.inject(cacheListenerService, self);
|
rf.inject(cacheListenerService, self);
|
||||||
logger.info("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService());
|
logger.info("[" + Thread.currentThread().getName() + "] Load Service " + cacheListenerService);
|
||||||
}
|
}
|
||||||
field.set(src, source);
|
field.set(src, source);
|
||||||
rf.inject(source, self); // 给 "datasource.nodeid" 赋值;
|
rf.inject(source, self); // 给其可能包含@Resource的字段赋值;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "DataSource inject error", e);
|
logger.log(Level.SEVERE, "DataSource inject error", e);
|
||||||
}
|
}
|
||||||
}, DataSource.class);
|
}, DataSource.class);
|
||||||
|
|
||||||
|
//------------------------------------- 注册CacheSource --------------------------------------------------------
|
||||||
resourceFactory.register((ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> {
|
resourceFactory.register((ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> {
|
||||||
try {
|
try {
|
||||||
if (field.getAnnotation(Resource.class) == null) return;
|
if (field.getAnnotation(Resource.class) == null) return;
|
||||||
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不得注入 CacheSource
|
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不需要注入 CacheSource
|
||||||
|
final Service srcService = (Service) src;
|
||||||
SncpClient client = Sncp.getSncpClient((Service) src);
|
SncpClient client = Sncp.getSncpClient(srcService);
|
||||||
Transport sameGroupTransport = Sncp.getSameGroupTransport((Service) src);
|
Transport sameGroupTransport = Sncp.getSameGroupTransport(srcService);
|
||||||
Transport[] dts = Sncp.getDiffGroupTransports((Service) src);
|
Transport[] dts = Sncp.getDiffGroupTransports((Service) src);
|
||||||
List<Transport> diffGroupTransports = dts == null ? new ArrayList<>() : Arrays.asList(dts);
|
List<Transport> diffGroupTransports = dts == null ? new ArrayList<>() : Arrays.asList(dts);
|
||||||
final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress();
|
final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress();
|
||||||
final CacheSourceService source = Sncp.createLocalService(resourceName, getExecutor(), appResFactory, CacheSourceService.class, sncpAddr, sameGroupTransport, diffGroupTransports);
|
final CacheMemorySource source = Sncp.createLocalService(resourceName, getExecutor(), appResFactory, CacheMemorySource.class, sncpAddr, Sncp.getSncpGroup(srcService), Sncp.getGroups(srcService), Sncp.getConf(srcService), sameGroupTransport, diffGroupTransports);
|
||||||
Type genericType = field.getGenericType();
|
Type genericType = field.getGenericType();
|
||||||
ParameterizedType pt = (genericType instanceof ParameterizedType) ? (ParameterizedType) genericType : null;
|
ParameterizedType pt = (genericType instanceof ParameterizedType) ? (ParameterizedType) genericType : null;
|
||||||
Type valType = pt == null ? null : pt.getActualTypeArguments()[1];
|
Type valType = pt == null ? null : pt.getActualTypeArguments()[1];
|
||||||
@@ -243,12 +273,11 @@ public abstract class NodeServer {
|
|||||||
rf.inject(source, self); //
|
rf.inject(source, self); //
|
||||||
((Service) source).init(null);
|
((Service) source).init(null);
|
||||||
|
|
||||||
if ((src instanceof WebSocketNodeService) && sncpAddr != null) { //只有WebSocketNodeService的服务才需要给SNCP服务注入CacheSourceService
|
if ((src instanceof WebSocketNodeService) && sncpAddr != null) { //只有WebSocketNodeService的服务才需要给SNCP服务注入CacheMemorySource
|
||||||
NodeSncpServer sncpServer = application.findNodeSncpServer(sncpAddr);
|
NodeSncpServer sncpServer = application.findNodeSncpServer(sncpAddr);
|
||||||
Set<String> gs = application.findSncpGroups(sameGroupTransport, diffGroupTransports);
|
Set<String> gs = application.findSncpGroups(sameGroupTransport, diffGroupTransports);
|
||||||
ServiceWrapper wrapper = new ServiceWrapper(CacheSourceService.class, (Service) source, resourceName, sncpServer.getSncpGroup(), gs, null);
|
sncpServer.getSncpServer().addSncpServlet((Service) source);
|
||||||
sncpServer.getSncpServer().addSncpServlet(wrapper);
|
logger.info("[" + Thread.currentThread().getName() + "] Load Service " + source);
|
||||||
logger.info("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService());
|
|
||||||
}
|
}
|
||||||
logger.info("[" + Thread.currentThread().getName() + "] Load Source " + source);
|
logger.info("[" + Thread.currentThread().getName() + "] Load Source " + source);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -265,55 +294,55 @@ public abstract class NodeServer {
|
|||||||
ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : resourceFactory;
|
ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : resourceFactory;
|
||||||
|
|
||||||
for (FilterEntry<Service> entry : entrys) { //service实现类
|
for (FilterEntry<Service> entry : entrys) { //service实现类
|
||||||
final Class<? extends Service> type = entry.getType();
|
final Class<? extends Service> serviceImplClass = entry.getType();
|
||||||
if (Modifier.isFinal(type.getModifiers())) continue; //修饰final的类跳过
|
if (Modifier.isFinal(serviceImplClass.getModifiers())) continue; //修饰final的类跳过
|
||||||
if (!Modifier.isPublic(type.getModifiers())) continue;
|
if (!Modifier.isPublic(serviceImplClass.getModifiers())) continue;
|
||||||
if (entry.isExpect()) {
|
if (entry.isExpect()) {
|
||||||
if (Modifier.isAbstract(type.getModifiers())) continue; //修饰abstract的类跳过
|
if (Modifier.isAbstract(serviceImplClass.getModifiers())) continue; //修饰abstract的类跳过
|
||||||
if (DataSource.class.isAssignableFrom(type)) continue;
|
if (DataSource.class.isAssignableFrom(serviceImplClass)) continue;
|
||||||
if (CacheSource.class.isAssignableFrom(type)) continue;
|
if (CacheSource.class.isAssignableFrom(serviceImplClass)) continue;
|
||||||
if (DataCacheListener.class.isAssignableFrom(type)) continue;
|
if (DataCacheListener.class.isAssignableFrom(serviceImplClass)) continue;
|
||||||
if (WebSocketNode.class.isAssignableFrom(type)) continue;
|
if (WebSocketNode.class.isAssignableFrom(serviceImplClass)) continue;
|
||||||
}
|
}
|
||||||
if (entry.getName().contains("$")) throw new RuntimeException("<name> value cannot contains '$' in " + entry.getProperty());
|
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(), serviceImplClass);
|
||||||
Service oldother = resourceFactory.find(entry.getName(), type);
|
if (oldother != null) { //Server加载Service时需要判断是否已经加载过了。
|
||||||
interceptorServiceWrappers.add(new NodeInterceptor.InterceptorServiceWrapper(entry.getName(), type, oldother));
|
interceptorServices.add(oldother);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final HashSet<String> groups = entry.getGroups(); //groups.isEmpty()表示<services>没有配置groups属性。
|
final HashSet<String> groups = entry.getGroups(); //groups.isEmpty()表示<services>没有配置groups属性。
|
||||||
if (groups.isEmpty() && isSNCP() && this.sncpGroup != null) groups.add(this.sncpGroup);
|
if (groups.isEmpty() && isSNCP() && this.sncpGroup != null) groups.add(this.sncpGroup);
|
||||||
|
|
||||||
final boolean localed = (this.sncpAddress == null && entry.isEmptyGroups() && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) //非SNCP的Server,通常是单点服务
|
final boolean localed = (this.sncpAddress == null && entry.isEmptyGroups() && !serviceImplClass.isInterface() && !Modifier.isAbstract(serviceImplClass.getModifiers())) //非SNCP的Server,通常是单点服务
|
||||||
|| groups.contains(this.sncpGroup) //本地IP含在内的
|
|| groups.contains(this.sncpGroup) //本地IP含在内的
|
||||||
|| (this.sncpGroup == null && entry.isEmptyGroups()) //空的SNCP配置
|
|| (this.sncpGroup == null && entry.isEmptyGroups()) //空的SNCP配置
|
||||||
|| type.getAnnotation(LocalService.class) != null;//本地模式
|
|| serviceImplClass.getAnnotation(LocalService.class) != null;//本地模式
|
||||||
if (localed && (type.isInterface() || Modifier.isAbstract(type.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类
|
if (localed && (serviceImplClass.isInterface() || Modifier.isAbstract(serviceImplClass.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类
|
||||||
final BiConsumer<ResourceFactory, Boolean> runner = (ResourceFactory rf, Boolean needinject) -> {
|
final BiConsumer<ResourceFactory, Boolean> runner = (ResourceFactory rf, Boolean needinject) -> {
|
||||||
try {
|
try {
|
||||||
Service service;
|
Service service;
|
||||||
if (localed) { //本地模式
|
if (localed) { //本地模式
|
||||||
service = Sncp.createLocalService(entry.getName(), getExecutor(), application.getResourceFactory(), type,
|
service = Sncp.createLocalService(entry.getName(), getExecutor(), application.getResourceFactory(), serviceImplClass,
|
||||||
NodeServer.this.sncpAddress, loadTransport(NodeServer.this.sncpGroup), loadTransports(groups));
|
NodeServer.this.sncpAddress, NodeServer.this.sncpGroup, groups, entry.getProperty(), loadTransport(NodeServer.this.sncpGroup), loadTransports(groups));
|
||||||
} else {
|
} else {
|
||||||
service = Sncp.createRemoteService(entry.getName(), getExecutor(), type, NodeServer.this.sncpAddress, loadTransport(groups));
|
service = Sncp.createRemoteService(entry.getName(), getExecutor(), serviceImplClass, NodeServer.this.sncpAddress, null, groups, entry.getProperty(), loadTransport(groups));
|
||||||
}
|
}
|
||||||
if (SncpClient.parseMethod(type).isEmpty()) return; //class没有可用的方法, 通常为BaseService
|
if (SncpClient.parseMethod(serviceImplClass).isEmpty()) return; //class没有可用的方法, 通常为BaseService
|
||||||
final ServiceWrapper wrapper = new ServiceWrapper(type, service, entry.getName(), localed ? NodeServer.this.sncpGroup : null, groups, entry.getProperty());
|
//final ServiceWrapper wrapper = new ServiceWrapper(serviceImplClass, service, entry.getName(), localed ? NodeServer.this.sncpGroup : null, groups, entry.getProperty());
|
||||||
for (final Class restype : wrapper.getTypes()) {
|
for (final Class restype : Sncp.getResourceTypes(service)) {
|
||||||
if (resourceFactory.find(wrapper.getName(), restype) == null) {
|
if (resourceFactory.find(entry.getName(), restype) == null) {
|
||||||
regFactory.register(wrapper.getName(), restype, wrapper.getService());
|
regFactory.register(entry.getName(), restype, service);
|
||||||
if (needinject) rf.inject(wrapper.getService()); //动态加载的Service也存在按需加载的注入资源
|
if (needinject) rf.inject(service); //动态加载的Service也存在按需加载的注入资源
|
||||||
} else if (isSNCP() && !entry.isAutoload()) {
|
} else if (isSNCP() && !entry.isAutoload()) {
|
||||||
throw new RuntimeException(ServiceWrapper.class.getSimpleName() + "(class:" + type.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat.");
|
throw new RuntimeException(restype.getSimpleName() + "(class:" + serviceImplClass.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (wrapper.isRemote()) {
|
if (Sncp.isRemote(service)) {
|
||||||
remoteServiceWrappers.add(wrapper);
|
remoteServices.add(service);
|
||||||
} else {
|
} else {
|
||||||
localServiceWrappers.add(wrapper);
|
localServices.add(service);
|
||||||
interceptorServiceWrappers.add(new NodeInterceptor.InterceptorServiceWrapper(entry.getName(), type, service));
|
interceptorServices.add(service);
|
||||||
if (consumer != null) consumer.accept(wrapper);
|
if (consumer != null) consumer.accept(service);
|
||||||
}
|
}
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw ex;
|
throw ex;
|
||||||
@@ -325,7 +354,9 @@ public abstract class NodeServer {
|
|||||||
ResourceFactory.ResourceLoader resourceLoader = (ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> {
|
ResourceFactory.ResourceLoader resourceLoader = (ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> {
|
||||||
runner.accept(rf, true);
|
runner.accept(rf, true);
|
||||||
};
|
};
|
||||||
for (final Class restype : ServiceWrapper.parseTypes(entry.getType())) {
|
ResourceType rty = entry.getType().getAnnotation(ResourceType.class);
|
||||||
|
Class[] resTypes = rty == null ? new Class[]{} : rty.value();
|
||||||
|
for (final Class restype : resTypes) {
|
||||||
resourceFactory.register(resourceLoader, restype);
|
resourceFactory.register(resourceLoader, restype);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -339,30 +370,38 @@ public abstract class NodeServer {
|
|||||||
|
|
||||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||||
//---------------- inject ----------------
|
//---------------- inject ----------------
|
||||||
new ArrayList<>(localServiceWrappers).forEach(y -> {
|
new ArrayList<>(localServices).forEach(y -> {
|
||||||
resourceFactory.inject(y.getService(), NodeServer.this);
|
resourceFactory.inject(y, NodeServer.this);
|
||||||
|
calcMaxLength(y);
|
||||||
});
|
});
|
||||||
new ArrayList<>(remoteServiceWrappers).forEach(y -> {
|
new ArrayList<>(remoteServices).forEach(y -> {
|
||||||
resourceFactory.inject(y.getService(), NodeServer.this);
|
resourceFactory.inject(y, NodeServer.this);
|
||||||
|
calcMaxLength(y);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (sb != null) {
|
if (sb != null) {
|
||||||
remoteServiceWrappers.forEach(y -> {
|
remoteServices.forEach(y -> {
|
||||||
sb.append(threadName).append(y.toSimpleString()).append(" loaded and injected").append(LINE_SEPARATOR);
|
sb.append(threadName).append(Sncp.toSimpleString(y, maxNameLength, maxClassNameLength)).append(" load and inject").append(LINE_SEPARATOR);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//----------------- init -----------------
|
//----------------- init -----------------
|
||||||
List<ServiceWrapper> swlist = new ArrayList<>(localServiceWrappers);
|
List<Service> swlist = new ArrayList<>(localServices);
|
||||||
Collections.sort(swlist);
|
Collections.sort(swlist, (o1, o2) -> {
|
||||||
localServiceWrappers.clear();
|
int rs = Sncp.getResourceTypes(o1)[0].getName().compareTo(Sncp.getResourceTypes(o2)[0].getName());
|
||||||
localServiceWrappers.addAll(swlist);
|
if (rs == 0) rs = Sncp.getResourceName(o1).compareTo(Sncp.getResourceName(o2));
|
||||||
|
return rs;
|
||||||
|
});
|
||||||
|
localServices.clear();
|
||||||
|
localServices.addAll(swlist);
|
||||||
final List<String> slist = sb == null ? null : new CopyOnWriteArrayList<>();
|
final List<String> slist = sb == null ? null : new CopyOnWriteArrayList<>();
|
||||||
CountDownLatch clds = new CountDownLatch(localServiceWrappers.size());
|
CountDownLatch clds = new CountDownLatch(localServices.size());
|
||||||
localServiceWrappers.parallelStream().forEach(y -> {
|
localServices.parallelStream().forEach(y -> {
|
||||||
try {
|
try {
|
||||||
long s = System.currentTimeMillis();
|
long s = System.currentTimeMillis();
|
||||||
y.getService().init(y.getConf());
|
y.init(Sncp.getConf(y));
|
||||||
long e = System.currentTimeMillis() - s;
|
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());
|
String serstr = Sncp.toSimpleString(y, maxNameLength, maxClassNameLength);
|
||||||
|
if (slist != null) slist.add(new StringBuilder().append(threadName).append(serstr).append(" load and init in ").append(e).append(" ms").append(LINE_SEPARATOR).toString());
|
||||||
} finally {
|
} finally {
|
||||||
clds.countDown();
|
clds.countDown();
|
||||||
}
|
}
|
||||||
@@ -378,6 +417,20 @@ public abstract class NodeServer {
|
|||||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void calcMaxLength(Service y) { //计算toString中的长度
|
||||||
|
maxNameLength = Math.max(maxNameLength, Sncp.getResourceName(y).length());
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
Class[] types = Sncp.getResourceTypes(y);
|
||||||
|
if (types.length == 1) {
|
||||||
|
s.append(types[0].getName());
|
||||||
|
} else {
|
||||||
|
s.append('[');
|
||||||
|
s.append(Arrays.asList(types).stream().map((Class t) -> t.getName()).collect(Collectors.joining(",")));
|
||||||
|
s.append(']');
|
||||||
|
}
|
||||||
|
maxClassNameLength = Math.max(maxClassNameLength, s.length() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
protected List<Transport> loadTransports(final HashSet<String> groups) {
|
protected List<Transport> loadTransports(final HashSet<String> groups) {
|
||||||
if (groups == null) return null;
|
if (groups == null) return null;
|
||||||
final List<Transport> transports = new ArrayList<>();
|
final List<Transport> transports = new ArrayList<>();
|
||||||
@@ -403,7 +456,7 @@ public abstract class NodeServer {
|
|||||||
Transport first = transports.get(0);
|
Transport first = transports.get(0);
|
||||||
GroupInfo ginfo = application.findGroupInfo(first.getName());
|
GroupInfo ginfo = application.findGroupInfo(first.getName());
|
||||||
Transport newTransport = new Transport(groupid, ginfo.getProtocol(), application.getWatchFactory(),
|
Transport newTransport = new Transport(groupid, ginfo.getProtocol(), application.getWatchFactory(),
|
||||||
ginfo.getKind(), application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs);
|
ginfo.getSubprotocol(), application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs);
|
||||||
synchronized (application.resourceFactory) {
|
synchronized (application.resourceFactory) {
|
||||||
transport = application.resourceFactory.find(groupid, Transport.class);
|
transport = application.resourceFactory.find(groupid, Transport.class);
|
||||||
if (transport == null) {
|
if (transport == null) {
|
||||||
@@ -429,7 +482,7 @@ public abstract class NodeServer {
|
|||||||
Set<InetSocketAddress> addrs = ginfo.copyAddrs();
|
Set<InetSocketAddress> addrs = ginfo.copyAddrs();
|
||||||
if (addrs == null) throw new RuntimeException("Not found <group> = " + group + " on <resources> ");
|
if (addrs == null) throw new RuntimeException("Not found <group> = " + group + " on <resources> ");
|
||||||
transport = new Transport(group, ginfo.getProtocol(), application.getWatchFactory(),
|
transport = new Transport(group, ginfo.getProtocol(), application.getWatchFactory(),
|
||||||
ginfo.getKind(), application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs);
|
ginfo.getSubprotocol(), application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs);
|
||||||
application.resourceFactory.register(group, transport);
|
application.resourceFactory.register(group, transport);
|
||||||
}
|
}
|
||||||
return transport;
|
return transport;
|
||||||
@@ -532,12 +585,12 @@ public abstract class NodeServer {
|
|||||||
public void shutdown() throws IOException {
|
public void shutdown() throws IOException {
|
||||||
if (interceptor != null) interceptor.preShutdown(this);
|
if (interceptor != null) interceptor.preShutdown(this);
|
||||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||||
localServiceWrappers.forEach(y -> {
|
localServices.forEach(y -> {
|
||||||
long s = System.currentTimeMillis();
|
long s = System.currentTimeMillis();
|
||||||
y.getService().destroy(y.getConf());
|
y.destroy(Sncp.getConf(y));
|
||||||
long e = System.currentTimeMillis() - s;
|
long e = System.currentTimeMillis() - s;
|
||||||
if (e > 2 && sb != null) {
|
if (e > 2 && sb != null) {
|
||||||
sb.append(y.toSimpleString()).append(" destroy ").append(e).append("ms").append(LINE_SEPARATOR);
|
sb.append(Sncp.toSimpleString(y, maxNameLength, maxClassNameLength)).append(" destroy ").append(e).append("ms").append(LINE_SEPARATOR);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||||
@@ -548,16 +601,16 @@ public abstract class NodeServer {
|
|||||||
return (T) server;
|
return (T) server;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<NodeInterceptor.InterceptorServiceWrapper> getInterceptorServiceWrappers() {
|
public Set<Service> getInterceptorServices() {
|
||||||
return new LinkedHashSet<>(interceptorServiceWrappers);
|
return new LinkedHashSet<>(interceptorServices);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ServiceWrapper> getLocalServiceWrappers() {
|
public Set<Service> getLocalServices() {
|
||||||
return new LinkedHashSet<>(localServiceWrappers);
|
return new LinkedHashSet<>(localServices);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ServiceWrapper> getRemoteServiceWrappers() {
|
public Set<Service> getRemoteServices() {
|
||||||
return new LinkedHashSet<>(remoteServiceWrappers);
|
return new LinkedHashSet<>(remoteServices);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,14 @@ import java.util.*;
|
|||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.net.sncp.*;
|
import org.redkale.net.sncp.*;
|
||||||
|
import org.redkale.service.Service;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* SNCP Server节点的配置Server
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@@ -47,8 +49,8 @@ public class NodeSncpServer extends NodeServer {
|
|||||||
return sncpServer == null ? null : sncpServer.getSocketAddress();
|
return sncpServer == null ? null : sncpServer.getSocketAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void consumerAccept(ServiceWrapper wrapper) {
|
public void consumerAccept(Service service) {
|
||||||
if (this.consumer != null) this.consumer.accept(wrapper);
|
if (this.consumer != null) this.consumer.accept(service);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -61,7 +63,7 @@ public class NodeSncpServer extends NodeServer {
|
|||||||
List<SncpServlet> servlets = sncpServer.getSncpServlets();
|
List<SncpServlet> servlets = sncpServer.getSncpServlets();
|
||||||
Collections.sort(servlets);
|
Collections.sort(servlets);
|
||||||
for (SncpServlet en : 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());
|
if (sb != null && sb.length() > 0) logger.log(Level.FINE, sb.toString());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"><title>Document</title>
|
<meta charset="UTF-8"><title>接口文档(apidoc生成)</title>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body {text-align: center;margin:auto;}
|
body {text-align: center;margin:auto;}
|
||||||
a{text-decoration: none;}
|
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 {margin: auto;border-collapse: collapse;border-spacing: 0;display: block;width: 100%;overflow: auto;word-break: normal;word-break: keep-all;}
|
||||||
.table td,.table th{padding: 0.4rem 1.2rem 0.4rem 1.2rem;border: 1px solid #aaa;}
|
.table td,.table th{padding: 0.2rem 0.8rem 0.2rem 0.8rem;border: 1px solid #aaa;}
|
||||||
.table td {text-align: left;}
|
.table td {text-align: left;}
|
||||||
.s {font-size: 0.8rem; vertical-align: middle;}
|
.s {font-size: 0.8rem; vertical-align: middle;}
|
||||||
.subtable {border-spacing: 0;border: 0;margin:0;}
|
.subtable {border-spacing: 0;border: 0;margin:0;}
|
||||||
@@ -25,13 +25,19 @@
|
|||||||
html.push('<div style="width:' + Math.floor(window.screen.width * 0.9) + 'px;margin:0 auto;text-align: center;">');
|
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">');
|
html.push('<br/><br/><table class="table" align="center">');
|
||||||
for (var i = 0; i < jsoncontent.servers.length; i++) {
|
for (var i = 0; i < jsoncontent.servers.length; i++) {
|
||||||
for (var j = 0; j < jsoncontent.servers[i].servlets.length; j++) {
|
var servlets = jsoncontent.servers[i].servlets;
|
||||||
var servlet = jsoncontent.servers[i].servlets[j];
|
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;"> </th></tr>');
|
if (html.length > 2) html.push(' <tr><th colspan="5" style="border-bottom:0;"> </th></tr>');
|
||||||
html.push(' <tr><th colspan="5" style="border-top:' + ((html.length > 2) ? 0 : 1) + ';">' + (servlet.comment || '未知模块') + '</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>');
|
html.push(' <tr><th>请求URL</th><th>描 述</th><th>鉴 权</th><th>参 数 <span style="font-size:12px;">(粗体: 必填项; 红色: Header; 蓝色: Cookie)</span></th><th>输 出</th></tr>');
|
||||||
for (var k = 0; k < servlet.actions.length; k++) {
|
for (var k = 0; k < servlet.mappings.length; k++) {
|
||||||
var action = servlet.actions[k];
|
var action = servlet.mappings[k];
|
||||||
html.push(' <tr>');
|
html.push(' <tr>');
|
||||||
html.push('<td style="color:#ff00ff;">' + action.url + '</td>');
|
html.push('<td style="color:#ff00ff;">' + action.url + '</td>');
|
||||||
html.push('<td>' + action.comment + '</td>');
|
html.push('<td>' + action.comment + '</td>');
|
||||||
@@ -47,15 +53,22 @@
|
|||||||
if (param.name == '&') {
|
if (param.name == '&') {
|
||||||
paramshtml.push('<tr><td style="font-size:12px;">内置 </td><td> ' + t + '</td><td> 当前用户</td></tr>');
|
paramshtml.push('<tr><td style="font-size:12px;">内置 </td><td> ' + t + '</td><td> 当前用户</td></tr>');
|
||||||
} else {
|
} else {
|
||||||
var c = ' style="font-weight:bold;"';
|
var w = param.required ? "font-weight:bold;" : "";
|
||||||
if (param.src == "HEADER") c = ' style="color:red;font-weight:bold;"';
|
var c = ' style="' + w + '"';
|
||||||
if (param.src == "COOKIE") c = ' style="color:blue;font-weight:bold;"';
|
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('<tr><td ' + c + '> ' + param.name + ' </td><td> ' + t + '</td><td> ' + param.comment + '</td></tr>');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
paramshtml.push('</table>');
|
paramshtml.push('</table>');
|
||||||
html.push('<td class="s" style="padding:0 5px;">' + paramshtml.join('') + '</td>');
|
html.push('<td class="s" style="padding:0 5px;">' + paramshtml.join('') + '</td>');
|
||||||
html.push('<td>' + action.result.replace(/</g,"<").replace(/>/g,">").replace(/([a-zA-Z0-9_\$]+\.)+/g, "") + '</td>');
|
var rs = [];
|
||||||
|
rs.push(action.result.replace(/</g, "<").replace(/>/g, ">").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>');
|
html.push('</tr>');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,8 +79,20 @@
|
|||||||
html.push(' <tr><td colspan="5"><table class="typetable">');
|
html.push(' <tr><td colspan="5"><table class="typetable">');
|
||||||
for (var fieldname in classmap[type]) {
|
for (var fieldname in classmap[type]) {
|
||||||
var field = classmap[type][fieldname];
|
var field = classmap[type][fieldname];
|
||||||
var t = field.type.replace(/</g,"<").replace(/>/g,">").replace(/([a-zA-Z0-9_\$]+\.)+/g, "");
|
var t = field.type.replace(/</g, "<").replace(/>/g, ">").replace(/\$/g, ".").replace(/([a-zA-Z0-9_\$]+\.)+/g, "");
|
||||||
html.push(' <tr class="l"><td>' + fieldname + '</td><td>' + t + '</td><td colspan="2">' + (field.comment || '') + '</td></tr>');
|
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<') === 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></td></tr>');
|
||||||
}
|
}
|
||||||
@@ -78,7 +103,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var jsoncontent = ${content};
|
var jsoncontent = '${content}'; //这里必须要用单引号引起来
|
||||||
document.write(createhtml(jsoncontent));
|
document.write(createhtml(jsoncontent));
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.lang.reflect.Type;
|
|||||||
/**
|
/**
|
||||||
* 对不明类型的对象进行序列化; BSON序列化时将对象的类名写入Writer,JSON则不写入。
|
* 对不明类型的对象进行序列化; BSON序列化时将对象的类名写入Writer,JSON则不写入。
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 序列化的泛型类型
|
* @param <T> 序列化的泛型类型
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import java.lang.reflect.*;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对象数组的序列化,不包含int[]、long[]这样的primitive class数组.
|
* 数组的反序列化操作类 <br>
|
||||||
* 数组长度不能超过 32767。 在BSON中数组长度设定的是short,对于大于32767长度的数组传输会影响性能,所以没有采用int存储。
|
* 对象数组的反序列化,不包含int[]、long[]这样的primitive class数组。 <br>
|
||||||
* 支持一定程度的泛型。
|
* 支持一定程度的泛型。 <br>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 反解析的数组元素类型
|
* @param <T> 反解析的数组元素类型
|
||||||
@@ -28,31 +28,53 @@ public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
|||||||
|
|
||||||
private final Class componentClass;
|
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) {
|
public ArrayDecoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
if (type instanceof GenericArrayType) {
|
try {
|
||||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
if (type instanceof GenericArrayType) {
|
||||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
Type t = ((GenericArrayType) type).getGenericComponentType();
|
||||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
||||||
this.componentType = ((Class) type).getComponentType();
|
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
||||||
} else {
|
this.componentType = ((Class) type).getComponentType();
|
||||||
throw new ConvertException("(" + type + ") is not a array type");
|
} 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
|
@Override
|
||||||
public T[] convertFrom(Reader in) {
|
public T[] convertFrom(Reader in) {
|
||||||
final int len = in.readArrayB();
|
final int len = in.readArrayB();
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
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 Decodeable<Reader, T> localdecoder = this.decoder;
|
||||||
final List<T> result = new ArrayList();
|
final List<T> result = new ArrayList();
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ package org.redkale.convert;
|
|||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对象数组的反序列化,不包含int[]、long[]这样的primitive class数组.
|
* 数组的序列化操作类 <br>
|
||||||
* 数组长度不能超过 32767。 在BSON中数组长度设定的是short,对于大于32767长度的数组传输会影响性能,所以没有必要采用int存储。
|
* 对象数组的序列化,不包含int[]、long[]这样的primitive class数组。 <br>
|
||||||
* 支持一定程度的泛型。
|
* 支持一定程度的泛型。 <br>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 序列化的数组元素类型
|
* @param <T> 序列化的数组元素类型
|
||||||
@@ -29,19 +29,30 @@ public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
|||||||
|
|
||||||
private final Encodeable<Writer, Object> encoder;
|
private final Encodeable<Writer, Object> encoder;
|
||||||
|
|
||||||
|
private boolean inited = false;
|
||||||
|
|
||||||
|
private final Object lock = new Object();
|
||||||
|
|
||||||
public ArrayEncoder(final ConvertFactory factory, final Type type) {
|
public ArrayEncoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
if (type instanceof GenericArrayType) {
|
try {
|
||||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
if (type instanceof GenericArrayType) {
|
||||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
Type t = ((GenericArrayType) type).getGenericComponentType();
|
||||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
||||||
this.componentType = ((Class) type).getComponentType();
|
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
||||||
} else {
|
this.componentType = ((Class) type).getComponentType();
|
||||||
throw new ConvertException("(" + type + ") is not a array type");
|
} 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
|
@Override
|
||||||
@@ -55,6 +66,17 @@ public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
|||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this.encoder == null) {
|
||||||
|
if (!this.inited) {
|
||||||
|
synchronized (lock) {
|
||||||
|
try {
|
||||||
|
lock.wait();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
out.writeArrayB(value.length);
|
out.writeArrayB(value.length);
|
||||||
final Type comp = this.componentType;
|
final Type comp = this.componentType;
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
|
|||||||
@@ -11,12 +11,11 @@ import java.lang.reflect.Type;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对象集合的反序列化.
|
* Collection的反序列化操作类 <br>
|
||||||
* 集合大小不能超过 32767。 在BSON中集合大小设定的是short,对于大于32767长度的集合传输会影响性能,所以没有采用int存储。
|
* 支持一定程度的泛型。 <br>
|
||||||
* 支持一定程度的泛型。
|
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 反解析的集合元素类型
|
* @param <T> 反解析的集合元素类型
|
||||||
@@ -30,18 +29,29 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
|
|||||||
|
|
||||||
protected Creator<Collection<T>> creator;
|
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) {
|
public CollectionDecoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
if (type instanceof ParameterizedType) {
|
try {
|
||||||
final ParameterizedType pt = (ParameterizedType) type;
|
if (type instanceof ParameterizedType) {
|
||||||
this.componentType = pt.getActualTypeArguments()[0];
|
final ParameterizedType pt = (ParameterizedType) type;
|
||||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
this.componentType = pt.getActualTypeArguments()[0];
|
||||||
factory.register(type, this);
|
this.creator = factory.loadCreator((Class) pt.getRawType());
|
||||||
this.decoder = factory.loadDecoder(this.componentType);
|
factory.register(type, this);
|
||||||
} else {
|
this.decoder = factory.loadDecoder(this.componentType);
|
||||||
throw new ConvertException("collectiondecoder not support the type (" + type + ")");
|
} 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) {
|
public Collection<T> convertFrom(Reader in) {
|
||||||
final int len = in.readArrayB();
|
final int len = in.readArrayB();
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
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 Decodeable<Reader, T> localdecoder = this.decoder;
|
||||||
final Collection<T> result = this.creator.create();
|
final Collection<T> result = this.creator.create();
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ import java.lang.reflect.*;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对象集合的序列化.
|
* Collection的序列化操作类 <br>
|
||||||
* 集合大小不能超过 32767。 在BSON中集合大小设定的是short,对于大于32767长度的集合传输会影响性能,所以没有采用int存储。
|
* 支持一定程度的泛型。 <br>
|
||||||
* 支持一定程度的泛型。
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 序列化的集合元素类型
|
* @param <T> 序列化的集合元素类型
|
||||||
*/
|
*/
|
||||||
@@ -24,17 +25,28 @@ public final class CollectionEncoder<T> implements Encodeable<Writer, Collection
|
|||||||
|
|
||||||
private final Encodeable<Writer, Object> encoder;
|
private final Encodeable<Writer, Object> encoder;
|
||||||
|
|
||||||
|
private boolean inited = false;
|
||||||
|
|
||||||
|
private final Object lock = new Object();
|
||||||
|
|
||||||
public CollectionEncoder(final ConvertFactory factory, final Type type) {
|
public CollectionEncoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
if (type instanceof ParameterizedType) {
|
try {
|
||||||
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
if (type instanceof ParameterizedType) {
|
||||||
if (t instanceof TypeVariable) {
|
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||||
this.encoder = factory.getAnyEncoder();
|
if (t instanceof TypeVariable) {
|
||||||
|
this.encoder = factory.getAnyEncoder();
|
||||||
|
} else {
|
||||||
|
this.encoder = factory.loadEncoder(t);
|
||||||
|
}
|
||||||
} else {
|
} 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();
|
out.writeArrayE();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this.encoder == null) {
|
||||||
|
if (!this.inited) {
|
||||||
|
synchronized (lock) {
|
||||||
|
try {
|
||||||
|
lock.wait();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
out.writeArrayB(value.size());
|
out.writeArrayB(value.size());
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (Object v : value) {
|
for (Object v : value) {
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 序列化操作类
|
* 序列化/反序列化操作类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类
|
* @param <R> Reader输入的子类
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import static java.lang.annotation.RetentionPolicy.*;
|
|||||||
* 依附在setter、getter方法、字段进行简单的配置
|
* 依附在setter、getter方法、字段进行简单的配置
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ package org.redkale.convert;
|
|||||||
/**
|
/**
|
||||||
* ConvertColumn 对应的实体类
|
* ConvertColumn 对应的实体类
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public final class ConvertColumnEntry {
|
public final class ConvertColumnEntry {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import static java.lang.annotation.RetentionPolicy.*;
|
|||||||
/**
|
/**
|
||||||
* ConvertColumn 的多用类
|
* ConvertColumn 的多用类
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@Inherited
|
@Inherited
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用于类名的别名, 类似javax.persistence.Table
|
* 用于类名的别名, 该值必须是全局唯一 <br>
|
||||||
* 该值必须是全局唯一
|
* 使用场景: 当BSON序列化为了不指定class可以使用@ConvertEntity来取个别名。关联方法: Reader.readClassName() 和 Writer.writeClassName(String value) 。
|
||||||
* 使用场景: 当BSON序列化为了不指定class可以使用@ConvertEntity来取个别名。关联方法: Reader.readClassName() 和 Writer.writeClassName(String value) 。
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@Inherited
|
@Inherited
|
||||||
@@ -23,5 +24,10 @@ import java.lang.annotation.*;
|
|||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public @interface ConvertEntity {
|
public @interface ConvertEntity {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 别名值
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
String value();
|
String value();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,11 @@
|
|||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 序列化自定义异常类
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class ConvertException extends RuntimeException {
|
public class ConvertException extends RuntimeException {
|
||||||
|
|||||||
@@ -17,9 +17,10 @@ import org.redkale.convert.ext.*;
|
|||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 序列化模块的工厂类,用于注册自定义的序列化类型,获取Convert
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类
|
* @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(InetSocketAddress.class, InetSocketAddressSimpledCoder.instance);
|
||||||
this.register(Pattern.class, PatternSimpledCoder.instance);
|
this.register(Pattern.class, PatternSimpledCoder.instance);
|
||||||
this.register(CompletionHandler.class, CompletionHandlerSimpledCoder.instance);
|
this.register(CompletionHandler.class, CompletionHandlerSimpledCoder.instance);
|
||||||
|
this.register(AsyncHandler.class, AsyncHandlerSimpledCoder.instance);
|
||||||
this.register(URL.class, URLSimpledCoder.instance);
|
this.register(URL.class, URLSimpledCoder.instance);
|
||||||
this.register(URI.class, URISimpledCoder.instance);
|
this.register(URI.class, URISimpledCoder.instance);
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
@@ -104,6 +106,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
this.register(double[].class, DoubleArraySimpledCoder.instance);
|
this.register(double[].class, DoubleArraySimpledCoder.instance);
|
||||||
this.register(String[].class, StringArraySimpledCoder.instance);
|
this.register(String[].class, StringArraySimpledCoder.instance);
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
|
this.register(AnyValue.class, Creator.create(AnyValue.DefaultAnyValue.class));
|
||||||
this.register(HttpCookie.class, new Creator<HttpCookie>() {
|
this.register(HttpCookie.class, new Creator<HttpCookie>() {
|
||||||
@Override
|
@Override
|
||||||
@Creator.ConstructorParameters({"name", "value"})
|
@Creator.ConstructorParameters({"name", "value"})
|
||||||
|
|||||||
@@ -6,8 +6,11 @@
|
|||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 序列化类型枚举,结合@ConvertColumn使用
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public enum ConvertType {
|
public enum ConvertType {
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ import java.lang.reflect.*;
|
|||||||
import org.redkale.util.Attribute;
|
import org.redkale.util.Attribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 字段的反序列化操作类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类
|
* @param <R> Reader输入的子类
|
||||||
@@ -88,6 +89,6 @@ public final class DeMember<R extends Reader, T, F> implements Comparable<DeMemb
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "DeMember{" + "attribute=" + attribute.field() + ", decoder=" + decoder + '}';
|
return "DeMember{" + "attribute=" + attribute.field() + ", decoder=" + (decoder == null ? null : decoder.getClass().getName()) + '}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ package org.redkale.convert;
|
|||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 反序列化操作类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类
|
* @param <R> Reader输入的子类
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ import java.lang.reflect.*;
|
|||||||
import org.redkale.util.Attribute;
|
import org.redkale.util.Attribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 字段的序列化操作类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <W> Writer输出的子类
|
* @param <W> Writer输出的子类
|
||||||
@@ -81,6 +82,6 @@ public final class EnMember<W extends Writer, T, F> implements Comparable<EnMemb
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "EnMember{" + "attribute=" + attribute.field() + ", encoder=" + encoder + '}';
|
return "EnMember{" + "attribute=" + attribute.field() + ", encoder=" + (encoder == null ? null : encoder.getClass().getName()) + '}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ package org.redkale.convert;
|
|||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 序列化操作类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <W> Writer输出的子类
|
* @param <W> Writer输出的子类
|
||||||
|
|||||||
@@ -11,8 +11,11 @@ import java.lang.reflect.Type;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Map的反序列化操作类 <br>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <K> Map key的数据类型
|
* @param <K> Map key的数据类型
|
||||||
* @param <V> Map value的数据类型
|
* @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;
|
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) {
|
public MapDecoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
if (type instanceof ParameterizedType) {
|
try {
|
||||||
final ParameterizedType pt = (ParameterizedType) type;
|
if (type instanceof ParameterizedType) {
|
||||||
this.keyType = pt.getActualTypeArguments()[0];
|
final ParameterizedType pt = (ParameterizedType) type;
|
||||||
this.valueType = pt.getActualTypeArguments()[1];
|
this.keyType = pt.getActualTypeArguments()[0];
|
||||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
this.valueType = pt.getActualTypeArguments()[1];
|
||||||
factory.register(type, this);
|
this.creator = factory.loadCreator((Class) pt.getRawType());
|
||||||
this.keyDecoder = factory.loadDecoder(this.keyType);
|
factory.register(type, this);
|
||||||
this.valueDecoder = factory.loadDecoder(this.valueType);
|
this.keyDecoder = factory.loadDecoder(this.keyType);
|
||||||
} else {
|
this.valueDecoder = factory.loadDecoder(this.valueType);
|
||||||
throw new ConvertException("mapdecoder not support the type (" + type + ")");
|
} else {
|
||||||
|
throw new ConvertException("mapdecoder not support the type (" + type + ")");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
inited = true;
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<K, V> convertFrom(Reader in) {
|
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();
|
final int len = in.readMapB();
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
final Map<K, V> result = this.creator.create();
|
final Map<K, V> result = this.creator.create();
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ import java.lang.reflect.Type;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Map的序列化操作类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <K> Map key的数据类型
|
* @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 final Encodeable<Writer, V> valencoder;
|
||||||
|
|
||||||
|
private boolean inited = false;
|
||||||
|
|
||||||
|
private final Object lock = new Object();
|
||||||
|
|
||||||
public MapEncoder(final ConvertFactory factory, final Type type) {
|
public MapEncoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
if (type instanceof ParameterizedType) {
|
try {
|
||||||
final Type[] pt = ((ParameterizedType) type).getActualTypeArguments();
|
if (type instanceof ParameterizedType) {
|
||||||
this.keyencoder = factory.loadEncoder(pt[0]);
|
final Type[] pt = ((ParameterizedType) type).getActualTypeArguments();
|
||||||
this.valencoder = factory.loadEncoder(pt[1]);
|
this.keyencoder = factory.loadEncoder(pt[0]);
|
||||||
} else {
|
this.valencoder = factory.loadEncoder(pt[1]);
|
||||||
this.keyencoder = factory.getAnyEncoder();
|
} else {
|
||||||
this.valencoder = factory.getAnyEncoder();
|
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();
|
out.writeNull();
|
||||||
return;
|
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());
|
out.writeMapB(values.size());
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (Map.Entry<K, V> en : values.entrySet()) {
|
for (Map.Entry<K, V> en : values.entrySet()) {
|
||||||
|
|||||||
@@ -13,9 +13,10 @@ import java.util.Set;
|
|||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 自定义对象的反序列化操作类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类
|
* @param <R> Reader输入的子类
|
||||||
@@ -66,7 +67,8 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
clazz = (Class) type;
|
clazz = (Class) type;
|
||||||
}
|
}
|
||||||
this.creator = factory.loadCreator(clazz);
|
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 Set<DeMember> list = new HashSet();
|
||||||
final String[] cps = ObjectEncoder.findConstructorProperties(this.creator);
|
final String[] cps = ObjectEncoder.findConstructorProperties(this.creator);
|
||||||
try {
|
try {
|
||||||
@@ -75,7 +77,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||||
ref = factory.findRef(field);
|
ref = factory.findRef(field);
|
||||||
if (ref != null && ref.ignore()) continue;
|
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)));
|
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, field, null, null), factory.loadDecoder(t)));
|
||||||
}
|
}
|
||||||
final boolean reversible = factory.isReversible();
|
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.isSynthetic()) continue;
|
||||||
if (method.getName().length() < 4) continue;
|
if (method.getName().length() < 4) continue;
|
||||||
if (!method.getName().startsWith("set")) continue;
|
if (!method.getName().startsWith("set")) continue;
|
||||||
|
if (method.getAnnotation(java.beans.Transient.class) != null) continue;
|
||||||
if (method.getParameterTypes().length != 1) continue;
|
if (method.getParameterTypes().length != 1) continue;
|
||||||
if (method.getReturnType() != void.class) continue;
|
if (method.getReturnType() != void.class) continue;
|
||||||
if (reversible && (cps == null || !ObjectEncoder.contains(cps, ConvertFactory.readGetSetFieldName(method)))) {
|
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);
|
ref = factory.findRef(method);
|
||||||
if (ref != null && ref.ignore()) continue;
|
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)));
|
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, null, method), factory.loadDecoder(t)));
|
||||||
}
|
}
|
||||||
if (cps != null) { //可能存在某些构造函数中的字段名不存在setter方法
|
if (cps != null) { //可能存在某些构造函数中的字段名不存在setter方法
|
||||||
@@ -113,7 +116,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
//不存在setter方法
|
//不存在setter方法
|
||||||
try {
|
try {
|
||||||
Field f = clazz.getDeclaredField(constructorField);
|
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)));
|
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, f, null, null), factory.loadDecoder(t)));
|
||||||
} catch (NoSuchFieldException nsfe) { //不存在field, 可能存在getter方法
|
} catch (NoSuchFieldException nsfe) { //不存在field, 可能存在getter方法
|
||||||
char[] fs = constructorField.toCharArray();
|
char[] fs = constructorField.toCharArray();
|
||||||
@@ -125,7 +128,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
} catch (NoSuchMethodException ex) {
|
} catch (NoSuchMethodException ex) {
|
||||||
getter = clazz.getMethod("is" + mn);
|
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)));
|
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, getter, null), factory.loadDecoder(t)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ import java.util.*;
|
|||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 自定义对象的序列化操作类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <W> Writer输出的子类
|
* @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;
|
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||||
ref = factory.findRef(field);
|
ref = factory.findRef(field);
|
||||||
if (ref != null && ref.ignore()) continue;
|
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)));
|
list.add(new EnMember(createAttribute(factory, clazz, field, null, null), factory.loadEncoder(t)));
|
||||||
}
|
}
|
||||||
for (final Method method : clazz.getMethods()) {
|
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().length() < 3) continue;
|
||||||
if (method.getName().equals("getClass")) continue;
|
if (method.getName().equals("getClass")) continue;
|
||||||
if (!method.getName().startsWith("is") && !method.getName().startsWith("get")) 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.getParameterTypes().length != 0) continue;
|
||||||
if (method.getReturnType() == void.class) continue;
|
if (method.getReturnType() == void.class) continue;
|
||||||
if (reversible && (cps == null || !contains(cps, ConvertFactory.readGetSetFieldName(method)))) {
|
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);
|
ref = factory.findRef(method);
|
||||||
if (ref != null && ref.ignore()) continue;
|
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)));
|
list.add(new EnMember(createAttribute(factory, clazz, null, method, null), factory.loadEncoder(t)));
|
||||||
}
|
}
|
||||||
this.members = list.toArray(new EnMember[list.size()]);
|
this.members = list.toArray(new EnMember[list.size()]);
|
||||||
@@ -144,42 +146,6 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
|
|||||||
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
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) {
|
// static Type makeGenericType(final Type type, final Type[] virGenericTypes, final Type[] realGenericTypes) {
|
||||||
// if (type instanceof Class) { //e.g. String
|
// 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;
|
// return type;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
static boolean contains(String[] values, String value) {
|
static boolean contains(String[] values, String value) {
|
||||||
for (String str : values) {
|
for (String str : values) {
|
||||||
if (str.equals(value)) return true;
|
if (str.equals(value)) return true;
|
||||||
|
|||||||
@@ -6,9 +6,10 @@
|
|||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 反序列化的数据读取流
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@@ -42,6 +43,7 @@ public abstract class Reader {
|
|||||||
* 读取对象的类名, 返回 null 表示对象为null, 返回空字符串表示当前class与返回的class一致,返回非空字符串表示class是当前class的子类。
|
* 读取对象的类名, 返回 null 表示对象为null, 返回空字符串表示当前class与返回的class一致,返回非空字符串表示class是当前class的子类。
|
||||||
*
|
*
|
||||||
* @param clazz 类名
|
* @param clazz 类名
|
||||||
|
*
|
||||||
* @return 返回字段数
|
* @return 返回字段数
|
||||||
*/
|
*/
|
||||||
public String readObjectB(final Class clazz) {
|
public String readObjectB(final Class clazz) {
|
||||||
@@ -86,6 +88,7 @@ public abstract class Reader {
|
|||||||
* 根据字段读取字段对应的DeMember
|
* 根据字段读取字段对应的DeMember
|
||||||
*
|
*
|
||||||
* @param members DeMember的全量集合
|
* @param members DeMember的全量集合
|
||||||
|
*
|
||||||
* @return 匹配的DeMember
|
* @return 匹配的DeMember
|
||||||
*/
|
*/
|
||||||
public abstract DeMember readFieldName(final DeMember[] members);
|
public abstract DeMember readFieldName(final DeMember[] members);
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ import java.lang.reflect.ParameterizedType;
|
|||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 简易类的序列化和反序列化操作类 <br>
|
||||||
|
* 能序列化为Boolean、Number或者字符串的类视为简易类 <br>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类
|
* @param <R> Reader输入的子类
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ package org.redkale.convert;
|
|||||||
import org.redkale.util.Attribute;
|
import org.redkale.util.Attribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 序列化的数据输出流
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@@ -37,7 +38,7 @@ public abstract class Writer {
|
|||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public abstract boolean needWriteClassName();
|
public abstract boolean needWriteClassName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 写入类名
|
* 写入类名
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ import static org.redkale.convert.Reader.SIGN_NULL;
|
|||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 以ByteBuffer为数据载体的BsonReader
|
||||||
|
*
|
||||||
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@@ -121,13 +124,13 @@ public class BsonByteBufferReader extends BsonReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ((((long) readByte() & 0xff) << 56)
|
return ((((long) readByte() & 0xff) << 56)
|
||||||
| (((long) readByte() & 0xff) << 48)
|
| (((long) readByte() & 0xff) << 48)
|
||||||
| (((long) readByte() & 0xff) << 40)
|
| (((long) readByte() & 0xff) << 40)
|
||||||
| (((long) readByte() & 0xff) << 32)
|
| (((long) readByte() & 0xff) << 32)
|
||||||
| (((long) readByte() & 0xff) << 24)
|
| (((long) readByte() & 0xff) << 24)
|
||||||
| (((long) readByte() & 0xff) << 16)
|
| (((long) readByte() & 0xff) << 16)
|
||||||
| (((long) readByte() & 0xff) << 8)
|
| (((long) readByte() & 0xff) << 8)
|
||||||
| (((long) readByte() & 0xff)));
|
| (((long) readByte() & 0xff)));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] read(final int len) {
|
protected byte[] read(final int len) {
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ package org.redkale.convert.bson;
|
|||||||
|
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
|
import org.redkale.util.Utility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 以ByteBuffer为数据载体的BsonWriter
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@@ -78,20 +80,14 @@ public class BsonByteBufferWriter extends BsonWriter {
|
|||||||
if (!buffer.hasRemaining()) {
|
if (!buffer.hasRemaining()) {
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
buffer = supplier.get();
|
buffer = supplier.get();
|
||||||
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
|
this.buffers = Utility.append(this.buffers, buffer);
|
||||||
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
|
|
||||||
bufs[this.buffers.length] = buffer;
|
|
||||||
this.buffers = bufs;
|
|
||||||
this.index++;
|
this.index++;
|
||||||
}
|
}
|
||||||
int len = buffer.remaining();
|
int len = buffer.remaining();
|
||||||
int size = 0;
|
int size = 0;
|
||||||
while (len < byteLength) {
|
while (len < byteLength) {
|
||||||
buffer = supplier.get();
|
buffer = supplier.get();
|
||||||
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
|
this.buffers = Utility.append(this.buffers, buffer);
|
||||||
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
|
|
||||||
bufs[this.buffers.length] = buffer;
|
|
||||||
this.buffers = bufs;
|
|
||||||
len += buffer.remaining();
|
len += buffer.remaining();
|
||||||
size++;
|
size++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,25 +15,25 @@ import org.redkale.util.*;
|
|||||||
/**
|
/**
|
||||||
* <blockquote><pre>
|
* <blockquote><pre>
|
||||||
* BSON协议格式:
|
* BSON协议格式:
|
||||||
* 1). 基本数据类型: 直接转换成byte[]
|
* 1) 基本数据类型: 直接转换成byte[]
|
||||||
* 2). SmallString(无特殊字符且长度小于256的字符串): length(1 byte) + byte[](utf8); 通常用于类名、字段名、枚举。
|
* 2) SmallString(无特殊字符且长度小于256的字符串): length(1 byte) + byte[](utf8); 通常用于类名、字段名、枚举。
|
||||||
* 3). String: length(4 bytes) + byte[](utf8);
|
* 3) String: length(4 bytes) + byte[](utf8);
|
||||||
* 4). 数组: length(4 bytes) + byte[]...
|
* 4) 数组: length(4 bytes) + byte[]...
|
||||||
* 5). Object:
|
* 5) Object:
|
||||||
* 1. realclass (SmallString) (如果指定格式化的class与实体对象的class不一致才会有该值, 该值可以使用@ConvertEntity给其取个别名)
|
* 1、 realclass (SmallString) (如果指定格式化的class与实体对象的class不一致才会有该值, 该值可以使用@ConvertEntity给其取个别名)
|
||||||
* 2. 空字符串(SmallString)
|
* 2、 空字符串(SmallString)
|
||||||
* 3. SIGN_OBJECTB 标记位,值固定为0xBB (short)
|
* 3、 SIGN_OBJECTB 标记位,值固定为0xBB (short)
|
||||||
* 4. 循环字段值:
|
* 4、 循环字段值:
|
||||||
* 4.1 SIGN_HASNEXT 标记位,值固定为1 (byte)
|
* 4.1 SIGN_HASNEXT 标记位,值固定为1 (byte)
|
||||||
* 4.2 字段类型; 1-9为基本类型和字符串; 101-109为基本类型和字符串的数组; 127为Object
|
* 4.2 字段类型; 1-9为基本类型和字符串; 101-109为基本类型和字符串的数组; 127为Object
|
||||||
* 4.3 字段名 (SmallString)
|
* 4.3 字段名 (SmallString)
|
||||||
* 4.4 字段的值Object
|
* 4.4 字段的值Object
|
||||||
* 5. SIGN_NONEXT 标记位,值固定为0 (byte)
|
* 5、 SIGN_NONEXT 标记位,值固定为0 (byte)
|
||||||
* 6. SIGN_OBJECTE 标记位,值固定为0xEE (short)
|
* 6、 SIGN_OBJECTE 标记位,值固定为0xEE (short)
|
||||||
*
|
*
|
||||||
* </pre></blockquote>
|
* </pre></blockquote>
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ package org.redkale.convert.bson;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import org.redkale.convert.*;
|
import org.redkale.convert.*;
|
||||||
|
import org.redkale.util.AnyValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* BSON的ConvertFactory
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@@ -27,6 +29,9 @@ public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
|
|||||||
static {
|
static {
|
||||||
instance.register(Serializable.class, objectDecoder);
|
instance.register(Serializable.class, objectDecoder);
|
||||||
instance.register(Serializable.class, objectEncoder);
|
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) {
|
private BsonFactory(BsonFactory parent, boolean tiny) {
|
||||||
|
|||||||
@@ -5,16 +5,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.convert.bson;
|
package org.redkale.convert.bson;
|
||||||
|
|
||||||
import java.util.function.*;
|
|
||||||
import org.redkale.convert.*;
|
import org.redkale.convert.*;
|
||||||
import static org.redkale.convert.Reader.SIGN_NULL;
|
import static org.redkale.convert.Reader.SIGN_NULL;
|
||||||
import org.redkale.convert.ext.*;
|
import org.redkale.convert.ext.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* BSON数据源
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@@ -42,19 +42,7 @@ public class BsonReader extends Reader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static ObjectPool<BsonReader> createPool(int max) {
|
public static ObjectPool<BsonReader> createPool(int max) {
|
||||||
return new ObjectPool<BsonReader>(max, new Creator<BsonReader>() {
|
return new ObjectPool<>(max, (Object... params) -> new BsonReader(), null, (t) -> t.recycle());
|
||||||
|
|
||||||
@Override
|
|
||||||
public BsonReader create(Object... params) {
|
|
||||||
return new BsonReader();
|
|
||||||
}
|
|
||||||
}, null, new Predicate<BsonReader>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(BsonReader t) {
|
|
||||||
return t.recycle();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BsonReader(byte[] bytes) {
|
public BsonReader(byte[] bytes) {
|
||||||
@@ -164,7 +152,7 @@ public class BsonReader extends Reader {
|
|||||||
if (bt == Reader.SIGN_NULL) return null;
|
if (bt == Reader.SIGN_NULL) return null;
|
||||||
if (bt != SIGN_OBJECTB) {
|
if (bt != SIGN_OBJECTB) {
|
||||||
throw new ConvertException("a bson object must begin with " + (SIGN_OBJECTB)
|
throw new ConvertException("a bson object must begin with " + (SIGN_OBJECTB)
|
||||||
+ " (position = " + position + ") but '" + currentByte() + "'");
|
+ " (position = " + position + ") but '" + currentByte() + "'");
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -173,7 +161,7 @@ public class BsonReader extends Reader {
|
|||||||
public final void readObjectE(final Class clazz) {
|
public final void readObjectE(final Class clazz) {
|
||||||
if (readShort() != SIGN_OBJECTE) {
|
if (readShort() != SIGN_OBJECTE) {
|
||||||
throw new ConvertException("a bson object must end with " + (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();
|
byte b = readByte();
|
||||||
if (b == SIGN_HASNEXT) return true;
|
if (b == SIGN_HASNEXT) return true;
|
||||||
if (b != SIGN_NONEXT) throw new ConvertException("hasNext option must be (" + (SIGN_HASNEXT)
|
if (b != SIGN_NONEXT) throw new ConvertException("hasNext option must be (" + (SIGN_HASNEXT)
|
||||||
+ " or " + (SIGN_NONEXT) + ") but '" + b + "' at position(" + this.position + ")");
|
+ " or " + (SIGN_NONEXT) + ") but '" + b + "' at position(" + this.position + ")");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,19 +260,19 @@ public class BsonReader extends Reader {
|
|||||||
@Override
|
@Override
|
||||||
public int readInt() {
|
public int readInt() {
|
||||||
return ((content[++this.position] & 0xff) << 24) | ((content[++this.position] & 0xff) << 16)
|
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
|
@Override
|
||||||
public long readLong() {
|
public long readLong() {
|
||||||
return ((((long) content[++this.position] & 0xff) << 56)
|
return ((((long) content[++this.position] & 0xff) << 56)
|
||||||
| (((long) content[++this.position] & 0xff) << 48)
|
| (((long) content[++this.position] & 0xff) << 48)
|
||||||
| (((long) content[++this.position] & 0xff) << 40)
|
| (((long) content[++this.position] & 0xff) << 40)
|
||||||
| (((long) content[++this.position] & 0xff) << 32)
|
| (((long) content[++this.position] & 0xff) << 32)
|
||||||
| (((long) content[++this.position] & 0xff) << 24)
|
| (((long) content[++this.position] & 0xff) << 24)
|
||||||
| (((long) content[++this.position] & 0xff) << 16)
|
| (((long) content[++this.position] & 0xff) << 16)
|
||||||
| (((long) content[++this.position] & 0xff) << 8)
|
| (((long) content[++this.position] & 0xff) << 8)
|
||||||
| (((long) content[++this.position] & 0xff)));
|
| (((long) content[++this.position] & 0xff)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import org.redkale.convert.SimpledCoder;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 序列化/反解析的数据类型
|
* @param <T> 序列化/反解析的数据类型
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import java.io.*;
|
|||||||
import org.redkale.convert.*;
|
import org.redkale.convert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import java.io.*;
|
|||||||
import org.redkale.convert.*;
|
import org.redkale.convert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,14 +6,13 @@
|
|||||||
package org.redkale.convert.bson;
|
package org.redkale.convert.bson;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.function.Predicate;
|
|
||||||
import org.redkale.convert.*;
|
import org.redkale.convert.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@@ -28,19 +27,7 @@ public class BsonWriter extends Writer {
|
|||||||
protected boolean tiny;
|
protected boolean tiny;
|
||||||
|
|
||||||
public static ObjectPool<BsonWriter> createPool(int max) {
|
public static ObjectPool<BsonWriter> createPool(int max) {
|
||||||
return new ObjectPool<BsonWriter>(max, new Creator<BsonWriter>() {
|
return new ObjectPool<>(max, (Object... params) -> new BsonWriter(), null, (t) -> t.recycle());
|
||||||
|
|
||||||
@Override
|
|
||||||
public BsonWriter create(Object... params) {
|
|
||||||
return new BsonWriter();
|
|
||||||
}
|
|
||||||
}, null, new Predicate<BsonWriter>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(BsonWriter t) {
|
|
||||||
return t.recycle();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] toArray() {
|
public byte[] toArray() {
|
||||||
@@ -82,6 +69,7 @@ public class BsonWriter extends Writer {
|
|||||||
* 扩充指定长度的缓冲区
|
* 扩充指定长度的缓冲区
|
||||||
*
|
*
|
||||||
* @param len 扩容长度
|
* @param len 扩容长度
|
||||||
|
*
|
||||||
* @return 固定0
|
* @return 固定0
|
||||||
*/
|
*/
|
||||||
protected int expand(int len) {
|
protected int expand(int len) {
|
||||||
@@ -248,11 +236,11 @@ public class BsonWriter extends Writer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char[] chars = Utility.charArray(value);
|
char[] chars = Utility.charArray(value);
|
||||||
if (chars.length > 255) throw new ConvertException("'" + value + "' has very long length");
|
if (chars.length > 255) throw new ConvertException("'" + value + "' have very long length");
|
||||||
byte[] bytes = new byte[chars.length + 1];
|
byte[] bytes = new byte[chars.length + 1];
|
||||||
bytes[0] = (byte) chars.length;
|
bytes[0] = (byte) chars.length;
|
||||||
for (int i = 0; i < chars.length; i++) {
|
for (int i = 0; i < chars.length; i++) {
|
||||||
if (chars[i] > Byte.MAX_VALUE) throw new ConvertException("'" + value + "' has double-word");
|
if (chars[i] > Byte.MAX_VALUE) throw new ConvertException("'" + value + "' have double-word");
|
||||||
bytes[i + 1] = (byte) chars[i];
|
bytes[i + 1] = (byte) chars[i];
|
||||||
}
|
}
|
||||||
writeTo(bytes);
|
writeTo(bytes);
|
||||||
|
|||||||
36
src/org/redkale/convert/ext/AsyncHandlerSimpledCoder.java
Normal file
36
src/org/redkale/convert/ext/AsyncHandlerSimpledCoder.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ import java.math.BigInteger;
|
|||||||
* BigInteger 的SimpledCoder实现
|
* BigInteger 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
|||||||
* boolean[] 的SimpledCoder实现
|
* boolean[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
|||||||
* boolean 的SimpledCoder实现
|
* boolean 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
|||||||
* byte[] 的SimpledCoder实现
|
* byte[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
|||||||
* byte 的SimpledCoder实现
|
* byte 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* char[] 的SimpledCoder实现
|
* char[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import org.redkale.convert.*;
|
|||||||
/**
|
/**
|
||||||
* CharSequence 的SimpledCoder实现
|
* CharSequence 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* char 的SimpledCoder实现
|
* char 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.redkale.convert.*;
|
|||||||
* java.nio.channels.CompletionHandler 的SimpledCoder实现, 只输出null
|
* java.nio.channels.CompletionHandler 的SimpledCoder实现, 只输出null
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import org.redkale.util.*;
|
|||||||
* Dlong 的SimpledCoder实现
|
* Dlong 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import java.util.Date;
|
|||||||
* Date 的SimpledCoder实现
|
* Date 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* double[] 的SimpledCoder实现
|
* double[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* double 的SimpledCoder实现
|
* double 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
|||||||
* 枚举 的SimpledCoder实现
|
* 枚举 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* float[] 的SimpledCoder实现
|
* float[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* float 的SimpledCoder实现
|
* float 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import java.net.*;
|
|||||||
* InetAddress 的SimpledCoder实现
|
* InetAddress 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* int[] 的SimpledCoder实现
|
* int[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* int 的SimpledCoder实现
|
* int 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
|||||||
* long[] 的SimpledCoder实现
|
* long[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* long 的SimpledCoder实现
|
* long 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
|||||||
* Number 的SimpledCoder实现
|
* Number 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import org.redkale.convert.*;
|
|||||||
/**
|
/**
|
||||||
* Pattern 的SimpledCoder实现
|
* Pattern 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* short[] 的SimpledCoder实现
|
* short[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* short 的SimpledCoder实现
|
* short 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* String[] 的SimpledCoder实现
|
* String[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* String 的SimpledCoder实现
|
* String 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: http://redkale.org
|
* <p> 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import org.redkale.convert.SimpledCoder;
|
|||||||
* Type 的SimpledCoder实现 只支持Type的子类Class
|
* Type 的SimpledCoder实现 只支持Type的子类Class
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
@@ -38,7 +38,7 @@ public class TypeSimpledCoder<R extends Reader, W extends Writer> extends Simple
|
|||||||
if (str == null) return null;
|
if (str == null) return null;
|
||||||
try {
|
try {
|
||||||
return Class.forName(str);
|
return Class.forName(str);
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import org.redkale.convert.*;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import org.redkale.convert.*;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
|
|||||||
@@ -11,8 +11,12 @@ import org.redkale.convert.*;
|
|||||||
import static org.redkale.convert.Reader.*;
|
import static org.redkale.convert.Reader.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 以ByteBuffer为数据载体的JsonReader <br>
|
||||||
|
*
|
||||||
* 只支持UTF-8格式
|
* 只支持UTF-8格式
|
||||||
*
|
*
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class JsonByteBufferReader extends JsonReader {
|
public class JsonByteBufferReader extends JsonReader {
|
||||||
|
|||||||
@@ -13,9 +13,10 @@ import org.redkale.convert.*;
|
|||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 以ByteBuffer为数据载体的JsonWriter
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@@ -84,20 +85,14 @@ public class JsonByteBufferWriter extends JsonWriter {
|
|||||||
if (!buffer.hasRemaining()) {
|
if (!buffer.hasRemaining()) {
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
buffer = supplier.get();
|
buffer = supplier.get();
|
||||||
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
|
this.buffers = Utility.append(this.buffers, buffer);
|
||||||
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
|
|
||||||
bufs[this.buffers.length] = buffer;
|
|
||||||
this.buffers = bufs;
|
|
||||||
this.index++;
|
this.index++;
|
||||||
}
|
}
|
||||||
int len = buffer.remaining();
|
int len = buffer.remaining();
|
||||||
int size = 0;
|
int size = 0;
|
||||||
while (len < byteLength) {
|
while (len < byteLength) {
|
||||||
buffer = supplier.get();
|
buffer = supplier.get();
|
||||||
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
|
this.buffers = Utility.append(this.buffers, buffer);
|
||||||
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
|
|
||||||
bufs[this.buffers.length] = buffer;
|
|
||||||
this.buffers = bufs;
|
|
||||||
len += buffer.remaining();
|
len += buffer.remaining();
|
||||||
size++;
|
size++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import org.redkale.util.*;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -10,12 +10,13 @@ import java.math.BigInteger;
|
|||||||
import java.net.*;
|
import java.net.*;
|
||||||
import org.redkale.convert.*;
|
import org.redkale.convert.*;
|
||||||
import org.redkale.convert.ext.*;
|
import org.redkale.convert.ext.*;
|
||||||
import org.redkale.util.DLong;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* JSON的ConvertFactory
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@@ -29,6 +30,9 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
|
|||||||
instance.register(DLong.class, DLongSimpledCoder.DLongJsonSimpledCoder.instance);
|
instance.register(DLong.class, DLongSimpledCoder.DLongJsonSimpledCoder.instance);
|
||||||
instance.register(BigInteger.class, BigIntegerSimpledCoder.BigIntegerJsonSimpledCoder.instance);
|
instance.register(BigInteger.class, BigIntegerSimpledCoder.BigIntegerJsonSimpledCoder.instance);
|
||||||
instance.register(Serializable.class, instance.loadEncoder(Object.class));
|
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) {
|
private JsonFactory(JsonFactory parent, boolean tiny) {
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ import static org.redkale.convert.Reader.*;
|
|||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* JSON数据源
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import org.redkale.convert.SimpledCoder;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 序列化/反解析的数据类型
|
* @param <T> 序列化/反解析的数据类型
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import org.redkale.convert.*;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
class JsonStreamReader extends JsonByteBufferReader {
|
class JsonStreamReader extends JsonByteBufferReader {
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import org.redkale.util.*;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
class JsonStreamWriter extends JsonByteBufferWriter {
|
class JsonStreamWriter extends JsonByteBufferWriter {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import org.redkale.util.*;
|
|||||||
*
|
*
|
||||||
* writeTo系列的方法输出的字符不能含特殊字符
|
* writeTo系列的方法输出的字符不能含特殊字符
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import java.util.concurrent.*;
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: http://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user