Redkale 2.4.0 结束
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,3 +10,4 @@
|
|||||||
|
|
||||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
hs_err_pid*
|
hs_err_pid*
|
||||||
|
/target/
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<h1>项目介绍</h1>
|
<h1>项目介绍</h1>
|
||||||
<p>
|
<p>
|
||||||
Redkale (中文名: 红菜苔,一种湖北特产蔬菜) 是基于Java 8全新的微服务框架, 包含HTTP、WebSocket、TCP/UDP、数据序列化、数据缓存、依赖注入等功能。 本框架致力于简化集中式和微服务架构的开发,在增强开发敏捷性的同时保持高性能。
|
Redkale (中文名: 红菜苔,一种湖北特产蔬菜) 是基于Java 11全新的微服务框架, 包含HTTP、WebSocket、TCP/UDP、数据序列化、数据缓存、依赖注入等功能。 本框架致力于简化集中式和微服务架构的开发,在增强开发敏捷性的同时保持高性能。
|
||||||
</p>
|
</p>
|
||||||
<strong>RedKale 有如下主要特点:</strong>
|
<strong>RedKale 有如下主要特点:</strong>
|
||||||
<ol>
|
<ol>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
@ECHO OFF
|
@ECHO OFF
|
||||||
|
|
||||||
SET APP_HOME=%~dp0
|
SET APP_HOME=%~dp0
|
||||||
|
|
||||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||||
|
|
||||||
java -DCMD=APIDOC -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
java -DCMD=APIDOC -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
@ECHO OFF
|
@ECHO OFF
|
||||||
|
|
||||||
SET APP_HOME=%~dp0
|
SET APP_HOME=%~dp0
|
||||||
|
|
||||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||||
|
|
||||||
java -DCMD=%1 -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
java -DCMD=%1 -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
@ECHO OFF
|
@ECHO OFF
|
||||||
|
|
||||||
SET APP_HOME=%~dp0
|
SET APP_HOME=%~dp0
|
||||||
|
|
||||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||||
|
|
||||||
call "%APP_HOME%\bin\shutdown.bat"
|
call "%APP_HOME%\bin\shutdown.bat"
|
||||||
|
|
||||||
call "%APP_HOME%\bin\start.bat"
|
call "%APP_HOME%\bin\start.bat"
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
@ECHO OFF
|
@ECHO OFF
|
||||||
|
|
||||||
SET APP_HOME=%~dp0
|
SET APP_HOME=%~dp0
|
||||||
|
|
||||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||||
|
|
||||||
java -DCMD=SHUTDOWN -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
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
@ECHO OFF
|
@ECHO OFF
|
||||||
|
|
||||||
SET APP_HOME=%~dp0
|
SET APP_HOME=%~dp0
|
||||||
|
|
||||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||||
|
|
||||||
java -server -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
java -server -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<application nodeid="10000" port="2121">
|
<application nodeid="10000" port="2020">
|
||||||
|
|
||||||
<!-- 详细配置说明见: http://redkale.org/redkale.html#redkale_confxml -->
|
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
<server protocol="HTTP" port="6060">
|
<server protocol="HTTP" port="5050">
|
||||||
|
|
||||||
<request>
|
<request>
|
||||||
<remoteaddr value="request.headers.X-RemoteAddress"/>
|
<remoteaddr value="request.headers.X-RemoteAddress"/>
|
||||||
@@ -24,7 +22,7 @@
|
|||||||
|
|
||||||
<filters autoload="true"/>
|
<filters autoload="true"/>
|
||||||
|
|
||||||
<rest path="/pipes" /> <!-- base指定的自定义HttpServlet子类必须标记@HttpUserType, 不设置base则视为没有当前用户信息设置 -->
|
<rest path="/pipes" />
|
||||||
|
|
||||||
<servlets path="/pipes" autoload="true" />
|
<servlets path="/pipes" autoload="true" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<persistence version="2.0">
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
|
|
||||||
|
|
||||||
<persistence-unit name="" transaction-type="RESOURCE_LOCAL">
|
<persistence-unit name="" transaction-type="RESOURCE_LOCAL">
|
||||||
<shared-cache-mode>ALL</shared-cache-mode>
|
<shared-cache-mode>ALL</shared-cache-mode>
|
||||||
|
|||||||
37
my/pom.xml
37
my/pom.xml
@@ -4,16 +4,33 @@
|
|||||||
<groupId>org.redkale</groupId>
|
<groupId>org.redkale</groupId>
|
||||||
<artifactId>redkale</artifactId>
|
<artifactId>redkale</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
<name>RedkaleProject</name>
|
||||||
<url>http://redkale.org</url>
|
<url>http://redkale.org</url>
|
||||||
<description>redkale -- java framework</description>
|
<description>redkale -- java framework</description>
|
||||||
<version>2.2.0</version>
|
<version>2.5.0</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<version>5.7.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<licenses>
|
<licenses>
|
||||||
<license>
|
<license>
|
||||||
<name>Apache 2</name>
|
<name>Apache 2</name>
|
||||||
<url>http://www.apache.org/licenses/</url>
|
<url>https://www.apache.org/licenses/</url>
|
||||||
<distribution>repo</distribution>
|
<distribution>repo</distribution>
|
||||||
<comments>Apache License</comments>
|
<comments>Apache License</comments>
|
||||||
</license>
|
</license>
|
||||||
</licenses>
|
</licenses>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
@@ -21,13 +38,13 @@
|
|||||||
<id>Redkale</id>
|
<id>Redkale</id>
|
||||||
<name>redkale</name>
|
<name>redkale</name>
|
||||||
<email>redkale@qq.com</email>
|
<email>redkale@qq.com</email>
|
||||||
<url>http://redkale.org</url>
|
<url>https://redkale.org</url>
|
||||||
<roles>
|
<roles>
|
||||||
<role>Project Manager</role>
|
<role>Project Manager</role>
|
||||||
<role>Architect</role>
|
<role>Architect</role>
|
||||||
</roles>
|
</roles>
|
||||||
<organization>redkale</organization>
|
<organization>redkale</organization>
|
||||||
<organizationUrl>http://redkale.org</organizationUrl>
|
<organizationUrl>https://redkale.org</organizationUrl>
|
||||||
<properties>
|
<properties>
|
||||||
<dept>No</dept>
|
<dept>No</dept>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -35,12 +52,6 @@
|
|||||||
</developer>
|
</developer>
|
||||||
</developers>
|
</developers>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
<maven.compiler.source>11</maven.compiler.source>
|
|
||||||
<maven.compiler.target>11</maven.compiler.target>
|
|
||||||
</properties>
|
|
||||||
<name>Redkale</name>
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
<snapshotRepository>
|
<snapshotRepository>
|
||||||
<id>ossrh</id>
|
<id>ossrh</id>
|
||||||
@@ -51,11 +62,13 @@
|
|||||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||||
</repository>
|
</repository>
|
||||||
</distributionManagement>
|
</distributionManagement>
|
||||||
|
|
||||||
<scm>
|
<scm>
|
||||||
<url>https://github.com/redkale/redkale</url>
|
<url>https://github.com/redkale/redkale</url>
|
||||||
<connection>scm:git:git@github.com/redkale/redkale.git</connection>
|
<connection>scm:git:git@github.com/redkale/redkale.git</connection>
|
||||||
<developerConnection>scm:git:git@github.com:redkale/redkale.git</developerConnection>
|
<developerConnection>scm:git:git@github.com:redkale/redkale.git</developerConnection>
|
||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -99,6 +112,7 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-source-plugin</artifactId>
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
@@ -111,6 +125,7 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
|||||||
194
my/settings.xml
194
my/settings.xml
@@ -1,97 +1,99 @@
|
|||||||
<settings>
|
<settings>
|
||||||
<servers>
|
<servers>
|
||||||
<server>
|
<server>
|
||||||
<id>ossrh</id>
|
<id>ossrh</id>
|
||||||
<username>redkale</username>
|
<username>redkale</username>
|
||||||
<password>xxxxxxxxxxxxxxxxxxxxxxxxx</password>
|
<password>xxxxxxxxxxxxxxxxxxxxxxxxx</password>
|
||||||
</server>
|
</server>
|
||||||
</servers>
|
</servers>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
<id>ossrh</id>
|
<id>ossrh</id>
|
||||||
<activation>
|
<activation>
|
||||||
<activeByDefault>true</activeByDefault>
|
<activeByDefault>true</activeByDefault>
|
||||||
</activation>
|
</activation>
|
||||||
<properties>
|
<properties>
|
||||||
<gpg.executable>gpg2</gpg.executable>
|
<gpg.executable>gpg2</gpg.executable>
|
||||||
<gpg.passphrase>xxxxxxxxxxxxxxxxxxxxxxxxx</gpg.passphrase>
|
<gpg.passphrase>xxxxxxxxxxxxxxxxxxxxxxxxx</gpg.passphrase>
|
||||||
</properties>
|
</properties>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
<profile>
|
<profile>
|
||||||
<id>release</id>
|
<id>release</id>
|
||||||
<build>
|
<!--
|
||||||
<plugins>
|
<build>
|
||||||
<plugin>
|
<plugins>
|
||||||
<groupId>org.sonatype.plugins</groupId>
|
<plugin>
|
||||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
<groupId>org.sonatype.plugins</groupId>
|
||||||
<version>1.6.6</version>
|
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||||
<extensions>true</extensions>
|
<version>1.6.6</version>
|
||||||
<configuration>
|
<extensions>true</extensions>
|
||||||
<serverId>ossrh</serverId>
|
<configuration>
|
||||||
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
<serverId>ossrh</serverId>
|
||||||
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||||
</configuration>
|
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||||
</plugin>
|
</configuration>
|
||||||
<plugin>
|
</plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<plugin>
|
||||||
<artifactId>maven-release-plugin</artifactId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<version>2.5.3</version>
|
<artifactId>maven-release-plugin</artifactId>
|
||||||
<configuration>
|
<version>2.5.3</version>
|
||||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
<configuration>
|
||||||
<useReleaseProfile>false</useReleaseProfile>
|
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||||
<releaseProfiles>release</releaseProfiles>
|
<useReleaseProfile>false</useReleaseProfile>
|
||||||
<goals>deploy</goals>
|
<releaseProfiles>release</releaseProfiles>
|
||||||
</configuration>
|
<goals>deploy</goals>
|
||||||
</plugin>
|
</configuration>
|
||||||
<plugin>
|
</plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<plugin>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<version>3.5.1</version>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
</plugin>
|
<version>3.5.1</version>
|
||||||
<plugin>
|
</plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<plugin>
|
||||||
<artifactId>maven-gpg-plugin</artifactId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<version>1.6</version>
|
<artifactId>maven-gpg-plugin</artifactId>
|
||||||
<executions>
|
<version>1.6</version>
|
||||||
<execution>
|
<executions>
|
||||||
<id>sign-artifacts</id>
|
<execution>
|
||||||
<phase>verify</phase>
|
<id>sign-artifacts</id>
|
||||||
<goals>
|
<phase>verify</phase>
|
||||||
<goal>sign</goal>
|
<goals>
|
||||||
</goals>
|
<goal>sign</goal>
|
||||||
</execution>
|
</goals>
|
||||||
</executions>
|
</execution>
|
||||||
</plugin>
|
</executions>
|
||||||
<plugin>
|
</plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<plugin>
|
||||||
<artifactId>maven-source-plugin</artifactId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<version>3.0.0</version>
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
<executions>
|
<version>3.0.0</version>
|
||||||
<execution>
|
<executions>
|
||||||
<id>attach-sources</id>
|
<execution>
|
||||||
<goals>
|
<id>attach-sources</id>
|
||||||
<goal>jar-no-fork</goal>
|
<goals>
|
||||||
</goals>
|
<goal>jar-no-fork</goal>
|
||||||
</execution>
|
</goals>
|
||||||
</executions>
|
</execution>
|
||||||
</plugin>
|
</executions>
|
||||||
<plugin>
|
</plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<plugin>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<version>2.10.3</version>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<executions>
|
<version>2.10.3</version>
|
||||||
<execution>
|
<executions>
|
||||||
<id>attach-javadocs</id>
|
<execution>
|
||||||
<goals>
|
<id>attach-javadocs</id>
|
||||||
<goal>jar</goal>
|
<goals>
|
||||||
</goals>
|
<goal>jar</goal>
|
||||||
</execution>
|
</goals>
|
||||||
</executions>
|
</execution>
|
||||||
</plugin>
|
</executions>
|
||||||
</plugins>
|
</plugin>
|
||||||
</build>
|
</plugins>
|
||||||
</profile>
|
</build>
|
||||||
</profiles>
|
-->
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
</settings>
|
</settings>
|
||||||
138
pom.xml
Normal file
138
pom.xml
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>org.redkale</groupId>
|
||||||
|
<artifactId>redkale</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>RedkaleProject</name>
|
||||||
|
<url>https://redkale.org</url>
|
||||||
|
<description>redkale -- java framework</description>
|
||||||
|
<version>2.5.0</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
|
||||||
|
<junit.version>5.7.0</junit.version>
|
||||||
|
<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
|
||||||
|
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
|
||||||
|
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
|
||||||
|
<maven-failsafe-plugin.version>3.0.0-M5</maven-failsafe-plugin.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>Apache 2</name>
|
||||||
|
<url>https://www.apache.org/licenses/</url>
|
||||||
|
<distribution>repo</distribution>
|
||||||
|
<comments>Apache License</comments>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<version>${junit.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>central</id>
|
||||||
|
<name>Central Repository</name>
|
||||||
|
<url>https://repo.maven.apache.org/maven2</url>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>sonatype-nexus-snapshots</id>
|
||||||
|
<name>Sonatype Nexus Snapshots</name>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<id>Redkale</id>
|
||||||
|
<name>redkale</name>
|
||||||
|
<email>redkale@qq.com</email>
|
||||||
|
<url>https://redkale.org</url>
|
||||||
|
<roles>
|
||||||
|
<role>Project Manager</role>
|
||||||
|
<role>Architect</role>
|
||||||
|
</roles>
|
||||||
|
<organization>redkale</organization>
|
||||||
|
<organizationUrl>https://redkale.org</organizationUrl>
|
||||||
|
<properties>
|
||||||
|
<dept>No</dept>
|
||||||
|
</properties>
|
||||||
|
<timezone>8</timezone>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<url>https://github.com/redkale/redkale</url>
|
||||||
|
<connection>scm:git:git@github.com/redkale/redkale.git</connection>
|
||||||
|
<developerConnection>scm:git:git@github.com:redkale/redkale.git</developerConnection>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>${maven-compiler-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
<compilerArgs>
|
||||||
|
<arg>-parameters</arg>
|
||||||
|
</compilerArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<!-- 需要注释掉, 否则会生成native-image配置信息
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.redkale.maven.plugins</groupId>
|
||||||
|
<artifactId>redkale-maven-plugin</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>redkale-compile</id>
|
||||||
|
<phase>process-classes</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>compile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
-->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>${maven-jar-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<addMavenDescriptor>false</addMavenDescriptor>
|
||||||
|
<manifest>
|
||||||
|
<mainClass>org.redkale.boot.Application</mainClass>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${maven-surefire-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-failsafe-plugin</artifactId>
|
||||||
|
<version>${maven-failsafe-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -136,12 +136,12 @@
|
|||||||
如果name是mimetype.property.开头的值将会在进程启动时进行MimeType.add("yyyy", "YYYYYY")操作。
|
如果name是mimetype.property.开头的值将会在进程启动时进行MimeType.add("yyyy", "YYYYYY")操作。
|
||||||
load: 加载文件,多个用;隔开。
|
load: 加载文件,多个用;隔开。
|
||||||
默认置入的system.property.的有:
|
默认置入的system.property.的有:
|
||||||
System.setProperty("net.transport.poolmaxconns", "100");
|
System.setProperty("redkale.net.transport.poolmaxconns", "100");
|
||||||
System.setProperty("net.transport.pinginterval", "30");
|
System.setProperty("redkale.net.transport.pinginterval", "30");
|
||||||
System.setProperty("net.transport.checkinterval", "30");
|
System.setProperty("redkale.net.transport.checkinterval", "30");
|
||||||
System.setProperty("convert.tiny", "true");
|
System.setProperty("redkale.convert.tiny", "true");
|
||||||
System.setProperty("convert.pool.size", "128");
|
System.setProperty("redkale.convert.pool.size", "128");
|
||||||
System.setProperty("convert.writer.buffer.defsize", "4096");
|
System.setProperty("redkale.convert.writer.buffer.defsize", "4096");
|
||||||
|
|
||||||
<properties>节点下也可包含非<property>节点.
|
<properties>节点下也可包含非<property>节点.
|
||||||
非<property>其节点可以通过@Resource(name="properties.xxxxxx")进行注入, 被注解的字段类型只能是AnyValue、AnyValue[]
|
非<property>其节点可以通过@Resource(name="properties.xxxxxx")进行注入, 被注解的字段类型只能是AnyValue、AnyValue[]
|
||||||
@@ -164,30 +164,38 @@
|
|||||||
excludelibs: 排除lib.path与excludes中的正则表达式匹配的路径, 多个正则表达式用分号;隔开
|
excludelibs: 排除lib.path与excludes中的正则表达式匹配的路径, 多个正则表达式用分号;隔开
|
||||||
charset: 文本编码, 默认: UTF-8
|
charset: 文本编码, 默认: UTF-8
|
||||||
backlog: 默认10K
|
backlog: 默认10K
|
||||||
threads: 线程数, 默认: CPU核数*2,最小8个【已废弃 @since 2.3.0】
|
threads【已废弃】: 线程数, 默认: CPU核数*2,最小8个【已废弃 @since 2.3.0】
|
||||||
maxconns: 最大连接数, 小于1表示无限制, 默认: 0
|
maxconns: 最大连接数, 小于1表示无限制, 默认: 0
|
||||||
maxbody: request.body最大值, 默认: 64K
|
maxbody: request.body最大值, 默认: 64K
|
||||||
bufferCapacity: ByteBuffer的初始化大小, TCP默认: 32K; (HTTP 2.0、WebSocket,必须要16k以上); UDP默认: 1350B
|
bufferCapacity: ByteBuffer的初始化大小, TCP默认: 32K; (HTTP 2.0、WebSocket,必须要16k以上); UDP默认: 1350B
|
||||||
bufferPoolSize: ByteBuffer池的大小,默认: 线程数*4
|
bufferPoolSize: ByteBuffer池的大小,默认: 线程数*4
|
||||||
responsePoolSize: Response池的大小,默认: 线程数*2
|
responsePoolSize: Response池的大小,默认: 1024
|
||||||
aliveTimeoutSeconds: KeepAlive读操作超时秒数, 默认30, 0表示永久不超时; -1表示禁止KeepAlive
|
aliveTimeoutSeconds: KeepAlive读操作超时秒数, 默认30, 0表示永久不超时; -1表示禁止KeepAlive
|
||||||
readTimeoutSeconds: 读操作超时秒数, 默认0, 表示永久不超时
|
readTimeoutSeconds: 读操作超时秒数, 默认0, 表示永久不超时
|
||||||
writeTimeoutSeconds: 写操作超时秒数, 默认0, 表示永久不超时
|
writeTimeoutSeconds: 写操作超时秒数, 默认0, 表示永久不超时
|
||||||
iogroup: 流线程组AsyncGroup对象,如果值为client,表示和Application.asyncGroup对象共用
|
|
||||||
interceptor: 启动/关闭NodeServer时被调用的拦截器实现类,必须是org.redkale.boot.NodeInterceptor的子类,默认为null
|
interceptor: 启动/关闭NodeServer时被调用的拦截器实现类,必须是org.redkale.boot.NodeInterceptor的子类,默认为null
|
||||||
-->
|
-->
|
||||||
<server protocol="HTTP" host="127.0.0.1" port="6060" root="root" lib="">
|
<server protocol="HTTP" host="127.0.0.1" port="6060" root="root" lib="">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
【节点在<server>中唯一】
|
【节点在<server>中唯一】
|
||||||
value: 创建SSLContext的实现类, 可自定义,必须是org.redkale.net.SSLCreator的子类
|
builder: 创建SSLContext的实现类, 可自定义,必须是org.redkale.net.SSLBuilder的子类
|
||||||
clientauth: true/false/want
|
sslProvider: java.security.Provider自定义的实现类,如第三方: org.conscrypt.OpenSSLProvider、org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||||
keystorepass: KEY密码
|
jsseProvider: java.security.Provider自定义的实现类,如第三方: org.conscrypt.JSSEProvider、 org.bouncycastle.jce.provider.BouncyCastleJsseProvider
|
||||||
keystorefile: KEY文件
|
protocol: TLS版本,默认值: TLS
|
||||||
truststorepass: TRUST密码
|
protocols: 设置setEnabledProtocols, 多个用,隔开 如: TLSv1.2,TLSv1.3
|
||||||
truststorefile: TRUST文件
|
clientAuth: WANT/NEED/NONE, 默认值: NONE
|
||||||
|
ciphers: 设置setEnabledCipherSuites, 多个用,隔开 如: TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256
|
||||||
|
keystorePass: KEY密码
|
||||||
|
keystoreFile: KEY文件 .jks
|
||||||
|
keystoreType: KEY类型, 默认值为JKS
|
||||||
|
keystoreAlgorithm: KEY文件的algorithm, 默认值为SunX509
|
||||||
|
truststorePass: TRUST密码
|
||||||
|
truststoreFile: TRUST文件
|
||||||
|
truststoreType: TRUST类型, 默认值为JKS
|
||||||
|
truststoreAlgorithm: TRUST文件的algorithm, 默认值为SunX509
|
||||||
-->
|
-->
|
||||||
<ssl creator=""/>
|
<ssl builder=""/>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
加载所有的Service服务;
|
加载所有的Service服务;
|
||||||
@@ -296,7 +304,7 @@
|
|||||||
period>0表示定时获取时间; 设置1000表示每秒刷新Date时间
|
period>0表示定时获取时间; 设置1000表示每秒刷新Date时间
|
||||||
-->
|
-->
|
||||||
<response>
|
<response>
|
||||||
<contenttype plain="text/plain; charset=utf-8" json="application/json; charset=utf-8"/>
|
<content-type plain="text/plain; charset=utf-8" json="application/json; charset=utf-8"/>
|
||||||
<defcookie domain="" path=""/>
|
<defcookie domain="" path=""/>
|
||||||
<addheader name="Access-Control-Allow-Origin" value="request.headers.Origin" />
|
<addheader name="Access-Control-Allow-Origin" value="request.headers.Origin" />
|
||||||
<setheader name="Access-Control-Allow-Headers" value="request.headers.Access-Control-Request-Headers"/>
|
<setheader name="Access-Control-Allow-Headers" value="request.headers.Access-Control-Request-Headers"/>
|
||||||
@@ -12,29 +12,18 @@
|
|||||||
是否开启缓存(标记为@Cacheable的Entity类),值目前只支持两种: ALL: 所有开启缓存。 NONE: 关闭所有缓存, 非NONE字样统一视为ALL
|
是否开启缓存(标记为@Cacheable的Entity类),值目前只支持两种: ALL: 所有开启缓存。 NONE: 关闭所有缓存, 非NONE字样统一视为ALL
|
||||||
-->
|
-->
|
||||||
<property name="javax.persistence.cachemode" value="ALL"/>
|
<property name="javax.persistence.cachemode" value="ALL"/>
|
||||||
|
<!--
|
||||||
|
是否自动建表当表不存在的时候, 目前只支持mysql、postgres, 默认为false
|
||||||
|
-->
|
||||||
|
<property name="javax.persistence.table.autoddl" value="false"/>
|
||||||
|
|
||||||
<!-- 多个URL用;隔开,如分布式SearchSource需要配多个URL -->
|
<!-- 多个URL用;隔开,如分布式SearchSource需要配多个URL -->
|
||||||
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/dbuser?characterEncoding=utf8"/>
|
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/dbuser?characterEncoding=utf8"/>
|
||||||
<!--
|
|
||||||
javax.persistence.jdbc.driver在JPA的值是JDBC驱动,Redkale有所不同,值应该是javax.sql.DataSource的子类。
|
|
||||||
为了兼容用户习惯,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
|
|
||||||
com.mysql.cj.jdbc.Driver —————— com.mysql.cj.jdbc.MysqlConnectionPoolDataSource
|
|
||||||
oracle.jdbc.driver.OracleDriver —————— oracle.jdbc.pool.OracleConnectionPoolDataSource
|
|
||||||
com.microsoft.sqlserver.jdbc.SQLServerDriver —————— com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource
|
|
||||||
org.h2.Driver —————— org.h2.jdbcx.JdbcDataSource
|
|
||||||
因此 com.mysql.jdbc.Driver 会被自动转换成 com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
|
|
||||||
并且如果JDBC驱动是以上几个版本,javax.persistence.jdbc.driver属性都可以省略,Redkale会根据javax.persistence.jdbc.url的值来识别驱动
|
|
||||||
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
|
||||||
<property name="javax.persistence.jdbc.source" value="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource"/>
|
|
||||||
-->
|
|
||||||
<property name="javax.persistence.jdbc.user" value="root"/>
|
<property name="javax.persistence.jdbc.user" value="root"/>
|
||||||
<property name="javax.persistence.jdbc.password" value="123456"/>
|
<property name="javax.persistence.jdbc.password" value="123456"/>
|
||||||
|
|
||||||
<!-- 最大连接数,默认值:CPU数*16 -->
|
<!-- 最大连接数,默认值:CPU数 -->
|
||||||
<property name="javax.persistence.connections.limit" value="32"/>
|
<property name="javax.persistence.connections.limit" value="12"/>
|
||||||
|
|
||||||
<!-- 包含的SQL模板,相当于反向LIKE,不同的JDBC驱动的SQL语句不一样,Redkale内置了MySQL的语句 -->
|
<!-- 包含的SQL模板,相当于反向LIKE,不同的JDBC驱动的SQL语句不一样,Redkale内置了MySQL的语句 -->
|
||||||
<property name="javax.persistence.contain.sqltemplate" value="LOCATE(${keystr}, ${column}) > 0"/>
|
<property name="javax.persistence.contain.sqltemplate" value="LOCATE(${keystr}, ${column}) > 0"/>
|
||||||
@@ -42,7 +31,7 @@
|
|||||||
|
|
||||||
<!-- 复制表结构的SQL模板,Redkale内置了MySQL的语句 -->
|
<!-- 复制表结构的SQL模板,Redkale内置了MySQL的语句 -->
|
||||||
<property name="javax.persistence.tablenotexist.sqlstates" value="42000;42S02"/>
|
<property name="javax.persistence.tablenotexist.sqlstates" value="42000;42S02"/>
|
||||||
<property name="javax.persistence.tablecopy.sqltemplate" value="CREATE TABLE ${newtable} LIKE ${oldtable}"/>
|
<property name="javax.persistence.tablecopy.sqltemplate" value="CREATE TABLE IF NOT EXISTS ${newtable} LIKE ${oldtable}"/>
|
||||||
|
|
||||||
</properties>
|
</properties>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
@@ -1,33 +1,39 @@
|
|||||||
/*
|
/*
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
* this work for additional information regarding copyright ownership.
|
* this work for additional information regarding copyright ownership.
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
* (the "License"); you may not use this file except in compliance with
|
* (the "License"); you may not use this file except in compliance with
|
||||||
* the License. You may obtain a copy of the License at
|
* the License. You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package javax.annotation;
|
package javax.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 值越大,优先级越高
|
* 值越大,优先级越高
|
||||||
*
|
*
|
||||||
* @since Common Annotations 1.2
|
* @since Common Annotations 1.2
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.TYPE})
|
@Target({ElementType.TYPE})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Priority {
|
public @interface Priority {
|
||||||
int value();
|
|
||||||
}
|
/**
|
||||||
|
* 优先级值
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int value();
|
||||||
|
}
|
||||||
@@ -1,32 +1,83 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package javax.annotation;
|
package javax.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since Common Annotations 1.0
|
* @since Common Annotations 1.0
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Resource {
|
public @interface Resource {
|
||||||
public enum AuthenticationType {
|
|
||||||
CONTAINER,
|
/**
|
||||||
APPLICATION
|
* AuthenticationType
|
||||||
}
|
*/
|
||||||
public String name() default "";
|
@Deprecated
|
||||||
|
public enum AuthenticationType {
|
||||||
public Class<?> type() default Object.class;
|
/**
|
||||||
public AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
|
* @deprecated
|
||||||
public boolean shareable() default true;
|
*/
|
||||||
public String description() default "";
|
CONTAINER,
|
||||||
public String mappedName() default "";
|
/**
|
||||||
|
* @deprecated
|
||||||
public String lookup() default "";
|
*/
|
||||||
}
|
APPLICATION
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源名称
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String name() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 依赖注入的类型
|
||||||
|
*
|
||||||
|
* @return Class
|
||||||
|
*/
|
||||||
|
public Class<?> type() default Object.class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return AuthenticationType
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public boolean shareable() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public String description() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public String mappedName() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public String lookup() default "";
|
||||||
|
}
|
||||||
@@ -1,62 +1,62 @@
|
|||||||
/** *****************************************************************************
|
/** *****************************************************************************
|
||||||
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
|
* Copyright (c) 2008 - 2013 Oracle Corporation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program and the accompanying materials are made available under the
|
* This program and the accompanying materials are made available under the
|
||||||
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
|
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
|
||||||
* which accompanies this distribution.
|
* which accompanies this distribution.
|
||||||
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
|
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
|
||||||
* and the Eclipse Distribution License is available at
|
* and the Eclipse Distribution License is available at
|
||||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Linda DeMichiel - Java Persistence 2.1
|
* Linda DeMichiel - Java Persistence 2.1
|
||||||
* Linda DeMichiel - Java Persistence 2.0
|
* Linda DeMichiel - Java Persistence 2.0
|
||||||
*
|
*
|
||||||
***************************************************************************** */
|
***************************************************************************** */
|
||||||
package javax.persistence;
|
package javax.persistence;
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.TYPE;
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether an entity should be cached if caching is enabled
|
* Specifies whether an entity should be cached if caching is enabled
|
||||||
* when the value of the <code>persistence.xml</code> caching element
|
* when the value of the <code>persistence.xml</code> caching element
|
||||||
* is <code>ENABLE_SELECTIVE</code> or <code>DISABLE_SELECTIVE</code>.
|
* is <code>ENABLE_SELECTIVE</code> or <code>DISABLE_SELECTIVE</code>.
|
||||||
* The value of the <code>Cacheable</code> annotation is inherited by
|
* The value of the <code>Cacheable</code> annotation is inherited by
|
||||||
* subclasses; it can be overridden by specifying
|
* subclasses; it can be overridden by specifying
|
||||||
* <code>Cacheable</code> on a subclass.
|
* <code>Cacheable</code> on a subclass.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <code>Cacheable(false)</code> means that the entity and its state must
|
* <code>Cacheable(false)</code> means that the entity and its state must
|
||||||
* not be cached by the provider.
|
* not be cached by the provider.
|
||||||
*
|
*
|
||||||
* @since Java Persistence 2.0
|
* @since Java Persistence 2.0
|
||||||
*/
|
*/
|
||||||
@Target({TYPE})
|
@Target({TYPE})
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public @interface Cacheable {
|
public @interface Cacheable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (Optional) Whether or not the entity should be cached.
|
* (Optional) Whether or not the entity should be cached.
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
boolean value() default true;
|
boolean value() default true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (Optional) 定时自动更新缓存的周期秒数,为0表示不做定时更新, 大于0表示每经过interval秒后会自动从数据库中拉取数据更新Cache
|
* (Optional) 定时自动更新缓存的周期秒数,为0表示不做定时更新, 大于0表示每经过interval秒后会自动从数据库中拉取数据更新Cache
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
int interval() default 0;
|
int interval() default 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DataSource是否直接返回对象的真实引用, 而不是copy一份
|
* DataSource是否直接返回对象的真实引用, 而不是copy一份
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
boolean direct() default false;
|
boolean direct() default false;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -81,12 +81,19 @@ public @interface Column {
|
|||||||
boolean unique() default false;
|
boolean unique() default false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (Optional) Whether the database column is nullable.
|
* (Optional) Whether the database column is required.
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
boolean nullable() default true;
|
boolean nullable() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for OpenAPI Specification 3
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
String example() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (Optional) Whether the column is included in SQL INSERT
|
* (Optional) Whether the column is included in SQL INSERT
|
||||||
* statements generated by the persistence provider.
|
* statements generated by the persistence provider.
|
||||||
@@ -109,11 +116,13 @@ public @interface Column {
|
|||||||
*
|
*
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
String table() default "";
|
String table() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (Optional) The column length. (Applies only if a
|
* (Optional) The column length. (Applies only if a
|
||||||
* string-valued column is used.)
|
* string-valued column is used.)
|
||||||
|
* if type==String and length == 65535 then sqltype is text
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
@@ -15,9 +15,7 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package javax.persistence;
|
package javax.persistence;
|
||||||
|
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.*;
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.Documented;
|
|
||||||
import static java.lang.annotation.ElementType.TYPE;
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
@@ -27,6 +25,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|||||||
*
|
*
|
||||||
* @since Java Persistence 1.0
|
* @since Java Persistence 1.0
|
||||||
*/
|
*/
|
||||||
|
@Inherited
|
||||||
@Documented
|
@Documented
|
||||||
@Target(TYPE)
|
@Target(TYPE)
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
@@ -82,6 +82,11 @@ public @interface Table {
|
|||||||
*/
|
*/
|
||||||
Index[] indexes() default {};
|
Index[] indexes() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* comment
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
String comment() default "";
|
String comment() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,20 +4,22 @@
|
|||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*
|
*
|
||||||
module org.redkale {
|
*/
|
||||||
|
module redkale {
|
||||||
|
|
||||||
requires java.base;
|
requires java.base;
|
||||||
requires java.logging;
|
requires java.logging;
|
||||||
requires java.xml;
|
requires java.net.http;
|
||||||
requires java.sql;
|
requires java.sql;
|
||||||
|
|
||||||
requires jdk.unsupported; //sun.misc.Unsafe
|
requires jdk.unsupported; //sun.misc.Unsafe
|
||||||
|
|
||||||
exports javax.annotation;
|
exports javax.annotation;
|
||||||
exports javax.persistence;
|
exports javax.persistence;
|
||||||
|
|
||||||
|
exports org.redkale.asm;
|
||||||
exports org.redkale.boot;
|
exports org.redkale.boot;
|
||||||
exports org.redkale.boot.watch;
|
exports org.redkale.boot.watch;
|
||||||
|
exports org.redkale.cluster;
|
||||||
exports org.redkale.convert;
|
exports org.redkale.convert;
|
||||||
exports org.redkale.convert.bson;
|
exports org.redkale.convert.bson;
|
||||||
exports org.redkale.convert.ext;
|
exports org.redkale.convert.ext;
|
||||||
@@ -32,10 +34,11 @@ module org.redkale {
|
|||||||
exports org.redkale.util;
|
exports org.redkale.util;
|
||||||
exports org.redkale.watch;
|
exports org.redkale.watch;
|
||||||
|
|
||||||
uses org.redkale.cluster.ClusterAgent;
|
|
||||||
uses org.redkale.mq.MessageAgent;
|
uses org.redkale.mq.MessageAgent;
|
||||||
uses org.redkale.source.CacheSource;
|
uses org.redkale.cluster.ClusterAgent;
|
||||||
uses org.redkale.source.SourceLoader;
|
uses org.redkale.convert.ConvertProvider;
|
||||||
|
uses org.redkale.source.CacheSourceProvider;
|
||||||
|
uses org.redkale.source.DataSourceProvider;
|
||||||
uses org.redkale.util.ResourceInjectLoader;
|
uses org.redkale.util.ResourceInjectLoader;
|
||||||
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
@@ -102,9 +102,6 @@ public abstract class AnnotationVisitor {
|
|||||||
* method calls. May be null.
|
* method calls. May be null.
|
||||||
*/
|
*/
|
||||||
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
|
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
|
||||||
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.av = av;
|
this.av = av;
|
||||||
}
|
}
|
||||||
@@ -286,8 +286,13 @@ public class Attribute {
|
|||||||
|
|
||||||
//The stuff below is temporary - once proper support for nestmate attribute has been added, it can be safely removed.
|
//The stuff below is temporary - once proper support for nestmate attribute has been added, it can be safely removed.
|
||||||
//see also changes in ClassReader.accept.
|
//see also changes in ClassReader.accept.
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
public static class NestMembers extends Attribute {
|
public static class NestMembers extends Attribute {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
public NestMembers() {
|
public NestMembers() {
|
||||||
super("NestMembers");
|
super("NestMembers");
|
||||||
}
|
}
|
||||||
@@ -321,11 +326,16 @@ public class Attribute {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
public static class NestHost extends Attribute {
|
public static class NestHost extends Attribute {
|
||||||
|
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
String clazz;
|
String clazz;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
public NestHost() {
|
public NestHost() {
|
||||||
super("NestHost");
|
super("NestHost");
|
||||||
}
|
}
|
||||||
@@ -104,9 +104,6 @@ public abstract class ClassVisitor {
|
|||||||
* calls. May be null.
|
* calls. May be null.
|
||||||
*/
|
*/
|
||||||
public ClassVisitor(final int api, final ClassVisitor cv) {
|
public ClassVisitor(final int api, final ClassVisitor cv) {
|
||||||
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.cv = cv;
|
this.cv = cv;
|
||||||
}
|
}
|
||||||
@@ -244,9 +241,6 @@ public abstract class ClassVisitor {
|
|||||||
*/
|
*/
|
||||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||||
TypePath typePath, String desc, boolean visible) {
|
TypePath typePath, String desc, boolean visible) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (cv != null) {
|
if (cv != null) {
|
||||||
return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||||
}
|
}
|
||||||
@@ -1297,38 +1297,6 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a handle to the constant pool of the class being build. Does nothing
|
|
||||||
* if the constant pool already contains a similar item. <i>This method is
|
|
||||||
* intended for {@link Attribute} sub classes, and is normally not needed by
|
|
||||||
* class generators or adapters.</i>
|
|
||||||
*
|
|
||||||
* @param tag
|
|
||||||
* the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
|
|
||||||
* {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
|
|
||||||
* {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
|
|
||||||
* {@link Opcodes#H_INVOKESTATIC},
|
|
||||||
* {@link Opcodes#H_INVOKESPECIAL},
|
|
||||||
* {@link Opcodes#H_NEWINVOKESPECIAL} or
|
|
||||||
* {@link Opcodes#H_INVOKEINTERFACE}.
|
|
||||||
* @param owner
|
|
||||||
* the internal name of the field or method owner class.
|
|
||||||
* @param name
|
|
||||||
* the name of the field or method.
|
|
||||||
* @param desc
|
|
||||||
* the descriptor of the field or method.
|
|
||||||
* @return the index of a new or already existing method type reference
|
|
||||||
* item.
|
|
||||||
*
|
|
||||||
* @deprecated this method is superseded by
|
|
||||||
* {@link #newHandle(int, String, String, String, boolean)}.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public int newHandle(final int tag, final String owner, final String name,
|
|
||||||
final String desc) {
|
|
||||||
return newHandle(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a handle to the constant pool of the class being build. Does nothing
|
* Adds a handle to the constant pool of the class being build. Does nothing
|
||||||
* if the constant pool already contains a similar item. <i>This method is
|
* if the constant pool already contains a similar item. <i>This method is
|
||||||
@@ -101,9 +101,6 @@ public abstract class FieldVisitor {
|
|||||||
* calls. May be null.
|
* calls. May be null.
|
||||||
*/
|
*/
|
||||||
public FieldVisitor(final int api, final FieldVisitor fv) {
|
public FieldVisitor(final int api, final FieldVisitor fv) {
|
||||||
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.fv = fv;
|
this.fv = fv;
|
||||||
}
|
}
|
||||||
@@ -145,9 +142,6 @@ public abstract class FieldVisitor {
|
|||||||
*/
|
*/
|
||||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||||
TypePath typePath, String desc, boolean visible) {
|
TypePath typePath, String desc, boolean visible) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (fv != null) {
|
if (fv != null) {
|
||||||
return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||||
}
|
}
|
||||||
@@ -99,35 +99,6 @@ public final class Handle {
|
|||||||
*/
|
*/
|
||||||
final boolean itf;
|
final boolean itf;
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new field or method handle.
|
|
||||||
*
|
|
||||||
* @param tag
|
|
||||||
* the kind of field or method designated by this Handle. Must be
|
|
||||||
* {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
|
|
||||||
* {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
|
|
||||||
* {@link Opcodes#H_INVOKEVIRTUAL},
|
|
||||||
* {@link Opcodes#H_INVOKESTATIC},
|
|
||||||
* {@link Opcodes#H_INVOKESPECIAL},
|
|
||||||
* {@link Opcodes#H_NEWINVOKESPECIAL} or
|
|
||||||
* {@link Opcodes#H_INVOKEINTERFACE}.
|
|
||||||
* @param owner
|
|
||||||
* the internal name of the class that owns the field or method
|
|
||||||
* designated by this handle.
|
|
||||||
* @param name
|
|
||||||
* the name of the field or method designated by this handle.
|
|
||||||
* @param desc
|
|
||||||
* the descriptor of the field or method designated by this
|
|
||||||
* handle.
|
|
||||||
*
|
|
||||||
* @deprecated this constructor has been superseded
|
|
||||||
* by {@link #Handle(int, String, String, String, boolean)}.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public Handle(int tag, String owner, String name, String desc) {
|
|
||||||
this(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new field or method handle.
|
* Constructs a new field or method handle.
|
||||||
*
|
*
|
||||||
@@ -1,192 +1,274 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.asm;
|
package org.redkale.asm;
|
||||||
|
|
||||||
import java.util.*;
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
/**
|
import java.util.*;
|
||||||
* MethodVisitor 的调试类
|
import static org.redkale.asm.Opcodes.*;
|
||||||
* <p>
|
|
||||||
* 详情见: https://redkale.org
|
/**
|
||||||
*
|
* MethodVisitor 的调试类
|
||||||
* @author zhangjx
|
* <p>
|
||||||
*/
|
* 详情见: https://redkale.org
|
||||||
public class MethodDebugVisitor {
|
*
|
||||||
|
* @author zhangjx
|
||||||
private final MethodVisitor visitor;
|
*/
|
||||||
|
public class MethodDebugVisitor {
|
||||||
private boolean debug = false;
|
|
||||||
|
private final MethodVisitor visitor;
|
||||||
public MethodDebugVisitor setDebug(boolean d) {
|
|
||||||
debug = d;
|
private boolean debug = false;
|
||||||
return this;
|
|
||||||
}
|
public MethodDebugVisitor setDebug(boolean d) {
|
||||||
|
debug = d;
|
||||||
public void debugLine() {
|
return this;
|
||||||
if (!debug) return;
|
}
|
||||||
System.out.println();
|
|
||||||
System.out.println();
|
public void debugLine() {
|
||||||
System.out.println();
|
if (!debug) return;
|
||||||
}
|
System.out.println();
|
||||||
|
System.out.println();
|
||||||
private final Map<Label, Integer> labels = new LinkedHashMap<>();
|
System.out.println();
|
||||||
|
}
|
||||||
private static final String[] opcodes = new String[200]; //0 -18
|
|
||||||
|
private final Map<Label, Integer> labels = new LinkedHashMap<>();
|
||||||
static {
|
|
||||||
try {
|
private static final String[] opcodes = new String[200]; //0 -18
|
||||||
for (java.lang.reflect.Field field : Opcodes.class.getFields()) {
|
|
||||||
String name = field.getName();
|
static {
|
||||||
if (name.startsWith("ASM")) continue;
|
try {
|
||||||
if (name.startsWith("V1_")) continue;
|
for (java.lang.reflect.Field field : Opcodes.class.getFields()) {
|
||||||
if (name.startsWith("ACC_")) continue;
|
String name = field.getName();
|
||||||
if (name.startsWith("T_")) continue;
|
if (name.startsWith("ASM")) continue;
|
||||||
if (name.startsWith("H_")) continue;
|
if (name.startsWith("V1_")) continue;
|
||||||
if (name.startsWith("F_")) continue;
|
if (name.startsWith("ACC_")) continue;
|
||||||
if (field.getType() != int.class) continue;
|
if (name.startsWith("T_")) continue;
|
||||||
opcodes[(int) (Integer) field.get(null)] = name;
|
if (name.startsWith("H_")) continue;
|
||||||
}
|
if (name.startsWith("F_")) continue;
|
||||||
} catch (Exception ex) {
|
if (field.getType() != int.class) continue;
|
||||||
throw new RuntimeException(ex); //不可能会发生
|
opcodes[(int) (Integer) field.get(null)] = name;
|
||||||
}
|
}
|
||||||
}
|
} catch (Exception ex) {
|
||||||
|
throw new RuntimeException(ex); //不可能会发生
|
||||||
public MethodDebugVisitor(MethodVisitor visitor) {
|
}
|
||||||
//super(Opcodes.ASM5, visitor);
|
}
|
||||||
this.visitor = visitor;
|
|
||||||
}
|
/**
|
||||||
|
*
|
||||||
public AnnotationVisitor visitParameterAnnotation(int i, String string, boolean bln) {
|
* @param visitor MethodVisitor
|
||||||
AnnotationVisitor av = visitor.visitParameterAnnotation(i, string, bln);
|
*/
|
||||||
if (debug) System.out.println("mv.visitParameterAnnotation(" + i + ", \"" + string + "\", " + bln + ");");
|
public MethodDebugVisitor(MethodVisitor visitor) {
|
||||||
return av;
|
//super(Opcodes.ASM5, visitor);
|
||||||
}
|
this.visitor = visitor;
|
||||||
|
}
|
||||||
public AnnotationVisitor visitAnnotation(String desc, boolean flag) {
|
|
||||||
AnnotationVisitor av = visitor.visitAnnotation(desc, flag);
|
public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
|
||||||
if (debug) System.out.println("mv.visitAnnotation(\"" + desc + "\", " + flag + ");");
|
visitor.visitTryCatchBlock(start, end, handler, type);
|
||||||
return av;
|
if (debug) System.out.println("mv.visitTryCatchBlock(label0, label1, label2, \"" + type + "\");");
|
||||||
}
|
}
|
||||||
|
|
||||||
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
|
public AnnotationVisitor visitParameterAnnotation(int i, String string, boolean bln) {
|
||||||
AnnotationVisitor av = visitor.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
AnnotationVisitor av = visitor.visitParameterAnnotation(i, string, bln);
|
||||||
if (debug) System.out.println("mv.visitTypeAnnotation(" + typeRef + ", " + typePath + ", \"" + desc + "\", " + visible + ");");
|
if (debug) System.out.println("mv.visitParameterAnnotation(" + i + ", \"" + string + "\", " + bln + ");");
|
||||||
return av;
|
return av;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitParameter(String name, int access) {
|
public AnnotationVisitor visitAnnotation(String desc, boolean flag) {
|
||||||
visitor.visitParameter(name, access);
|
AnnotationVisitor av = visitor.visitAnnotation(desc, flag);
|
||||||
if (debug) System.out.println("mv.visitParameter(" + name + ", " + access + ");");
|
if (debug) System.out.println("mv.visitAnnotation(\"" + desc + "\", " + flag + ");");
|
||||||
}
|
return av;
|
||||||
|
}
|
||||||
public void visitVarInsn(int opcode, int var) {
|
|
||||||
visitor.visitVarInsn(opcode, var);
|
public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
|
||||||
if (debug) System.out.println("mv.visitVarInsn(" + opcodes[opcode] + ", " + var + ");");
|
AnnotationVisitor av = visitor.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||||
}
|
if (debug) System.out.println("mv.visitTypeAnnotation(" + typeRef + ", " + typePath + ", \"" + desc + "\", " + visible + ");");
|
||||||
|
return av;
|
||||||
public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
|
}
|
||||||
visitor.visitFrame(type, nLocal, local, nStack, stack);
|
|
||||||
if (debug) {
|
public void visitParameter(String name, int access) {
|
||||||
String typestr = "" + type;
|
visitor.visitParameter(name, access);
|
||||||
if (type == -1) {
|
if (debug) System.out.println("mv.visitParameter(" + name + ", " + access + ");");
|
||||||
typestr = "Opcodes.F_NEW";
|
}
|
||||||
} else if (type == 1) {
|
|
||||||
typestr = "Opcodes.F_APPEND";
|
public void visitVarInsn(int opcode, int var) {
|
||||||
} else if (type == 2) {
|
visitor.visitVarInsn(opcode, var);
|
||||||
typestr = "Opcodes.F_CHOP";
|
if (debug) System.out.println("mv.visitVarInsn(" + opcodes[opcode] + ", " + var + ");");
|
||||||
} else if (type == 3) {
|
}
|
||||||
typestr = "Opcodes.F_SAME";
|
|
||||||
} else if (type == 4) {
|
public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
|
||||||
typestr = "Opcodes.F_SAME1";
|
visitor.visitFrame(type, nLocal, local, nStack, stack);
|
||||||
}
|
if (debug) {
|
||||||
System.out.println("mv.visitFrame(" + typestr + ", " + nLocal + ", " + Arrays.toString(local) + ", " + nStack + ", " + Arrays.toString(stack) + ");");
|
String typestr = "" + type;
|
||||||
}
|
if (type == -1) {
|
||||||
}
|
typestr = "Opcodes.F_NEW";
|
||||||
|
} else if (type == 1) {
|
||||||
public void visitJumpInsn(int opcode, Label var) { //调用此方法的 ClassWriter 必须由 COMPUTE_FRAMES 构建
|
typestr = "Opcodes.F_APPEND";
|
||||||
visitor.visitJumpInsn(opcode, var);
|
} else if (type == 2) {
|
||||||
if (debug) {
|
typestr = "Opcodes.F_CHOP";
|
||||||
Integer index = labels.get(var);
|
} else if (type == 3) {
|
||||||
if (index == null) {
|
typestr = "Opcodes.F_SAME";
|
||||||
index = labels.size();
|
} else if (type == 4) {
|
||||||
labels.put(var, index);
|
typestr = "Opcodes.F_SAME1";
|
||||||
System.out.println("Label l" + index + " = new Label();");
|
}
|
||||||
}
|
System.out.println("mv.visitFrame(" + typestr + ", " + nLocal + ", " + Arrays.toString(local) + ", " + nStack + ", " + Arrays.toString(stack) + ");");
|
||||||
System.out.println("mv.visitJumpInsn(" + opcodes[opcode] + ", l" + index + ");");
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public void visitJumpInsn(int opcode, Label var) { //调用此方法的 ClassWriter 必须由 COMPUTE_FRAMES 构建
|
||||||
public void visitCode() {
|
visitor.visitJumpInsn(opcode, var);
|
||||||
visitor.visitCode();
|
if (debug) {
|
||||||
if (debug) System.out.println("mv.visitCode();");
|
Integer index = labels.get(var);
|
||||||
}
|
if (index == null) {
|
||||||
|
index = labels.size();
|
||||||
public void visitLabel(Label var) {
|
labels.put(var, index);
|
||||||
visitor.visitLabel(var);
|
System.out.println("Label l" + index + " = new Label();");
|
||||||
if (debug) {
|
}
|
||||||
Integer index = labels.get(var);
|
System.out.println("mv.visitJumpInsn(" + opcodes[opcode] + ", l" + index + ");");
|
||||||
if (index == null) {
|
}
|
||||||
index = labels.size();
|
}
|
||||||
labels.put(var, index);
|
|
||||||
System.out.println("Label l" + index + " = new Label();");
|
public void visitCode() {
|
||||||
}
|
visitor.visitCode();
|
||||||
System.out.println("mv.visitLabel(l" + index + ");");
|
if (debug) System.out.println("mv.visitCode();");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public void visitLabel(Label var) {
|
||||||
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
|
visitor.visitLabel(var);
|
||||||
visitor.visitMethodInsn(opcode, owner, name, desc, itf);
|
if (debug) {
|
||||||
if (debug) System.out.println("mv.visitMethodInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\", " + itf + ");");
|
Integer index = labels.get(var);
|
||||||
}
|
if (index == null) {
|
||||||
|
index = labels.size();
|
||||||
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
|
labels.put(var, index);
|
||||||
visitor.visitFieldInsn(opcode, owner, name, desc);
|
System.out.println("Label l" + index + " = new Label();");
|
||||||
if (debug) System.out.println("mv.visitFieldInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\");");
|
}
|
||||||
}
|
System.out.println("mv.visitLabel(l" + index + ");");
|
||||||
|
}
|
||||||
public void visitTypeInsn(int opcode, String type) {
|
}
|
||||||
visitor.visitTypeInsn(opcode, type);
|
|
||||||
if (debug) System.out.println("mv.visitTypeInsn(" + opcodes[opcode] + ", \"" + type + "\");");
|
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
|
||||||
}
|
visitor.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||||
|
if (debug) System.out.println("mv.visitMethodInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\", " + itf + ");");
|
||||||
public void visitInsn(int opcode) {
|
}
|
||||||
visitor.visitInsn(opcode);
|
|
||||||
if (debug) System.out.println("mv.visitInsn(" + opcodes[opcode] + ");");
|
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
|
||||||
}
|
visitor.visitFieldInsn(opcode, owner, name, desc);
|
||||||
|
if (debug) System.out.println("mv.visitFieldInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\");");
|
||||||
public void visitIntInsn(int opcode, int value) {
|
}
|
||||||
visitor.visitIntInsn(opcode, value);
|
|
||||||
if (debug) System.out.println("mv.visitIntInsn(" + opcodes[opcode] + ", " + value + ");");
|
public void visitTypeInsn(int opcode, String type) {
|
||||||
}
|
visitor.visitTypeInsn(opcode, type);
|
||||||
|
if (debug) System.out.println("mv.visitTypeInsn(" + opcodes[opcode] + ", \"" + type + "\");");
|
||||||
public void visitIincInsn(int opcode, int value) {
|
}
|
||||||
visitor.visitIincInsn(opcode, value);
|
|
||||||
if (debug) System.out.println("mv.visitIincInsn(" + opcode + ", " + value + ");");
|
public void visitInsn(int opcode) {
|
||||||
}
|
visitor.visitInsn(opcode);
|
||||||
|
if (debug) System.out.println("mv.visitInsn(" + opcodes[opcode] + ");");
|
||||||
public void visitLdcInsn(Object o) {
|
}
|
||||||
visitor.visitLdcInsn(o);
|
|
||||||
if (debug) {
|
public void visitIntInsn(int opcode, int value) {
|
||||||
if (o instanceof CharSequence) {
|
visitor.visitIntInsn(opcode, value);
|
||||||
System.out.println("mv.visitLdcInsn(\"" + o + "\");");
|
if (debug) System.out.println("mv.visitIntInsn(" + opcodes[opcode] + ", " + value + ");");
|
||||||
} else if (o instanceof org.redkale.asm.Type) {
|
}
|
||||||
System.out.println("mv.visitLdcInsn(Type.getType(\"" + o + "\"));");
|
|
||||||
} else {
|
public void visitIincInsn(int opcode, int value) {
|
||||||
System.out.println("mv.visitLdcInsn(" + o + ");");
|
visitor.visitIincInsn(opcode, value);
|
||||||
}
|
if (debug) System.out.println("mv.visitIincInsn(" + opcode + ", " + value + ");");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public void visitLdcInsn(Object o) {
|
||||||
public void visitMaxs(int maxStack, int maxLocals) {
|
visitor.visitLdcInsn(o);
|
||||||
visitor.visitMaxs(maxStack, maxLocals);
|
if (debug) {
|
||||||
if (debug) System.out.println("mv.visitMaxs(" + maxStack + ", " + maxLocals + ");");
|
if (o instanceof CharSequence) {
|
||||||
}
|
System.out.println("mv.visitLdcInsn(\"" + o + "\");");
|
||||||
|
} else if (o instanceof org.redkale.asm.Type) {
|
||||||
public void visitEnd() {
|
System.out.println("mv.visitLdcInsn(Type.getType(\"" + o + "\"));");
|
||||||
visitor.visitEnd();
|
} else {
|
||||||
if (debug) System.out.println("mv.visitEnd();\r\n\r\n\r\n");
|
System.out.println("mv.visitLdcInsn(" + o + ");");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitMaxs(int maxStack, int maxLocals) {
|
||||||
|
visitor.visitMaxs(maxStack, maxLocals);
|
||||||
|
if (debug) System.out.println("mv.visitMaxs(" + maxStack + ", " + maxLocals + ");");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitEnd() {
|
||||||
|
visitor.visitEnd();
|
||||||
|
if (debug) System.out.println("mv.visitEnd();\r\n\r\n\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void pushInt(MethodDebugVisitor mv, int num) {
|
||||||
|
if (num < 6) {
|
||||||
|
mv.visitInsn(ICONST_0 + num);
|
||||||
|
} else if (num <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(BIPUSH, num);
|
||||||
|
} else if (num <= Short.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(SIPUSH, num);
|
||||||
|
} else {
|
||||||
|
mv.visitLdcInsn(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void pushInt(MethodVisitor mv, int num) {
|
||||||
|
if (num < 6) {
|
||||||
|
mv.visitInsn(ICONST_0 + num);
|
||||||
|
} else if (num <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(BIPUSH, num);
|
||||||
|
} else if (num <= Short.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(SIPUSH, num);
|
||||||
|
} else {
|
||||||
|
mv.visitLdcInsn(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void visitAnnotation(final AnnotationVisitor av, final Annotation ann) {
|
||||||
|
try {
|
||||||
|
for (Method anm : ann.annotationType().getMethods()) {
|
||||||
|
final String mname = anm.getName();
|
||||||
|
if ("equals".equals(mname) || "hashCode".equals(mname) || "toString".equals(mname) || "annotationType".equals(mname)) continue;
|
||||||
|
final Object r = anm.invoke(ann);
|
||||||
|
if (r instanceof String[]) {
|
||||||
|
AnnotationVisitor av1 = av.visitArray(mname);
|
||||||
|
for (String item : (String[]) r) {
|
||||||
|
av1.visit(null, item);
|
||||||
|
}
|
||||||
|
av1.visitEnd();
|
||||||
|
} else if (r instanceof Class[]) {
|
||||||
|
AnnotationVisitor av1 = av.visitArray(mname);
|
||||||
|
for (Class item : (Class[]) r) {
|
||||||
|
av1.visit(null, Type.getType(item));
|
||||||
|
}
|
||||||
|
av1.visitEnd();
|
||||||
|
} else if (r instanceof Enum[]) {
|
||||||
|
AnnotationVisitor av1 = av.visitArray(mname);
|
||||||
|
for (Enum item : (Enum[]) r) {
|
||||||
|
av1.visitEnum(null, Type.getDescriptor(item.getClass()), ((Enum) item).name());
|
||||||
|
}
|
||||||
|
av1.visitEnd();
|
||||||
|
} else if (r instanceof Annotation[]) {
|
||||||
|
AnnotationVisitor av1 = av.visitArray(mname);
|
||||||
|
for (Annotation item : (Annotation[]) r) {
|
||||||
|
visitAnnotation(av1.visitAnnotation(null, Type.getDescriptor(((Annotation) item).annotationType())), item);
|
||||||
|
}
|
||||||
|
av1.visitEnd();
|
||||||
|
} else if (r instanceof Class) {
|
||||||
|
av.visit(mname, Type.getType((Class) r));
|
||||||
|
} else if (r instanceof Enum) {
|
||||||
|
av.visitEnum(mname, Type.getDescriptor(r.getClass()), ((Enum) r).name());
|
||||||
|
} else if (r instanceof Annotation) {
|
||||||
|
visitAnnotation(av.visitAnnotation(null, Type.getDescriptor(((Annotation) r).annotationType())), (Annotation) r);
|
||||||
|
} else {
|
||||||
|
av.visit(mname, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
av.visitEnd();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -118,9 +118,6 @@ public abstract class MethodVisitor {
|
|||||||
* calls. May be null.
|
* calls. May be null.
|
||||||
*/
|
*/
|
||||||
public MethodVisitor(final int api, final MethodVisitor mv) {
|
public MethodVisitor(final int api, final MethodVisitor mv) {
|
||||||
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.mv = mv;
|
this.mv = mv;
|
||||||
}
|
}
|
||||||
@@ -140,9 +137,6 @@ public abstract class MethodVisitor {
|
|||||||
* allowed (see {@link Opcodes}).
|
* allowed (see {@link Opcodes}).
|
||||||
*/
|
*/
|
||||||
public void visitParameter(String name, int access) {
|
public void visitParameter(String name, int access) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
if (mv != null) {
|
||||||
mv.visitParameter(name, access);
|
mv.visitParameter(name, access);
|
||||||
}
|
}
|
||||||
@@ -209,9 +203,6 @@ public abstract class MethodVisitor {
|
|||||||
*/
|
*/
|
||||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||||
TypePath typePath, String desc, boolean visible) {
|
TypePath typePath, String desc, boolean visible) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
if (mv != null) {
|
||||||
return mv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
return mv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||||
}
|
}
|
||||||
@@ -453,35 +444,6 @@ public abstract class MethodVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Visits a method instruction. A method instruction is an instruction that
|
|
||||||
* invokes a method.
|
|
||||||
*
|
|
||||||
* @param opcode
|
|
||||||
* the opcode of the type instruction to be visited. This opcode
|
|
||||||
* is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
|
|
||||||
* INVOKEINTERFACE.
|
|
||||||
* @param owner
|
|
||||||
* the internal name of the method's owner class (see
|
|
||||||
* {@link Type#getInternalName() getInternalName}).
|
|
||||||
* @param name
|
|
||||||
* the method's name.
|
|
||||||
* @param desc
|
|
||||||
* the method's descriptor (see {@link Type Type}).
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void visitMethodInsn(int opcode, String owner, String name,
|
|
||||||
String desc) {
|
|
||||||
if (api >= Opcodes.ASM5) {
|
|
||||||
boolean itf = opcode == Opcodes.INVOKEINTERFACE;
|
|
||||||
visitMethodInsn(opcode, owner, name, desc, itf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
|
||||||
mv.visitMethodInsn(opcode, owner, name, desc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visits a method instruction. A method instruction is an instruction that
|
* Visits a method instruction. A method instruction is an instruction that
|
||||||
* invokes a method.
|
* invokes a method.
|
||||||
@@ -502,14 +464,6 @@ public abstract class MethodVisitor {
|
|||||||
*/
|
*/
|
||||||
public void visitMethodInsn(int opcode, String owner, String name,
|
public void visitMethodInsn(int opcode, String owner, String name,
|
||||||
String desc, boolean itf) {
|
String desc, boolean itf) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"INVOKESPECIAL/STATIC on interfaces require ASM 5");
|
|
||||||
}
|
|
||||||
visitMethodInsn(opcode, owner, name, desc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
if (mv != null) {
|
||||||
mv.visitMethodInsn(opcode, owner, name, desc, itf);
|
mv.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||||
}
|
}
|
||||||
@@ -723,9 +677,6 @@ public abstract class MethodVisitor {
|
|||||||
*/
|
*/
|
||||||
public AnnotationVisitor visitInsnAnnotation(int typeRef,
|
public AnnotationVisitor visitInsnAnnotation(int typeRef,
|
||||||
TypePath typePath, String desc, boolean visible) {
|
TypePath typePath, String desc, boolean visible) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
if (mv != null) {
|
||||||
return mv.visitInsnAnnotation(typeRef, typePath, desc, visible);
|
return mv.visitInsnAnnotation(typeRef, typePath, desc, visible);
|
||||||
}
|
}
|
||||||
@@ -783,9 +734,6 @@ public abstract class MethodVisitor {
|
|||||||
*/
|
*/
|
||||||
public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
|
public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
|
||||||
TypePath typePath, String desc, boolean visible) {
|
TypePath typePath, String desc, boolean visible) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
if (mv != null) {
|
||||||
return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible);
|
return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible);
|
||||||
}
|
}
|
||||||
@@ -854,9 +802,6 @@ public abstract class MethodVisitor {
|
|||||||
public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
|
public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
|
||||||
TypePath typePath, Label[] start, Label[] end, int[] index,
|
TypePath typePath, Label[] start, Label[] end, int[] index,
|
||||||
String desc, boolean visible) {
|
String desc, boolean visible) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
if (mv != null) {
|
||||||
return mv.visitLocalVariableAnnotation(typeRef, typePath, start,
|
return mv.visitLocalVariableAnnotation(typeRef, typePath, start,
|
||||||
end, index, desc, visible);
|
end, index, desc, visible);
|
||||||
@@ -73,10 +73,9 @@ package org.redkale.asm;
|
|||||||
public interface Opcodes {
|
public interface Opcodes {
|
||||||
|
|
||||||
// ASM API versions
|
// ASM API versions
|
||||||
|
int ASM4 = 4 << 16 | 0 << 8;
|
||||||
int ASM4 = 4 << 16 | 0 << 8 | 0;
|
int ASM5 = 5 << 16 | 0 << 8;
|
||||||
int ASM5 = 5 << 16 | 0 << 8 | 0;
|
int ASM6 = 6 << 16 | 0 << 8;
|
||||||
int ASM6 = 6 << 16 | 0 << 8 | 0;
|
|
||||||
|
|
||||||
// versions
|
// versions
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ public class TypePath {
|
|||||||
* @return the corresponding TypePath object, or null if the path is empty.
|
* @return the corresponding TypePath object, or null if the path is empty.
|
||||||
*/
|
*/
|
||||||
public static TypePath fromString(final String typePath) {
|
public static TypePath fromString(final String typePath) {
|
||||||
if (typePath == null || typePath.length() == 0) {
|
if (typePath == null || typePath.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
int n = typePath.length();
|
int n = typePath.length();
|
||||||
@@ -1,27 +1,27 @@
|
|||||||
need copy classes:
|
need copy classes:
|
||||||
|
|
||||||
AnnotationVisitor.java
|
AnnotationVisitor.java
|
||||||
AnnotationWriter.java
|
AnnotationWriter.java
|
||||||
Attribute.java
|
Attribute.java
|
||||||
ByteVector.java
|
ByteVector.java
|
||||||
ClassReader.java
|
ClassReader.java
|
||||||
ClassVisitor.java
|
ClassVisitor.java
|
||||||
ClassWriter.java
|
ClassWriter.java
|
||||||
Context.java
|
Context.java
|
||||||
CurrentFrame.java
|
CurrentFrame.java
|
||||||
Edge.java
|
Edge.java
|
||||||
FieldVisitor.java
|
FieldVisitor.java
|
||||||
FieldWriter.java
|
FieldWriter.java
|
||||||
Frame.java
|
Frame.java
|
||||||
Handle.java
|
Handle.java
|
||||||
Handler.java
|
Handler.java
|
||||||
Item.java
|
Item.java
|
||||||
Label.java
|
Label.java
|
||||||
MethodVisitor.java
|
MethodVisitor.java
|
||||||
MethodWriter.java
|
MethodWriter.java
|
||||||
ModuleVisitor.java
|
ModuleVisitor.java
|
||||||
ModuleWriter.java
|
ModuleWriter.java
|
||||||
Opcodes.java
|
Opcodes.java
|
||||||
Type.java
|
Type.java
|
||||||
TypePath.java
|
TypePath.java
|
||||||
TypeReference.java
|
TypeReference.java
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/**
|
/**
|
||||||
* 本包下所有代码均是从/java.base/jdk/internal/org/objectweb/asm 拷贝过来的
|
* 本包下所有代码均是从/java.base/jdk/internal/org/objectweb/asm 拷贝过来的
|
||||||
*/
|
*/
|
||||||
package org.redkale.asm;
|
package org.redkale.asm;
|
||||||
535
src/main/java/org/redkale/boot/ApiDocsService.java
Normal file
535
src/main/java/org/redkale/boot/ApiDocsService.java
Normal file
@@ -0,0 +1,535 @@
|
|||||||
|
/*
|
||||||
|
* 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.math.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.*;
|
||||||
|
import java.util.logging.*;
|
||||||
|
import javax.persistence.*;
|
||||||
|
import org.redkale.convert.*;
|
||||||
|
import org.redkale.convert.json.*;
|
||||||
|
import org.redkale.mq.MessageMultiConsumer;
|
||||||
|
import org.redkale.net.http.*;
|
||||||
|
import org.redkale.service.RetResult;
|
||||||
|
import org.redkale.source.*;
|
||||||
|
import org.redkale.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API接口文档生成类,作用:生成Application实例中所有HttpServer的可用HttpServlet的API接口方法 <br>
|
||||||
|
* 继承 HttpBaseServlet 是为了获取 HttpMapping 信息 <br>
|
||||||
|
* https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public final class ApiDocsService {
|
||||||
|
|
||||||
|
private static final java.lang.reflect.Type TYPE_RETRESULT_OBJECT = new TypeToken<RetResult<Object>>() {
|
||||||
|
}.getType();
|
||||||
|
|
||||||
|
private static final java.lang.reflect.Type TYPE_RETRESULT_STRING = new TypeToken<RetResult<String>>() {
|
||||||
|
}.getType();
|
||||||
|
|
||||||
|
private static final java.lang.reflect.Type TYPE_RETRESULT_INTEGER = new TypeToken<RetResult<Integer>>() {
|
||||||
|
}.getType();
|
||||||
|
|
||||||
|
private static final java.lang.reflect.Type TYPE_RETRESULT_LONG = new TypeToken<RetResult<Long>>() {
|
||||||
|
}.getType();
|
||||||
|
|
||||||
|
private final Application app; //Application全局对象
|
||||||
|
|
||||||
|
public ApiDocsService(Application app) {
|
||||||
|
this.app = app;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run(String[] args) throws Exception {
|
||||||
|
//是否跳过RPC接口
|
||||||
|
final boolean skipRPC = Arrays.toString(args).toLowerCase().contains("skip-rpc") && !Arrays.toString(args).toLowerCase().contains("skip-rpc=false");
|
||||||
|
|
||||||
|
List<Map> serverList = new ArrayList<>();
|
||||||
|
Field __prefix = HttpServlet.class.getDeclaredField("_prefix");
|
||||||
|
__prefix.setAccessible(true);
|
||||||
|
Map<String, Map<String, Map<String, Object>>> typesMap = new LinkedHashMap<>();
|
||||||
|
//https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md
|
||||||
|
Map<String, Object> swaggerPathsMap = new LinkedHashMap<>();
|
||||||
|
List<Map> swaggerServers = new ArrayList<>();
|
||||||
|
List<Map> swaggerTags = new ArrayList<>();
|
||||||
|
Map<String, Map<String, Object>> swaggerComponentsMap = 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());
|
||||||
|
swaggerServers.add(Utility.ofMap("url", "http://localhost:" + server.getSocketAddress().getPort()));
|
||||||
|
List<Map<String, Object>> servletsList = new ArrayList<>();
|
||||||
|
map.put("servlets", servletsList);
|
||||||
|
String plainContentType = server.getResponseConfig() == null ? "application/json" : server.getResponseConfig().plainContentType;
|
||||||
|
if (plainContentType == null || plainContentType.isEmpty()) plainContentType = "application/json";
|
||||||
|
if (plainContentType.indexOf(';') > 0) plainContentType = plainContentType.substring(0, plainContentType.indexOf(';'));
|
||||||
|
|
||||||
|
for (HttpServlet servlet : server.getPrepareServlet().getServlets()) {
|
||||||
|
if (!(servlet instanceof HttpServlet)) continue;
|
||||||
|
if (servlet instanceof WebSocketServlet) continue;
|
||||||
|
if (servlet.getClass().getAnnotation(MessageMultiConsumer.class) != null) {
|
||||||
|
node.logger.log(Level.INFO, servlet + " be skipped because has @MessageMultiConsumer");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
|
||||||
|
if (ws == null) {
|
||||||
|
node.logger.log(Level.WARNING, servlet + " not found @WebServlet");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ws.name().isEmpty()) {
|
||||||
|
node.logger.log(Level.INFO, servlet + " be skipped because @WebServlet.name is empty");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final String tag = ws.name().isEmpty() ? servlet.getClass().getSimpleName().replace("Servlet", "").toLowerCase() : ws.name();
|
||||||
|
final Map<String, Object> servletMap = new LinkedHashMap<>();
|
||||||
|
String prefix = (String) __prefix.get(servlet);
|
||||||
|
String[] urlregs = ws.value();
|
||||||
|
if (prefix != null && !prefix.isEmpty()) {
|
||||||
|
for (int i = 0; i < urlregs.length; i++) {
|
||||||
|
urlregs[i] = prefix + urlregs[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
servletMap.put("urlregs", urlregs);
|
||||||
|
servletMap.put("moduleid", ws.moduleid());
|
||||||
|
servletMap.put("name", ws.name());
|
||||||
|
servletMap.put("comment", ws.comment());
|
||||||
|
|
||||||
|
List<Map> mappingsList = new ArrayList<>();
|
||||||
|
servletMap.put("mappings", mappingsList);
|
||||||
|
final Class selfClz = servlet.getClass();
|
||||||
|
Class clz = servlet.getClass();
|
||||||
|
HashSet<String> actionUrls = new HashSet<>();
|
||||||
|
do {
|
||||||
|
if (Modifier.isAbstract(clz.getModifiers())) break;
|
||||||
|
for (Method method : clz.getMethods()) {
|
||||||
|
if (method.getParameterCount() != 2) continue;
|
||||||
|
HttpMapping action = method.getAnnotation(HttpMapping.class);
|
||||||
|
if (action == null) continue;
|
||||||
|
if (!action.inherited() && selfClz != clz) continue; //忽略不被继承的方法
|
||||||
|
if (actionUrls.contains(action.url())) continue;
|
||||||
|
if (HttpScope.class.isAssignableFrom(action.result())) continue; //忽略模板引擎的方法
|
||||||
|
if (action.rpconly() && skipRPC) continue; //不生成RPC接口
|
||||||
|
|
||||||
|
final List<Map<String, Object>> swaggerParamsList = new ArrayList<>();
|
||||||
|
|
||||||
|
final Map<String, Object> mappingMap = new LinkedHashMap<>();
|
||||||
|
mappingMap.put("url", prefix + action.url());
|
||||||
|
actionUrls.add(action.url());
|
||||||
|
mappingMap.put("auth", action.auth());
|
||||||
|
mappingMap.put("actionid", action.actionid());
|
||||||
|
mappingMap.put("comment", action.comment());
|
||||||
|
List<Map> paramsList = new ArrayList<>();
|
||||||
|
mappingMap.put("params", paramsList);
|
||||||
|
List<String> results = new ArrayList<>();
|
||||||
|
Type resultType = action.result();
|
||||||
|
if (!action.resultref().isEmpty()) {
|
||||||
|
Field f = servlet.getClass().getDeclaredField(action.resultref());
|
||||||
|
f.setAccessible(true);
|
||||||
|
resultType = (Type) f.get(servlet);
|
||||||
|
}
|
||||||
|
// for (final Class rtype : action.results()) {
|
||||||
|
// results.add(rtype.getName());
|
||||||
|
// if (typesMap.containsKey(rtype.getName())) continue;
|
||||||
|
// if (rtype.getName().startsWith("java.")) continue;
|
||||||
|
// if (rtype.getName().startsWith("javax.")) continue;
|
||||||
|
// final boolean filter = FilterBean.class.isAssignableFrom(rtype);
|
||||||
|
// final Map<String, Map<String, Object>> typeMap = new LinkedHashMap<>();
|
||||||
|
// Class loop = rtype;
|
||||||
|
// do {
|
||||||
|
// if (loop == null || loop.isInterface()) break;
|
||||||
|
// for (Field field : loop.getDeclaredFields()) {
|
||||||
|
// if (Modifier.isFinal(field.getModifiers())) continue;
|
||||||
|
// if (Modifier.isStatic(field.getModifiers())) continue;
|
||||||
|
//
|
||||||
|
// Map<String, Object> fieldmap = new LinkedHashMap<>();
|
||||||
|
// fieldmap.put("type", field.getType().isArray() ? (field.getType().getComponentType().getName() + "[]") : field.getGenericType().getTypeName());
|
||||||
|
//
|
||||||
|
// Comment comment = field.getAnnotation(Comment.class);
|
||||||
|
// Column col = field.getAnnotation(Column.class);
|
||||||
|
// FilterColumn fc = field.getAnnotation(FilterColumn.class);
|
||||||
|
// if (comment != null) {
|
||||||
|
// fieldmap.put("comment", comment.value());
|
||||||
|
// } else if (col != null) {
|
||||||
|
// fieldmap.put("comment", col.comment());
|
||||||
|
// } else if (fc != null) {
|
||||||
|
// fieldmap.put("comment", fc.comment());
|
||||||
|
// }
|
||||||
|
// fieldmap.put("primary", !filter && (field.getAnnotation(Id.class) != null));
|
||||||
|
// fieldmap.put("updatable", (filter || col == null || col.updatable()));
|
||||||
|
// if (servlet.getClass().getAnnotation(Rest.RestDyn.class) != null) {
|
||||||
|
// if (field.getAnnotation(RestAddress.class) != null) continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// typeMap.put(field.getName(), fieldmap);
|
||||||
|
// }
|
||||||
|
// } while ((loop = loop.getSuperclass()) != Object.class);
|
||||||
|
// typesMap.put(rtype.getName(), typeMap);
|
||||||
|
// }
|
||||||
|
mappingMap.put("results", results);
|
||||||
|
boolean hasbodyparam = false;
|
||||||
|
Map<String, Object> swaggerRequestBody = new LinkedHashMap<>();
|
||||||
|
for (HttpParam param : method.getAnnotationsByType(HttpParam.class)) {
|
||||||
|
final Map<String, Object> oldapisParamMap = new LinkedHashMap<>();
|
||||||
|
final boolean isarray = param.type().isArray();
|
||||||
|
final Class ptype = isarray ? param.type().getComponentType() : param.type();
|
||||||
|
oldapisParamMap.put("name", param.name());
|
||||||
|
oldapisParamMap.put("radix", param.radix());
|
||||||
|
oldapisParamMap.put("type", ptype.getName() + (isarray ? "[]" : ""));
|
||||||
|
oldapisParamMap.put("style", param.style());
|
||||||
|
oldapisParamMap.put("comment", param.comment());
|
||||||
|
oldapisParamMap.put("required", param.required());
|
||||||
|
paramsList.add(oldapisParamMap);
|
||||||
|
{
|
||||||
|
final Map<String, Object> paramSchemaMap = new LinkedHashMap<>();
|
||||||
|
Type paramGenericType = param.type();
|
||||||
|
if (!param.typeref().isEmpty()) {
|
||||||
|
Field f = servlet.getClass().getDeclaredField(param.typeref());
|
||||||
|
f.setAccessible(true);
|
||||||
|
paramGenericType = (Type) f.get(servlet);
|
||||||
|
}
|
||||||
|
simpleSchemaType(node.getLogger(), swaggerComponentsMap, param.type(), paramGenericType, paramSchemaMap, true);
|
||||||
|
if (param.style() == HttpParam.HttpParameterStyle.BODY) {
|
||||||
|
swaggerRequestBody.put("description", param.comment());
|
||||||
|
swaggerRequestBody.put("content", Utility.ofMap(plainContentType, Utility.ofMap("schema", paramSchemaMap)));
|
||||||
|
} else {
|
||||||
|
final Map<String, Object> swaggerParamMap = new LinkedHashMap<>();
|
||||||
|
swaggerParamMap.put("name", param.name());
|
||||||
|
swaggerParamMap.put("in", param.style().name().toLowerCase());
|
||||||
|
swaggerParamMap.put("description", param.comment());
|
||||||
|
swaggerParamMap.put("required", param.required());
|
||||||
|
if (param.deprecated()) {
|
||||||
|
swaggerParamMap.put("deprecated", param.deprecated());
|
||||||
|
}
|
||||||
|
//https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameterStyle
|
||||||
|
swaggerParamMap.put("style", param.style() == HttpParam.HttpParameterStyle.HEADER || param.name().indexOf('#') == 0 ? "simple" : "form");
|
||||||
|
swaggerParamMap.put("explode", true);
|
||||||
|
swaggerParamMap.put("schema", paramSchemaMap);
|
||||||
|
Object example = formatExample(param.example(), param.type(), paramGenericType);
|
||||||
|
if (example != null) swaggerParamMap.put("example", example);
|
||||||
|
if (!param.example().isEmpty()) {
|
||||||
|
swaggerParamMap.put("example", param.example());
|
||||||
|
}
|
||||||
|
swaggerParamsList.add(swaggerParamMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (param.style() == HttpParam.HttpParameterStyle.BODY) hasbodyparam = true;
|
||||||
|
if (ptype.isPrimitive() || ptype == String.class) continue;
|
||||||
|
if (typesMap.containsKey(ptype.getName())) continue;
|
||||||
|
if (ptype.getName().startsWith("java.")) continue;
|
||||||
|
if (ptype.getName().startsWith("javax.")) continue;
|
||||||
|
|
||||||
|
final Map<String, Map<String, Object>> typeMap = new LinkedHashMap<>();
|
||||||
|
Class loop = ptype;
|
||||||
|
final boolean filter = FilterBean.class.isAssignableFrom(loop);
|
||||||
|
do {
|
||||||
|
if (loop == null || loop.isInterface()) break;
|
||||||
|
for (Field field : loop.getDeclaredFields()) {
|
||||||
|
if (Modifier.isFinal(field.getModifiers())) continue;
|
||||||
|
if (Modifier.isStatic(field.getModifiers())) continue;
|
||||||
|
|
||||||
|
Map<String, Object> fieldmap = new LinkedHashMap<>();
|
||||||
|
fieldmap.put("type", field.getType().isArray() ? (field.getType().getComponentType().getName() + "[]") : field.getGenericType().getTypeName());
|
||||||
|
|
||||||
|
Column col = field.getAnnotation(Column.class);
|
||||||
|
FilterColumn fc = field.getAnnotation(FilterColumn.class);
|
||||||
|
Comment comment = field.getAnnotation(Comment.class);
|
||||||
|
if (comment != null) {
|
||||||
|
fieldmap.put("comment", comment.value());
|
||||||
|
} else if (col != null) {
|
||||||
|
fieldmap.put("comment", col.comment());
|
||||||
|
} else if (fc != null) {
|
||||||
|
fieldmap.put("comment", fc.comment());
|
||||||
|
}
|
||||||
|
fieldmap.put("primary", !filter && (field.getAnnotation(Id.class) != null));
|
||||||
|
fieldmap.put("updatable", (filter || col == null || col.updatable()));
|
||||||
|
|
||||||
|
if (servlet.getClass().getAnnotation(Rest.RestDyn.class) != null) {
|
||||||
|
if (field.getAnnotation(RestAddress.class) != null) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
typeMap.put(field.getName(), fieldmap);
|
||||||
|
}
|
||||||
|
} while ((loop = loop.getSuperclass()) != Object.class);
|
||||||
|
|
||||||
|
typesMap.put(ptype.getName(), typeMap);
|
||||||
|
}
|
||||||
|
mappingMap.put("result", action.result().getSimpleName().replace("void", "Object"));
|
||||||
|
mappingsList.add(mappingMap);
|
||||||
|
|
||||||
|
final Map<String, Object> swaggerOperatMap = new LinkedHashMap<>();
|
||||||
|
swaggerOperatMap.put("tags", new String[]{tag});
|
||||||
|
swaggerOperatMap.put("operationId", action.name());
|
||||||
|
if (method.getAnnotation(Deprecated.class) != null) {
|
||||||
|
swaggerOperatMap.put("deprecated", true);
|
||||||
|
}
|
||||||
|
Map<String, Object> respSchemaMap = new LinkedHashMap<>();
|
||||||
|
simpleSchemaType(node.getLogger(), swaggerComponentsMap, action.result(), resultType, respSchemaMap, true);
|
||||||
|
|
||||||
|
Map<String, Object> respMap = new LinkedHashMap<>();
|
||||||
|
respMap.put("schema", respSchemaMap);
|
||||||
|
Object example = formatExample(action.example(), action.result(), resultType);
|
||||||
|
if (example != null) swaggerOperatMap.put("example", example);
|
||||||
|
if (!swaggerRequestBody.isEmpty()) swaggerOperatMap.put("requestBody", swaggerRequestBody);
|
||||||
|
swaggerOperatMap.put("parameters", swaggerParamsList);
|
||||||
|
String actiondesc = action.comment();
|
||||||
|
if (action.rpconly()) actiondesc = "[Only for RPC API] " + actiondesc;
|
||||||
|
swaggerOperatMap.put("responses", Utility.ofMap("200", Utility.ofMap("description", actiondesc, "content", Utility.ofMap("application/json", respMap))));
|
||||||
|
|
||||||
|
String m = action.methods() == null || action.methods().length == 0 ? null : action.methods()[0].toLowerCase();
|
||||||
|
if (m == null) {
|
||||||
|
m = hasbodyparam || TYPE_RETRESULT_STRING.equals(resultType) || TYPE_RETRESULT_INTEGER.equals(resultType)
|
||||||
|
|| TYPE_RETRESULT_LONG.equals(resultType) || action.name().contains("create") || action.name().contains("insert")
|
||||||
|
|| action.name().contains("update") || action.name().contains("delete") || action.name().contains("send") ? "post" : "get";
|
||||||
|
}
|
||||||
|
swaggerPathsMap.put(prefix + action.url(), Utility.ofMap("description", action.comment(), m, swaggerOperatMap));
|
||||||
|
}
|
||||||
|
} while ((clz = clz.getSuperclass()) != HttpServlet.class);
|
||||||
|
mappingsList.sort((o1, o2) -> ((String) o1.get("url")).compareTo((String) o2.get("url")));
|
||||||
|
servletsList.add(servletMap);
|
||||||
|
if (!actionUrls.isEmpty()) swaggerTags.add(Utility.ofMap("name", tag, "description", ws.comment()));
|
||||||
|
}
|
||||||
|
servletsList.sort((o1, o2) -> {
|
||||||
|
String[] urlregs1 = (String[]) o1.get("urlregs");
|
||||||
|
String[] urlregs2 = (String[]) o2.get("urlregs");
|
||||||
|
return urlregs1.length > 0 ? (urlregs2.length > 0 ? urlregs1[0].compareTo(urlregs2[0]) : 1) : -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{ // https://github.com/OAI/OpenAPI-Specification
|
||||||
|
Map<String, Object> swaggerResultMap = new LinkedHashMap<>();
|
||||||
|
swaggerResultMap.put("openapi", "3.0.0");
|
||||||
|
Map<String, Object> infomap = new LinkedHashMap<>();
|
||||||
|
infomap.put("title", "Redkale generate apidoc");
|
||||||
|
infomap.put("version", "1.0.0");
|
||||||
|
swaggerResultMap.put("info", infomap);
|
||||||
|
swaggerResultMap.put("servers", swaggerServers);
|
||||||
|
swaggerResultMap.put("paths", swaggerPathsMap);
|
||||||
|
swaggerResultMap.put("tags", swaggerTags);
|
||||||
|
if (!swaggerComponentsMap.isEmpty()) swaggerResultMap.put("components", Utility.ofMap("schemas", swaggerComponentsMap));
|
||||||
|
final FileOutputStream out = new FileOutputStream(new File(app.getHome(), "openapi-doc.json"));
|
||||||
|
out.write(JsonConvert.root().convertTo(swaggerResultMap).getBytes(StandardCharsets.UTF_8));
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Map<String, Object> oldapisResultMap = new LinkedHashMap<>();
|
||||||
|
oldapisResultMap.put("servers", serverList);
|
||||||
|
oldapisResultMap.put("types", typesMap);
|
||||||
|
final String json = JsonConvert.root().convertTo(oldapisResultMap);
|
||||||
|
final FileOutputStream out = new FileOutputStream(new File(app.getHome(), "apidoc.json"));
|
||||||
|
out.write(json.getBytes(StandardCharsets.UTF_8));
|
||||||
|
out.close();
|
||||||
|
File doctemplate = new File(app.getConfPath().toString(), "apidoc-template.html");
|
||||||
|
InputStream in = null;
|
||||||
|
if (doctemplate.isFile() && doctemplate.canRead()) {
|
||||||
|
in = new FileInputStream(doctemplate);
|
||||||
|
}
|
||||||
|
if (in == null) in = ApiDocsService.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(StandardCharsets.UTF_8));
|
||||||
|
outhtml.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void simpleSchemaType(Logger logger, Map<String, Map<String, Object>> componentsMap, Class type, Type genericType, Map<String, Object> schemaMap, boolean recursive) {
|
||||||
|
if (type == int.class || type == Integer.class || type == AtomicInteger.class) {
|
||||||
|
schemaMap.put("type", "integer");
|
||||||
|
schemaMap.put("format", "int32");
|
||||||
|
} else if (type == long.class || type == Long.class
|
||||||
|
|| type == AtomicLong.class || type == LongAdder.class || type == BigInteger.class) {
|
||||||
|
schemaMap.put("type", "integer");
|
||||||
|
schemaMap.put("format", "int64");
|
||||||
|
} else if (type == float.class || type == Float.class) {
|
||||||
|
schemaMap.put("type", "number");
|
||||||
|
schemaMap.put("format", "float");
|
||||||
|
} else if (type == double.class || type == Double.class || type == BigDecimal.class) {
|
||||||
|
schemaMap.put("type", "number");
|
||||||
|
schemaMap.put("format", "double");
|
||||||
|
} else if (type == boolean.class || type == Boolean.class || type == AtomicBoolean.class) {
|
||||||
|
schemaMap.put("type", "boolean");
|
||||||
|
} else if (type.isPrimitive() || Number.class.isAssignableFrom(type)) {
|
||||||
|
schemaMap.put("type", "number");
|
||||||
|
} else if (type == String.class || CharSequence.class.isAssignableFrom(type)) {
|
||||||
|
schemaMap.put("type", "string");
|
||||||
|
} else if (recursive && (type.isArray() || Collection.class.isAssignableFrom(type))) {
|
||||||
|
schemaMap.put("type", "array");
|
||||||
|
Map<String, Object> sbumap = new LinkedHashMap<>();
|
||||||
|
if (type.isArray()) {
|
||||||
|
simpleSchemaType(logger, componentsMap, type.getComponentType(), type.getComponentType(), sbumap, false);
|
||||||
|
} else if (genericType instanceof ParameterizedType) {
|
||||||
|
Type subpt = ((ParameterizedType) genericType).getActualTypeArguments()[0];
|
||||||
|
if (subpt instanceof Class) {
|
||||||
|
simpleSchemaType(logger, componentsMap, (Class) subpt, subpt, sbumap, false);
|
||||||
|
} else if (subpt instanceof ParameterizedType && ((ParameterizedType) subpt).getOwnerType() instanceof Class) {
|
||||||
|
simpleSchemaType(logger, componentsMap, (Class) ((ParameterizedType) subpt).getOwnerType(), subpt, sbumap, false);
|
||||||
|
} else {
|
||||||
|
sbumap.put("type", "object");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sbumap.put("type", "object");
|
||||||
|
}
|
||||||
|
schemaMap.put("items", sbumap);
|
||||||
|
} else if (!type.getName().startsWith("java.") && !type.getName().startsWith("javax.")) {
|
||||||
|
String ct = simpleComponentType(logger, componentsMap, type, genericType);
|
||||||
|
if (ct == null) {
|
||||||
|
schemaMap.put("type", "object");
|
||||||
|
} else {
|
||||||
|
schemaMap.put("$ref", "#/components/schemas/" + ct);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
schemaMap.put("type", "object");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String simpleComponentType(Logger logger, Map<String, Map<String, Object>> componentsMap, Class type, Type genericType) {
|
||||||
|
try {
|
||||||
|
Encodeable encodeable = JsonFactory.root().loadEncoder(genericType);
|
||||||
|
String ct = componentKey(logger, componentsMap, null, encodeable, true);
|
||||||
|
if (ct == null || ct.length() == 0) return null;
|
||||||
|
if (componentsMap.containsKey(ct)) return ct;
|
||||||
|
Map<String, Object> cmap = new LinkedHashMap<>();
|
||||||
|
componentsMap.put(ct, cmap); //必须在调用simpleSchemaType之前put,不然嵌套情况下死循环
|
||||||
|
|
||||||
|
cmap.put("type", "object");
|
||||||
|
List<String> requireds = new ArrayList<>();
|
||||||
|
Map<String, Object> properties = new LinkedHashMap<>();
|
||||||
|
if (encodeable instanceof ObjectEncoder) {
|
||||||
|
for (EnMember member : ((ObjectEncoder) encodeable).getMembers()) {
|
||||||
|
Map<String, Object> schemaMap = new LinkedHashMap<>();
|
||||||
|
simpleSchemaType(logger, componentsMap, TypeToken.typeToClassOrElse(member.getEncoder().getType(), Object.class), member.getEncoder().getType(), schemaMap, true);
|
||||||
|
String desc = "";
|
||||||
|
if (member.getField() != null) {
|
||||||
|
Column col = member.getField().getAnnotation(Column.class);
|
||||||
|
if (col == null) {
|
||||||
|
FilterColumn fcol = member.getField().getAnnotation(FilterColumn.class);
|
||||||
|
if (fcol != null) {
|
||||||
|
desc = fcol.comment();
|
||||||
|
if (fcol.required()) requireds.add(member.getAttribute().field());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
desc = col.comment();
|
||||||
|
if (!col.nullable()) requireds.add(member.getAttribute().field());
|
||||||
|
}
|
||||||
|
if (desc.isEmpty() && member.getField().getAnnotation(Comment.class) != null) {
|
||||||
|
desc = member.getField().getAnnotation(Comment.class).value();
|
||||||
|
}
|
||||||
|
} else if (member.getMethod() != null) {
|
||||||
|
Column col = member.getMethod().getAnnotation(Column.class);
|
||||||
|
if (col == null) {
|
||||||
|
FilterColumn fcol = member.getMethod().getAnnotation(FilterColumn.class);
|
||||||
|
if (fcol != null) {
|
||||||
|
desc = fcol.comment();
|
||||||
|
if (fcol.required()) requireds.add(member.getAttribute().field());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
desc = col.comment();
|
||||||
|
if (!col.nullable()) requireds.add(member.getAttribute().field());
|
||||||
|
}
|
||||||
|
if (desc.isEmpty() && member.getMethod().getAnnotation(Comment.class) != null) {
|
||||||
|
desc = member.getMethod().getAnnotation(Comment.class).value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!desc.isEmpty()) schemaMap.put("description", desc);
|
||||||
|
properties.put(member.getAttribute().field(), schemaMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!requireds.isEmpty()) cmap.put("required", requireds);
|
||||||
|
cmap.put("properties", properties);
|
||||||
|
return ct;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.WARNING, genericType + " generate component info error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String componentKey(Logger logger, Map<String, Map<String, Object>> componentsMap, EnMember field, Encodeable encodeable, boolean first) {
|
||||||
|
if (encodeable instanceof ObjectEncoder) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(((ObjectEncoder) encodeable).getTypeClass().getSimpleName());
|
||||||
|
for (EnMember member : ((ObjectEncoder) encodeable).getMembers()) {
|
||||||
|
if (member.getEncoder() instanceof ArrayEncoder
|
||||||
|
|| member.getEncoder() instanceof CollectionEncoder) {
|
||||||
|
String subsb = componentKey(logger, componentsMap, member, member.getEncoder(), false);
|
||||||
|
if (subsb == null) return null;
|
||||||
|
AccessibleObject real = member.getField() == null ? member.getMethod() : member.getField();
|
||||||
|
if (real == null) continue;
|
||||||
|
Class cz = real instanceof Field ? ((Field) real).getType() : ((Method) real).getReturnType();
|
||||||
|
Type ct = real instanceof Field ? ((Field) real).getGenericType() : ((Method) real).getGenericReturnType();
|
||||||
|
if (cz == ct) continue;
|
||||||
|
if (sb.length() > 0 && subsb.length() > 0) sb.append("_");
|
||||||
|
sb.append(subsb);
|
||||||
|
} else if (member.getEncoder() instanceof ObjectEncoder || member.getEncoder() instanceof SimpledCoder) {
|
||||||
|
AccessibleObject real = member.getField() == null ? member.getMethod() : member.getField();
|
||||||
|
if (real == null) continue;
|
||||||
|
if (member.getEncoder() instanceof SimpledCoder) {
|
||||||
|
simpleSchemaType(logger, componentsMap, ((SimpledCoder) member.getEncoder()).getType(), ((SimpledCoder) member.getEncoder()).getType(), new LinkedHashMap<>(), true);
|
||||||
|
} else {
|
||||||
|
simpleSchemaType(logger, componentsMap, ((ObjectEncoder) member.getEncoder()).getTypeClass(), ((ObjectEncoder) member.getEncoder()).getType(), new LinkedHashMap<>(), true);
|
||||||
|
}
|
||||||
|
Class cz = real instanceof Field ? ((Field) real).getType() : ((Method) real).getReturnType();
|
||||||
|
Type ct = real instanceof Field ? ((Field) real).getGenericType() : ((Method) real).getGenericReturnType();
|
||||||
|
if (cz == ct) continue;
|
||||||
|
String subsb = componentKey(logger, componentsMap, member, member.getEncoder(), false);
|
||||||
|
if (subsb == null) return null;
|
||||||
|
if (sb.length() > 0 && subsb.length() > 0) sb.append("_");
|
||||||
|
sb.append(subsb);
|
||||||
|
} else if (member.getEncoder() instanceof MapEncoder) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
} else if (encodeable instanceof ArrayEncoder || encodeable instanceof CollectionEncoder) {
|
||||||
|
final boolean array = (encodeable instanceof ArrayEncoder);
|
||||||
|
Encodeable subEncodeable = array ? ((ArrayEncoder) encodeable).getComponentEncoder() : ((CollectionEncoder) encodeable).getComponentEncoder();
|
||||||
|
if (subEncodeable instanceof SimpledCoder && field != null) return "";
|
||||||
|
final String sb = componentKey(logger, componentsMap, null, subEncodeable, false);
|
||||||
|
if (sb == null || sb.isEmpty()) return sb;
|
||||||
|
if (field != null && field.getField() != null && field.getField().getDeclaringClass() == Sheet.class) {
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
return sb + (array ? "_Array" : "_Collection");
|
||||||
|
} else if (encodeable instanceof SimpledCoder) {
|
||||||
|
Class stype = ((SimpledCoder) encodeable).getType();
|
||||||
|
if (stype.isPrimitive() || stype == Boolean.class || Number.class.isAssignableFrom(stype) || CharSequence.class.isAssignableFrom(stype)) {
|
||||||
|
return stype.getSimpleName();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
} else if (encodeable instanceof MapEncoder) {
|
||||||
|
return first ? null : "";
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object formatExample(String example, Class type, Type genericType) {
|
||||||
|
if (example == null || example.isEmpty()) return null;
|
||||||
|
if (type == Flipper.class) {
|
||||||
|
return new Flipper();
|
||||||
|
} else if (TYPE_RETRESULT_OBJECT.equals(genericType)) {
|
||||||
|
return RetResult.success();
|
||||||
|
} else if (TYPE_RETRESULT_STRING.equals(genericType)) {
|
||||||
|
return RetResult.success();
|
||||||
|
} else if (TYPE_RETRESULT_INTEGER.equals(genericType)) {
|
||||||
|
return RetResult.success(0);
|
||||||
|
} else if (TYPE_RETRESULT_LONG.equals(genericType)) {
|
||||||
|
return RetResult.success(0L);
|
||||||
|
}
|
||||||
|
return example;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,53 +1,69 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot;
|
package org.redkale.boot;
|
||||||
|
|
||||||
import org.redkale.util.AnyValue;
|
import org.redkale.util.AnyValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application启动和关闭时的监听事件 <br>
|
* Application启动和关闭时的监听事件 <br>
|
||||||
* 只能通过application.xml配置
|
* 只能通过application.xml配置
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public interface ApplicationListener {
|
public interface ApplicationListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化方法
|
* 初始化方法
|
||||||
*
|
*
|
||||||
* @param config 配置参数
|
* @param config 配置参数
|
||||||
*/
|
*/
|
||||||
default void init(AnyValue config) {
|
default void init(AnyValue config) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application 在运行start前调用
|
* Application 在运行start前调用
|
||||||
*
|
*
|
||||||
* @param application Application
|
* @param application Application
|
||||||
*/
|
*/
|
||||||
default void preStart(Application application) {
|
default void preStart(Application application) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application 在运行start后调用
|
* Application 在运行start后调用
|
||||||
*
|
*
|
||||||
* @param application Application
|
* @param application Application
|
||||||
*/
|
*/
|
||||||
default void postStart(Application application) {
|
default void postStart(Application application) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application 在运行shutdown前调用
|
* Application 在运行Compile前调用
|
||||||
*
|
*
|
||||||
* @param application Application
|
* @param application Application
|
||||||
*/
|
*/
|
||||||
default void preShutdown(Application application) {
|
default void preCompile(Application application) {
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Application 在运行Compile后调用
|
||||||
|
*
|
||||||
|
* @param application Application
|
||||||
|
*/
|
||||||
|
default void postCompile(Application application) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application 在运行shutdown前调用
|
||||||
|
*
|
||||||
|
* @param application Application
|
||||||
|
*/
|
||||||
|
default void preShutdown(Application application) {
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,366 +1,372 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot;
|
package org.redkale.boot;
|
||||||
|
|
||||||
import java.io.*;
|
import org.redkale.util.RedkaleClassLoader;
|
||||||
import java.nio.file.*;
|
|
||||||
import static java.nio.file.StandardCopyOption.*;
|
import java.io.*;
|
||||||
import java.time.*;
|
import java.nio.file.*;
|
||||||
import java.util.*;
|
import static java.nio.file.StandardCopyOption.*;
|
||||||
import java.util.concurrent.*;
|
import java.time.*;
|
||||||
import java.util.concurrent.atomic.*;
|
import java.util.*;
|
||||||
import java.util.logging.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.logging.Formatter;
|
import java.util.concurrent.atomic.*;
|
||||||
import java.util.regex.Pattern;
|
import java.util.logging.*;
|
||||||
|
import java.util.logging.Formatter;
|
||||||
/**
|
import java.util.regex.Pattern;
|
||||||
* 自定义的日志输出类
|
|
||||||
* <p>
|
/**
|
||||||
* 详情见: https://redkale.org
|
* 自定义的日志输出类
|
||||||
*
|
* <p>
|
||||||
* @author zhangjx
|
* 详情见: https://redkale.org
|
||||||
*/
|
*
|
||||||
@SuppressWarnings("unchecked")
|
* @author zhangjx
|
||||||
public class LogFileHandler extends Handler {
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
/**
|
public class LoggingFileHandler extends Handler {
|
||||||
* SNCP的日志输出Handler
|
|
||||||
*/
|
//public static final String FORMATTER_FORMAT = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL %4$s %2$s%n%5$s%6$s%n";
|
||||||
public static class SncpLogFileHandler extends LogFileHandler {
|
public static final String FORMATTER_FORMAT = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL %4$s %2$s\r\n%5$s%6$s\r\n";
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public String getPrefix() {
|
* SNCP的日志输出Handler
|
||||||
return "sncp-";
|
*/
|
||||||
}
|
public static class LoggingSncpFileHandler extends LoggingFileHandler {
|
||||||
}
|
|
||||||
|
@Override
|
||||||
/**
|
public String getPrefix() {
|
||||||
* 默认的日志时间格式化类
|
return "sncp-";
|
||||||
*
|
}
|
||||||
*/
|
}
|
||||||
public static class LoggingFormater extends Formatter {
|
|
||||||
|
/**
|
||||||
private static final String format = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL %4$s %2$s\r\n%5$s%6$s\r\n";
|
* 默认的日志时间格式化类
|
||||||
|
* 与SimpleFormatter的区别在于level不使用本地化
|
||||||
@Override
|
*
|
||||||
public String format(LogRecord log) {
|
*/
|
||||||
String source;
|
public static class LoggingFormater extends Formatter {
|
||||||
if (log.getSourceClassName() != null) {
|
|
||||||
source = log.getSourceClassName();
|
@Override
|
||||||
if (log.getSourceMethodName() != null) {
|
public String format(LogRecord log) {
|
||||||
source += " " + log.getSourceMethodName();
|
String source;
|
||||||
}
|
if (log.getSourceClassName() != null) {
|
||||||
} else {
|
source = log.getSourceClassName();
|
||||||
source = log.getLoggerName();
|
if (log.getSourceMethodName() != null) {
|
||||||
}
|
source += " " + log.getSourceMethodName();
|
||||||
String message = formatMessage(log);
|
}
|
||||||
String throwable = "";
|
} else {
|
||||||
if (log.getThrown() != null) {
|
source = log.getLoggerName();
|
||||||
StringWriter sw = new StringWriter();
|
}
|
||||||
PrintWriter pw = new PrintWriter(sw) {
|
String message = formatMessage(log);
|
||||||
@Override
|
String throwable = "";
|
||||||
public void println() {
|
if (log.getThrown() != null) {
|
||||||
super.print("\r\n");
|
StringWriter sw = new StringWriter();
|
||||||
}
|
PrintWriter pw = new PrintWriter(sw) {
|
||||||
};
|
@Override
|
||||||
pw.println();
|
public void println() {
|
||||||
log.getThrown().printStackTrace(pw);
|
super.print("\r\n");
|
||||||
pw.close();
|
}
|
||||||
throwable = sw.toString();
|
};
|
||||||
}
|
pw.println();
|
||||||
return String.format(format,
|
log.getThrown().printStackTrace(pw);
|
||||||
System.currentTimeMillis(),
|
pw.close();
|
||||||
source,
|
throwable = sw.toString();
|
||||||
log.getLoggerName(),
|
}
|
||||||
log.getLevel().getName(),
|
return String.format(FORMATTER_FORMAT,
|
||||||
message,
|
System.currentTimeMillis(),
|
||||||
throwable);
|
source,
|
||||||
}
|
log.getLoggerName(),
|
||||||
}
|
log.getLevel().getName(),
|
||||||
|
message,
|
||||||
public static void initDebugLogConfig() {
|
throwable);
|
||||||
try {
|
}
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
}
|
||||||
final PrintStream ps = new PrintStream(out);
|
|
||||||
ps.println("handlers = java.util.logging.ConsoleHandler");
|
public static void initDebugLogConfig() {
|
||||||
ps.println(".level = FINEST");
|
try {
|
||||||
ps.println("jdk.level = INFO");
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
ps.println("sun.level = INFO");
|
final PrintStream ps = new PrintStream(out);
|
||||||
ps.println("com.sun.level = INFO");
|
ps.println("handlers = java.util.logging.ConsoleHandler");
|
||||||
ps.println("javax.level = INFO");
|
ps.println(".level = FINEST");
|
||||||
ps.println("java.util.logging.ConsoleHandler.level = FINEST");
|
ps.println("jdk.level = INFO");
|
||||||
ps.println("java.util.logging.ConsoleHandler.formatter = " + LogFileHandler.LoggingFormater.class.getName());
|
ps.println("sun.level = INFO");
|
||||||
LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(out.toByteArray()));
|
ps.println("com.sun.level = INFO");
|
||||||
} catch (Exception e) {
|
ps.println("javax.level = INFO");
|
||||||
}
|
ps.println("java.util.logging.ConsoleHandler.level = FINEST");
|
||||||
}
|
ps.println("java.util.logging.ConsoleHandler.formatter = " + LoggingFileHandler.LoggingFormater.class.getName());
|
||||||
|
LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(out.toByteArray()));
|
||||||
protected final LinkedBlockingQueue<LogRecord> logqueue = new LinkedBlockingQueue();
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
private String pattern;
|
}
|
||||||
|
|
||||||
private String unusual; //不为null表示将 WARNING、SEVERE 级别的日志写入单独的文件中
|
protected final LinkedBlockingQueue<LogRecord> logqueue = new LinkedBlockingQueue();
|
||||||
|
|
||||||
private int limit; //文件大小限制
|
private String pattern;
|
||||||
|
|
||||||
private final AtomicInteger logindex = new AtomicInteger();
|
private String unusual; //不为null表示将 WARNING、SEVERE 级别的日志写入单独的文件中
|
||||||
|
|
||||||
private final AtomicInteger logunusualindex = new AtomicInteger();
|
private int limit; //文件大小限制
|
||||||
|
|
||||||
private int count = 1; //文件限制
|
private final AtomicInteger logindex = new AtomicInteger();
|
||||||
|
|
||||||
private long tomorrow;
|
private final AtomicInteger logunusualindex = new AtomicInteger();
|
||||||
|
|
||||||
private boolean append;
|
private int count = 1; //文件限制
|
||||||
|
|
||||||
private Pattern denyreg;
|
private long tomorrow;
|
||||||
|
|
||||||
private final AtomicLong loglength = new AtomicLong();
|
private boolean append;
|
||||||
|
|
||||||
private final AtomicLong logunusuallength = new AtomicLong();
|
private Pattern denyreg;
|
||||||
|
|
||||||
private File logfile;
|
private final AtomicLong loglength = new AtomicLong();
|
||||||
|
|
||||||
private File logunusualfile;
|
private final AtomicLong logunusuallength = new AtomicLong();
|
||||||
|
|
||||||
private OutputStream logstream;
|
private File logfile;
|
||||||
|
|
||||||
private OutputStream logunusualstream;
|
private File logunusualfile;
|
||||||
|
|
||||||
public LogFileHandler() {
|
private OutputStream logstream;
|
||||||
updateTomorrow();
|
|
||||||
configure();
|
private OutputStream logunusualstream;
|
||||||
open();
|
|
||||||
}
|
public LoggingFileHandler() {
|
||||||
|
updateTomorrow();
|
||||||
private void updateTomorrow() {
|
configure();
|
||||||
Calendar cal = Calendar.getInstance();
|
open();
|
||||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
}
|
||||||
cal.set(Calendar.MINUTE, 0);
|
|
||||||
cal.set(Calendar.SECOND, 0);
|
private void updateTomorrow() {
|
||||||
cal.set(Calendar.MILLISECOND, 0);
|
Calendar cal = Calendar.getInstance();
|
||||||
cal.add(Calendar.DAY_OF_YEAR, 1);
|
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
long t = cal.getTimeInMillis();
|
cal.set(Calendar.MINUTE, 0);
|
||||||
if (this.tomorrow != t) logindex.set(0);
|
cal.set(Calendar.SECOND, 0);
|
||||||
this.tomorrow = t;
|
cal.set(Calendar.MILLISECOND, 0);
|
||||||
}
|
cal.add(Calendar.DAY_OF_YEAR, 1);
|
||||||
|
long t = cal.getTimeInMillis();
|
||||||
private void open() {
|
if (this.tomorrow != t) logindex.set(0);
|
||||||
final String name = "Redkale-Logging-" + getClass().getSimpleName() + "-Thread";
|
this.tomorrow = t;
|
||||||
new Thread() {
|
}
|
||||||
{
|
|
||||||
setName(name);
|
private void open() {
|
||||||
setDaemon(true);
|
final String name = "Redkale-Logging-" + getClass().getSimpleName() + "-Thread";
|
||||||
}
|
new Thread() {
|
||||||
|
{
|
||||||
@Override
|
setName(name);
|
||||||
public void run() {
|
setDaemon(true);
|
||||||
while (true) {
|
}
|
||||||
try {
|
|
||||||
LogRecord log = logqueue.take();
|
@Override
|
||||||
final boolean bigger = (limit > 0 && limit <= loglength.get());
|
public void run() {
|
||||||
final boolean changeday = tomorrow <= log.getMillis();
|
while (true) {
|
||||||
if (bigger || changeday) {
|
try {
|
||||||
updateTomorrow();
|
LogRecord log = logqueue.take();
|
||||||
if (logstream != null) {
|
final boolean bigger = (limit > 0 && limit <= loglength.get());
|
||||||
logstream.close();
|
final boolean changeday = tomorrow <= log.getMillis();
|
||||||
if (bigger) {
|
if (bigger || changeday) {
|
||||||
for (int i = Math.min(count - 2, logindex.get() - 1); i > 0; i--) {
|
updateTomorrow();
|
||||||
File greater = new File(logfile.getPath() + "." + i);
|
if (logstream != null) {
|
||||||
if (greater.exists()) Files.move(greater.toPath(), new File(logfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
logstream.close();
|
||||||
}
|
if (bigger) {
|
||||||
Files.move(logfile.toPath(), new File(logfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
for (int i = Math.min(count - 2, logindex.get() - 1); i > 0; i--) {
|
||||||
} else {
|
File greater = new File(logfile.getPath() + "." + i);
|
||||||
if (logfile.exists() && logfile.length() < 1) logfile.delete();
|
if (greater.exists()) Files.move(greater.toPath(), new File(logfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||||
}
|
}
|
||||||
logstream = null;
|
Files.move(logfile.toPath(), new File(logfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||||
}
|
} else {
|
||||||
}
|
if (logfile.exists() && logfile.length() < 1) logfile.delete();
|
||||||
if (unusual != null && changeday && logunusualstream != null) {
|
}
|
||||||
logunusualstream.close();
|
logstream = null;
|
||||||
if (limit > 0 && limit <= logunusuallength.get()) {
|
}
|
||||||
for (int i = Math.min(count - 2, logunusualindex.get() - 1); i > 0; i--) {
|
}
|
||||||
File greater = new File(logunusualfile.getPath() + "." + i);
|
if (unusual != null && changeday && logunusualstream != null) {
|
||||||
if (greater.exists()) Files.move(greater.toPath(), new File(logunusualfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
logunusualstream.close();
|
||||||
}
|
if (limit > 0 && limit <= logunusuallength.get()) {
|
||||||
Files.move(logunusualfile.toPath(), new File(logunusualfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
for (int i = Math.min(count - 2, logunusualindex.get() - 1); i > 0; i--) {
|
||||||
} else {
|
File greater = new File(logunusualfile.getPath() + "." + i);
|
||||||
if (logunusualfile.exists() && logunusualfile.length() < 1) logunusualfile.delete();
|
if (greater.exists()) Files.move(greater.toPath(), new File(logunusualfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||||
}
|
}
|
||||||
logunusualstream = null;
|
Files.move(logunusualfile.toPath(), new File(logunusualfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE);
|
||||||
}
|
} else {
|
||||||
if (logstream == null) {
|
if (logunusualfile.exists() && logunusualfile.length() < 1) logunusualfile.delete();
|
||||||
logindex.incrementAndGet();
|
}
|
||||||
java.time.LocalDate date = LocalDate.now();
|
logunusualstream = null;
|
||||||
logfile = new File(pattern.replace("%m", String.valueOf((date.getYear() * 100 + date.getMonthValue()))).replace("%d", String.valueOf((date.getYear() * 10000 + date.getMonthValue() * 100 + date.getDayOfMonth()))));
|
}
|
||||||
logfile.getParentFile().mkdirs();
|
if (logstream == null) {
|
||||||
loglength.set(logfile.length());
|
logindex.incrementAndGet();
|
||||||
logstream = new FileOutputStream(logfile, append);
|
java.time.LocalDate date = LocalDate.now();
|
||||||
}
|
logfile = new File(pattern.replace("%m", String.valueOf((date.getYear() * 100 + date.getMonthValue()))).replace("%d", String.valueOf((date.getYear() * 10000 + date.getMonthValue() * 100 + date.getDayOfMonth()))));
|
||||||
if (unusual != null && logunusualstream == null) {
|
logfile.getParentFile().mkdirs();
|
||||||
logunusualindex.incrementAndGet();
|
loglength.set(logfile.length());
|
||||||
java.time.LocalDate date = LocalDate.now();
|
logstream = new FileOutputStream(logfile, append);
|
||||||
logunusualfile = new File(unusual.replace("%m", String.valueOf((date.getYear() * 100 + date.getMonthValue()))).replace("%d", String.valueOf((date.getYear() * 10000 + date.getMonthValue() * 100 + date.getDayOfMonth()))));
|
}
|
||||||
logunusualfile.getParentFile().mkdirs();
|
if (unusual != null && logunusualstream == null) {
|
||||||
logunusuallength.set(logunusualfile.length());
|
logunusualindex.incrementAndGet();
|
||||||
logunusualstream = new FileOutputStream(logunusualfile, append);
|
java.time.LocalDate date = LocalDate.now();
|
||||||
}
|
logunusualfile = new File(unusual.replace("%m", String.valueOf((date.getYear() * 100 + date.getMonthValue()))).replace("%d", String.valueOf((date.getYear() * 10000 + date.getMonthValue() * 100 + date.getDayOfMonth()))));
|
||||||
//----------------------写日志-------------------------
|
logunusualfile.getParentFile().mkdirs();
|
||||||
String message = getFormatter().format(log);
|
logunusuallength.set(logunusualfile.length());
|
||||||
String encoding = getEncoding();
|
logunusualstream = new FileOutputStream(logunusualfile, append);
|
||||||
byte[] bytes = encoding == null ? message.getBytes() : message.getBytes(encoding);
|
}
|
||||||
logstream.write(bytes);
|
//----------------------写日志-------------------------
|
||||||
loglength.addAndGet(bytes.length);
|
String message = getFormatter().format(log);
|
||||||
if (unusual != null && (log.getLevel() == Level.WARNING || log.getLevel() == Level.SEVERE)) {
|
String encoding = getEncoding();
|
||||||
logunusualstream.write(bytes);
|
byte[] bytes = encoding == null ? message.getBytes() : message.getBytes(encoding);
|
||||||
logunusuallength.addAndGet(bytes.length);
|
logstream.write(bytes);
|
||||||
}
|
loglength.addAndGet(bytes.length);
|
||||||
} catch (Exception e) {
|
if (unusual != null && (log.getLevel() == Level.WARNING || log.getLevel() == Level.SEVERE)) {
|
||||||
ErrorManager err = getErrorManager();
|
logunusualstream.write(bytes);
|
||||||
if (err != null) err.error(null, e, ErrorManager.WRITE_FAILURE);
|
logunusuallength.addAndGet(bytes.length);
|
||||||
}
|
}
|
||||||
}
|
} catch (Exception e) {
|
||||||
|
ErrorManager err = getErrorManager();
|
||||||
}
|
if (err != null) err.error(null, e, ErrorManager.WRITE_FAILURE);
|
||||||
}.start();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPrefix() {
|
}
|
||||||
return "";
|
}.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configure() {
|
public String getPrefix() {
|
||||||
LogManager manager = LogManager.getLogManager();
|
return "";
|
||||||
String cname = LogFileHandler.class.getName();
|
}
|
||||||
this.pattern = manager.getProperty(cname + ".pattern");
|
|
||||||
if (this.pattern == null) {
|
private void configure() {
|
||||||
this.pattern = "logs-%m/" + getPrefix() + "log-%d.log";
|
LogManager manager = LogManager.getLogManager();
|
||||||
} else {
|
String cname = LoggingFileHandler.class.getName();
|
||||||
int pos = this.pattern.lastIndexOf('/');
|
this.pattern = manager.getProperty(cname + ".pattern");
|
||||||
if (pos > 0) {
|
if (this.pattern == null) {
|
||||||
this.pattern = this.pattern.substring(0, pos + 1) + getPrefix() + this.pattern.substring(pos + 1);
|
this.pattern = "logs-%m/" + getPrefix() + "log-%d.log";
|
||||||
} else {
|
} else {
|
||||||
this.pattern = getPrefix() + this.pattern;
|
int pos = this.pattern.lastIndexOf('/');
|
||||||
}
|
if (pos > 0) {
|
||||||
}
|
this.pattern = this.pattern.substring(0, pos + 1) + getPrefix() + this.pattern.substring(pos + 1);
|
||||||
String unusualstr = manager.getProperty(cname + ".unusual");
|
} else {
|
||||||
if (unusualstr != null) {
|
this.pattern = getPrefix() + this.pattern;
|
||||||
int pos = unusualstr.lastIndexOf('/');
|
}
|
||||||
if (pos > 0) {
|
}
|
||||||
this.unusual = unusualstr.substring(0, pos + 1) + getPrefix() + unusualstr.substring(pos + 1);
|
String unusualstr = manager.getProperty(cname + ".unusual");
|
||||||
} else {
|
if (unusualstr != null) {
|
||||||
this.unusual = getPrefix() + unusualstr;
|
int pos = unusualstr.lastIndexOf('/');
|
||||||
}
|
if (pos > 0) {
|
||||||
}
|
this.unusual = unusualstr.substring(0, pos + 1) + getPrefix() + unusualstr.substring(pos + 1);
|
||||||
String limitstr = manager.getProperty(cname + ".limit");
|
} else {
|
||||||
try {
|
this.unusual = getPrefix() + unusualstr;
|
||||||
if (limitstr != null) {
|
}
|
||||||
limitstr = limitstr.toUpperCase();
|
}
|
||||||
boolean g = limitstr.indexOf('G') > 0;
|
String limitstr = manager.getProperty(cname + ".limit");
|
||||||
boolean m = limitstr.indexOf('M') > 0;
|
try {
|
||||||
boolean k = limitstr.indexOf('K') > 0;
|
if (limitstr != null) {
|
||||||
int ls = Math.abs(Integer.decode(limitstr.replace("G", "").replace("M", "").replace("K", "").replace("B", "")));
|
limitstr = limitstr.toUpperCase();
|
||||||
if (g) {
|
boolean g = limitstr.indexOf('G') > 0;
|
||||||
ls *= 1024 * 1024 * 1024;
|
boolean m = limitstr.indexOf('M') > 0;
|
||||||
} else if (m) {
|
boolean k = limitstr.indexOf('K') > 0;
|
||||||
ls *= 1024 * 1024;
|
int ls = Math.abs(Integer.decode(limitstr.replace("G", "").replace("M", "").replace("K", "").replace("B", "")));
|
||||||
} else if (k) {
|
if (g) {
|
||||||
ls *= 1024;
|
ls *= 1024 * 1024 * 1024;
|
||||||
}
|
} else if (m) {
|
||||||
this.limit = ls;
|
ls *= 1024 * 1024;
|
||||||
}
|
} else if (k) {
|
||||||
} catch (Exception e) {
|
ls *= 1024;
|
||||||
}
|
}
|
||||||
String countstr = manager.getProperty(cname + ".count");
|
this.limit = ls;
|
||||||
try {
|
}
|
||||||
if (countstr != null) this.count = Math.max(1, Math.abs(Integer.decode(countstr)));
|
} catch (Exception e) {
|
||||||
} catch (Exception e) {
|
}
|
||||||
}
|
String countstr = manager.getProperty(cname + ".count");
|
||||||
String appendstr = manager.getProperty(cname + ".append");
|
try {
|
||||||
try {
|
if (countstr != null) this.count = Math.max(1, Math.abs(Integer.decode(countstr)));
|
||||||
if (appendstr != null) this.append = "true".equalsIgnoreCase(appendstr) || "1".equals(appendstr);
|
} catch (Exception e) {
|
||||||
} catch (Exception e) {
|
}
|
||||||
}
|
String appendstr = manager.getProperty(cname + ".append");
|
||||||
String levelstr = manager.getProperty(cname + ".level");
|
try {
|
||||||
try {
|
if (appendstr != null) this.append = "true".equalsIgnoreCase(appendstr) || "1".equals(appendstr);
|
||||||
if (levelstr != null) {
|
} catch (Exception e) {
|
||||||
Level l = Level.parse(levelstr);
|
}
|
||||||
setLevel(l != null ? l : Level.ALL);
|
String levelstr = manager.getProperty(cname + ".level");
|
||||||
}
|
try {
|
||||||
} catch (Exception e) {
|
if (levelstr != null) {
|
||||||
}
|
Level l = Level.parse(levelstr);
|
||||||
String filterstr = manager.getProperty(cname + ".filter");
|
setLevel(l != null ? l : Level.ALL);
|
||||||
try {
|
}
|
||||||
if (filterstr != null) {
|
} catch (Exception e) {
|
||||||
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(filterstr);
|
}
|
||||||
setFilter((Filter) clz.getDeclaredConstructor().newInstance());
|
String filterstr = manager.getProperty(cname + ".filter");
|
||||||
}
|
try {
|
||||||
} catch (Exception e) {
|
if (filterstr != null) {
|
||||||
}
|
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(filterstr);
|
||||||
String formatterstr = manager.getProperty(cname + ".formatter");
|
RedkaleClassLoader.putReflectionDeclaredConstructors(clz, clz.getName());
|
||||||
try {
|
setFilter((Filter) clz.getDeclaredConstructor().newInstance());
|
||||||
if (formatterstr != null) {
|
}
|
||||||
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(formatterstr);
|
} catch (Exception e) {
|
||||||
setFormatter((Formatter) clz.getDeclaredConstructor().newInstance());
|
}
|
||||||
}
|
String formatterstr = manager.getProperty(cname + ".formatter");
|
||||||
} catch (Exception e) {
|
try {
|
||||||
}
|
if (formatterstr != null) {
|
||||||
if (getFormatter() == null) setFormatter(new SimpleFormatter());
|
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(formatterstr);
|
||||||
|
RedkaleClassLoader.putReflectionDeclaredConstructors(clz, clz.getName());
|
||||||
String encodingstr = manager.getProperty(cname + ".encoding");
|
setFormatter((Formatter) clz.getDeclaredConstructor().newInstance());
|
||||||
try {
|
}
|
||||||
if (encodingstr != null) setEncoding(encodingstr);
|
} catch (Exception e) {
|
||||||
} catch (Exception e) {
|
}
|
||||||
}
|
if (getFormatter() == null) setFormatter(new SimpleFormatter());
|
||||||
|
|
||||||
String denyregstr = manager.getProperty(cname + ".denyreg");
|
String encodingstr = manager.getProperty(cname + ".encoding");
|
||||||
try {
|
try {
|
||||||
if (denyregstr != null && !denyregstr.trim().isEmpty()) {
|
if (encodingstr != null) setEncoding(encodingstr);
|
||||||
denyreg = Pattern.compile(denyregstr);
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
String denyregstr = manager.getProperty(cname + ".denyreg");
|
||||||
}
|
try {
|
||||||
|
if (denyregstr != null && !denyregstr.trim().isEmpty()) {
|
||||||
@Override
|
denyreg = Pattern.compile(denyregstr);
|
||||||
public void publish(LogRecord log) {
|
}
|
||||||
final String sourceClassName = log.getSourceClassName();
|
} catch (Exception e) {
|
||||||
if (sourceClassName == null || true) {
|
}
|
||||||
StackTraceElement[] ses = new Throwable().getStackTrace();
|
}
|
||||||
for (int i = 2; i < ses.length; i++) {
|
|
||||||
if (ses[i].getClassName().startsWith("java.util.logging")) continue;
|
@Override
|
||||||
log.setSourceClassName('[' + Thread.currentThread().getName() + "] " + ses[i].getClassName());
|
public void publish(LogRecord log) {
|
||||||
log.setSourceMethodName(ses[i].getMethodName());
|
final String sourceClassName = log.getSourceClassName();
|
||||||
break;
|
if (sourceClassName == null || true) {
|
||||||
}
|
StackTraceElement[] ses = new Throwable().getStackTrace();
|
||||||
} else {
|
for (int i = 2; i < ses.length; i++) {
|
||||||
log.setSourceClassName('[' + Thread.currentThread().getName() + "] " + sourceClassName);
|
if (ses[i].getClassName().startsWith("java.util.logging")) continue;
|
||||||
}
|
log.setSourceClassName('[' + Thread.currentThread().getName() + "] " + ses[i].getClassName());
|
||||||
if (denyreg != null && denyreg.matcher(log.getMessage()).find()) return;
|
log.setSourceMethodName(ses[i].getMethodName());
|
||||||
logqueue.offer(log);
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
@Override
|
log.setSourceClassName('[' + Thread.currentThread().getName() + "] " + sourceClassName);
|
||||||
public void flush() {
|
}
|
||||||
try {
|
if (denyreg != null && denyreg.matcher(log.getMessage()).find()) return;
|
||||||
if (logstream != null) logstream.flush();
|
logqueue.offer(log);
|
||||||
} catch (Exception e) {
|
}
|
||||||
ErrorManager err = getErrorManager();
|
|
||||||
if (err != null) err.error(null, e, ErrorManager.FLUSH_FAILURE);
|
@Override
|
||||||
}
|
public void flush() {
|
||||||
}
|
try {
|
||||||
|
if (logstream != null) logstream.flush();
|
||||||
@Override
|
} catch (Exception e) {
|
||||||
public void close() throws SecurityException {
|
ErrorManager err = getErrorManager();
|
||||||
try {
|
if (err != null) err.error(null, e, ErrorManager.FLUSH_FAILURE);
|
||||||
if (logstream != null) logstream.close();
|
}
|
||||||
} catch (Exception e) {
|
}
|
||||||
ErrorManager err = getErrorManager();
|
|
||||||
if (err != null) err.error(null, e, ErrorManager.CLOSE_FAILURE);
|
@Override
|
||||||
}
|
public void close() throws SecurityException {
|
||||||
}
|
try {
|
||||||
|
if (logstream != null) logstream.close();
|
||||||
}
|
} catch (Exception e) {
|
||||||
|
ErrorManager err = getErrorManager();
|
||||||
|
if (err != null) err.error(null, e, ErrorManager.CLOSE_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,399 +1,446 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot;
|
package org.redkale.boot;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.annotation.*;
|
import java.util.stream.Stream;
|
||||||
import static org.redkale.boot.Application.RESNAME_SNCP_ADDR;
|
import javax.annotation.*;
|
||||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
import static org.redkale.boot.Application.RESNAME_SNCP_ADDR;
|
||||||
import org.redkale.cluster.ClusterAgent;
|
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||||
import org.redkale.mq.MessageAgent;
|
import org.redkale.cluster.ClusterAgent;
|
||||||
import org.redkale.net.*;
|
import org.redkale.mq.MessageAgent;
|
||||||
import org.redkale.net.http.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.net.sncp.Sncp;
|
import org.redkale.net.http.*;
|
||||||
import org.redkale.service.*;
|
import org.redkale.net.sncp.Sncp;
|
||||||
import org.redkale.util.AnyValue.DefaultAnyValue;
|
import org.redkale.service.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.AnyValue.DefaultAnyValue;
|
||||||
import org.redkale.watch.*;
|
import org.redkale.util.*;
|
||||||
|
import org.redkale.watch.*;
|
||||||
/**
|
|
||||||
* HTTP Server节点的配置Server
|
/**
|
||||||
*
|
* HTTP Server节点的配置Server
|
||||||
* <p>
|
*
|
||||||
* 详情见: https://redkale.org
|
* <p>
|
||||||
*
|
* 详情见: https://redkale.org
|
||||||
* @author zhangjx
|
*
|
||||||
*/
|
* @author zhangjx
|
||||||
@NodeProtocol("HTTP")
|
*/
|
||||||
public class NodeHttpServer extends NodeServer {
|
@NodeProtocol("HTTP")
|
||||||
|
public class NodeHttpServer extends NodeServer {
|
||||||
protected final boolean rest; //是否加载REST服务, 为true加载rest节点信息并将所有可REST化的Service生成RestServlet
|
|
||||||
|
protected final boolean rest; //是否加载REST服务, 为true加载rest节点信息并将所有可REST化的Service生成RestServlet
|
||||||
protected final HttpServer httpServer;
|
|
||||||
|
protected final HttpServer httpServer;
|
||||||
public NodeHttpServer(Application application, AnyValue serconf) {
|
|
||||||
super(application, createServer(application, serconf));
|
public NodeHttpServer(Application application, AnyValue serconf) {
|
||||||
this.httpServer = (HttpServer) server;
|
super(application, createServer(application, serconf));
|
||||||
this.rest = serconf == null ? false : serconf.getAnyValue("rest") != null;
|
this.httpServer = (HttpServer) server;
|
||||||
}
|
this.rest = serconf == null ? false : serconf.getAnyValue("rest") != null;
|
||||||
|
}
|
||||||
private static Server createServer(Application application, AnyValue serconf) {
|
|
||||||
return new HttpServer(application, application.getStartTime(), application.getResourceFactory().createChild());
|
private static Server createServer(Application application, AnyValue serconf) {
|
||||||
}
|
return new HttpServer(application, application.getStartTime(), application.getResourceFactory().createChild());
|
||||||
|
}
|
||||||
public HttpServer getHttpServer() {
|
|
||||||
return httpServer;
|
public HttpServer getHttpServer() {
|
||||||
}
|
return httpServer;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public InetSocketAddress getSocketAddress() {
|
@Override
|
||||||
return httpServer == null ? null : httpServer.getSocketAddress();
|
public InetSocketAddress getSocketAddress() {
|
||||||
}
|
return httpServer == null ? null : httpServer.getSocketAddress();
|
||||||
|
}
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
@Override
|
||||||
protected ClassFilter<Service> createServiceClassFilter() {
|
@SuppressWarnings("unchecked")
|
||||||
return createClassFilter(this.sncpGroup, null, Service.class, new Class[]{org.redkale.watch.WatchService.class}, Annotation.class, "services", "service");
|
protected ClassFilter<Service> createServiceClassFilter() {
|
||||||
}
|
return createClassFilter(this.sncpGroup, null, Service.class, new Class[]{org.redkale.watch.WatchService.class}, Annotation.class, "services", "service");
|
||||||
|
}
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
@Override
|
||||||
protected ClassFilter<Filter> createFilterClassFilter() {
|
@SuppressWarnings("unchecked")
|
||||||
return createClassFilter(null, null, HttpFilter.class, new Class[]{WatchFilter.class}, null, "filters", "filter");
|
protected ClassFilter<Filter> createFilterClassFilter() {
|
||||||
}
|
return createClassFilter(null, null, HttpFilter.class, new Class[]{WatchFilter.class}, null, "filters", "filter");
|
||||||
|
}
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
@Override
|
||||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
@SuppressWarnings("unchecked")
|
||||||
return createClassFilter(null, WebServlet.class, HttpServlet.class, new Class[]{WatchServlet.class}, null, "servlets", "servlet");
|
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||||
}
|
return createClassFilter(null, WebServlet.class, HttpServlet.class, new Class[]{WatchServlet.class}, null, "servlets", "servlet");
|
||||||
|
}
|
||||||
@Override
|
|
||||||
protected ClassFilter createOtherClassFilter() {
|
@Override
|
||||||
return createClassFilter(null, RestWebSocket.class, WebSocket.class, null, null, "rest", "websocket");
|
protected ClassFilter createOtherClassFilter() {
|
||||||
}
|
return createClassFilter(null, RestWebSocket.class, WebSocket.class, null, null, "rest", "websocket");
|
||||||
|
}
|
||||||
@Override
|
|
||||||
protected void loadService(ClassFilter<? extends Service> serviceFilter, ClassFilter otherFilter) throws Exception {
|
@Override
|
||||||
super.loadService(serviceFilter, otherFilter);
|
protected void loadService(ClassFilter<? extends Service> serviceFilter, ClassFilter otherFilter) throws Exception {
|
||||||
initWebSocketService();
|
super.loadService(serviceFilter, otherFilter);
|
||||||
}
|
initWebSocketService();
|
||||||
|
}
|
||||||
@Override
|
|
||||||
protected void loadFilter(ClassFilter<? extends Filter> filterFilter, ClassFilter otherFilter) throws Exception {
|
@Override
|
||||||
if (httpServer != null) loadHttpFilter(this.serverConf.getAnyValue("filters"), filterFilter);
|
protected void loadFilter(ClassFilter<? extends Filter> filterFilter, ClassFilter otherFilter) throws Exception {
|
||||||
}
|
if (httpServer != null) loadHttpFilter(this.serverConf.getAnyValue("filters"), filterFilter);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
@Override
|
||||||
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter, ClassFilter otherFilter) throws Exception {
|
@SuppressWarnings("unchecked")
|
||||||
if (httpServer != null) loadHttpServlet(servletFilter, otherFilter);
|
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter, ClassFilter otherFilter) throws Exception {
|
||||||
}
|
if (httpServer != null) loadHttpServlet(servletFilter, otherFilter);
|
||||||
|
}
|
||||||
private void initWebSocketService() {
|
|
||||||
final NodeServer self = this;
|
private void initWebSocketService() {
|
||||||
final ResourceFactory regFactory = application.getResourceFactory();
|
final NodeServer self = this;
|
||||||
resourceFactory.register((ResourceFactory rf, final Object src, final String resourceName, Field field, Object attachment) -> { //主要用于单点的服务
|
final ResourceFactory regFactory = application.getResourceFactory();
|
||||||
try {
|
resourceFactory.register((ResourceFactory rf, final Object src, final String resourceName, Field field, Object attachment) -> { //主要用于单点的服务
|
||||||
if (field.getAnnotation(Resource.class) == null) return;
|
try {
|
||||||
if (!(src instanceof WebSocketServlet)) return;
|
if (field.getAnnotation(Resource.class) == null) return;
|
||||||
ResourceFactory.ResourceLoader loader = null;
|
if (!(src instanceof WebSocketServlet)) return;
|
||||||
ResourceFactory sncpResFactory = null;
|
ResourceFactory.ResourceLoader loader = null;
|
||||||
for (NodeServer ns : application.servers) {
|
ResourceFactory sncpResFactory = null;
|
||||||
if (!ns.isSNCP()) continue;
|
for (NodeServer ns : application.servers) {
|
||||||
sncpResFactory = ns.resourceFactory;
|
if (!ns.isSNCP()) continue;
|
||||||
loader = sncpResFactory.findLoader(WebSocketNode.class, field);
|
sncpResFactory = ns.resourceFactory;
|
||||||
if (loader != null) break;
|
loader = sncpResFactory.findLoader(WebSocketNode.class, field);
|
||||||
}
|
if (loader != null) break;
|
||||||
if (loader != null) loader.load(sncpResFactory, src, resourceName, field, attachment);
|
}
|
||||||
synchronized (regFactory) {
|
if (loader != null) loader.load(sncpResFactory, src, resourceName, field, attachment);
|
||||||
Service nodeService = (Service) rf.find(resourceName, WebSocketNode.class);
|
synchronized (regFactory) {
|
||||||
if (sncpResFactory != null && resourceFactory.find(RESNAME_SNCP_ADDR, String.class) == null) {
|
Service nodeService = (Service) rf.find(resourceName, WebSocketNode.class);
|
||||||
resourceFactory.register(RESNAME_SNCP_ADDR, InetSocketAddress.class, sncpResFactory.find(RESNAME_SNCP_ADDR, InetSocketAddress.class));
|
if (sncpResFactory != null && resourceFactory.find(RESNAME_SNCP_ADDR, String.class) == null) {
|
||||||
resourceFactory.register(RESNAME_SNCP_ADDR, SocketAddress.class, sncpResFactory.find(RESNAME_SNCP_ADDR, SocketAddress.class));
|
resourceFactory.register(RESNAME_SNCP_ADDR, InetSocketAddress.class, sncpResFactory.find(RESNAME_SNCP_ADDR, InetSocketAddress.class));
|
||||||
resourceFactory.register(RESNAME_SNCP_ADDR, String.class, sncpResFactory.find(RESNAME_SNCP_ADDR, String.class));
|
resourceFactory.register(RESNAME_SNCP_ADDR, SocketAddress.class, sncpResFactory.find(RESNAME_SNCP_ADDR, SocketAddress.class));
|
||||||
}
|
resourceFactory.register(RESNAME_SNCP_ADDR, String.class, sncpResFactory.find(RESNAME_SNCP_ADDR, String.class));
|
||||||
if (nodeService == null) {
|
}
|
||||||
MessageAgent messageAgent = null;
|
if (nodeService == null) {
|
||||||
try {
|
MessageAgent messageAgent = null;
|
||||||
Field c = WebSocketServlet.class.getDeclaredField("messageAgent");
|
try {
|
||||||
c.setAccessible(true);
|
Field c = WebSocketServlet.class.getDeclaredField("messageAgent");
|
||||||
messageAgent = (MessageAgent) c.get(src);
|
c.setAccessible(true);
|
||||||
} catch (Exception ex) {
|
messageAgent = (MessageAgent) c.get(src);
|
||||||
logger.log(Level.WARNING, "WebSocketServlet getMessageAgent error", ex);
|
} catch (Exception ex) {
|
||||||
}
|
logger.log(Level.WARNING, "WebSocketServlet getMessageAgent error", ex);
|
||||||
nodeService = Sncp.createLocalService(serverClassLoader, resourceName, WebSocketNodeService.class, messageAgent, application.getResourceFactory(), application.getSncpTransportFactory(), (InetSocketAddress) null, (Set<String>) null, (AnyValue) null);
|
}
|
||||||
regFactory.register(resourceName, WebSocketNode.class, nodeService);
|
nodeService = Sncp.createLocalService(serverClassLoader, resourceName, WebSocketNodeService.class, messageAgent, application.getResourceFactory(), application.getSncpTransportFactory(), (InetSocketAddress) null, (Set<String>) null, (AnyValue) null);
|
||||||
}
|
regFactory.register(resourceName, WebSocketNode.class, nodeService);
|
||||||
resourceFactory.inject(nodeService, self);
|
}
|
||||||
field.set(src, nodeService);
|
resourceFactory.inject(nodeService, self);
|
||||||
logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + nodeService);
|
field.set(src, nodeService);
|
||||||
}
|
logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + nodeService);
|
||||||
} catch (Exception e) {
|
}
|
||||||
logger.log(Level.SEVERE, "WebSocketNode inject error", e);
|
} catch (Exception e) {
|
||||||
}
|
logger.log(Level.SEVERE, "WebSocketNode inject error", e);
|
||||||
}, WebSocketNode.class);
|
}
|
||||||
}
|
}, WebSocketNode.class);
|
||||||
|
}
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected void loadHttpFilter(final AnyValue filtersConf, final ClassFilter<? extends Filter> classFilter) throws Exception {
|
@SuppressWarnings("unchecked")
|
||||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
protected void loadHttpFilter(final AnyValue filtersConf, final ClassFilter<? extends Filter> classFilter) throws Exception {
|
||||||
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||||
List<FilterEntry<? extends Filter>> list = new ArrayList(classFilter.getFilterEntrys());
|
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
||||||
for (FilterEntry<? extends Filter> en : list) {
|
List<FilterEntry<? extends Filter>> list = new ArrayList(classFilter.getFilterEntrys());
|
||||||
Class<HttpFilter> clazz = (Class<HttpFilter>) en.getType();
|
for (FilterEntry<? extends Filter> en : list) {
|
||||||
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
Class<HttpFilter> clazz = (Class<HttpFilter>) en.getType();
|
||||||
final HttpFilter filter = clazz.getDeclaredConstructor().newInstance();
|
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
||||||
resourceFactory.inject(filter, this);
|
RedkaleClassLoader.putReflectionDeclaredConstructors(clazz, clazz.getName());
|
||||||
DefaultAnyValue filterConf = (DefaultAnyValue) en.getProperty();
|
final HttpFilter filter = clazz.getDeclaredConstructor().newInstance();
|
||||||
this.httpServer.addHttpFilter(filter, filterConf);
|
resourceFactory.inject(filter, this);
|
||||||
if (sb != null) sb.append(localThreadName).append(" Load ").append(clazz.getName()).append(LINE_SEPARATOR);
|
DefaultAnyValue filterConf = (DefaultAnyValue) en.getProperty();
|
||||||
}
|
this.httpServer.addHttpFilter(filter, filterConf);
|
||||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
if (sb != null) sb.append(localThreadName).append(" Load ").append(clazz.getName()).append(LINE_SEPARATOR);
|
||||||
}
|
}
|
||||||
|
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||||
@SuppressWarnings("unchecked")
|
}
|
||||||
protected void loadHttpServlet(final ClassFilter<? extends Servlet> servletFilter, ClassFilter<? extends WebSocket> webSocketFilter) throws Exception {
|
|
||||||
final AnyValue servletsConf = this.serverConf.getAnyValue("servlets");
|
@SuppressWarnings("unchecked")
|
||||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
protected void loadHttpServlet(final ClassFilter<? extends Servlet> servletFilter, ClassFilter<? extends WebSocket> webSocketFilter) throws Exception {
|
||||||
String prefix0 = servletsConf == null ? "" : servletsConf.getValue("path", "");
|
RedkaleClassLoader.putReflectionPublicClasses(HttpServlet.class.getName());
|
||||||
if (!prefix0.isEmpty() && prefix0.charAt(prefix0.length() - 1) == '/') prefix0 = prefix0.substring(0, prefix0.length() - 1);
|
RedkaleClassLoader.putReflectionPublicClasses(HttpPrepareServlet.class.getName());
|
||||||
if (!prefix0.isEmpty() && prefix0.charAt(0) != '/') prefix0 = '/' + prefix0;
|
RedkaleClassLoader.putReflectionDeclaredConstructors(HttpResourceServlet.class, HttpResourceServlet.class.getName());
|
||||||
final String prefix = prefix0;
|
final AnyValue servletsConf = this.serverConf.getAnyValue("servlets");
|
||||||
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||||
List<FilterEntry<? extends Servlet>> list = new ArrayList(servletFilter.getFilterEntrys());
|
String prefix0 = servletsConf == null ? "" : servletsConf.getValue("path", "");
|
||||||
list.sort((FilterEntry<? extends Servlet> o1, FilterEntry<? extends Servlet> o2) -> { //必须保证WebSocketServlet优先加载, 因为要确保其他的HttpServlet可以注入本地模式的WebSocketNode
|
if (!prefix0.isEmpty() && prefix0.charAt(prefix0.length() - 1) == '/') prefix0 = prefix0.substring(0, prefix0.length() - 1);
|
||||||
boolean ws1 = WebSocketServlet.class.isAssignableFrom(o1.getType());
|
if (!prefix0.isEmpty() && prefix0.charAt(0) != '/') prefix0 = '/' + prefix0;
|
||||||
boolean ws2 = WebSocketServlet.class.isAssignableFrom(o2.getType());
|
final String prefix = prefix0;
|
||||||
if (ws1 == ws2) {
|
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
||||||
Priority p1 = o1.getType().getAnnotation(Priority.class);
|
List<FilterEntry<? extends Servlet>> list = new ArrayList(servletFilter.getFilterEntrys());
|
||||||
Priority p2 = o2.getType().getAnnotation(Priority.class);
|
list.sort((FilterEntry<? extends Servlet> o1, FilterEntry<? extends Servlet> o2) -> { //必须保证WebSocketServlet优先加载, 因为要确保其他的HttpServlet可以注入本地模式的WebSocketNode
|
||||||
int v = (p2 == null ? 0 : p2.value()) - (p1 == null ? 0 : p1.value());
|
boolean ws1 = WebSocketServlet.class.isAssignableFrom(o1.getType());
|
||||||
return v == 0 ? o1.getType().getName().compareTo(o2.getType().getName()) : 0;
|
boolean ws2 = WebSocketServlet.class.isAssignableFrom(o2.getType());
|
||||||
}
|
if (ws1 == ws2) {
|
||||||
return ws1 ? -1 : 1;
|
Priority p1 = o1.getType().getAnnotation(Priority.class);
|
||||||
});
|
Priority p2 = o2.getType().getAnnotation(Priority.class);
|
||||||
final List<AbstractMap.SimpleEntry<String, String[]>> ss = sb == null ? null : new ArrayList<>();
|
int v = (p2 == null ? 0 : p2.value()) - (p1 == null ? 0 : p1.value());
|
||||||
for (FilterEntry<? extends Servlet> en : list) {
|
return v == 0 ? o1.getType().getName().compareTo(o2.getType().getName()) : 0;
|
||||||
Class<HttpServlet> clazz = (Class<HttpServlet>) en.getType();
|
}
|
||||||
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
return ws1 ? -1 : 1;
|
||||||
WebServlet ws = clazz.getAnnotation(WebServlet.class);
|
});
|
||||||
if (ws == null) continue;
|
final long starts = System.currentTimeMillis();
|
||||||
if (ws.value().length == 0) {
|
final List<AbstractMap.SimpleEntry<String, String[]>> ss = sb == null ? null : new ArrayList<>();
|
||||||
logger.log(Level.INFO, "not found @WebServlet.value in " + clazz.getName());
|
for (FilterEntry<? extends Servlet> en : list) {
|
||||||
continue;
|
Class<HttpServlet> clazz = (Class<HttpServlet>) en.getType();
|
||||||
}
|
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
||||||
final HttpServlet servlet = clazz.getDeclaredConstructor().newInstance();
|
if (clazz.getAnnotation(Rest.RestDyn.class) != null) continue; //动态生成的跳过
|
||||||
resourceFactory.inject(servlet, this);
|
WebServlet ws = clazz.getAnnotation(WebServlet.class);
|
||||||
final String[] mappings = ws.value();
|
if (ws == null) continue;
|
||||||
String pref = ws.repair() ? prefix : "";
|
if (ws.value().length == 0) {
|
||||||
DefaultAnyValue servletConf = (DefaultAnyValue) en.getProperty();
|
logger.log(Level.INFO, "not found @WebServlet.value in " + clazz.getName());
|
||||||
this.httpServer.addHttpServlet(servlet, pref, servletConf, mappings);
|
continue;
|
||||||
if (ss != null) {
|
}
|
||||||
for (int i = 0; i < mappings.length; i++) {
|
RedkaleClassLoader.putReflectionDeclaredConstructors(clazz, clazz.getName());
|
||||||
mappings[i] = pref + mappings[i];
|
final HttpServlet servlet = clazz.getDeclaredConstructor().newInstance();
|
||||||
}
|
resourceFactory.inject(servlet, this);
|
||||||
ss.add(new AbstractMap.SimpleEntry<>(clazz.getName(), mappings));
|
final String[] mappings = ws.value();
|
||||||
}
|
String pref = ws.repair() ? prefix : "";
|
||||||
}
|
DefaultAnyValue servletConf = (DefaultAnyValue) en.getProperty();
|
||||||
int max = 0;
|
this.httpServer.addHttpServlet(servlet, pref, servletConf, mappings);
|
||||||
if (ss != null && sb != null) {
|
if (ss != null) {
|
||||||
ss.sort((AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey()));
|
for (int i = 0; i < mappings.length; i++) {
|
||||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
mappings[i] = pref + mappings[i];
|
||||||
if (as.getKey().length() > max) max = as.getKey().length();
|
}
|
||||||
}
|
ss.add(new AbstractMap.SimpleEntry<>("HttpServlet (type=" + clazz.getName() + ")", mappings));
|
||||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
}
|
||||||
sb.append(localThreadName).append(" Load ").append(as.getKey());
|
}
|
||||||
for (int i = 0; i < max - as.getKey().length(); i++) {
|
final List<AbstractMap.SimpleEntry<String, String[]>> rests = sb == null ? null : new ArrayList<>();
|
||||||
sb.append(' ');
|
final List<AbstractMap.SimpleEntry<String, String[]>> webss = sb == null ? null : new ArrayList<>();
|
||||||
}
|
if (rest && serverConf != null) {
|
||||||
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
|
final List<Object> restedObjects = new ArrayList<>();
|
||||||
}
|
for (AnyValue restConf : serverConf.getAnyValues("rest")) {
|
||||||
}
|
loadRestServlet(webSocketFilter, restConf, restedObjects, sb, rests, webss);
|
||||||
if (rest && serverConf != null) {
|
}
|
||||||
final List<Object> restedObjects = new ArrayList<>();
|
}
|
||||||
for (AnyValue restConf : serverConf.getAnyValues("rest")) {
|
int max = 0;
|
||||||
loadRestServlet(webSocketFilter, restConf, restedObjects, sb);
|
if (ss != null && sb != null) {
|
||||||
}
|
int maxTypeLength = 0;
|
||||||
}
|
int maxNameLength = 0;
|
||||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString().trim());
|
if (rests != null) {
|
||||||
}
|
for (AbstractMap.SimpleEntry<String, String[]> en : rests) {
|
||||||
|
int pos = en.getKey().indexOf('#');
|
||||||
@SuppressWarnings("unchecked")
|
if (pos > maxTypeLength) maxTypeLength = pos;
|
||||||
protected void loadRestServlet(final ClassFilter<? extends WebSocket> webSocketFilter, final AnyValue restConf, final List<Object> restedObjects, final StringBuilder sb) throws Exception {
|
int len = en.getKey().length() - pos - 1;
|
||||||
if (!rest) return;
|
if (len > maxNameLength) maxNameLength = len;
|
||||||
if (restConf == null) return; //不存在REST服务
|
}
|
||||||
|
}
|
||||||
final long starts = System.currentTimeMillis();
|
if (webss != null) {
|
||||||
String prefix0 = restConf.getValue("path", "");
|
for (AbstractMap.SimpleEntry<String, String[]> en : webss) {
|
||||||
if (!prefix0.isEmpty() && prefix0.charAt(prefix0.length() - 1) == '/') prefix0 = prefix0.substring(0, prefix0.length() - 1);
|
int pos = en.getKey().indexOf('#');
|
||||||
if (!prefix0.isEmpty() && prefix0.charAt(0) != '/') prefix0 = '/' + prefix0;
|
if (pos > maxTypeLength) maxTypeLength = pos;
|
||||||
|
int len = en.getKey().length() - pos - 1;
|
||||||
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
if (len > maxNameLength) maxNameLength = len;
|
||||||
final List<AbstractMap.SimpleEntry<String, String[]>> ss = sb == null ? null : new ArrayList<>();
|
}
|
||||||
String mqname = restConf.getValue("mq");
|
}
|
||||||
MessageAgent agent0 = null;
|
if (rests != null) {
|
||||||
if (mqname != null) {
|
for (AbstractMap.SimpleEntry<String, String[]> en : rests) {
|
||||||
agent0 = application.getMessageAgent(mqname);
|
StringBuilder sub = new StringBuilder();
|
||||||
if (agent0 == null) throw new RuntimeException("not found " + MessageAgent.class.getSimpleName() + " config for (name=" + mqname + ")");
|
int pos = en.getKey().indexOf('#');
|
||||||
}
|
sub.append("RestDynServlet (type=").append(en.getKey().substring(0, pos));
|
||||||
final MessageAgent messageAgent = agent0;
|
for (int i = 0; i < maxTypeLength - pos; i++) {
|
||||||
if (messageAgent != null) prefix0 = ""; //开启MQ时,prefix字段失效
|
sub.append(' ');
|
||||||
final String prefix = prefix0;
|
}
|
||||||
final boolean autoload = restConf.getBoolValue("autoload", true);
|
sub.append(", name='").append(en.getKey().substring(pos + 1));
|
||||||
{ //加载RestService
|
for (int i = 0; i < maxNameLength - pos; i++) {
|
||||||
String userTypeStr = restConf.getValue("usertype");
|
sub.append(' ');
|
||||||
final Class userType = userTypeStr == null ? null : this.serverClassLoader.loadClass(userTypeStr);
|
}
|
||||||
|
sub.append("')");
|
||||||
final Class baseServletType = this.serverClassLoader.loadClass(restConf.getValue("base", HttpServlet.class.getName()));
|
ss.add(new AbstractMap.SimpleEntry<>(sub.toString(), en.getValue()));
|
||||||
final Set<String> includeValues = new HashSet<>();
|
}
|
||||||
final Set<String> excludeValues = new HashSet<>();
|
}
|
||||||
for (AnyValue item : restConf.getAnyValues("service")) {
|
if (webss != null) {
|
||||||
if (item.getBoolValue("ignore", false)) {
|
for (AbstractMap.SimpleEntry<String, String[]> en : webss) {
|
||||||
excludeValues.add(item.getValue("value", ""));
|
StringBuilder sub = new StringBuilder();
|
||||||
} else {
|
int pos = en.getKey().indexOf('#');
|
||||||
includeValues.add(item.getValue("value", ""));
|
sub.append("RestWebSocket (type=").append(en.getKey().substring(0, pos));
|
||||||
}
|
for (int i = 0; i < maxTypeLength - pos; i++) {
|
||||||
}
|
sub.append(' ');
|
||||||
|
}
|
||||||
final ClassFilter restFilter = ClassFilter.create(null, restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
|
sub.append(", name='").append(en.getKey().substring(pos + 1));
|
||||||
final boolean finest = logger.isLoggable(Level.FINEST);
|
for (int i = 0; i < maxNameLength - pos; i++) {
|
||||||
final CountDownLatch scdl = new CountDownLatch(super.interceptorServices.size());
|
sub.append(' ');
|
||||||
super.interceptorServices.stream().parallel().forEach((service) -> {
|
}
|
||||||
try {
|
sub.append("')");
|
||||||
final Class stype = Sncp.getServiceType(service);
|
ss.add(new AbstractMap.SimpleEntry<>(sub.toString(), en.getValue()));
|
||||||
final String name = Sncp.getResourceName(service);
|
}
|
||||||
RestService rs = (RestService) stype.getAnnotation(RestService.class);
|
}
|
||||||
if (rs == null || rs.ignore()) return;
|
ss.sort((AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey()));
|
||||||
|
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
||||||
final String stypename = stype.getName();
|
if (as.getKey().length() > max) max = as.getKey().length();
|
||||||
if (!autoload && !includeValues.contains(stypename)) return;
|
}
|
||||||
if (!restFilter.accept(stypename)) return;
|
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
||||||
synchronized (restedObjects) {
|
sb.append(localThreadName).append("Load ").append(as.getKey());
|
||||||
if (restedObjects.contains(service)) {
|
for (int i = 0; i < max - as.getKey().length(); i++) {
|
||||||
logger.log(Level.WARNING, stype.getName() + " repeat create rest servlet, so ignore");
|
sb.append(' ');
|
||||||
return;
|
}
|
||||||
}
|
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
|
||||||
restedObjects.add(service); //避免重复创建Rest对象
|
}
|
||||||
}
|
sb.append(localThreadName).append("All HttpServlets load cost ").append(System.currentTimeMillis() - starts).append(" ms").append(LINE_SEPARATOR);
|
||||||
HttpServlet servlet = httpServer.addRestServlet(serverClassLoader, service, userType, baseServletType, prefix);
|
}
|
||||||
if (servlet == null) return; //没有HttpMapping方法的HttpServlet调用Rest.createRestServlet就会返回null
|
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString().trim());
|
||||||
String prefix2 = prefix;
|
}
|
||||||
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
|
|
||||||
if (ws != null && !ws.repair()) prefix2 = "";
|
@SuppressWarnings("unchecked")
|
||||||
resourceFactory.inject(servlet, NodeHttpServer.this);
|
protected void loadRestServlet(final ClassFilter<? extends WebSocket> webSocketFilter, final AnyValue restConf, final List<Object> restedObjects, final StringBuilder sb,
|
||||||
dynServletMap.put(service, servlet);
|
final List<AbstractMap.SimpleEntry<String, String[]>> rests, final List<AbstractMap.SimpleEntry<String, String[]>> webss) throws Exception {
|
||||||
if (messageAgent != null) messageAgent.putService(this, service, servlet);
|
if (!rest) return;
|
||||||
//if (finest) logger.finest(localThreadName + " Create RestServlet(resource.name='" + name + "') = " + servlet);
|
if (restConf == null) return; //不存在REST服务
|
||||||
if (ss != null) {
|
|
||||||
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
|
String prefix0 = restConf.getValue("path", "");
|
||||||
for (int i = 0; i < mappings.length; i++) {
|
if (!prefix0.isEmpty() && prefix0.charAt(prefix0.length() - 1) == '/') prefix0 = prefix0.substring(0, prefix0.length() - 1);
|
||||||
mappings[i] = prefix2 + mappings[i];
|
if (!prefix0.isEmpty() && prefix0.charAt(0) != '/') prefix0 = '/' + prefix0;
|
||||||
}
|
|
||||||
synchronized (ss) {
|
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
||||||
ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName() + "(rest.name='" + name + "')", mappings));
|
String mqname = restConf.getValue("mq");
|
||||||
}
|
MessageAgent agent0 = null;
|
||||||
}
|
if (mqname != null) {
|
||||||
} finally {
|
agent0 = application.getMessageAgent(mqname);
|
||||||
scdl.countDown();
|
if (agent0 == null) throw new RuntimeException("not found " + MessageAgent.class.getSimpleName() + " config for (name=" + mqname + ")");
|
||||||
}
|
}
|
||||||
});
|
final MessageAgent messageAgent = agent0;
|
||||||
scdl.await();
|
if (messageAgent != null) prefix0 = ""; //开启MQ时,prefix字段失效
|
||||||
}
|
final String prefix = prefix0;
|
||||||
if (webSocketFilter != null) { //加载RestWebSocket
|
final boolean autoload = restConf.getBoolValue("autoload", true);
|
||||||
final Set<String> includeValues = new HashSet<>();
|
{ //加载RestService
|
||||||
final Set<String> excludeValues = new HashSet<>();
|
String userTypeStr = restConf.getValue("usertype");
|
||||||
for (AnyValue item : restConf.getAnyValues("websocket")) {
|
final Class userType = userTypeStr == null ? null : this.serverClassLoader.loadClass(userTypeStr);
|
||||||
if (item.getBoolValue("ignore", false)) {
|
|
||||||
excludeValues.add(item.getValue("value", ""));
|
final Class baseServletType = this.serverClassLoader.loadClass(restConf.getValue("base", HttpServlet.class.getName()));
|
||||||
} else {
|
final Set<String> includeValues = new HashSet<>();
|
||||||
includeValues.add(item.getValue("value", ""));
|
final Set<String> excludeValues = new HashSet<>();
|
||||||
}
|
for (AnyValue item : restConf.getAnyValues("service")) {
|
||||||
}
|
if (item.getBoolValue("ignore", false)) {
|
||||||
|
excludeValues.add(item.getValue("value", ""));
|
||||||
final ClassFilter restFilter = ClassFilter.create(null, restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
|
} else {
|
||||||
final boolean finest = logger.isLoggable(Level.FINEST);
|
includeValues.add(item.getValue("value", ""));
|
||||||
|
}
|
||||||
List<FilterEntry<? extends WebSocket>> list = new ArrayList(webSocketFilter.getFilterEntrys());
|
}
|
||||||
for (FilterEntry<? extends WebSocket> en : list) {
|
|
||||||
Class<WebSocket> clazz = (Class<WebSocket>) en.getType();
|
final ClassFilter restFilter = ClassFilter.create(serverClassLoader, null, application.isCompileMode() ? "" : restConf.getValue("includes", ""), application.isCompileMode() ? "" : restConf.getValue("excludes", ""), includeValues, excludeValues);
|
||||||
if (Modifier.isAbstract(clazz.getModifiers())) {
|
final CountDownLatch scdl = new CountDownLatch(super.interceptorServices.size());
|
||||||
logger.log(Level.FINE, clazz.getName() + " cannot abstract on rest websocket, so ignore");
|
Stream<Service> stream = super.interceptorServices.stream();
|
||||||
continue;
|
if (!application.isCompileMode()) stream = stream.parallel(); //不能并行,否则在maven plugin运行环境下ClassLoader不对
|
||||||
}
|
stream.forEach((service) -> {
|
||||||
if (Modifier.isFinal(clazz.getModifiers())) {
|
try {
|
||||||
logger.log(Level.FINE, clazz.getName() + " cannot final on rest websocket, so ignore");
|
final Class stype = Sncp.getServiceType(service);
|
||||||
continue;
|
final String name = Sncp.getResourceName(service);
|
||||||
}
|
RestService rs = (RestService) stype.getAnnotation(RestService.class);
|
||||||
final Class<? extends WebSocket> stype = en.getType();
|
if (rs == null || rs.ignore()) return;
|
||||||
RestWebSocket rs = stype.getAnnotation(RestWebSocket.class);
|
|
||||||
if (rs == null || rs.ignore()) return;
|
final String stypename = stype.getName();
|
||||||
|
if (!autoload && !includeValues.contains(stypename)) return;
|
||||||
final String stypename = stype.getName();
|
if (!restFilter.accept(stypename)) return;
|
||||||
if (!autoload && !includeValues.contains(stypename)) return;
|
synchronized (restedObjects) {
|
||||||
if (!restFilter.accept(stypename)) return;
|
if (restedObjects.contains(service)) {
|
||||||
if (restedObjects.contains(stype)) {
|
logger.log(Level.WARNING, stype.getName() + " repeat create rest servlet, so ignore");
|
||||||
logger.log(Level.WARNING, stype.getName() + " repeat create rest websocket, so ignore");
|
return;
|
||||||
return;
|
}
|
||||||
}
|
restedObjects.add(service); //避免重复创建Rest对象
|
||||||
restedObjects.add(stype); //避免重复创建Rest对象
|
}
|
||||||
WebSocketServlet servlet = httpServer.addRestWebSocketServlet(serverClassLoader, stype, messageAgent, prefix, en.getProperty());
|
HttpServlet servlet = httpServer.addRestServlet(serverClassLoader, service, userType, baseServletType, prefix);
|
||||||
if (servlet == null) return; //没有RestOnMessage方法的HttpServlet调用Rest.createRestWebSocketServlet就会返回null
|
if (servlet == null) return; //没有HttpMapping方法的HttpServlet调用Rest.createRestServlet就会返回null
|
||||||
String prefix2 = prefix;
|
String prefix2 = prefix;
|
||||||
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
|
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
|
||||||
if (ws != null && !ws.repair()) prefix2 = "";
|
if (ws != null && !ws.repair()) prefix2 = "";
|
||||||
resourceFactory.inject(servlet, NodeHttpServer.this);
|
resourceFactory.inject(servlet, NodeHttpServer.this);
|
||||||
if (finest) logger.finest(localThreadName + " " + stype.getName() + " create a RestWebSocketServlet");
|
dynServletMap.put(service, servlet);
|
||||||
if (ss != null) {
|
if (messageAgent != null) messageAgent.putService(this, service, servlet);
|
||||||
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
|
//if (finest) logger.finest(localThreadName + " Create RestServlet(resource.name='" + name + "') = " + servlet);
|
||||||
for (int i = 0; i < mappings.length; i++) {
|
if (rests != null) {
|
||||||
mappings[i] = prefix2 + mappings[i];
|
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
|
||||||
}
|
for (int i = 0; i < mappings.length; i++) {
|
||||||
ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName(), mappings));
|
mappings[i] = prefix2 + mappings[i];
|
||||||
}
|
}
|
||||||
}
|
synchronized (rests) {
|
||||||
}
|
rests.add(new AbstractMap.SimpleEntry<>(Sncp.getServiceType(service).getName() + "#" + name, mappings));
|
||||||
if (messageAgent != null) this.messageAgents.put(messageAgent.getName(), messageAgent);
|
}
|
||||||
//输出信息
|
}
|
||||||
if (ss != null && !ss.isEmpty() && sb != null) {
|
} finally {
|
||||||
ss.sort((AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey()));
|
scdl.countDown();
|
||||||
int max = 0;
|
}
|
||||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
});
|
||||||
if (as.getKey().length() > max) max = as.getKey().length();
|
scdl.await();
|
||||||
}
|
}
|
||||||
for (AbstractMap.SimpleEntry<String, String[]> as : ss) {
|
if (webSocketFilter != null) { //加载RestWebSocket
|
||||||
sb.append(localThreadName).append(" Load ").append(as.getKey());
|
final Set<String> includeValues = new HashSet<>();
|
||||||
for (int i = 0; i < max - as.getKey().length(); i++) {
|
final Set<String> excludeValues = new HashSet<>();
|
||||||
sb.append(' ');
|
for (AnyValue item : restConf.getAnyValues("websocket")) {
|
||||||
}
|
if (item.getBoolValue("ignore", false)) {
|
||||||
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
|
excludeValues.add(item.getValue("value", ""));
|
||||||
}
|
} else {
|
||||||
sb.append(localThreadName).append(" All HttpServlets load cost ").append(System.currentTimeMillis() - starts).append(" ms").append(LINE_SEPARATOR);
|
includeValues.add(item.getValue("value", ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
final ClassFilter restFilter = ClassFilter.create(serverClassLoader, null, application.isCompileMode() ? "" : restConf.getValue("includes", ""), application.isCompileMode() ? "" : restConf.getValue("excludes", ""), includeValues, excludeValues);
|
||||||
@Override //loadServlet执行之后调用
|
final boolean finest = logger.isLoggable(Level.FINEST);
|
||||||
protected void postLoadServlets() {
|
|
||||||
final ClusterAgent cluster = application.clusterAgent;
|
List<FilterEntry<? extends WebSocket>> list = new ArrayList(webSocketFilter.getFilterEntrys());
|
||||||
if (cluster != null) {
|
for (FilterEntry<? extends WebSocket> en : list) {
|
||||||
NodeProtocol pros = getClass().getAnnotation(NodeProtocol.class);
|
Class<WebSocket> clazz = (Class<WebSocket>) en.getType();
|
||||||
String protocol = pros.value().toUpperCase();
|
if (Modifier.isAbstract(clazz.getModifiers())) {
|
||||||
if (!cluster.containsProtocol(protocol)) return;
|
logger.log(Level.FINE, clazz.getName() + " cannot abstract on rest websocket, so ignore");
|
||||||
if (!cluster.containsPort(server.getSocketAddress().getPort())) return;
|
continue;
|
||||||
cluster.register(this, protocol, dynServletMap.keySet(), new HashSet<>());
|
}
|
||||||
}
|
if (Modifier.isFinal(clazz.getModifiers())) {
|
||||||
}
|
logger.log(Level.FINE, clazz.getName() + " cannot final on rest websocket, so ignore");
|
||||||
|
continue;
|
||||||
@Override
|
}
|
||||||
protected void afterClusterDeregisterOnPreDestroyServices(ClusterAgent cluster, String protocol) {
|
final Class<? extends WebSocket> stype = en.getType();
|
||||||
cluster.deregister(this, protocol, dynServletMap.keySet(), new HashSet<>());
|
if (stype.getAnnotation(Rest.RestDyn.class) != null) continue;
|
||||||
}
|
RestWebSocket rs = stype.getAnnotation(RestWebSocket.class);
|
||||||
}
|
if (rs == null || rs.ignore()) continue;
|
||||||
|
|
||||||
|
final String stypename = stype.getName();
|
||||||
|
if (!autoload && !includeValues.contains(stypename)) continue;
|
||||||
|
if (!restFilter.accept(stypename)) continue;
|
||||||
|
if (restedObjects.contains(stype)) {
|
||||||
|
logger.log(Level.WARNING, stype.getName() + " repeat create rest websocket, so ignore");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
restedObjects.add(stype); //避免重复创建Rest对象
|
||||||
|
WebSocketServlet servlet = httpServer.addRestWebSocketServlet(serverClassLoader, stype, messageAgent, prefix, en.getProperty());
|
||||||
|
if (servlet == null) continue; //没有RestOnMessage方法的HttpServlet调用Rest.createRestWebSocketServlet就会返回null
|
||||||
|
String prefix2 = prefix;
|
||||||
|
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
|
||||||
|
if (ws != null && !ws.repair()) prefix2 = "";
|
||||||
|
resourceFactory.inject(servlet, NodeHttpServer.this);
|
||||||
|
if (finest) logger.finest(localThreadName + " " + stype.getName() + " create a RestWebSocketServlet");
|
||||||
|
if (webss != null) {
|
||||||
|
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
|
||||||
|
for (int i = 0; i < mappings.length; i++) {
|
||||||
|
mappings[i] = prefix2 + mappings[i];
|
||||||
|
}
|
||||||
|
synchronized (webss) {
|
||||||
|
webss.add(new AbstractMap.SimpleEntry<>(stype.getName() + "#" + rs.name(), mappings));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (messageAgent != null) this.messageAgents.put(messageAgent.getName(), messageAgent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override //loadServlet执行之后调用
|
||||||
|
protected void postLoadServlets() {
|
||||||
|
final ClusterAgent cluster = application.clusterAgent;
|
||||||
|
if (!application.isCompileMode() && cluster != null) {
|
||||||
|
NodeProtocol pros = getClass().getAnnotation(NodeProtocol.class);
|
||||||
|
String protocol = pros.value().toUpperCase();
|
||||||
|
if (!cluster.containsProtocol(protocol)) return;
|
||||||
|
if (!cluster.containsPort(server.getSocketAddress().getPort())) return;
|
||||||
|
cluster.register(this, protocol, dynServletMap.keySet(), new HashSet<>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void afterClusterDeregisterOnPreDestroyServices(ClusterAgent cluster, String protocol) {
|
||||||
|
cluster.deregister(this, protocol, dynServletMap.keySet(), new HashSet<>());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,38 +1,38 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot;
|
package org.redkale.boot;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NodeServer的拦截类
|
* NodeServer的拦截类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class NodeInterceptor {
|
public class NodeInterceptor {
|
||||||
|
|
||||||
/** *
|
/** *
|
||||||
* Server.start之前调用 <br>
|
* Server.start之前调用 <br>
|
||||||
* NodeServer.start的部署是先执行NodeInterceptor.preStart,再执行 Server.start 方法
|
* NodeServer.start的部署是先执行NodeInterceptor.preStart,再执行 Server.start 方法
|
||||||
*
|
*
|
||||||
* @param server NodeServer
|
* @param server NodeServer
|
||||||
*/
|
*/
|
||||||
public void preStart(NodeServer server) {
|
public void preStart(NodeServer server) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server.shutdown之前调用 <br>
|
* Server.shutdown之前调用 <br>
|
||||||
* NodeServer.shutdown的部署是先执行NodeInterceptor.preShutdown,再执行 Server.sshutdown 方法
|
* NodeServer.shutdown的部署是先执行NodeInterceptor.preShutdown,再执行 Server.sshutdown 方法
|
||||||
*
|
*
|
||||||
* @param server NodeServer
|
* @param server NodeServer
|
||||||
*/
|
*/
|
||||||
public void preShutdown(NodeServer server) {
|
public void preShutdown(NodeServer server) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot;
|
package org.redkale.boot;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据application.xml中的server节点中的protocol值来适配Server的加载逻辑, 只能注解在NodeServer子类上
|
* 根据application.xml中的server节点中的protocol值来适配Server的加载逻辑, 只能注解在NodeServer子类上
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.TYPE})
|
@Target({ElementType.TYPE})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Documented
|
@Documented
|
||||||
public @interface NodeProtocol {
|
public @interface NodeProtocol {
|
||||||
|
|
||||||
String value();
|
String value();
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,122 +1,125 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot;
|
package org.redkale.boot;
|
||||||
|
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||||
import org.redkale.mq.MessageAgent;
|
import org.redkale.mq.MessageAgent;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.net.sncp.*;
|
import org.redkale.net.sncp.*;
|
||||||
import org.redkale.service.*;
|
import org.redkale.service.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
import org.redkale.util.AnyValue.DefaultAnyValue;
|
import org.redkale.util.AnyValue.DefaultAnyValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SNCP Server节点的配置Server
|
* SNCP Server节点的配置Server
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@NodeProtocol("SNCP")
|
@NodeProtocol("SNCP")
|
||||||
public class NodeSncpServer extends NodeServer {
|
public class NodeSncpServer extends NodeServer {
|
||||||
|
|
||||||
protected final SncpServer sncpServer;
|
protected final SncpServer sncpServer;
|
||||||
|
|
||||||
private NodeSncpServer(Application application, AnyValue serconf) {
|
private NodeSncpServer(Application application, AnyValue serconf) {
|
||||||
super(application, createServer(application, serconf));
|
super(application, createServer(application, serconf));
|
||||||
this.sncpServer = (SncpServer) this.server;
|
this.sncpServer = (SncpServer) this.server;
|
||||||
this.consumer = sncpServer == null || application.singletonrun ? null : (agent, x) -> {//singleton模式下不生成SncpServlet
|
this.consumer = sncpServer == null || application.isSingletonMode() ? null : (agent, x) -> {//singleton模式下不生成SncpServlet
|
||||||
if (x.getClass().getAnnotation(Local.class) != null) return;
|
if (x.getClass().getAnnotation(Local.class) != null) return; //本地模式的Service不生成SncpServlet
|
||||||
SncpDynServlet servlet = sncpServer.addSncpServlet(x);
|
SncpDynServlet servlet = sncpServer.addSncpServlet(x);
|
||||||
dynServletMap.put(x, servlet);
|
dynServletMap.put(x, servlet);
|
||||||
if (agent != null) agent.putService(this, x, servlet);
|
if (agent != null) agent.putService(this, x, servlet);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NodeServer createNodeServer(Application application, AnyValue serconf) {
|
public static NodeServer createNodeServer(Application application, AnyValue serconf) {
|
||||||
return new NodeSncpServer(application, serconf);
|
return new NodeSncpServer(application, serconf);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Server createServer(Application application, AnyValue serconf) {
|
private static Server createServer(Application application, AnyValue serconf) {
|
||||||
return new SncpServer(application, application.getStartTime(), serconf, application.getResourceFactory().createChild());
|
return new SncpServer(application, application.getStartTime(), serconf, application.getResourceFactory().createChild());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InetSocketAddress getSocketAddress() {
|
public InetSocketAddress getSocketAddress() {
|
||||||
return sncpServer == null ? null : sncpServer.getSocketAddress();
|
return sncpServer == null ? null : sncpServer.getSocketAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void consumerAccept(MessageAgent messageAgent, Service service) {
|
public void consumerAccept(MessageAgent messageAgent, Service service) {
|
||||||
if (this.consumer != null) this.consumer.accept(messageAgent, service);
|
if (this.consumer != null) this.consumer.accept(messageAgent, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(AnyValue config) throws Exception {
|
public void init(AnyValue config) throws Exception {
|
||||||
super.init(config);
|
super.init(config);
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
if (sncpServer == null) return; //调试时server才可能为null
|
if (sncpServer == null) return; //调试时server才可能为null
|
||||||
final StringBuilder sb = logger.isLoggable(Level.FINE) ? new StringBuilder() : null;
|
final StringBuilder sb = logger.isLoggable(Level.FINE) ? new StringBuilder() : null;
|
||||||
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
||||||
List<SncpServlet> servlets = sncpServer.getSncpServlets();
|
List<SncpServlet> servlets = sncpServer.getSncpServlets();
|
||||||
Collections.sort(servlets);
|
Collections.sort(servlets);
|
||||||
for (SncpServlet en : servlets) {
|
for (SncpServlet en : servlets) {
|
||||||
if (sb != null) sb.append(localThreadName).append(" Load ").append(en).append(LINE_SEPARATOR);
|
if (sb != null) sb.append(localThreadName).append(" Load ").append(en).append(LINE_SEPARATOR);
|
||||||
}
|
}
|
||||||
if (sb != null && sb.length() > 0) logger.log(Level.FINE, sb.toString());
|
if (sb != null && sb.length() > 0) logger.log(Level.FINE, sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSNCP() {
|
public boolean isSNCP() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SncpServer getSncpServer() {
|
public SncpServer getSncpServer() {
|
||||||
return sncpServer;
|
return sncpServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadFilter(ClassFilter<? extends Filter> filterFilter, ClassFilter otherFilter) throws Exception {
|
protected void loadFilter(ClassFilter<? extends Filter> filterFilter, ClassFilter otherFilter) throws Exception {
|
||||||
if (sncpServer != null) loadSncpFilter(this.serverConf.getAnyValue("fliters"), filterFilter);
|
if (sncpServer != null) loadSncpFilter(this.serverConf.getAnyValue("fliters"), filterFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected void loadSncpFilter(final AnyValue servletsConf, final ClassFilter<? extends Filter> classFilter) throws Exception {
|
protected void loadSncpFilter(final AnyValue servletsConf, final ClassFilter<? extends Filter> classFilter) throws Exception {
|
||||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||||
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
final String localThreadName = "[" + Thread.currentThread().getName() + "] ";
|
||||||
List<FilterEntry<? extends Filter>> list = new ArrayList(classFilter.getFilterEntrys());
|
List<FilterEntry<? extends Filter>> list = new ArrayList(classFilter.getFilterEntrys());
|
||||||
for (FilterEntry<? extends Filter> en : list) {
|
for (FilterEntry<? extends Filter> en : list) {
|
||||||
Class<SncpFilter> clazz = (Class<SncpFilter>) en.getType();
|
Class<SncpFilter> clazz = (Class<SncpFilter>) en.getType();
|
||||||
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
||||||
final SncpFilter filter = clazz.getDeclaredConstructor().newInstance();
|
RedkaleClassLoader.putReflectionDeclaredConstructors(clazz, clazz.getName());
|
||||||
resourceFactory.inject(filter, this);
|
final SncpFilter filter = clazz.getDeclaredConstructor().newInstance();
|
||||||
DefaultAnyValue filterConf = (DefaultAnyValue) en.getProperty();
|
resourceFactory.inject(filter, this);
|
||||||
this.sncpServer.addSncpFilter(filter, filterConf);
|
DefaultAnyValue filterConf = (DefaultAnyValue) en.getProperty();
|
||||||
if (sb != null) sb.append(localThreadName).append(" Load ").append(clazz.getName()).append(LINE_SEPARATOR);
|
this.sncpServer.addSncpFilter(filter, filterConf);
|
||||||
}
|
if (sb != null) sb.append(localThreadName).append(" Load ").append(clazz.getName()).append(LINE_SEPARATOR);
|
||||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
}
|
||||||
}
|
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||||
|
}
|
||||||
@Override
|
|
||||||
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter, ClassFilter otherFilter) throws Exception {
|
@Override
|
||||||
}
|
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter, ClassFilter otherFilter) throws Exception {
|
||||||
|
RedkaleClassLoader.putReflectionPublicClasses(SncpServlet.class.getName());
|
||||||
@Override
|
RedkaleClassLoader.putReflectionPublicClasses(SncpDynServlet.class.getName());
|
||||||
@SuppressWarnings("unchecked")
|
}
|
||||||
protected ClassFilter<Filter> createFilterClassFilter() {
|
|
||||||
return createClassFilter(null, null, SncpFilter.class, new Class[]{org.redkale.watch.WatchFilter.class}, null, "filters", "filter");
|
@Override
|
||||||
}
|
@SuppressWarnings("unchecked")
|
||||||
|
protected ClassFilter<Filter> createFilterClassFilter() {
|
||||||
@Override
|
return createClassFilter(null, null, SncpFilter.class, new Class[]{org.redkale.watch.WatchFilter.class}, null, "filters", "filter");
|
||||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
}
|
||||||
return null;
|
|
||||||
}
|
@Override
|
||||||
|
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,53 +1,53 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot;
|
package org.redkale.boot;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.net.http.*;
|
import org.redkale.net.http.*;
|
||||||
import org.redkale.service.Service;
|
import org.redkale.service.Service;
|
||||||
import org.redkale.util.AnyValue;
|
import org.redkale.util.AnyValue;
|
||||||
import org.redkale.watch.*;
|
import org.redkale.watch.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@NodeProtocol("WATCH")
|
@NodeProtocol("WATCH")
|
||||||
public class NodeWatchServer extends NodeHttpServer {
|
public class NodeWatchServer extends NodeHttpServer {
|
||||||
|
|
||||||
public NodeWatchServer(Application application, AnyValue serconf) {
|
public NodeWatchServer(Application application, AnyValue serconf) {
|
||||||
super(application, serconf);
|
super(application, serconf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected ClassFilter<Service> createServiceClassFilter() {
|
protected ClassFilter<Service> createServiceClassFilter() {
|
||||||
return createClassFilter(this.sncpGroup, null, WatchService.class, null, Annotation.class, "services", "service");
|
return createClassFilter(this.sncpGroup, null, WatchService.class, null, Annotation.class, "services", "service");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected ClassFilter<Filter> createFilterClassFilter() {
|
protected ClassFilter<Filter> createFilterClassFilter() {
|
||||||
return createClassFilter(null, null, WatchFilter.class, null, null, "filters", "filter");
|
return createClassFilter(null, null, WatchFilter.class, null, null, "filters", "filter");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||||
return createClassFilter(null, WebServlet.class, WatchServlet.class, null, null, "servlets", "servlet");
|
return createClassFilter(null, WebServlet.class, WatchServlet.class, null, null, "servlets", "servlet");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ClassFilter createOtherClassFilter() {
|
protected ClassFilter createOtherClassFilter() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isWATCH() {
|
public boolean isWATCH() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
86
src/main/java/org/redkale/boot/PrepareCompiler.java
Normal file
86
src/main/java/org/redkale/boot/PrepareCompiler.java
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* 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.lang.reflect.Modifier;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||||
|
import org.redkale.convert.Decodeable;
|
||||||
|
import org.redkale.convert.bson.BsonFactory;
|
||||||
|
import org.redkale.convert.json.*;
|
||||||
|
import org.redkale.source.*;
|
||||||
|
import org.redkale.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行一次Application.run提前获取所有动态类
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @since 2.5.0
|
||||||
|
*/
|
||||||
|
public class PrepareCompiler {
|
||||||
|
|
||||||
|
// public static void main(String[] args) throws Exception {
|
||||||
|
// new PrepareCompiler().run();
|
||||||
|
// }
|
||||||
|
public Application run() throws Exception {
|
||||||
|
final Application application = new Application(false, true, Application.loadAppConfig());
|
||||||
|
application.init();
|
||||||
|
for (ApplicationListener listener : application.listeners) {
|
||||||
|
listener.preStart(application);
|
||||||
|
}
|
||||||
|
for (ApplicationListener listener : application.listeners) {
|
||||||
|
listener.preCompile(application);
|
||||||
|
}
|
||||||
|
application.start();
|
||||||
|
final boolean hasSncp = application.getNodeServers().stream().filter(v -> v instanceof NodeSncpServer).findFirst().isPresent();
|
||||||
|
final String[] exlibs = (application.excludelibs != null ? (application.excludelibs + ";") : "").split(";");
|
||||||
|
|
||||||
|
final ClassFilter<?> entityFilter = new ClassFilter(application.getClassLoader(), Entity.class, Object.class, (Class[]) null);
|
||||||
|
final ClassFilter<?> beanFilter = new ClassFilter(application.getClassLoader(), Bean.class, Object.class, (Class[]) null);
|
||||||
|
final ClassFilter<?> filterFilter = new ClassFilter(application.getClassLoader(), null, FilterBean.class, (Class[]) null);
|
||||||
|
|
||||||
|
ClassFilter.Loader.load(application.getHome(), application.getClassLoader(), exlibs, entityFilter, beanFilter, filterFilter);
|
||||||
|
|
||||||
|
for (FilterEntry en : entityFilter.getFilterEntrys()) {
|
||||||
|
Class clz = en.getType();
|
||||||
|
if (clz.isInterface() || Modifier.isAbstract(clz.getModifiers())) continue;
|
||||||
|
try {
|
||||||
|
application.dataSources.forEach(source -> source.compile(clz));
|
||||||
|
JsonFactory.root().loadEncoder(clz);
|
||||||
|
if (hasSncp) BsonFactory.root().loadEncoder(clz);
|
||||||
|
Decodeable decoder = JsonFactory.root().loadDecoder(clz);
|
||||||
|
if (hasSncp) BsonFactory.root().loadDecoder(clz);
|
||||||
|
decoder.convertFrom(new JsonReader("{}"));
|
||||||
|
} catch (Exception e) { //JsonFactory.loadDecoder可能会失败,因为class可能包含抽象类字段,如ColumnValue.value字段
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (FilterEntry en : beanFilter.getFilterEntrys()) {
|
||||||
|
Class clz = en.getType();
|
||||||
|
if (clz.isInterface() || Modifier.isAbstract(clz.getModifiers())) continue;
|
||||||
|
try {
|
||||||
|
JsonFactory.root().loadEncoder(clz);
|
||||||
|
if (hasSncp) BsonFactory.root().loadEncoder(clz);
|
||||||
|
Decodeable decoder = JsonFactory.root().loadDecoder(clz);
|
||||||
|
if (hasSncp) BsonFactory.root().loadDecoder(clz);
|
||||||
|
decoder.convertFrom(new JsonReader("{}"));
|
||||||
|
} catch (Exception e) { //JsonFactory.loadDecoder可能会失败,因为class可能包含抽象类字段,如ColumnValue.value字段
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (FilterEntry en : filterFilter.getFilterEntrys()) {
|
||||||
|
Class clz = en.getType();
|
||||||
|
if (clz.isInterface() || Modifier.isAbstract(clz.getModifiers())) continue;
|
||||||
|
try {
|
||||||
|
FilterNodeBean.load(clz);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (ApplicationListener listener : application.listeners) {
|
||||||
|
listener.postCompile(application);
|
||||||
|
}
|
||||||
|
application.shutdown();
|
||||||
|
return application;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,110 +1,110 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"><title>接口文档(apidoc生成)</title>
|
<meta charset="UTF-8"><title>接口文档(apidoc生成)</title>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body {text-align: center;margin:auto;}
|
body {text-align: center;margin:auto;}
|
||||||
a{text-decoration: none;}
|
a{text-decoration: none;}
|
||||||
.table {margin: auto;border-collapse: collapse;border-spacing: 0;display: block;width: 100%;overflow: auto;word-break: normal;word-break: keep-all;}
|
.table {margin: auto;border-collapse: collapse;border-spacing: 0;display: block;width: 100%;overflow: auto;word-break: normal;word-break: keep-all;}
|
||||||
.table td,.table th{padding: 0.2rem 0.8rem 0.2rem 0.8rem;border: 1px solid #aaa;}
|
.table td,.table th{padding: 0.2rem 0.8rem 0.2rem 0.8rem;border: 1px solid #aaa;}
|
||||||
.table td {text-align: left;}
|
.table td {text-align: left;}
|
||||||
.s {font-size: 0.8rem; vertical-align: middle;}
|
.s {font-size: 0.8rem; vertical-align: middle;}
|
||||||
.subtable {border-spacing: 0;border: 0;margin:0;}
|
.subtable {border-spacing: 0;border: 0;margin:0;}
|
||||||
.subtable td{border: 0;padding: 0 0 0 10px;}
|
.subtable td{border: 0;padding: 0 0 0 10px;}
|
||||||
.typetable {border-spacing: 0;border: 0;margin:0;}
|
.typetable {border-spacing: 0;border: 0;margin:0;}
|
||||||
.typetable td{border: 0;padding: 2px 20px 2px 10px;}
|
.typetable td{border: 0;padding: 2px 20px 2px 10px;}
|
||||||
.typetable .l{border-bottom: 1px solid red;}
|
.typetable .l{border-bottom: 1px solid red;}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var createhtml = function (jsoncontent) {
|
var createhtml = function (jsoncontent) {
|
||||||
var classmap = jsoncontent.types;
|
var classmap = jsoncontent.types;
|
||||||
var html = [];
|
var html = [];
|
||||||
html.push('<div style="width:' + Math.floor(window.screen.width * 0.9) + 'px;margin:0 auto;text-align: center;">');
|
html.push('<div style="width:' + Math.floor(window.screen.width * 0.9) + 'px;margin:0 auto;text-align: center;">');
|
||||||
html.push('<br/><br/><table class="table" align="center">');
|
html.push('<br/><br/><table class="table" align="center">');
|
||||||
for (var i = 0; i < jsoncontent.servers.length; i++) {
|
for (var i = 0; i < jsoncontent.servers.length; i++) {
|
||||||
var servlets = jsoncontent.servers[i].servlets;
|
var servlets = jsoncontent.servers[i].servlets;
|
||||||
if (servlets.length && (servlets[0].comment || "").indexOf("【") === 0) {
|
if (servlets.length && (servlets[0].comment || "").indexOf("【") === 0) {
|
||||||
servlets.sort(function (a, b) {
|
servlets.sort(function (a, b) {
|
||||||
return a.comment > b.comment ? -1 : (a.comment == b.comment ? 0 : 1);
|
return a.comment > b.comment ? -1 : (a.comment == b.comment ? 0 : 1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for (var j = 0; j < servlets.length; j++) {
|
for (var j = 0; j < servlets.length; j++) {
|
||||||
var servlet = servlets[j];
|
var servlet = servlets[j];
|
||||||
if (html.length > 2) html.push(' <tr><th colspan="5" style="border-bottom:0;"> </th></tr>');
|
if (html.length > 2) html.push(' <tr><th colspan="5" style="border-bottom:0;"> </th></tr>');
|
||||||
html.push(' <tr><th colspan="5" style="border-top:' + ((html.length > 2) ? 0 : 1) + ';">' + (servlet.comment || '未知模块') + '</th></tr>');
|
html.push(' <tr><th colspan="5" style="border-top:' + ((html.length > 2) ? 0 : 1) + ';">' + (servlet.comment || '未知模块') + '</th></tr>');
|
||||||
html.push(' <tr><th>请求URL</th><th>描 述</th><th>鉴 权</th><th>参 数 <span style="font-size:12px;">(粗体: 必填项; 红色: Header; 蓝色: Cookie)</span></th><th>输 出</th></tr>');
|
html.push(' <tr><th>请求URL</th><th>描 述</th><th>鉴 权</th><th>参 数 <span style="font-size:12px;">(粗体: 必填项; 红色: Header; 蓝色: Cookie)</span></th><th>输 出</th></tr>');
|
||||||
for (var k = 0; k < servlet.mappings.length; k++) {
|
for (var k = 0; k < servlet.mappings.length; k++) {
|
||||||
var action = servlet.mappings[k];
|
var action = servlet.mappings[k];
|
||||||
html.push(' <tr>');
|
html.push(' <tr>');
|
||||||
html.push('<td style="color:#ff00ff;">' + action.url + '</td>');
|
html.push('<td style="color:#ff00ff;">' + action.url + '</td>');
|
||||||
html.push('<td>' + action.comment + '</td>');
|
html.push('<td>' + action.comment + '</td>');
|
||||||
html.push('<td class="s" style="width:80px;">模块ID: ' + servlet.moduleid + '<br/>操作ID: ' + action.actionid + '<br/>需鉴权: ' + (action.auth ? '<font style="font-weight:bold;color:green;">true</font>' : '<font color=red>false</font>') + '</td>');
|
html.push('<td class="s" style="width:80px;">模块ID: ' + servlet.moduleid + '<br/>操作ID: ' + action.actionid + '<br/>需鉴权: ' + (action.auth ? '<font style="font-weight:bold;color:green;">true</font>' : '<font color=red>false</font>') + '</td>');
|
||||||
var paramshtml = [];
|
var paramshtml = [];
|
||||||
paramshtml.push('<table class="subtable">');
|
paramshtml.push('<table class="subtable">');
|
||||||
for (var p = 0; p < action.params.length; p++) {
|
for (var p = 0; p < action.params.length; p++) {
|
||||||
var param = action.params[p];
|
var param = action.params[p];
|
||||||
var t = param.type.substring(param.type.lastIndexOf('.') + 1);
|
var t = param.type.substring(param.type.lastIndexOf('.') + 1);
|
||||||
if (classmap[param.type.replace('[]', '')]) {
|
if (classmap[param.type.replace('[]', '')]) {
|
||||||
t = '<a href="#' + param.type.replace('[]', '') + '">' + t + '</a>';
|
t = '<a href="#' + param.type.replace('[]', '') + '">' + t + '</a>';
|
||||||
}
|
}
|
||||||
if (param.name == '&') {
|
if (param.name == '&') {
|
||||||
paramshtml.push('<tr><td style="font-size:12px;">内置 </td><td> ' + t + '</td><td> 当前用户</td></tr>');
|
paramshtml.push('<tr><td style="font-size:12px;">内置 </td><td> ' + t + '</td><td> 当前用户</td></tr>');
|
||||||
} else {
|
} else {
|
||||||
var w = param.required ? "font-weight:bold;" : "";
|
var w = param.required ? "font-weight:bold;" : "";
|
||||||
var c = ' style="' + w + '"';
|
var c = ' style="' + w + '"';
|
||||||
if (param.src == "HEADER") c = ' style="color:red;' + w + '"';
|
if (param.style == "HEADER") c = ' style="color:red;' + w + '"';
|
||||||
if (param.src == "COOKIE") c = ' style="color:blue;' + w + '"';
|
if (param.style == "COOKIE") c = ' style="color:blue;' + w + '"';
|
||||||
paramshtml.push('<tr><td ' + c + '> ' + param.name + ' </td><td> ' + t + '</td><td> ' + param.comment + '</td></tr>');
|
paramshtml.push('<tr><td ' + c + '> ' + param.name + ' </td><td> ' + t + '</td><td> ' + param.comment + '</td></tr>');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
paramshtml.push('</table>');
|
paramshtml.push('</table>');
|
||||||
html.push('<td class="s" style="padding:0 5px;">' + paramshtml.join('') + '</td>');
|
html.push('<td class="s" style="padding:0 5px;">' + paramshtml.join('') + '</td>');
|
||||||
var rs = [];
|
var rs = [];
|
||||||
rs.push(action.result.replace(/</g, "<").replace(/>/g, ">").replace(/([a-zA-Z0-9_\$]+\.)+/g, ""));
|
rs.push(action.result.replace(/</g, "<").replace(/>/g, ">").replace(/([a-zA-Z0-9_\$]+\.)+/g, ""));
|
||||||
var results = action.results || [];
|
var results = action.results || [];
|
||||||
for (var r = 0; r < results.length; r++) {
|
for (var r = 0; r < results.length; r++) {
|
||||||
rs.push('<a href="#' + results[r].replace('[]', '') + '">' + results[r].replace(/([a-zA-Z0-9_\$]+\.)+/g, "") + '</a>');
|
rs.push('<a href="#' + results[r].replace('[]', '') + '">' + results[r].replace(/([a-zA-Z0-9_\$]+\.)+/g, "") + '</a>');
|
||||||
}
|
}
|
||||||
html.push('<td>' + rs.join("<br/>") + '</td>');
|
html.push('<td>' + rs.join("<br/>") + '</td>');
|
||||||
html.push('</tr>');
|
html.push('</tr>');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (var type in classmap) {
|
for (var type in classmap) {
|
||||||
html.push(' <tr><th colspan="5" style="border-bottom:0;"> </th></tr>');
|
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 id="' + type + '"><th colspan="5" style="border-top:0;">' + type + '</th></tr>');
|
||||||
html.push(' <tr><td colspan="5"><table class="typetable">');
|
html.push(' <tr><td colspan="5"><table class="typetable">');
|
||||||
for (var fieldname in classmap[type]) {
|
for (var fieldname in classmap[type]) {
|
||||||
var field = classmap[type][fieldname];
|
var field = classmap[type][fieldname];
|
||||||
var t = field.type.replace(/</g, "<").replace(/>/g, ">").replace(/\$/g, ".").replace(/([a-zA-Z0-9_\$]+\.)+/g, "");
|
var t = field.type.replace(/</g, "<").replace(/>/g, ">").replace(/\$/g, ".").replace(/([a-zA-Z0-9_\$]+\.)+/g, "");
|
||||||
if (t == 'boolean' || t == 'short' || t == 'int' || t == 'long' || t == 'float' || t == 'double'
|
if (t == 'boolean' || t == 'short' || t == 'int' || t == 'long' || t == 'float' || t == 'double'
|
||||||
|| t == 'boolean[]' || t == 'short[]' || t == 'int[]' || t == 'long[]' || t == 'float[]' || t == 'double[]') {
|
|| t == 'boolean[]' || t == 'short[]' || t == 'int[]' || t == 'long[]' || t == 'float[]' || t == 'double[]') {
|
||||||
t = '<font color=blue>' + t + '</font>';
|
t = '<font color=blue>' + t + '</font>';
|
||||||
} else if (t == 'String' || t == 'String[]' || t == 'LongRange' || t.indexOf('Map<') === 0) {
|
} else if (t == 'String' || t == 'String[]' || t == 'LongRange' || t.indexOf('Map<') === 0) {
|
||||||
t = '<font color=red>' + t + '</font>';
|
t = '<font color=red>' + t + '</font>';
|
||||||
}
|
}
|
||||||
var c = (field.comment || '');
|
var c = (field.comment || '');
|
||||||
if (field.primary) {
|
if (field.primary) {
|
||||||
c = '【主键】 ' + c;
|
c = '【主键】 ' + c;
|
||||||
} else if (!field.updatable) {
|
} else if (!field.updatable) {
|
||||||
c = '【只读】 ' + c;
|
c = '【只读】 ' + c;
|
||||||
}
|
}
|
||||||
html.push(' <tr class="l"><td>' + fieldname + '</td><td>' + t + '</td><td colspan="2">' + c + '</td></tr>');
|
html.push(' <tr class="l"><td>' + fieldname + '</td><td>' + t + '</td><td colspan="2">' + c + '</td></tr>');
|
||||||
}
|
}
|
||||||
html.push(' </table></td></tr>');
|
html.push(' </table></td></tr>');
|
||||||
}
|
}
|
||||||
html.push('</table><br/><br/><br/>');
|
html.push('</table><br/><br/><br/>');
|
||||||
html.push('</div>');
|
html.push('</div>');
|
||||||
return html.join('');
|
return html.join('');
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var jsoncontent = '${content}'; //这里必须要用单引号引起来
|
var jsoncontent = '${content}'; //这里必须要用单引号引起来
|
||||||
document.write(createhtml(jsoncontent));
|
document.write(createhtml(jsoncontent));
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/**
|
/**
|
||||||
* 提供Redkale服务器的启动、初始化和加载功能
|
* 提供Redkale服务器的启动、初始化和加载功能
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot;
|
package org.redkale.boot;
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot.watch;
|
package org.redkale.boot.watch;
|
||||||
|
|
||||||
import org.redkale.service.AbstractService;
|
import org.redkale.service.AbstractService;
|
||||||
import org.redkale.util.Comment;
|
import org.redkale.util.Comment;
|
||||||
import org.redkale.watch.WatchService;
|
import org.redkale.watch.WatchService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractWatchService extends AbstractService implements WatchService {
|
public abstract class AbstractWatchService extends AbstractService implements WatchService {
|
||||||
|
|
||||||
@Comment("缺少参数")
|
@Comment("缺少参数")
|
||||||
public static final int RET_WATCH_PARAMS_ILLEGAL = 1600_0001;
|
public static final int RET_WATCH_PARAMS_ILLEGAL = 1600_0001;
|
||||||
|
|
||||||
@Comment("执行异常")
|
@Comment("执行异常")
|
||||||
public static final int RET_WATCH_RUN_EXCEPTION = 1600_0002;
|
public static final int RET_WATCH_RUN_EXCEPTION = 1600_0002;
|
||||||
}
|
}
|
||||||
@@ -1,80 +1,80 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot.watch;
|
package org.redkale.boot.watch;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import org.redkale.boot.*;
|
import org.redkale.boot.*;
|
||||||
import org.redkale.net.http.*;
|
import org.redkale.net.http.*;
|
||||||
import org.redkale.service.RetResult;
|
import org.redkale.service.RetResult;
|
||||||
import org.redkale.util.Comment;
|
import org.redkale.util.Comment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@RestService(name = "filter", catalog = "watch", repair = false)
|
@RestService(name = "filter", catalog = "watch", repair = false)
|
||||||
public class FilterWatchService extends AbstractWatchService {
|
public class FilterWatchService extends AbstractWatchService {
|
||||||
|
|
||||||
@Comment("Filter类名不存在")
|
@Comment("Filter类名不存在")
|
||||||
public static final int RET_FILTER_TYPE_NOT_EXISTS = 1601_0002;
|
public static final int RET_FILTER_TYPE_NOT_EXISTS = 1601_0002;
|
||||||
|
|
||||||
@Comment("Filter类名不合法")
|
@Comment("Filter类名不合法")
|
||||||
public static final int RET_FILTER_TYPE_ILLEGAL = 1601_0003;
|
public static final int RET_FILTER_TYPE_ILLEGAL = 1601_0003;
|
||||||
|
|
||||||
@Comment("Filter类名已存在")
|
@Comment("Filter类名已存在")
|
||||||
public static final int RET_FILTER_EXISTS = 1601_0004;
|
public static final int RET_FILTER_EXISTS = 1601_0004;
|
||||||
|
|
||||||
@Comment("Filter的JAR包不存在")
|
@Comment("Filter的JAR包不存在")
|
||||||
public static final int RET_FILTER_JAR_ILLEGAL = 1601_0005;
|
public static final int RET_FILTER_JAR_ILLEGAL = 1601_0005;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
protected Application application;
|
protected Application application;
|
||||||
|
|
||||||
@RestMapping(name = "addFilter", auth = false, comment = "动态增加Filter")
|
@RestMapping(name = "addFilter", auth = false, comment = "动态增加Filter")
|
||||||
public RetResult addFilter(@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar,
|
public RetResult addFilter(@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar,
|
||||||
@RestParam(name = "server", comment = "Server节点名") final String serverName,
|
@RestParam(name = "server", comment = "Server节点名") final String serverName,
|
||||||
@RestParam(name = "type", comment = "Filter类名") final String filterType) throws IOException {
|
@RestParam(name = "type", comment = "Filter类名") final String filterType) throws IOException {
|
||||||
if (filterType == null) return new RetResult(RET_FILTER_TYPE_NOT_EXISTS, "Not found Filter Type (" + filterType + ")");
|
if (filterType == null) return new RetResult(RET_FILTER_TYPE_NOT_EXISTS, "Not found Filter Type (" + filterType + ")");
|
||||||
if (jar == null) return new RetResult(RET_FILTER_JAR_ILLEGAL, "Not found jar file");
|
if (jar == null) return new RetResult(RET_FILTER_JAR_ILLEGAL, "Not found jar file");
|
||||||
List<NodeServer> nodes = application.getNodeServers();
|
List<NodeServer> nodes = application.getNodeServers();
|
||||||
for (NodeServer node : nodes) {
|
for (NodeServer node : nodes) {
|
||||||
if (node.getServer().containsFilter(filterType)) return new RetResult(RET_FILTER_EXISTS, "Filter(" + filterType + ") exists");
|
if (node.getServer().containsFilter(filterType)) return new RetResult(RET_FILTER_EXISTS, "Filter(" + filterType + ") exists");
|
||||||
}
|
}
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "test1", auth = false, comment = "预留")
|
@RestMapping(name = "test1", auth = false, comment = "预留")
|
||||||
public RetResult test1() {
|
public RetResult test1() {
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "test2", auth = false, comment = "预留")
|
@RestMapping(name = "test2", auth = false, comment = "预留")
|
||||||
public RetResult test2() {
|
public RetResult test2() {
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "test3", auth = false, comment = "预留")
|
@RestMapping(name = "test3", auth = false, comment = "预留")
|
||||||
public RetResult test3() {
|
public RetResult test3() {
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "test4", auth = false, comment = "预留")
|
@RestMapping(name = "test4", auth = false, comment = "预留")
|
||||||
public RetResult test4() {
|
public RetResult test4() {
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "test5", auth = false, comment = "预留")
|
@RestMapping(name = "test5", auth = false, comment = "预留")
|
||||||
public RetResult test5() {
|
public RetResult test5() {
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "test6", auth = false, comment = "预留")
|
@RestMapping(name = "test6", auth = false, comment = "预留")
|
||||||
public RetResult test6() {
|
public RetResult test6() {
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,104 +1,104 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot.watch;
|
package org.redkale.boot.watch;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import org.redkale.boot.*;
|
import org.redkale.boot.*;
|
||||||
import org.redkale.net.Server;
|
import org.redkale.net.Server;
|
||||||
import org.redkale.net.http.*;
|
import org.redkale.net.http.*;
|
||||||
import org.redkale.service.RetResult;
|
import org.redkale.service.RetResult;
|
||||||
import org.redkale.util.Comment;
|
import org.redkale.util.Comment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@RestService(name = "server", catalog = "watch", repair = false)
|
@RestService(name = "server", catalog = "watch", repair = false)
|
||||||
public class ServerWatchService extends AbstractWatchService {
|
public class ServerWatchService extends AbstractWatchService {
|
||||||
|
|
||||||
@Comment("不存在的Server节点")
|
@Comment("不存在的Server节点")
|
||||||
public static final int RET_SERVER_NOT_EXISTS = 1602_0001;
|
public static final int RET_SERVER_NOT_EXISTS = 1602_0001;
|
||||||
|
|
||||||
@Comment("更改Server监听地址端口失败")
|
@Comment("更改Server监听地址端口失败")
|
||||||
public static final int RET_SERVER_CHANGEPORT_ERROR = 1602_0002;
|
public static final int RET_SERVER_CHANGEPORT_ERROR = 1602_0002;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
protected Application application;
|
protected Application application;
|
||||||
|
|
||||||
@RestMapping(name = "info", comment = "单个Server信息查询")
|
@RestMapping(name = "info", comment = "单个Server信息查询")
|
||||||
public RetResult info(@RestParam(name = "#port:") final int port) {
|
public RetResult info(@RestParam(name = "#port:") final int port) {
|
||||||
Stream<NodeServer> stream = application.getNodeServers().stream();
|
Stream<NodeServer> stream = application.getNodeServers().stream();
|
||||||
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == port).findFirst().orElse(null);
|
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == port).findFirst().orElse(null);
|
||||||
if (node == null) return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + port + ") not found");
|
if (node == null) return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + port + ") not found");
|
||||||
return new RetResult(formatToMap(node));
|
return new RetResult(formatToMap(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "infos", comment = "Server信息查询")
|
@RestMapping(name = "infos", comment = "Server信息查询")
|
||||||
public RetResult infos() {
|
public RetResult infos() {
|
||||||
Map<String, Object> rs = new LinkedHashMap<>();
|
Map<String, Object> rs = new LinkedHashMap<>();
|
||||||
for (NodeServer ns : application.getNodeServers()) {
|
for (NodeServer ns : application.getNodeServers()) {
|
||||||
Server server = ns.getServer();
|
Server server = ns.getServer();
|
||||||
rs.put("" + server.getSocketAddress().getPort(), formatToMap(ns));
|
rs.put("" + server.getSocketAddress().getPort(), formatToMap(ns));
|
||||||
}
|
}
|
||||||
return new RetResult(rs);
|
return new RetResult(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "changeAddress", comment = "更改Server的监听地址和端口")
|
@RestMapping(name = "changeAddress", comment = "更改Server的监听地址和端口")
|
||||||
public RetResult changeAddress(@RestParam(name = "#port:") final int oldport,
|
public RetResult changeAddress(@RestParam(name = "#port:") final int oldport,
|
||||||
@RestParam(name = "#newhost:") final String newhost, @RestParam(name = "#newport:") final int newport) {
|
@RestParam(name = "#newhost:") final String newhost, @RestParam(name = "#newport:") final int newport) {
|
||||||
if (oldport < 1) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `oldport`");
|
if (oldport < 1) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `oldport`");
|
||||||
if (newport < 1) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `newport`");
|
if (newport < 1) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `newport`");
|
||||||
Stream<NodeServer> stream = application.getNodeServers().stream();
|
Stream<NodeServer> stream = application.getNodeServers().stream();
|
||||||
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == oldport).findFirst().orElse(null);
|
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == oldport).findFirst().orElse(null);
|
||||||
if (node == null) return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + oldport + ") not found");
|
if (node == null) return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + oldport + ") not found");
|
||||||
final Server server = node.getServer();
|
final Server server = node.getServer();
|
||||||
InetSocketAddress newAddr = new InetSocketAddress(newhost == null || newhost.isEmpty() ? server.getSocketAddress().getHostString() : newhost, newport);
|
InetSocketAddress newAddr = new InetSocketAddress(newhost == null || newhost.isEmpty() ? server.getSocketAddress().getHostString() : newhost, newport);
|
||||||
try {
|
try {
|
||||||
server.changeAddress(application, newAddr);
|
server.changeAddress(application, newAddr);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return new RetResult(RET_SERVER_CHANGEPORT_ERROR, "changeaddress error");
|
return new RetResult(RET_SERVER_CHANGEPORT_ERROR, "changeaddress error");
|
||||||
}
|
}
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Object> formatToMap(NodeServer node) {
|
private Map<String, Object> formatToMap(NodeServer node) {
|
||||||
Server server = node.getServer();
|
Server server = node.getServer();
|
||||||
Map<String, Object> rs = new LinkedHashMap<>();
|
Map<String, Object> rs = new LinkedHashMap<>();
|
||||||
String protocol = server.getNetprotocol();
|
String protocol = server.getNetprotocol();
|
||||||
if (node instanceof NodeSncpServer) {
|
if (node instanceof NodeSncpServer) {
|
||||||
protocol += "/SNCP";
|
protocol += "/SNCP";
|
||||||
} else if (node instanceof NodeWatchServer) {
|
} else if (node instanceof NodeWatchServer) {
|
||||||
protocol += "/WATCH";
|
protocol += "/WATCH";
|
||||||
} else if (node instanceof NodeHttpServer) {
|
} else if (node instanceof NodeHttpServer) {
|
||||||
protocol += "/HTTP";
|
protocol += "/HTTP";
|
||||||
} else {
|
} else {
|
||||||
NodeProtocol np = node.getClass().getAnnotation(NodeProtocol.class);
|
NodeProtocol np = node.getClass().getAnnotation(NodeProtocol.class);
|
||||||
protocol += "/" + np.value();
|
protocol += "/" + np.value();
|
||||||
}
|
}
|
||||||
rs.put("name", server.getName());
|
rs.put("name", server.getName());
|
||||||
rs.put("protocol", protocol);
|
rs.put("protocol", protocol);
|
||||||
rs.put("address", server.getSocketAddress());
|
rs.put("address", server.getSocketAddress());
|
||||||
rs.put("backlog", server.getBacklog());
|
rs.put("backlog", server.getBacklog());
|
||||||
rs.put("bufferCapacity", server.getBufferCapacity());
|
rs.put("bufferCapacity", server.getBufferCapacity());
|
||||||
rs.put("bufferPoolSize", server.getBufferPoolSize());
|
rs.put("bufferPoolSize", server.getBufferPoolSize());
|
||||||
rs.put("charset", server.getCharset() == null ? "UTF-8" : server.getCharset().name());
|
rs.put("charset", server.getCharset() == null ? "UTF-8" : server.getCharset().name());
|
||||||
rs.put("maxbody", server.getMaxbody());
|
rs.put("maxbody", server.getMaxbody());
|
||||||
rs.put("maxconns", server.getMaxconns());
|
rs.put("maxconns", server.getMaxconns());
|
||||||
rs.put("serverStartTime", server.getServerStartTime());
|
rs.put("serverStartTime", server.getServerStartTime());
|
||||||
rs.put("responsePoolSize", server.getResponsePoolSize());
|
rs.put("responsePoolSize", server.getResponsePoolSize());
|
||||||
rs.put("readTimeoutSeconds", server.getReadTimeoutSeconds());
|
rs.put("readTimeoutSeconds", server.getReadTimeoutSeconds());
|
||||||
rs.put("writeTimeoutSeconds", server.getWriteTimeoutSeconds());
|
rs.put("writeTimeoutSeconds", server.getWriteTimeoutSeconds());
|
||||||
rs.put("createConnectionCount", server.getCreateConnectionCount());
|
rs.put("createConnectionCount", server.getCreateConnectionCount());
|
||||||
rs.put("livingConnectionCount", server.getLivingConnectionCount());
|
rs.put("livingConnectionCount", server.getLivingConnectionCount());
|
||||||
rs.put("closedConnectionCount", server.getClosedConnectionCount());
|
rs.put("closedConnectionCount", server.getClosedConnectionCount());
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,199 +1,199 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot.watch;
|
package org.redkale.boot.watch;
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import org.redkale.boot.*;
|
import org.redkale.boot.*;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
import org.redkale.net.http.*;
|
import org.redkale.net.http.*;
|
||||||
import org.redkale.service.RetResult;
|
import org.redkale.service.RetResult;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@RestService(name = "service", catalog = "watch", repair = false)
|
@RestService(name = "service", catalog = "watch", repair = false)
|
||||||
public class ServiceWatchService extends AbstractWatchService {
|
public class ServiceWatchService extends AbstractWatchService {
|
||||||
|
|
||||||
@Comment("没有找到目标Service")
|
@Comment("没有找到目标Service")
|
||||||
public static final int RET_SERVICE_DEST_NOT_EXISTS = 1603_0001;
|
public static final int RET_SERVICE_DEST_NOT_EXISTS = 1603_0001;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
protected Application application;
|
protected Application application;
|
||||||
|
|
||||||
@RestConvert(type = void.class)
|
@RestConvert(type = void.class)
|
||||||
@RestMapping(name = "setField", auth = false, comment = "设置Service中指定字段的内容")
|
@RestMapping(name = "setField", auth = false, comment = "设置Service中指定字段的内容")
|
||||||
public RetResult setField(@RestParam(name = "name", comment = "Service的资源名") String name,
|
public RetResult setField(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||||
@RestParam(name = "field", comment = "字段名") String field,
|
@RestParam(name = "field", comment = "字段名") String field,
|
||||||
@RestParam(name = "value", comment = "字段值") String value) {
|
@RestParam(name = "value", comment = "字段值") String value) {
|
||||||
if (name == null) name = "";
|
if (name == null) name = "";
|
||||||
if (type == null) type = "";
|
if (type == null) type = "";
|
||||||
if (field == null) field = "";
|
if (field == null) field = "";
|
||||||
type = type.trim();
|
type = type.trim();
|
||||||
field = field.trim();
|
field = field.trim();
|
||||||
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||||
if (field.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
|
if (field.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
|
||||||
Object dest = findService(name, type);
|
Object dest = findService(name, type);
|
||||||
Class clazz = dest.getClass();
|
Class clazz = dest.getClass();
|
||||||
Throwable t = null;
|
Throwable t = null;
|
||||||
try {
|
try {
|
||||||
Field fieldObj = null;
|
Field fieldObj = null;
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
fieldObj = clazz.getDeclaredField(field);
|
fieldObj = clazz.getDeclaredField(field);
|
||||||
break;
|
break;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (t == null) t = e;
|
if (t == null) t = e;
|
||||||
}
|
}
|
||||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||||
if (fieldObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + String.valueOf(t) + ")");
|
if (fieldObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + String.valueOf(t) + ")");
|
||||||
fieldObj.setAccessible(true);
|
fieldObj.setAccessible(true);
|
||||||
fieldObj.set(dest, JsonConvert.root().convertFrom(fieldObj.getGenericType(), value));
|
fieldObj.set(dest, JsonConvert.root().convertFrom(fieldObj.getGenericType(), value));
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
} catch (Throwable t2) {
|
} catch (Throwable t2) {
|
||||||
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestConvert(type = void.class)
|
@RestConvert(type = void.class)
|
||||||
@RestMapping(name = "getField", auth = false, comment = "查询Service中指定字段的内容")
|
@RestMapping(name = "getField", auth = false, comment = "查询Service中指定字段的内容")
|
||||||
public RetResult getField(@RestParam(name = "name", comment = "Service的资源名") String name,
|
public RetResult getField(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||||
@RestParam(name = "field", comment = "字段名") String field) {
|
@RestParam(name = "field", comment = "字段名") String field) {
|
||||||
if (name == null) name = "";
|
if (name == null) name = "";
|
||||||
if (type == null) type = "";
|
if (type == null) type = "";
|
||||||
if (field == null) field = "";
|
if (field == null) field = "";
|
||||||
type = type.trim();
|
type = type.trim();
|
||||||
field = field.trim();
|
field = field.trim();
|
||||||
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||||
if (field.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
|
if (field.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
|
||||||
Object dest = findService(name, type);
|
Object dest = findService(name, type);
|
||||||
Class clazz = dest.getClass();
|
Class clazz = dest.getClass();
|
||||||
Throwable t = null;
|
Throwable t = null;
|
||||||
try {
|
try {
|
||||||
Field fieldObj = null;
|
Field fieldObj = null;
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
fieldObj = clazz.getDeclaredField(field);
|
fieldObj = clazz.getDeclaredField(field);
|
||||||
break;
|
break;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (t == null) t = e;
|
if (t == null) t = e;
|
||||||
}
|
}
|
||||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||||
if (fieldObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + String.valueOf(t) + ")");
|
if (fieldObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + String.valueOf(t) + ")");
|
||||||
fieldObj.setAccessible(true);
|
fieldObj.setAccessible(true);
|
||||||
return new RetResult(fieldObj.get(dest));
|
return new RetResult(fieldObj.get(dest));
|
||||||
} catch (Throwable t2) {
|
} catch (Throwable t2) {
|
||||||
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestConvert(type = void.class)
|
@RestConvert(type = void.class)
|
||||||
@RestMapping(name = "runMethod", auth = false, comment = "调用Service中指定方法")
|
@RestMapping(name = "runMethod", auth = false, comment = "调用Service中指定方法")
|
||||||
public RetResult runMethod(@RestParam(name = "name", comment = "Service的资源名") String name,
|
public RetResult runMethod(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||||
@RestParam(name = "type", comment = "Service的类名") String type,
|
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||||
@RestParam(name = "method", comment = "Service的方法名") String method,
|
@RestParam(name = "method", comment = "Service的方法名") String method,
|
||||||
@RestParam(name = "params", comment = "方法的参数值") List<String> params,
|
@RestParam(name = "params", comment = "方法的参数值") List<String> params,
|
||||||
@RestParam(name = "paramtypes", comment = "方法的参数数据类型") List<String> paramtypes) {
|
@RestParam(name = "paramtypes", comment = "方法的参数数据类型") List<String> paramtypes) {
|
||||||
if (name == null) name = "";
|
if (name == null) name = "";
|
||||||
if (type == null) type = "";
|
if (type == null) type = "";
|
||||||
if (method == null) method = "";
|
if (method == null) method = "";
|
||||||
type = type.trim();
|
type = type.trim();
|
||||||
method = method.trim();
|
method = method.trim();
|
||||||
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||||
if (method.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `method`");
|
if (method.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `method`");
|
||||||
Object dest = findService(name, type);
|
Object dest = findService(name, type);
|
||||||
Class clazz = dest.getClass();
|
Class clazz = dest.getClass();
|
||||||
Throwable t = null;
|
Throwable t = null;
|
||||||
final int paramcount = params == null ? 0 : params.size();
|
final int paramcount = params == null ? 0 : params.size();
|
||||||
if (paramtypes != null && paramcount != paramtypes.size()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "params.size not equals to paramtypes.size");
|
if (paramtypes != null && paramcount != paramtypes.size()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "params.size not equals to paramtypes.size");
|
||||||
try {
|
try {
|
||||||
Method methodObj = null;
|
Method methodObj = null;
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
for (Method m : clazz.getDeclaredMethods()) {
|
for (Method m : clazz.getDeclaredMethods()) {
|
||||||
if (m.getName().equals(method) && m.getParameterCount() == paramcount) {
|
if (m.getName().equals(method) && m.getParameterCount() == paramcount) {
|
||||||
boolean flag = true;
|
boolean flag = true;
|
||||||
if (paramtypes != null) {
|
if (paramtypes != null) {
|
||||||
Class[] pts = m.getParameterTypes();
|
Class[] pts = m.getParameterTypes();
|
||||||
for (int i = 0; i < pts.length; i++) {
|
for (int i = 0; i < pts.length; i++) {
|
||||||
if (!pts[i].getName().endsWith(paramtypes.get(i))) {
|
if (!pts[i].getName().endsWith(paramtypes.get(i))) {
|
||||||
flag = false;
|
flag = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flag) {
|
if (flag) {
|
||||||
methodObj = m;
|
methodObj = m;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (methodObj != null) break;
|
if (methodObj != null) break;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (t == null) t = e;
|
if (t == null) t = e;
|
||||||
}
|
}
|
||||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||||
if (methodObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + (t == null ? ("not found method(" + method + ")") : String.valueOf(t)) + ")");
|
if (methodObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + (t == null ? ("not found method(" + method + ")") : String.valueOf(t)) + ")");
|
||||||
methodObj.setAccessible(true);
|
methodObj.setAccessible(true);
|
||||||
if (paramcount < 1) return new RetResult(methodObj.invoke(dest));
|
if (paramcount < 1) return new RetResult(methodObj.invoke(dest));
|
||||||
Object[] paramObjs = new Object[paramcount];
|
Object[] paramObjs = new Object[paramcount];
|
||||||
Type[] pts = methodObj.getGenericParameterTypes();
|
Type[] pts = methodObj.getGenericParameterTypes();
|
||||||
for (int i = 0; i < paramObjs.length; i++) {
|
for (int i = 0; i < paramObjs.length; i++) {
|
||||||
paramObjs[i] = JsonConvert.root().convertFrom(pts[i], params.get(i));
|
paramObjs[i] = JsonConvert.root().convertFrom(pts[i], params.get(i));
|
||||||
}
|
}
|
||||||
return new RetResult(methodObj.invoke(dest, paramObjs));
|
return new RetResult(methodObj.invoke(dest, paramObjs));
|
||||||
} catch (Throwable t2) {
|
} catch (Throwable t2) {
|
||||||
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object findService(String name, String type) {
|
protected Object findService(String name, String type) {
|
||||||
Object dest = null;
|
Object dest = null;
|
||||||
for (NodeServer ns : application.getNodeServers()) {
|
for (NodeServer ns : application.getNodeServers()) {
|
||||||
ResourceFactory resFactory = ns.getResourceFactory();
|
ResourceFactory resFactory = ns.getResourceFactory();
|
||||||
List list = resFactory.query((n, s) -> name.equals(n) && s != null && s.getClass().getName().endsWith(type));
|
List list = resFactory.query((n, s) -> name.equals(n) && s != null && s.getClass().getName().endsWith(type));
|
||||||
if (list == null || list.isEmpty()) continue;
|
if (list == null || list.isEmpty()) continue;
|
||||||
dest = list.get(0);
|
dest = list.get(0);
|
||||||
}
|
}
|
||||||
if (dest == null) return new RetResult(RET_SERVICE_DEST_NOT_EXISTS, "not found servie (name=" + name + ", type=" + type + ")");
|
if (dest == null) return new RetResult(RET_SERVICE_DEST_NOT_EXISTS, "not found servie (name=" + name + ", type=" + type + ")");
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "loadService", auth = false, comment = "动态增加Service")
|
@RestMapping(name = "loadService", auth = false, comment = "动态增加Service")
|
||||||
public RetResult loadService(@RestParam(name = "type", comment = "Service的类名") String type,
|
public RetResult loadService(@RestParam(name = "type", comment = "Service的类名") String type,
|
||||||
@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {
|
@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {
|
||||||
//待开发
|
//待开发
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "reloadService", auth = false, comment = "重新加载Service")
|
@RestMapping(name = "reloadService", auth = false, comment = "重新加载Service")
|
||||||
public RetResult reloadService(@RestParam(name = "name", comment = "Service的资源名") String name,
|
public RetResult reloadService(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||||
@RestParam(name = "type", comment = "Service的类名") String type) {
|
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||||
//待开发
|
//待开发
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "stopService", auth = false, comment = "动态停止Service")
|
@RestMapping(name = "stopService", auth = false, comment = "动态停止Service")
|
||||||
public RetResult stopService(@RestParam(name = "name", comment = "Service的资源名") String name,
|
public RetResult stopService(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||||
@RestParam(name = "type", comment = "Service的类名") String type) {
|
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||||
//待开发
|
//待开发
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "findService", auth = false, comment = "查找Service")
|
@RestMapping(name = "findService", auth = false, comment = "查找Service")
|
||||||
public RetResult find(@RestParam(name = "name", comment = "Service的资源名") String name,
|
public RetResult find(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||||
@RestParam(name = "type", comment = "Service的类名") String type) {
|
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||||
//待开发
|
//待开发
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,39 +1,39 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot.watch;
|
package org.redkale.boot.watch;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import org.redkale.boot.Application;
|
import org.redkale.boot.Application;
|
||||||
import org.redkale.net.TransportFactory;
|
import org.redkale.net.TransportFactory;
|
||||||
import org.redkale.net.http.*;
|
import org.redkale.net.http.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@RestService(name = "servlet", catalog = "watch", repair = false)
|
@RestService(name = "servlet", catalog = "watch", repair = false)
|
||||||
public class ServletWatchService extends AbstractWatchService {
|
public class ServletWatchService extends AbstractWatchService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
protected Application application;
|
protected Application application;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
protected TransportFactory transportFactory;
|
protected TransportFactory transportFactory;
|
||||||
//
|
//
|
||||||
// @RestMapping(name = "loadServlet", auth = false, comment = "动态增加Servlet")
|
// @RestMapping(name = "loadServlet", auth = false, comment = "动态增加Servlet")
|
||||||
// public RetResult loadServlet(String type, @RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {
|
// public RetResult loadServlet(String type, @RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {
|
||||||
// //待开发
|
// //待开发
|
||||||
// return RetResult.success();
|
// return RetResult.success();
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// @RestMapping(name = "stopServlet", auth = false, comment = "动态停止Servlet")
|
// @RestMapping(name = "stopServlet", auth = false, comment = "动态停止Servlet")
|
||||||
// public RetResult stopServlet(String type) {
|
// public RetResult stopServlet(String type) {
|
||||||
// //待开发
|
// //待开发
|
||||||
// return RetResult.success();
|
// return RetResult.success();
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
@@ -1,140 +1,140 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.boot.watch;
|
package org.redkale.boot.watch;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.nio.channels.AsynchronousSocketChannel;
|
import java.nio.channels.AsynchronousSocketChannel;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import org.redkale.boot.Application;
|
import org.redkale.boot.Application;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.net.http.*;
|
import org.redkale.net.http.*;
|
||||||
import org.redkale.net.sncp.*;
|
import org.redkale.net.sncp.*;
|
||||||
import org.redkale.service.*;
|
import org.redkale.service.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
import org.redkale.util.AnyValue.DefaultAnyValue;
|
import org.redkale.util.AnyValue.DefaultAnyValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@RestService(name = "transport", catalog = "watch", repair = false)
|
@RestService(name = "transport", catalog = "watch", repair = false)
|
||||||
public class TransportWatchService extends AbstractWatchService {
|
public class TransportWatchService extends AbstractWatchService {
|
||||||
|
|
||||||
@Comment("不存在的Group节点")
|
@Comment("不存在的Group节点")
|
||||||
public static final int RET_TRANSPORT_GROUP_NOT_EXISTS = 1606_0001;
|
public static final int RET_TRANSPORT_GROUP_NOT_EXISTS = 1606_0001;
|
||||||
|
|
||||||
@Comment("非法的Node节点IP地址")
|
@Comment("非法的Node节点IP地址")
|
||||||
public static final int RET_TRANSPORT_ADDR_ILLEGAL = 1606_0002;
|
public static final int RET_TRANSPORT_ADDR_ILLEGAL = 1606_0002;
|
||||||
|
|
||||||
@Comment("Node节点IP地址已存在")
|
@Comment("Node节点IP地址已存在")
|
||||||
public static final int RET_TRANSPORT_ADDR_EXISTS = 1606_0003;
|
public static final int RET_TRANSPORT_ADDR_EXISTS = 1606_0003;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
protected Application application;
|
protected Application application;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
protected TransportFactory transportFactory;
|
protected TransportFactory transportFactory;
|
||||||
|
|
||||||
@RestMapping(name = "listnodes", auth = false, comment = "获取所有Node节点")
|
@RestMapping(name = "listnodes", auth = false, comment = "获取所有Node节点")
|
||||||
public List<TransportGroupInfo> listNodes() {
|
public List<TransportGroupInfo> listNodes() {
|
||||||
return transportFactory.getGroupInfos();
|
return transportFactory.getGroupInfos();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "addnode", auth = false, comment = "动态增加指定Group的Node节点")
|
@RestMapping(name = "addnode", auth = false, comment = "动态增加指定Group的Node节点")
|
||||||
public RetResult addNode(@RestParam(name = "group", comment = "Group节点名") final String group,
|
public RetResult addNode(@RestParam(name = "group", comment = "Group节点名") final String group,
|
||||||
@RestParam(name = "addr", comment = "节点IP") final String addr,
|
@RestParam(name = "addr", comment = "节点IP") final String addr,
|
||||||
@RestParam(name = "port", comment = "节点端口") final int port) throws IOException {
|
@RestParam(name = "port", comment = "节点端口") final int port) throws IOException {
|
||||||
InetSocketAddress address;
|
InetSocketAddress address;
|
||||||
try {
|
try {
|
||||||
address = new InetSocketAddress(addr, port);
|
address = new InetSocketAddress(addr, port);
|
||||||
AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
|
AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
|
||||||
channel.connect(address).get(2, TimeUnit.SECONDS); //连接超时2秒
|
channel.connect(address).get(2, TimeUnit.SECONDS); //连接超时2秒
|
||||||
channel.close();
|
channel.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return new RetResult(RET_TRANSPORT_ADDR_ILLEGAL, "InetSocketAddress(addr=" + addr + ", port=" + port + ") is illegal or cannot connect");
|
return new RetResult(RET_TRANSPORT_ADDR_ILLEGAL, "InetSocketAddress(addr=" + addr + ", port=" + port + ") is illegal or cannot connect");
|
||||||
}
|
}
|
||||||
if (transportFactory.findGroupName(address) != null) return new RetResult(RET_TRANSPORT_ADDR_ILLEGAL, "InetSocketAddress(addr=" + addr + ", port=" + port + ") is exists");
|
if (transportFactory.findGroupName(address) != null) return new RetResult(RET_TRANSPORT_ADDR_ILLEGAL, "InetSocketAddress(addr=" + addr + ", port=" + port + ") is exists");
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (transportFactory.findGroupInfo(group) == null) {
|
if (transportFactory.findGroupInfo(group) == null) {
|
||||||
return new RetResult(RET_TRANSPORT_GROUP_NOT_EXISTS, "not found group (" + group + ")");
|
return new RetResult(RET_TRANSPORT_GROUP_NOT_EXISTS, "not found group (" + group + ")");
|
||||||
}
|
}
|
||||||
transportFactory.addGroupInfo(group, address);
|
transportFactory.addGroupInfo(group, address);
|
||||||
for (Service service : transportFactory.getServices()) {
|
for (Service service : transportFactory.getServices()) {
|
||||||
if (!Sncp.isSncpDyn(service)) continue;
|
if (!Sncp.isSncpDyn(service)) continue;
|
||||||
SncpClient client = Sncp.getSncpClient(service);
|
SncpClient client = Sncp.getSncpClient(service);
|
||||||
if (Sncp.isRemote(service)) {
|
if (Sncp.isRemote(service)) {
|
||||||
if (client.getRemoteGroups() != null && client.getRemoteGroups().contains(group)) {
|
if (client.getRemoteGroups() != null && client.getRemoteGroups().contains(group)) {
|
||||||
client.getRemoteGroupTransport().addRemoteAddresses(address);
|
client.getRemoteGroupTransport().addRemoteAddresses(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultAnyValue node = DefaultAnyValue.create("addr", addr).addValue("port", port);
|
DefaultAnyValue node = DefaultAnyValue.create("addr", addr).addValue("port", port);
|
||||||
for (AnyValue groupconf : application.getAppConfig().getAnyValue("resources").getAnyValues("group")) {
|
for (AnyValue groupconf : application.getAppConfig().getAnyValue("resources").getAnyValues("group")) {
|
||||||
if (group.equals(groupconf.getValue("name"))) {
|
if (group.equals(groupconf.getValue("name"))) {
|
||||||
((DefaultAnyValue) groupconf).addValue("node", node);
|
((DefaultAnyValue) groupconf).addValue("node", node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//application.restoreConfig();
|
//application.restoreConfig();
|
||||||
}
|
}
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "removenode", auth = false, comment = "动态删除指定Group的Node节点")
|
@RestMapping(name = "removenode", auth = false, comment = "动态删除指定Group的Node节点")
|
||||||
public RetResult removeNode(@RestParam(name = "group", comment = "Group节点名") final String group,
|
public RetResult removeNode(@RestParam(name = "group", comment = "Group节点名") final String group,
|
||||||
@RestParam(name = "addr", comment = "节点IP") final String addr,
|
@RestParam(name = "addr", comment = "节点IP") final String addr,
|
||||||
@RestParam(name = "port", comment = "节点端口") final int port) throws IOException {
|
@RestParam(name = "port", comment = "节点端口") final int port) throws IOException {
|
||||||
if (group == null) return new RetResult(RET_TRANSPORT_GROUP_NOT_EXISTS, "not found group (" + group + ")");
|
if (group == null) return new RetResult(RET_TRANSPORT_GROUP_NOT_EXISTS, "not found group (" + group + ")");
|
||||||
final InetSocketAddress address = new InetSocketAddress(addr, port);
|
final InetSocketAddress address = new InetSocketAddress(addr, port);
|
||||||
if (!group.equals(transportFactory.findGroupName(address))) return new RetResult(RET_TRANSPORT_ADDR_ILLEGAL, "InetSocketAddress(addr=" + addr + ", port=" + port + ") not belong to group(" + group + ")");
|
if (!group.equals(transportFactory.findGroupName(address))) return new RetResult(RET_TRANSPORT_ADDR_ILLEGAL, "InetSocketAddress(addr=" + addr + ", port=" + port + ") not belong to group(" + group + ")");
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (transportFactory.findGroupInfo(group) == null) {
|
if (transportFactory.findGroupInfo(group) == null) {
|
||||||
return new RetResult(RET_TRANSPORT_GROUP_NOT_EXISTS, "not found group (" + group + ")");
|
return new RetResult(RET_TRANSPORT_GROUP_NOT_EXISTS, "not found group (" + group + ")");
|
||||||
}
|
}
|
||||||
transportFactory.removeGroupInfo(group, address);
|
transportFactory.removeGroupInfo(group, address);
|
||||||
for (Service service : transportFactory.getServices()) {
|
for (Service service : transportFactory.getServices()) {
|
||||||
if (!Sncp.isSncpDyn(service)) continue;
|
if (!Sncp.isSncpDyn(service)) continue;
|
||||||
SncpClient client = Sncp.getSncpClient(service);
|
SncpClient client = Sncp.getSncpClient(service);
|
||||||
if (Sncp.isRemote(service)) {
|
if (Sncp.isRemote(service)) {
|
||||||
if (client.getRemoteGroups() != null && client.getRemoteGroups().contains(group)) {
|
if (client.getRemoteGroups() != null && client.getRemoteGroups().contains(group)) {
|
||||||
client.getRemoteGroupTransport().removeRemoteAddresses(address);
|
client.getRemoteGroupTransport().removeRemoteAddresses(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (AnyValue groupconf : application.getAppConfig().getAnyValue("resources").getAnyValues("group")) {
|
for (AnyValue groupconf : application.getAppConfig().getAnyValue("resources").getAnyValues("group")) {
|
||||||
if (group.equals(groupconf.getValue("name"))) {
|
if (group.equals(groupconf.getValue("name"))) {
|
||||||
((DefaultAnyValue) groupconf).removeValue("node", DefaultAnyValue.create("addr", addr).addValue("port", port));
|
((DefaultAnyValue) groupconf).removeValue("node", DefaultAnyValue.create("addr", addr).addValue("port", port));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//application.restoreConfig();
|
//application.restoreConfig();
|
||||||
}
|
}
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "test1", auth = false, comment = "预留")
|
@RestMapping(name = "test1", auth = false, comment = "预留")
|
||||||
public RetResult test1() {
|
public RetResult test1() {
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "test2", auth = false, comment = "预留")
|
@RestMapping(name = "test2", auth = false, comment = "预留")
|
||||||
public RetResult test2() {
|
public RetResult test2() {
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "test3", auth = false, comment = "预留")
|
@RestMapping(name = "test3", auth = false, comment = "预留")
|
||||||
public RetResult test3() {
|
public RetResult test3() {
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RestMapping(name = "test4", auth = false, comment = "预留")
|
@RestMapping(name = "test4", auth = false, comment = "预留")
|
||||||
public RetResult test4() {
|
public RetResult test4() {
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,327 +1,327 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.cluster;
|
package org.redkale.cluster;
|
||||||
|
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import org.redkale.boot.*;
|
import org.redkale.boot.*;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
import org.redkale.service.Service;
|
import org.redkale.service.Service;
|
||||||
import org.redkale.source.CacheSource;
|
import org.redkale.source.CacheSource;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用CacheSource实现的第三方服务发现管理接口cluster
|
* 使用CacheSource实现的第三方服务发现管理接口cluster
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*
|
*
|
||||||
* @since 2.3.0
|
* @since 2.3.0
|
||||||
*/
|
*/
|
||||||
public class CacheClusterAgent extends ClusterAgent implements Resourcable {
|
public class CacheClusterAgent extends ClusterAgent implements Resourcable {
|
||||||
|
|
||||||
@Resource(name = "$")
|
@Resource(name = "$")
|
||||||
private CacheSource source;
|
private CacheSource source;
|
||||||
|
|
||||||
private String sourceName;
|
private String sourceName;
|
||||||
|
|
||||||
protected int ttls = 10; //定时检查的秒数
|
protected int ttls = 10; //定时检查的秒数
|
||||||
|
|
||||||
protected ScheduledThreadPoolExecutor scheduler;
|
protected ScheduledThreadPoolExecutor scheduler;
|
||||||
|
|
||||||
//可能被HttpMessageClient用到的服务 key: servicename
|
//可能被HttpMessageClient用到的服务 key: servicename
|
||||||
protected final ConcurrentHashMap<String, Collection<InetSocketAddress>> httpAddressMap = new ConcurrentHashMap<>();
|
protected final ConcurrentHashMap<String, Collection<InetSocketAddress>> httpAddressMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
//可能被mqtp用到的服务 key: servicename
|
//可能被mqtp用到的服务 key: servicename
|
||||||
protected final ConcurrentHashMap<String, Collection<InetSocketAddress>> mqtpAddressMap = new ConcurrentHashMap<>();
|
protected final ConcurrentHashMap<String, Collection<InetSocketAddress>> mqtpAddressMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(AnyValue config) {
|
public void init(AnyValue config) {
|
||||||
super.init(config);
|
super.init(config);
|
||||||
this.sourceName = getSourceName();
|
this.sourceName = getSourceName();
|
||||||
|
|
||||||
AnyValue[] properties = config.getAnyValues("property");
|
AnyValue[] properties = config.getAnyValues("property");
|
||||||
for (AnyValue property : properties) {
|
for (AnyValue property : properties) {
|
||||||
if ("ttls".equalsIgnoreCase(property.getValue("name"))) {
|
if ("ttls".equalsIgnoreCase(property.getValue("name"))) {
|
||||||
this.ttls = Integer.parseInt(property.getValue("value", "").trim());
|
this.ttls = Integer.parseInt(property.getValue("value", "").trim());
|
||||||
if (this.ttls < 5) this.ttls = 10;
|
if (this.ttls < 5) this.ttls = 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy(AnyValue config) {
|
public void destroy(AnyValue config) {
|
||||||
if (scheduler != null) scheduler.shutdownNow();
|
if (scheduler != null) scheduler.shutdownNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSourceName() {
|
public String getSourceName() {
|
||||||
AnyValue[] properties = config.getAnyValues("property");
|
AnyValue[] properties = config.getAnyValues("property");
|
||||||
for (AnyValue property : properties) {
|
for (AnyValue property : properties) {
|
||||||
if ("source".equalsIgnoreCase(property.getValue("name"))
|
if ("source".equalsIgnoreCase(property.getValue("name"))
|
||||||
&& property.getValue("value") != null) {
|
&& property.getValue("value") != null) {
|
||||||
this.sourceName = property.getValue("value");
|
this.sourceName = property.getValue("value");
|
||||||
return this.sourceName;
|
return this.sourceName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String resourceName() {
|
public String resourceName() {
|
||||||
return sourceName;
|
return sourceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override //ServiceLoader时判断配置是否符合当前实现类
|
@Override //ServiceLoader时判断配置是否符合当前实现类
|
||||||
public boolean match(AnyValue config) {
|
public boolean acceptsConf(AnyValue config) {
|
||||||
if (config == null) return false;
|
if (config == null) return false;
|
||||||
AnyValue[] properties = config.getAnyValues("property");
|
AnyValue[] properties = config.getAnyValues("property");
|
||||||
if (properties == null || properties.length == 0) return false;
|
if (properties == null || properties.length == 0) return false;
|
||||||
for (AnyValue property : properties) {
|
for (AnyValue property : properties) {
|
||||||
if ("source".equalsIgnoreCase(property.getValue("name"))
|
if ("source".equalsIgnoreCase(property.getValue("name"))
|
||||||
&& property.getValue("value") != null) return true;
|
&& property.getValue("value") != null) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
if (this.scheduler == null) {
|
if (this.scheduler == null) {
|
||||||
this.scheduler = new ScheduledThreadPoolExecutor(4, (Runnable r) -> {
|
this.scheduler = new ScheduledThreadPoolExecutor(4, (Runnable r) -> {
|
||||||
final Thread t = new Thread(r, "Redkale-" + CacheClusterAgent.class.getSimpleName() + "-Task-Thread");
|
final Thread t = new Thread(r, "Redkale-" + CacheClusterAgent.class.getSimpleName() + "-Task-Thread");
|
||||||
t.setDaemon(true);
|
t.setDaemon(true);
|
||||||
return t;
|
return t;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.scheduler.scheduleAtFixedRate(() -> {
|
this.scheduler.scheduleAtFixedRate(() -> {
|
||||||
try {
|
try {
|
||||||
checkApplicationHealth();
|
checkApplicationHealth();
|
||||||
checkHttpAddressHealth();
|
checkHttpAddressHealth();
|
||||||
loadMqtpAddressHealth();
|
loadMqtpAddressHealth();
|
||||||
localEntrys.values().stream().filter(e -> !e.canceled).forEach(entry -> {
|
localEntrys.values().stream().filter(e -> !e.canceled).forEach(entry -> {
|
||||||
checkLocalHealth(entry);
|
checkLocalHealth(entry);
|
||||||
});
|
});
|
||||||
remoteEntrys.values().stream().filter(entry -> "SNCP".equalsIgnoreCase(entry.protocol)).forEach(entry -> {
|
remoteEntrys.values().stream().filter(entry -> "SNCP".equalsIgnoreCase(entry.protocol)).forEach(entry -> {
|
||||||
updateSncpTransport(entry);
|
updateSncpTransport(entry);
|
||||||
});
|
});
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "scheduleAtFixedRate check error", e);
|
logger.log(Level.SEVERE, "scheduleAtFixedRate check error", e);
|
||||||
}
|
}
|
||||||
}, Math.max(2000, ttls * 1000), Math.max(2000, ttls * 1000), TimeUnit.MILLISECONDS);
|
}, Math.max(2000, ttls * 1000), Math.max(2000, ttls * 1000), TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void loadMqtpAddressHealth() {
|
protected void loadMqtpAddressHealth() {
|
||||||
List<String> keys = source.queryKeysStartsWith("cluster.mqtp:");
|
List<String> keys = source.queryKeysStartsWith("cluster.mqtp:");
|
||||||
keys.forEach(servicename -> {
|
keys.forEach(servicename -> {
|
||||||
try {
|
try {
|
||||||
this.mqtpAddressMap.put(servicename, queryAddress(servicename).get(3, TimeUnit.SECONDS));
|
this.mqtpAddressMap.put(servicename, queryAddress(servicename).get(3, TimeUnit.SECONDS));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "loadMqtpAddressHealth check " + servicename + " error", e);
|
logger.log(Level.SEVERE, "loadMqtpAddressHealth check " + servicename + " error", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void checkHttpAddressHealth() {
|
protected void checkHttpAddressHealth() {
|
||||||
try {
|
try {
|
||||||
this.httpAddressMap.keySet().stream().forEach(servicename -> {
|
this.httpAddressMap.keySet().stream().forEach(servicename -> {
|
||||||
try {
|
try {
|
||||||
this.httpAddressMap.put(servicename, queryAddress(servicename).get(3, TimeUnit.SECONDS));
|
this.httpAddressMap.put(servicename, queryAddress(servicename).get(3, TimeUnit.SECONDS));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "checkHttpAddressHealth check " + servicename + " error", e);
|
logger.log(Level.SEVERE, "checkHttpAddressHealth check " + servicename + " error", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
logger.log(Level.SEVERE, "checkHttpAddressHealth check error", ex);
|
logger.log(Level.SEVERE, "checkHttpAddressHealth check error", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void checkLocalHealth(final ClusterEntry entry) {
|
protected void checkLocalHealth(final ClusterEntry entry) {
|
||||||
AddressEntry newaddr = new AddressEntry();
|
AddressEntry newaddr = new AddressEntry();
|
||||||
newaddr.addr = entry.address;
|
newaddr.addr = entry.address;
|
||||||
newaddr.nodeid = this.nodeid;
|
newaddr.nodeid = this.nodeid;
|
||||||
newaddr.time = System.currentTimeMillis();
|
newaddr.time = System.currentTimeMillis();
|
||||||
source.hset(entry.checkname, entry.checkid, AddressEntry.class, newaddr);
|
source.hset(entry.checkname, entry.checkid, AddressEntry.class, newaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override //获取MQTP的HTTP远程服务的可用ip列表, key = servicename的后半段
|
@Override //获取MQTP的HTTP远程服务的可用ip列表, key = servicename的后半段
|
||||||
public CompletableFuture<Map<String, Collection<InetSocketAddress>>> queryMqtpAddress(String protocol, String module, String resname) {
|
public CompletableFuture<Map<String, Collection<InetSocketAddress>>> queryMqtpAddress(String protocol, String module, String resname) {
|
||||||
final Map<String, Collection<InetSocketAddress>> rsmap = new ConcurrentHashMap<>();
|
final Map<String, Collection<InetSocketAddress>> rsmap = new ConcurrentHashMap<>();
|
||||||
final String servicenamprefix = generateHttpServiceName(protocol, module, null) + ":";
|
final String servicenamprefix = generateHttpServiceName(protocol, module, null) + ":";
|
||||||
mqtpAddressMap.keySet().stream().filter(k -> k.startsWith(servicenamprefix))
|
mqtpAddressMap.keySet().stream().filter(k -> k.startsWith(servicenamprefix))
|
||||||
.forEach(sn -> rsmap.put(sn.substring(servicenamprefix.length()), mqtpAddressMap.get(sn)));
|
.forEach(sn -> rsmap.put(sn.substring(servicenamprefix.length()), mqtpAddressMap.get(sn)));
|
||||||
return CompletableFuture.completedFuture(rsmap);
|
return CompletableFuture.completedFuture(rsmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override //获取HTTP远程服务的可用ip列表
|
@Override //获取HTTP远程服务的可用ip列表
|
||||||
public CompletableFuture<Collection<InetSocketAddress>> queryHttpAddress(String protocol, String module, String resname) {
|
public CompletableFuture<Collection<InetSocketAddress>> queryHttpAddress(String protocol, String module, String resname) {
|
||||||
final String servicename = generateHttpServiceName(protocol, module, resname);
|
final String servicename = generateHttpServiceName(protocol, module, resname);
|
||||||
Collection<InetSocketAddress> rs = httpAddressMap.get(servicename);
|
Collection<InetSocketAddress> rs = httpAddressMap.get(servicename);
|
||||||
if (rs != null) return CompletableFuture.completedFuture(rs);
|
if (rs != null) return CompletableFuture.completedFuture(rs);
|
||||||
return queryAddress(servicename).thenApply(t -> {
|
return queryAddress(servicename).thenApply(t -> {
|
||||||
httpAddressMap.put(servicename, t);
|
httpAddressMap.put(servicename, t);
|
||||||
return t;
|
return t;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CompletableFuture<Collection<InetSocketAddress>> queryAddress(final ClusterEntry entry) {
|
protected CompletableFuture<Collection<InetSocketAddress>> queryAddress(final ClusterEntry entry) {
|
||||||
return queryAddress(entry.servicename);
|
return queryAddress(entry.servicename);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Collection<InetSocketAddress>> queryAddress(final String servicename) {
|
private CompletableFuture<Collection<InetSocketAddress>> queryAddress(final String servicename) {
|
||||||
final CompletableFuture<Map<String, AddressEntry>> future = source.hmapAsync(servicename, AddressEntry.class, 0, 10000);
|
final CompletableFuture<Map<String, AddressEntry>> future = source.hmapAsync(servicename, AddressEntry.class, 0, 10000);
|
||||||
return future.thenApply(map -> {
|
return future.thenApply(map -> {
|
||||||
final Set<InetSocketAddress> set = new HashSet<>();
|
final Set<InetSocketAddress> set = new HashSet<>();
|
||||||
map.forEach((n, v) -> {
|
map.forEach((n, v) -> {
|
||||||
if (v != null && (System.currentTimeMillis() - v.time) / 1000 < ttls) set.add(v.addr);
|
if (v != null && (System.currentTimeMillis() - v.time) / 1000 < ttls) set.add(v.addr);
|
||||||
});
|
});
|
||||||
return set;
|
return set;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isApplicationHealth() {
|
protected boolean isApplicationHealth() {
|
||||||
String servicename = generateApplicationServiceName();
|
String servicename = generateApplicationServiceName();
|
||||||
String serviceid = generateApplicationServiceId();
|
String serviceid = generateApplicationServiceId();
|
||||||
AddressEntry entry = (AddressEntry) source.hget(servicename, serviceid, AddressEntry.class);
|
AddressEntry entry = (AddressEntry) source.hget(servicename, serviceid, AddressEntry.class);
|
||||||
return entry != null && (System.currentTimeMillis() - entry.time) / 1000 < ttls;
|
return entry != null && (System.currentTimeMillis() - entry.time) / 1000 < ttls;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void checkApplicationHealth() {
|
protected void checkApplicationHealth() {
|
||||||
String checkname = generateApplicationServiceName();
|
String checkname = generateApplicationServiceName();
|
||||||
String checkid = generateApplicationCheckId();
|
String checkid = generateApplicationCheckId();
|
||||||
AddressEntry entry = new AddressEntry();
|
AddressEntry entry = new AddressEntry();
|
||||||
entry.addr = this.appAddress;
|
entry.addr = this.appAddress;
|
||||||
entry.nodeid = this.nodeid;
|
entry.nodeid = this.nodeid;
|
||||||
entry.time = System.currentTimeMillis();
|
entry.time = System.currentTimeMillis();
|
||||||
source.hset(checkname, checkid, AddressEntry.class, entry);
|
source.hset(checkname, checkid, AddressEntry.class, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(Application application) {
|
public void register(Application application) {
|
||||||
if (isApplicationHealth()) throw new RuntimeException("application.nodeid=" + nodeid + " exists in cluster");
|
if (isApplicationHealth()) throw new RuntimeException("application.nodeid=" + nodeid + " exists in cluster");
|
||||||
deregister(application);
|
deregister(application);
|
||||||
|
|
||||||
String serviceid = generateApplicationServiceId();
|
String serviceid = generateApplicationServiceId();
|
||||||
String servicename = generateApplicationServiceName();
|
String servicename = generateApplicationServiceName();
|
||||||
AddressEntry entry = new AddressEntry();
|
AddressEntry entry = new AddressEntry();
|
||||||
entry.addr = this.appAddress;
|
entry.addr = this.appAddress;
|
||||||
entry.nodeid = this.nodeid;
|
entry.nodeid = this.nodeid;
|
||||||
entry.time = System.currentTimeMillis();
|
entry.time = System.currentTimeMillis();
|
||||||
source.hset(servicename, serviceid, AddressEntry.class, entry);
|
source.hset(servicename, serviceid, AddressEntry.class, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deregister(Application application) {
|
public void deregister(Application application) {
|
||||||
String servicename = generateApplicationServiceName();
|
String servicename = generateApplicationServiceName();
|
||||||
source.remove(servicename);
|
source.remove(servicename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ClusterEntry register(NodeServer ns, String protocol, Service service) {
|
protected ClusterEntry register(NodeServer ns, String protocol, Service service) {
|
||||||
deregister(ns, protocol, service, false);
|
deregister(ns, protocol, service, false);
|
||||||
//
|
//
|
||||||
ClusterEntry clusterEntry = new ClusterEntry(ns, protocol, service);
|
ClusterEntry clusterEntry = new ClusterEntry(ns, protocol, service);
|
||||||
AddressEntry entry = new AddressEntry();
|
AddressEntry entry = new AddressEntry();
|
||||||
entry.addr = clusterEntry.address;
|
entry.addr = clusterEntry.address;
|
||||||
entry.nodeid = this.nodeid;
|
entry.nodeid = this.nodeid;
|
||||||
entry.time = System.currentTimeMillis();
|
entry.time = System.currentTimeMillis();
|
||||||
source.hset(clusterEntry.servicename, clusterEntry.serviceid, AddressEntry.class, entry);
|
source.hset(clusterEntry.servicename, clusterEntry.serviceid, AddressEntry.class, entry);
|
||||||
return clusterEntry;
|
return clusterEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void deregister(NodeServer ns, String protocol, Service service) {
|
protected void deregister(NodeServer ns, String protocol, Service service) {
|
||||||
deregister(ns, protocol, service, true);
|
deregister(ns, protocol, service, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void deregister(NodeServer ns, String protocol, Service service, boolean realcanceled) {
|
protected void deregister(NodeServer ns, String protocol, Service service, boolean realcanceled) {
|
||||||
String servicename = generateServiceName(ns, protocol, service);
|
String servicename = generateServiceName(ns, protocol, service);
|
||||||
String serviceid = generateServiceId(ns, protocol, service);
|
String serviceid = generateServiceId(ns, protocol, service);
|
||||||
ClusterEntry currEntry = null;
|
ClusterEntry currEntry = null;
|
||||||
for (final ClusterEntry entry : localEntrys.values()) {
|
for (final ClusterEntry entry : localEntrys.values()) {
|
||||||
if (entry.servicename.equals(servicename) && entry.serviceid.equals(serviceid)) {
|
if (entry.servicename.equals(servicename) && entry.serviceid.equals(serviceid)) {
|
||||||
currEntry = entry;
|
currEntry = entry;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currEntry == null) {
|
if (currEntry == null) {
|
||||||
for (final ClusterEntry entry : remoteEntrys.values()) {
|
for (final ClusterEntry entry : remoteEntrys.values()) {
|
||||||
if (entry.servicename.equals(servicename) && entry.serviceid.equals(serviceid)) {
|
if (entry.servicename.equals(servicename) && entry.serviceid.equals(serviceid)) {
|
||||||
currEntry = entry;
|
currEntry = entry;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
source.hremove(servicename, serviceid);
|
source.hremove(servicename, serviceid);
|
||||||
if (realcanceled && currEntry != null) currEntry.canceled = true;
|
if (realcanceled && currEntry != null) currEntry.canceled = true;
|
||||||
if (!"mqtp".equals(protocol) && currEntry != null && currEntry.submqtp) {
|
if (!"mqtp".equals(protocol) && currEntry != null && currEntry.submqtp) {
|
||||||
deregister(ns, "mqtp", service, realcanceled);
|
deregister(ns, "mqtp", service, realcanceled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String generateApplicationServiceName() {
|
protected String generateApplicationServiceName() {
|
||||||
return "cluster." + super.generateApplicationServiceName();
|
return "cluster." + super.generateApplicationServiceName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String generateServiceName(NodeServer ns, String protocol, Service service) {
|
protected String generateServiceName(NodeServer ns, String protocol, Service service) {
|
||||||
return "cluster." + super.generateServiceName(ns, protocol, service);
|
return "cluster." + super.generateServiceName(ns, protocol, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String generateHttpServiceName(String protocol, String module, String resname) {
|
public String generateHttpServiceName(String protocol, String module, String resname) {
|
||||||
return "cluster." + super.generateHttpServiceName(protocol, module, resname);
|
return "cluster." + super.generateHttpServiceName(protocol, module, resname);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String generateApplicationCheckName() {
|
protected String generateApplicationCheckName() {
|
||||||
return generateApplicationServiceName();
|
return generateApplicationServiceName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String generateApplicationCheckId() {
|
protected String generateApplicationCheckId() {
|
||||||
return generateApplicationServiceId();
|
return generateApplicationServiceId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String generateCheckName(NodeServer ns, String protocol, Service service) {
|
protected String generateCheckName(NodeServer ns, String protocol, Service service) {
|
||||||
return generateServiceName(ns, protocol, service);
|
return generateServiceName(ns, protocol, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String generateCheckId(NodeServer ns, String protocol, Service service) {
|
protected String generateCheckId(NodeServer ns, String protocol, Service service) {
|
||||||
return generateServiceId(ns, protocol, service);
|
return generateServiceId(ns, protocol, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AddressEntry {
|
public static class AddressEntry {
|
||||||
|
|
||||||
public InetSocketAddress addr;
|
public InetSocketAddress addr;
|
||||||
|
|
||||||
public int nodeid;
|
public int nodeid;
|
||||||
|
|
||||||
public long time;
|
public long time;
|
||||||
|
|
||||||
public AddressEntry() {
|
public AddressEntry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AddressEntry refresh() {
|
public AddressEntry refresh() {
|
||||||
this.time = System.currentTimeMillis();
|
this.time = System.currentTimeMillis();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return JsonConvert.root().convertTo(this);
|
return JsonConvert.root().convertTo(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,342 +1,342 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.cluster;
|
package org.redkale.cluster;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import org.redkale.boot.*;
|
import org.redkale.boot.*;
|
||||||
import static org.redkale.boot.Application.*;
|
import static org.redkale.boot.Application.*;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
import org.redkale.mq.MessageMultiConsumer;
|
import org.redkale.mq.MessageMultiConsumer;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.net.http.*;
|
import org.redkale.net.http.*;
|
||||||
import org.redkale.net.sncp.*;
|
import org.redkale.net.sncp.*;
|
||||||
import org.redkale.service.*;
|
import org.redkale.service.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 第三方服务发现管理接口cluster
|
* 第三方服务发现管理接口cluster
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*
|
*
|
||||||
* @since 2.1.0
|
* @since 2.1.0
|
||||||
*/
|
*/
|
||||||
public abstract class ClusterAgent {
|
public abstract class ClusterAgent {
|
||||||
|
|
||||||
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
|
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
|
||||||
|
|
||||||
@Resource(name = RESNAME_APP_NODEID)
|
@Resource(name = RESNAME_APP_NODEID)
|
||||||
protected int nodeid;
|
protected int nodeid;
|
||||||
|
|
||||||
@Resource(name = RESNAME_APP_NAME)
|
@Resource(name = RESNAME_APP_NAME)
|
||||||
protected String appName = "";
|
protected String appName = "";
|
||||||
|
|
||||||
@Resource(name = RESNAME_APP_ADDR)
|
@Resource(name = RESNAME_APP_ADDR)
|
||||||
protected InetSocketAddress appAddress;
|
protected InetSocketAddress appAddress;
|
||||||
|
|
||||||
protected String name;
|
protected String name;
|
||||||
|
|
||||||
protected boolean waits;
|
protected boolean waits;
|
||||||
|
|
||||||
protected String[] protocols; //必须全大写
|
protected String[] protocols; //必须全大写
|
||||||
|
|
||||||
protected int[] ports;
|
protected int[] ports;
|
||||||
|
|
||||||
protected AnyValue config;
|
protected AnyValue config;
|
||||||
|
|
||||||
protected TransportFactory transportFactory;
|
protected TransportFactory transportFactory;
|
||||||
|
|
||||||
protected final ConcurrentHashMap<String, ClusterEntry> localEntrys = new ConcurrentHashMap<>();
|
protected final ConcurrentHashMap<String, ClusterEntry> localEntrys = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
protected final ConcurrentHashMap<String, ClusterEntry> remoteEntrys = new ConcurrentHashMap<>();
|
protected final ConcurrentHashMap<String, ClusterEntry> remoteEntrys = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public void init(AnyValue config) {
|
public void init(AnyValue config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.name = config.getValue("name", "");
|
this.name = config.getValue("name", "");
|
||||||
this.waits = config.getBoolValue("waits", false);
|
this.waits = config.getBoolValue("waits", false);
|
||||||
{
|
{
|
||||||
String ps = config.getValue("protocols", "").toUpperCase();
|
String ps = config.getValue("protocols", "").toUpperCase();
|
||||||
if (ps == null || ps.isEmpty()) ps = "SNCP;HTTP";
|
if (ps == null || ps.isEmpty()) ps = "SNCP;HTTP";
|
||||||
this.protocols = ps.split(";");
|
this.protocols = ps.split(";");
|
||||||
}
|
}
|
||||||
String ts = config.getValue("ports", "");
|
String ts = config.getValue("ports", "");
|
||||||
if (ts != null && !ts.isEmpty()) {
|
if (ts != null && !ts.isEmpty()) {
|
||||||
String[] its = ts.split(";");
|
String[] its = ts.split(";");
|
||||||
List<Integer> list = new ArrayList<>();
|
List<Integer> list = new ArrayList<>();
|
||||||
for (String str : its) {
|
for (String str : its) {
|
||||||
if (str.trim().isEmpty()) continue;
|
if (str.trim().isEmpty()) continue;
|
||||||
list.add(Integer.parseInt(str.trim()));
|
list.add(Integer.parseInt(str.trim()));
|
||||||
}
|
}
|
||||||
if (!list.isEmpty()) this.ports = list.stream().mapToInt(x -> x).toArray();
|
if (!list.isEmpty()) this.ports = list.stream().mapToInt(x -> x).toArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy(AnyValue config) {
|
public void destroy(AnyValue config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//ServiceLoader时判断配置是否符合当前实现类
|
//ServiceLoader时判断配置是否符合当前实现类
|
||||||
public abstract boolean match(AnyValue config);
|
public abstract boolean acceptsConf(AnyValue config);
|
||||||
|
|
||||||
public boolean containsProtocol(String protocol) {
|
public boolean containsProtocol(String protocol) {
|
||||||
if (protocol == null || protocol.isEmpty()) return false;
|
if (protocol == null || protocol.isEmpty()) return false;
|
||||||
return protocols == null || Utility.contains(protocols, protocol.toUpperCase());
|
return protocols == null || Utility.contains(protocols, protocol.toUpperCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsPort(int port) {
|
public boolean containsPort(int port) {
|
||||||
if (ports == null || ports.length == 0) return true;
|
if (ports == null || ports.length == 0) return true;
|
||||||
return Utility.contains(ports, port);
|
return Utility.contains(ports, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void register(Application application);
|
public abstract void register(Application application);
|
||||||
|
|
||||||
public abstract void deregister(Application application);
|
public abstract void deregister(Application application);
|
||||||
|
|
||||||
//注册服务, 在NodeService调用Service.init方法之前调用
|
//注册服务, 在NodeService调用Service.init方法之前调用
|
||||||
public void register(NodeServer ns, String protocol, Set<Service> localServices, Set<Service> remoteServices) {
|
public void register(NodeServer ns, String protocol, Set<Service> localServices, Set<Service> remoteServices) {
|
||||||
if (localServices.isEmpty()) return;
|
if (localServices.isEmpty()) return;
|
||||||
//注册本地模式
|
//注册本地模式
|
||||||
for (Service service : localServices) {
|
for (Service service : localServices) {
|
||||||
if (!canRegister(protocol, service)) continue;
|
if (!canRegister(protocol, service)) continue;
|
||||||
ClusterEntry htentry = register(ns, protocol, service);
|
ClusterEntry htentry = register(ns, protocol, service);
|
||||||
localEntrys.put(htentry.serviceid, htentry);
|
localEntrys.put(htentry.serviceid, htentry);
|
||||||
if (protocol.toLowerCase().startsWith("http")) {
|
if (protocol.toLowerCase().startsWith("http")) {
|
||||||
MessageMultiConsumer mmc = service.getClass().getAnnotation(MessageMultiConsumer.class);
|
MessageMultiConsumer mmc = service.getClass().getAnnotation(MessageMultiConsumer.class);
|
||||||
if (mmc != null) {
|
if (mmc != null) {
|
||||||
ClusterEntry mqentry = register(ns, "mqtp", service);
|
ClusterEntry mqentry = register(ns, "mqtp", service);
|
||||||
localEntrys.put(mqentry.serviceid, mqentry);
|
localEntrys.put(mqentry.serviceid, mqentry);
|
||||||
htentry.submqtp = true;
|
htentry.submqtp = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//远程模式加载IP列表, 只支持SNCP协议
|
//远程模式加载IP列表, 只支持SNCP协议
|
||||||
if (ns.isSNCP()) {
|
if (ns.isSNCP()) {
|
||||||
for (Service service : remoteServices) {
|
for (Service service : remoteServices) {
|
||||||
ClusterEntry entry = new ClusterEntry(ns, protocol, service);
|
ClusterEntry entry = new ClusterEntry(ns, protocol, service);
|
||||||
updateSncpTransport(entry);
|
updateSncpTransport(entry);
|
||||||
remoteEntrys.put(entry.serviceid, entry);
|
remoteEntrys.put(entry.serviceid, entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//注销服务, 在NodeService调用Service.destroy 方法之前调用
|
//注销服务, 在NodeService调用Service.destroy 方法之前调用
|
||||||
public void deregister(NodeServer ns, String protocol, Set<Service> localServices, Set<Service> remoteServices) {
|
public void deregister(NodeServer ns, String protocol, Set<Service> localServices, Set<Service> remoteServices) {
|
||||||
//注销本地模式 远程模式不注册
|
//注销本地模式 远程模式不注册
|
||||||
for (Service service : localServices) {
|
for (Service service : localServices) {
|
||||||
if (!canRegister(protocol, service)) continue;
|
if (!canRegister(protocol, service)) continue;
|
||||||
deregister(ns, protocol, service);
|
deregister(ns, protocol, service);
|
||||||
}
|
}
|
||||||
afterDeregister(ns, protocol);
|
afterDeregister(ns, protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean canRegister(String protocol, Service service) {
|
protected boolean canRegister(String protocol, Service service) {
|
||||||
if ("SNCP".equalsIgnoreCase(protocol) && service.getClass().getAnnotation(Local.class) != null) return false;
|
if ("SNCP".equalsIgnoreCase(protocol) && service.getClass().getAnnotation(Local.class) != null) return false;
|
||||||
AutoLoad al = service.getClass().getAnnotation(AutoLoad.class);
|
AutoLoad al = service.getClass().getAnnotation(AutoLoad.class);
|
||||||
if (al != null && !al.value() && service.getClass().getAnnotation(Local.class) != null) return false;
|
if (al != null && !al.value() && service.getClass().getAnnotation(Local.class) != null) return false;
|
||||||
if (service instanceof WebSocketNode) {
|
if (service instanceof WebSocketNode) {
|
||||||
if (((WebSocketNode) service).getLocalWebSocketEngine() == null) return false;
|
if (((WebSocketNode) service).getLocalWebSocketEngine() == null) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void afterDeregister(NodeServer ns, String protocol) {
|
protected void afterDeregister(NodeServer ns, String protocol) {
|
||||||
if (!this.waits) return;
|
if (!this.waits) return;
|
||||||
int s = intervalCheckSeconds();
|
int s = intervalCheckSeconds();
|
||||||
if (s > 0) { //暂停,弥补其他依赖本进程服务的周期偏差
|
if (s > 0) { //暂停,弥补其他依赖本进程服务的周期偏差
|
||||||
try {
|
try {
|
||||||
Thread.sleep(s * 1000);
|
Thread.sleep(s * 1000);
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
}
|
}
|
||||||
logger.info(this.getClass().getSimpleName() + " wait for " + s * 1000 + "ms after deregister");
|
logger.info(this.getClass().getSimpleName() + " wait for " + s * 1000 + "ms after deregister");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int intervalCheckSeconds() {
|
public int intervalCheckSeconds() {
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取MQTP的HTTP远程服务的可用ip列表, key = servicename的后半段
|
//获取MQTP的HTTP远程服务的可用ip列表, key = servicename的后半段
|
||||||
public abstract CompletableFuture<Map<String, Collection<InetSocketAddress>>> queryMqtpAddress(String protocol, String module, String resname);
|
public abstract CompletableFuture<Map<String, Collection<InetSocketAddress>>> queryMqtpAddress(String protocol, String module, String resname);
|
||||||
|
|
||||||
//获取HTTP远程服务的可用ip列表
|
//获取HTTP远程服务的可用ip列表
|
||||||
public abstract CompletableFuture<Collection<InetSocketAddress>> queryHttpAddress(String protocol, String module, String resname);
|
public abstract CompletableFuture<Collection<InetSocketAddress>> queryHttpAddress(String protocol, String module, String resname);
|
||||||
|
|
||||||
//获取远程服务的可用ip列表
|
//获取远程服务的可用ip列表
|
||||||
protected abstract CompletableFuture<Collection<InetSocketAddress>> queryAddress(ClusterEntry entry);
|
protected abstract CompletableFuture<Collection<InetSocketAddress>> queryAddress(ClusterEntry entry);
|
||||||
|
|
||||||
//注册服务
|
//注册服务
|
||||||
protected abstract ClusterEntry register(NodeServer ns, String protocol, Service service);
|
protected abstract ClusterEntry register(NodeServer ns, String protocol, Service service);
|
||||||
|
|
||||||
//注销服务
|
//注销服务
|
||||||
protected abstract void deregister(NodeServer ns, String protocol, Service service);
|
protected abstract void deregister(NodeServer ns, String protocol, Service service);
|
||||||
|
|
||||||
//格式: protocol:classtype-resourcename
|
//格式: protocol:classtype-resourcename
|
||||||
protected void updateSncpTransport(ClusterEntry entry) {
|
protected void updateSncpTransport(ClusterEntry entry) {
|
||||||
Service service = entry.serviceref.get();
|
Service service = entry.serviceref.get();
|
||||||
if (service == null) return;
|
if (service == null) return;
|
||||||
Collection<InetSocketAddress> addrs = ClusterAgent.this.queryAddress(entry).join();
|
Collection<InetSocketAddress> addrs = ClusterAgent.this.queryAddress(entry).join();
|
||||||
Sncp.updateTransport(service, transportFactory, Sncp.getResourceType(service).getName() + "-" + Sncp.getResourceName(service), entry.netprotocol, entry.address, null, addrs);
|
Sncp.updateTransport(service, transportFactory, Sncp.getResourceType(service).getName() + "-" + Sncp.getResourceName(service), entry.netprotocol, entry.address, null, addrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String generateApplicationServiceName() {
|
protected String generateApplicationServiceName() {
|
||||||
return "application" + (appName == null || appName.isEmpty() ? "" : ("." + appName)) + ".node" + this.nodeid;
|
return "application" + (appName == null || appName.isEmpty() ? "" : ("." + appName)) + ".node" + this.nodeid;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String generateApplicationServiceId() { //与servicename相同
|
protected String generateApplicationServiceId() { //与servicename相同
|
||||||
return generateApplicationServiceName();
|
return generateApplicationServiceName();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String generateApplicationCheckName() {
|
protected String generateApplicationCheckName() {
|
||||||
return "check-" + generateApplicationServiceName();
|
return "check-" + generateApplicationServiceName();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String generateApplicationCheckId() {
|
protected String generateApplicationCheckId() {
|
||||||
return "check-" + generateApplicationServiceId();
|
return "check-" + generateApplicationServiceId();
|
||||||
}
|
}
|
||||||
|
|
||||||
//也会提供给HttpMessageClusterAgent适用
|
//也会提供给HttpMessageClusterAgent适用
|
||||||
public String generateHttpServiceName(String protocol, String module, String resname) {
|
public String generateHttpServiceName(String protocol, String module, String resname) {
|
||||||
return protocol.toLowerCase() + ":" + module + (resname == null || resname.isEmpty() ? "" : ("-" + resname));
|
return protocol.toLowerCase() + ":" + module + (resname == null || resname.isEmpty() ? "" : ("-" + resname));
|
||||||
}
|
}
|
||||||
|
|
||||||
//格式: protocol:classtype-resourcename
|
//格式: protocol:classtype-resourcename
|
||||||
protected String generateServiceName(NodeServer ns, String protocol, Service service) {
|
protected String generateServiceName(NodeServer ns, String protocol, Service service) {
|
||||||
if (protocol.toLowerCase().startsWith("http")) { //HTTP使用RestService.name方式是为了与MessageClient中的module保持一致, 因为HTTP依靠的url中的module,无法知道Service类名
|
if (protocol.toLowerCase().startsWith("http")) { //HTTP使用RestService.name方式是为了与MessageClient中的module保持一致, 因为HTTP依靠的url中的module,无法知道Service类名
|
||||||
String resname = Sncp.getResourceName(service);
|
String resname = Sncp.getResourceName(service);
|
||||||
String module = Rest.getRestModule(service).toLowerCase();
|
String module = Rest.getRestModule(service).toLowerCase();
|
||||||
return protocol.toLowerCase() + ":" + module + (resname.isEmpty() ? "" : ("-" + resname));
|
return protocol.toLowerCase() + ":" + module + (resname.isEmpty() ? "" : ("-" + resname));
|
||||||
}
|
}
|
||||||
if ("mqtp".equalsIgnoreCase(protocol)) {
|
if ("mqtp".equalsIgnoreCase(protocol)) {
|
||||||
MessageMultiConsumer mmc = service.getClass().getAnnotation(MessageMultiConsumer.class);
|
MessageMultiConsumer mmc = service.getClass().getAnnotation(MessageMultiConsumer.class);
|
||||||
String selfmodule = Rest.getRestModule(service).toLowerCase();
|
String selfmodule = Rest.getRestModule(service).toLowerCase();
|
||||||
return protocol.toLowerCase() + ":" + mmc.module() + ":" + selfmodule;
|
return protocol.toLowerCase() + ":" + mmc.module() + ":" + selfmodule;
|
||||||
}
|
}
|
||||||
if (!Sncp.isSncpDyn(service)) return protocol.toLowerCase() + ":" + service.getClass().getName();
|
if (!Sncp.isSncpDyn(service)) return protocol.toLowerCase() + ":" + service.getClass().getName();
|
||||||
String resname = Sncp.getResourceName(service);
|
String resname = Sncp.getResourceName(service);
|
||||||
return protocol.toLowerCase() + ":" + Sncp.getResourceType(service).getName() + (resname.isEmpty() ? "" : ("-" + resname));
|
return protocol.toLowerCase() + ":" + Sncp.getResourceType(service).getName() + (resname.isEmpty() ? "" : ("-" + resname));
|
||||||
}
|
}
|
||||||
|
|
||||||
//格式: protocol:classtype-resourcename:nodeid
|
//格式: protocol:classtype-resourcename:nodeid
|
||||||
protected String generateServiceId(NodeServer ns, String protocol, Service service) {
|
protected String generateServiceId(NodeServer ns, String protocol, Service service) {
|
||||||
return generateServiceName(ns, protocol, service) + ":" + this.nodeid;
|
return generateServiceName(ns, protocol, service) + ":" + this.nodeid;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String generateCheckName(NodeServer ns, String protocol, Service service) {
|
protected String generateCheckName(NodeServer ns, String protocol, Service service) {
|
||||||
return "check-" + generateServiceName(ns, protocol, service);
|
return "check-" + generateServiceName(ns, protocol, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String generateCheckId(NodeServer ns, String protocol, Service service) {
|
protected String generateCheckId(NodeServer ns, String protocol, Service service) {
|
||||||
return "check-" + generateServiceId(ns, protocol, service);
|
return "check-" + generateServiceId(ns, protocol, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ConcurrentHashMap<String, ClusterEntry> getLocalEntrys() {
|
protected ConcurrentHashMap<String, ClusterEntry> getLocalEntrys() {
|
||||||
return localEntrys;
|
return localEntrys;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ConcurrentHashMap<String, ClusterEntry> getRemoteEntrys() {
|
protected ConcurrentHashMap<String, ClusterEntry> getRemoteEntrys() {
|
||||||
return remoteEntrys;
|
return remoteEntrys;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return JsonConvert.root().convertTo(this);
|
return JsonConvert.root().convertTo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TransportFactory getTransportFactory() {
|
public TransportFactory getTransportFactory() {
|
||||||
return transportFactory;
|
return transportFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTransportFactory(TransportFactory transportFactory) {
|
public void setTransportFactory(TransportFactory transportFactory) {
|
||||||
this.transportFactory = transportFactory;
|
this.transportFactory = transportFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getProtocols() {
|
public String[] getProtocols() {
|
||||||
return protocols;
|
return protocols;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProtocols(String[] protocols) {
|
public void setProtocols(String[] protocols) {
|
||||||
this.protocols = protocols;
|
this.protocols = protocols;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[] getPorts() {
|
public int[] getPorts() {
|
||||||
return ports;
|
return ports;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPorts(int[] ports) {
|
public void setPorts(int[] ports) {
|
||||||
this.ports = ports;
|
this.ports = ports;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AnyValue getConfig() {
|
public AnyValue getConfig() {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConfig(AnyValue config) {
|
public void setConfig(AnyValue config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ClusterEntry {
|
public class ClusterEntry {
|
||||||
|
|
||||||
public String serviceid;
|
public String serviceid;
|
||||||
|
|
||||||
public String servicename;
|
public String servicename;
|
||||||
|
|
||||||
public String checkid;
|
public String checkid;
|
||||||
|
|
||||||
public String checkname;
|
public String checkname;
|
||||||
|
|
||||||
public String protocol;
|
public String protocol;
|
||||||
|
|
||||||
public String netprotocol;
|
public String netprotocol;
|
||||||
|
|
||||||
public WeakReference<Service> serviceref;
|
public WeakReference<Service> serviceref;
|
||||||
|
|
||||||
public InetSocketAddress address;
|
public InetSocketAddress address;
|
||||||
|
|
||||||
public boolean canceled;
|
public boolean canceled;
|
||||||
|
|
||||||
public boolean submqtp;
|
public boolean submqtp;
|
||||||
|
|
||||||
public ClusterEntry(NodeServer ns, String protocol, Service service) {
|
public ClusterEntry(NodeServer ns, String protocol, Service service) {
|
||||||
this.serviceid = generateServiceId(ns, protocol, service);
|
this.serviceid = generateServiceId(ns, protocol, service);
|
||||||
this.servicename = generateServiceName(ns, protocol, service);
|
this.servicename = generateServiceName(ns, protocol, service);
|
||||||
this.checkid = generateCheckId(ns, protocol, service);
|
this.checkid = generateCheckId(ns, protocol, service);
|
||||||
this.checkname = generateCheckName(ns, protocol, service);
|
this.checkname = generateCheckName(ns, protocol, service);
|
||||||
this.protocol = protocol;
|
this.protocol = protocol;
|
||||||
InetSocketAddress addr = ns.getSocketAddress();
|
InetSocketAddress addr = ns.getSocketAddress();
|
||||||
String host = addr.getHostString();
|
String host = addr.getHostString();
|
||||||
if ("0.0.0.0".equals(host)) {
|
if ("0.0.0.0".equals(host)) {
|
||||||
host = appAddress.getHostString();
|
host = appAddress.getHostString();
|
||||||
addr = new InetSocketAddress(host, addr.getPort());
|
addr = new InetSocketAddress(host, addr.getPort());
|
||||||
}
|
}
|
||||||
this.address = addr;
|
this.address = addr;
|
||||||
this.serviceref = new WeakReference(service);
|
this.serviceref = new WeakReference(service);
|
||||||
Server server = ns.getServer();
|
Server server = ns.getServer();
|
||||||
this.netprotocol = server instanceof SncpServer ? ((SncpServer) server).getNetprotocol() : Transport.DEFAULT_NETPROTOCOL;
|
this.netprotocol = server instanceof SncpServer ? ((SncpServer) server).getNetprotocol() : Transport.DEFAULT_NETPROTOCOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return JsonConvert.root().convertTo(this);
|
return JsonConvert.root().convertTo(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.cluster;
|
package org.redkale.cluster;
|
||||||
|
|
||||||
import org.redkale.util.AnyValue;
|
import org.redkale.util.AnyValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义的ClusterAgent加载器
|
* 自定义的ClusterAgent加载器
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @since 2.4.0
|
* @since 2.5.0
|
||||||
*/
|
*/
|
||||||
public interface ClusterAgentLoader {
|
public interface ClusterAgentProvider {
|
||||||
|
|
||||||
public boolean match(AnyValue config);
|
public boolean acceptsConf(AnyValue config);
|
||||||
|
|
||||||
public Class<? extends ClusterAgent> agentClass();
|
public Class<? extends ClusterAgent> agentClass();
|
||||||
}
|
}
|
||||||
@@ -1,64 +1,64 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
import org.redkale.convert.Reader.ValueType;
|
import org.redkale.convert.Reader.ValueType;
|
||||||
import static org.redkale.convert.Reader.ValueType.MAP;
|
import static org.redkale.convert.Reader.ValueType.MAP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对不明类型的对象进行反序列化。 <br>
|
* 对不明类型的对象进行反序列化。 <br>
|
||||||
* <b>注意: 目前只支持文本格式</b> <br>
|
* <b>注意: 目前只支持文本格式</b> <br>
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class AnyDecoder implements Decodeable<Reader, Object> {
|
public class AnyDecoder implements Decodeable<Reader, Object> {
|
||||||
|
|
||||||
private static final Type collectionObjectType = new TypeToken<Collection<Object>>() {
|
private static final Type collectionObjectType = new TypeToken<Collection<Object>>() {
|
||||||
}.getType();
|
}.getType();
|
||||||
|
|
||||||
private static final Type mapObjectType = new TypeToken<Map<String, Object>>() {
|
private static final Type mapObjectType = new TypeToken<Map<String, Object>>() {
|
||||||
}.getType();
|
}.getType();
|
||||||
|
|
||||||
private static final Creator<ArrayList> collectionCreator = Creator.create(ArrayList.class);
|
private static final Creator<ArrayList> collectionCreator = Creator.create(ArrayList.class);
|
||||||
|
|
||||||
private static final Creator<HashMap> mapCreator = Creator.create(HashMap.class);
|
private static final Creator<HashMap> mapCreator = Creator.create(HashMap.class);
|
||||||
|
|
||||||
protected final Decodeable<Reader, String> stringDecoder;
|
protected final Decodeable<Reader, String> stringDecoder;
|
||||||
|
|
||||||
protected final CollectionDecoder collectionDecoder;
|
protected final CollectionDecoder collectionDecoder;
|
||||||
|
|
||||||
protected final MapDecoder mapDecoder;
|
protected final MapDecoder mapDecoder;
|
||||||
|
|
||||||
public AnyDecoder(final ConvertFactory factory) {
|
public AnyDecoder(final ConvertFactory factory) {
|
||||||
this.stringDecoder = factory.loadDecoder(String.class);
|
this.stringDecoder = factory.loadDecoder(String.class);
|
||||||
this.collectionDecoder = new CollectionDecoder(factory, collectionObjectType, Object.class, collectionCreator, this);
|
this.collectionDecoder = new CollectionDecoder(factory, collectionObjectType, Object.class, collectionCreator, this);
|
||||||
this.mapDecoder = new MapDecoder(factory, mapObjectType, String.class, Object.class, mapCreator, stringDecoder, this);
|
this.mapDecoder = new MapDecoder(factory, mapObjectType, String.class, Object.class, mapCreator, stringDecoder, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object convertFrom(Reader in) {
|
public Object convertFrom(Reader in) {
|
||||||
ValueType vt = in.readType();
|
ValueType vt = in.readType();
|
||||||
if (vt == null) return null;
|
if (vt == null) return null;
|
||||||
switch (vt) {
|
switch (vt) {
|
||||||
case ARRAY:
|
case ARRAY:
|
||||||
return this.collectionDecoder.convertFrom(in);
|
return this.collectionDecoder.convertFrom(in);
|
||||||
case MAP:
|
case MAP:
|
||||||
return this.mapDecoder.convertFrom(in);
|
return this.mapDecoder.convertFrom(in);
|
||||||
}
|
}
|
||||||
return this.stringDecoder.convertFrom(in);
|
return this.stringDecoder.convertFrom(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return void.class;
|
return void.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,73 +1,73 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对不明类型的对象进行序列化; BSON序列化时将对象的类名写入Writer,JSON则不写入。
|
* 对不明类型的对象进行序列化; BSON序列化时将对象的类名写入Writer,JSON则不写入。
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 序列化的泛型类型
|
* @param <T> 序列化的泛型类型
|
||||||
*/
|
*/
|
||||||
public final class AnyEncoder<T> implements Encodeable<Writer, T> {
|
public final class AnyEncoder<T> implements Encodeable<Writer, T> {
|
||||||
|
|
||||||
final ConvertFactory factory;
|
final ConvertFactory factory;
|
||||||
|
|
||||||
AnyEncoder(ConvertFactory factory) {
|
AnyEncoder(ConvertFactory factory) {
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void convertTo(final Writer out, final T value) {
|
public void convertTo(final Writer out, final T value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.writeClassName(null);
|
out.writeClassName(null);
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
} else {
|
} else {
|
||||||
Class clazz = value.getClass();
|
Class clazz = value.getClass();
|
||||||
if (clazz == Object.class) {
|
if (clazz == Object.class) {
|
||||||
out.writeObjectB(value);
|
out.writeObjectB(value);
|
||||||
out.writeObjectE(value);
|
out.writeObjectE(value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (out.needWriteClassName()) out.writeClassName(factory.getEntityAlias(clazz));
|
if (out.needWriteClassName()) out.writeClassName(factory.getEntityAlias(clazz));
|
||||||
factory.loadEncoder(clazz).convertTo(out, value);
|
factory.loadEncoder(clazz).convertTo(out, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void convertMapTo(final Writer out, final Object... values) {
|
public void convertMapTo(final Writer out, final Object... values) {
|
||||||
if (values == null) {
|
if (values == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
} else {
|
} else {
|
||||||
int count = values.length - values.length % 2;
|
int count = values.length - values.length % 2;
|
||||||
if (out.writeMapB(count / 2, (Encodeable) this, (Encodeable) this, values) < 0) {
|
if (out.writeMapB(count / 2, (Encodeable) this, (Encodeable) this, values) < 0) {
|
||||||
for (int i = 0; i < count; i += 2) {
|
for (int i = 0; i < count; i += 2) {
|
||||||
if (i > 0) out.writeArrayMark();
|
if (i > 0) out.writeArrayMark();
|
||||||
this.convertTo(out, (T) values[i]);
|
this.convertTo(out, (T) values[i]);
|
||||||
out.writeMapMark();
|
out.writeMapMark();
|
||||||
Object val = values[i + 1];
|
Object val = values[i + 1];
|
||||||
if (val instanceof CompletableFuture) {
|
if (val instanceof CompletableFuture) {
|
||||||
this.convertTo(out, (T) ((CompletableFuture) val).join());
|
this.convertTo(out, (T) ((CompletableFuture) val).join());
|
||||||
} else {
|
} else {
|
||||||
this.convertTo(out, (T) val);
|
this.convertTo(out, (T) val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.writeMapE();
|
out.writeMapE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return Object.class;
|
return Object.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
40
src/main/java/org/redkale/convert/AnyValueDecoder.java
Normal file
40
src/main/java/org/redkale/convert/AnyValueDecoder.java
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.redkale.convert;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import org.redkale.util.AnyValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AnyValue的Decoder实现
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @param <R> Reader输入的子类型
|
||||||
|
*
|
||||||
|
* @since 2.5.0
|
||||||
|
*/
|
||||||
|
public class AnyValueDecoder<R extends Reader> implements Decodeable<R, AnyValue> {
|
||||||
|
|
||||||
|
protected final ConvertFactory factory;
|
||||||
|
|
||||||
|
public AnyValueDecoder(final ConvertFactory factory) {
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnyValue convertFrom(R in) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return AnyValue.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
33
src/main/java/org/redkale/convert/AnyValueEncoder.java
Normal file
33
src/main/java/org/redkale/convert/AnyValueEncoder.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.redkale.convert;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import org.redkale.util.AnyValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AnyValue的Encoder实现
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @param <W> Writer输出的子类
|
||||||
|
*
|
||||||
|
* @since 2.5.0
|
||||||
|
*/
|
||||||
|
public class AnyValueEncoder<W extends Writer> implements Encodeable<W, AnyValue> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void convertTo(W out, AnyValue value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return AnyValue.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,144 +1,144 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数组的反序列化操作类 <br>
|
* 数组的反序列化操作类 <br>
|
||||||
* 对象数组的反序列化,不包含int[]、long[]这样的primitive class数组。 <br>
|
* 对象数组的反序列化,不包含int[]、long[]这样的primitive class数组。 <br>
|
||||||
* 支持一定程度的泛型。 <br>
|
* 支持一定程度的泛型。 <br>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 反解析的数组元素类型
|
* @param <T> 反解析的数组元素类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
public class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
||||||
|
|
||||||
protected final Type type;
|
protected final Type type;
|
||||||
|
|
||||||
protected final Type componentType;
|
protected final Type componentType;
|
||||||
|
|
||||||
protected final Class componentClass;
|
protected final Class componentClass;
|
||||||
|
|
||||||
protected final Decodeable<Reader, T> componentDecoder;
|
protected final Decodeable<Reader, T> componentDecoder;
|
||||||
|
|
||||||
protected volatile boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
protected final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
public ArrayDecoder(final ConvertFactory factory, final Type type) {
|
public ArrayDecoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
try {
|
try {
|
||||||
if (type instanceof GenericArrayType) {
|
if (type instanceof GenericArrayType) {
|
||||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
Type t = ((GenericArrayType) type).getGenericComponentType();
|
||||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
||||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
||||||
this.componentType = ((Class) type).getComponentType();
|
this.componentType = ((Class) type).getComponentType();
|
||||||
} else {
|
} else {
|
||||||
throw new ConvertException("(" + type + ") is not a array type");
|
throw new ConvertException("(" + type + ") is not a array type");
|
||||||
}
|
}
|
||||||
if (this.componentType instanceof ParameterizedType) {
|
if (this.componentType instanceof ParameterizedType) {
|
||||||
this.componentClass = (Class) ((ParameterizedType) this.componentType).getRawType();
|
this.componentClass = (Class) ((ParameterizedType) this.componentType).getRawType();
|
||||||
} else {
|
} else {
|
||||||
this.componentClass = (Class) this.componentType;
|
this.componentClass = (Class) this.componentType;
|
||||||
}
|
}
|
||||||
factory.register(type, this);
|
factory.register(type, this);
|
||||||
this.componentDecoder = factory.loadDecoder(this.componentType);
|
this.componentDecoder = factory.loadDecoder(this.componentType);
|
||||||
} finally {
|
} finally {
|
||||||
inited = true;
|
inited = true;
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
lock.notifyAll();
|
lock.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T[] convertFrom(Reader in) {
|
public T[] convertFrom(Reader in) {
|
||||||
return convertFrom(in, null);
|
return convertFrom(in, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T[] convertFrom(Reader in, DeMember member) {
|
public T[] convertFrom(Reader in, DeMember member) {
|
||||||
byte[] typevals = new byte[1];
|
byte[] typevals = new byte[1];
|
||||||
int len = in.readArrayB(member, typevals, componentDecoder);
|
int len = in.readArrayB(member, typevals, componentDecoder);
|
||||||
int contentLength = -1;
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
contentLength = in.readMemberContentLength(member, componentDecoder);
|
contentLength = in.readMemberContentLength(member, componentDecoder);
|
||||||
len = Reader.SIGN_NOLENGTH;
|
len = Reader.SIGN_NOLENGTH;
|
||||||
}
|
}
|
||||||
if (this.componentDecoder == null) {
|
if (this.componentDecoder == null) {
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
lock.wait();
|
lock.wait();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
|
final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
|
||||||
final List<T> result = new ArrayList();
|
final List<T> result = new ArrayList();
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
int startPosition = in.position();
|
int startPosition = in.position();
|
||||||
while (hasNext(in, member, startPosition, contentLength, first)) {
|
while (hasNext(in, member, startPosition, contentLength, first)) {
|
||||||
Reader itemReader = getItemReader(in, member, first);
|
Reader itemReader = getItemReader(in, member, first);
|
||||||
if (itemReader == null) break;
|
if (itemReader == null) break;
|
||||||
result.add(readMemberValue(itemReader, member, localdecoder, first));
|
result.add(readMemberValue(itemReader, member, localdecoder, first));
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
result.add(localdecoder.convertFrom(in));
|
result.add(localdecoder.convertFrom(in));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
in.readArrayE();
|
in.readArrayE();
|
||||||
T[] rs = (T[]) Array.newInstance((Class) this.componentClass, result.size());
|
T[] rs = (T[]) Array.newInstance((Class) this.componentClass, result.size());
|
||||||
return result.toArray(rs);
|
return result.toArray(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
||||||
return in.hasNext(startPosition, contentLength);
|
return in.hasNext(startPosition, contentLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||||
return decoder;
|
return decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
|
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
|
||||||
if (in == null) return null;
|
if (in == null) return null;
|
||||||
return decoder.convertFrom(in);
|
return decoder.convertFrom(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", decoder:" + this.componentDecoder + "}";
|
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", decoder:" + this.componentDecoder + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getComponentType() {
|
public Type getComponentType() {
|
||||||
return componentType;
|
return componentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Decodeable<Reader, T> getComponentDecoder() {
|
public Decodeable<Reader, T> getComponentDecoder() {
|
||||||
return componentDecoder;
|
return componentDecoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,133 +1,133 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数组的序列化操作类 <br>
|
* 数组的序列化操作类 <br>
|
||||||
* 对象数组的序列化,不包含int[]、long[]这样的primitive class数组。 <br>
|
* 对象数组的序列化,不包含int[]、long[]这样的primitive class数组。 <br>
|
||||||
* 支持一定程度的泛型。 <br>
|
* 支持一定程度的泛型。 <br>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 序列化的数组元素类型
|
* @param <T> 序列化的数组元素类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
public class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
||||||
|
|
||||||
protected final Type type;
|
protected final Type type;
|
||||||
|
|
||||||
protected final Type componentType;
|
protected final Type componentType;
|
||||||
|
|
||||||
protected final Encodeable anyEncoder;
|
protected final Encodeable anyEncoder;
|
||||||
|
|
||||||
protected final Encodeable<Writer, Object> componentEncoder;
|
protected final Encodeable<Writer, Object> componentEncoder;
|
||||||
|
|
||||||
protected final boolean subtypefinal;
|
protected final boolean subtypefinal;
|
||||||
|
|
||||||
protected volatile boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
protected final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
public ArrayEncoder(final ConvertFactory factory, final Type type) {
|
public ArrayEncoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
try {
|
try {
|
||||||
if (type instanceof GenericArrayType) {
|
if (type instanceof GenericArrayType) {
|
||||||
Type t = ((GenericArrayType) type).getGenericComponentType();
|
Type t = ((GenericArrayType) type).getGenericComponentType();
|
||||||
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
this.componentType = t instanceof TypeVariable ? Object.class : t;
|
||||||
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
} else if ((type instanceof Class) && ((Class) type).isArray()) {
|
||||||
this.componentType = ((Class) type).getComponentType();
|
this.componentType = ((Class) type).getComponentType();
|
||||||
} else {
|
} else {
|
||||||
throw new ConvertException("(" + type + ") is not a array type");
|
throw new ConvertException("(" + type + ") is not a array type");
|
||||||
}
|
}
|
||||||
factory.register(type, this);
|
factory.register(type, this);
|
||||||
this.componentEncoder = factory.loadEncoder(this.componentType);
|
this.componentEncoder = factory.loadEncoder(this.componentType);
|
||||||
this.anyEncoder = factory.getAnyEncoder();
|
this.anyEncoder = factory.getAnyEncoder();
|
||||||
this.subtypefinal = (this.componentType instanceof Class) && Modifier.isFinal(((Class) this.componentType).getModifiers());
|
this.subtypefinal = (this.componentType instanceof Class) && Modifier.isFinal(((Class) this.componentType).getModifiers());
|
||||||
} finally {
|
} finally {
|
||||||
inited = true;
|
inited = true;
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
lock.notifyAll();
|
lock.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void convertTo(Writer out, T[] value) {
|
public void convertTo(Writer out, T[] value) {
|
||||||
convertTo(out, null, value);
|
convertTo(out, null, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void convertTo(Writer out, EnMember member, T[] value) {
|
public void convertTo(Writer out, EnMember member, T[] value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int iMax = value.length - 1;
|
int iMax = value.length - 1;
|
||||||
if (iMax == -1) {
|
if (iMax == -1) {
|
||||||
out.writeArrayB(0, this, componentEncoder, value);
|
out.writeArrayB(0, this, componentEncoder, value);
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.componentEncoder == null) {
|
if (this.componentEncoder == null) {
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
lock.wait();
|
lock.wait();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Encodeable<Writer, Object> itemEncoder = this.componentEncoder;
|
Encodeable<Writer, Object> itemEncoder = this.componentEncoder;
|
||||||
if (subtypefinal) {
|
if (subtypefinal) {
|
||||||
if (out.writeArrayB(value.length, this, itemEncoder, value) < 0) {
|
if (out.writeArrayB(value.length, this, itemEncoder, value) < 0) {
|
||||||
for (int i = 0;; i++) {
|
for (int i = 0;; i++) {
|
||||||
writeMemberValue(out, member, itemEncoder, value[i], i);
|
writeMemberValue(out, member, itemEncoder, value[i], i);
|
||||||
if (i == iMax) break;
|
if (i == iMax) break;
|
||||||
out.writeArrayMark();
|
out.writeArrayMark();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (out.writeArrayB(value.length, this, itemEncoder, value) < 0) {
|
if (out.writeArrayB(value.length, this, itemEncoder, value) < 0) {
|
||||||
final Type comp = this.componentType;
|
final Type comp = this.componentType;
|
||||||
for (int i = 0;; i++) {
|
for (int i = 0;; i++) {
|
||||||
Object v = value[i];
|
Object v = value[i];
|
||||||
writeMemberValue(out, member, ((v != null && (v.getClass() == comp || out.specify() == comp)) ? itemEncoder : anyEncoder), v, i);
|
writeMemberValue(out, member, ((v != null && (v.getClass() == comp || out.specify() == comp)) ? itemEncoder : anyEncoder), v, i);
|
||||||
if (i == iMax) break;
|
if (i == iMax) break;
|
||||||
out.writeArrayMark();
|
out.writeArrayMark();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeMemberValue(Writer out, EnMember member, Encodeable<Writer, Object> encoder, Object value, int index) {
|
protected void writeMemberValue(Writer out, EnMember member, Encodeable<Writer, Object> encoder, Object value, int index) {
|
||||||
encoder.convertTo(out, value);
|
encoder.convertTo(out, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", encoder:" + this.componentEncoder + "}";
|
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", encoder:" + this.componentEncoder + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getComponentType() {
|
public Type getComponentType() {
|
||||||
return componentType;
|
return componentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Encodeable<Writer, Object> getComponentEncoder() {
|
public Encodeable<Writer, Object> getComponentEncoder() {
|
||||||
return componentEncoder;
|
return componentEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,35 +1,35 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 二进制序列化/反序列化操作类
|
* 二进制序列化/反序列化操作类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类
|
* @param <R> Reader输入的子类
|
||||||
* @param <W> Writer输出的子类
|
* @param <W> Writer输出的子类
|
||||||
*/
|
*/
|
||||||
public abstract class BinaryConvert<R extends Reader, W extends Writer> extends Convert<R, W> {
|
public abstract class BinaryConvert<R extends Reader, W extends Writer> extends Convert<R, W> {
|
||||||
|
|
||||||
protected BinaryConvert(ConvertFactory<R, W> factory) {
|
protected BinaryConvert(ConvertFactory<R, W> factory) {
|
||||||
super(factory);
|
super(factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean isBinary() {
|
public final boolean isBinary() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract byte[] convertTo(final Object value);
|
public abstract byte[] convertTo(final Object value);
|
||||||
|
|
||||||
public abstract byte[] convertTo(final Type type, final Object value);
|
public abstract byte[] convertTo(final Type type, final Object value);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,149 +1,149 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import org.redkale.util.Creator;
|
import org.redkale.util.Creator;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection的反序列化操作类 <br>
|
* Collection的反序列化操作类 <br>
|
||||||
* 支持一定程度的泛型。 <br>
|
* 支持一定程度的泛型。 <br>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 反解析的集合元素类型
|
* @param <T> 反解析的集合元素类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class CollectionDecoder<T> implements Decodeable<Reader, Collection<T>> {
|
public class CollectionDecoder<T> implements Decodeable<Reader, Collection<T>> {
|
||||||
|
|
||||||
protected final Type type;
|
protected final Type type;
|
||||||
|
|
||||||
protected final Type componentType;
|
protected final Type componentType;
|
||||||
|
|
||||||
protected Creator<Collection<T>> creator;
|
protected Creator<Collection<T>> creator;
|
||||||
|
|
||||||
protected final Decodeable<Reader, T> componentDecoder;
|
protected final Decodeable<Reader, T> componentDecoder;
|
||||||
|
|
||||||
protected volatile boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
protected final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
public CollectionDecoder(final ConvertFactory factory, final Type type) {
|
public CollectionDecoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
try {
|
try {
|
||||||
if (type instanceof ParameterizedType) {
|
if (type instanceof ParameterizedType) {
|
||||||
final ParameterizedType pt = (ParameterizedType) type;
|
final ParameterizedType pt = (ParameterizedType) type;
|
||||||
this.componentType = pt.getActualTypeArguments()[0];
|
this.componentType = pt.getActualTypeArguments()[0];
|
||||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
this.creator = factory.loadCreator((Class) pt.getRawType());
|
||||||
factory.register(type, this);
|
factory.register(type, this);
|
||||||
this.componentDecoder = factory.loadDecoder(this.componentType);
|
this.componentDecoder = factory.loadDecoder(this.componentType);
|
||||||
} else if (factory.isReversible()) {
|
} else if (factory.isReversible()) {
|
||||||
this.componentType = Object.class;
|
this.componentType = Object.class;
|
||||||
this.creator = factory.loadCreator(type instanceof Class ? (Class) type : Collection.class);
|
this.creator = factory.loadCreator(type instanceof Class ? (Class) type : Collection.class);
|
||||||
factory.register(type, this);
|
factory.register(type, this);
|
||||||
this.componentDecoder = factory.loadDecoder(this.componentType);
|
this.componentDecoder = factory.loadDecoder(this.componentType);
|
||||||
} else {
|
} else {
|
||||||
throw new ConvertException("CollectionDecoder not support the type (" + type + ")");
|
throw new ConvertException("CollectionDecoder not support the type (" + type + ")");
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
inited = true;
|
inited = true;
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
lock.notifyAll();
|
lock.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//仅供类似JsonAnyDecoder这种动态创建使用, 不得调用 factory.register
|
//仅供类似JsonAnyDecoder这种动态创建使用, 不得调用 factory.register
|
||||||
public CollectionDecoder(final ConvertFactory factory, Type type, Type componentType,
|
public CollectionDecoder(final ConvertFactory factory, Type type, Type componentType,
|
||||||
Creator<Collection<T>> creator, final Decodeable<Reader, T> componentDecoder) {
|
Creator<Collection<T>> creator, final Decodeable<Reader, T> componentDecoder) {
|
||||||
Objects.requireNonNull(componentDecoder);
|
Objects.requireNonNull(componentDecoder);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.componentType = componentType;
|
this.componentType = componentType;
|
||||||
this.creator = creator;
|
this.creator = creator;
|
||||||
this.componentDecoder = componentDecoder;
|
this.componentDecoder = componentDecoder;
|
||||||
this.inited = true;
|
this.inited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<T> convertFrom(Reader in) {
|
public Collection<T> convertFrom(Reader in) {
|
||||||
return convertFrom(in, null);
|
return convertFrom(in, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<T> convertFrom(Reader in, DeMember member) {
|
public Collection<T> convertFrom(Reader in, DeMember member) {
|
||||||
byte[] typevals = new byte[1];
|
byte[] typevals = new byte[1];
|
||||||
int len = in.readArrayB(member, typevals, componentDecoder);
|
int len = in.readArrayB(member, typevals, componentDecoder);
|
||||||
int contentLength = -1;
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
contentLength = in.readMemberContentLength(member, componentDecoder);
|
contentLength = in.readMemberContentLength(member, componentDecoder);
|
||||||
len = Reader.SIGN_NOLENGTH;
|
len = Reader.SIGN_NOLENGTH;
|
||||||
}
|
}
|
||||||
if (this.componentDecoder == null) {
|
if (this.componentDecoder == null) {
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
lock.wait();
|
lock.wait();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
|
final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
|
||||||
final Collection<T> result = this.creator.create();
|
final Collection<T> result = this.creator.create();
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
int startPosition = in.position();
|
int startPosition = in.position();
|
||||||
while (hasNext(in, member, startPosition, contentLength, first)) {
|
while (hasNext(in, member, startPosition, contentLength, first)) {
|
||||||
Reader itemReader = getItemReader(in, member, first);
|
Reader itemReader = getItemReader(in, member, first);
|
||||||
if (itemReader == null) break;
|
if (itemReader == null) break;
|
||||||
result.add(readMemberValue(itemReader, member, localdecoder, first));
|
result.add(readMemberValue(itemReader, member, localdecoder, first));
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
result.add(localdecoder.convertFrom(in));
|
result.add(localdecoder.convertFrom(in));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
in.readArrayE();
|
in.readArrayE();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
||||||
return in.hasNext(startPosition, contentLength);
|
return in.hasNext(startPosition, contentLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||||
return decoder;
|
return decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
|
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
|
||||||
if (in == null) return null;
|
if (in == null) return null;
|
||||||
return decoder.convertFrom(in);
|
return decoder.convertFrom(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getComponentType() {
|
public Type getComponentType() {
|
||||||
return componentType;
|
return componentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Decodeable<Reader, T> getComponentDecoder() {
|
public Decodeable<Reader, T> getComponentDecoder() {
|
||||||
return componentDecoder;
|
return componentDecoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,111 +1,111 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection的序列化操作类 <br>
|
* Collection的序列化操作类 <br>
|
||||||
* 支持一定程度的泛型。 <br>
|
* 支持一定程度的泛型。 <br>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <T> 序列化的集合元素类型
|
* @param <T> 序列化的集合元素类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class CollectionEncoder<T> implements Encodeable<Writer, Collection<T>> {
|
public class CollectionEncoder<T> implements Encodeable<Writer, Collection<T>> {
|
||||||
|
|
||||||
protected final Type type;
|
protected final Type type;
|
||||||
|
|
||||||
protected final Encodeable<Writer, Object> componentEncoder;
|
protected final Encodeable<Writer, Object> componentEncoder;
|
||||||
|
|
||||||
protected volatile boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
protected final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
public CollectionEncoder(final ConvertFactory factory, final Type type) {
|
public CollectionEncoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
try {
|
try {
|
||||||
if (type instanceof ParameterizedType) {
|
if (type instanceof ParameterizedType) {
|
||||||
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||||
if (t instanceof TypeVariable) {
|
if (t instanceof TypeVariable) {
|
||||||
this.componentEncoder = factory.getAnyEncoder();
|
this.componentEncoder = factory.getAnyEncoder();
|
||||||
} else {
|
} else {
|
||||||
this.componentEncoder = factory.loadEncoder(t);
|
this.componentEncoder = factory.loadEncoder(t);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.componentEncoder = factory.getAnyEncoder();
|
this.componentEncoder = factory.getAnyEncoder();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
inited = true;
|
inited = true;
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
lock.notifyAll();
|
lock.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void convertTo(Writer out, Collection<T> value) {
|
public void convertTo(Writer out, Collection<T> value) {
|
||||||
convertTo(out, null, value);
|
convertTo(out, null, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void convertTo(Writer out, EnMember member, Collection<T> value) {
|
public void convertTo(Writer out, EnMember member, Collection<T> value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value.isEmpty()) {
|
if (value.isEmpty()) {
|
||||||
out.writeArrayB(0, this, componentEncoder, value);
|
out.writeArrayB(0, this, componentEncoder, value);
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.componentEncoder == null) {
|
if (this.componentEncoder == null) {
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
lock.wait();
|
lock.wait();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (out.writeArrayB(value.size(), this, componentEncoder, value) < 0) {
|
if (out.writeArrayB(value.size(), this, componentEncoder, value) < 0) {
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (Object v : value) {
|
for (Object v : value) {
|
||||||
if (!first) out.writeArrayMark();
|
if (!first) out.writeArrayMark();
|
||||||
writeMemberValue(out, member, v, first);
|
writeMemberValue(out, member, v, first);
|
||||||
if (first) first = false;
|
if (first) first = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeMemberValue(Writer out, EnMember member, Object value, boolean first) {
|
protected void writeMemberValue(Writer out, EnMember member, Object value, boolean first) {
|
||||||
componentEncoder.convertTo(out, value);
|
componentEncoder.convertTo(out, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.getClass().getSimpleName() + "{componentType:" + this.type + ", encoder:" + this.componentEncoder + "}";
|
return this.getClass().getSimpleName() + "{componentType:" + this.type + ", encoder:" + this.componentEncoder + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Encodeable<Writer, Object> getComponentEncoder() {
|
public Encodeable<Writer, Object> getComponentEncoder() {
|
||||||
return componentEncoder;
|
return componentEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getComponentType() {
|
public Type getComponentType() {
|
||||||
return componentEncoder == null ? null : componentEncoder.getType();
|
return componentEncoder == null ? null : componentEncoder.getType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,76 +1,80 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 序列化/反序列化操作类
|
* 序列化/反序列化操作类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类
|
* @param <R> Reader输入的子类
|
||||||
* @param <W> Writer输出的子类
|
* @param <W> Writer输出的子类
|
||||||
*/
|
*/
|
||||||
public abstract class Convert<R extends Reader, W extends Writer> {
|
public abstract class Convert<R extends Reader, W extends Writer> {
|
||||||
|
|
||||||
protected final ConvertFactory<R, W> factory;
|
protected final ConvertFactory<R, W> factory;
|
||||||
|
|
||||||
protected Convert(ConvertFactory<R, W> factory) {
|
protected Convert(ConvertFactory<R, W> factory) {
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertFactory<R, W> getFactory() {
|
public ConvertFactory<R, W> getFactory() {
|
||||||
return this.factory;
|
return this.factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <S extends W> S configWrite(S writer) {
|
protected <S extends W> S configWrite(S writer) {
|
||||||
return writer;
|
return writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <S extends W> S fieldFunc(S writer, BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
|
protected <S extends W> S fieldFunc(S writer, BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
|
||||||
writer.objFieldFunc = objFieldFunc;
|
writer.objFieldFunc = objFieldFunc;
|
||||||
writer.objExtFunc = objExtFunc;
|
writer.objExtFunc = objExtFunc;
|
||||||
return writer;
|
return writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Convert<R, W> newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc);
|
public abstract Convert<R, W> newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc);
|
||||||
|
|
||||||
public abstract Convert<R, W> newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc);
|
public abstract Convert<R, W> newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc, Function<Object, ConvertField[]> objExtFunc);
|
||||||
|
|
||||||
public abstract boolean isBinary();
|
public abstract boolean isBinary();
|
||||||
|
|
||||||
public abstract <T> T convertFrom(final Type type, final byte[] bytes);
|
public abstract <T> T convertFrom(final Type type, final byte[] bytes);
|
||||||
|
|
||||||
//@since 2.2.0
|
//@since 2.2.0
|
||||||
public abstract <T> T convertFrom(final Type type, final byte[] bytes, final int offset, final int length);
|
public abstract <T> T convertFrom(final Type type, final byte[] bytes, final int offset, final int length);
|
||||||
|
|
||||||
public abstract <T> T convertFrom(final Type type, final ByteBuffer... buffers);
|
public abstract <T> T convertFrom(final Type type, final ByteBuffer... buffers);
|
||||||
|
|
||||||
public abstract <T> T convertFrom(final Type type, final ConvertMask mask, final ByteBuffer... buffers);
|
public abstract <T> T convertFrom(final Type type, final ConvertMask mask, final ByteBuffer... buffers);
|
||||||
|
|
||||||
public abstract byte[] convertToBytes(final Object value);
|
public abstract void convertTo(final W writer, final Object value);
|
||||||
|
|
||||||
public abstract byte[] convertToBytes(final Type type, final Object value);
|
public abstract void convertTo(final W writer, final Type type, final Object value);
|
||||||
|
|
||||||
public abstract void convertToBytes(final Object value, final ConvertBytesHandler handler);
|
public abstract byte[] convertToBytes(final Object value);
|
||||||
|
|
||||||
public abstract void convertToBytes(final Type type, final Object value, final ConvertBytesHandler handler);
|
public abstract byte[] convertToBytes(final Type type, final Object value);
|
||||||
|
|
||||||
public abstract void convertToBytes(final ByteArray array, final Object value);
|
public abstract void convertToBytes(final Object value, final ConvertBytesHandler handler);
|
||||||
|
|
||||||
public abstract void convertToBytes(final ByteArray array, final Type type, final Object value);
|
public abstract void convertToBytes(final Type type, final Object value, final ConvertBytesHandler handler);
|
||||||
|
|
||||||
public abstract ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Object value);
|
public abstract void convertToBytes(final ByteArray array, final Object value);
|
||||||
|
|
||||||
public abstract ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value);
|
public abstract void convertToBytes(final ByteArray array, final Type type, final Object value);
|
||||||
|
|
||||||
}
|
public abstract ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Object value);
|
||||||
|
|
||||||
|
public abstract ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* convertToBytes系列的方法的回调
|
* convertToBytes系列的方法的回调
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*
|
*
|
||||||
* @since 2.3.0
|
* @since 2.3.0
|
||||||
*/
|
*/
|
||||||
public interface ConvertBytesHandler {
|
public interface ConvertBytesHandler {
|
||||||
|
|
||||||
<A> void completed(byte[] bs, int offset, int length, Consumer<A> callback, A attachment);
|
<A> void completed(byte[] bs, int offset, int length, Consumer<A> callback, A attachment);
|
||||||
}
|
}
|
||||||
@@ -1,71 +1,71 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
import static java.lang.annotation.ElementType.*;
|
import static java.lang.annotation.ElementType.*;
|
||||||
import static java.lang.annotation.RetentionPolicy.*;
|
import static java.lang.annotation.RetentionPolicy.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 依附在setter、getter方法、字段进行简单的配置
|
* 依附在setter、getter方法、字段进行简单的配置
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@Inherited
|
@Inherited
|
||||||
@Documented
|
@Documented
|
||||||
@Target({METHOD, FIELD})
|
@Target({METHOD, FIELD})
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
@Repeatable(ConvertColumn.ConvertColumns.class)
|
@Repeatable(ConvertColumn.ConvertColumns.class)
|
||||||
public @interface ConvertColumn {
|
public @interface ConvertColumn {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 给字段取个别名
|
* 给字段取个别名
|
||||||
*
|
*
|
||||||
* @return 字段别名
|
* @return 字段别名
|
||||||
*/
|
*/
|
||||||
String name() default "";
|
String name() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 给字段取个序号ID,值小靠前
|
* 给字段取个序号ID,值小靠前
|
||||||
*
|
*
|
||||||
* @return 字段排序ID
|
* @return 字段排序ID
|
||||||
*/
|
*/
|
||||||
int index() default 0;
|
int index() default 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析/序列化时是否屏蔽该字段
|
* 解析/序列化时是否屏蔽该字段
|
||||||
*
|
*
|
||||||
* @return 是否屏蔽该字段
|
* @return 是否屏蔽该字段
|
||||||
*/
|
*/
|
||||||
boolean ignore() default false;
|
boolean ignore() default false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析/序列化定制化的TYPE
|
* 解析/序列化定制化的TYPE
|
||||||
*
|
*
|
||||||
* @return JSON or BSON or ALL
|
* @return JSON or BSON or ALL
|
||||||
*/
|
*/
|
||||||
ConvertType type() default ConvertType.ALL;
|
ConvertType type() default ConvertType.ALL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConvertColumn 的多用类
|
* ConvertColumn 的多用类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@Inherited
|
@Inherited
|
||||||
@Documented
|
@Documented
|
||||||
@Target({METHOD, FIELD})
|
@Target({METHOD, FIELD})
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public static @interface ConvertColumns {
|
public static @interface ConvertColumns {
|
||||||
|
|
||||||
ConvertColumn[] value();
|
ConvertColumn[] value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,97 +1,97 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConvertColumn 对应的实体类
|
* ConvertColumn 对应的实体类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public final class ConvertColumnEntry {
|
public final class ConvertColumnEntry {
|
||||||
|
|
||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
private String name = "";
|
private String name = "";
|
||||||
|
|
||||||
private boolean ignore;
|
private boolean ignore;
|
||||||
|
|
||||||
private ConvertType convertType;
|
private ConvertType convertType;
|
||||||
|
|
||||||
public ConvertColumnEntry() {
|
public ConvertColumnEntry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertColumnEntry(ConvertColumn column) {
|
public ConvertColumnEntry(ConvertColumn column) {
|
||||||
if (column == null) return;
|
if (column == null) return;
|
||||||
this.name = column.name();
|
this.name = column.name();
|
||||||
this.index = column.index();
|
this.index = column.index();
|
||||||
this.ignore = column.ignore();
|
this.ignore = column.ignore();
|
||||||
this.convertType = column.type();
|
this.convertType = column.type();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertColumnEntry(String name) {
|
public ConvertColumnEntry(String name) {
|
||||||
this(name, false);
|
this(name, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertColumnEntry(String name, boolean ignore) {
|
public ConvertColumnEntry(String name, boolean ignore) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.ignore = ignore;
|
this.ignore = ignore;
|
||||||
this.convertType = ConvertType.ALL;
|
this.convertType = ConvertType.ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertColumnEntry(String name, boolean ignore, ConvertType convertType) {
|
public ConvertColumnEntry(String name, boolean ignore, ConvertType convertType) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.ignore = ignore;
|
this.ignore = ignore;
|
||||||
this.convertType = convertType;
|
this.convertType = convertType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertColumnEntry(String name, int index, boolean ignore, ConvertType convertType) {
|
public ConvertColumnEntry(String name, int index, boolean ignore, ConvertType convertType) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.ignore = ignore;
|
this.ignore = ignore;
|
||||||
this.convertType = convertType;
|
this.convertType = convertType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String name() {
|
public String name() {
|
||||||
return name == null ? "" : name;
|
return name == null ? "" : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean ignore() {
|
public boolean ignore() {
|
||||||
return ignore;
|
return ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIgnore(boolean ignore) {
|
public void setIgnore(boolean ignore) {
|
||||||
this.ignore = ignore;
|
this.ignore = ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertType type() {
|
public ConvertType type() {
|
||||||
return convertType == null ? ConvertType.ALL : convertType;
|
return convertType == null ? ConvertType.ALL : convertType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConvertType(ConvertType convertType) {
|
public void setConvertType(ConvertType convertType) {
|
||||||
this.convertType = convertType;
|
this.convertType = convertType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getIndex() {
|
public int getIndex() {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIndex(int index) {
|
public void setIndex(int index) {
|
||||||
this.index = index;
|
this.index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ConvertColumnEntry{" + "index=" + index + ", name=" + name + ", ignore=" + ignore + ", convertType=" + convertType + '}';
|
return "ConvertColumnEntry{" + "index=" + index + ", name=" + name + ", ignore=" + ignore + ", convertType=" + convertType + '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,47 +1,47 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
import static java.lang.annotation.ElementType.*;
|
import static java.lang.annotation.ElementType.*;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 序列化时永久禁用该字段, 与ConvertColumn.ignore()的区别在于: ConvertDisabled不能通过ConvertEntity来解禁
|
* 序列化时永久禁用该字段, 与ConvertColumn.ignore()的区别在于: ConvertDisabled不能通过ConvertEntity来解禁
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@Target({METHOD, FIELD})
|
@Target({METHOD, FIELD})
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public @interface ConvertDisabled {
|
public @interface ConvertDisabled {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析/序列化定制化的TYPE
|
* 解析/序列化定制化的TYPE
|
||||||
*
|
*
|
||||||
* @return JSON or BSON or ALL
|
* @return JSON or BSON or ALL
|
||||||
*/
|
*/
|
||||||
ConvertType type() default ConvertType.ALL;
|
ConvertType type() default ConvertType.ALL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConvertDisabled 的多用类
|
* ConvertDisabled 的多用类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@Inherited
|
@Inherited
|
||||||
@Documented
|
@Documented
|
||||||
@Target({METHOD, FIELD})
|
@Target({METHOD, FIELD})
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public static @interface ConvertDisableds {
|
public static @interface ConvertDisableds {
|
||||||
|
|
||||||
ConvertDisabled[] value();
|
ConvertDisabled[] value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.TYPE;
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用于类名的别名, 该值必须是全局唯一 <br>
|
* 用于类名的别名, 该值必须是全局唯一 <br>
|
||||||
* 使用场景: 当BSON序列化为了不指定class可以使用@ConvertEntity来取个别名。关联方法: Reader.readClassName() 和 Writer.writeClassName(String value) 。
|
* 使用场景: 当BSON序列化为了不指定class可以使用@ConvertEntity来取个别名。关联方法: Reader.readClassName() 和 Writer.writeClassName(String value) 。
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@Inherited
|
@Inherited
|
||||||
@Documented
|
@Documented
|
||||||
@Target({TYPE})
|
@Target({TYPE})
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public @interface ConvertEntity {
|
public @interface ConvertEntity {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 别名值
|
* 别名值
|
||||||
*
|
*
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
String value();
|
String value();
|
||||||
}
|
}
|
||||||
@@ -1,32 +1,32 @@
|
|||||||
/*
|
/*
|
||||||
* To change this template, choose Tools | Templates
|
* To change this template, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 序列化自定义异常类
|
* 序列化自定义异常类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class ConvertException extends RuntimeException {
|
public class ConvertException extends RuntimeException {
|
||||||
|
|
||||||
public ConvertException() {
|
public ConvertException() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertException(String s) {
|
public ConvertException(String s) {
|
||||||
super(s);
|
super(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertException(String message, Throwable cause) {
|
public ConvertException(String message, Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertException(Throwable cause) {
|
public ConvertException(Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,102 +1,102 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* newConvert参数中的Function返回结果的数据类
|
* newConvert参数中的Function返回结果的数据类
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public class ConvertField implements Serializable {
|
public class ConvertField implements Serializable {
|
||||||
|
|
||||||
protected String name;
|
protected String name;
|
||||||
|
|
||||||
protected Type type;
|
protected Type type;
|
||||||
|
|
||||||
protected int position;
|
protected int position;
|
||||||
|
|
||||||
protected Object value;
|
protected Object value;
|
||||||
|
|
||||||
public ConvertField() {
|
public ConvertField() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertField(String name, Object value) {
|
public ConvertField(String name, Object value) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertField(String name, int position, Object value) {
|
public ConvertField(String name, int position, Object value) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertField(String name, Type type, Object value) {
|
public ConvertField(String name, Type type, Object value) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertField(String name, Type type, int position, Object value) {
|
public ConvertField(String name, Type type, int position, Object value) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ConvertField[] ofArray(Object... items) {
|
public static ConvertField[] ofArray(Object... items) {
|
||||||
int len = items.length / 2;
|
int len = items.length / 2;
|
||||||
ConvertField[] rs = new ConvertField[len];
|
ConvertField[] rs = new ConvertField[len];
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
rs[i] = new ConvertField(items[i * 2].toString(), items[i * 2 + 1]);
|
rs[i] = new ConvertField(items[i * 2].toString(), items[i * 2 + 1]);
|
||||||
}
|
}
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setType(Type type) {
|
public void setType(Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPosition() {
|
public int getPosition() {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPosition(int position) {
|
public void setPosition(int position) {
|
||||||
this.position = position;
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getValue() {
|
public Object getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValue(Object value) {
|
public void setValue(Object value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return JsonConvert.root().convertTo(this);
|
return JsonConvert.root().convertTo(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
53
src/main/java/org/redkale/convert/ConvertImpl.java
Normal file
53
src/main/java/org/redkale/convert/ConvertImpl.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.redkale.convert;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于序列化时接口或抽象类的默认实现类, 被标记的类必须是接口或抽象类 <br>
|
||||||
|
* 使用场景: <br>
|
||||||
|
*
|
||||||
|
* <blockquote><pre>
|
||||||
|
* @ConvertImpl(OneImpl.class)
|
||||||
|
* public interface OneEntity {
|
||||||
|
* public String getName();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* public class OneImpl implements OneEntity {
|
||||||
|
* private String name;
|
||||||
|
* public String getName(){return name;}
|
||||||
|
* public void setName(String name){this.name=name;}
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* String json = "{'name':'hello'}";
|
||||||
|
* OneEntity one = JsonConvert.root.convertFrom(OneEntity.class, json);
|
||||||
|
* //one instanceof OneImpl
|
||||||
|
*
|
||||||
|
* </pre></blockquote>
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @since 2.5.0
|
||||||
|
*/
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
@Target({TYPE})
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
public @interface ConvertImpl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认的实现类
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
Class value();
|
||||||
|
}
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mask接口
|
* Mask接口
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public interface ConvertMask {
|
public interface ConvertMask {
|
||||||
|
|
||||||
default byte mask(byte value) {
|
default byte mask(byte value) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
default byte unmask(byte value) {
|
default byte unmask(byte value) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert的扩展实现类加载器
|
* Convert的扩展实现类加载器
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*
|
*
|
||||||
* @since 2.2.0
|
* @since 2.5.0
|
||||||
*/
|
*/
|
||||||
public interface ConvertLoader {
|
public interface ConvertProvider {
|
||||||
|
|
||||||
public ConvertType type();
|
public ConvertType type();
|
||||||
|
|
||||||
public Convert convert();
|
public Convert convert();
|
||||||
}
|
}
|
||||||
@@ -1,27 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
import static java.lang.annotation.ElementType.*;
|
import static java.lang.annotation.ElementType.*;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 序列化时标记String字段的值是否为无转义字符且长度不超过255的字符串
|
* 序列化时标记String字段的值是否为无转义字符且长度不超过255的字符串
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*
|
*
|
||||||
* @since 2.3.0
|
* @since 2.3.0
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Target({METHOD, FIELD})
|
@Target({METHOD, FIELD})
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public @interface ConvertSmallString {
|
public @interface ConvertSmallString {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,46 +1,46 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
* To change this template file, choose Tools | Templates
|
* To change this template file, choose Tools | Templates
|
||||||
* and open the template in the editor.
|
* and open the template in the editor.
|
||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 序列化类型枚举,结合@ConvertColumn使用
|
* 序列化类型枚举,结合@ConvertColumn使用
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public enum ConvertType {
|
public enum ConvertType {
|
||||||
|
|
||||||
JSON(1),
|
JSON(1),
|
||||||
BSON(2),
|
BSON(2),
|
||||||
PROTOBUF(64),
|
PROTOBUF(64),
|
||||||
PROTOBUF_JSON(64 + 1),
|
PROTOBUF_JSON(64 + 1),
|
||||||
DIY(256),
|
DIY(256),
|
||||||
ALL(1023);
|
ALL(1023);
|
||||||
|
|
||||||
private final int value;
|
private final int value;
|
||||||
|
|
||||||
private ConvertType(int v) {
|
private ConvertType(int v) {
|
||||||
this.value = v;
|
this.value = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getValue() {
|
public int getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(ConvertType type) {
|
public boolean contains(ConvertType type) {
|
||||||
if (type == null) return false;
|
if (type == null) return false;
|
||||||
return this.value >= type.value && (this.value & type.value) > 0;
|
return this.value >= type.value && (this.value & type.value) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ConvertType find(int value) {
|
public static ConvertType find(int value) {
|
||||||
for (ConvertType t : ConvertType.values()) {
|
for (ConvertType t : ConvertType.values()) {
|
||||||
if (value == t.value) return t;
|
if (value == t.value) return t;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user