Compare commits
281 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
54b7863be6 | ||
|
|
26453fe4c5 | ||
|
|
036b248092 | ||
|
|
8ca79face5 | ||
|
|
6fd3250fba | ||
|
|
93a213448a | ||
|
|
e12cf185d9 | ||
|
|
ca6c90eacd | ||
|
|
8901dd9a07 | ||
|
|
93fef97c56 | ||
|
|
ddef9018e2 | ||
|
|
fb51997c6b | ||
|
|
65da7118fc | ||
|
|
fc2dfa1a8a | ||
|
|
68db4e37e2 | ||
|
|
28c9b2606a | ||
|
|
d47b63e47b | ||
|
|
7f86972fa1 | ||
|
|
92eefc872a | ||
|
|
c43e516d14 | ||
|
|
8884fabf90 | ||
|
|
1720470424 | ||
|
|
1da2e95f46 | ||
|
|
940af0b251 | ||
|
|
43102b9d35 | ||
|
|
fa601c69e7 | ||
|
|
b365b18be0 | ||
|
|
bc8a52eef8 | ||
|
|
afa45498d4 | ||
|
|
6f056bbcb6 | ||
|
|
4fb218fd18 | ||
|
|
1e7575c7b7 | ||
|
|
02fd74f6de | ||
|
|
77732347d0 | ||
|
|
53eaad17ea | ||
|
|
4cdc1f82c5 | ||
|
|
77c2f72b42 | ||
|
|
469069d2ac | ||
|
|
d7542a0c0a | ||
|
|
15d36735da | ||
|
|
d3163a6e0d | ||
|
|
23fd664eef | ||
|
|
f21cb2c233 | ||
|
|
0a2a9f0e80 | ||
|
|
9b74f46b22 | ||
|
|
59ca4afd8b | ||
|
|
bc1c749152 | ||
|
|
d35987612d | ||
|
|
04b5b361ad | ||
|
|
a81c9f7d21 | ||
|
|
2c75c04b7e | ||
|
|
9bf5044654 | ||
|
|
e99fd3c049 | ||
|
|
4e9b3f45fc | ||
|
|
95f4cd0634 | ||
|
|
a43f9a0121 | ||
|
|
6f6952ad2c | ||
|
|
21cfbebe26 | ||
|
|
f16beca680 | ||
|
|
1341e81361 | ||
|
|
f08a29b15a | ||
|
|
fea5123915 | ||
|
|
cd45cafec5 | ||
|
|
bed86d44a1 | ||
|
|
bd3ae4bb41 | ||
|
|
589d34d8a4 | ||
|
|
a455795703 | ||
|
|
fbb9cdefe1 | ||
|
|
d202b2fbad | ||
|
|
9d82ca84a4 | ||
|
|
1f0e0accb1 | ||
|
|
fa8e40f6c0 | ||
|
|
1a22cd0fe1 | ||
|
|
8422173411 | ||
|
|
c63248ba7f | ||
|
|
de4dda7c73 | ||
|
|
e546ff74a5 | ||
|
|
506f930320 | ||
|
|
09beaedee8 | ||
|
|
40845f5f60 | ||
|
|
f3f001d72d | ||
|
|
b49a4d2c83 | ||
|
|
90884f4621 | ||
|
|
c2fd7be5e2 | ||
|
|
b1773107a1 | ||
|
|
f6aa646ea4 | ||
|
|
72887106ea | ||
|
|
aa6126ddec | ||
|
|
a98a35b4af | ||
|
|
07253b1f17 | ||
|
|
48a4c6d53c | ||
|
|
d78c08878c | ||
|
|
d40ea81fc3 | ||
|
|
78ac88b57c | ||
|
|
3595f8b6bc | ||
|
|
1421b83e49 | ||
|
|
90361edba1 | ||
|
|
3d3347b64f | ||
|
|
f8a439e21f | ||
|
|
9d76e693fb | ||
|
|
a206ecd76b | ||
|
|
81f386dcdb | ||
|
|
e8e6459679 | ||
|
|
9f5ab4b068 | ||
|
|
1ea816a60e | ||
|
|
2c5876ba3e | ||
|
|
cffe181344 | ||
|
|
4647545ff5 | ||
|
|
bfe78a805e | ||
|
|
c480b2b18e | ||
|
|
7e9885de2e | ||
|
|
db32656c8a | ||
|
|
b981307768 | ||
|
|
b0e0a341ec | ||
|
|
40ef40b813 | ||
|
|
dfacd49a70 | ||
|
|
470a82b6e6 | ||
|
|
d5a752dea0 | ||
|
|
554932201b | ||
|
|
54462e8c26 | ||
|
|
d9807148db | ||
|
|
66a5fc2447 | ||
|
|
4f9c8ce145 | ||
|
|
884cc930c8 | ||
|
|
cd4b18ad45 | ||
|
|
707fc783b5 | ||
|
|
3ca6ad6e12 | ||
|
|
4972f5804e | ||
|
|
aec69d2973 | ||
|
|
3f2a7f684f | ||
|
|
ce9f517244 | ||
|
|
192e52f18f | ||
|
|
cdbe53d3d9 | ||
|
|
58f4f28e14 | ||
|
|
bc19d75422 |
@@ -8,17 +8,17 @@
|
||||
<li>提供HTTP服务,同时内置JSON功能与限时缓存功能</li>
|
||||
<li>TCP层完全使用NIO.2,并统一TCP与UDP的接口换</li>
|
||||
<li>提供分布式与集中式部署的无缝切换</li>
|
||||
<li>提供类似JPA功能,并包含数据缓存自动同步与简洁的数据层操作接口</li>
|
||||
<li>提供类似JPA功能,包含数据缓存自动同步、分表分库与简洁的数据层操作接口</li>
|
||||
<li>可以动态修改已依赖注入的资源</li>
|
||||
</ol>
|
||||
|
||||
<strong>Redkale 设计理念</strong>
|
||||
<p>
|
||||
作为一个全新的微服务框架,不仅是使用了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显得很简单,这也是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在接口定义上使用了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,除了负载均衡还能静动分离,因此HTTPS的加解密应交给nginx这样的高性能服务器处理。Redkale再提供HTTPS服务就显得鸡肋。JSP其实算是一个落后的技术,现在是一个多样化终端的时代,终端不只局限于桌面程序和PC浏览器,还有原生App、混合式App、微信端、移动H5、提供第三方接口等各种形式的终端,这些都不是JSP能方便兼顾的,而HTTP+JSON作为通用性接口可以避免重复开发,模版引擎的功能加上各种强大的JS框架足以取代JSP。Redkale在功能上做了筛选,不会为了迎合主流而提供,而是以良好的设计思想为指导。这是Redkale的主导思维。
|
||||
</p>
|
||||
|
||||
|
||||
由于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>
|
||||
|
||||
7
bin/apidoc.bat
Normal file
7
bin/apidoc.bat
Normal file
@@ -0,0 +1,7 @@
|
||||
@ECHO OFF
|
||||
|
||||
SET APP_HOME=%~dp0
|
||||
|
||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||
|
||||
java -DCMD=APIDOC -DAPP_HOME=%APP_HOME% -classpath %APP_HOME%\lib\* org.redkale.boot.Application
|
||||
18
bin/apidoc.sh
Normal file
18
bin/apidoc.sh
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
export LC_ALL="zh_CN.UTF-8"
|
||||
|
||||
APP_HOME=`dirname "$0"`
|
||||
|
||||
if [ ! -a "$APP_HOME"/conf/application.xml ]; then
|
||||
APP_HOME="$APP_HOME"/..
|
||||
fi
|
||||
|
||||
lib='.'
|
||||
for jar in `ls $APP_HOME/lib/*.jar`
|
||||
do
|
||||
lib=$lib:$jar
|
||||
done
|
||||
export CLASSPATH=$CLASSPATH:$lib
|
||||
echo "$APP_HOME"
|
||||
java -DCMD=APIDOC -DAPP_HOME="$APP_HOME" org.redkale.boot.Application
|
||||
@@ -4,4 +4,4 @@ SET APP_HOME=%~dp0
|
||||
|
||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||
|
||||
java -DSHUTDOWN=true -DAPP_HOME=%APP_HOME% -classpath %APP_HOME%\lib\* org.redkale.boot.Application
|
||||
java -DCMD=SHUTDOWN -DAPP_HOME=%APP_HOME% -classpath %APP_HOME%\lib\* org.redkale.boot.Application
|
||||
|
||||
@@ -15,4 +15,4 @@ do
|
||||
done
|
||||
export CLASSPATH=$CLASSPATH:$lib
|
||||
echo "$APP_HOME"
|
||||
java -DSHUTDOWN=true -DAPP_HOME="$APP_HOME" org.redkale.boot.Application
|
||||
java -DCMD=SHUTDOWN -DAPP_HOME="$APP_HOME" org.redkale.boot.Application
|
||||
|
||||
296
pom.xml
296
pom.xml
@@ -1,158 +1,140 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.redkale</groupId>
|
||||
<artifactId>redkale</artifactId>
|
||||
<name>Redkale</name>
|
||||
<packaging>jar</packaging>
|
||||
<url>http://redkale.org</url>
|
||||
<!-- -SNAPSHOT
|
||||
mvn clean deploy -P release -Dgpg.passphrase=password
|
||||
mvn release:clean release:prepare release:perform
|
||||
-->
|
||||
<version>1.0.0-rc1</version>
|
||||
|
||||
<description>Redkale is a Microservices Framework written in Java</description>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
<compilerArguments>
|
||||
<verbose />
|
||||
<bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>org.redkale.boot.Application</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.3</version>
|
||||
<configuration>
|
||||
<charset>${file_encoding}</charset>
|
||||
<encoding>${file_encoding}</encoding>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-compiler-javac</artifactId>
|
||||
<version>2.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-utils</artifactId>
|
||||
<version>3.0.22</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>release-sign-artifacts</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>performRelease</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<scm>
|
||||
<url>https://github.com/redkale/redkale/tags/redkale-1.0.0-rc1</url>
|
||||
<connection>scm:svn:https://github.com/redkale/redkale/tags/redkale-1.0.0-rc1</connection>
|
||||
</scm>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>redkale</id>
|
||||
<name>redkale</name>
|
||||
<email>redkale@qq.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache 2</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
<comments>A business-friendly OSS license</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.redkale</groupId>
|
||||
<artifactId>redkale</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<url>http://redkale.org</url>
|
||||
<description>redkale -- java framework</description>
|
||||
<version>1.4.0-SNAPSHOT</version>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache 2</name>
|
||||
<url>http://www.apache.org/licenses/</url>
|
||||
<distribution>repo</distribution>
|
||||
<comments>Apache License</comments>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>Redkale</id>
|
||||
<name>redkale</name>
|
||||
<email>redkale@qq.com</email>
|
||||
<url>http://redkale.org</url>
|
||||
<roles>
|
||||
<role>Project Manager</role>
|
||||
<role>Architect</role>
|
||||
</roles>
|
||||
<organization>redkale</organization>
|
||||
<organizationUrl>http://redkale.org</organizationUrl>
|
||||
<properties>
|
||||
<dept>No</dept>
|
||||
</properties>
|
||||
<timezone>8</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
<name>Redkale</name>
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
<scm>
|
||||
<url>https://github.com/redkale/redkale</url>
|
||||
<connection>scm:git:git@github.com/redkale/redkale.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:redkale/redkale.git</developerConnection>
|
||||
</scm>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
<compilerArguments>
|
||||
<verbose />
|
||||
<bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>org.redkale.boot.Application</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-compiler-javac</artifactId>
|
||||
<version>2.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-utils</artifactId>
|
||||
<version>3.0.22</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -2,6 +2,7 @@
|
||||
<!--
|
||||
文件说明:
|
||||
${APP_HOME} 指当前程序的根目录APP_HOME
|
||||
没注明唯一的节点可多个存在
|
||||
required: 被声明required的属性值不能为空
|
||||
|
||||
group
|
||||
@@ -18,27 +19,31 @@
|
||||
serviceid1_name1 serviceid1_name2 serviceid2_name1 serviceid2_name2
|
||||
-->
|
||||
<!--
|
||||
address: 本地的IP地址, 默认值为默认网卡的ip,当不使用默认值需要指定值,如127.0.0.1
|
||||
address: 本地局域网的IP地址, 默认值为默认网卡的ip,当不使用默认值需要指定值,如192.168.1.22
|
||||
port: required 程序的管理Server的端口,用于关闭或者与监管系统进行数据交互
|
||||
host: 程序的管理Server的地址; 默认为127.0.0.1。
|
||||
lib: 加上额外的lib路径,多个路径用分号;隔开; 默认为空。 例如: ${APP_HOME}/lib/a.jar;${APP_HOME}/lib2/b.jar;
|
||||
-->
|
||||
<application port="6560" lib="">
|
||||
|
||||
<!-- 所有服务所需的资源 -->
|
||||
<!--
|
||||
【节点全局唯一】
|
||||
所有服务所需的资源
|
||||
-->
|
||||
<resources>
|
||||
<!--
|
||||
【节点全局唯一】
|
||||
transport节点只能有一个,用于配置所有Transport的池参数,没配置该节点将自动创建一个。
|
||||
threads: 线程总数, 默认: <group>节点数*CPU核数*8
|
||||
bufferCapacity: ByteBuffer的初始化大小, 默认: 8K;
|
||||
bufferPoolSize: ByteBuffer池的大小,默认: <group>节点数*CPU核数*8
|
||||
-->
|
||||
<transport capacity="8192" bufferPoolSize="32" threads="32"/>
|
||||
<transport bufferCapacity="8K" bufferPoolSize="32" threads="32"/>
|
||||
<!--
|
||||
一个组包含多个NODE, 同一Service服务可以由多个进程提供,这些进程称为一个GROUP,且同一GROUP内的进程必须在同一机房或局域网内
|
||||
一个group节点对应一个 Transport 对象。
|
||||
name: 服务组ID,长度不能超过11个字节. 默认为空字符串。 注意: name不能包含$符号。
|
||||
protocol:值只能是UDP TCP, 默认TCP
|
||||
kind: 与SNCP服务连接时的数据传输类型;可选值有:rest(不区分大小写);值为空或空字符串表示按SNCP协议传输; 为rest表示按REST传输。默认值为空
|
||||
注意: 一个node只能所属一个group。只要存在protocol=SNCP的Server节点信息, 就必须有group节点信息。
|
||||
-->
|
||||
<group name="" protocol="TCP">
|
||||
@@ -53,6 +58,7 @@
|
||||
<node addr="127.0.0.1" port="7070"/>
|
||||
</group>
|
||||
<!--
|
||||
【节点全局唯一】
|
||||
全局的参数配置, 可以通过@Resource(name="property.xxxxxx") 进行注入, 被注解的字段类型只能是String、primitive class
|
||||
如果name是system.property.开头的值将会在进程启动时进行System.setProperty("yyyy", "YYYYYY")操作。
|
||||
如果name是mimetype.property.开头的值将会在进程启动时进行MimeType.add("yyyy", "YYYYYY")操作。
|
||||
@@ -78,7 +84,8 @@
|
||||
host: 服务所占address , 默认: 0.0.0.0
|
||||
port: required 服务所占端口
|
||||
root: 如果是web类型服务,则包含页面 默认:{APP_HOME}/root
|
||||
lib: server额外的class目录, 默认为空
|
||||
lib: server额外的class目录, 默认为空
|
||||
excludelibs: 排除lib.path与excludes中的正则表达式匹配的路径, 多个正则表达式用分号;隔开
|
||||
charset: 文本编码, 默认: UTF-8
|
||||
backlog: 默认10K
|
||||
threads: 线程总数, 默认: CPU核数*16
|
||||
@@ -121,7 +128,25 @@
|
||||
</service>
|
||||
</services>
|
||||
|
||||
<!--
|
||||
REST的核心配置项
|
||||
当Server为HTTP协议时, rest节点才有效。存在[rest]节点则Server启动时会加载REST服务, 节点可以多个
|
||||
base: REST服务的BaseServlet,必须是 org.redkale.net.http.RestHttpServlet 的子类,该属性值默认值为 org.redkale.net.http.DefaultRestServlet。
|
||||
autoload:默认值"true" 默认值. 加载当前server所能使用的Servce对象;
|
||||
mustsign:默认值"true" 是否只加载标记为RestService的Service类,默认只加载标记RestService且ignore=false的Service
|
||||
includes:当autoload="true", 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
|
||||
excludes:当autoload="true", 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
|
||||
-->
|
||||
<rest base="org.redkale.net.http.DefaultRestServlet" mustsign="true" autoload="true" includes="" excludes="">
|
||||
<!--
|
||||
value: Service类名,列出的表示必须被加载的Service对象
|
||||
ignore: 是否忽略,设置为true则不会加载该Service对象,默认值为false
|
||||
-->
|
||||
<service value="com.xxx.XXXXService"/>
|
||||
</rest>
|
||||
|
||||
<!--
|
||||
【节点在<server>中唯一】
|
||||
当Server为HTTP协议时, request节点才有效。
|
||||
remoteaddr 节点: 替换请求方节点的IP地址, 通常请求方是由nginx等web静态服务器转发过的则需要配置该节点。
|
||||
且value值只能是以request.headers.开头,表示从request.headers中获取对应的header值。
|
||||
@@ -132,6 +157,7 @@
|
||||
</request>
|
||||
|
||||
<!--
|
||||
【节点在<server>中唯一】
|
||||
当Server为HTTP协议时, response节点才有效。
|
||||
defcookie 节点: 当response里输出的cookie没有指定domain 和path时,使用该节点的默认值。
|
||||
如果addheader、setheader 的value值以request.parameters.开头则表示从request.parameters中获取对应的parameter值
|
||||
@@ -144,6 +170,31 @@
|
||||
<setheader name="Access-Control-Allow-Credentials" value="true"/>
|
||||
</response>
|
||||
|
||||
<!--
|
||||
【节点在<server>中唯一】
|
||||
当Server为HTTP协议时,ResourceServlet才有效. 默认存在一个有默认属性的resource-servlet节点
|
||||
webroot: web资源的根目录, 默认取server节点中的root值
|
||||
servlet: 静态资源HttpServlet的实现,默认使用HttpResourceServlet
|
||||
index : 启始页,默认值:index.html
|
||||
-->
|
||||
<resource-servlet webroot="root" index="index.html">
|
||||
<!--
|
||||
【节点在<resource-servlet>中唯一】
|
||||
资源缓存的配置, 默认存在一个含默认属性的caches节点
|
||||
limit: 资源缓存最大容量, 默认: 0, 为0表示不缓存, 单位可以是B、K、M、G,不区分大小写
|
||||
lengthmax: 可缓存的文件大小上限, 默认: 1M(超过1M的文件不会被缓存)
|
||||
watch: 是否监控缓存文件的变化, 默认为false,不监控
|
||||
-->
|
||||
<cache limit="0M" lengthmax="1M" watch="false"/>
|
||||
<!--
|
||||
支持类似nginx中的rewrite, 目前只支持静态资源对静态资源的跳转。
|
||||
type: 匹配的类型, 目前只支持location(匹配requestURI), 默认: location
|
||||
match: 匹配的正则表达式
|
||||
forward: 需跳转后的资源链接
|
||||
例如下面例子是将/xxx-yyy.html的页面全部跳转到/xxx.html
|
||||
-->
|
||||
<rewrite type="location" match="^/([^-]+)-[^-\.]+\.html(.*)" forward="/$1.html"/>
|
||||
</resource-servlet>
|
||||
<!--
|
||||
加载所有的Servlet服务;
|
||||
path: servlet的ContextPath前缀 默认为空
|
||||
@@ -154,28 +205,6 @@
|
||||
excludes: 当autoload="true", 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
|
||||
-->
|
||||
<servlets path="/pipes" autoload="true" includes="" excludes="">
|
||||
<!--
|
||||
当Server为HTTP协议时,ResourceServlet才有效. 默认存在一个有默认属性的resource-servlet节点
|
||||
webroot: web资源的根目录, 默认取server节点中的root值
|
||||
index : 启始页,默认值:index.html
|
||||
-->
|
||||
<resource-servlet webroot="root" index="index.html">
|
||||
<!--
|
||||
资源缓存的配置, 默认存在一个含默认属性的caches节点
|
||||
limit: 资源缓存最大容量, 默认: 0, 为0表示不缓存, 单位可以是B、K、M、G,不区分大小写
|
||||
lengthmax: 可缓存的文件大小上限, 默认: 1M(超过1M的文件不会被缓存)
|
||||
watch: 是否监控缓存文件的变化, 默认不监控
|
||||
-->
|
||||
<cache limit="0M" lengthmax="1M" watch="false"/>
|
||||
<!--
|
||||
支持类似nginx中的rewrite, 目前只支持静态资源对静态资源的跳转。
|
||||
type: 匹配的类型, 目前只支持location(匹配requestURI), 默认: location
|
||||
match: 匹配的正则表达式
|
||||
forward: 需跳转后的资源链接
|
||||
例如下面例子是将/xxx-yyy.html的页面全部跳转到/xxx.html
|
||||
-->
|
||||
<rewrite type="location" match="^/([^-]+)-[^-\.]+\.html(.*)" forward="/$1.html"/>
|
||||
</resource-servlet>
|
||||
<!-- 显著加载指定的Servlet -->
|
||||
<servlet value="com.xxx.XXX1Servlet" />
|
||||
<servlet value="com.xxx.XXX2Servlet" />
|
||||
|
||||
@@ -16,6 +16,8 @@ java.util.logging.FileHandler.limit = 10485760
|
||||
java.util.logging.FileHandler.count = 100
|
||||
java.util.logging.FileHandler.encoding = UTF-8
|
||||
java.util.logging.FileHandler.pattern = ${APP_HOME}/logs-%m/log-%u.log
|
||||
#java.util.logging.FileHandler.unusual \u5c5e\u6027\u8868\u793a\u5c06 WARNING\u3001SEVERE \u7ea7\u522b\u7684\u65e5\u5fd7\u590d\u5236\u5199\u5165\u5355\u72ec\u7684\u6587\u4ef6\u4e2d
|
||||
#java.util.logging.FileHandler.unusual = ${APP_HOME}/logs-%m/log-error-%u.log
|
||||
java.util.logging.FileHandler.append = true
|
||||
|
||||
#java.util.logging.ConsoleHandler.level = FINE
|
||||
|
||||
49
src/META-INF/persistence-template.xml
Normal file
49
src/META-INF/persistence-template.xml
Normal file
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 其配置算是标准的JPA配置文件的缩略版 -->
|
||||
<persistence>
|
||||
<!-- 系统基本库 -->
|
||||
<persistence-unit name="demouser">
|
||||
<!-- 为NONE表示不启动缓存,@Cacheable 失效; 非NONE值(通常用ALL)表示开启缓存。 -->
|
||||
<shared-cache-mode>NONE</shared-cache-mode>
|
||||
<properties>
|
||||
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/dbuser?characterEncoding=utf8"/>
|
||||
<!--
|
||||
javax.persistence.jdbc.driver在JPA的值是JDBC驱动,Redkale有所不同,值应该是javax.sql.DataSource的子类。
|
||||
为了兼容用户习惯,Redkale内置常见JDBC驱动到javax.sql.DataSource的映射关系:
|
||||
org.mariadb.jdbc.Driver —————— org.mariadb.jdbc.MySQLDataSource
|
||||
org.postgresql.Driver —————— org.postgresql.ds.PGConnectionPoolDataSource
|
||||
com.mysql.jdbc.Driver —————— com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
|
||||
oracle.jdbc.driver.OracleDriver —————— oracle.jdbc.pool.OracleConnectionPoolDataSource
|
||||
com.microsoft.sqlserver.jdbc.SQLServerDriver —————— com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource
|
||||
因此 com.mysql.jdbc.Driver 会被自动转换成 com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
|
||||
并且如果JDBC驱动是以上几个版本,javax.persistence.jdbc.driver属性都可以省略,Redkale会根据javax.persistence.jdbc.url的值来识别驱动
|
||||
-->
|
||||
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
||||
<property name="javax.persistence.jdbc.user" value="root"/>
|
||||
<property name="javax.persistence.jdbc.password" value="123456"/>
|
||||
|
||||
<!-- 最大连接数,默认值:CPU数*16 -->
|
||||
<property name="javax.persistence.connections.limit" value="32"/>
|
||||
|
||||
<!-- 包含的SQL模板,相当于反向LIKE,不同的JDBC驱动的SQL语句不一样,Redkale内置了MySQL的语句 -->
|
||||
<property name="javax.persistence.contain.sqltemplate" value="LOCATE(${keystr}, ${column}) > 0"/>
|
||||
<property name="javax.persistence.notcontain.sqltemplate" value="LOCATE(${keystr}, ${column}) = 0"/>
|
||||
|
||||
<!-- 复制表结构的SQL模板,Redkale内置了MySQL的语句 -->
|
||||
<property name="javax.persistence.tablenotexist.sqlstates" value="42000;42S02"/>
|
||||
<property name="javax.persistence.tablecopy.sqltemplate" value="CREATE TABLE ${newtable} LIKE ${oldtable}"/>
|
||||
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
<!-- IM消息库 -->
|
||||
<persistence-unit name="demoim">
|
||||
<shared-cache-mode>NONE</shared-cache-mode>
|
||||
<properties>
|
||||
<!-- jdbc:mysql://127.0.0.1:3306/dbim?autoReconnect=true&autoReconnectForPools=true&characterEncoding=utf8 -->
|
||||
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/dbim?characterEncoding=utf8"/>
|
||||
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
||||
<property name="javax.persistence.jdbc.user" value="root"/>
|
||||
<property name="javax.persistence.jdbc.password" value="123456"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
@@ -1,4 +1,4 @@
|
||||
/*******************************************************************************
|
||||
/** *****************************************************************************
|
||||
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
@@ -12,7 +12,7 @@
|
||||
* Linda DeMichiel - Java Persistence 2.1
|
||||
* Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
******************************************************************************/
|
||||
***************************************************************************** */
|
||||
package javax.persistence;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
@@ -27,19 +27,28 @@ import java.lang.annotation.Target;
|
||||
* The value of the <code>Cacheable</code> annotation is inherited by
|
||||
* subclasses; it can be overridden by specifying
|
||||
* <code>Cacheable</code> on a subclass.
|
||||
*
|
||||
* <p> <code>Cacheable(false)</code> means that the entity and its state must
|
||||
*
|
||||
* <p>
|
||||
* <code>Cacheable(false)</code> means that the entity and its state must
|
||||
* not be cached by the provider.
|
||||
*
|
||||
*
|
||||
* @since Java Persistence 2.0
|
||||
*/
|
||||
@Target( { TYPE })
|
||||
@Target({TYPE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface Cacheable {
|
||||
|
||||
/**
|
||||
* (Optional) Whether or not the entity should be cached.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
boolean value() default true;
|
||||
|
||||
/**
|
||||
* (Optional) 定时自动更新缓存的周期秒数,为0表示不做定时更新, 大于0表示每经过interval秒后会自动从数据库中拉取数据更新Cache
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int interval() default 0;
|
||||
}
|
||||
|
||||
@@ -61,6 +61,13 @@ public @interface Column {
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* (Optional) The comment of the column.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String comment() default "";
|
||||
|
||||
/**
|
||||
* (Optional) Whether the column is a unique key. This is a
|
||||
* shortcut for the <code>UniqueConstraint</code> annotation at the table
|
||||
@@ -96,17 +103,6 @@ public @interface Column {
|
||||
*/
|
||||
boolean updatable() default true;
|
||||
|
||||
/**
|
||||
* (Optional) The SQL fragment that is used when
|
||||
* generating the DDL for the column.
|
||||
* <p>
|
||||
* Defaults to the generated SQL to create a
|
||||
* column of the inferred type.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String columnDefinition() default "";
|
||||
|
||||
/**
|
||||
* (Optional) The name of the table that contains the column.
|
||||
* If absent the column is assumed to be in the primary table.
|
||||
|
||||
@@ -40,4 +40,11 @@ public @interface Entity {
|
||||
* @return String
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
@@ -12,7 +12,7 @@
|
||||
* Linda DeMichiel - Java Persistence 2.1
|
||||
* Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
******************************************************************************/
|
||||
***************************************************************************** */
|
||||
package javax.persistence;
|
||||
|
||||
import java.lang.annotation.Target;
|
||||
@@ -23,13 +23,14 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Provides for the specification of generation strategies for the
|
||||
* values of primary keys.
|
||||
* values of primary keys.
|
||||
*
|
||||
* <p> The <code>GeneratedValue</code> annotation
|
||||
* <p>
|
||||
* The <code>GeneratedValue</code> annotation
|
||||
* may be applied to a primary key property or field of an entity or
|
||||
* mapped superclass in conjunction with the {@link Id} annotation.
|
||||
* The use of the <code>GeneratedValue</code> annotation is only
|
||||
* required to be supported for simple primary keys. Use of the
|
||||
* required to be supported for simple primary keys. Use of the
|
||||
* <code>GeneratedValue</code> annotation is not supported for derived
|
||||
* primary keys.
|
||||
*
|
||||
@@ -58,22 +59,5 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
@Retention(RUNTIME)
|
||||
|
||||
public @interface GeneratedValue {
|
||||
/**
|
||||
* (Optional) The primary key generation strategy
|
||||
* that the persistence provider must use to
|
||||
* generate the annotated entity primary key.
|
||||
* @return GenerationType
|
||||
*/
|
||||
@Deprecated
|
||||
GenerationType strategy() default GenerationType.AUTO;
|
||||
|
||||
/**
|
||||
* (Optional) The name of the primary key generator
|
||||
* to use as specified in the SequenceGenerator
|
||||
* or TableGenerator annotation.
|
||||
* <p> Defaults to the id generator supplied by persistence provider.
|
||||
* @return String
|
||||
*/
|
||||
@Deprecated
|
||||
String generator() default "";
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
@@ -12,7 +12,7 @@
|
||||
* Linda DeMichiel - Java Persistence 2.1
|
||||
* Linda DeMichiel - Java Persistence 2.0
|
||||
*
|
||||
******************************************************************************/
|
||||
***************************************************************************** */
|
||||
package javax.persistence;
|
||||
|
||||
import java.lang.annotation.Target;
|
||||
@@ -22,9 +22,10 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Specifies the primary table for the annotated entity. Additional
|
||||
* tables may be specified using SecondaryTable or SecondaryTables annotation.
|
||||
* tables may be specified using SecondaryTable or SecondaryTables annotation.
|
||||
*
|
||||
* <p> If no <code>Table</code> annotation is specified for an entity
|
||||
* <p>
|
||||
* If no <code>Table</code> annotation is specified for an entity
|
||||
* class, the default values apply.
|
||||
*
|
||||
* <pre>
|
||||
@@ -37,27 +38,50 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
*
|
||||
* @since Java Persistence 1.0
|
||||
*/
|
||||
@Target(TYPE)
|
||||
@Target(TYPE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Table {
|
||||
|
||||
/**
|
||||
* (Optional) The name of the table.
|
||||
* <p> Defaults to the entity name.
|
||||
* <p>
|
||||
* Defaults to the entity name.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/** (Optional) The catalog of the table.
|
||||
* <p> Defaults to the default catalog.
|
||||
* <p>
|
||||
* Defaults to the default catalog.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String catalog() default "";
|
||||
|
||||
/** (Optional) The schema of the table.
|
||||
* <p> Defaults to the default schema for user.
|
||||
* @return String
|
||||
/**
|
||||
* (Optional) Unique constraints that are to be placed on
|
||||
* the table. These are only used if table generation is in
|
||||
* effect. These constraints apply in addition to any constraints
|
||||
* specified by the <code>Column</code> and <code>JoinColumn</code>
|
||||
* annotations and constraints entailed by primary key mappings.
|
||||
* <p>
|
||||
* Defaults to no additional constraints.
|
||||
* @return UniqueConstraint[]
|
||||
*/
|
||||
String schema() default "";
|
||||
UniqueConstraint[] uniqueConstraints() default {};
|
||||
|
||||
/**
|
||||
* (Optional) Indexes for the table. These are only used if
|
||||
* table generation is in effect. Note that it is not necessary
|
||||
* to specify an index for a primary key, as the primary key
|
||||
* index will be created automatically.
|
||||
*
|
||||
* @return indexes
|
||||
* @since Java Persistence 2.1
|
||||
*/
|
||||
Index[] indexes() default {};
|
||||
|
||||
String comment() default "";
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
209
src/org/redkale/boot/ApiDocs.java
Normal file
209
src/org/redkale/boot/ApiDocs.java
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import javax.persistence.*;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.net.http.*;
|
||||
import org.redkale.source.*;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* 继承 HttpBaseServlet 是为了获取 WebAction 信息
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ApiDocs extends HttpBaseServlet {
|
||||
|
||||
private final Application app;
|
||||
|
||||
public ApiDocs(Application app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
List<Map> serverList = new ArrayList<>();
|
||||
|
||||
Map<String, Map<String, Map<String, Object>>> typesmap = new LinkedHashMap<>();
|
||||
for (NodeServer node : app.servers) {
|
||||
if (!(node instanceof NodeHttpServer)) continue;
|
||||
final Map<String, Object> map = new LinkedHashMap<>();
|
||||
serverList.add(map);
|
||||
HttpServer server = node.getServer();
|
||||
map.put("address", server.getSocketAddress());
|
||||
List<Map<String, Object>> servletsList = new ArrayList<>();
|
||||
map.put("servlets", servletsList);
|
||||
for (HttpServlet servlet : server.getPrepareServlet().getServlets()) {
|
||||
if (!(servlet instanceof HttpServlet)) continue;
|
||||
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
|
||||
if (ws == null) {
|
||||
System.err.println(servlet + " not found @WebServlet");
|
||||
continue;
|
||||
}
|
||||
final Map<String, Object> servletmap = new LinkedHashMap<>();
|
||||
String prefix = _prefix(servlet);
|
||||
String[] mappings = ws.value();
|
||||
if (prefix != null && !prefix.isEmpty()) {
|
||||
for (int i = 0; i < mappings.length; i++) {
|
||||
mappings[i] = prefix + mappings[i];
|
||||
}
|
||||
}
|
||||
servletmap.put("mappings", mappings);
|
||||
servletmap.put("moduleid", ws.moduleid());
|
||||
servletmap.put("name", ws.name());
|
||||
servletmap.put("comment", ws.comment());
|
||||
|
||||
List<Map> actionsList = new ArrayList<>();
|
||||
servletmap.put("actions", actionsList);
|
||||
final Class selfClz = servlet.getClass();
|
||||
Class clz = servlet.getClass();
|
||||
HashSet<String> actionurls = new HashSet<>();
|
||||
do {
|
||||
if (Modifier.isAbstract(clz.getModifiers())) break;
|
||||
for (Method method : clz.getMethods()) {
|
||||
if (method.getParameterCount() != 2) continue;
|
||||
WebAction action = method.getAnnotation(WebAction.class);
|
||||
if (action == null) continue;
|
||||
if (!action.inherited() && selfClz != clz) continue; //忽略不被继承的方法
|
||||
final Map<String, Object> actionmap = new LinkedHashMap<>();
|
||||
if (actionurls.contains(action.url())) continue;
|
||||
actionmap.put("url", prefix + action.url());
|
||||
actionurls.add(action.url());
|
||||
actionmap.put("auth", method.getAnnotation(AuthIgnore.class) == null);
|
||||
actionmap.put("actionid", action.actionid());
|
||||
actionmap.put("comment", action.comment());
|
||||
List<Map> paramsList = new ArrayList<>();
|
||||
actionmap.put("params", paramsList);
|
||||
List<String> results = new ArrayList<>();
|
||||
for (final Class rtype : action.results()) {
|
||||
results.add(rtype.getName());
|
||||
if (typesmap.containsKey(rtype.getName())) continue;
|
||||
final boolean filter = FilterBean.class.isAssignableFrom(rtype);
|
||||
final Map<String, Map<String, Object>> typemap = new LinkedHashMap<>();
|
||||
Class loop = rtype;
|
||||
do {
|
||||
if (loop == null || loop.isInterface()) break;
|
||||
for (Field field : loop.getDeclaredFields()) {
|
||||
if (Modifier.isFinal(field.getModifiers())) continue;
|
||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||
|
||||
Map<String, Object> fieldmap = new LinkedHashMap<>();
|
||||
fieldmap.put("type", field.getType().isArray() ? (field.getType().getComponentType().getName() + "[]") : field.getGenericType().getTypeName());
|
||||
|
||||
Comment comment = field.getAnnotation(Comment.class);
|
||||
Column col = field.getAnnotation(Column.class);
|
||||
FilterColumn fc = field.getAnnotation(FilterColumn.class);
|
||||
if (comment != null) {
|
||||
fieldmap.put("comment", comment.value());
|
||||
} else if (col != null) {
|
||||
fieldmap.put("comment", col.comment());
|
||||
} else if (fc != null) {
|
||||
fieldmap.put("comment", fc.comment());
|
||||
}
|
||||
fieldmap.put("primary", !filter && (field.getAnnotation(Id.class) != null));
|
||||
fieldmap.put("updatable", (filter || col == null || col.updatable()));
|
||||
if (servlet.getClass().getAnnotation(Rest.RestDynamic.class) != null) {
|
||||
if (field.getAnnotation(RestAddress.class) != null) continue;
|
||||
}
|
||||
|
||||
typemap.put(field.getName(), fieldmap);
|
||||
}
|
||||
} while ((loop = loop.getSuperclass()) != Object.class);
|
||||
typesmap.put(rtype.getName(), typemap);
|
||||
}
|
||||
actionmap.put("results", results);
|
||||
for (WebParam param : method.getAnnotationsByType(WebParam.class)) {
|
||||
final Map<String, Object> parammap = new LinkedHashMap<>();
|
||||
final boolean isarray = param.type().isArray();
|
||||
final Class ptype = isarray ? param.type().getComponentType() : param.type();
|
||||
parammap.put("name", param.name());
|
||||
parammap.put("radix", param.radix());
|
||||
parammap.put("type", ptype.getName() + (isarray ? "[]" : ""));
|
||||
parammap.put("src", param.src());
|
||||
parammap.put("comment", param.comment());
|
||||
parammap.put("required", param.required());
|
||||
paramsList.add(parammap);
|
||||
if (ptype.isPrimitive() || ptype == String.class) continue;
|
||||
if (typesmap.containsKey(ptype.getName())) continue;
|
||||
|
||||
final Map<String, Map<String, Object>> typemap = new LinkedHashMap<>();
|
||||
Class loop = ptype;
|
||||
final boolean filter = FilterBean.class.isAssignableFrom(loop);
|
||||
do {
|
||||
if (loop == null || loop.isInterface()) break;
|
||||
for (Field field : loop.getDeclaredFields()) {
|
||||
if (Modifier.isFinal(field.getModifiers())) continue;
|
||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||
|
||||
Map<String, Object> fieldmap = new LinkedHashMap<>();
|
||||
fieldmap.put("type", field.getType().isArray() ? (field.getType().getComponentType().getName() + "[]") : field.getGenericType().getTypeName());
|
||||
|
||||
Column col = field.getAnnotation(Column.class);
|
||||
FilterColumn fc = field.getAnnotation(FilterColumn.class);
|
||||
Comment comment = field.getAnnotation(Comment.class);
|
||||
if (comment != null) {
|
||||
fieldmap.put("comment", comment.value());
|
||||
} else if (col != null) {
|
||||
fieldmap.put("comment", col.comment());
|
||||
} else if (fc != null) {
|
||||
fieldmap.put("comment", fc.comment());
|
||||
}
|
||||
fieldmap.put("primary", !filter && (field.getAnnotation(Id.class) != null));
|
||||
fieldmap.put("updatable", (filter || col == null || col.updatable()));
|
||||
|
||||
if (servlet.getClass().getAnnotation(Rest.RestDynamic.class) != null) {
|
||||
if (field.getAnnotation(RestAddress.class) != null) continue;
|
||||
}
|
||||
|
||||
typemap.put(field.getName(), fieldmap);
|
||||
}
|
||||
} while ((loop = loop.getSuperclass()) != Object.class);
|
||||
|
||||
typesmap.put(ptype.getName(), typemap);
|
||||
}
|
||||
actionmap.put("result", action.result());
|
||||
actionsList.add(actionmap);
|
||||
}
|
||||
} while ((clz = clz.getSuperclass()) != HttpServlet.class);
|
||||
actionsList.sort((o1, o2) -> ((String) o1.get("url")).compareTo((String) o2.get("url")));
|
||||
servletsList.add(servletmap);
|
||||
}
|
||||
servletsList.sort((o1, o2) -> {
|
||||
String[] mappings1 = (String[]) o1.get("mappings");
|
||||
String[] mappings2 = (String[]) o2.get("mappings");
|
||||
return mappings1.length > 0 ? (mappings2.length > 0 ? mappings1[0].compareTo(mappings2[0]) : 1) : -1;
|
||||
});
|
||||
}
|
||||
Map<String, Object> resultmap = new LinkedHashMap<>();
|
||||
resultmap.put("servers", serverList);
|
||||
resultmap.put("types", typesmap);
|
||||
final String json = JsonConvert.root().convertTo(resultmap);
|
||||
final FileOutputStream out = new FileOutputStream(new File(app.getHome(), "apidoc.json"));
|
||||
out.write(json.getBytes("UTF-8"));
|
||||
out.close();
|
||||
File doctemplate = new File(app.getHome(), "conf/apidoc-template.html");
|
||||
InputStream in = null;
|
||||
if (doctemplate.isFile() && doctemplate.canRead()) {
|
||||
in = new FileInputStream(doctemplate);
|
||||
}
|
||||
if (in == null) in = ApiDocs.class.getResourceAsStream("apidoc-template.html");
|
||||
String content = Utility.read(in).replace("'${content}'", json);
|
||||
in.close();
|
||||
FileOutputStream outhtml = new FileOutputStream(new File(app.getHome(), "apidoc.html"));
|
||||
outhtml.write(content.getBytes("UTF-8"));
|
||||
outhtml.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authenticate(int moduleid, int actionid, HttpRequest request, HttpResponse response) throws IOException {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
@@ -33,7 +34,7 @@ import org.w3c.dom.*;
|
||||
* <p>
|
||||
* 进程启动类,程序启动后读取application.xml,进行classpath扫描动态加载Service与Servlet 优先加载所有SNCP协议的服务, 再加载其他协议服务, 最后进行Service、Servlet与其他资源之间的依赖注入。
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@@ -65,9 +66,7 @@ public final class Application {
|
||||
|
||||
final Map<InetSocketAddress, String> globalNodes = new HashMap<>();
|
||||
|
||||
final Map<String, Set<InetSocketAddress>> globalGroups = new HashMap<>();
|
||||
|
||||
final Map<String, String> globalGroupProtocols = new HashMap<>();
|
||||
final Map<String, GroupInfo> globalGroups = new HashMap<>();
|
||||
|
||||
final InetAddress localAddress;
|
||||
|
||||
@@ -77,8 +76,6 @@ public final class Application {
|
||||
|
||||
final List<NodeServer> servers = new CopyOnWriteArrayList<>();
|
||||
|
||||
CountDownLatch servicecdl; //会出现两次赋值
|
||||
|
||||
final ObjectPool<ByteBuffer> transportBufferPool;
|
||||
|
||||
final ExecutorService transportExecutor;
|
||||
@@ -87,6 +84,8 @@ public final class Application {
|
||||
|
||||
final ResourceFactory resourceFactory = ResourceFactory.root();
|
||||
|
||||
CountDownLatch servicecdl; //会出现两次赋值
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
private final boolean singletonrun;
|
||||
|
||||
@@ -190,6 +189,7 @@ public final class Application {
|
||||
}
|
||||
this.logger = Logger.getLogger(this.getClass().getSimpleName());
|
||||
this.serversLatch = new CountDownLatch(config.getAnyValues("server").length + 1);
|
||||
logger.log(Level.INFO, "------------------------------- Redkale ------------------------------");
|
||||
//------------------配置 <transport> 节点 ------------------
|
||||
ObjectPool<ByteBuffer> transportPool = null;
|
||||
ExecutorService transportExec = null;
|
||||
@@ -331,15 +331,14 @@ public final class Application {
|
||||
if (!"TCP".equalsIgnoreCase(protocol) && !"UDP".equalsIgnoreCase(protocol)) {
|
||||
throw new RuntimeException("Not supported Transport Protocol " + conf.getValue("protocol"));
|
||||
}
|
||||
Set<InetSocketAddress> addrs = globalGroups.get(group);
|
||||
if (addrs == null) {
|
||||
addrs = new LinkedHashSet<>();
|
||||
globalGroupProtocols.put(group, protocol);
|
||||
globalGroups.put(group, addrs);
|
||||
GroupInfo ginfo = globalGroups.get(group);
|
||||
if (ginfo == null) {
|
||||
ginfo = new GroupInfo(group, protocol, conf.getValue("kind", ""), new LinkedHashSet<>());
|
||||
globalGroups.put(group, ginfo);
|
||||
}
|
||||
for (AnyValue node : conf.getAnyValues("node")) {
|
||||
final InetSocketAddress addr = new InetSocketAddress(node.getValue("addr"), node.getIntValue("port"));
|
||||
addrs.add(addr);
|
||||
ginfo.addrs.add(addr);
|
||||
String oldgroup = globalNodes.get(addr);
|
||||
if (oldgroup != null) throw new RuntimeException(addr + " had one more group " + (globalNodes.get(addr)));
|
||||
globalNodes.put(addr, group);
|
||||
@@ -362,7 +361,7 @@ public final class Application {
|
||||
final DatagramChannel channel = DatagramChannel.open();
|
||||
channel.configureBlocking(true);
|
||||
channel.socket().setSoTimeout(3000);
|
||||
channel.bind(new InetSocketAddress(config.getValue("host", "127.0.0.1"), config.getIntValue("port")));
|
||||
channel.bind(new InetSocketAddress("127.0.0.1", config.getIntValue("port")));
|
||||
boolean loop = true;
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
|
||||
while (loop) {
|
||||
@@ -391,6 +390,19 @@ public final class Application {
|
||||
buffer.flip();
|
||||
channel.send(buffer, address);
|
||||
}
|
||||
} else if ("APIDOC".equalsIgnoreCase(new String(bytes))) {
|
||||
try {
|
||||
new ApiDocs(application).run();
|
||||
buffer.clear();
|
||||
buffer.put("APIDOC OK".getBytes());
|
||||
buffer.flip();
|
||||
channel.send(buffer, address);
|
||||
} catch (Exception ex) {
|
||||
buffer.clear();
|
||||
buffer.put("APIDOC FAIL".getBytes());
|
||||
buffer.flip();
|
||||
channel.send(buffer, address);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -401,12 +413,12 @@ public final class Application {
|
||||
}.start();
|
||||
}
|
||||
|
||||
private void sendShutDown() throws Exception {
|
||||
private void sendCommand(String command) throws Exception {
|
||||
final DatagramChannel channel = DatagramChannel.open();
|
||||
channel.configureBlocking(true);
|
||||
channel.connect(new InetSocketAddress(config.getValue("host", "127.0.0.1"), config.getIntValue("port")));
|
||||
channel.connect(new InetSocketAddress("127.0.0.1", config.getIntValue("port")));
|
||||
ByteBuffer buffer = ByteBuffer.allocate(128);
|
||||
buffer.put("SHUTDOWN".getBytes());
|
||||
buffer.put(command.getBytes());
|
||||
buffer.flip();
|
||||
channel.write(buffer);
|
||||
buffer.clear();
|
||||
@@ -451,7 +463,7 @@ public final class Application {
|
||||
for (final AnyValue serconf : serconfs) {
|
||||
Thread thread = new Thread() {
|
||||
{
|
||||
String host = serconf.getValue("host", "").replace("0.0.0.0", "[0]");
|
||||
String host = serconf.getValue("host", "0.0.0.0").replace("0.0.0.0", "*");
|
||||
setName(serconf.getValue("protocol", "Server").toUpperCase() + "-" + host + ":" + serconf.getIntValue("port") + "-Thread");
|
||||
this.setDaemon(true);
|
||||
}
|
||||
@@ -464,15 +476,15 @@ public final class Application {
|
||||
final String protocol = serconf.getValue("protocol", "").replaceFirst("\\..+", "").toUpperCase();
|
||||
NodeServer server = null;
|
||||
if ("SNCP".equals(protocol)) {
|
||||
server = new NodeSncpServer(Application.this, serconf);
|
||||
} else if ("HTTP".equals(protocol)) {
|
||||
server = NodeSncpServer.createNodeServer(Application.this, serconf);
|
||||
} else if ("HTTP".equalsIgnoreCase(protocol)) {
|
||||
server = new NodeHttpServer(Application.this, serconf);
|
||||
} else {
|
||||
if (!inited.get()) {
|
||||
synchronized (nodeClasses) {
|
||||
if (!inited.getAndSet(true)) { //加载自定义的协议,如:SOCKS
|
||||
ClassFilter profilter = new ClassFilter(NodeProtocol.class, NodeServer.class);
|
||||
ClassFilter.Loader.load(home, profilter);
|
||||
ClassFilter.Loader.load(home, serconf.getValue("excludelibs", "").split(";"), profilter);
|
||||
final Set<FilterEntry<NodeServer>> entrys = profilter.getFilterEntrys();
|
||||
for (FilterEntry<NodeServer> entry : entrys) {
|
||||
final Class<? extends NodeServer> type = entry.getType();
|
||||
@@ -516,6 +528,7 @@ public final class Application {
|
||||
}
|
||||
|
||||
public static <T extends Service> T singleton(String name, Class<T> serviceClass) throws Exception {
|
||||
if (serviceClass == null) throw new IllegalArgumentException("serviceClass is null");
|
||||
final Application application = Application.create(true);
|
||||
application.init();
|
||||
application.start();
|
||||
@@ -523,7 +536,9 @@ public final class Application {
|
||||
T service = server.resourceFactory.find(name, serviceClass);
|
||||
if (service != null) return service;
|
||||
}
|
||||
return null;
|
||||
if (Modifier.isAbstract(serviceClass.getModifiers())) throw new IllegalArgumentException("abstract class not allowed");
|
||||
if (serviceClass.isInterface()) throw new IllegalArgumentException("interface class not allowed");
|
||||
throw new IllegalArgumentException(serviceClass.getName() + " maybe have zero not-final public method");
|
||||
}
|
||||
|
||||
public static Application create(final boolean singleton) throws IOException {
|
||||
@@ -537,8 +552,11 @@ public final class Application {
|
||||
Utility.midnight(); //先初始化一下Utility
|
||||
//运行主程序
|
||||
final Application application = Application.create(false);
|
||||
if (System.getProperty("SHUTDOWN") != null) {
|
||||
application.sendShutDown();
|
||||
if (System.getProperty("CMD") != null) {
|
||||
application.sendCommand(System.getProperty("CMD"));
|
||||
return;
|
||||
} else if (System.getProperty("SHUTDOWN") != null) { //兼容旧接口
|
||||
application.sendCommand("SHUTDOWN");
|
||||
return;
|
||||
}
|
||||
application.init();
|
||||
@@ -572,15 +590,9 @@ public final class Application {
|
||||
return null;
|
||||
}
|
||||
|
||||
String findGroupProtocol(String group) {
|
||||
GroupInfo findGroupInfo(String group) {
|
||||
if (group == null) return null;
|
||||
return globalGroupProtocols.get(group);
|
||||
}
|
||||
|
||||
Set<InetSocketAddress> findGlobalGroup(String group) {
|
||||
if (group == null) return null;
|
||||
Set<InetSocketAddress> set = globalGroups.get(group);
|
||||
return set == null ? null : new LinkedHashSet<>(set);
|
||||
return globalGroups.get(group);
|
||||
}
|
||||
|
||||
private void shutdown() throws Exception {
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.redkale.util.AnyValue.DefaultAnyValue;
|
||||
/**
|
||||
* class过滤器, 符合条件的class会保留下来存入FilterEntry。
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 泛型
|
||||
@@ -32,25 +32,29 @@ public final class ClassFilter<T> {
|
||||
|
||||
private static final boolean finer = logger.isLoggable(Level.FINER);
|
||||
|
||||
private final Set<FilterEntry<T>> entrys = new HashSet<>();
|
||||
private final Set<FilterEntry<T>> entrys = new HashSet<>(); //符合条件的结果
|
||||
|
||||
private final Set<FilterEntry<T>> expectEntrys = new HashSet<>();
|
||||
private final Set<FilterEntry<T>> expectEntrys = new HashSet<>(); //准备符合条件的结果
|
||||
|
||||
private boolean refused;
|
||||
private boolean refused; //是否拒绝所有数据,设置true,则其他规则失效,都是拒绝.
|
||||
|
||||
private Class superClass;
|
||||
private Class superClass; //符合的父类型。不为空时,扫描结果的class必须是superClass的子类
|
||||
|
||||
private Class<? extends Annotation> annotationClass;
|
||||
private Class<? extends Annotation> annotationClass;//符合的注解。不为空时,扫描结果的class必须包含该注解
|
||||
|
||||
private Pattern[] includePatterns;
|
||||
private Pattern[] includePatterns; //符合的classname正则表达式
|
||||
|
||||
private Pattern[] excludePatterns;
|
||||
private Pattern[] excludePatterns;//拒绝的classname正则表达式
|
||||
|
||||
private List<ClassFilter> ors;
|
||||
private Set<String> privilegeIncludes; //特批符合条件的classname
|
||||
|
||||
private List<ClassFilter> ands;
|
||||
private Set<String> privilegeExcludes;//特批拒绝条件的classname
|
||||
|
||||
private AnyValue conf;
|
||||
private List<ClassFilter> ors; //或关系的其他ClassFilter
|
||||
|
||||
private List<ClassFilter> ands;//与关系的其他ClassFilter
|
||||
|
||||
private AnyValue conf; //基本配置信息, 当符合条件时将conf的属性赋值到FilterEntry中去。
|
||||
|
||||
public ClassFilter(Class<? extends Annotation> annotationClass, Class superClass) {
|
||||
this(annotationClass, superClass, null);
|
||||
@@ -62,6 +66,15 @@ public final class ClassFilter<T> {
|
||||
this.conf = conf;
|
||||
}
|
||||
|
||||
public static ClassFilter create(String includeregs, String excluderegs, Set<String> includeValues, Set<String> excludeValues) {
|
||||
ClassFilter filter = new ClassFilter(null, null);
|
||||
filter.setIncludePatterns(includeregs == null ? null : includeregs.split(";"));
|
||||
filter.setExcludePatterns(excluderegs == null ? null : excluderegs.split(";"));
|
||||
filter.setPrivilegeIncludes(includeValues);
|
||||
filter.setPrivilegeExcludes(excludeValues);
|
||||
return filter;
|
||||
}
|
||||
|
||||
public ClassFilter<T> or(ClassFilter<T> filter) {
|
||||
if (ors == null) ors = new ArrayList<>();
|
||||
ors.add(filter);
|
||||
@@ -164,24 +177,20 @@ public final class ClassFilter<T> {
|
||||
} catch (Throwable cfe) {
|
||||
if (finer && !clazzname.startsWith("sun.") && !clazzname.startsWith("javax.")
|
||||
&& !clazzname.startsWith("com.sun.") && !clazzname.startsWith("jdk.")) {
|
||||
logger.log(Level.FINER, ClassFilter.class.getSimpleName() + " filter error", cfe);
|
||||
//logger.log(Level.FINEST, ClassFilter.class.getSimpleName() + " filter error", cfe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Pattern[] toPattern(String[] regs) {
|
||||
if (regs == null) return null;
|
||||
int i = 0;
|
||||
Pattern[] rs = new Pattern[regs.length];
|
||||
for (String reg : regs) {
|
||||
if (reg == null || reg.trim().isEmpty()) continue;
|
||||
rs[i++] = Pattern.compile(reg.trim());
|
||||
}
|
||||
if (i == 0) return null;
|
||||
if (i == rs.length) return rs;
|
||||
Pattern[] ps = new Pattern[i];
|
||||
System.arraycopy(rs, 0, ps, 0, i);
|
||||
return ps;
|
||||
/**
|
||||
* 判断class是否有效
|
||||
*
|
||||
* @param classname String
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean accept(String classname) {
|
||||
return accept(null, classname);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,6 +218,8 @@ public final class ClassFilter<T> {
|
||||
|
||||
private boolean accept0(AnyValue property, String classname) {
|
||||
if (this.refused) return false;
|
||||
if (this.privilegeIncludes != null && this.privilegeIncludes.contains(classname)) return true;
|
||||
if (this.privilegeExcludes != null && this.privilegeExcludes.contains(classname)) return false;
|
||||
if (classname.startsWith("java.") || classname.startsWith("javax.")) return false;
|
||||
if (excludePatterns != null) {
|
||||
for (Pattern reg : excludePatterns) {
|
||||
@@ -239,6 +250,21 @@ public final class ClassFilter<T> {
|
||||
return superClass == null || (clazz != superClass && superClass.isAssignableFrom(clazz));
|
||||
}
|
||||
|
||||
public static Pattern[] toPattern(String[] regs) {
|
||||
if (regs == null || regs.length == 0) return null;
|
||||
int i = 0;
|
||||
Pattern[] rs = new Pattern[regs.length];
|
||||
for (String reg : regs) {
|
||||
if (reg == null || reg.trim().isEmpty()) continue;
|
||||
rs[i++] = Pattern.compile(reg.trim());
|
||||
}
|
||||
if (i == 0) return null;
|
||||
if (i == rs.length) return rs;
|
||||
Pattern[] ps = new Pattern[i];
|
||||
System.arraycopy(rs, 0, ps, 0, i);
|
||||
return ps;
|
||||
}
|
||||
|
||||
public void setSuperClass(Class superClass) {
|
||||
this.superClass = superClass;
|
||||
}
|
||||
@@ -279,6 +305,22 @@ public final class ClassFilter<T> {
|
||||
this.refused = refused;
|
||||
}
|
||||
|
||||
public Set<String> getPrivilegeIncludes() {
|
||||
return privilegeIncludes;
|
||||
}
|
||||
|
||||
public void setPrivilegeIncludes(Set<String> privilegeIncludes) {
|
||||
this.privilegeIncludes = privilegeIncludes == null || privilegeIncludes.isEmpty() ? null : privilegeIncludes;
|
||||
}
|
||||
|
||||
public Set<String> getPrivilegeExcludes() {
|
||||
return privilegeExcludes;
|
||||
}
|
||||
|
||||
public void setPrivilegeExcludes(Set<String> privilegeExcludes) {
|
||||
this.privilegeExcludes = privilegeExcludes == null || privilegeExcludes.isEmpty() ? null : privilegeExcludes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 存放符合条件的class与class指定的属性项
|
||||
*
|
||||
@@ -379,18 +421,30 @@ public final class ClassFilter<T> {
|
||||
/**
|
||||
* 加载当前线程的classpath扫描所有class进行过滤
|
||||
*
|
||||
* @param exclude 不需要扫描的文件夹, 可以为null
|
||||
* @param filters 过滤器
|
||||
* @param excludeFile 不需要扫描的文件夹, 可以为null
|
||||
* @param excludeRegs 包含此关键字的文件将被跳过, 可以为null
|
||||
* @param filters 过滤器
|
||||
*
|
||||
* @throws IOException 异常
|
||||
*/
|
||||
public static void load(final File exclude, final ClassFilter... filters) throws IOException {
|
||||
public static void load(final File excludeFile, final String[] excludeRegs, final ClassFilter... filters) throws IOException {
|
||||
URLClassLoader loader = (URLClassLoader) Thread.currentThread().getContextClassLoader();
|
||||
List<URL> urlfiles = new ArrayList<>(2);
|
||||
List<URL> urljares = new ArrayList<>(2);
|
||||
final URL exurl = exclude != null ? exclude.toURI().toURL() : null;
|
||||
final URL exurl = excludeFile != null ? excludeFile.toURI().toURL() : null;
|
||||
final Pattern[] excludePatterns = toPattern(excludeRegs);
|
||||
for (URL url : loader.getURLs()) {
|
||||
if (exurl != null && exurl.sameFile(url)) continue;
|
||||
if (excludePatterns != null) {
|
||||
boolean skip = false;
|
||||
for (Pattern p : excludePatterns) {
|
||||
if (p.matcher(url.toString()).matches()) {
|
||||
skip = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skip) continue;
|
||||
}
|
||||
if (url.getPath().endsWith(".jar")) {
|
||||
urljares.add(url);
|
||||
} else {
|
||||
@@ -435,7 +489,7 @@ public final class ClassFilter<T> {
|
||||
files.clear();
|
||||
File root = new File(url.getFile());
|
||||
String rootpath = root.getPath();
|
||||
loadClassFiles(exclude, root, files);
|
||||
loadClassFiles(excludeFile, root, files);
|
||||
for (File f : files) {
|
||||
String classname = f.getPath().substring(rootpath.length() + 1, f.getPath().length() - 6).replace(File.separatorChar, '.');
|
||||
if (classname.startsWith("javax.") || classname.startsWith("com.sun.")) continue;
|
||||
|
||||
74
src/org/redkale/boot/GroupInfo.java
Normal file
74
src/org/redkale/boot/GroupInfo.java
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class GroupInfo {
|
||||
|
||||
protected String name;
|
||||
|
||||
protected String protocol;
|
||||
|
||||
protected String kind;
|
||||
|
||||
protected Set<InetSocketAddress> addrs;
|
||||
|
||||
public GroupInfo() {
|
||||
}
|
||||
|
||||
public GroupInfo(String name, String protocol, String kind, Set<InetSocketAddress> addrs) {
|
||||
this.name = name;
|
||||
this.protocol = protocol;
|
||||
this.kind = kind;
|
||||
this.addrs = addrs;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public void setProtocol(String protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public String getKind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
public void setKind(String kind) {
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
public Set<InetSocketAddress> getAddrs() {
|
||||
return addrs;
|
||||
}
|
||||
|
||||
public Set<InetSocketAddress> copyAddrs() {
|
||||
return addrs == null ? null : new LinkedHashSet<>(addrs);
|
||||
}
|
||||
|
||||
public void setAddrs(Set<InetSocketAddress> addrs) {
|
||||
this.addrs = addrs;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,7 @@ import java.util.logging.Formatter;
|
||||
/**
|
||||
* 自定义的日志输出类
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@@ -70,12 +70,12 @@ public class LogFileHandler extends Handler {
|
||||
throwable = sw.toString();
|
||||
}
|
||||
return String.format(format,
|
||||
System.currentTimeMillis(),
|
||||
source,
|
||||
record.getLoggerName(),
|
||||
record.getLevel().getName(),
|
||||
message,
|
||||
throwable);
|
||||
System.currentTimeMillis(),
|
||||
source,
|
||||
record.getLoggerName(),
|
||||
record.getLevel().getName(),
|
||||
message,
|
||||
throwable);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -84,9 +84,13 @@ public class LogFileHandler extends Handler {
|
||||
|
||||
private String pattern;
|
||||
|
||||
private String unusual; //不为null表示将 WARNING、SEVERE 级别的日志写入单独的文件中
|
||||
|
||||
private int limit; //文件大小限制
|
||||
|
||||
private final AtomicInteger index = new AtomicInteger();
|
||||
private final AtomicInteger logindex = new AtomicInteger();
|
||||
|
||||
private final AtomicInteger logunusualindex = new AtomicInteger();
|
||||
|
||||
private int count = 1; //文件限制
|
||||
|
||||
@@ -94,11 +98,17 @@ public class LogFileHandler extends Handler {
|
||||
|
||||
private boolean append;
|
||||
|
||||
private final AtomicLong length = new AtomicLong();
|
||||
private final AtomicLong loglength = new AtomicLong();
|
||||
|
||||
private final AtomicLong logunusuallength = new AtomicLong();
|
||||
|
||||
private File logfile;
|
||||
|
||||
private OutputStream stream;
|
||||
private File logunusualfile;
|
||||
|
||||
private OutputStream logstream;
|
||||
|
||||
private OutputStream logunusualstream;
|
||||
|
||||
public LogFileHandler() {
|
||||
updateTomorrow();
|
||||
@@ -114,7 +124,7 @@ public class LogFileHandler extends Handler {
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
cal.add(Calendar.DAY_OF_YEAR, 1);
|
||||
long t = cal.getTimeInMillis();
|
||||
if (this.tomorrow != t) index.set(0);
|
||||
if (this.tomorrow != t) logindex.set(0);
|
||||
this.tomorrow = t;
|
||||
}
|
||||
|
||||
@@ -131,35 +141,59 @@ public class LogFileHandler extends Handler {
|
||||
while (true) {
|
||||
try {
|
||||
LogRecord record = records.take();
|
||||
final boolean bigger = (limit > 0 && limit <= length.get());
|
||||
if (bigger || tomorrow <= record.getMillis()) {
|
||||
final boolean bigger = (limit > 0 && limit <= loglength.get());
|
||||
final boolean changeday = tomorrow <= record.getMillis();
|
||||
if (bigger || changeday) {
|
||||
updateTomorrow();
|
||||
if (stream != null) {
|
||||
stream.close();
|
||||
if (logstream != null) {
|
||||
logstream.close();
|
||||
if (bigger) {
|
||||
for (int i = Math.min(count - 2, index.get() - 1); i > 0; i--) {
|
||||
for (int i = Math.min(count - 2, logindex.get() - 1); i > 0; i--) {
|
||||
File greater = new File(logfile.getPath() + "." + i);
|
||||
if (greater.exists()) Files.move(greater.toPath(), new File(logfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||
}
|
||||
Files.move(logfile.toPath(), new File(logfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||
}
|
||||
stream = null;
|
||||
logstream = null;
|
||||
}
|
||||
}
|
||||
if (stream == null) {
|
||||
index.incrementAndGet();
|
||||
if (unusual != null && changeday && logunusualstream != null) {
|
||||
logunusualstream.close();
|
||||
if (limit > 0 && limit <= logunusuallength.get()) {
|
||||
for (int i = Math.min(count - 2, logunusualindex.get() - 1); i > 0; i--) {
|
||||
File greater = new File(logunusualfile.getPath() + "." + i);
|
||||
if (greater.exists()) Files.move(greater.toPath(), new File(logunusualfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||
}
|
||||
Files.move(logunusualfile.toPath(), new File(logunusualfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||
}
|
||||
logunusualstream = null;
|
||||
}
|
||||
if (logstream == null) {
|
||||
logindex.incrementAndGet();
|
||||
java.time.LocalDate date = LocalDate.now();
|
||||
logfile = new File(pattern.replace("%m", String.valueOf((date.getYear() * 100 + date.getMonthValue()))).replace("%d", String.valueOf((date.getYear() * 10000 + date.getMonthValue() * 100 + date.getDayOfMonth()))));
|
||||
logfile.getParentFile().mkdirs();
|
||||
length.set(logfile.length());
|
||||
stream = new FileOutputStream(logfile, append);
|
||||
loglength.set(logfile.length());
|
||||
logstream = new FileOutputStream(logfile, append);
|
||||
}
|
||||
if (unusual != null && logunusualstream == null) {
|
||||
logunusualindex.incrementAndGet();
|
||||
java.time.LocalDate date = LocalDate.now();
|
||||
logunusualfile = new File(unusual.replace("%m", String.valueOf((date.getYear() * 100 + date.getMonthValue()))).replace("%d", String.valueOf((date.getYear() * 10000 + date.getMonthValue() * 100 + date.getDayOfMonth()))));
|
||||
logunusualfile.getParentFile().mkdirs();
|
||||
logunusuallength.set(logunusualfile.length());
|
||||
logunusualstream = new FileOutputStream(logunusualfile, append);
|
||||
}
|
||||
//----------------------写日志-------------------------
|
||||
String message = getFormatter().format(record);
|
||||
String encoding = getEncoding();
|
||||
byte[] bytes = encoding == null ? message.getBytes() : message.getBytes(encoding);
|
||||
stream.write(bytes);
|
||||
length.addAndGet(bytes.length);
|
||||
logstream.write(bytes);
|
||||
loglength.addAndGet(bytes.length);
|
||||
if (unusual != null && (record.getLevel() == Level.WARNING || record.getLevel() == Level.SEVERE)) {
|
||||
logunusualstream.write(bytes);
|
||||
logunusuallength.addAndGet(bytes.length);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ErrorManager err = getErrorManager();
|
||||
if (err != null) err.error(null, e, ErrorManager.WRITE_FAILURE);
|
||||
@@ -177,30 +211,39 @@ public class LogFileHandler extends Handler {
|
||||
private void configure() {
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
String cname = LogFileHandler.class.getName();
|
||||
pattern = manager.getProperty(cname + ".pattern");
|
||||
if (pattern == null) {
|
||||
pattern = "logs-%m/" + getPrefix() + "log-%d.log";
|
||||
this.pattern = manager.getProperty(cname + ".pattern");
|
||||
if (this.pattern == null) {
|
||||
this.pattern = "logs-%m/" + getPrefix() + "log-%d.log";
|
||||
} else {
|
||||
int pos = pattern.lastIndexOf('/');
|
||||
int pos = this.pattern.lastIndexOf('/');
|
||||
if (pos > 0) {
|
||||
pattern = pattern.substring(0, pos + 1) + getPrefix() + pattern.substring(pos + 1);
|
||||
this.pattern = this.pattern.substring(0, pos + 1) + getPrefix() + this.pattern.substring(pos + 1);
|
||||
} else {
|
||||
pattern = getPrefix() + pattern;
|
||||
this.pattern = getPrefix() + this.pattern;
|
||||
}
|
||||
}
|
||||
String unusualstr = manager.getProperty(cname + ".unusual");
|
||||
if (unusualstr != null) {
|
||||
int pos = unusualstr.lastIndexOf('/');
|
||||
if (pos > 0) {
|
||||
this.unusual = unusualstr.substring(0, pos + 1) + getPrefix() + unusualstr.substring(pos + 1);
|
||||
} else {
|
||||
this.unusual = getPrefix() + unusualstr;
|
||||
}
|
||||
}
|
||||
String limitstr = manager.getProperty(cname + ".limit");
|
||||
try {
|
||||
if (limitstr != null) limit = Math.abs(Integer.decode(limitstr));
|
||||
if (limitstr != null) this.limit = Math.abs(Integer.decode(limitstr));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String countstr = manager.getProperty(cname + ".count");
|
||||
try {
|
||||
if (countstr != null) count = Math.max(1, Math.abs(Integer.decode(countstr)));
|
||||
if (countstr != null) this.count = Math.max(1, Math.abs(Integer.decode(countstr)));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String appendstr = manager.getProperty(cname + ".append");
|
||||
try {
|
||||
if (appendstr != null) append = "true".equalsIgnoreCase(appendstr) || "1".equals(appendstr);
|
||||
if (appendstr != null) this.append = "true".equalsIgnoreCase(appendstr) || "1".equals(appendstr);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String levelstr = manager.getProperty(cname + ".level");
|
||||
@@ -256,7 +299,7 @@ public class LogFileHandler extends Handler {
|
||||
@Override
|
||||
public void flush() {
|
||||
try {
|
||||
if (stream != null) stream.flush();
|
||||
if (logstream != null) logstream.flush();
|
||||
} catch (Exception e) {
|
||||
ErrorManager err = getErrorManager();
|
||||
if (err != null) err.error(null, e, ErrorManager.FLUSH_FAILURE);
|
||||
@@ -266,7 +309,7 @@ public class LogFileHandler extends Handler {
|
||||
@Override
|
||||
public void close() throws SecurityException {
|
||||
try {
|
||||
if (stream != null) stream.close();
|
||||
if (logstream != null) logstream.close();
|
||||
} catch (Exception e) {
|
||||
ErrorManager err = getErrorManager();
|
||||
if (err != null) err.error(null, e, ErrorManager.CLOSE_FAILURE);
|
||||
|
||||
@@ -22,18 +22,21 @@ import org.redkale.util.*;
|
||||
* HTTP Server节点的配置Server
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@NodeProtocol({"HTTP"})
|
||||
public final class NodeHttpServer extends NodeServer {
|
||||
public class NodeHttpServer extends NodeServer {
|
||||
|
||||
private final HttpServer httpServer;
|
||||
protected final boolean rest;
|
||||
|
||||
protected final HttpServer httpServer;
|
||||
|
||||
public NodeHttpServer(Application application, AnyValue serconf) {
|
||||
super(application, createServer(application, serconf));
|
||||
this.httpServer = (HttpServer) server;
|
||||
this.rest = serconf == null ? false : serconf.getAnyValue("rest") != null;
|
||||
}
|
||||
|
||||
private static Server createServer(Application application, AnyValue serconf) {
|
||||
@@ -84,9 +87,9 @@ public final class NodeHttpServer extends NodeServer {
|
||||
}, WebSocketNode.class);
|
||||
}
|
||||
|
||||
protected void loadHttpServlet(final AnyValue conf, final ClassFilter<? extends Servlet> filter) throws Exception {
|
||||
protected void loadHttpServlet(final AnyValue servletsConf, final ClassFilter<? extends Servlet> filter) throws Exception {
|
||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||
final String prefix = conf == null ? "" : conf.getValue("path", "");
|
||||
final String prefix = servletsConf == null ? "" : servletsConf.getValue("path", "");
|
||||
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
||||
List<FilterEntry<? extends Servlet>> list = new ArrayList(filter.getFilterEntrys());
|
||||
list.sort((FilterEntry<? extends Servlet> o1, FilterEntry<? extends Servlet> o2) -> { //必须保证WebSocketServlet优先加载, 因为要确保其他的HttpServlet可以注入本地模式的WebSocketNode
|
||||
@@ -121,14 +124,85 @@ public final class NodeHttpServer extends NodeServer {
|
||||
ss.add(new AbstractMap.SimpleEntry<>(clazz.getName(), mappings));
|
||||
}
|
||||
}
|
||||
if (ss != null) {
|
||||
if (ss != null && sb != null) {
|
||||
Collections.sort(ss, (AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey()));
|
||||
int max = 0;
|
||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
||||
if (as.getKey().length() > max) max = as.getKey().length();
|
||||
}
|
||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
||||
sb.append(threadName).append(" Loaded ").append(as.getKey());
|
||||
sb.append(threadName).append(" Load ").append(as.getKey());
|
||||
for (int i = 0; i < max - as.getKey().length(); i++) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
|
||||
}
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||
if (rest && serverConf != null) {
|
||||
for (AnyValue restConf : serverConf.getAnyValues("rest")) {
|
||||
loadRestServlet(prefix, restConf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void loadRestServlet(final String prefix, final AnyValue restConf) throws Exception {
|
||||
if (!rest) return;
|
||||
if (restConf == null) return; //不存在REST服务
|
||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
||||
final List<AbstractMap.SimpleEntry<String, String[]>> ss = sb == null ? null : new ArrayList<>();
|
||||
|
||||
final Class baseServletClass = Class.forName(restConf.getValue("base", DefaultRestServlet.class.getName()));
|
||||
|
||||
final boolean autoload = restConf.getBoolValue("autoload", true);
|
||||
final boolean mustsign = restConf.getBoolValue("mustsign", true); //是否只加载标记@RestService的Service类
|
||||
|
||||
final Set<String> includeValues = new HashSet<>();
|
||||
final Set<String> excludeValues = new HashSet<>();
|
||||
for (AnyValue item : restConf.getAnyValues("service")) {
|
||||
if (item.getBoolValue("ignore", false)) {
|
||||
excludeValues.add(item.getValue("value", ""));
|
||||
} else {
|
||||
includeValues.add(item.getValue("value", ""));
|
||||
}
|
||||
}
|
||||
|
||||
final ClassFilter restFilter = ClassFilter.create(restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
|
||||
|
||||
super.interceptorServiceWrappers.forEach((wrapper) -> {
|
||||
final Class stype = wrapper.getType();
|
||||
RestService rs = (RestService) stype.getAnnotation(RestService.class);
|
||||
if (rs != null && rs.ignore()) return;
|
||||
if (mustsign && rs == null) return;
|
||||
if (stype.getAnnotation(LocalService.class) != null && rs == null) return;
|
||||
|
||||
final String stypename = stype.getName();
|
||||
if (!autoload && !includeValues.contains(stypename)) return;
|
||||
if (!restFilter.accept(stypename)) return;
|
||||
|
||||
RestHttpServlet servlet = httpServer.addRestServlet(wrapper.getName(), stype, wrapper.getService(), baseServletClass, prefix, (AnyValue) null);
|
||||
resourceFactory.inject(servlet, NodeHttpServer.this);
|
||||
if (finest) logger.finest("Create RestServlet[resource=" + wrapper.getName() + "] = " + servlet);
|
||||
if (ss != null) {
|
||||
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
|
||||
for (int i = 0; i < mappings.length; i++) {
|
||||
mappings[i] = prefix + mappings[i];
|
||||
}
|
||||
if (servlet.getClass().getSimpleName().charAt(0) != '_') {
|
||||
ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName(), mappings));
|
||||
}
|
||||
}
|
||||
});
|
||||
//输出信息
|
||||
if (ss != null && sb != null) {
|
||||
Collections.sort(ss, (AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey()));
|
||||
int max = 0;
|
||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
||||
if (as.getKey().length() > max) max = as.getKey().length();
|
||||
}
|
||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
||||
sb.append(threadName).append(" Load ").append(as.getKey());
|
||||
for (int i = 0; i < max - as.getKey().length(); i++) {
|
||||
sb.append(' ');
|
||||
}
|
||||
@@ -137,5 +211,4 @@ public final class NodeHttpServer extends NodeServer {
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.redkale.service.Service;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.lang.annotation.*;
|
||||
* 根据application.xml中的server节点中的protocol值来适配Server的加载逻辑
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -6,13 +6,12 @@
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.io.*;
|
||||
import static java.lang.Class.forName;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.*;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.*;
|
||||
import java.util.logging.*;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -32,7 +31,7 @@ import org.redkale.util.*;
|
||||
* Server节点的初始化配置类
|
||||
*
|
||||
*
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@@ -48,9 +47,12 @@ public abstract class NodeServer {
|
||||
//日志是否为FINE级别
|
||||
protected final boolean fine;
|
||||
|
||||
//日志是否为FINE级别
|
||||
//日志是否为FINER级别
|
||||
protected final boolean finer;
|
||||
|
||||
//日志是否为FINEST级别
|
||||
protected final boolean finest;
|
||||
|
||||
//进程主类
|
||||
protected final Application application;
|
||||
|
||||
@@ -91,6 +93,7 @@ public abstract class NodeServer {
|
||||
this.logger = Logger.getLogger(this.getClass().getSimpleName());
|
||||
this.fine = logger.isLoggable(Level.FINE);
|
||||
this.finer = logger.isLoggable(Level.FINER);
|
||||
this.finest = logger.isLoggable(Level.FINEST);
|
||||
}
|
||||
|
||||
protected Consumer<Runnable> getExecutor() throws Exception {
|
||||
@@ -162,7 +165,7 @@ public abstract class NodeServer {
|
||||
initResource(); //给 DataSource、CacheSource 注册依赖注入时的监听回调事件。
|
||||
String interceptorClass = this.serverConf.getValue("interceptor", "");
|
||||
if (!interceptorClass.isEmpty()) {
|
||||
Class clazz = forName(interceptorClass);
|
||||
Class clazz = Class.forName(interceptorClass);
|
||||
this.interceptor = (NodeInterceptor) clazz.newInstance();
|
||||
}
|
||||
|
||||
@@ -170,9 +173,9 @@ public abstract class NodeServer {
|
||||
ClassFilter<Service> serviceFilter = createServiceClassFilter();
|
||||
long s = System.currentTimeMillis();
|
||||
if (servletFilter == null) {
|
||||
ClassFilter.Loader.load(application.getHome(), serviceFilter);
|
||||
ClassFilter.Loader.load(application.getHome(), serverConf.getValue("excludelibs", "").split(";"), serviceFilter);
|
||||
} else {
|
||||
ClassFilter.Loader.load(application.getHome(), serviceFilter, servletFilter);
|
||||
ClassFilter.Loader.load(application.getHome(), serverConf.getValue("excludelibs", "").split(";"), serviceFilter, servletFilter);
|
||||
}
|
||||
long e = System.currentTimeMillis() - s;
|
||||
logger.info(this.getClass().getSimpleName() + " load filter class in " + e + " ms");
|
||||
@@ -234,6 +237,7 @@ public abstract class NodeServer {
|
||||
source.setStoreType(pt == null ? Serializable.class : (Class) pt.getActualTypeArguments()[0], valType instanceof Class ? (Class) valType : Object.class);
|
||||
if (field.getAnnotation(Transient.class) != null) source.setNeedStore(false); //必须在setStoreType之后
|
||||
application.cacheSources.add(source);
|
||||
appResFactory.register(resourceName, genericType, source);
|
||||
appResFactory.register(resourceName, CacheSource.class, source);
|
||||
field.set(src, source);
|
||||
rf.inject(source, self); //
|
||||
@@ -243,7 +247,7 @@ public abstract class NodeServer {
|
||||
NodeSncpServer sncpServer = application.findNodeSncpServer(sncpAddr);
|
||||
Set<String> gs = application.findSncpGroups(sameGroupTransport, diffGroupTransports);
|
||||
ServiceWrapper wrapper = new ServiceWrapper(CacheSourceService.class, (Service) source, resourceName, sncpServer.getSncpGroup(), gs, null);
|
||||
sncpServer.getSncpServer().addService(wrapper);
|
||||
sncpServer.getSncpServer().addSncpServlet(wrapper);
|
||||
logger.info("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService());
|
||||
}
|
||||
logger.info("[" + Thread.currentThread().getName() + "] Load Source " + source);
|
||||
@@ -268,7 +272,6 @@ public abstract class NodeServer {
|
||||
if (Modifier.isAbstract(type.getModifiers())) continue; //修饰abstract的类跳过
|
||||
if (DataSource.class.isAssignableFrom(type)) continue;
|
||||
if (CacheSource.class.isAssignableFrom(type)) continue;
|
||||
if (DataSQLListener.class.isAssignableFrom(type)) continue;
|
||||
if (DataCacheListener.class.isAssignableFrom(type)) continue;
|
||||
if (WebSocketNode.class.isAssignableFrom(type)) continue;
|
||||
}
|
||||
@@ -344,7 +347,7 @@ public abstract class NodeServer {
|
||||
});
|
||||
if (sb != null) {
|
||||
remoteServiceWrappers.forEach(y -> {
|
||||
sb.append(threadName).append(y.toSimpleString()).append(" loaded and injected").append(LINE_SEPARATOR);
|
||||
sb.append(threadName).append(y.toSimpleString()).append(" load and inject").append(LINE_SEPARATOR);
|
||||
});
|
||||
}
|
||||
//----------------- init -----------------
|
||||
@@ -353,15 +356,22 @@ public abstract class NodeServer {
|
||||
localServiceWrappers.clear();
|
||||
localServiceWrappers.addAll(swlist);
|
||||
final List<String> slist = sb == null ? null : new CopyOnWriteArrayList<>();
|
||||
CountDownLatch clds = new CountDownLatch(localServiceWrappers.size());
|
||||
localServiceWrappers.parallelStream().forEach(y -> {
|
||||
long s = System.currentTimeMillis();
|
||||
y.getService().init(y.getConf());
|
||||
long e = System.currentTimeMillis() - s;
|
||||
if (slist != null) slist.add(new StringBuilder().append(threadName).append(y.toSimpleString()).append(" loaded and inited ").append(e).append(" ms").append(LINE_SEPARATOR).toString());
|
||||
try {
|
||||
long s = System.currentTimeMillis();
|
||||
y.getService().init(y.getConf());
|
||||
long e = System.currentTimeMillis() - s;
|
||||
if (slist != null) slist.add(new StringBuilder().append(threadName).append(y.toSimpleString()).append(" load and init in ").append(e).append(" ms").append(LINE_SEPARATOR).toString());
|
||||
} finally {
|
||||
clds.countDown();
|
||||
}
|
||||
});
|
||||
Collections.sort(slist);
|
||||
clds.await();
|
||||
if (slist != null && sb != null) {
|
||||
for (String s : slist) {
|
||||
List<String> wlist = new ArrayList<>(slist); //直接使用CopyOnWriteArrayList偶尔会出现莫名的异常(CopyOnWriteArrayList源码1185行)
|
||||
Collections.sort(wlist);
|
||||
for (String s : wlist) {
|
||||
sb.append(s);
|
||||
}
|
||||
}
|
||||
@@ -391,8 +401,9 @@ public abstract class NodeServer {
|
||||
Set<InetSocketAddress> addrs = new HashSet();
|
||||
transports.forEach(t -> addrs.addAll(Arrays.asList(t.getRemoteAddresses())));
|
||||
Transport first = transports.get(0);
|
||||
Transport newTransport = new Transport(groupid, application.findGroupProtocol(first.getName()), application.getWatchFactory(),
|
||||
application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs);
|
||||
GroupInfo ginfo = application.findGroupInfo(first.getName());
|
||||
Transport newTransport = new Transport(groupid, ginfo.getProtocol(), application.getWatchFactory(),
|
||||
ginfo.getKind(), application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs);
|
||||
synchronized (application.resourceFactory) {
|
||||
transport = application.resourceFactory.find(groupid, Transport.class);
|
||||
if (transport == null) {
|
||||
@@ -414,10 +425,11 @@ public abstract class NodeServer {
|
||||
}
|
||||
return transport;
|
||||
}
|
||||
Set<InetSocketAddress> addrs = application.findGlobalGroup(group);
|
||||
GroupInfo ginfo = application.findGroupInfo(group);
|
||||
Set<InetSocketAddress> addrs = ginfo.copyAddrs();
|
||||
if (addrs == null) throw new RuntimeException("Not found <group> = " + group + " on <resources> ");
|
||||
transport = new Transport(group, application.findGroupProtocol(group), application.getWatchFactory(),
|
||||
application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs);
|
||||
transport = new Transport(group, ginfo.getProtocol(), application.getWatchFactory(),
|
||||
ginfo.getKind(), application.transportBufferPool, application.transportChannelGroup, this.sncpAddress, addrs);
|
||||
application.resourceFactory.register(group, transport);
|
||||
}
|
||||
return transport;
|
||||
|
||||
@@ -15,19 +15,27 @@ import org.redkale.util.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@NodeProtocol({"SNCP"})
|
||||
public final class NodeSncpServer extends NodeServer {
|
||||
public class NodeSncpServer extends NodeServer {
|
||||
|
||||
private final SncpServer sncpServer;
|
||||
protected final SncpServer sncpServer;
|
||||
|
||||
public NodeSncpServer(Application application, AnyValue serconf) {
|
||||
private NodeSncpServer(Application application, AnyValue serconf) {
|
||||
super(application, createServer(application, serconf));
|
||||
this.sncpServer = (SncpServer) this.server;
|
||||
this.consumer = sncpServer == null ? null : x -> sncpServer.addService(x);
|
||||
this.consumer = sncpServer == null ? null : x -> sncpServer.addSncpServlet(x);
|
||||
}
|
||||
|
||||
public static NodeServer createNodeServer(Application application, AnyValue serconf) {
|
||||
if (serconf != null && serconf.getAnyValue("rest") != null) {
|
||||
((AnyValue.DefaultAnyValue) serconf).addValue("_$sncp", "true");
|
||||
return new NodeHttpServer(application, serconf);
|
||||
}
|
||||
return new NodeSncpServer(application, serconf);
|
||||
}
|
||||
|
||||
private static Server createServer(Application application, AnyValue serconf) {
|
||||
@@ -53,7 +61,7 @@ public final class NodeSncpServer extends NodeServer {
|
||||
List<SncpServlet> servlets = sncpServer.getSncpServlets();
|
||||
Collections.sort(servlets);
|
||||
for (SncpServlet en : servlets) {
|
||||
if (sb != null) sb.append(threadName).append(" Loaded ").append(en).append(LINE_SEPARATOR);
|
||||
if (sb != null) sb.append(threadName).append(" Load ").append(en).append(LINE_SEPARATOR);
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.FINE, sb.toString());
|
||||
}
|
||||
|
||||
110
src/org/redkale/boot/apidoc-template.html
Normal file
110
src/org/redkale/boot/apidoc-template.html
Normal file
@@ -0,0 +1,110 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8"><title>接口文档(apidoc生成)</title>
|
||||
<style type="text/css">
|
||||
body {text-align: center;margin:auto;}
|
||||
a{text-decoration: none;}
|
||||
.table {margin: auto;border-collapse: collapse;border-spacing: 0;display: block;width: 100%;overflow: auto;word-break: normal;word-break: keep-all;}
|
||||
.table td,.table th{padding: 0.2rem 0.8rem 0.2rem 0.8rem;border: 1px solid #aaa;}
|
||||
.table td {text-align: left;}
|
||||
.s {font-size: 0.8rem; vertical-align: middle;}
|
||||
.subtable {border-spacing: 0;border: 0;margin:0;}
|
||||
.subtable td{border: 0;padding: 0 0 0 10px;}
|
||||
.typetable {border-spacing: 0;border: 0;margin:0;}
|
||||
.typetable td{border: 0;padding: 2px 20px 2px 10px;}
|
||||
.typetable .l{border-bottom: 1px solid red;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script>
|
||||
var createhtml = function (jsoncontent) {
|
||||
var classmap = jsoncontent.types;
|
||||
var html = [];
|
||||
html.push('<div style="width:' + Math.floor(window.screen.width * 0.9) + 'px;margin:0 auto;text-align: center;">');
|
||||
html.push('<br/><br/><table class="table" align="center">');
|
||||
for (var i = 0; i < jsoncontent.servers.length; i++) {
|
||||
var servlets = jsoncontent.servers[i].servlets;
|
||||
if (servlets.length && (servlets[0].comment || "").indexOf("【") === 0) {
|
||||
servlets.sort(function (a, b) {
|
||||
return a.comment > b.comment ? -1 : (a.comment == b.comment ? 0 : 1);
|
||||
});
|
||||
}
|
||||
for (var j = 0; j < servlets.length; j++) {
|
||||
var servlet = servlets[j];
|
||||
if (html.length > 2) html.push(' <tr><th colspan="5" style="border-bottom:0;"> </th></tr>');
|
||||
html.push(' <tr><th colspan="5" style="border-top:' + ((html.length > 2) ? 0 : 1) + ';">' + (servlet.comment || '未知模块') + '</th></tr>');
|
||||
html.push(' <tr><th>请求URL</th><th>描 述</th><th>鉴 权</th><th>参 数 <span style="font-size:12px;">(粗体: 必填项; 红色: Header; 蓝色: Cookie)</span></th><th>输 出</th></tr>');
|
||||
for (var k = 0; k < servlet.actions.length; k++) {
|
||||
var action = servlet.actions[k];
|
||||
html.push(' <tr>');
|
||||
html.push('<td style="color:#ff00ff;">' + action.url + '</td>');
|
||||
html.push('<td>' + action.comment + '</td>');
|
||||
html.push('<td class="s">模块ID: ' + servlet.moduleid + '<br/>操作ID: ' + action.actionid + '<br/>需鉴权: ' + (action.auth ? '<font style="font-weight:bold;color:green;">true</font>' : '<font color=red>false</font>') + '</td>');
|
||||
var paramshtml = [];
|
||||
paramshtml.push('<table class="subtable">');
|
||||
for (var p = 0; p < action.params.length; p++) {
|
||||
var param = action.params[p];
|
||||
var t = param.type.substring(param.type.lastIndexOf('.') + 1);
|
||||
if (classmap[param.type.replace('[]', '')]) {
|
||||
t = '<a href="#' + param.type.replace('[]', '') + '">' + t + '</a>';
|
||||
}
|
||||
if (param.name == '&') {
|
||||
paramshtml.push('<tr><td style="font-size:12px;">内置 </td><td> ' + t + '</td><td> 当前用户</td></tr>');
|
||||
} else {
|
||||
var w = param.required ? "font-weight:bold;" : "";
|
||||
var c = ' style="' + w + '"';
|
||||
if (param.src == "HEADER") c = ' style="color:red;' + w + '"';
|
||||
if (param.src == "COOKIE") c = ' style="color:blue;' + w + '"';
|
||||
paramshtml.push('<tr><td ' + c + '> ' + param.name + ' </td><td> ' + t + '</td><td> ' + param.comment + '</td></tr>');
|
||||
}
|
||||
}
|
||||
paramshtml.push('</table>');
|
||||
html.push('<td class="s" style="padding:0 5px;">' + paramshtml.join('') + '</td>');
|
||||
var rs = [];
|
||||
rs.push(action.result.replace(/</g, "<").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>');
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var type in classmap) {
|
||||
html.push(' <tr><th colspan="5" style="border-bottom:0;"> </th></tr>');
|
||||
html.push(' <tr id="' + type + '"><th colspan="5" style="border-top:0;">' + type + '</th></tr>');
|
||||
html.push(' <tr><td colspan="5"><table class="typetable">');
|
||||
for (var fieldname in classmap[type]) {
|
||||
var field = classmap[type][fieldname];
|
||||
var t = field.type.replace(/</g, "<").replace(/>/g, ">").replace(/\$/g, ".").replace(/([a-zA-Z0-9_\$]+\.)+/g, "");
|
||||
if (t == 'boolean' || t == 'short' || t == 'int' || t == 'long' || t == 'float' || t == 'double'
|
||||
|| t == 'boolean[]' || t == 'short[]' || t == 'int[]' || t == 'long[]' || t == 'float[]' || t == 'double[]') {
|
||||
t = '<font color=blue>' + t + '</font>';
|
||||
} else if (t == 'String' || t == 'String[]' || t == 'LongRange' || t.indexOf('Map<') === 0) {
|
||||
t = '<font color=red>' + t + '</font>';
|
||||
}
|
||||
var c = (field.comment || '');
|
||||
if (field.primary) {
|
||||
c = '【主键】 ' + c;
|
||||
} else if (!field.updatable) {
|
||||
c = '【只读】 ' + c;
|
||||
}
|
||||
html.push(' <tr class="l"><td>' + fieldname + '</td><td>' + t + '</td><td colspan="2">' + c + '</td></tr>');
|
||||
}
|
||||
html.push(' </table></td></tr>');
|
||||
}
|
||||
html.push('</table><br/><br/><br/>');
|
||||
html.push('</div>');
|
||||
return html.join('');
|
||||
};
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var jsoncontent = '${content}'; //这里必须要用单引号引起来
|
||||
document.write(createhtml(jsoncontent));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* 提供RedKale服务器的启动、初始化和加载功能
|
||||
* 提供Redkale服务器的启动、初始化和加载功能
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.lang.reflect.Type;
|
||||
/**
|
||||
* 对不明类型的对象进行序列化; BSON序列化时将对象的类名写入Writer,JSON则不写入。
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化的泛型类型
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.*;
|
||||
* 支持一定程度的泛型。
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 反解析的数组元素类型
|
||||
@@ -28,31 +28,53 @@ public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
||||
|
||||
private final Class componentClass;
|
||||
|
||||
private final Decodeable<Reader, T> decoder;
|
||||
protected final Decodeable<Reader, T> decoder;
|
||||
|
||||
private boolean inited = false;
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
public ArrayDecoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
if (type instanceof GenericArrayType) {
|
||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
||||
this.componentType = ((Class) type).getComponentType();
|
||||
} else {
|
||||
throw new ConvertException("(" + type + ") is not a array type");
|
||||
try {
|
||||
if (type instanceof GenericArrayType) {
|
||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
||||
this.componentType = ((Class) type).getComponentType();
|
||||
} else {
|
||||
throw new ConvertException("(" + type + ") is not a array type");
|
||||
}
|
||||
if (this.componentType instanceof ParameterizedType) {
|
||||
this.componentClass = (Class) ((ParameterizedType) this.componentType).getRawType();
|
||||
} else {
|
||||
this.componentClass = (Class) this.componentType;
|
||||
}
|
||||
factory.register(type, this);
|
||||
this.decoder = factory.loadDecoder(this.componentType);
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
if (this.componentType instanceof ParameterizedType) {
|
||||
this.componentClass = (Class) ((ParameterizedType) this.componentType).getRawType();
|
||||
} else {
|
||||
this.componentClass = (Class) this.componentType;
|
||||
}
|
||||
factory.register(type, this);
|
||||
this.decoder = factory.loadDecoder(this.componentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T[] convertFrom(Reader in) {
|
||||
final int len = in.readArrayB();
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (this.decoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final Decodeable<Reader, T> localdecoder = this.decoder;
|
||||
final List<T> result = new ArrayList();
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.lang.reflect.*;
|
||||
* 支持一定程度的泛型。
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化的数组元素类型
|
||||
@@ -29,19 +29,30 @@ public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
||||
|
||||
private final Encodeable<Writer, Object> encoder;
|
||||
|
||||
private boolean inited = false;
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
public ArrayEncoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
if (type instanceof GenericArrayType) {
|
||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
||||
this.componentType = ((Class) type).getComponentType();
|
||||
} else {
|
||||
throw new ConvertException("(" + type + ") is not a array type");
|
||||
try {
|
||||
if (type instanceof GenericArrayType) {
|
||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
||||
this.componentType = ((Class) type).getComponentType();
|
||||
} else {
|
||||
throw new ConvertException("(" + type + ") is not a array type");
|
||||
}
|
||||
factory.register(type, this);
|
||||
this.encoder = factory.loadEncoder(this.componentType);
|
||||
this.anyEncoder = factory.getAnyEncoder();
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
factory.register(type, this);
|
||||
this.encoder = factory.loadEncoder(this.componentType);
|
||||
this.anyEncoder = factory.getAnyEncoder();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,6 +66,17 @@ public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
||||
out.writeArrayE();
|
||||
return;
|
||||
}
|
||||
if (this.encoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out.writeArrayB(value.length);
|
||||
final Type comp = this.componentType;
|
||||
boolean first = true;
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.Collection;
|
||||
* 支持一定程度的泛型。
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 反解析的集合元素类型
|
||||
@@ -30,18 +30,29 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
|
||||
|
||||
protected Creator<Collection<T>> creator;
|
||||
|
||||
private final Decodeable<Reader, T> decoder;
|
||||
protected final Decodeable<Reader, T> decoder;
|
||||
|
||||
private boolean inited = false;
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
public CollectionDecoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.componentType = pt.getActualTypeArguments()[0];
|
||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
||||
factory.register(type, this);
|
||||
this.decoder = factory.loadDecoder(this.componentType);
|
||||
} else {
|
||||
throw new ConvertException("collectiondecoder not support the type (" + type + ")");
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.componentType = pt.getActualTypeArguments()[0];
|
||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
||||
factory.register(type, this);
|
||||
this.decoder = factory.loadDecoder(this.componentType);
|
||||
} else {
|
||||
throw new ConvertException("collectiondecoder not support the type (" + type + ")");
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +60,17 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
|
||||
public Collection<T> convertFrom(Reader in) {
|
||||
final int len = in.readArrayB();
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
if (this.decoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final Decodeable<Reader, T> localdecoder = this.decoder;
|
||||
final Collection<T> result = this.creator.create();
|
||||
if (len == Reader.SIGN_NOLENGTH) {
|
||||
|
||||
@@ -10,10 +10,12 @@ import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 对象集合的序列化.
|
||||
* 集合大小不能超过 32767。 在BSON中集合大小设定的是short,对于大于32767长度的集合传输会影响性能,所以没有采用int存储。
|
||||
* 集合大小不能超过 32767。 在BSON中集合大小设定的是short,对于大于32767长度的集合传输会影响性能,所以没有采用int存储。
|
||||
* 支持一定程度的泛型。
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化的集合元素类型
|
||||
*/
|
||||
@@ -24,17 +26,28 @@ public final class CollectionEncoder<T> implements Encodeable<Writer, Collection
|
||||
|
||||
private final Encodeable<Writer, Object> encoder;
|
||||
|
||||
private boolean inited = false;
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
public CollectionEncoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
if (type instanceof ParameterizedType) {
|
||||
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
if (t instanceof TypeVariable) {
|
||||
this.encoder = factory.getAnyEncoder();
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
if (t instanceof TypeVariable) {
|
||||
this.encoder = factory.getAnyEncoder();
|
||||
} else {
|
||||
this.encoder = factory.loadEncoder(t);
|
||||
}
|
||||
} else {
|
||||
this.encoder = factory.loadEncoder(t);
|
||||
this.encoder = factory.getAnyEncoder();
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
} else {
|
||||
this.encoder = factory.getAnyEncoder();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +62,17 @@ public final class CollectionEncoder<T> implements Encodeable<Writer, Collection
|
||||
out.writeArrayE();
|
||||
return;
|
||||
}
|
||||
if (this.encoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out.writeArrayB(value.size());
|
||||
boolean first = true;
|
||||
for (Object v : value) {
|
||||
|
||||
@@ -9,7 +9,7 @@ package org.redkale.convert;
|
||||
* 序列化操作类
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
|
||||
@@ -13,7 +13,7 @@ import static java.lang.annotation.RetentionPolicy.*;
|
||||
* 依附在setter、getter方法、字段进行简单的配置
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -8,7 +8,7 @@ package org.redkale.convert;
|
||||
/**
|
||||
* ConvertColumn 对应的实体类
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
*/
|
||||
public final class ConvertColumnEntry {
|
||||
|
||||
@@ -12,7 +12,7 @@ import static java.lang.annotation.RetentionPolicy.*;
|
||||
/**
|
||||
* ConvertColumn 的多用类
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.lang.annotation.*;
|
||||
* 该值必须是全局唯一
|
||||
* 使用场景: 当BSON序列化为了不指定class可以使用@ConvertEntity来取个别名。关联方法: Reader.readClassName() 和 Writer.writeClassName(String value) 。
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
*/
|
||||
@Inherited
|
||||
|
||||
@@ -6,7 +6,7 @@ package org.redkale.convert;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ConvertException extends RuntimeException {
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.redkale.util.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
@@ -104,6 +104,14 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
||||
this.register(double[].class, DoubleArraySimpledCoder.instance);
|
||||
this.register(String[].class, StringArraySimpledCoder.instance);
|
||||
//---------------------------------------------------------
|
||||
this.register(HttpCookie.class, new Creator<HttpCookie>() {
|
||||
@Override
|
||||
@Creator.ConstructorParameters({"name", "value"})
|
||||
public HttpCookie create(Object... params) {
|
||||
return new HttpCookie((String) params[0], (String) params[1]);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +212,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
||||
/**
|
||||
* 使所有类的所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false
|
||||
*
|
||||
* @param skipIgnore
|
||||
* @param skipIgnore 忽略ignore
|
||||
*
|
||||
* @return 自身
|
||||
*/
|
||||
@@ -387,7 +395,9 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
||||
} else if (clazz == Object.class) {
|
||||
od = new ObjectDecoder(type);
|
||||
decoder = od;
|
||||
} else if (!clazz.getName().startsWith("java.") || clazz.getName().startsWith("java.awt.geom.Point2D")) {
|
||||
} else if (!clazz.getName().startsWith("java.")
|
||||
|| java.net.HttpCookie.class == clazz
|
||||
|| clazz.getName().startsWith("java.awt.geom.Point2D")) {
|
||||
Decodeable simpleCoder = null;
|
||||
for (final Method method : clazz.getDeclaredMethods()) {
|
||||
if (!Modifier.isStatic(method.getModifiers())) continue;
|
||||
@@ -467,7 +477,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
||||
encoder = new MapEncoder(this, type);
|
||||
} else if (clazz == Object.class) {
|
||||
return (Encodeable<W, E>) this.anyEncoder;
|
||||
} else if (!clazz.getName().startsWith("java.")) {
|
||||
} else if (!clazz.getName().startsWith("java.") || java.net.HttpCookie.class == clazz) {
|
||||
Encodeable simpleCoder = null;
|
||||
for (final Method method : clazz.getDeclaredMethods()) {
|
||||
if (!Modifier.isStatic(method.getModifiers())) continue;
|
||||
|
||||
@@ -7,7 +7,7 @@ package org.redkale.convert;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
*/
|
||||
public enum ConvertType {
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.redkale.util.Attribute;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
@@ -88,6 +88,6 @@ public final class DeMember<R extends Reader, T, F> implements Comparable<DeMemb
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeMember{" + "attribute=" + attribute.field() + ", decoder=" + decoder + '}';
|
||||
return "DeMember{" + "attribute=" + attribute.field() + ", decoder=" + (decoder == null ? null : decoder.getClass().getName()) + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.lang.reflect.Type;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.redkale.util.Attribute;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <W> Writer输出的子类
|
||||
@@ -81,6 +81,6 @@ public final class EnMember<W extends Writer, T, F> implements Comparable<EnMemb
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EnMember{" + "attribute=" + attribute.field() + ", encoder=" + encoder + '}';
|
||||
return "EnMember{" + "attribute=" + attribute.field() + ", encoder=" + (encoder == null ? null : encoder.getClass().getName()) + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.lang.reflect.Type;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <W> Writer输出的子类
|
||||
|
||||
@@ -12,7 +12,9 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <K> Map key的数据类型
|
||||
* @param <V> Map value的数据类型
|
||||
@@ -28,27 +30,49 @@ public final class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
|
||||
|
||||
protected Creator<Map<K, V>> creator;
|
||||
|
||||
private final Decodeable<Reader, K> keyDecoder;
|
||||
protected final Decodeable<Reader, K> keyDecoder;
|
||||
|
||||
private final Decodeable<Reader, V> valueDecoder;
|
||||
protected final Decodeable<Reader, V> valueDecoder;
|
||||
|
||||
private boolean inited = false;
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
public MapDecoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.keyType = pt.getActualTypeArguments()[0];
|
||||
this.valueType = pt.getActualTypeArguments()[1];
|
||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
||||
factory.register(type, this);
|
||||
this.keyDecoder = factory.loadDecoder(this.keyType);
|
||||
this.valueDecoder = factory.loadDecoder(this.valueType);
|
||||
} else {
|
||||
throw new ConvertException("mapdecoder not support the type (" + type + ")");
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
final ParameterizedType pt = (ParameterizedType) type;
|
||||
this.keyType = pt.getActualTypeArguments()[0];
|
||||
this.valueType = pt.getActualTypeArguments()[1];
|
||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
||||
factory.register(type, this);
|
||||
this.keyDecoder = factory.loadDecoder(this.keyType);
|
||||
this.valueDecoder = factory.loadDecoder(this.valueType);
|
||||
} else {
|
||||
throw new ConvertException("mapdecoder not support the type (" + type + ")");
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<K, V> convertFrom(Reader in) {
|
||||
if (this.keyDecoder == null || this.valueDecoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final int len = in.readMapB();
|
||||
if (len == Reader.SIGN_NULL) return null;
|
||||
final Map<K, V> result = this.creator.create();
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.Map;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <K> Map key的数据类型
|
||||
@@ -27,15 +27,26 @@ public final class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
|
||||
|
||||
private final Encodeable<Writer, V> valencoder;
|
||||
|
||||
private boolean inited = false;
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
public MapEncoder(final ConvertFactory factory, final Type type) {
|
||||
this.type = type;
|
||||
if (type instanceof ParameterizedType) {
|
||||
final Type[] pt = ((ParameterizedType) type).getActualTypeArguments();
|
||||
this.keyencoder = factory.loadEncoder(pt[0]);
|
||||
this.valencoder = factory.loadEncoder(pt[1]);
|
||||
} else {
|
||||
this.keyencoder = factory.getAnyEncoder();
|
||||
this.valencoder = factory.getAnyEncoder();
|
||||
try {
|
||||
if (type instanceof ParameterizedType) {
|
||||
final Type[] pt = ((ParameterizedType) type).getActualTypeArguments();
|
||||
this.keyencoder = factory.loadEncoder(pt[0]);
|
||||
this.valencoder = factory.loadEncoder(pt[1]);
|
||||
} else {
|
||||
this.keyencoder = factory.getAnyEncoder();
|
||||
this.valencoder = factory.getAnyEncoder();
|
||||
}
|
||||
} finally {
|
||||
inited = true;
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +57,18 @@ public final class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
|
||||
out.writeNull();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.keyencoder == null || this.valencoder == null) {
|
||||
if (!this.inited) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out.writeMapB(values.size());
|
||||
boolean first = true;
|
||||
for (Map.Entry<K, V> en : values.entrySet()) {
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.redkale.util.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.util.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <W> Writer输出的子类
|
||||
@@ -121,7 +121,7 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value != null && value.getClass() != this.typeClass) {
|
||||
if (value.getClass() != this.typeClass) {
|
||||
final Class clz = value.getClass();
|
||||
if (out.needWriteClassName()) out.writeClassName(factory.getEntityAlias(clz));
|
||||
factory.loadEncoder(clz).convertTo(out, value);
|
||||
|
||||
@@ -8,7 +8,7 @@ package org.redkale.convert;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.lang.reflect.Type;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
|
||||
@@ -10,7 +10,7 @@ import org.redkale.util.Attribute;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,8 @@ import static org.redkale.convert.Reader.SIGN_NULL;
|
||||
import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -7,11 +7,12 @@ package org.redkale.convert.bson;
|
||||
|
||||
import java.nio.*;
|
||||
import java.util.function.*;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@@ -78,20 +79,14 @@ public class BsonByteBufferWriter extends BsonWriter {
|
||||
if (!buffer.hasRemaining()) {
|
||||
buffer.flip();
|
||||
buffer = supplier.get();
|
||||
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
|
||||
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
|
||||
bufs[this.buffers.length] = buffer;
|
||||
this.buffers = bufs;
|
||||
this.buffers = Utility.append(this.buffers, buffer);
|
||||
this.index++;
|
||||
}
|
||||
int len = buffer.remaining();
|
||||
int size = 0;
|
||||
while (len < byteLength) {
|
||||
buffer = supplier.get();
|
||||
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
|
||||
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
|
||||
bufs[this.buffers.length] = buffer;
|
||||
this.buffers = bufs;
|
||||
this.buffers = Utility.append(this.buffers, buffer);
|
||||
len += buffer.remaining();
|
||||
size++;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.redkale.util.*;
|
||||
*
|
||||
* </pre></blockquote>
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.redkale.convert.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.redkale.util.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,7 @@ import org.redkale.convert.SimpledCoder;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化/反解析的数据类型
|
||||
|
||||
@@ -9,6 +9,8 @@ import java.io.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -9,6 +9,8 @@ import java.io.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.redkale.util.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.math.BigInteger;
|
||||
* BigInteger 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
||||
* boolean[] 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
||||
* boolean 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
||||
* byte[] 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
||||
* byte 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
||||
/**
|
||||
* char[] 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -10,7 +10,7 @@ import org.redkale.convert.*;
|
||||
/**
|
||||
* CharSequence 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
||||
/**
|
||||
* char 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.convert.*;
|
||||
* java.nio.channels.CompletionHandler 的SimpledCoder实现, 只输出null
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.redkale.util.*;
|
||||
* Dlong 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.Date;
|
||||
* Date 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
||||
/**
|
||||
* double[] 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
||||
/**
|
||||
* double 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
||||
* 枚举 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
||||
/**
|
||||
* float[] 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
||||
/**
|
||||
* float 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.net.*;
|
||||
* InetAddress 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
||||
/**
|
||||
* int[] 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
||||
/**
|
||||
* int 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
||||
* long[] 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
||||
/**
|
||||
* long 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.redkale.convert.Writer;
|
||||
* Number 的SimpledCoder实现
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.redkale.convert.*;
|
||||
/**
|
||||
* Pattern 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
||||
/**
|
||||
* short[] 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
||||
/**
|
||||
* short 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
||||
/**
|
||||
* String[] 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.convert.Writer;
|
||||
/**
|
||||
* String 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.redkale.convert.SimpledCoder;
|
||||
* Type 的SimpledCoder实现 只支持Type的子类Class
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.redkale.convert.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.redkale.convert.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
|
||||
@@ -11,7 +11,10 @@ import org.redkale.convert.*;
|
||||
import static org.redkale.convert.Reader.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 只支持UTF-8格式
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.redkale.util.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@@ -84,20 +84,14 @@ public class JsonByteBufferWriter extends JsonWriter {
|
||||
if (!buffer.hasRemaining()) {
|
||||
buffer.flip();
|
||||
buffer = supplier.get();
|
||||
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
|
||||
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
|
||||
bufs[this.buffers.length] = buffer;
|
||||
this.buffers = bufs;
|
||||
this.buffers = Utility.append(this.buffers, buffer);
|
||||
this.index++;
|
||||
}
|
||||
int len = buffer.remaining();
|
||||
int size = 0;
|
||||
while (len < byteLength) {
|
||||
buffer = supplier.get();
|
||||
ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1];
|
||||
System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length);
|
||||
bufs[this.buffers.length] = buffer;
|
||||
this.buffers = bufs;
|
||||
this.buffers = Utility.append(this.buffers, buffer);
|
||||
len += buffer.remaining();
|
||||
size++;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import org.redkale.util.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.redkale.util.DLong;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.redkale.util.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,7 @@ import org.redkale.convert.SimpledCoder;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化/反解析的数据类型
|
||||
|
||||
@@ -10,6 +10,8 @@ import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
class JsonStreamReader extends JsonByteBufferReader {
|
||||
|
||||
@@ -13,6 +13,8 @@ import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
class JsonStreamWriter extends JsonByteBufferWriter {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user