Compare commits
287 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
bb77681445 | ||
|
|
d2a3291f13 | ||
|
|
116e82115b | ||
|
|
e0b5067949 | ||
|
|
8e639e32a3 | ||
|
|
5a1586bc6a | ||
|
|
30b6ddc4f4 | ||
|
|
0667c6a12e | ||
|
|
6eb9429b68 | ||
|
|
91f32684ef | ||
|
|
fc475d6253 | ||
|
|
3df13a3b17 | ||
|
|
3d0bd3a5c2 | ||
|
|
42c188867a | ||
|
|
a3647f79ac | ||
|
|
f83fded877 | ||
|
|
df42be86d6 | ||
|
|
d22b44f1f9 | ||
|
|
1592938d99 | ||
|
|
a3681ca698 | ||
|
|
5f1556e5cb | ||
|
|
64bc543df2 | ||
|
|
36f03344bd | ||
|
|
d764b741d4 | ||
|
|
e5a83c51f3 | ||
|
|
42e7ac298e | ||
|
|
bf9098df86 | ||
|
|
d44e45166e | ||
|
|
07304e61d9 | ||
|
|
c69fcc25db | ||
|
|
72e25d653b | ||
|
|
c3fde23d77 | ||
|
|
1369bd3e9e | ||
|
|
2c70162798 | ||
|
|
5db8426553 | ||
|
|
3c667d88aa | ||
|
|
7a11b7887c | ||
|
|
bfbc48a597 | ||
|
|
ba14c59baa | ||
|
|
63d7e85fb4 | ||
|
|
66c2f0970f | ||
|
|
e78d590fc2 | ||
|
|
8f7ca376a9 | ||
|
|
82b041e6d5 | ||
|
|
5ae6afa20e | ||
|
|
1aeae47a89 | ||
|
|
7bf73b60b5 | ||
|
|
7e26ddddd5 | ||
|
|
593ed3e7e0 | ||
|
|
c0ff67df73 | ||
|
|
5489e01987 | ||
|
|
65910f8b66 | ||
|
|
ea277f4ea3 | ||
|
|
02fc248fcf | ||
|
|
1b42a4241a | ||
|
|
7ed0020b1d | ||
|
|
94bb11329d | ||
|
|
fccf314282 | ||
|
|
35029ad796 | ||
|
|
ea059594f0 | ||
|
|
839c742423 | ||
|
|
00b6910986 | ||
|
|
01da67dbf8 | ||
|
|
73a7864e09 | ||
|
|
a996ab5eb5 | ||
|
|
0d6a778d9c | ||
|
|
34ddd0d65e | ||
|
|
4f950d5874 | ||
|
|
6b228f1fc9 | ||
|
|
521a0d4cbb | ||
|
|
9ba2571ed1 | ||
|
|
cfcdb093e7 | ||
|
|
9c3c7e414a | ||
|
|
a7781322c7 | ||
|
|
34a0fef035 | ||
|
|
4dfda3ec51 | ||
|
|
fd0a6b94e9 | ||
|
|
1af2457cc7 | ||
|
|
f4bd6074f1 | ||
|
|
5b6e01ecb8 | ||
|
|
85844276ed | ||
|
|
af74bad593 | ||
|
|
f82becfe62 | ||
|
|
a98d5f32a1 | ||
|
|
a2d4b6ec37 | ||
|
|
29a80e95c7 | ||
|
|
41c1ea32d1 | ||
|
|
c100207302 | ||
|
|
5b4b08b6ce | ||
|
|
a6a3890e70 | ||
|
|
d3d24529a6 | ||
|
|
5593a518fc | ||
|
|
511a31bf95 | ||
|
|
999f55222b | ||
|
|
56cd881a99 | ||
|
|
a0439518f3 |
@@ -21,4 +21,4 @@
|
||||
|
||||
由于RedKale使用了JDK 8 内置的ASM包,所以需要在源码工程中的编译器选项中加入: <b>-XDignore.symbol.file=true</b>
|
||||
|
||||
<h5>详情请访问: <a href='http://www.redkale.org' target='_blank'>http://www.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
|
||||
|
||||
@@ -5,10 +5,12 @@ handlers = java.util.logging.ConsoleHandler
|
||||
############################################################
|
||||
.level = FINE
|
||||
|
||||
org.level = INFO
|
||||
java.level = INFO
|
||||
javax.level = INFO
|
||||
com.sun.level = INFO
|
||||
sun.level = INFO
|
||||
jdk.level = INFO
|
||||
|
||||
|
||||
java.util.logging.FileHandler.level = FINE
|
||||
#10M
|
||||
|
||||
158
pom.xml
158
pom.xml
@@ -1,158 +0,0 @@
|
||||
<?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>
|
||||
</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
|
||||
@@ -88,7 +95,7 @@
|
||||
responsePoolSize: Response池的大小,默认: CPU核数*256
|
||||
readTimeoutSecond: 读操作超时秒数, 默认0, 表示永久不超时
|
||||
writeTimeoutSecond: 写操作超时秒数, 默认0, 表示永久不超时
|
||||
nodeInterceptor: 启动/关闭NodeServer时被调用的拦截器实现类,必须是org.redkale.boot.NodeInterceptor的子类,默认为null
|
||||
interceptor: 启动/关闭NodeServer时被调用的拦截器实现类,必须是org.redkale.boot.NodeInterceptor的子类,默认为null
|
||||
-->
|
||||
<server protocol="HTTP" host="127.0.0.1" port="6060" root="root" lib="">
|
||||
|
||||
@@ -114,13 +121,32 @@
|
||||
-->
|
||||
<service value="com.xxx.XXX2Service" name="" groups="xxx;yyy"/>
|
||||
<!-- 给Service增加配置属性 -->
|
||||
<service value="com.xxx.XXX1Service">
|
||||
<property name="xxxxxx" value="XXXXXXXX"/>
|
||||
<service value="com.xxx.XXX1Service">
|
||||
<!-- property节点值在 public void init(AnyValue conf) 方法中可以通过 AnyValue properties = conf.getAnyValue("properties");获取 -->
|
||||
<property name="xxxxxx" value="XXXXXXXX"/>
|
||||
<property name="xxxxxx" value="XXXXXXXX"/>
|
||||
</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="false" 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值。
|
||||
@@ -131,6 +157,7 @@
|
||||
</request>
|
||||
|
||||
<!--
|
||||
【节点在<server>中唯一】
|
||||
当Server为HTTP协议时, response节点才有效。
|
||||
defcookie 节点: 当response里输出的cookie没有指定domain 和path时,使用该节点的默认值。
|
||||
如果addheader、setheader 的value值以request.parameters.开头则表示从request.parameters中获取对应的parameter值
|
||||
@@ -143,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前缀 默认为空
|
||||
@@ -153,26 +205,6 @@
|
||||
excludes: 当autoload="true", 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开
|
||||
-->
|
||||
<servlets path="/pipes" autoload="true" includes="" excludes="">
|
||||
<!--
|
||||
当Server为HTTP协议时,ResourceServlet才有效. 默认存在一个有默认属性的resource-servlet节点
|
||||
webroot: web资源的根目录, 默认取server节点中的root值
|
||||
-->
|
||||
<resource-servlet webroot="root">
|
||||
<!--
|
||||
资源缓存的配置, 默认存在一个含默认属性的caches节点
|
||||
limit: 资源缓存最大容量, 默认: 0, 为0表示不缓存, 单位可以是B、K、M、G,不区分大小写
|
||||
lengthmax: 可缓存的文件大小上限, 默认: 1M(超过1M的文件不会被缓存)
|
||||
-->
|
||||
<caches limit="0M" lengthmax="1M" />
|
||||
<!--
|
||||
支持类似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" />
|
||||
|
||||
@@ -5,7 +5,6 @@ handlers = java.util.logging.ConsoleHandler,java.util.logging.FileHandler
|
||||
############################################################
|
||||
.level = FINE
|
||||
|
||||
org.level = INFO
|
||||
sun.level = INFO
|
||||
java.level = INFO
|
||||
javax.level = INFO
|
||||
|
||||
48
src/META-INF/persistence-template.xml
Normal file
48
src/META-INF/persistence-template.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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
|
||||
-->
|
||||
<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>
|
||||
@@ -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
|
||||
}
|
||||
@@ -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,25 @@ 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
|
||||
*/
|
||||
String schema() default "";
|
||||
|
||||
}
|
||||
|
||||
154
src/org/redkale/boot/ApiDocs.java
Normal file
154
src/org/redkale/boot/ApiDocs.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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.Column;
|
||||
import org.redkale.convert.json.JsonConvert;
|
||||
import org.redkale.net.http.*;
|
||||
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, String>>> typesmap = new LinkedHashMap<>();
|
||||
for (NodeServer node : app.servers) {
|
||||
if (!(node instanceof NodeHttpServer)) continue;
|
||||
final Map<String, Object> map = new LinkedHashMap<>();
|
||||
serverList.add(map);
|
||||
HttpServer server = node.getServer();
|
||||
map.put("address", server.getSocketAddress());
|
||||
List<Map<String, Object>> servletsList = new ArrayList<>();
|
||||
map.put("servlets", servletsList);
|
||||
for (HttpServlet servlet : server.getPrepareServlet().getServlets()) {
|
||||
if (!(servlet instanceof HttpServlet)) continue;
|
||||
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
|
||||
if (ws == null) {
|
||||
System.err.println(servlet + " not found @WebServlet");
|
||||
continue;
|
||||
}
|
||||
final Map<String, Object> servletmap = new LinkedHashMap<>();
|
||||
String prefix = _prefix(servlet);
|
||||
String[] mappings = ws.value();
|
||||
if (prefix != null && !prefix.isEmpty()) {
|
||||
for (int i = 0; i < mappings.length; i++) {
|
||||
mappings[i] = prefix + mappings[i];
|
||||
}
|
||||
}
|
||||
servletmap.put("mappings", mappings);
|
||||
servletmap.put("moduleid", ws.moduleid());
|
||||
servletmap.put("name", ws.name());
|
||||
servletmap.put("comment", ws.comment());
|
||||
|
||||
List<Map> actionsList = new ArrayList<>();
|
||||
servletmap.put("actions", actionsList);
|
||||
for (Method method : servlet.getClass().getMethods()) {
|
||||
if (method.getParameterCount() != 2) continue;
|
||||
WebAction action = method.getAnnotation(WebAction.class);
|
||||
if (action == null) continue;
|
||||
final Map<String, Object> actionmap = new LinkedHashMap<>();
|
||||
actionmap.put("url", prefix + action.url());
|
||||
actionmap.put("auth", method.getAnnotation(AuthIgnore.class) == null);
|
||||
actionmap.put("actionid", action.actionid());
|
||||
actionmap.put("comment", action.comment());
|
||||
List<Map> paramsList = new ArrayList<>();
|
||||
actionmap.put("params", paramsList);
|
||||
for (WebParam param : method.getAnnotationsByType(WebParam.class)) {
|
||||
final Map<String, Object> parammap = new LinkedHashMap<>();
|
||||
final boolean isarray = param.type().isArray();
|
||||
final Class ptype = isarray ? param.type().getComponentType() : param.type();
|
||||
parammap.put("name", param.name());
|
||||
parammap.put("radix", param.radix());
|
||||
parammap.put("type", ptype.getName() + (isarray ? "[]" : ""));
|
||||
parammap.put("src", param.src());
|
||||
parammap.put("comment", param.comment());
|
||||
paramsList.add(parammap);
|
||||
if (ptype.isPrimitive() || ptype == String.class) continue;
|
||||
if (typesmap.containsKey(ptype.getName())) continue;
|
||||
|
||||
final Map<String, Map<String, String>> typemap = new LinkedHashMap<>();
|
||||
Class loop = ptype;
|
||||
do {
|
||||
if (loop == null || loop.isInterface()) break;
|
||||
for (Field field : loop.getDeclaredFields()) {
|
||||
if (Modifier.isFinal(field.getModifiers())) continue;
|
||||
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||
|
||||
Map<String, String> fieldmap = new LinkedHashMap<>();
|
||||
fieldmap.put("type", field.getType().isArray() ? (field.getType().getComponentType().getName() + "[]") : field.getGenericType().getTypeName());
|
||||
|
||||
Comment comment = field.getAnnotation(Comment.class);
|
||||
if (comment != null) {
|
||||
fieldmap.put("comment", comment.value());
|
||||
} else {
|
||||
Column col = field.getAnnotation(Column.class);
|
||||
if (col != null) fieldmap.put("comment", col.comment());
|
||||
}
|
||||
|
||||
if (servlet.getClass().getAnnotation(Rest.RestDynamic.class) != null) {
|
||||
if (field.getAnnotation(RestAddress.class) != null) continue;
|
||||
}
|
||||
|
||||
typemap.put(field.getName(), fieldmap);
|
||||
}
|
||||
} while ((loop = loop.getSuperclass()) != Object.class);
|
||||
|
||||
typesmap.put(ptype.getName(), typemap);
|
||||
}
|
||||
actionmap.put("result", action.result());
|
||||
actionsList.add(actionmap);
|
||||
}
|
||||
actionsList.sort((o1, o2) -> ((String) o1.get("url")).compareTo((String) o2.get("url")));
|
||||
servletsList.add(servletmap);
|
||||
}
|
||||
servletsList.sort((o1, o2) -> {
|
||||
String[] mappings1 = (String[]) o1.get("mappings");
|
||||
String[] mappings2 = (String[]) o2.get("mappings");
|
||||
return mappings1.length > 0 ? (mappings2.length > 0 ? mappings1[0].compareTo(mappings2[0]) : 1) : -1;
|
||||
});
|
||||
}
|
||||
Map<String, Object> resultmap = new LinkedHashMap<>();
|
||||
resultmap.put("servers", serverList);
|
||||
resultmap.put("types", typesmap);
|
||||
final String json = JsonConvert.root().convertTo(resultmap);
|
||||
final FileOutputStream out = new FileOutputStream(new File(app.getHome(), "apidoc.json"));
|
||||
out.write(json.getBytes("UTF-8"));
|
||||
out.close();
|
||||
File doctemplate = new File(app.getHome(), "conf/apidoc-template.html");
|
||||
InputStream in = null;
|
||||
if (doctemplate.isFile() && doctemplate.canRead()) {
|
||||
in = new FileInputStream(doctemplate);
|
||||
}
|
||||
if (in == null) in = ApiDocs.class.getResourceAsStream("apidoc-template.html");
|
||||
String content = Utility.read(in).replace("${content}", json);
|
||||
in.close();
|
||||
FileOutputStream outhtml = new FileOutputStream(new File(app.getHome(), "apidoc.html"));
|
||||
outhtml.write(content.getBytes("UTF-8"));
|
||||
outhtml.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authenticate(int 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,9 +34,7 @@ import org.w3c.dom.*;
|
||||
* <p>
|
||||
* 进程启动类,程序启动后读取application.xml,进行classpath扫描动态加载Service与Servlet 优先加载所有SNCP协议的服务, 再加载其他协议服务, 最后进行Service、Servlet与其他资源之间的依赖注入。
|
||||
* <p>
|
||||
* <p>
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@@ -67,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;
|
||||
|
||||
@@ -79,8 +76,6 @@ public final class Application {
|
||||
|
||||
final List<NodeServer> servers = new CopyOnWriteArrayList<>();
|
||||
|
||||
CountDownLatch servicecdl; //会出现两次赋值
|
||||
|
||||
final ObjectPool<ByteBuffer> transportBufferPool;
|
||||
|
||||
final ExecutorService transportExecutor;
|
||||
@@ -89,6 +84,8 @@ public final class Application {
|
||||
|
||||
final ResourceFactory resourceFactory = ResourceFactory.root();
|
||||
|
||||
CountDownLatch servicecdl; //会出现两次赋值
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
private final boolean singletonrun;
|
||||
|
||||
@@ -333,15 +330,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);
|
||||
@@ -364,7 +360,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) {
|
||||
@@ -393,6 +389,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) {
|
||||
@@ -403,12 +412,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();
|
||||
@@ -466,15 +475,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();
|
||||
@@ -518,6 +527,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();
|
||||
@@ -525,7 +535,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 {
|
||||
@@ -539,8 +551,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();
|
||||
@@ -574,15 +589,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 {
|
||||
|
||||
@@ -14,15 +14,13 @@ import java.util.concurrent.*;
|
||||
import java.util.jar.*;
|
||||
import java.util.logging.*;
|
||||
import java.util.regex.*;
|
||||
import org.redkale.util.AnyValue;
|
||||
import org.redkale.util.*;
|
||||
import org.redkale.util.AnyValue.DefaultAnyValue;
|
||||
import org.redkale.util.AutoLoad;
|
||||
|
||||
/**
|
||||
* class过滤器, 符合条件的class会保留下来存入FilterEntry。
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 泛型
|
||||
@@ -30,23 +28,33 @@ import org.redkale.util.AutoLoad;
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class ClassFilter<T> {
|
||||
|
||||
private final Set<FilterEntry<T>> entrys = new HashSet<>();
|
||||
private static final Logger logger = Logger.getLogger(ClassFilter.class.getName());
|
||||
|
||||
private boolean refused;
|
||||
private static final boolean finer = logger.isLoggable(Level.FINER);
|
||||
|
||||
private Class superClass;
|
||||
private final Set<FilterEntry<T>> entrys = new HashSet<>(); //符合条件的结果
|
||||
|
||||
private Class<? extends Annotation> annotationClass;
|
||||
private final Set<FilterEntry<T>> expectEntrys = new HashSet<>(); //准备符合条件的结果
|
||||
|
||||
private Pattern[] includePatterns;
|
||||
private boolean refused; //是否拒绝所有数据,设置true,则其他规则失效,都是拒绝.
|
||||
|
||||
private Pattern[] excludePatterns;
|
||||
private Class superClass; //符合的父类型。不为空时,扫描结果的class必须是superClass的子类
|
||||
|
||||
private List<ClassFilter> ors;
|
||||
private Class<? extends Annotation> annotationClass;//符合的注解。不为空时,扫描结果的class必须包含该注解
|
||||
|
||||
private List<ClassFilter> ands;
|
||||
private Pattern[] includePatterns; //符合的classname正则表达式
|
||||
|
||||
private AnyValue conf;
|
||||
private Pattern[] excludePatterns;//拒绝的classname正则表达式
|
||||
|
||||
private Set<String> privilegeIncludes; //特批符合条件的classname
|
||||
|
||||
private Set<String> privilegeExcludes;//特批拒绝条件的classname
|
||||
|
||||
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);
|
||||
@@ -58,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);
|
||||
@@ -79,10 +96,31 @@ public final class ClassFilter<T> {
|
||||
return entrys;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取预留的class集合
|
||||
*
|
||||
* @return Set<FilterEntry<T>>
|
||||
*/
|
||||
public final Set<FilterEntry<T>> getFilterExpectEntrys() {
|
||||
return expectEntrys;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有的class集合
|
||||
*
|
||||
* @return Set<FilterEntry<T>>
|
||||
*/
|
||||
public final Set<FilterEntry<T>> getAllFilterEntrys() {
|
||||
HashSet<FilterEntry<T>> rs = new HashSet<>();
|
||||
rs.addAll(entrys);
|
||||
rs.addAll(expectEntrys);
|
||||
return rs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动扫描地过滤指定的class
|
||||
*
|
||||
* @param property AnyValue
|
||||
* @param property AnyValue
|
||||
* @param clazzname String
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -93,9 +131,9 @@ public final class ClassFilter<T> {
|
||||
/**
|
||||
* 过滤指定的class
|
||||
*
|
||||
* @param property application.xml中对应class节点下的property属性项
|
||||
* @param property application.xml中对应class节点下的property属性项
|
||||
* @param clazzname class名称
|
||||
* @param autoscan 为true表示自动扫描的, false表示显著调用filter, AutoLoad的注解将被忽略
|
||||
* @param autoscan 为true表示自动扫描的, false表示显著调用filter, AutoLoad的注解将被忽略
|
||||
*/
|
||||
public final void filter(AnyValue property, String clazzname, boolean autoscan) {
|
||||
boolean r = accept0(property, clazzname);
|
||||
@@ -113,7 +151,7 @@ public final class ClassFilter<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cf == null) return;
|
||||
if (cf == null || clazzname.startsWith("sun.")) return;
|
||||
try {
|
||||
Class clazz = Class.forName(clazzname);
|
||||
if (!cf.accept(property, clazz, autoscan)) return;
|
||||
@@ -129,31 +167,38 @@ public final class ClassFilter<T> {
|
||||
property = dav;
|
||||
}
|
||||
}
|
||||
entrys.add(new FilterEntry(clazz, autoscan, property));
|
||||
} catch (Throwable cfe) {
|
||||
}
|
||||
}
|
||||
|
||||
private 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());
|
||||
AutoLoad auto = (AutoLoad) clazz.getAnnotation(AutoLoad.class);
|
||||
if (autoscan && auto != null && !auto.value()) { //自动扫描且被标记为@AutoLoad(false)的
|
||||
expectEntrys.add(new FilterEntry(clazz, autoscan, true, property));
|
||||
} else {
|
||||
entrys.add(new FilterEntry(clazz, autoscan, false, property));
|
||||
}
|
||||
} catch (Throwable cfe) {
|
||||
if (finer && !clazzname.startsWith("sun.") && !clazzname.startsWith("javax.")
|
||||
&& !clazzname.startsWith("com.sun.") && !clazzname.startsWith("jdk.")) {
|
||||
//logger.log(Level.FINEST, ClassFilter.class.getSimpleName() + " filter error", cfe);
|
||||
}
|
||||
}
|
||||
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 property AnyValue
|
||||
* @param classname String
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean accept(String classname) {
|
||||
return accept(null, classname);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断class是否有效
|
||||
*
|
||||
* @param property AnyValue
|
||||
* @param classname String
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean accept(AnyValue property, String classname) {
|
||||
@@ -173,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) {
|
||||
@@ -191,21 +238,33 @@ public final class ClassFilter<T> {
|
||||
* 判断class是否有效
|
||||
*
|
||||
* @param property AnyValue
|
||||
* @param clazz Class
|
||||
* @param clazz Class
|
||||
* @param autoscan boolean
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean accept(AnyValue property, Class clazz, boolean autoscan) {
|
||||
if (this.refused || !Modifier.isPublic(clazz.getModifiers())) return false;
|
||||
if (autoscan) {
|
||||
AutoLoad auto = (AutoLoad) clazz.getAnnotation(AutoLoad.class);
|
||||
if (auto != null && !auto.value()) return false;
|
||||
}
|
||||
if (annotationClass != null && clazz.getAnnotation(annotationClass) == null) return false;
|
||||
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;
|
||||
}
|
||||
@@ -246,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指定的属性项
|
||||
*
|
||||
@@ -263,11 +338,13 @@ public final class ClassFilter<T> {
|
||||
|
||||
private final boolean autoload;
|
||||
|
||||
private final boolean expect;
|
||||
|
||||
public FilterEntry(Class<T> type, AnyValue property) {
|
||||
this(type, false, property);
|
||||
this(type, false, false, property);
|
||||
}
|
||||
|
||||
public FilterEntry(Class<T> type, final boolean autoload, AnyValue property) {
|
||||
public FilterEntry(Class<T> type, final boolean autoload, boolean expect, AnyValue property) {
|
||||
this.type = type;
|
||||
String str = property == null ? null : property.getValue("groups");
|
||||
if (str != null) {
|
||||
@@ -277,6 +354,7 @@ public final class ClassFilter<T> {
|
||||
if (str != null) groups.addAll(Arrays.asList(str.split(";")));
|
||||
this.property = property;
|
||||
this.autoload = autoload;
|
||||
this.expect = expect;
|
||||
this.name = property == null ? "" : property.getValue("name", "");
|
||||
}
|
||||
|
||||
@@ -322,6 +400,9 @@ public final class ClassFilter<T> {
|
||||
return autoload;
|
||||
}
|
||||
|
||||
public boolean isExpect() {
|
||||
return expect;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -340,17 +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 {
|
||||
@@ -395,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
|
||||
*/
|
||||
|
||||
@@ -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 {
|
||||
final StringBuilder sb = logger.isLoggable(Level.FINE) ? new StringBuilder() : null;
|
||||
final String prefix = conf == null ? "" : conf.getValue("path", "");
|
||||
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 = 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,7 +124,7 @@ 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) {
|
||||
@@ -135,7 +138,77 @@ public final class NodeHttpServer extends NodeServer {
|
||||
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
|
||||
}
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.FINE, sb.toString());
|
||||
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(" Loaded ").append(as.getKey());
|
||||
for (int i = 0; i < max - as.getKey().length(); i++) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
|
||||
}
|
||||
}
|
||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.redkale.service.Service;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@@ -21,4 +24,64 @@ public class NodeInterceptor {
|
||||
public void preShutdown(NodeServer server) {
|
||||
|
||||
}
|
||||
|
||||
public static class InterceptorServiceWrapper<T extends Service> {
|
||||
|
||||
private String name;
|
||||
|
||||
private Class<T> type;
|
||||
|
||||
private T service;
|
||||
|
||||
public InterceptorServiceWrapper() {
|
||||
}
|
||||
|
||||
public InterceptorServiceWrapper(String name, Class<T> type, T service) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Class<T> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Class<T> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public T getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
public void setService(T service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 97 * hash + Objects.hashCode(this.name);
|
||||
hash = 97 * hash + Objects.hashCode(this.type);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass()) return false;
|
||||
final InterceptorServiceWrapper<?> other = (InterceptorServiceWrapper<?>) obj;
|
||||
return Objects.equals(this.name, other.name) && Objects.equals(this.type, other.type);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.lang.annotation.*;
|
||||
* 根据application.xml中的server节点中的protocol值来适配Server的加载逻辑
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -6,14 +6,13 @@
|
||||
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.function.Consumer;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.*;
|
||||
import java.util.logging.*;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Resource;
|
||||
@@ -21,6 +20,7 @@ import javax.persistence.Transient;
|
||||
import static org.redkale.boot.Application.*;
|
||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||
import org.redkale.net.*;
|
||||
import org.redkale.net.http.WebSocketNode;
|
||||
import org.redkale.net.sncp.*;
|
||||
import org.redkale.service.*;
|
||||
import org.redkale.source.*;
|
||||
@@ -29,9 +29,9 @@ import org.redkale.util.*;
|
||||
|
||||
/**
|
||||
* Server节点的初始化配置类
|
||||
* <p>
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
*
|
||||
*
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
@@ -47,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;
|
||||
|
||||
@@ -74,6 +77,9 @@ public abstract class NodeServer {
|
||||
//加载server节点后的拦截器
|
||||
protected NodeInterceptor interceptor;
|
||||
|
||||
//供interceptor使用的Service对象集合
|
||||
protected final Set<NodeInterceptor.InterceptorServiceWrapper> interceptorServiceWrappers = new LinkedHashSet<>();
|
||||
|
||||
//本地模式的Service对象集合
|
||||
protected final Set<ServiceWrapper> localServiceWrappers = new LinkedHashSet<>();
|
||||
|
||||
@@ -87,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 {
|
||||
@@ -106,7 +113,11 @@ public abstract class NodeServer {
|
||||
logger.log(Level.SEVERE, "Server (" + server.getSocketAddress() + ") cannot find Context", e);
|
||||
}
|
||||
}
|
||||
context.submit(t);
|
||||
if (context == null) {
|
||||
t.run();
|
||||
} else {
|
||||
context.submit(t);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@@ -134,7 +145,7 @@ public abstract class NodeServer {
|
||||
if (this.sncpGroup != null) this.resourceFactory.register(RESNAME_SERVER_GROUP, this.sncpGroup);
|
||||
{
|
||||
//设置root文件夹
|
||||
String webroot = config.getValue("root", "root");
|
||||
String webroot = this.serverConf.getValue("root", "root");
|
||||
File myroot = new File(webroot);
|
||||
if (!webroot.contains(":") && !webroot.startsWith("/")) {
|
||||
myroot = new File(System.getProperty(Application.RESNAME_APP_HOME), webroot);
|
||||
@@ -146,15 +157,15 @@ public abstract class NodeServer {
|
||||
|
||||
final String homepath = myroot.getCanonicalPath();
|
||||
//加入指定的classpath
|
||||
Server.loadLib(logger, config.getValue("lib", "").replace("${APP_HOME}", homepath) + ";" + homepath + "/lib/*;" + homepath + "/classes");
|
||||
Server.loadLib(logger, this.serverConf.getValue("lib", "").replace("${APP_HOME}", homepath) + ";" + homepath + "/lib/*;" + homepath + "/classes");
|
||||
}
|
||||
//必须要进行初始化, 构建Service时需要使用Context中的ExecutorService
|
||||
server.init(config);
|
||||
server.init(this.serverConf);
|
||||
|
||||
initResource(); //给 DataSource、CacheSource 注册依赖注入时的监听回调事件。
|
||||
String interceptorClass = config.getValue("nodeInterceptor", "");
|
||||
String interceptorClass = this.serverConf.getValue("interceptor", "");
|
||||
if (!interceptorClass.isEmpty()) {
|
||||
Class clazz = forName(interceptorClass);
|
||||
Class clazz = Class.forName(interceptorClass);
|
||||
this.interceptor = (NodeInterceptor) clazz.newInstance();
|
||||
}
|
||||
|
||||
@@ -162,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");
|
||||
@@ -201,7 +212,7 @@ public abstract class NodeServer {
|
||||
localServiceWrappers.add(wrapper);
|
||||
sncpServer.consumerAccept(wrapper);
|
||||
rf.inject(cacheListenerService, self);
|
||||
if (fine) logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService());
|
||||
logger.info("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService());
|
||||
}
|
||||
field.set(src, source);
|
||||
rf.inject(source, self); // 给 "datasource.nodeid" 赋值;
|
||||
@@ -226,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); //
|
||||
@@ -235,10 +247,10 @@ 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);
|
||||
if (finer) logger.finer("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService());
|
||||
sncpServer.getSncpServer().addSncpServlet(wrapper);
|
||||
logger.info("[" + Thread.currentThread().getName() + "] Load Service " + wrapper.getService());
|
||||
}
|
||||
logger.finer("[" + Thread.currentThread().getName() + "] Load Source " + source);
|
||||
logger.info("[" + Thread.currentThread().getName() + "] Load Source " + source);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "DataSource inject error", e);
|
||||
}
|
||||
@@ -249,15 +261,26 @@ public abstract class NodeServer {
|
||||
protected void loadService(ClassFilter serviceFilter) throws Exception {
|
||||
if (serviceFilter == null) return;
|
||||
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
||||
final Set<FilterEntry<Service>> entrys = serviceFilter.getFilterEntrys();
|
||||
final Set<FilterEntry<Service>> entrys = serviceFilter.getAllFilterEntrys();
|
||||
ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : resourceFactory;
|
||||
|
||||
for (FilterEntry<Service> entry : entrys) { //service实现类
|
||||
final Class<? extends Service> type = entry.getType();
|
||||
if (Modifier.isFinal(type.getModifiers())) continue; //修饰final的类跳过
|
||||
if (!Modifier.isPublic(type.getModifiers())) continue;
|
||||
if (entry.isExpect()) {
|
||||
if (Modifier.isAbstract(type.getModifiers())) continue; //修饰abstract的类跳过
|
||||
if (DataSource.class.isAssignableFrom(type)) continue;
|
||||
if (CacheSource.class.isAssignableFrom(type)) continue;
|
||||
if (DataCacheListener.class.isAssignableFrom(type)) continue;
|
||||
if (WebSocketNode.class.isAssignableFrom(type)) continue;
|
||||
}
|
||||
if (entry.getName().contains("$")) throw new RuntimeException("<name> value cannot contains '$' in " + entry.getProperty());
|
||||
if (resourceFactory.find(entry.getName(), type) != null) continue; //Server加载Service时需要判断是否已经加载过了。
|
||||
if (resourceFactory.find(entry.getName(), type) != null) { //Server加载Service时需要判断是否已经加载过了。
|
||||
Service oldother = resourceFactory.find(entry.getName(), type);
|
||||
interceptorServiceWrappers.add(new NodeInterceptor.InterceptorServiceWrapper(entry.getName(), type, oldother));
|
||||
continue;
|
||||
}
|
||||
final HashSet<String> groups = entry.getGroups(); //groups.isEmpty()表示<services>没有配置groups属性。
|
||||
if (groups.isEmpty() && isSNCP() && this.sncpGroup != null) groups.add(this.sncpGroup);
|
||||
|
||||
@@ -266,29 +289,51 @@ public abstract class NodeServer {
|
||||
|| (this.sncpGroup == null && entry.isEmptyGroups()) //空的SNCP配置
|
||||
|| type.getAnnotation(LocalService.class) != null;//本地模式
|
||||
if (localed && (type.isInterface() || Modifier.isAbstract(type.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类
|
||||
|
||||
Service service;
|
||||
if (localed) { //本地模式
|
||||
service = Sncp.createLocalService(entry.getName(), getExecutor(), application.getResourceFactory(), type, this.sncpAddress, loadTransport(this.sncpGroup), loadTransports(groups));
|
||||
} else {
|
||||
service = Sncp.createRemoteService(entry.getName(), getExecutor(), type, this.sncpAddress, loadTransport(groups));
|
||||
}
|
||||
if (SncpClient.parseMethod(type).isEmpty()) continue; //class没有可用的方法, 通常为BaseService
|
||||
final ServiceWrapper wrapper = new ServiceWrapper(type, service, entry.getName(), localed ? this.sncpGroup : null, groups, entry.getProperty());
|
||||
for (final Class restype : wrapper.getTypes()) {
|
||||
if (resourceFactory.find(wrapper.getName(), restype) == null) {
|
||||
regFactory.register(wrapper.getName(), restype, wrapper.getService());
|
||||
} else if (isSNCP() && !entry.isAutoload()) {
|
||||
throw new RuntimeException(ServiceWrapper.class.getSimpleName() + "(class:" + type.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat.");
|
||||
final BiConsumer<ResourceFactory, Boolean> runner = (ResourceFactory rf, Boolean needinject) -> {
|
||||
try {
|
||||
Service service;
|
||||
if (localed) { //本地模式
|
||||
service = Sncp.createLocalService(entry.getName(), getExecutor(), application.getResourceFactory(), type,
|
||||
NodeServer.this.sncpAddress, loadTransport(NodeServer.this.sncpGroup), loadTransports(groups));
|
||||
} else {
|
||||
service = Sncp.createRemoteService(entry.getName(), getExecutor(), type, NodeServer.this.sncpAddress, loadTransport(groups));
|
||||
}
|
||||
if (SncpClient.parseMethod(type).isEmpty()) return; //class没有可用的方法, 通常为BaseService
|
||||
final ServiceWrapper wrapper = new ServiceWrapper(type, service, entry.getName(), localed ? NodeServer.this.sncpGroup : null, groups, entry.getProperty());
|
||||
for (final Class restype : wrapper.getTypes()) {
|
||||
if (resourceFactory.find(wrapper.getName(), restype) == null) {
|
||||
regFactory.register(wrapper.getName(), restype, wrapper.getService());
|
||||
if (needinject) rf.inject(wrapper.getService()); //动态加载的Service也存在按需加载的注入资源
|
||||
} else if (isSNCP() && !entry.isAutoload()) {
|
||||
throw new RuntimeException(ServiceWrapper.class.getSimpleName() + "(class:" + type.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat.");
|
||||
}
|
||||
}
|
||||
if (wrapper.isRemote()) {
|
||||
remoteServiceWrappers.add(wrapper);
|
||||
} else {
|
||||
localServiceWrappers.add(wrapper);
|
||||
interceptorServiceWrappers.add(new NodeInterceptor.InterceptorServiceWrapper(entry.getName(), type, service));
|
||||
if (consumer != null) consumer.accept(wrapper);
|
||||
}
|
||||
} catch (RuntimeException ex) {
|
||||
throw ex;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
};
|
||||
if (entry.isExpect()) {
|
||||
ResourceFactory.ResourceLoader resourceLoader = (ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> {
|
||||
runner.accept(rf, true);
|
||||
};
|
||||
for (final Class restype : ServiceWrapper.parseTypes(entry.getType())) {
|
||||
resourceFactory.register(resourceLoader, restype);
|
||||
}
|
||||
}
|
||||
if (wrapper.isRemote()) {
|
||||
remoteServiceWrappers.add(wrapper);
|
||||
} else {
|
||||
localServiceWrappers.add(wrapper);
|
||||
if (consumer != null) consumer.accept(wrapper);
|
||||
runner.accept(resourceFactory, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
application.servicecdl.countDown();
|
||||
application.servicecdl.await();
|
||||
|
||||
@@ -297,27 +342,36 @@ public abstract class NodeServer {
|
||||
new ArrayList<>(localServiceWrappers).forEach(y -> {
|
||||
resourceFactory.inject(y.getService(), NodeServer.this);
|
||||
});
|
||||
remoteServiceWrappers.forEach(y -> {
|
||||
new ArrayList<>(remoteServiceWrappers).forEach(y -> {
|
||||
resourceFactory.inject(y.getService(), NodeServer.this);
|
||||
if (sb != null) {
|
||||
sb.append(threadName).append(y.toSimpleString()).append(" loaded and injected").append(LINE_SEPARATOR);
|
||||
}
|
||||
});
|
||||
if (sb != null) {
|
||||
remoteServiceWrappers.forEach(y -> {
|
||||
sb.append(threadName).append(y.toSimpleString()).append(" loaded and injected").append(LINE_SEPARATOR);
|
||||
});
|
||||
}
|
||||
//----------------- init -----------------
|
||||
List<ServiceWrapper> swlist = new ArrayList<>(localServiceWrappers);
|
||||
Collections.sort(swlist);
|
||||
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 init ").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(" loaded and inited ").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);
|
||||
}
|
||||
}
|
||||
@@ -347,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) {
|
||||
@@ -370,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;
|
||||
@@ -406,19 +462,19 @@ public abstract class NodeServer {
|
||||
prop.addValue("groups", sc);
|
||||
}
|
||||
ClassFilter filter = new ClassFilter(ref, inter, prop);
|
||||
for (AnyValue av : list.getAnyValues(property)) {
|
||||
for (AnyValue av : list.getAnyValues(property)) { // <service> 或 <servlet> 节点
|
||||
final AnyValue[] items = av.getAnyValues("property");
|
||||
if (av instanceof DefaultAnyValue && items.length > 0) {
|
||||
if (av instanceof DefaultAnyValue && items.length > 0) { //存在 <property>节点
|
||||
DefaultAnyValue dav = DefaultAnyValue.create();
|
||||
final AnyValue.Entry<String>[] strings = av.getStringEntrys();
|
||||
if (strings != null) {
|
||||
if (strings != null) { //将<service>或<servlet>节点的属性值传给dav
|
||||
for (AnyValue.Entry<String> en : strings) {
|
||||
dav.addValue(en.name, en.getValue());
|
||||
}
|
||||
}
|
||||
final AnyValue.Entry<AnyValue>[] anys = av.getAnyEntrys();
|
||||
if (anys != null) {
|
||||
for (AnyValue.Entry<AnyValue> en : anys) {
|
||||
for (AnyValue.Entry<AnyValue> en : anys) { //将<service>或<servlet>节点的非property属性节点传给dav
|
||||
if (!"property".equals(en.name)) dav.addValue(en.name, en.getValue());
|
||||
}
|
||||
}
|
||||
@@ -426,7 +482,7 @@ public abstract class NodeServer {
|
||||
for (AnyValue item : items) {
|
||||
ps.addValue(item.getValue("name"), item.getValue("value"));
|
||||
}
|
||||
dav.addValue("property", ps);
|
||||
dav.addValue("properties", ps);
|
||||
av = dav;
|
||||
}
|
||||
filter.filter(av, av.getValue("value"), false);
|
||||
@@ -460,6 +516,10 @@ public abstract class NodeServer {
|
||||
return serverConf;
|
||||
}
|
||||
|
||||
public Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public String getSncpGroup() {
|
||||
return sncpGroup;
|
||||
}
|
||||
@@ -488,6 +548,10 @@ public abstract class NodeServer {
|
||||
return (T) server;
|
||||
}
|
||||
|
||||
public Set<NodeInterceptor.InterceptorServiceWrapper> getInterceptorServiceWrappers() {
|
||||
return new LinkedHashSet<>(interceptorServiceWrappers);
|
||||
}
|
||||
|
||||
public Set<ServiceWrapper> getLocalServiceWrappers() {
|
||||
return new LinkedHashSet<>(localServiceWrappers);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
85
src/org/redkale/boot/apidoc-template.html
Normal file
85
src/org/redkale/boot/apidoc-template.html
Normal file
@@ -0,0 +1,85 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8"><title>Document</title>
|
||||
<style type="text/css">
|
||||
body {text-align: center;margin:auto;}
|
||||
a{text-decoration: none;}
|
||||
.table {margin: auto;border-collapse: collapse;border-spacing: 0;display: block;width: 100%;overflow: auto;word-break: normal;word-break: keep-all;}
|
||||
.table td,.table th{padding: 0.4rem 1.2rem 0.4rem 1.2rem;border: 1px solid #aaa;}
|
||||
.table td {text-align: left;}
|
||||
.s {font-size: 0.8rem; vertical-align: middle;}
|
||||
.subtable {border-spacing: 0;border: 0;margin:0;}
|
||||
.subtable td{border: 0;padding: 0 0 0 10px;}
|
||||
.typetable {border-spacing: 0;border: 0;margin:0;}
|
||||
.typetable td{border: 0;padding: 2px 20px 2px 10px;}
|
||||
.typetable .l{border-bottom: 1px solid red;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script>
|
||||
var createhtml = function (jsoncontent) {
|
||||
var classmap = jsoncontent.types;
|
||||
var html = [];
|
||||
html.push('<div style="width:' + Math.floor(window.screen.width * 0.9) + 'px;margin:0 auto;text-align: center;">');
|
||||
html.push('<br/><br/><table class="table" align="center">');
|
||||
for (var i = 0; i < jsoncontent.servers.length; i++) {
|
||||
for (var j = 0; j < jsoncontent.servers[i].servlets.length; j++) {
|
||||
var servlet = jsoncontent.servers[i].servlets[j];
|
||||
if (html.length > 2) html.push(' <tr><th colspan="5" style="border-bottom:0;"> </th></tr>');
|
||||
html.push(' <tr><th colspan="5" style="border-top:' + ((html.length > 2) ? 0 : 1) + ';">' + (servlet.comment || '未知模块') + '</th></tr>');
|
||||
html.push(' <tr><th>请求URL</th><th>描 述</th><th>鉴 权</th><th>参 数 <span style="font-size:12px;">(红色: Header; 蓝色: Cookie)</span></th><th>输 出</th></tr>');
|
||||
for (var k = 0; k < servlet.actions.length; k++) {
|
||||
var action = servlet.actions[k];
|
||||
html.push(' <tr>');
|
||||
html.push('<td style="color:#ff00ff;">' + action.url + '</td>');
|
||||
html.push('<td>' + action.comment + '</td>');
|
||||
html.push('<td class="s">模块ID: ' + servlet.moduleid + '<br/>操作ID: ' + action.actionid + '<br/>需鉴权: ' + (action.auth ? '<font style="font-weight:bold;color:green;">true</font>' : '<font color=red>false</font>') + '</td>');
|
||||
var paramshtml = [];
|
||||
paramshtml.push('<table class="subtable">');
|
||||
for (var p = 0; p < action.params.length; p++) {
|
||||
var param = action.params[p];
|
||||
var t = param.type.substring(param.type.lastIndexOf('.') + 1);
|
||||
if (classmap[param.type.replace('[]', '')]) {
|
||||
t = '<a href="#' + param.type.replace('[]', '') + '">' + t + '</a>';
|
||||
}
|
||||
if (param.name == '&') {
|
||||
paramshtml.push('<tr><td style="font-size:12px;">内置 </td><td> ' + t + '</td><td> 当前用户</td></tr>');
|
||||
} else {
|
||||
var c = ' style="font-weight:bold;"';
|
||||
if (param.src == "HEADER") c = ' style="color:red;font-weight:bold;"';
|
||||
if (param.src == "COOKIE") c = ' style="color:blue;font-weight:bold;"';
|
||||
paramshtml.push('<tr><td ' + c + '> ' + param.name + ' </td><td> ' + t + '</td><td> ' + param.comment + '</td></tr>');
|
||||
}
|
||||
}
|
||||
paramshtml.push('</table>');
|
||||
html.push('<td class="s" style="padding:0 5px;">' + paramshtml.join('') + '</td>');
|
||||
html.push('<td>' + action.result.replace(/</g,"<").replace(/>/g,">").replace(/([a-zA-Z0-9_\$]+\.)+/g, "") + '</td>');
|
||||
html.push('</tr>');
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var type in classmap) {
|
||||
html.push(' <tr><th colspan="5" style="border-bottom:0;"> </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(/([a-zA-Z0-9_\$]+\.)+/g, "");
|
||||
html.push(' <tr class="l"><td>' + fieldname + '</td><td>' + t + '</td><td colspan="2">' + (field.comment || '') + '</td></tr>');
|
||||
}
|
||||
html.push(' </table></td></tr>');
|
||||
}
|
||||
html.push('</table><br/><br/><br/>');
|
||||
html.push('</div>');
|
||||
return html.join('');
|
||||
};
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var jsoncontent = ${content};
|
||||
document.write(createhtml(jsoncontent));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* 提供RedKale服务器的启动、初始化和加载功能
|
||||
* 提供Redkale服务器的启动、初始化和加载功能
|
||||
*/
|
||||
package org.redkale.boot;
|
||||
|
||||
@@ -10,8 +10,7 @@ import java.lang.reflect.Type;
|
||||
/**
|
||||
* 对不明类型的对象进行序列化; BSON序列化时将对象的类名写入Writer,JSON则不写入。
|
||||
* <p>
|
||||
* <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> 反解析的数组元素类型
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.lang.reflect.*;
|
||||
* 支持一定程度的泛型。
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化的数组元素类型
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.Collection;
|
||||
* 支持一定程度的泛型。
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <T> 反解析的集合元素类型
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.util.Collection;
|
||||
* 集合大小不能超过 32767。 在BSON中集合大小设定的是short,对于大于32767长度的集合传输会影响性能,所以没有采用int存储。
|
||||
* 支持一定程度的泛型。
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <T> 序列化的集合元素类型
|
||||
*/
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,6 +209,18 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
||||
this.skipAllIgnore = skipIgnore;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使所有类的所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false
|
||||
*
|
||||
* @param skipIgnore 忽略ignore
|
||||
*
|
||||
* @return 自身
|
||||
*/
|
||||
public ConvertFactory<R, W> skipAllIgnore(final boolean skipIgnore) {
|
||||
this.skipAllIgnore = skipIgnore;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使该类所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false
|
||||
*
|
||||
@@ -215,11 +235,11 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
||||
register(type, column, new ConvertColumnEntry(column, ignore));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public final boolean register(final Class type, String column, String alias) {
|
||||
return register(type, column, new ConvertColumnEntry(alias));
|
||||
}
|
||||
|
||||
|
||||
public final boolean register(final Class type, String column, ConvertColumnEntry entry) {
|
||||
if (type == null || column == null || entry == null) return false;
|
||||
try {
|
||||
@@ -375,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.")) {
|
||||
} 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;
|
||||
@@ -455,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输入的子类
|
||||
|
||||
@@ -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输出的子类
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.lang.reflect.Type;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <W> Writer输出的子类
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p> 详情见: https://redkale.org
|
||||
* @author zhangjx
|
||||
* @param <K> Map key的数据类型
|
||||
* @param <V> Map value的数据类型
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.Map;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <K> Map key的数据类型
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.redkale.util.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类
|
||||
@@ -161,6 +161,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
||||
* 对象格式: [0x1][short字段个数][字段名][字段值]...[0x2]
|
||||
*
|
||||
* @param in 输入流
|
||||
*
|
||||
* @return 反解析后的对象结果
|
||||
*/
|
||||
@Override
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.util.function.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -39,6 +39,12 @@ public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonFactory skipAllIgnore(final boolean skipIgnore) {
|
||||
this.registerSkipAllIgnore(skipIgnore);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static BsonFactory root() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -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输入的子类型
|
||||
|
||||
@@ -13,7 +13,9 @@ import java.util.Date;
|
||||
/**
|
||||
* Date 的SimpledCoder实现
|
||||
*
|
||||
* <p> 详情见: http://redkale.org
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
@@ -24,12 +26,13 @@ public final class DateSimpledCoder<R extends Reader, W extends Writer> extends
|
||||
|
||||
@Override
|
||||
public void convertTo(W out, Date value) {
|
||||
out.writeLong(value.getTime());
|
||||
out.writeLong(value == null ? 0L : value.getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date convertFrom(R in) {
|
||||
return new Date(in.readLong());
|
||||
long t = in.readLong();
|
||||
return t == 0 ? null : new Date();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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输入的子类型
|
||||
|
||||
@@ -9,8 +9,13 @@ import java.net.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public class URISimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, URI> {
|
||||
|
||||
|
||||
@@ -9,8 +9,13 @@ import java.net.*;
|
||||
import org.redkale.convert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <R> Reader输入的子类型
|
||||
* @param <W> Writer输出的子类型
|
||||
*/
|
||||
public class URLSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, URL> {
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -41,6 +41,12 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonFactory skipAllIgnore(final boolean skipIgnore) {
|
||||
this.registerSkipAllIgnore(skipIgnore);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static JsonFactory root() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -13,8 +13,7 @@ import org.redkale.util.*;
|
||||
*
|
||||
* writeTo系列的方法输出的字符不能含特殊字符
|
||||
* <p>
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
@@ -15,7 +15,7 @@ import java.util.concurrent.*;
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* 详情见: http://redkale.org
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user