修复push消息时连续for循环中推送时,android , java 客户端会收不到消息的问题

This commit is contained in:
远方夕阳 2020-03-07 15:49:09 +08:00
parent f3b7ec63e0
commit 5dc06714ff
78 changed files with 2092 additions and 2253 deletions

View File

@ -25,45 +25,45 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.2.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.2.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.2.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.2.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.2.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.12.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.12.1" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.29" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.30" level="project" />
<orderEntry type="library" name="Maven: jakarta.annotation:jakarta.annotation-api:1.3.5" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.2.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.2.4.RELEASE" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.25" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.10.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.10.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.10.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.10.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.29" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.29" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.29" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-validation:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: jakarta.validation:jakarta.validation-api:2.0.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.2.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.2.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.10.2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.10.2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.10.2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.10.2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.2.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.31" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.31" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.31" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-validation:2.2.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: jakarta.validation:jakarta.validation-api:2.0.2" level="project" />
<orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.0.18.Final" level="project" />
<orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.4.1.Final" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-freemarker:2.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.2.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.2.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.2.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.2.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.2.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-freemarker:2.2.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.freemarker:freemarker:2.3.29" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context-support:5.2.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context-support:5.2.4.RELEASE" level="project" />
<orderEntry type="module-library">
<library name="Maven: com.farsunset:cim-server-sdk:3.8.0">
<CLASSES>
@ -74,7 +74,7 @@
</library>
</orderEntry>
<orderEntry type="library" name="Maven: org.apache.mina:mina-core:2.1.3" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.29" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.30" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-handler:4.1.35.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-buffer:4.1.35.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec:4.1.35.Final" level="project" />

View File

@ -77,6 +77,23 @@
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
<component name="libraryTable">
<library name="Maven: ch.qos.logback:logback-classic:1.2.3">
<CLASSES>
@ -111,70 +128,70 @@
<root url="jar://$MAVEN_REPOSITORY$/cn/teaey/apns4j/apns4j/1.1.4/apns4j-1.1.4-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.10.1">
<library name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.10.2">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-annotations/2.10.1/jackson-annotations-2.10.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-annotations/2.10.2/jackson-annotations-2.10.2.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-annotations/2.10.1/jackson-annotations-2.10.1-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-annotations/2.10.2/jackson-annotations-2.10.2-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-annotations/2.10.1/jackson-annotations-2.10.1-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-annotations/2.10.2/jackson-annotations-2.10.2-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: com.fasterxml.jackson.core:jackson-core:2.10.1">
<library name="Maven: com.fasterxml.jackson.core:jackson-core:2.10.2">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-core/2.10.1/jackson-core-2.10.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-core/2.10.2/jackson-core-2.10.2.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-core/2.10.1/jackson-core-2.10.1-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-core/2.10.2/jackson-core-2.10.2-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-core/2.10.1/jackson-core-2.10.1-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-core/2.10.2/jackson-core-2.10.2-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: com.fasterxml.jackson.core:jackson-databind:2.10.1">
<library name="Maven: com.fasterxml.jackson.core:jackson-databind:2.10.2">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-databind/2.10.1/jackson-databind-2.10.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-databind/2.10.2/jackson-databind-2.10.2.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-databind/2.10.1/jackson-databind-2.10.1-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-databind/2.10.2/jackson-databind-2.10.2-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-databind/2.10.1/jackson-databind-2.10.1-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-databind/2.10.2/jackson-databind-2.10.2-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.10.1">
<library name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.10.2">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.10.1/jackson-datatype-jdk8-2.10.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.10.2/jackson-datatype-jdk8-2.10.2.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.10.1/jackson-datatype-jdk8-2.10.1-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.10.2/jackson-datatype-jdk8-2.10.2-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.10.1/jackson-datatype-jdk8-2.10.1-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.10.2/jackson-datatype-jdk8-2.10.2-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.1">
<library name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.2">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.10.1/jackson-datatype-jsr310-2.10.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.10.2/jackson-datatype-jsr310-2.10.2.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.10.1/jackson-datatype-jsr310-2.10.1-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.10.2/jackson-datatype-jsr310-2.10.2-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.10.1/jackson-datatype-jsr310-2.10.1-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.10.2/jackson-datatype-jsr310-2.10.2-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.1">
<library name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.2">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/module/jackson-module-parameter-names/2.10.1/jackson-module-parameter-names-2.10.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/module/jackson-module-parameter-names/2.10.2/jackson-module-parameter-names-2.10.2.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/module/jackson-module-parameter-names/2.10.1/jackson-module-parameter-names-2.10.1-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/module/jackson-module-parameter-names/2.10.2/jackson-module-parameter-names-2.10.2-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/module/jackson-module-parameter-names/2.10.1/jackson-module-parameter-names-2.10.1-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/module/jackson-module-parameter-names/2.10.2/jackson-module-parameter-names-2.10.2-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: com.fasterxml:classmate:1.5.1">
@ -298,15 +315,15 @@
<root url="jar://$MAVEN_REPOSITORY$/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: jakarta.validation:jakarta.validation-api:2.0.1">
<library name="Maven: jakarta.validation:jakarta.validation-api:2.0.2">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/jakarta/validation/jakarta.validation-api/2.0.1/jakarta.validation-api-2.0.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/jakarta/validation/jakarta.validation-api/2.0.2/jakarta.validation-api-2.0.2.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/jakarta/validation/jakarta.validation-api/2.0.1/jakarta.validation-api-2.0.1-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/jakarta/validation/jakarta.validation-api/2.0.2/jakarta.validation-api-2.0.2-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/jakarta/validation/jakarta.validation-api/2.0.1/jakarta.validation-api-2.0.1-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/jakarta/validation/jakarta.validation-api/2.0.2/jakarta.validation-api-2.0.2-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.apache.commons:commons-lang3:3.8.1">
@ -353,37 +370,37 @@
<root url="jar://$MAVEN_REPOSITORY$/org/apache/mina/mina-core/2.1.3/mina-core-2.1.3-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.29">
<library name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.31">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-core/9.0.29/tomcat-embed-core-9.0.29.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-core/9.0.31/tomcat-embed-core-9.0.31.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-core/9.0.29/tomcat-embed-core-9.0.29-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-core/9.0.31/tomcat-embed-core-9.0.31-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-core/9.0.29/tomcat-embed-core-9.0.29-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-core/9.0.31/tomcat-embed-core-9.0.31-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.29">
<library name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.31">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-el/9.0.29/tomcat-embed-el-9.0.29.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-el/9.0.31/tomcat-embed-el-9.0.31.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-el/9.0.29/tomcat-embed-el-9.0.29-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-el/9.0.31/tomcat-embed-el-9.0.31-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-el/9.0.29/tomcat-embed-el-9.0.29-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-el/9.0.31/tomcat-embed-el-9.0.31-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.29">
<library name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.31">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.29/tomcat-embed-websocket-9.0.29.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.31/tomcat-embed-websocket-9.0.31.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.29/tomcat-embed-websocket-9.0.29-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.31/tomcat-embed-websocket-9.0.31-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.29/tomcat-embed-websocket-9.0.29-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.31/tomcat-embed-websocket-9.0.31-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.freemarker:freemarker:2.3.29">
@ -419,224 +436,224 @@
<root url="jar://$MAVEN_REPOSITORY$/org/jboss/logging/jboss-logging/3.4.1.Final/jboss-logging-3.4.1.Final-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.slf4j:jul-to-slf4j:1.7.29">
<library name="Maven: org.slf4j:jul-to-slf4j:1.7.30">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/jul-to-slf4j/1.7.29/jul-to-slf4j-1.7.29.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/jul-to-slf4j/1.7.30/jul-to-slf4j-1.7.30.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/jul-to-slf4j/1.7.29/jul-to-slf4j-1.7.29-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/jul-to-slf4j/1.7.30/jul-to-slf4j-1.7.30-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/jul-to-slf4j/1.7.29/jul-to-slf4j-1.7.29-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/jul-to-slf4j/1.7.30/jul-to-slf4j-1.7.30-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.slf4j:slf4j-api:1.7.29">
<library name="Maven: org.slf4j:slf4j-api:1.7.30">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/1.7.29/slf4j-api-1.7.29.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/1.7.29/slf4j-api-1.7.29-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/1.7.29/slf4j-api-1.7.29-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.2.2.RELEASE">
<library name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.2.5.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-autoconfigure/2.2.2.RELEASE/spring-boot-autoconfigure-2.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-autoconfigure/2.2.5.RELEASE/spring-boot-autoconfigure-2.2.5.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-autoconfigure/2.2.2.RELEASE/spring-boot-autoconfigure-2.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-autoconfigure/2.2.5.RELEASE/spring-boot-autoconfigure-2.2.5.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-autoconfigure/2.2.2.RELEASE/spring-boot-autoconfigure-2.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-autoconfigure/2.2.5.RELEASE/spring-boot-autoconfigure-2.2.5.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework.boot:spring-boot-starter-freemarker:2.2.2.RELEASE">
<library name="Maven: org.springframework.boot:spring-boot-starter-freemarker:2.2.5.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-freemarker/2.2.2.RELEASE/spring-boot-starter-freemarker-2.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-freemarker/2.2.5.RELEASE/spring-boot-starter-freemarker-2.2.5.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-freemarker/2.2.2.RELEASE/spring-boot-starter-freemarker-2.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-freemarker/2.2.5.RELEASE/spring-boot-starter-freemarker-2.2.5.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-freemarker/2.2.2.RELEASE/spring-boot-starter-freemarker-2.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-freemarker/2.2.5.RELEASE/spring-boot-starter-freemarker-2.2.5.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework.boot:spring-boot-starter-json:2.2.2.RELEASE">
<library name="Maven: org.springframework.boot:spring-boot-starter-json:2.2.5.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-json/2.2.2.RELEASE/spring-boot-starter-json-2.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-json/2.2.5.RELEASE/spring-boot-starter-json-2.2.5.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-json/2.2.2.RELEASE/spring-boot-starter-json-2.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-json/2.2.5.RELEASE/spring-boot-starter-json-2.2.5.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-json/2.2.2.RELEASE/spring-boot-starter-json-2.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-json/2.2.5.RELEASE/spring-boot-starter-json-2.2.5.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework.boot:spring-boot-starter-logging:2.2.2.RELEASE">
<library name="Maven: org.springframework.boot:spring-boot-starter-logging:2.2.5.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-logging/2.2.2.RELEASE/spring-boot-starter-logging-2.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-logging/2.2.5.RELEASE/spring-boot-starter-logging-2.2.5.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-logging/2.2.2.RELEASE/spring-boot-starter-logging-2.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-logging/2.2.5.RELEASE/spring-boot-starter-logging-2.2.5.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-logging/2.2.2.RELEASE/spring-boot-starter-logging-2.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-logging/2.2.5.RELEASE/spring-boot-starter-logging-2.2.5.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.2.2.RELEASE">
<library name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.2.5.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-tomcat/2.2.2.RELEASE/spring-boot-starter-tomcat-2.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-tomcat/2.2.5.RELEASE/spring-boot-starter-tomcat-2.2.5.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-tomcat/2.2.2.RELEASE/spring-boot-starter-tomcat-2.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-tomcat/2.2.5.RELEASE/spring-boot-starter-tomcat-2.2.5.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-tomcat/2.2.2.RELEASE/spring-boot-starter-tomcat-2.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-tomcat/2.2.5.RELEASE/spring-boot-starter-tomcat-2.2.5.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework.boot:spring-boot-starter-validation:2.2.2.RELEASE">
<library name="Maven: org.springframework.boot:spring-boot-starter-validation:2.2.5.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-validation/2.2.2.RELEASE/spring-boot-starter-validation-2.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-validation/2.2.5.RELEASE/spring-boot-starter-validation-2.2.5.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-validation/2.2.2.RELEASE/spring-boot-starter-validation-2.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-validation/2.2.5.RELEASE/spring-boot-starter-validation-2.2.5.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-validation/2.2.2.RELEASE/spring-boot-starter-validation-2.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-validation/2.2.5.RELEASE/spring-boot-starter-validation-2.2.5.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework.boot:spring-boot-starter-web:2.2.2.RELEASE">
<library name="Maven: org.springframework.boot:spring-boot-starter-web:2.2.5.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-web/2.2.2.RELEASE/spring-boot-starter-web-2.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-web/2.2.5.RELEASE/spring-boot-starter-web-2.2.5.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-web/2.2.2.RELEASE/spring-boot-starter-web-2.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-web/2.2.5.RELEASE/spring-boot-starter-web-2.2.5.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-web/2.2.2.RELEASE/spring-boot-starter-web-2.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-web/2.2.5.RELEASE/spring-boot-starter-web-2.2.5.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework.boot:spring-boot-starter:2.2.2.RELEASE">
<library name="Maven: org.springframework.boot:spring-boot-starter:2.2.5.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter/2.2.2.RELEASE/spring-boot-starter-2.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter/2.2.5.RELEASE/spring-boot-starter-2.2.5.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter/2.2.2.RELEASE/spring-boot-starter-2.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter/2.2.5.RELEASE/spring-boot-starter-2.2.5.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter/2.2.2.RELEASE/spring-boot-starter-2.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter/2.2.5.RELEASE/spring-boot-starter-2.2.5.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework.boot:spring-boot:2.2.2.RELEASE">
<library name="Maven: org.springframework.boot:spring-boot:2.2.5.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot/2.2.2.RELEASE/spring-boot-2.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot/2.2.5.RELEASE/spring-boot-2.2.5.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot/2.2.2.RELEASE/spring-boot-2.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot/2.2.5.RELEASE/spring-boot-2.2.5.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot/2.2.2.RELEASE/spring-boot-2.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot/2.2.5.RELEASE/spring-boot-2.2.5.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework:spring-aop:5.2.2.RELEASE">
<library name="Maven: org.springframework:spring-aop:5.2.4.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-aop/5.2.2.RELEASE/spring-aop-5.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-aop/5.2.4.RELEASE/spring-aop-5.2.4.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-aop/5.2.2.RELEASE/spring-aop-5.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-aop/5.2.4.RELEASE/spring-aop-5.2.4.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-aop/5.2.2.RELEASE/spring-aop-5.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-aop/5.2.4.RELEASE/spring-aop-5.2.4.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework:spring-beans:5.2.2.RELEASE">
<library name="Maven: org.springframework:spring-beans:5.2.4.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-beans/5.2.2.RELEASE/spring-beans-5.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-beans/5.2.4.RELEASE/spring-beans-5.2.4.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-beans/5.2.2.RELEASE/spring-beans-5.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-beans/5.2.4.RELEASE/spring-beans-5.2.4.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-beans/5.2.2.RELEASE/spring-beans-5.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-beans/5.2.4.RELEASE/spring-beans-5.2.4.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework:spring-context-support:5.2.2.RELEASE">
<library name="Maven: org.springframework:spring-context-support:5.2.4.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-context-support/5.2.2.RELEASE/spring-context-support-5.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-context-support/5.2.4.RELEASE/spring-context-support-5.2.4.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-context-support/5.2.2.RELEASE/spring-context-support-5.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-context-support/5.2.4.RELEASE/spring-context-support-5.2.4.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-context-support/5.2.2.RELEASE/spring-context-support-5.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-context-support/5.2.4.RELEASE/spring-context-support-5.2.4.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework:spring-context:5.2.2.RELEASE">
<library name="Maven: org.springframework:spring-context:5.2.4.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-context/5.2.2.RELEASE/spring-context-5.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-context/5.2.4.RELEASE/spring-context-5.2.4.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-context/5.2.2.RELEASE/spring-context-5.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-context/5.2.4.RELEASE/spring-context-5.2.4.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-context/5.2.2.RELEASE/spring-context-5.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-context/5.2.4.RELEASE/spring-context-5.2.4.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework:spring-core:5.2.2.RELEASE">
<library name="Maven: org.springframework:spring-core:5.2.4.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-core/5.2.2.RELEASE/spring-core-5.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-core/5.2.4.RELEASE/spring-core-5.2.4.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-core/5.2.2.RELEASE/spring-core-5.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-core/5.2.4.RELEASE/spring-core-5.2.4.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-core/5.2.2.RELEASE/spring-core-5.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-core/5.2.4.RELEASE/spring-core-5.2.4.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework:spring-expression:5.2.2.RELEASE">
<library name="Maven: org.springframework:spring-expression:5.2.4.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-expression/5.2.2.RELEASE/spring-expression-5.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-expression/5.2.4.RELEASE/spring-expression-5.2.4.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-expression/5.2.2.RELEASE/spring-expression-5.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-expression/5.2.4.RELEASE/spring-expression-5.2.4.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-expression/5.2.2.RELEASE/spring-expression-5.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-expression/5.2.4.RELEASE/spring-expression-5.2.4.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework:spring-jcl:5.2.2.RELEASE">
<library name="Maven: org.springframework:spring-jcl:5.2.4.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-jcl/5.2.2.RELEASE/spring-jcl-5.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-jcl/5.2.4.RELEASE/spring-jcl-5.2.4.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-jcl/5.2.2.RELEASE/spring-jcl-5.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-jcl/5.2.4.RELEASE/spring-jcl-5.2.4.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-jcl/5.2.2.RELEASE/spring-jcl-5.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-jcl/5.2.4.RELEASE/spring-jcl-5.2.4.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework:spring-web:5.2.2.RELEASE">
<library name="Maven: org.springframework:spring-web:5.2.4.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-web/5.2.2.RELEASE/spring-web-5.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-web/5.2.4.RELEASE/spring-web-5.2.4.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-web/5.2.2.RELEASE/spring-web-5.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-web/5.2.4.RELEASE/spring-web-5.2.4.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-web/5.2.2.RELEASE/spring-web-5.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-web/5.2.4.RELEASE/spring-web-5.2.4.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.springframework:spring-webmvc:5.2.2.RELEASE">
<library name="Maven: org.springframework:spring-webmvc:5.2.4.RELEASE">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-webmvc/5.2.2.RELEASE/spring-webmvc-5.2.2.RELEASE.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-webmvc/5.2.4.RELEASE/spring-webmvc-5.2.4.RELEASE.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-webmvc/5.2.2.RELEASE/spring-webmvc-5.2.2.RELEASE-javadoc.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-webmvc/5.2.4.RELEASE/spring-webmvc-5.2.4.RELEASE-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-webmvc/5.2.2.RELEASE/spring-webmvc-5.2.2.RELEASE-sources.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-webmvc/5.2.4.RELEASE/spring-webmvc-5.2.4.RELEASE-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.yaml:snakeyaml:1.25">

View File

@ -23,7 +23,6 @@
<component name="ProjectId" id="1PxWQToGq56jcmMz176UjXWLSaU" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showExcludedFiles" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
@ -34,7 +33,7 @@
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="aspect.path.notification.shown" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/lib" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.tslint" value="true" />
<property name="node.js.path.for.package.eslint" value="project" />
@ -74,18 +73,6 @@
</list>
</recent_temporary>
</component>
<component name="ServiceViewManager">
<option name="viewStates">
<list>
<serviceView>
<treeState>
<expand />
<select />
</treeState>
</serviceView>
</list>
</option>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
@ -115,13 +102,23 @@
<workItem from="1568597528002" duration="523000" />
<workItem from="1579076046499" duration="14355000" />
<workItem from="1579226829168" duration="8852000" />
<workItem from="1583472574255" duration="526000" />
<workItem from="1583473153031" duration="14749000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
<option name="version" value="2" />
</component>
<component name="WindowStateProjectService">
<state x="609" y="345" key="#com.intellij.fileTypes.FileTypeChooser" timestamp="1583567210548">
<screen x="0" y="23" width="1920" height="1057" />
</state>
<state x="609" y="345" key="#com.intellij.fileTypes.FileTypeChooser/0.23.1920.1057@0.23.1920.1057" timestamp="1583567210548" />
<state x="645" y="287" key="#com.intellij.openapi.updateSettings.impl.PluginUpdateInfoDialog" timestamp="1583472646530">
<screen x="0" y="23" width="1920" height="1057" />
</state>
<state x="645" y="287" key="#com.intellij.openapi.updateSettings.impl.PluginUpdateInfoDialog/0.23.1920.1057@0.23.1920.1057" timestamp="1583472646530" />
<state x="627" y="209" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog" timestamp="1579149988674">
<screen x="0" y="0" width="1920" height="1040" />
</state>
@ -130,38 +127,46 @@
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state x="690" y="218" key="FileChooserDialogImpl/0.0.1920.1040@0.0.1920.1040" timestamp="1579230010253" />
<state width="1867" height="615" key="GridCell.Tab.0.bottom" timestamp="1579243696749">
<screen x="0" y="0" width="1920" height="1040" />
<state width="1870" height="565" key="GridCell.Tab.0.bottom" timestamp="1583566851136">
<screen x="0" y="23" width="1920" height="1057" />
</state>
<state width="1867" height="615" key="GridCell.Tab.0.bottom/0.0.1920.1040@0.0.1920.1040" timestamp="1579243696749" />
<state width="1867" height="615" key="GridCell.Tab.0.center" timestamp="1579243696749">
<screen x="0" y="0" width="1920" height="1040" />
<state width="1870" height="565" key="GridCell.Tab.0.bottom/0.23.1920.1057@0.23.1920.1057" timestamp="1583566851136" />
<state width="1870" height="565" key="GridCell.Tab.0.center" timestamp="1583566851135">
<screen x="0" y="23" width="1920" height="1057" />
</state>
<state width="1867" height="615" key="GridCell.Tab.0.center/0.0.1920.1040@0.0.1920.1040" timestamp="1579243696749" />
<state width="1867" height="615" key="GridCell.Tab.0.left" timestamp="1579243696749">
<screen x="0" y="0" width="1920" height="1040" />
<state width="1870" height="565" key="GridCell.Tab.0.center/0.23.1920.1057@0.23.1920.1057" timestamp="1583566851135" />
<state width="1870" height="565" key="GridCell.Tab.0.left" timestamp="1583566851135">
<screen x="0" y="23" width="1920" height="1057" />
</state>
<state width="1867" height="615" key="GridCell.Tab.0.left/0.0.1920.1040@0.0.1920.1040" timestamp="1579243696749" />
<state width="1867" height="615" key="GridCell.Tab.0.right" timestamp="1579243696749">
<screen x="0" y="0" width="1920" height="1040" />
<state width="1870" height="565" key="GridCell.Tab.0.left/0.23.1920.1057@0.23.1920.1057" timestamp="1583566851135" />
<state width="1870" height="565" key="GridCell.Tab.0.right" timestamp="1583566851136">
<screen x="0" y="23" width="1920" height="1057" />
</state>
<state width="1867" height="615" key="GridCell.Tab.0.right/0.0.1920.1040@0.0.1920.1040" timestamp="1579243696749" />
<state width="1867" height="615" key="GridCell.Tab.1.bottom" timestamp="1579243696751">
<screen x="0" y="0" width="1920" height="1040" />
<state width="1870" height="565" key="GridCell.Tab.0.right/0.23.1920.1057@0.23.1920.1057" timestamp="1583566851136" />
<state width="1870" height="565" key="GridCell.Tab.1.bottom" timestamp="1583566851137">
<screen x="0" y="23" width="1920" height="1057" />
</state>
<state width="1867" height="615" key="GridCell.Tab.1.bottom/0.0.1920.1040@0.0.1920.1040" timestamp="1579243696751" />
<state width="1867" height="615" key="GridCell.Tab.1.center" timestamp="1579243696750">
<screen x="0" y="0" width="1920" height="1040" />
<state width="1870" height="565" key="GridCell.Tab.1.bottom/0.23.1920.1057@0.23.1920.1057" timestamp="1583566851137" />
<state width="1870" height="565" key="GridCell.Tab.1.center" timestamp="1583566851136">
<screen x="0" y="23" width="1920" height="1057" />
</state>
<state width="1867" height="615" key="GridCell.Tab.1.center/0.0.1920.1040@0.0.1920.1040" timestamp="1579243696750" />
<state width="1867" height="615" key="GridCell.Tab.1.left" timestamp="1579243696749">
<screen x="0" y="0" width="1920" height="1040" />
<state width="1870" height="565" key="GridCell.Tab.1.center/0.23.1920.1057@0.23.1920.1057" timestamp="1583566851136" />
<state width="1870" height="565" key="GridCell.Tab.1.left" timestamp="1583566851136">
<screen x="0" y="23" width="1920" height="1057" />
</state>
<state width="1867" height="615" key="GridCell.Tab.1.left/0.0.1920.1040@0.0.1920.1040" timestamp="1579243696749" />
<state width="1867" height="615" key="GridCell.Tab.1.right" timestamp="1579243696751">
<screen x="0" y="0" width="1920" height="1040" />
<state width="1870" height="565" key="GridCell.Tab.1.left/0.23.1920.1057@0.23.1920.1057" timestamp="1583566851136" />
<state width="1870" height="565" key="GridCell.Tab.1.right" timestamp="1583566851137">
<screen x="0" y="23" width="1920" height="1057" />
</state>
<state width="1867" height="615" key="GridCell.Tab.1.right/0.0.1920.1040@0.0.1920.1040" timestamp="1579243696751" />
<state width="1870" height="565" key="GridCell.Tab.1.right/0.23.1920.1057@0.23.1920.1057" timestamp="1583566851137" />
<state width="1867" height="386" key="GridCell.Tab.2.bottom" timestamp="1579156159339">
<screen x="0" y="0" width="1920" height="1040" />
</state>
@ -178,18 +183,20 @@
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state width="1867" height="386" key="GridCell.Tab.2.right/0.0.1920.1040@0.0.1920.1040" timestamp="1579156159339" />
<state x="574" y="193" width="771" height="654" key="find.popup" timestamp="1579242964438">
<screen x="0" y="0" width="1920" height="1040" />
<state x="574" y="219" width="771" height="670" key="find.popup" timestamp="1583473246286">
<screen x="0" y="23" width="1920" height="1057" />
</state>
<state x="574" y="193" width="771" height="654" key="find.popup/0.0.1920.1040@0.0.1920.1040" timestamp="1579242964438" />
<state x="574" y="219" width="771" height="670" key="find.popup/0.23.1920.1057@0.23.1920.1057" timestamp="1583473246286" />
<state x="161" y="163" key="new project wizard" timestamp="1579242569030">
<screen x="0" y="0" width="1920" height="1040" />
</state>
<state x="161" y="163" key="new project wizard/0.0.1920.1040@0.0.1920.1040" timestamp="1579242569030" />
<state x="539" y="5" width="840" height="1034" key="search.everywhere.popup" timestamp="1579235575382">
<screen x="0" y="0" width="1920" height="1040" />
<state x="539" y="28" width="840" height="1051" key="search.everywhere.popup" timestamp="1583567214095">
<screen x="0" y="23" width="1920" height="1057" />
</state>
<state x="539" y="5" width="840" height="1034" key="search.everywhere.popup/0.0.1920.1040@0.0.1920.1040" timestamp="1579235575382" />
<state x="539" y="28" width="840" height="1051" key="search.everywhere.popup/0.23.1920.1057@0.23.1920.1057" timestamp="1583567214095" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager>
@ -204,6 +211,11 @@
<line>22</line>
<option name="timeStamp" value="10" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/com/farsunset/cim/handler/SessionClosedHandler.java</url>
<line>48</line>
<option name="timeStamp" value="12" />
</line-breakpoint>
</breakpoints>
</breakpoint-manager>
</component>

View File

@ -11,7 +11,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<version>2.2.5.RELEASE</version>
<relativePath/>
</parent>

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -21,12 +21,11 @@
*/
package com.farsunset.cim.api.controller;
import com.farsunset.cim.api.controller.dto.MessageResult;
import com.farsunset.cim.push.DefaultMessagePusher;
import com.farsunset.cim.sdk.server.model.Message;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@ -39,30 +38,15 @@ public class MessageController {
@Resource
private DefaultMessagePusher defaultMessagePusher;
/**
* 此方法仅仅在集群时通过服务器调用
*
* @param message
* @return
*/
@PostMapping(value = "/dispatch")
public MessageResult dispatchSend(Message message) {
return send(message);
}
@PostMapping(value = "/send")
public MessageResult send(Message message) {
MessageResult result = new MessageResult();
public ResponseEntity<Long> send(Message message) {
message.setId(System.currentTimeMillis());
defaultMessagePusher.push(message);
result.id = message.getId();
result.timestamp = message.getTimestamp();
return result;
return ResponseEntity.ok(message.getId());
}
}

View File

@ -1,34 +0,0 @@
/**
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.api.controller.dto;
import org.springframework.http.HttpStatus;
import java.util.List;
public class BaseResult {
public int code = HttpStatus.OK.value();
public String message;
public Object data;
public List<?> dataList;
}

View File

@ -1,27 +0,0 @@
/**
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.api.controller.dto;
public class MessageResult extends BaseResult {
public long timestamp;
public long id;
}

View File

@ -13,7 +13,6 @@ import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.HashMap;
@ -23,19 +22,8 @@ public class CIMConfig implements CIMRequestHandler, ApplicationListener<Applica
@Resource
private ApplicationContext applicationContext;
private HashMap<String,Class<? extends CIMRequestHandler>> appHandlerMap = new HashMap<>();
private final HashMap<String,CIMRequestHandler> appHandlerMap = new HashMap<>();
@PostConstruct
private void initHandler() {
/*
* 账号绑定handler
*/
appHandlerMap.put("client_bind", BindHandler.class);
/*
* 连接关闭handler
*/
appHandlerMap.put("client_closed", SessionClosedHandler.class);
}
@Bean(destroyMethod = "destroy")
public CIMNioSocketAcceptor getNioSocketAcceptor(@Value("${cim.app.port}") int port,
@ -52,28 +40,22 @@ public class CIMConfig implements CIMRequestHandler, ApplicationListener<Applica
@Override
public void process(CIMSession session, SentBody body) {
CIMRequestHandler handler = findHandlerByKey(body.getKey());
CIMRequestHandler handler = appHandlerMap.get(body.getKey());
if(handler == null) {return ;}
handler.process(session, body);
}
private CIMRequestHandler findHandlerByKey(String key){
Class<? extends CIMRequestHandler> handlerClass = appHandlerMap.get(key);
if (handlerClass==null){
return null;
}
return applicationContext.getBean(handlerClass);
}
/**
/*
* springboot启动完成之后再启动cim服务的避免服务正在重启时客户端会立即开始连接导致意外异常发生.
*/
@Override
public void onApplicationEvent(ApplicationStartedEvent applicationStartedEvent) {
appHandlerMap.put("client_bind",applicationContext.getBean(BindHandler.class));
appHandlerMap.put("client_closed",applicationContext.getBean(SessionClosedHandler.class));
applicationContext.getBean(CIMNioSocketAcceptor.class).bind();
}
}

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -39,7 +39,7 @@ import javax.annotation.Resource;
import java.util.Objects;
/**
/*
* 账号绑定实现
*
*/

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -33,7 +33,7 @@ import javax.annotation.Resource;
import java.util.Objects;
/**
/*
* 断开连接清除session
*
*/
@ -56,15 +56,7 @@ public class SessionClosedHandler implements CIMRequestHandler {
return;
}
CIMSession oldSession = cimSessionService.get(account.toString());
if (oldSession == null || oldSession.isApnsEnable()) {
return;
}
oldSession.setState(CIMSession.STATE_DISABLED);
oldSession.setNid(null);
cimSessionService.save(oldSession);
cimSessionService.remove(account.toString());
}
}

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -23,13 +23,13 @@ package com.farsunset.cim.push;
import com.farsunset.cim.sdk.server.model.Message;
/**
/*
* 消息发送实接口
*
*/
public interface CIMMessagePusher {
/**
/*
* 向用户发送消息
*
* @param msg

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -31,7 +31,7 @@ import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Objects;
/**
/*
* 消息发送实现类
*
*/
@ -50,7 +50,7 @@ public class DefaultMessagePusher implements CIMMessagePusher {
private ApnsService apnsService;
/**
/*
* 向用户发送消息
*
* @param message
@ -76,9 +76,10 @@ public class DefaultMessagePusher implements CIMMessagePusher {
* 如果连接到了其他服务器则转发请求到目标服务器
*/
if (session.isConnected() && !Objects.equals(host, session.getHost())) {
/**
/*
* @TODO
* 在此调用目标服务器接口来发送
* 在此调用目标服务器接口来发送如session.host = 123.123.123.123
* 调用目标服务器的消息发送接口http://123.123.123.123:8080/message/send
*/
return;
}

View File

@ -7,7 +7,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
/*
* 正式场景下使用redis或者数据库来存储session信息
*/
@Repository

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -26,7 +26,7 @@ import com.farsunset.cim.sdk.server.model.CIMSession;
import java.util.List;
/**
/*
* 集群 session管理实现示例 各位可以自行实现 AbstractSessionManager接口来实现自己的 session管理 服务器集群时
* 须要将CIMSession 信息存入数据库或者redis中 第三方存储空间中便于所有服务器都可以访问
*/

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -46,7 +46,7 @@ public class CIMSessionServiceImpl implements CIMSessionService {
sessionRepository.save(session);
}
/**
/*
*
* @param account 用户id
* @return

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,4 +1,4 @@
/**
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -24,9 +24,3 @@ cim.websocket.port=34567
apple.apns.debug=false
apple.apns.p12.password= your p12 password
apple.apns.p12.file= /apns/lvxin.p12
##################################################################
# System Config #
##################################################################
sys.message.dispatch.url = http://%1$s:${server.port}/api/message/dispatch

View File

@ -1,67 +1,67 @@
module.common.html.title = CIM\u7BA1\u7406\u7CFB\u7EDF
module.common.account = \u5e10\u53f7
module.common.password = \u5bc6\u7801
module.common.save = \u4fdd\u5b58
module.common.html.title = CIM管理系统
module.common.account = 帐号
module.common.password = 密码
module.common.save = 保存
module.common.id = ID
module.common.type =\u7c7b\u578b
module.common.name =\u540d\u79f0
module.common.time =\u65f6\u95f4
module.common.operation =\u64cd\u4f5c
module.common.query =\u67e5\u8be2
module.common.look =\u67e5\u770b
module.common.preview =\u9884\u89c8
module.common.send =\u53d1\u9001
module.common.saveing = \u6b63\u5728\u4fdd\u5b58,\u8bf7\u7a0d\u5019......
module.common.add = \u6dfb\u52a0
module.common.update = \u4fee\u6539
module.common.delete = \u5220\u9664
module.common.save.success = \u4fdd\u5b58\u6210\u529f
module.common.delete.success = \u5220\u9664\u6210\u529f
module.common.delete.loading =\u6b63\u5728\u5220\u9664,\u8bf7\u7a0d\u5019......
module.common.loading = \u52a0\u8f7d\u4e2d,\u8bf7\u7a0d\u5019......
module.common.description = \u8bf4\u660e
module.common.state = \u72b6\u6001
module.common.content = \u5185\u5bb9
module.common.location = \u4f4d\u7f6e
module.common.longitude = \u7ecf\u5ea6
module.common.latitude = \u7eac\u5ea6
module.common.sort = \u6392\u5e8f
module.common.code = \u7f16\u53f7
module.common.import = \u5bfc\u5165
module.common.headlogo = \u5934\u50cf
module.common.homepage = \u4e3b\u9875
module.common.website = \u7f51\u5740
module.common.text = \u6587\u5b57
module.common.type =类型
module.common.name =名称
module.common.time =时间
module.common.operation =操作
module.common.query =查询
module.common.look =查看
module.common.preview =预览
module.common.send =发送
module.common.saveing = 正在保存,请稍候......
module.common.add = 添加
module.common.update = 修改
module.common.delete = 删除
module.common.save.success = 保存成功
module.common.delete.success = 删除成功
module.common.delete.loading =正在删除,请稍候......
module.common.loading = 加载中,请稍候......
module.common.description = 说明
module.common.state = 状态
module.common.content = 内容
module.common.location = 位置
module.common.longitude = 经度
module.common.latitude = 纬度
module.common.sort = 排序
module.common.code = 编号
module.common.import = 导入
module.common.headlogo = 头像
module.common.homepage = 主页
module.common.website = 网址
module.common.text = 文字
module.global.error.500.hint = \u670d\u52a1\u7a0b\u5e8f\u53d1\u751f\u5185\u90e8\u9519\u8bef
module.global.error.400.hint = \u8bf7\u6c42\u53c2\u6570\u7c7b\u578b\u4e0d\u6b63\u786e
module.global.error.404.hint = \u8bbf\u95ee\u7684\u8d44\u6e90\u4e0d\u5b58\u5728
module.global.pager.next = \u4e0b\u4e00\u9875
module.global.pager.previou = \u4e0a\u4e00\u9875
module.global.pager.description = \u5171{0}\u6761\u8bb0\u5f55,{1}\u9875
module.global.error.500.hint = 服务程序发生内部错误
module.global.error.400.hint = 请求参数类型不正确
module.global.error.404.hint = 访问的资源不存在
module.global.pager.next = 下一页
module.global.pager.previou = 上一页
module.global.pager.description = 共{0}条记录,{1}页
module.console.about = \u5173\u4e8e
module.console.about.version = v3.5.0
module.console.about.author = \u4f5c\u8005: \u8fdc\u65b9\u5915\u9633
module.console.about.author.wechat = \u5fae\u4fe1: 3979434
module.console.about = 关于
module.console.about.version = 1.0.0
module.console.about.author = 作者: 远方夕阳
module.console.about.author.wechat = 微信: 3979434
module.console.about.author.qq = Q Q: 3979434
module.console.about.copyright = \u57FA\u4E8EJava\u670D\u52A1\u7AEF\u7684\u5373\u65F6\u901A\u4FE1\u89E3\u51B3\u65B9\u6848,\u4E0Eandroid \u5BA2\u6237\u7AEF\u5B8C\u7F8E\u7ED3\u5408\uFF0C\u540C\u65F6\u652F\u6301\u5176\u4ED6\u8BED\u8A00\u7684\u79FB\u52A8\u5E94\u7528\uFF0C\u7269\u8054\u7F51\uFF0C\u667A\u80FD\u5BB6\u5C45\uFF0C\u684C\u9762\u5E94\u7528\uFF0CWEB\u5E94\u7528\u4EE5\u53CA\u540E\u53F0\u7CFB\u7EDF\u4E4B\u95F4\u7684\u5373\u65F6\u6D88\u4EA4\u4E92\uFF0C\u4E3A\u4F60\u89E3\u51B3\u4E86\u957F\u8FDE\u63A5\u5404\u79CD\u6D88\u606F\u4E8B\u4EF6\uFF0C\u65AD\u7EBF\u91CD\u8FDE\u7B49\u7E41\u7410\u7684\u5904\u7406\uFF0C\u4F7F\u7528\u65B9\u4FBF\u6613\u4E8E\u96C6\u6210\u3002<br/><a target="_blank" href="https://gitee.com/farsunset/cim">https://gitee.com/farsunset/cim</a>
module.console.menu.onlineuser = \u5728\u7ebf\u7528\u6237
module.console.about.copyright = 基于Java服务端的即时通信解决方案,与android 客户端完美结合同时支持其他语言的移动应用物联网智能家居桌面应用WEB应用以及后台系统之间的即时消交互为你解决了长连接各种消息事件断线重连等繁琐的处理使用方便易于集成。<br/><a target="_blank" href="https://gitee.com/farsunset/cim">https://gitee.com/farsunset/cim</a>
module.console.menu.onlineuser = 在线用户
module.console.cimsession.sending = \u6b63\u5728\u53d1\u9001\uff0c\u8bf7\u7a0d\u5019......
module.console.cimsession.send.success = \u53d1\u9001\u6210\u529f
module.console.cimsession.logo =\u5934\u50cf
module.console.cimsession.account =\u5e10\u53f7
module.console.cimsession.nid = \u8fde\u63a5ID
module.console.cimsession.channel = \u7ec8\u7aef
module.console.cimsession.app.version =\u5e94\u7528\u7248\u672c
module.console.cimsession.os.version =\u7cfb\u7edf\u7248\u672c
module.console.cimsession.deviceid =\u8bbe\u5907\u7f16\u53f7
module.console.cimsession.device.model =\u7ec8\u7aef\u578b\u53f7
module.console.cimsession.online.time =\u5728\u7ebf\u65f6\u957f(\u79d2)
module.console.cimsession.time.format ={0}\u79d2
module.console.cimsession.sending = 正在发送,请稍候......
module.console.cimsession.send.success = 发送成功
module.console.cimsession.logo =头像
module.console.cimsession.account =帐号
module.console.cimsession.nid = 连接ID
module.console.cimsession.channel = 终端
module.console.cimsession.app.version =应用版本
module.console.cimsession.os.version =系统版本
module.console.cimsession.deviceid =设备编号
module.console.cimsession.device.model =终端型号
module.console.cimsession.online.time =在线时长(秒)
module.console.cimsession.time.format ={0}
module.console.cimsession.send.message =\u53d1\u9001\u6d88\u606f
module.console.cimsession.receiver = \u63a5\u6536\u5e10\u53f7
module.console.cimsession.message = \u6d88\u606f\u5185\u5bb9
module.console.cimsession.send.message =发送消息
module.console.cimsession.receiver = 接收帐号
module.console.cimsession.message = 消息内容

24
cim-client-sdk/cim-android-sdk/cim-android-sdk.iml Normal file → Executable file
View File

@ -1,2 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4" />
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.google.protobuf:protobuf-lite:3.0.1" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.30" level="project" />
<orderEntry type="module-library">
<library name="Maven: android:android:8.0.0">
<CLASSES>
<root url="jar://$MODULE_DIR$/libs/android.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>

0
cim-client-sdk/cim-android-sdk/jar.bat Normal file → Executable file
View File

0
cim-client-sdk/cim-android-sdk/jar.sh Normal file → Executable file
View File

0
cim-client-sdk/cim-android-sdk/pom.xml Normal file → Executable file
View File

View File

@ -29,8 +29,6 @@ import android.net.Uri;
class CIMCacheManager {
public static final String CIM_CONFIG_INFO = "CIM_CONFIG_INFO";
public static final String KEY_ACCOUNT = "KEY_ACCOUNT";
public static final String KEY_DEVICE_ID = "KEY_DEVICE_ID";

View File

@ -26,7 +26,7 @@ import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
import com.farsunset.cim.sdk.android.coder.CIMLogger;
import com.farsunset.cim.sdk.android.logger.CIMLogger;
import com.farsunset.cim.sdk.android.coder.ClientMessageDecoder;
import com.farsunset.cim.sdk.android.coder.ClientMessageEncoder;
import com.farsunset.cim.sdk.android.constant.CIMConstant;
@ -41,26 +41,23 @@ import java.nio.channels.SocketChannel;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicLong;
/**
/*
* 连接服务端管理cim核心处理类管理连接以及消息处理
*
* @author 3979434@qq.com
*/
class CIMConnectorManager {
private static CIMConnectorManager manager;
private static final int READ_BUFFER_SIZE = 2048;
private static final int WRITE_BUFFER_SIZE = 1024;
private static final int READ_IDLE_TIME = 120 * 1000;
private static final int CONNECT_TIME_OUT = 10 * 1000;
private static final int CONNECT_ALIVE_TIME_OUT = 150 * 1000;
private static final AtomicLong LAST_READ_TIME = new AtomicLong(0);
@ -69,25 +66,24 @@ class CIMConnectorManager{
private static final HandlerThread IDLE_HANDLER_THREAD = new HandlerThread("READ-IDLE", Process.THREAD_PRIORITY_BACKGROUND);
private Semaphore semaphore = new Semaphore(1, true);
private volatile SocketChannel socketChannel;
private Context context;
private final Context context;
private final ByteBuffer headerBuffer = ByteBuffer.allocate(CIMConstant.DATA_HEADER_LENGTH);
private ByteBuffer readBuffer = ByteBuffer.allocate(READ_BUFFER_SIZE);
private final ExecutorService workerExecutor = Executors.newFixedThreadPool(1, r -> new Thread(r, "worker-"));
private ExecutorService workerExecutor = Executors.newFixedThreadPool(1, r -> new Thread(r,"worker-"));
private final ExecutorService bossExecutor = Executors.newFixedThreadPool(1, r -> new Thread(r, "boss-"));
private ExecutorService bossExecutor = Executors.newFixedThreadPool(1, r -> new Thread(r,"boss-"));
private ClientMessageEncoder messageEncoder = new ClientMessageEncoder();
private ClientMessageDecoder messageDecoder = new ClientMessageDecoder();
private final ClientMessageEncoder messageEncoder = new ClientMessageEncoder();
private final ClientMessageDecoder messageDecoder = new ClientMessageDecoder();
static {
IDLE_HANDLER_THREAD.start();
}
private CIMConnectorManager(Context context) {
this.context = context;
}
@ -131,8 +127,6 @@ class CIMConnectorManager{
try {
semaphore.acquire();
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(true);
socketChannel.socket().setTcpNoDelay(true);
@ -142,45 +136,32 @@ class CIMConnectorManager{
socketChannel.socket().connect(new InetSocketAddress(host, port), CONNECT_TIME_OUT);
semaphore.release();
handleConnectedEvent();
handelConnectedEvent();
int result = -1;
while((result = socketChannel.read(readBuffer)) > 0) {
if(readBuffer.position() == readBuffer.capacity()) {
extendByteBuffer();
/*
*开始读取来自服务端的消息先读取3个字节的消息头
*/
while (socketChannel.read(headerBuffer) > 0) {
handleSocketReadEvent();
}
handelSocketReadEvent(result);
}
handelSocketReadEvent(result);
/*
*read 返回 <= 0的情况发生了意外需要断开重链
*/
closeSession();
} catch (ConnectException | SocketTimeoutException ignore) {
semaphore.release();
handleConnectAbortedEvent();
} catch (IOException ignore) {
semaphore.release();
handelDisconnectedEvent();
}catch(InterruptedException ignore) {
semaphore.release();
handleDisconnectedEvent();
}
});
}
public void destroy() {
closeSession();
}
public void closeSession() {
if (!isConnected()) {
@ -210,8 +191,6 @@ class CIMConnectorManager{
int result = 0;
try {
semaphore.acquire();
ByteBuffer buffer = messageEncoder.encode(body);
while (buffer.hasRemaining()) {
result += socketChannel.write(buffer);
@ -221,8 +200,6 @@ class CIMConnectorManager{
result = -1;
} finally {
semaphore.release();
if (result <= 0) {
closeSession();
} else {
@ -254,12 +231,6 @@ class CIMConnectorManager{
LOGGER.sessionClosed(socketChannel);
readBuffer.clear();
if(readBuffer.capacity() > READ_BUFFER_SIZE) {
readBuffer = ByteBuffer.allocate(READ_BUFFER_SIZE);
}
Intent intent = new Intent();
intent.setPackage(context.getPackageName());
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED);
@ -315,14 +286,14 @@ class CIMConnectorManager{
}
}
private Handler idleHandler = new Handler(IDLE_HANDLER_THREAD.getLooper()) {
private final Handler idleHandler = new Handler(IDLE_HANDLER_THREAD.getLooper()) {
@Override
public void handleMessage(android.os.Message m) {
sessionIdle();
}
};
private void handelDisconnectedEvent() {
private void handleDisconnectedEvent() {
closeSession();
}
@ -340,52 +311,31 @@ class CIMConnectorManager{
}
private void handelConnectedEvent() {
private void handleConnectedEvent() {
sessionCreated();
idleHandler.sendEmptyMessageDelayed(0, READ_IDLE_TIME);
}
private void handelSocketReadEvent(int result) {
private void handleSocketReadEvent() throws IOException {
if(result == -1) {
closeSession();
return;
}
onMessageDecodeFinished(messageDecoder.doDecode(headerBuffer,socketChannel));
markLastReadTime();
readBuffer.position(0);
Object message = messageDecoder.doDecode(readBuffer);
if(message == null) {
return;
}
private void onMessageDecodeFinished(Object message){
LOGGER.messageReceived(socketChannel, message);
if(isHeartbeatRequest(message)) {
if (message instanceof HeartbeatRequest) {
send(HeartbeatResponse.getInstance());
return;
}
this.messageReceived(message);
}
private void extendByteBuffer() {
ByteBuffer newBuffer = ByteBuffer.allocate(readBuffer.capacity() + READ_BUFFER_SIZE / 2);
readBuffer.position(0);
newBuffer.put(readBuffer);
readBuffer.clear();
readBuffer = newBuffer;
}
@ -399,10 +349,4 @@ class CIMConnectorManager{
}
private boolean isHeartbeatRequest(Object data) {
return data instanceof HeartbeatRequest;
}
}

View File

@ -31,7 +31,7 @@ import com.farsunset.cim.sdk.android.model.Message;
import com.farsunset.cim.sdk.android.model.ReplyBody;
import com.farsunset.cim.sdk.android.model.SentBody;
/**
/*
* 消息入口所有消息都会经过这里
*/
public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
@ -187,6 +187,7 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver {
/**
* 接收消息实现方法
*
* @param message
* @param intent
*/

View File

@ -62,25 +62,23 @@ public interface CIMEventListener {
/**
* 当连接服务器成功时回调
*
* @param hasAutoBind
* true 已经自动绑定账号到服务器了不需要再手动调用bindAccount
* @param hasAutoBind true 已经自动绑定账号到服务器了不需要再手动调用bindAccount
*/
void onConnectFinished(boolean hasAutoBind);
/**
* 当断开服务器连接的时候回调
*
*/
void onConnectionClosed();
/**
* 当连接服务器失败的时候回调
*
*/
void onConnectFailed();
/**
* 监听器在容器里面的排序值越大则越先接收
*
* @return 排序 值越大优先级越高
*/
int getEventDispatchOrder();

View File

@ -37,8 +37,8 @@ import java.util.Iterator;
*/
public class CIMListenerManager {
private static ArrayList<CIMEventListener> cimListeners = new ArrayList<CIMEventListener>();
private static ReceiveComparator comparator = new ReceiveComparator();
private static final ArrayList<CIMEventListener> cimListeners = new ArrayList<CIMEventListener>();
private static final ReceiveComparator comparator = new ReceiveComparator();
private CIMListenerManager() {

View File

@ -29,7 +29,7 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.text.TextUtils;
import com.farsunset.cim.sdk.android.coder.CIMLogger;
import com.farsunset.cim.sdk.android.logger.CIMLogger;
import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.model.SentBody;
@ -40,17 +40,19 @@ import java.util.UUID;
*/
public class CIMPushManager {
protected static String ACTION_ACTIVATE_PUSH_SERVICE = "ACTION_ACTIVATE_PUSH_SERVICE";
protected static final String ACTION_ACTIVATE_PUSH_SERVICE = "ACTION_ACTIVATE_PUSH_SERVICE";
protected static String ACTION_CREATE_CIM_CONNECTION = "ACTION_CREATE_CIM_CONNECTION";
protected static final String ACTION_CREATE_CIM_CONNECTION = "ACTION_CREATE_CIM_CONNECTION";
protected static String ACTION_SEND_REQUEST_BODY = "ACTION_SEND_REQUEST_BODY";
protected static final String ACTION_SEND_REQUEST_BODY = "ACTION_SEND_REQUEST_BODY";
protected static String ACTION_CLOSE_CIM_CONNECTION = "ACTION_CLOSE_CIM_CONNECTION";
protected static final String ACTION_CLOSE_CIM_CONNECTION = "ACTION_CLOSE_CIM_CONNECTION";
protected static String ACTION_SET_LOGGER_EATABLE = "ACTION_SET_LOGGER_EATABLE";
protected static final String ACTION_DESTROY_CIM_SERVICE = "ACTION_DESTROY_CIM_SERVICE";
protected static String KEY_SEND_BODY = "KEY_SEND_BODY";
protected static final String ACTION_SET_LOGGER_EATABLE = "ACTION_SET_LOGGER_EATABLE";
protected static final String KEY_SEND_BODY = "KEY_SEND_BODY";
/**
* 初始化,连接服务端在程序启动页或者 在Application里调用
@ -171,7 +173,9 @@ public class CIMPushManager {
CIMCacheManager.putBoolean(context, CIMCacheManager.KEY_CIM_DESTROYED, true);
CIMCacheManager.putString(context, CIMCacheManager.KEY_ACCOUNT, null);
context.stopService(new Intent(context, CIMPushService.class));
Intent serviceIntent = new Intent(context, CIMPushService.class);
serviceIntent.setAction(ACTION_DESTROY_CIM_SERVICE);
startService(context, serviceIntent);
}
@ -218,7 +222,6 @@ public class CIMPushManager {
}
private static String getVersionName(Context context) {
try {

View File

@ -35,7 +35,7 @@ import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import com.farsunset.cim.sdk.android.coder.CIMLogger;
import com.farsunset.cim.sdk.android.logger.CIMLogger;
import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.model.SentBody;
@ -43,7 +43,6 @@ import com.farsunset.cim.sdk.android.model.SentBody;
* 与服务端连接服务
*
* @author 3979434
*
*/
public class CIMPushService extends Service {
public final static String KEY_DELAYED_TIME = "KEY_DELAYED_TIME";
@ -54,6 +53,7 @@ public class CIMPushService extends Service {
private CIMConnectorManager manager;
private KeepAliveBroadcastReceiver keepAliveReceiver;
private ConnectivityManager connectivityManager;
@Override
public void onCreate() {
manager = CIMConnectorManager.getManager(this.getApplicationContext());
@ -73,7 +73,7 @@ public class CIMPushService extends Service {
}
}
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
final ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
Intent intent = new Intent();
@ -81,6 +81,7 @@ public class CIMPushService extends Service {
intent.setAction(CIMConstant.IntentAction.ACTION_NETWORK_CHANGED);
sendBroadcast(intent);
}
@Override
public void onUnavailable() {
Intent intent = new Intent();
@ -91,19 +92,20 @@ public class CIMPushService extends Service {
};
Handler connectHandler = new Handler() {
final Handler connectHandler = new Handler() {
@Override
public void handleMessage(android.os.Message message) {
connect();
}
};
Handler notificationHandler = new Handler() {
final Handler notificationHandler = new Handler() {
@Override
public void handleMessage(android.os.Message message) {
stopForeground(true);
}
};
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
@ -144,6 +146,11 @@ public class CIMPushService extends Service {
CIMLogger.getLogger().debugMode(enable);
}
if (CIMPushManager.ACTION_DESTROY_CIM_SERVICE.equals(action)) {
manager.destroy();
stopSelf();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationHandler.sendEmptyMessageDelayed(0, 1000);
}
@ -183,7 +190,7 @@ public class CIMPushService extends Service {
private void handleKeepAlive() {
if (manager.isConnected()) {
CIMLogger.getLogger().connectState(true);
CIMLogger.getLogger().connectState(true,CIMPushManager.isStopped(this),CIMPushManager.isDestroyed(this));
return;
}
@ -196,16 +203,13 @@ public class CIMPushService extends Service {
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
manager.destroy();
public void release() {
connectHandler.removeMessages(0);
notificationHandler.removeMessages(0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
unregisterReceiver(keepAliveReceiver);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
@ -213,6 +217,14 @@ public class CIMPushService extends Service {
}
}
@Override
public void onDestroy() {
super.onDestroy();
release();
}
public class KeepAliveBroadcastReceiver extends BroadcastReceiver {
@Override

View File

@ -1,138 +0,0 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.coder;
import android.util.Log;
import java.nio.channels.SocketChannel;
/**
* 日志打印添加session 的id和ip address
*/
public class CIMLogger {
private final static String TAG = "CIM";
private boolean debug = true;
public static CIMLogger getLogger() {
return LoggerHolder.logger;
}
private CIMLogger() {
}
private static class LoggerHolder{
private static CIMLogger logger = new CIMLogger();
}
public void debugMode(boolean mode) {
debug = mode;
}
public void messageReceived(SocketChannel session, Object message) {
if(debug) {
Log.i(TAG,String.format("[RECEIVED]" + getSessionInfo(session) + "\n%s", message));
}
}
public void messageSent(SocketChannel session, Object message) {
if(debug) {
Log.i(TAG,String.format("[ SENT ]" + getSessionInfo(session) + "\n%s", message));
}
}
public void sessionCreated( SocketChannel session) {
if(debug) {
Log.i(TAG,"[ OPENED ]" + getSessionInfo(session));
}
}
public void sessionIdle( SocketChannel session) {
if(debug) {
Log.d(TAG,"[ IDLE ]" + getSessionInfo(session));
}
}
public void sessionClosed( SocketChannel session) {
if(debug) {
Log.w(TAG,"[ CLOSED ] ID = " + session.hashCode());
}
}
public void connectFailure(long interval) {
if(debug) {
Log.d(TAG,"CONNECT FAILURE, TRY RECONNECT AFTER " + interval +"ms");
}
}
public void startConnect(String host , int port) {
if(debug) {
Log.i(TAG,"START CONNECT REMOTE HOST:" + host + " PORT:" + port);
}
}
public void invalidHostPort(String host , int port) {
if(debug) {
Log.d(TAG,"INVALID SOCKET ADDRESS -> HOST:" + host + " PORT:" + port);
}
}
public void connectState(boolean isConnected) {
if(debug) {
Log.d(TAG,"CONNECTED:" + isConnected);
}
}
public void connectState(boolean isConnected,boolean isManualStop,boolean isDestroyed) {
if(debug) {
Log.d(TAG,"CONNECTED:" + isConnected + " STOPPED:"+isManualStop+ " DESTROYED:"+isDestroyed);
}
}
private String getSessionInfo(SocketChannel session) {
StringBuilder builder = new StringBuilder();
if (session == null) {
return "";
}
builder.append(" [");
builder.append("id:").append(session.hashCode());
try {
if (session.socket().getLocalAddress() != null) {
builder.append(" L:").append(session.socket().getLocalAddress()).append(":").append(session.socket().getLocalPort());
}
} catch (Exception ignore) {
}
try {
if (session.socket().getRemoteSocketAddress() != null) {
builder.append(" R:").append(session.socket().getRemoteSocketAddress().toString());
}
} catch (Exception ignore) {
}
builder.append("]");
return builder.toString();
}
}

View File

@ -28,63 +28,56 @@ import com.farsunset.cim.sdk.android.model.Message;
import com.farsunset.cim.sdk.android.model.ReplyBody;
import com.farsunset.cim.sdk.android.model.proto.MessageProto;
import com.farsunset.cim.sdk.android.model.proto.ReplyBodyProto;
import com.google.protobuf.InvalidProtocolBufferException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
/**
* 客户端消息解码
*/
public class ClientMessageDecoder {
/**
*
* @param headerBuffer 读取到的消息头
* @param socketChannel
* @return
*/
public Object doDecode(ByteBuffer headerBuffer , SocketChannel socketChannel) throws IOException {
public Object doDecode(ByteBuffer buffer) {
headerBuffer.position(0);
byte type = headerBuffer.get();
byte lv = headerBuffer.get();
byte hv = headerBuffer.get();
headerBuffer.clear();
/*
* 消息头3位
* 先通过消息头拿到消息的长度然后进行定长读取
* 解决消息的断包和粘包情况
*/
if (buffer.remaining() < CIMConstant.DATA_HEADER_LENGTH) {
return null;
}
buffer.mark();
int dataLength = getContentLength(lv, hv);
byte type = buffer.get();
byte lv = buffer.get();
byte hv = buffer.get();
int length = getContentLength(lv, hv);
ByteBuffer bodyBuffer = ByteBuffer.allocate(dataLength);
/*
*如果消息体没有接收完整则重置读取等待下一次重新读取
* 如果读取的消息长度不够则进行等待后续消息到来
* 当读取的消息长度(bodyBuffer.position() == dataLength)时意味着一个完整的消息已经接收完成
*/
if (length > buffer.remaining()) {
buffer.reset();
return null;
}
do {
socketChannel.read(bodyBuffer);
} while (bodyBuffer.position() != dataLength);
byte[] dataBytes = new byte[length];
buffer.get(dataBytes, 0, length);
buffer.position(0);
try {
return mappingMessageObject(dataBytes, type);
} catch (InvalidProtocolBufferException e) {
return null;
}
}
private Object mappingMessageObject(byte[] bytes, byte type) throws InvalidProtocolBufferException {
/*
消息读取完成后通过type来解析成对应的消息体
*/
if (CIMConstant.ProtobufType.S_H_RQ == type) {
return HeartbeatRequest.getInstance();
}
if (CIMConstant.ProtobufType.REPLY_BODY == type) {
ReplyBodyProto.Model bodyProto = ReplyBodyProto.Model.parseFrom(bytes);
ReplyBodyProto.Model bodyProto = ReplyBodyProto.Model.parseFrom(bodyBuffer.array());
ReplyBody body = new ReplyBody();
body.setKey(bodyProto.getKey());
body.setTimestamp(bodyProto.getTimestamp());
@ -94,8 +87,7 @@ public class ClientMessageDecoder {
return body;
}
if (CIMConstant.ProtobufType.MESSAGE == type) {
MessageProto.Model bodyProto = MessageProto.Model.parseFrom(bytes);
MessageProto.Model bodyProto = MessageProto.Model.parseFrom(bodyBuffer.array());
Message message = new Message();
message.setId(bodyProto.getId());
message.setAction(bodyProto.getAction());
@ -109,10 +101,6 @@ public class ClientMessageDecoder {
return message;
}
return null;
}
/**
* 解析消息体长度
*/

View File

@ -23,23 +23,20 @@ package com.farsunset.cim.sdk.android.coder;
import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.model.Protobufable;
import com.farsunset.cim.sdk.android.model.SentBody;
import java.nio.ByteBuffer;
/**
* 客户端消息发送前进行编码
*/
public class ClientMessageEncoder {
public ByteBuffer encode(Object object) {
public ByteBuffer encode(Protobufable body) {
Protobufable data = (Protobufable) object;
byte[] byteArray = data.getByteArray();
byte[] data = body.getByteArray();
ByteBuffer buffer = ByteBuffer.allocate(byteArray.length + CIMConstant.DATA_HEADER_LENGTH);
ByteBuffer buffer = ByteBuffer.allocate(data.length + CIMConstant.DATA_HEADER_LENGTH);
buffer.put(createHeader(data.getType(), byteArray.length));
buffer.put(byteArray);
buffer.put(createHeader(body.getType(), data.length));
buffer.put(data);
buffer.flip();
return buffer;

View File

@ -21,39 +21,31 @@
*/
package com.farsunset.cim.sdk.android.constant;
/**
* 常量
*/
public interface CIMConstant {
long RECONNECT_INTERVAL_TIME = 30 * 1000;
/**
消息头长度为3个字节第一个字节为消息类型第二第三字节 转换int后为消息长度
/*
* 消息头长度为3个字节第一个字节为消息类型第二第三字节 转换int后为消息长度
*/
int DATA_HEADER_LENGTH = 3;
interface ReturnCode {
String CODE_404 = "404";
String CODE_403 = "403";
String CODE_405 = "405";
String CODE_200 = "200";
String CODE_206 = "206";
String CODE_500 = "500";
}
interface ProtobufType {
/*
客户端->服务端 发送的心跳响应
*/
byte C_H_RS = 0;
/*
服务端->客户端 发送的心跳请求
*/
byte S_H_RQ = 1;
byte MESSAGE = 2;
byte SENT_BODY = 3;
byte REPLY_BODY = 4;
}
@ -61,8 +53,6 @@ public interface CIMConstant {
String CLIENT_BIND = "client_bind";
String CLIENT_LOGOUT = "client_logout";
}
interface MessageAction {

View File

@ -0,0 +1,133 @@
/*
* Copyright 2013-2019 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.logger;
import android.util.Log;
import java.nio.channels.SocketChannel;
/**
* 日志打印添加session 的id和ip address
*/
public class CIMLogger {
private final static String TAG = "CIM";
private boolean debug = true;
public static CIMLogger getLogger() {
return LoggerHolder.logger;
}
private CIMLogger() {
}
private static class LoggerHolder {
private static final CIMLogger logger = new CIMLogger();
}
public void debugMode(boolean mode) {
debug = mode;
}
public void messageReceived(SocketChannel session, Object message) {
if (debug) {
Log.i(TAG, String.format("[RECEIVED]" + getSessionInfo(session) + "\n%s", message));
}
}
public void messageSent(SocketChannel session, Object message) {
if (debug) {
Log.i(TAG, String.format("[ SENT ]" + getSessionInfo(session) + "\n%s", message));
}
}
public void sessionCreated(SocketChannel session) {
if (debug) {
Log.i(TAG, "[ OPENED ]" + getSessionInfo(session));
}
}
public void sessionIdle(SocketChannel session) {
if (debug) {
Log.d(TAG, "[ IDLE ]" + getSessionInfo(session));
}
}
public void sessionClosed(SocketChannel session) {
if (debug) {
Log.w(TAG, "[ CLOSED ] ID = " + session.hashCode());
}
}
public void connectFailure(long interval) {
if (debug) {
Log.d(TAG, "CONNECT FAILURE, TRY RECONNECT AFTER " + interval + "ms");
}
}
public void startConnect(String host, int port) {
if (debug) {
Log.i(TAG, "START CONNECT REMOTE HOST:" + host + " PORT:" + port);
}
}
public void invalidHostPort(String host, int port) {
if (debug) {
Log.d(TAG, "INVALID SOCKET ADDRESS -> HOST:" + host + " PORT:" + port);
}
}
public void connectState(boolean isConnected, boolean isManualStop, boolean isDestroyed) {
if (debug) {
Log.d(TAG, "CONNECTED:" + isConnected + " STOPPED:" + isManualStop + " DESTROYED:" + isDestroyed);
}
}
private String getSessionInfo(SocketChannel session) {
StringBuilder builder = new StringBuilder();
if (session == null) {
return "";
}
builder.append(" [");
builder.append("id:").append(session.hashCode());
try {
if (session.socket().getLocalAddress() != null) {
builder.append(" L:").append(session.socket().getLocalAddress()).append(":").append(session.socket().getLocalPort());
}
} catch (Exception ignore) {
}
try {
if (session.socket().getRemoteSocketAddress() != null) {
builder.append(" R:").append(session.socket().getRemoteSocketAddress().toString());
}
} catch (Exception ignore) {
}
builder.append("]");
return builder.toString();
}
}

View File

@ -27,7 +27,6 @@ import java.io.Serializable;
/**
* 服务端心跳请求
*
*/
public class HeartbeatRequest implements Serializable, Protobufable {
@ -35,7 +34,7 @@ public class HeartbeatRequest implements Serializable, Protobufable {
private static final String TAG = "SERVER_HEARTBEAT_REQUEST";
private static final String CMD_HEARTBEAT_REQUEST = "SR";
private static HeartbeatRequest object = new HeartbeatRequest();
private static final HeartbeatRequest object = new HeartbeatRequest();
private HeartbeatRequest() {

View File

@ -34,7 +34,7 @@ public class HeartbeatResponse implements Serializable, Protobufable {
private static final String TAG = "CLIENT_HEARTBEAT_RESPONSE";
private static final String CMD_HEARTBEAT_RESPONSE = "CR";
private static HeartbeatResponse object = new HeartbeatResponse();
private static final HeartbeatResponse object = new HeartbeatResponse();
private HeartbeatResponse() {

View File

@ -28,7 +28,6 @@ import java.util.Set;
/**
* 请求应答对象
*
*/
public class ReplyBody implements Serializable {
@ -54,7 +53,7 @@ public class ReplyBody implements Serializable {
/**
* 返回数据集合
*/
private Hashtable<String, String> data = new Hashtable<String, String>();
private final Hashtable<String, String> data = new Hashtable<String, String>();
public long getTimestamp() {
return timestamp;

View File

@ -30,7 +30,6 @@ import java.util.Set;
/**
* java |android 客户端请求结构
*
*/
public class SentBody implements Serializable, Protobufable {
@ -38,7 +37,7 @@ public class SentBody implements Serializable, Protobufable {
private String key;
private Hashtable<String, String> data = new Hashtable<String, String>();;
private final Hashtable<String, String> data = new Hashtable<String, String>();
private long timestamp;

15
cim-client-sdk/cim-java-sdk/cim-java-sdk.iml Normal file → Executable file
View File

@ -1,2 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4" />
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.google.protobuf:protobuf-java:3.11.1" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.30" level="project" />
</component>
</module>

0
cim-client-sdk/cim-java-sdk/jar.bat Normal file → Executable file
View File

0
cim-client-sdk/cim-java-sdk/jar.sh Normal file → Executable file
View File

0
cim-client-sdk/cim-java-sdk/pom.xml Normal file → Executable file
View File

View File

@ -25,7 +25,7 @@ import java.util.HashMap;
class CIMCacheManager {
private static HashMap<String, String> CIM_CONFIG_INFO = new HashMap<String, String>();
private static final HashMap<String, String> CIM_CONFIG_INFO = new HashMap<String, String>();
public static final String KEY_MANUAL_STOP = "KEY_MANUAL_STOP";

View File

@ -30,7 +30,6 @@ import java.nio.channels.SocketChannel;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import com.farsunset.cim.sdk.client.coder.CIMLogger;
import com.farsunset.cim.sdk.client.coder.ClientMessageDecoder;
@ -64,16 +63,15 @@ class CIMConnectorManager {
private ByteBuffer readBuffer = ByteBuffer.allocate(READ_BUFFER_SIZE);
private ExecutorService workerExecutor = Executors.newFixedThreadPool(1, r -> new Thread(r,"worker-"));
private ExecutorService bossExecutor = Executors.newFixedThreadPool(1, r -> new Thread(r,"boss-"));
private ExecutorService eventExecutor = Executors.newFixedThreadPool(1, r -> new Thread(r,"event-"));
private Semaphore semaphore = new Semaphore(1, true);
private final ExecutorService workerExecutor = Executors.newFixedThreadPool(1, r -> new Thread(r,"worker-"));
private final ExecutorService bossExecutor = Executors.newFixedThreadPool(1, r -> new Thread(r,"boss-"));
private final ExecutorService eventExecutor = Executors.newFixedThreadPool(1, r -> new Thread(r,"event-"));
private ClientMessageEncoder messageEncoder = new ClientMessageEncoder();
private ClientMessageDecoder messageDecoder = new ClientMessageDecoder();
private final ClientMessageEncoder messageEncoder = new ClientMessageEncoder();
private final ClientMessageDecoder messageDecoder = new ClientMessageDecoder();
private final ByteBuffer headerBuffer = ByteBuffer.allocate(CIMConstant.DATA_HEADER_LENGTH);
public synchronized static CIMConnectorManager getManager() {
@ -105,8 +103,6 @@ class CIMConnectorManager {
try {
semaphore.acquire();
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(true);
socketChannel.socket().setTcpNoDelay(true);
@ -116,40 +112,30 @@ class CIMConnectorManager {
socketChannel.socket().connect(new InetSocketAddress(host, port),CONNECT_TIME_OUT);
semaphore.release();
handelConnectedEvent();
handleConnectedEvent();
int result = -1;
while((result = socketChannel.read(readBuffer)) > 0) {
if(readBuffer.position() == readBuffer.capacity()) {
extendByteBuffer();
/*
*开始读取来自服务端的消息先读取3个字节的消息头
*/
while (socketChannel.read(headerBuffer) > 0) {
handleSocketReadEvent();
}
handelSocketReadEvent(result);
}
handelSocketReadEvent(result);
/*
*read 返回 <= 0的情况发生了意外需要断开重链
*/
closeSession();
}catch(ConnectException | SocketTimeoutException ignore){
semaphore.release();
handleConnectAbortedEvent();
} catch(IOException ignore) {
semaphore.release();
handelDisconnectedEvent();
}catch (InterruptedException ignore) {
semaphore.release();
handleDisconnectedEvent();
}
});
}
private void handelDisconnectedEvent() {
private void handleDisconnectedEvent() {
closeSession();
}
@ -166,48 +152,24 @@ class CIMConnectorManager {
}
private void handelConnectedEvent() {
private void handleConnectedEvent() {
sessionCreated();
}
private void handelSocketReadEvent(int result) {
private void handleSocketReadEvent() throws IOException {
if(result == -1) {
closeSession();
return;
}
readBuffer.position(0);
Object message = messageDecoder.doDecode(readBuffer);
if(message == null) {
return;
}
Object message = messageDecoder.doDecode(headerBuffer,socketChannel);
LOGGER.messageReceived(socketChannel, message);
if (isHeartbeatRequest(message)) {
send(getHeartbeatResponse());
send(HeartbeatResponse.getInstance());
return;
}
this.messageReceived(message);
}
private void extendByteBuffer() {
ByteBuffer newBuffer = ByteBuffer.allocate(readBuffer.capacity() + READ_BUFFER_SIZE / 2);
readBuffer.position(0);
newBuffer.put(readBuffer);
readBuffer.clear();
readBuffer = newBuffer;
}
@ -221,8 +183,6 @@ class CIMConnectorManager {
int result = 0;
try {
semaphore.acquire();
ByteBuffer buffer = messageEncoder.encode(body);
while(buffer.hasRemaining()){
result += socketChannel.write(buffer);
@ -232,8 +192,6 @@ class CIMConnectorManager {
result = -1;
}finally {
semaphore.release();
if(result <= 0) {
closeSession();
}else {
@ -302,10 +260,6 @@ class CIMConnectorManager {
}
}
public HeartbeatResponse getHeartbeatResponse() {
return HeartbeatResponse.getInstance();
}
public boolean isHeartbeatRequest(Object data) {
return data instanceof HeartbeatRequest;
}

View File

@ -38,7 +38,7 @@ public class CIMEventBroadcastReceiver {
private static CIMEventBroadcastReceiver receiver;
private CIMEventListener listener;
private ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, r -> {
private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, r -> {
Thread thread = new Thread(r);
thread.setName("cim-reconnect-");
return thread;

View File

@ -36,8 +36,8 @@ import com.farsunset.cim.sdk.client.model.ReplyBody;
*/
public class CIMListenerManager {
private static ArrayList<CIMEventListener> cimListeners = new ArrayList<CIMEventListener>();
private static CIMMessageReceiveComparator comparator = new CIMMessageReceiveComparator();
private static final ArrayList<CIMEventListener> cimListeners = new ArrayList<CIMEventListener>();
private static final CIMMessageReceiveComparator comparator = new CIMMessageReceiveComparator();
private static final Logger LOGGER = LoggerFactory.getLogger(CIMListenerManager.class);
public static void registerMessageListener(CIMEventListener listener) {
@ -56,9 +56,9 @@ public class CIMListenerManager {
}
}
public static void notifyOnConnectionSuccessed(boolean antoBind) {
public static void notifyOnConnectFinished(boolean autoBind) {
for (CIMEventListener listener : cimListeners) {
listener.onConnectFinished(antoBind);
listener.onConnectFinished(autoBind);
}
}
@ -80,13 +80,13 @@ public class CIMListenerManager {
}
}
public static void notifyOnConnectionFailed() {
public static void notifyOnConnectFailed() {
for (CIMEventListener listener : cimListeners) {
listener.onConnectFailed();
}
}
public static void destory() {
public static void destroy() {
cimListeners.clear();
}

View File

@ -87,10 +87,10 @@ public class CIMPushManager {
protected static void connect() {
boolean isManualStop = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_MANUAL_STOP);
boolean isManualDestroy = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
boolean isManualStopped = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_MANUAL_STOP);
boolean isManualDestroyed = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
if (isManualStop || isManualDestroy) {
if (isManualStopped || isManualDestroyed) {
return;
}
@ -124,8 +124,8 @@ public class CIMPushManager {
*/
public static void bindAccount(String account) {
boolean isManualDestroy = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
if (isManualDestroy || account == null || account.trim().length() == 0) {
boolean isManualDestroyed = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
if (isManualDestroyed || account == null || account.trim().length() == 0) {
return;
}
sendBindRequest(account);
@ -136,9 +136,9 @@ public class CIMPushManager {
String account = getAccount();
boolean isManualDestory = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
boolean isManualStoped = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_MANUAL_STOP);
if (isManualStoped || account == null || account.trim().length() == 0 || isManualDestory) {
boolean isManualDestroyed = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
boolean isManualStopped = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_MANUAL_STOP);
if (isManualStopped || account == null || account.trim().length() == 0 || isManualDestroyed) {
return false;
}
@ -154,10 +154,10 @@ public class CIMPushManager {
*/
public static void sendRequest(SentBody body) {
boolean isManualStop = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_MANUAL_STOP);
boolean isManualDestroy = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
boolean isManualStopped = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_MANUAL_STOP);
boolean isManualDestroyed = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
if (isManualStop || isManualDestroy) {
if (isManualStopped || isManualDestroyed) {
return;
}
@ -174,8 +174,8 @@ public class CIMPushManager {
*/
public static void stop() {
boolean isManualDestroy = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
if (isManualDestroy) {
boolean isManualDestroyed = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
if (isManualDestroyed) {
return;
}
@ -199,12 +199,12 @@ public class CIMPushManager {
}
/**
* 重新恢复接收推送重新连接服务端并登录当前账号如果aotuBind == true
* 重新恢复接收推送重新连接服务端并登录当前账号如果autoBind == true
*/
public static void resume() {
boolean isManualDestroy = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
if (isManualDestroy) {
boolean isManualDestroyed = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
if (isManualDestroyed) {
return;
}
@ -216,13 +216,13 @@ public class CIMPushManager {
}
public static int getState() {
boolean isManualDestroy = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
if (isManualDestroy) {
boolean isManualDestroyed = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_CIM_DESTROYED);
if (isManualDestroyed) {
return STATE_DESTROYED;
}
boolean isManualStop = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_MANUAL_STOP);
if (isManualStop) {
boolean isManualStopped = CIMCacheManager.getInstance().getBoolean(CIMCacheManager.KEY_MANUAL_STOP);
if (isManualStopped) {
return STATE_STOPPED;
}

View File

@ -29,7 +29,7 @@ import com.farsunset.cim.sdk.client.model.SentBody;
*/
public class CIMPushService {
private CIMConnectorManager manager;
private final CIMConnectorManager manager;
private static CIMPushService service;

View File

@ -42,7 +42,7 @@ public class CIMLogger {
}
private static class LoggerHolder{
private static CIMLogger logger = new CIMLogger();
private static final CIMLogger logger = new CIMLogger();
}

View File

@ -22,7 +22,9 @@
package com.farsunset.cim.sdk.client.coder;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import com.farsunset.cim.sdk.client.constant.CIMConstant;
import com.farsunset.cim.sdk.client.model.HeartbeatRequest;
@ -30,60 +32,56 @@ import com.farsunset.cim.sdk.client.model.Message;
import com.farsunset.cim.sdk.client.model.ReplyBody;
import com.farsunset.cim.sdk.model.proto.MessageProto;
import com.farsunset.cim.sdk.model.proto.ReplyBodyProto;
import com.google.protobuf.InvalidProtocolBufferException;
/**
* 客户端消息解码
*/
public class ClientMessageDecoder {
/**
*
* @param headerBuffer 读取到的消息头
* @param socketChannel
* @return
*/
public Object doDecode(ByteBuffer iobuffer) {
public Object doDecode(ByteBuffer headerBuffer , SocketChannel socketChannel) throws IOException {
headerBuffer.position(0);
byte type = headerBuffer.get();
byte lv = headerBuffer.get();
byte hv = headerBuffer.get();
headerBuffer.clear();
/*
* 消息头3位
* 先通过消息头拿到消息的长度然后进行定长读取
* 解决消息的断包和粘包情况
*/
if (iobuffer.remaining() < CIMConstant.DATA_HEADER_LENGTH) {
return null;
}
iobuffer.mark();
int dataLength = getContentLength(lv, hv);
byte type = iobuffer.get();
ByteBuffer bodyBuffer = ByteBuffer.allocate(dataLength);
byte lv = iobuffer.get();
byte hv = iobuffer.get();
/*
* 如果读取的消息长度不够则进行等待后续消息到来
* 当读取的消息长度(bodyBuffer.position() == dataLength)时意味着一个完整的消息已经接收完成
*/
do {
socketChannel.read(bodyBuffer);
} while (bodyBuffer.position() != dataLength);
int length = getContentLength(lv, hv);
// 如果消息体没有接收完整则重置读取等待下一次重新读取
if (length > iobuffer.remaining()) {
iobuffer.reset();
return null;
}
byte[] dataBytes = new byte[length];
iobuffer.get(dataBytes, 0, length);
iobuffer.position(0);
try {
return mappingMessageObject(dataBytes, type);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
return null;
}
}
private Object mappingMessageObject(byte[] bytes, byte type) throws InvalidProtocolBufferException {
/*
消息读取完成后通过type来解析成对应的消息体
*/
if (CIMConstant.ProtobufType.S_H_RQ == type) {
return HeartbeatRequest.getInstance();
}
if (CIMConstant.ProtobufType.REPLY_BODY == type) {
ReplyBodyProto.Model bodyProto = ReplyBodyProto.Model.parseFrom(bytes);
ReplyBodyProto.Model bodyProto = ReplyBodyProto.Model.parseFrom(bodyBuffer.array());
ReplyBody body = new ReplyBody();
body.setKey(bodyProto.getKey());
body.setTimestamp(bodyProto.getTimestamp());
@ -93,8 +91,7 @@ public class ClientMessageDecoder {
return body;
}
if (CIMConstant.ProtobufType.MESSAGE == type) {
MessageProto.Model bodyProto = MessageProto.Model.parseFrom(bytes);
MessageProto.Model bodyProto = MessageProto.Model.parseFrom(bodyBuffer.array());
Message message = new Message();
message.setId(bodyProto.getId());
message.setAction(bodyProto.getAction());
@ -108,14 +105,8 @@ public class ClientMessageDecoder {
return message;
}
return null;
}
/**
* 解析消息体长度
*
* @return
*/
private int getContentLength(byte lv, byte hv) {
int l = (lv & 0xff);
@ -123,4 +114,5 @@ public class ClientMessageDecoder {
return (l | h << 8);
}
}

View File

@ -32,15 +32,14 @@ import com.farsunset.cim.sdk.client.model.Protobufable;
*/
public class ClientMessageEncoder {
public ByteBuffer encode(Object object) {
public ByteBuffer encode(Protobufable body) {
Protobufable data = (Protobufable) object;
byte[] byteArray = data.getByteArray();
byte[] data = body.getByteArray();
ByteBuffer ioBuffer = ByteBuffer.allocate(byteArray.length + CIMConstant.DATA_HEADER_LENGTH);
ByteBuffer ioBuffer = ByteBuffer.allocate(data.length + CIMConstant.DATA_HEADER_LENGTH);
ioBuffer.put(createHeader(data.getType(), byteArray.length));
ioBuffer.put(byteArray);
ioBuffer.put(createHeader(body.getType(), data.length));
ioBuffer.put(data);
ioBuffer.flip();
return ioBuffer;

View File

@ -27,26 +27,11 @@ package com.farsunset.cim.sdk.client.constant;
public interface CIMConstant {
long RECONNECT_INTERVAL_TIME = 30 * 1000;
/**
/*
* 消息头长度为3个字节第一个字节为消息类型第二第三字节 转换int后为消息长度
*/
int DATA_HEADER_LENGTH = 3;
interface ReturnCode {
String CODE_404 = "404";
String CODE_403 = "403";
String CODE_405 = "405";
String CODE_200 = "200";
String CODE_206 = "206";
String CODE_500 = "500";
}
interface ConfigKey {

View File

@ -35,7 +35,7 @@ public class HeartbeatRequest implements Serializable, Protobufable {
private static final String TAG = "SERVER_HEARTBEAT_REQUEST";
private static final String CMD_HEARTBEAT_RESPONSE = "SR";
private static HeartbeatRequest object = new HeartbeatRequest();
private static final HeartbeatRequest object = new HeartbeatRequest();
private HeartbeatRequest() {

View File

@ -34,7 +34,7 @@ public class HeartbeatResponse implements Serializable, Protobufable {
private static final String TAG = "CLIENT_HEARTBEAT_RESPONSE";
private static final String CMD_HEARTBEAT_RESPONSE = "CR";
private static HeartbeatResponse object = new HeartbeatResponse();
private static final HeartbeatResponse object = new HeartbeatResponse();
private HeartbeatResponse() {

View File

@ -34,7 +34,7 @@ public class Intent implements Serializable {
private String action;
private HashMap<String, Object> data = new HashMap<String, Object>();
private final HashMap<String, Object> data = new HashMap<String, Object>();
public Intent() {
}

View File

@ -1,13 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<compositeConfiguration>
<compositeBuild compositeDefinitionSource="SCRIPT" />
</compositeConfiguration>
<option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>

View File

@ -4,6 +4,8 @@
<modules>
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
<module fileurl="file://$PROJECT_DIR$/cim-client-android.iml" filepath="$PROJECT_DIR$/cim-client-android.iml" />
<module fileurl="file://$PROJECT_DIR$/app/cim-client-android-app.iml" filepath="$PROJECT_DIR$/app/cim-client-android-app.iml" group="cim-client-android/app" />
<module fileurl="file://$PROJECT_DIR$/cim-use-examples-cim-client-android.iml" filepath="$PROJECT_DIR$/cim-use-examples-cim-client-android.iml" group="cim-client-android" />
</modules>
</component>
</project>

View File

@ -65,11 +65,6 @@ public class SystemMsgListViewAdapter extends BaseAdapter {
return 0;
}
@Override
public void notifyDataSetChanged() {
//Collections.sort(list, new MessageTimeDescComparator());
}
@SuppressLint("ViewHolder")
@Override
public View getView(int position, View chatItemView, ViewGroup parent) {

View File

@ -24,7 +24,7 @@ package com.farsunset.ichat.example.app;
public interface Constant {
//服务端IP地址
String CIM_SERVER_HOST = "192.168.1.88";
String CIM_SERVER_HOST = "192.168.2.103";
//注意这里的端口不是tomcat的端口没改动就使用默认的23456
int CIM_SERVER_PORT = 23456;

View File

@ -88,7 +88,7 @@ public class LoginActivity extends CIMMonitorActivity implements OnClickListener
/*
* 收到code为200的回应 账号绑定成功
*/
if (reply.getKey().equals(CIMConstant.RequestKey.CLIENT_BIND) && reply.getCode().equals(CIMConstant.ReturnCode.CODE_200)) {
if (reply.getKey().equals(CIMConstant.RequestKey.CLIENT_BIND) && reply.getCode().equals("200")) {
Intent intent = new Intent(this, SystemMessageActivity.class);
intent.putExtra("account", accountEdit.getText().toString().trim());
startActivity(intent);

View File

@ -87,9 +87,14 @@ public class SystemMessageActivity extends CIMMonitorActivity implements OnClick
startActivity(intent);
this.finish();
} else {
list.add(message);
list.add(0,message);
adapter.notifyDataSetChanged();
chatListView.setSelection(chatListView.getTop());
chatListView.postDelayed(new Runnable() {
@Override
public void run() {
chatListView.setSelection(0);
}
},500);
}
}

View File

@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.android.tools.build:gradle:3.6.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@ -1,7 +1,6 @@
#Mon May 13 14:19:31 CST 2019
#Fri Mar 06 13:42:48 CST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.google.protobuf:protobuf-java:3.11.1" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.30" level="project" />
<orderEntry type="module-library">
<library name="Maven: com.farsunset:cim-java-sdk:3.8.0">
<CLASSES>
<root url="jar://$MODULE_DIR$/libs/cim-java-sdk-3.8.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>