This commit is contained in:
yuhaiming
2026-05-09 10:12:36 +08:00
parent def9b89ecd
commit 39fe8065da
80 changed files with 3883 additions and 6102 deletions

BIN
.idea/.cache/.Apifox_Helper/.toolWindow.db generated Normal file

Binary file not shown.

12
.idea/ApifoxUploaderProjectSetting.xml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ApifoxUploaderProjectSetting">
<option name="apiAccessToken" value="afxp_50a721c5J4ATh9Deij55QbuH34yDtScWPyUe" />
<option name="apiProjectIds">
<array>
<option value="&lt;byte-array&gt;rO0ABXNyADZjb20uaXRhbmdjZW50LmlkZWEucGx1Z2luLmFwaS5hY2NvdW50LlByb2plY3RBbmRNb2R1bGUAAAAAAAAAAQIAFVoABmVuYWJsZUwACG1vZHVsZUlkdAASTGphdmEvbGFuZy9TdHJpbmc7TAAGb3RoZXIxcQB+AAFMAAdvdGhlcjEwcQB+AAFMAAdvdGhlcjExcQB+AAFMAAdvdGhlcjEycQB+AAFMAAZvdGhlcjJxAH4AAUwABm90aGVyM3EAfgABTAAGb3RoZXI0cQB+AAFMAAZvdGhlcjVxAH4AAUwABm90aGVyNnEAfgABTAAGb3RoZXI3cQB+AAFMAAZvdGhlcjhxAH4AAUwABm90aGVyOXEAfgABTAAKcGF0aEJlZm9yZXEAfgABTAANcHJvamVjdEZvbGRlcnEAfgABTAAPcHJvamVjdEZvbGRlcklkcQB+AAFMAAlwcm9qZWN0SWRxAH4AAUwAC3Byb2plY3ROYW1lcQB+AAFMAAxzY2hlbWFGb2xkZXJxAH4AAUwACHNjaGVtYUlkcQB+AAF4cAF0AAt3YXRlci1hZG1pbnQABzc5MzY0NzhwcHB0AAc3NjEzNTE2dAALYnJhbmNoLW1haW50AAzpu5jorqTmqKHlnZdwcHBwcHQAAHQACeagueebruW9lXQAATB0AAc4MTc3MzA3dAAM5pm66IO954GM5rqJcQB+AAlxAH4ACg==&lt;/byte-array&gt;" />
</array>
</option>
<option name="treeNodesJTree" value="&lt;byte-array&gt;rO0ABXNyACFqYXZheC5zd2luZy50cmVlLkRlZmF1bHRUcmVlTW9kZWynvpEmGsXl2QMAA1oAEmFza3NBbGxvd3NDaGlsZHJlbkwADGxpc3RlbmVyTGlzdHQAJUxqYXZheC9zd2luZy9ldmVudC9FdmVudExpc3RlbmVyTGlzdDtMAARyb290dAAbTGphdmF4L3N3aW5nL3RyZWUvVHJlZU5vZGU7eHAAc3IAI2phdmF4LnN3aW5nLmV2ZW50LkV2ZW50TGlzdGVuZXJMaXN0kUjMLXPfDt4DAAB4cHB4c3IAJ2phdmF4LnN3aW5nLnRyZWUuRGVmYXVsdE11dGFibGVUcmVlTm9kZcRYv/zyqHHgAwADWgAOYWxsb3dzQ2hpbGRyZW5MAAhjaGlsZHJlbnQAEkxqYXZhL3V0aWwvVmVjdG9yO0wABnBhcmVudHQAIkxqYXZheC9zd2luZy90cmVlL011dGFibGVUcmVlTm9kZTt4cAFzcgAQamF2YS51dGlsLlZlY3RvctmXfVuAO68BAwADSQARY2FwYWNpdHlJbmNyZW1lbnRJAAxlbGVtZW50Q291bnRbAAtlbGVtZW50RGF0YXQAE1tMamF2YS9sYW5nL09iamVjdDt4cAAAAAAAAAADdXIAE1tMamF2YS5sYW5nLk9iamVjdDuQzlifEHMpbAIAAHhwAAAACnNxAH4ABgFzcQB+AAoAAAAAAAAAAXVxAH4ADQAAAApzcQB+AAYBcHEAfgAPdXEAfgANAAAAAnQACnVzZXJPYmplY3RzcgAuY29tLml0YW5nY2VudC5pZGVhLnBsdWdpbi5hcGkuYWNjb3VudC5UcmVlTm9kZQAAAAAAAAABAgAQTAAHYWxsUGF0aHQAEkxqYXZhL2xhbmcvU3RyaW5nO1sAFGJyYW5jaEFuZFZlcnNpb25JdGVtdABLW0xjb20vaXRhbmdjZW50L2lkZWEvcGx1Z2luL2RpYWxvZy9jb21wb25lbnQvYWNjb3VudC9BY2NvdW50UmlnaHRQYW5lbEl0ZW07TAAUYnJhbmNoSWRBbmRWZXJzaW9uSWRxAH4AFkwACGNoaWxkcmVudAAPTGphdmEvdXRpbC9NYXA7TAAKZm9sZGVyVHlwZXEAfgAWTAAIZnVsbFBhdGhxAH4AFkwAA2tleXEAfgAWWwAJbW9kZWxJdGVtcQB+ABdMAAhtb2R1bGVJZHEAfgAWTAAEbmFtZXEAfgAWTAAIcGFyZW50SWRxAH4AFkwACXByb2plY3RJZHEAfgAWTAALcHJvamVjdE5hbWVxAH4AFkwABnRlYW1JZHEAfgAWTAAIdGVhbU5hbWVxAH4AFkwABHR5cGV0ADBMY29tL2l0YW5nY2VudC9pZGVhL3BsdWdpbi9hcGkvYWNjb3VudC9Ob2RlVHlwZTt4cHQAGeS4quS6uuepuumXtC/kuKrkurrpobnnm65wcHNyABdqYXZhLnV0aWwuTGlua2VkSGFzaE1hcDTATlwQbMD7AgABWgALYWNjZXNzT3JkZXJ4cgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAAdwgAAAAQAAAAAHgAcHB0AAczMDg2MDAwcHB0ABbkuKrkurrpobnnm64gKDMwODYwMDApdAAHMTgyMTY4M3QABzMwODYwMDB0AAzkuKrkurrpobnnm650AAcxODIxNjgzcH5yAC5jb20uaXRhbmdjZW50LmlkZWEucGx1Z2luLmFwaS5hY2NvdW50Lk5vZGVUeXBlAAAAAAAAAAASAAB4cgAOamF2YS5sYW5nLkVudW0AAAAAAAAAABIAAHhwdAAHUFJPSkVDVHhwcHBwcHBwcHB4cQB+AAl1cQB+AA0AAAACcQB+ABRzcQB+ABV0AAzkuKrkurrnqbrpl7RwcHNxAH4AHD9AAAAAAAAAdwgAAAAQAAAAAHgAcHB0AAcxODIxNjgzcHB0AAzkuKrkurrnqbrpl7RwcHB0AAcxODIxNjgzdAAM5Liq5Lq656m66Ze0fnEAfgAldAAEVEVBTXhzcQB+AAYBc3EAfgAKAAAAAAAAAAF1cQB+AA0AAAAKc3EAfgAGAXBxAH4AM3VxAH4ADQAAAAJxAH4AFHNxAH4AFXQAE+mYsuW+oeacui/pmLLlvqHmnLpwcHNxAH4AHD9AAAAAAAAAdwgAAAAQAAAAAHgAcHB0AAc4MDQ0NjM1cHB0ABPpmLLlvqHmnLogKDgwNDQ2MzUpdAAHNDMwMTk2M3QABzgwNDQ2MzV0AAnpmLLlvqHmnLp0AAc0MzAxOTYzcHEAfgAneHBwcHBwcHBwcHhxAH4ACXVxAH4ADQAAAAJxAH4AFHNxAH4AFXQACemYsuW+oeacunBwc3EAfgAcP0AAAAAAAAB3CAAAABAAAAAAeABwcHQABzQzMDE5NjNwcHQACemYsuW+oeacunBwcHQABzQzMDE5NjN0AAnpmLLlvqHmnLpxAH4AMXhzcQB+AAYBc3EAfgAKAAAAAAAAAAF1cQB+AA0AAAAKc3EAfgAGAXBxAH4ASXVxAH4ADQAAAAJxAH4AFHNxAH4AFXQAGeaZuuiDveeBjOa6iS/mmbrog73ngYzmuol1cgBLW0xjb20uaXRhbmdjZW50LmlkZWEucGx1Z2luLmRpYWxvZy5jb21wb25lbnQuYWNjb3VudC5BY2NvdW50UmlnaHRQYW5lbEl0ZW07KbxSniq4DKkCAAB4cAAAAAFzcgBIY29tLml0YW5nY2VudC5pZGVhLnBsdWdpbi5kaWFsb2cuY29tcG9uZW50LmFjY291bnQuQWNjb3VudFJpZ2h0UGFuZWxJdGVtAAAAAAAAAAECAARaAA9pc01haW5PckRlZmF1bHRMAAhpY29uVHlwZXEAfgAWTAACaWRxAH4AFkwABG5hbWVxAH4AFnhwAXQABmJyYW5jaHQABzc5MzY0Nzh0AARtYWlucHNxAH4AHD9AAAAAAAAAdwgAAAAQAAAAAHgAcHB0AAc4MTc3MzA3dXEAfgBQAAAAAXNxAH4AUgF0AAVtb2RlbHQABzc2MTM1MTZ0AAzpu5jorqTmqKHlnZdwdAAW5pm66IO954GM5rqJICg4MTc3MzA3KXQABzQzOTAwMDh0AAc4MTc3MzA3dAAM5pm66IO954GM5rqJdAAHNDM5MDAwOHBxAH4AJ3hwcHBwcHBwcHB4cQB+AAl1cQB+AA0AAAACcQB+ABRzcQB+ABV0AAzmmbrog73ngYzmuolwcHNxAH4AHD9AAAAAAAAAdwgAAAAQAAAAAHgAcHB0AAc0MzkwMDA4cHB0AAzmmbrog73ngYzmuolwcHB0AAc0MzkwMDA4dAAM5pm66IO954GM5rqJcQB+ADF4cHBwcHBwcHhwdXEAfgANAAAAAnEAfgAUc3EAfgAVdAAEUm9vdHBwcHBwdAABMHBwcQB+AG1wcHBwcHEAfgAxeHNxAH4ACgAAAAAAAAACdXEAfgANAAAACnQABHJvb3RxAH4ACXBwcHBwcHBweHg=&lt;/byte-array&gt;" />
</component>
</project>

24
.idea/compiler.xml generated
View File

@@ -8,18 +8,18 @@
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" /> <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" /> <outputRelativeToContentRoot value="true" />
<processorPath useClasspath="false"> <processorPath useClasspath="false">
<entry name="$MAVEN_REPOSITORY$/com/github/therapi/therapi-runtime-javadoc-scribe/0.15.0/therapi-runtime-javadoc-scribe-0.15.0.jar" /> <entry name="$PROJECT_DIR$/../../repository/com/github/therapi/therapi-runtime-javadoc-scribe/0.15.0/therapi-runtime-javadoc-scribe-0.15.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/github/therapi/therapi-runtime-javadoc/0.15.0/therapi-runtime-javadoc-0.15.0.jar" /> <entry name="$PROJECT_DIR$/../../repository/com/github/therapi/therapi-runtime-javadoc/0.15.0/therapi-runtime-javadoc-0.15.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/projectlombok/lombok/1.18.42/lombok-1.18.42.jar" /> <entry name="$PROJECT_DIR$/../../repository/org/projectlombok/lombok/1.18.42/lombok-1.18.42.jar" />
<entry name="$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-configuration-processor/3.5.12/spring-boot-configuration-processor-3.5.12.jar" /> <entry name="$PROJECT_DIR$/../../repository/org/springframework/boot/spring-boot-configuration-processor/3.5.12/spring-boot-configuration-processor-3.5.12.jar" />
<entry name="$MAVEN_REPOSITORY$/io/github/linpeilie/mapstruct-plus-processor/1.5.0/mapstruct-plus-processor-1.5.0.jar" /> <entry name="$PROJECT_DIR$/../../repository/io/github/linpeilie/mapstruct-plus-processor/1.5.0/mapstruct-plus-processor-1.5.0.jar" />
<entry name="$MAVEN_REPOSITORY$/io/github/linpeilie/mapstruct-plus/1.5.0/mapstruct-plus-1.5.0.jar" /> <entry name="$PROJECT_DIR$/../../repository/io/github/linpeilie/mapstruct-plus/1.5.0/mapstruct-plus-1.5.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/mapstruct/mapstruct/1.6.3/mapstruct-1.6.3.jar" /> <entry name="$PROJECT_DIR$/../../repository/org/mapstruct/mapstruct/1.6.3/mapstruct-1.6.3.jar" />
<entry name="$MAVEN_REPOSITORY$/io/github/linpeilie/mapstruct-plus-object-convert/1.5.0/mapstruct-plus-object-convert-1.5.0.jar" /> <entry name="$PROJECT_DIR$/../../repository/io/github/linpeilie/mapstruct-plus-object-convert/1.5.0/mapstruct-plus-object-convert-1.5.0.jar" />
<entry name="$MAVEN_REPOSITORY$/cn/easii/tutelary-repackage-javapoet/1.0.5/tutelary-repackage-javapoet-1.0.5.jar" /> <entry name="$PROJECT_DIR$/../../repository/cn/easii/tutelary-repackage-javapoet/1.0.5/tutelary-repackage-javapoet-1.0.5.jar" />
<entry name="$MAVEN_REPOSITORY$/org/mapstruct/mapstruct-processor/1.6.3/mapstruct-processor-1.6.3.jar" /> <entry name="$PROJECT_DIR$/../../repository/org/mapstruct/mapstruct-processor/1.6.3/mapstruct-processor-1.6.3.jar" />
<entry name="$MAVEN_REPOSITORY$/org/mapstruct/tools/gem/gem-api/1.0.0.Alpha3/gem-api-1.0.0.Alpha3.jar" /> <entry name="$PROJECT_DIR$/../../repository/org/mapstruct/tools/gem/gem-api/1.0.0.Alpha3/gem-api-1.0.0.Alpha3.jar" />
<entry name="$MAVEN_REPOSITORY$/org/projectlombok/lombok-mapstruct-binding/0.2.0/lombok-mapstruct-binding-0.2.0.jar" /> <entry name="$PROJECT_DIR$/../../repository/org/projectlombok/lombok-mapstruct-binding/0.2.0/lombok-mapstruct-binding-0.2.0.jar" />
</processorPath> </processorPath>
<module name="water-app" /> <module name="water-app" />
<module name="water-common-excel" /> <module name="water-common-excel" />

17
.idea/dataSources.xml generated Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="water@localhost" uuid="35c4cdc9-3d60-4dc9-bf1d-92174c5f87ab">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://localhost:3306/water</jdbc-url>
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
<property name="com.intellij.clouds.kubernetes.db.container.port" />
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

14
.idea/encodings.xml generated
View File

@@ -1,12 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="Encoding"> <component name="Encoding" defaultCharsetForPropertiesFiles="UTF-8">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-admin/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-admin/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-admin/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-admin/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-core/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-core/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-core/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-core/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-doc/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-doc/src/main/java" charset="UTF-8" />
@@ -14,7 +10,6 @@
<file url="file://$PROJECT_DIR$/water-common/water-common-encrypt/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-encrypt/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-encrypt/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-encrypt/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-excel/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-excel/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-excel/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-idempotent/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-idempotent/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-idempotent/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-idempotent/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-job/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-job/src/main/java" charset="UTF-8" />
@@ -28,7 +23,6 @@
<file url="file://$PROJECT_DIR$/water-common/water-common-mybatis/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-mybatis/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-mybatis/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-mybatis/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-oss/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-oss/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-oss/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-ratelimiter/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-ratelimiter/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-ratelimiter/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-ratelimiter/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-redis/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-redis/src/main/java" charset="UTF-8" />
@@ -38,7 +32,6 @@
<file url="file://$PROJECT_DIR$/water-common/water-common-security/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-security/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-security/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-security/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-sensitive/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-sensitive/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-sensitive/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-sms/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-sms/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-sms/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-sms/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-social/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-social/src/main/java" charset="UTF-8" />
@@ -53,14 +46,10 @@
<file url="file://$PROJECT_DIR$/water-common/water-common-web/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-web/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-websocket/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-websocket/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-common/water-common-websocket/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-common/water-common-websocket/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-extend/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-extend/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-extend/water-monitor-admin/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-extend/water-monitor-admin/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-extend/water-monitor-admin/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-extend/water-monitor-admin/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-extend/water-snailjob-server/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-extend/water-snailjob-server/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-extend/water-snailjob-server/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-extend/water-snailjob-server/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-modules/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-modules/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-modules/water-app/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-modules/water-app/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-modules/water-app/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-modules/water-app/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-modules/water-demo/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-modules/water-demo/src/main/java" charset="UTF-8" />
@@ -68,7 +57,6 @@
<file url="file://$PROJECT_DIR$/water-modules/water-generator/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-modules/water-generator/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-modules/water-generator/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-modules/water-generator/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-modules/water-job/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-modules/water-job/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-modules/water-job/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-modules/water-system/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-modules/water-system/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-modules/water-system/src/main/resources" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-modules/water-system/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/water-modules/water-workflow/src/main/java" charset="UTF-8" /> <file url="file://$PROJECT_DIR$/water-modules/water-workflow/src/main/java" charset="UTF-8" />

View File

@@ -6,6 +6,11 @@
<option name="name" value="Central Repository" /> <option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" /> <option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository> </remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="http://maven.aliyun.com/nexus/content/repositories/central/" />
</remote-repository>
<remote-repository> <remote-repository>
<option name="id" value="central" /> <option name="id" value="central" />
<option name="name" value="Maven Central repository" /> <option name="name" value="Maven Central repository" />

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,136 +1,662 @@
2026-04-24 08:28:21 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final 2026-05-09 09:01:56 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2026-04-24 08:28:21 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 22648 (D:\code\water\water-admin\target\classes started by admin in D:\code\water) 2026-05-09 09:01:56 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 32304 (D:\code\water\water-admin\target\classes started by admin in D:\code\water)
2026-04-24 08:28:21 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev" 2026-05-09 09:01:56 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev"
2026-04-24 08:28:24 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext 2026-05-09 09:02:00 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext
2026-04-24 08:28:24 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it 2026-05-09 09:02:00 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it
2026-04-24 08:28:24 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting... 2026-05-09 09:02:00 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting...
2026-04-24 08:32:49 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final 2026-05-09 09:02:00 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@2403c1c5
2026-04-24 08:32:49 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 9636 (D:\code\water\water-admin\target\classes started by admin in D:\code\water) 2026-05-09 09:02:00 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed.
2026-04-24 08:32:49 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev" 2026-05-09 09:02:00 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success
2026-04-24 08:32:53 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext 2026-05-09 09:02:00 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
2026-04-24 08:32:53 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it 2026-05-09 09:02:02 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置
2026-04-24 08:32:53 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting... 2026-05-09 09:02:02 [main] INFO org.redisson.Version - Redisson 3.52.0
2026-04-24 08:32:53 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@7322013f 2026-05-09 09:02:02 [redisson-netty-1-5] INFO o.r.connection.ConnectionsHolder - 1 connections initialized for localhost/127.0.0.1:6379
2026-04-24 08:32:53 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed. 2026-05-09 09:02:02 [redisson-netty-1-4] INFO o.r.connection.ConnectionsHolder - 8 connections initialized for localhost/127.0.0.1:6379
2026-04-24 08:32:53 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success 2026-05-09 09:02:03 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-04-24 08:32:53 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master] 2026-05-09 09:02:03 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-04-24 08:32:54 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置 2026-05-09 09:02:03 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-04-24 08:32:55 [main] INFO org.redisson.Version - Redisson 3.52.0 2026-05-09 09:02:04 [main] INFO o.d.common.json.config.JacksonConfig - 初始化 jackson 配置
2026-04-24 08:33:02 [main] INFO o.d.c.core.config.ThreadPoolConfig - ====关闭后台任务任务线程池==== 2026-05-09 09:02:04 [main] INFO c.a.s.c.s.SnailJobClientJobCoreAutoConfiguration - Snail-Job 客户端IP为: 192.168.0.217
2026-04-24 08:33:02 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource start closing .... 2026-05-09 09:02:04 [main] INFO c.b.m.e.s.MybatisPlusApplicationContextAware - Register ApplicationContext instances org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@65bb9029
2026-04-24 08:33:02 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown initiated... 2026-05-09 09:02:08 [main] INFO o.d.w.p.modes.sb.config.BeanConfig - 【warm-flow】加载完成
2026-04-24 08:33:02 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown completed. 2026-05-09 09:02:09 [main] INFO io.undertow - starting server: Undertow - 2.3.23.Final
2026-04-24 08:33:02 [main] INFO c.b.d.d.d.DefaultDataSourceDestroyer - dynamic-datasource close the datasource named [master] success, 2026-05-09 09:02:09 [main] INFO org.xnio - XNIO version 3.8.16.Final
2026-04-24 08:33:02 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource all closed success,bye 2026-05-09 09:02:09 [main] INFO org.xnio.nio - XNIO NIO Implementation Version 3.8.16.Final
2026-04-24 08:33:29 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final 2026-05-09 09:02:09 [main] INFO org.jboss.threads - JBoss Threads version 3.7.0.Final
2026-04-24 08:33:29 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 29592 (D:\code\water\water-admin\target\classes started by admin in D:\code\water) 2026-05-09 09:02:09 [main] INFO org.dromara.DromaraApplication - Started DromaraApplication in 14.199 seconds (process running for 15.467)
2026-04-24 08:33:29 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev" 2026-05-09 09:02:09 [main] INFO o.d.c.sse.listener.SseTopicListener - 初始化SSE主题订阅监听器成功
2026-04-24 08:33:32 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext 2026-05-09 09:02:09 [main] INFO o.d.s.runner.SystemApplicationRunner - 初始化OSS配置成功
2026-04-24 08:33:32 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it 2026-05-09 09:02:09 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client is preparing to start... v1.9.0
2026-04-24 08:33:32 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting... 2026-05-09 09:02:10 [main] INFO c.a.s.c.c.r.c.g.SnailJobGrpcClient - gRPC client started connect to server
2026-04-24 08:33:33 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@252f00ba 2026-05-09 09:02:10 [main] INFO c.a.s.c.c.rpc.server.SnailGrpcServer - ------> snail-job remoting server start success, grpc = com.aizuda.snailjob.client.common.rpc.server.SnailGrpcServer, port = 28081
2026-04-24 08:33:33 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed. 2026-05-09 09:02:10 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client started successfully v1.9.0
2026-04-24 08:33:33 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success 2026-05-09 09:02:11 [RMI TCP Connection(15)-192.168.111.1] INFO io.undertow.servlet - Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-04-24 08:33:33 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master] 2026-05-09 09:03:15 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[POST /app/v1/addDevice],参数类型[json],参数:[{"device_no":"sn165165fdfdsa","device_name":"测试设备一","device_img":"","wifi_name":"wifi","wifi_password":"12345678","device_em":"dfasdfas","device_sn":"fdasfsadf","fw_ver":"fsdfas","mac_address":"2.285ssadf.fsad"}]
2026-04-24 08:33:34 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置 2026-05-09 09:03:15 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[POST /app/v1/addDevice],耗时:[223]毫秒
2026-04-24 08:33:34 [main] INFO org.redisson.Version - Redisson 3.52.0 2026-05-09 09:03:39 [Thread-5] INFO c.a.s.c.c.window.SlidingRingWindow - JVM is about to exit, emitting data in the Window
2026-04-24 08:33:41 [main] INFO o.d.c.core.config.ThreadPoolConfig - ====关闭后台任务任务线程池==== 2026-05-09 09:03:39 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client about to shutdown v1.9.0
2026-04-24 08:33:41 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource start closing .... 2026-05-09 09:03:39 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log about to shutdown
2026-04-24 08:33:41 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown initiated... 2026-05-09 09:03:39 [SpringApplicationShutdownHook] INFO c.a.s.c.c.window.SlidingRingWindow - Sliding window is about to exit, emitting data in the Window
2026-04-24 08:33:41 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown completed. 2026-05-09 09:03:39 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log has been shutdown
2026-04-24 08:33:41 [main] INFO c.b.d.d.d.DefaultDataSourceDestroyer - dynamic-datasource close the datasource named [master] success, 2026-05-09 09:03:39 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client closed successfully v1.9.0
2026-04-24 08:33:41 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource all closed success,bye 2026-05-09 09:03:39 [SpringApplicationShutdownHook] INFO io.undertow - stopping server: Undertow - 2.3.23.Final
2026-04-24 08:34:25 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final 2026-05-09 09:03:39 [SpringApplicationShutdownHook] INFO o.d.c.core.config.ThreadPoolConfig - ====关闭后台任务任务线程池====
2026-04-24 08:34:25 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 19800 (D:\code\water\water-admin\target\classes started by admin in D:\code\water) 2026-05-09 09:03:39 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource start closing ....
2026-04-24 08:34:25 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev" 2026-05-09 09:03:39 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown initiated...
2026-04-24 08:34:29 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext 2026-05-09 09:03:39 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown completed.
2026-04-24 08:34:29 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it 2026-05-09 09:03:39 [SpringApplicationShutdownHook] INFO c.b.d.d.d.DefaultDataSourceDestroyer - dynamic-datasource close the datasource named [master] success,
2026-04-24 08:34:29 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting... 2026-05-09 09:03:39 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource all closed success,bye
2026-04-24 08:34:30 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@14a488ed 2026-05-09 09:03:39 [SpringApplicationShutdownHook] INFO io.undertow.servlet - Destroying Spring FrameworkServlet 'dispatcherServlet'
2026-04-24 08:34:30 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed. 2026-05-09 09:03:44 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2026-04-24 08:34:30 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success 2026-05-09 09:03:44 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 19172 (D:\code\water\water-admin\target\classes started by admin in D:\code\water)
2026-04-24 08:34:30 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master] 2026-05-09 09:03:44 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev"
2026-04-24 08:34:31 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置 2026-05-09 09:03:47 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext
2026-04-24 08:34:31 [main] INFO org.redisson.Version - Redisson 3.52.0 2026-05-09 09:03:47 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it
2026-04-24 08:34:32 [redisson-netty-1-6] INFO o.r.connection.ConnectionsHolder - 1 connections initialized for localhost/127.0.0.1:6379 2026-05-09 09:03:47 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting...
2026-04-24 08:34:32 [redisson-netty-1-4] INFO o.r.connection.ConnectionsHolder - 8 connections initialized for localhost/127.0.0.1:6379 2026-05-09 09:03:47 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@1001b435
2026-04-24 08:34:33 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker 2026-05-09 09:03:47 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed.
2026-04-24 08:34:33 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker 2026-05-09 09:03:47 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success
2026-04-24 08:34:33 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker 2026-05-09 09:03:47 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
2026-04-24 08:34:33 [main] INFO o.d.common.json.config.JacksonConfig - 初始化 jackson 配置 2026-05-09 09:03:49 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置
2026-04-24 08:34:33 [main] INFO c.a.s.c.s.SnailJobClientJobCoreAutoConfiguration - Snail-Job 客户端IP为: 192.168.0.217 2026-05-09 09:03:49 [main] INFO org.redisson.Version - Redisson 3.52.0
2026-04-24 08:34:33 [main] INFO c.b.m.e.s.MybatisPlusApplicationContextAware - Register ApplicationContext instances org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@1bfe3203 2026-05-09 09:03:49 [redisson-netty-1-5] INFO o.r.connection.ConnectionsHolder - 1 connections initialized for localhost/127.0.0.1:6379
2026-04-24 08:34:38 [main] INFO o.d.w.p.modes.sb.config.BeanConfig - 【warm-flow】加载完成 2026-05-09 09:03:49 [redisson-netty-1-4] INFO o.r.connection.ConnectionsHolder - 8 connections initialized for localhost/127.0.0.1:6379
2026-04-24 08:34:39 [main] INFO io.undertow - starting server: Undertow - 2.3.23.Final 2026-05-09 09:03:50 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-04-24 08:34:39 [main] INFO org.xnio - XNIO version 3.8.16.Final 2026-05-09 09:03:50 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-04-24 08:34:39 [main] INFO org.xnio.nio - XNIO NIO Implementation Version 3.8.16.Final 2026-05-09 09:03:50 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-04-24 08:34:39 [main] INFO org.jboss.threads - JBoss Threads version 3.7.0.Final 2026-05-09 09:03:50 [main] INFO o.d.common.json.config.JacksonConfig - 初始化 jackson 配置
2026-04-24 08:34:39 [main] INFO org.dromara.DromaraApplication - Started DromaraApplication in 14.862 seconds (process running for 15.581) 2026-05-09 09:03:51 [main] INFO c.a.s.c.s.SnailJobClientJobCoreAutoConfiguration - Snail-Job 客户端IP为: 192.168.0.217
2026-04-24 08:34:39 [main] INFO o.d.c.sse.listener.SseTopicListener - 初始化SSE主题订阅监听器成功 2026-05-09 09:03:51 [main] INFO c.b.m.e.s.MybatisPlusApplicationContextAware - Register ApplicationContext instances org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@62e6a3ec
2026-04-24 08:34:40 [main] INFO o.d.s.runner.SystemApplicationRunner - 初始化OSS配置成功 2026-05-09 09:03:55 [main] INFO o.d.w.p.modes.sb.config.BeanConfig - 【warm-flow】加载完成
2026-04-24 08:34:40 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client is preparing to start... v1.9.0 2026-05-09 09:03:56 [main] INFO io.undertow - starting server: Undertow - 2.3.23.Final
2026-04-24 08:34:40 [main] INFO c.a.s.c.c.r.c.g.SnailJobGrpcClient - gRPC client started connect to server 2026-05-09 09:03:56 [main] INFO org.xnio - XNIO version 3.8.16.Final
2026-04-24 08:34:40 [main] INFO c.a.s.c.c.rpc.server.SnailGrpcServer - ------> snail-job remoting server start success, grpc = com.aizuda.snailjob.client.common.rpc.server.SnailGrpcServer, port = 28081 2026-05-09 09:03:56 [main] INFO org.xnio.nio - XNIO NIO Implementation Version 3.8.16.Final
2026-04-24 08:34:40 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client started successfully v1.9.0 2026-05-09 09:03:56 [main] INFO org.jboss.threads - JBoss Threads version 3.7.0.Final
2026-04-24 08:34:41 [RMI TCP Connection(22)-192.168.111.1] INFO io.undertow.servlet - Initializing Spring DispatcherServlet 'dispatcherServlet' 2026-05-09 09:03:56 [main] INFO org.dromara.DromaraApplication - Started DromaraApplication in 13.286 seconds (process running for 14.075)
2026-04-24 08:39:11 [Thread-6] INFO c.a.s.c.c.window.SlidingRingWindow - JVM is about to exit, emitting data in the Window 2026-05-09 09:03:56 [main] INFO o.d.c.sse.listener.SseTopicListener - 初始化SSE主题订阅监听器成功
2026-04-24 08:39:11 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client about to shutdown v1.9.0 2026-05-09 09:03:56 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client is preparing to start... v1.9.0
2026-04-24 08:39:11 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log about to shutdown 2026-05-09 09:03:56 [XNIO-1 task-2] INFO io.undertow.servlet - Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-04-24 08:39:11 [SpringApplicationShutdownHook] INFO c.a.s.c.c.window.SlidingRingWindow - Sliding window is about to exit, emitting data in the Window 2026-05-09 09:03:57 [main] INFO c.a.s.c.c.r.c.g.SnailJobGrpcClient - gRPC client started connect to server
2026-04-24 08:39:11 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log has been shutdown 2026-05-09 09:03:57 [main] INFO c.a.s.c.c.rpc.server.SnailGrpcServer - ------> snail-job remoting server start success, grpc = com.aizuda.snailjob.client.common.rpc.server.SnailGrpcServer, port = 28081
2026-04-24 08:39:11 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client closed successfully v1.9.0 2026-05-09 09:03:57 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[POST /app/v1/addDevice],参数类型[json],参数:[{"device_no":"sn165165fdfdsa","device_name":"测试设备一","device_img":"","wifi_name":"wifi","wifi_password":"12345678","device_em":"dfasdfas","device_sn":"fdasfsadf","fw_ver":"fsdfas","mac_address":"2.285ssadf.fsad"}]
2026-04-24 08:39:11 [SpringApplicationShutdownHook] INFO io.undertow - stopping server: Undertow - 2.3.23.Final 2026-05-09 09:03:58 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client started successfully v1.9.0
2026-04-24 08:39:11 [SpringApplicationShutdownHook] INFO o.d.c.core.config.ThreadPoolConfig - ====关闭后台任务任务线程池==== 2026-05-09 09:03:58 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[POST /app/v1/addDevice],耗时:[317]毫秒
2026-04-24 08:39:11 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource start closing .... 2026-05-09 09:03:58 [main] INFO o.d.s.runner.SystemApplicationRunner - 初始化OSS配置成功
2026-04-24 08:39:11 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown initiated... 2026-05-09 09:06:52 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[POST /app/v1/addDevice],参数类型[json],参数:[{"device_no":"sn165165fdfdsa","device_name":"测试设备一","device_img":"","wifi_name":"wifi","wifi_password":"12345678","device_em":"dfasdfas","device_sn":"fdasfsadf","fw_ver":"fsdfas","mac_address":"2.285ssadf.fsad"}]
2026-04-24 08:39:11 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown completed. 2026-05-09 09:07:22 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[POST /app/v1/addDevice],耗时:[29717]毫秒
2026-04-24 08:39:11 [SpringApplicationShutdownHook] INFO c.b.d.d.d.DefaultDataSourceDestroyer - dynamic-datasource close the datasource named [master] success, 2026-05-09 09:07:58 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[POST /app/v1/addDevice],参数类型[json],参数:[{"deviceNo":"sn165165fdfdsa","deviceName":"测试设备一","deviceImg":"","wifiName":"wifi","wifiPassword":"12345678","deviceEm":"dfasdfas","deviceSn":"fdasfsadf","fwVer":"fsdfas","macAddress":"2.285ssadf.fsad"}]
2026-04-24 08:39:11 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource all closed success,bye 2026-05-09 09:07:58 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[POST /app/v1/addDevice],耗时:[9]毫秒
2026-04-24 08:39:11 [SpringApplicationShutdownHook] INFO io.undertow.servlet - Destroying Spring FrameworkServlet 'dispatcherServlet' 2026-05-09 09:09:43 [Thread-5] INFO c.a.s.c.c.window.SlidingRingWindow - JVM is about to exit, emitting data in the Window
2026-04-24 08:42:03 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final 2026-05-09 09:09:43 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client about to shutdown v1.9.0
2026-04-24 08:42:03 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 18948 (D:\code\water\water-admin\target\classes started by admin in D:\code\water) 2026-05-09 09:09:43 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log about to shutdown
2026-04-24 08:42:03 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev" 2026-05-09 09:09:43 [SpringApplicationShutdownHook] INFO c.a.s.c.c.window.SlidingRingWindow - Sliding window is about to exit, emitting data in the Window
2026-04-24 08:42:06 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext 2026-05-09 09:09:43 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log has been shutdown
2026-04-24 08:42:06 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it 2026-05-09 09:09:43 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client closed successfully v1.9.0
2026-04-24 08:42:06 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting... 2026-05-09 09:09:43 [SpringApplicationShutdownHook] INFO io.undertow - stopping server: Undertow - 2.3.23.Final
2026-04-24 08:42:06 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@5603632c 2026-05-09 09:09:43 [SpringApplicationShutdownHook] INFO o.d.c.core.config.ThreadPoolConfig - ====关闭后台任务任务线程池====
2026-04-24 08:42:06 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed. 2026-05-09 09:09:43 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource start closing ....
2026-04-24 08:42:06 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success 2026-05-09 09:09:43 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown initiated...
2026-04-24 08:42:06 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master] 2026-05-09 09:09:43 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown completed.
2026-04-24 08:42:07 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置 2026-05-09 09:09:43 [SpringApplicationShutdownHook] INFO c.b.d.d.d.DefaultDataSourceDestroyer - dynamic-datasource close the datasource named [master] success,
2026-04-24 08:42:07 [main] INFO org.redisson.Version - Redisson 3.52.0 2026-05-09 09:09:43 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource all closed success,bye
2026-04-24 08:42:08 [redisson-netty-1-5] INFO o.r.connection.ConnectionsHolder - 1 connections initialized for localhost/127.0.0.1:6379 2026-05-09 09:09:43 [SpringApplicationShutdownHook] INFO io.undertow.servlet - Destroying Spring FrameworkServlet 'dispatcherServlet'
2026-04-24 08:42:08 [redisson-netty-1-4] INFO o.r.connection.ConnectionsHolder - 8 connections initialized for localhost/127.0.0.1:6379 2026-05-09 09:09:50 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2026-04-24 08:42:08 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker 2026-05-09 09:09:50 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 16776 (D:\code\water\water-admin\target\classes started by admin in D:\code\water)
2026-04-24 08:42:08 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker 2026-05-09 09:09:50 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev"
2026-04-24 08:42:08 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker 2026-05-09 09:09:54 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext
2026-04-24 08:42:09 [main] INFO o.d.common.json.config.JacksonConfig - 初始化 jackson 配置 2026-05-09 09:09:54 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it
2026-04-24 08:42:09 [main] INFO c.a.s.c.s.SnailJobClientJobCoreAutoConfiguration - Snail-Job 客户端IP为: 192.168.0.217 2026-05-09 09:09:54 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting...
2026-04-24 08:42:09 [main] INFO c.b.m.e.s.MybatisPlusApplicationContextAware - Register ApplicationContext instances org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@378bd86d 2026-05-09 09:09:54 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@1001b435
2026-04-24 08:42:13 [main] INFO o.d.w.p.modes.sb.config.BeanConfig - 【warm-flow】加载完成 2026-05-09 09:09:54 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed.
2026-04-24 08:42:14 [main] INFO io.undertow - starting server: Undertow - 2.3.23.Final 2026-05-09 09:09:54 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success
2026-04-24 08:42:14 [main] INFO org.xnio - XNIO version 3.8.16.Final 2026-05-09 09:09:54 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
2026-04-24 08:42:14 [main] INFO org.xnio.nio - XNIO NIO Implementation Version 3.8.16.Final 2026-05-09 09:09:55 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置
2026-04-24 08:42:14 [main] INFO org.jboss.threads - JBoss Threads version 3.7.0.Final 2026-05-09 09:09:56 [main] INFO org.redisson.Version - Redisson 3.52.0
2026-04-24 08:42:14 [main] INFO org.dromara.DromaraApplication - Started DromaraApplication in 11.002 seconds (process running for 11.654) 2026-05-09 09:09:56 [redisson-netty-1-5] INFO o.r.connection.ConnectionsHolder - 1 connections initialized for localhost/127.0.0.1:6379
2026-04-24 08:42:14 [main] INFO o.d.c.sse.listener.SseTopicListener - 初始化SSE主题订阅监听器成功 2026-05-09 09:09:56 [redisson-netty-1-4] INFO o.r.connection.ConnectionsHolder - 8 connections initialized for localhost/127.0.0.1:6379
2026-04-24 08:42:14 [main] INFO o.d.s.runner.SystemApplicationRunner - 初始化OSS配置成功 2026-05-09 09:09:57 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-04-24 08:42:14 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client is preparing to start... v1.9.0 2026-05-09 09:09:57 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-04-24 08:42:14 [main] INFO c.a.s.c.c.r.c.g.SnailJobGrpcClient - gRPC client started connect to server 2026-05-09 09:09:57 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-04-24 08:42:14 [main] INFO c.a.s.c.c.rpc.server.SnailGrpcServer - ------> snail-job remoting server start success, grpc = com.aizuda.snailjob.client.common.rpc.server.SnailGrpcServer, port = 28081 2026-05-09 09:09:57 [main] INFO o.d.common.json.config.JacksonConfig - 初始化 jackson 配置
2026-04-24 08:42:15 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client started successfully v1.9.0 2026-05-09 09:09:57 [main] INFO c.a.s.c.s.SnailJobClientJobCoreAutoConfiguration - Snail-Job 客户端IP为: 192.168.0.217
2026-04-24 08:42:15 [RMI TCP Connection(2)-192.168.111.1] INFO io.undertow.servlet - Initializing Spring DispatcherServlet 'dispatcherServlet' 2026-05-09 09:09:57 [main] INFO c.b.m.e.s.MybatisPlusApplicationContextAware - Register ApplicationContext instances org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@62e6a3ec
2026-04-24 10:08:38 [Thread-6] INFO c.a.s.c.c.window.SlidingRingWindow - JVM is about to exit, emitting data in the Window 2026-05-09 09:10:01 [main] INFO o.d.w.p.modes.sb.config.BeanConfig - 【warm-flow】加载完成
2026-04-24 10:08:38 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client about to shutdown v1.9.0 2026-05-09 09:10:02 [main] INFO io.undertow - starting server: Undertow - 2.3.23.Final
2026-04-24 10:08:38 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log about to shutdown 2026-05-09 09:10:02 [main] INFO org.xnio - XNIO version 3.8.16.Final
2026-04-24 10:08:38 [SpringApplicationShutdownHook] INFO c.a.s.c.c.window.SlidingRingWindow - Sliding window is about to exit, emitting data in the Window 2026-05-09 09:10:02 [main] INFO org.xnio.nio - XNIO NIO Implementation Version 3.8.16.Final
2026-04-24 10:08:38 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log has been shutdown 2026-05-09 09:10:02 [main] INFO org.jboss.threads - JBoss Threads version 3.7.0.Final
2026-04-24 10:08:38 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client closed successfully v1.9.0 2026-05-09 09:10:02 [main] INFO org.dromara.DromaraApplication - Started DromaraApplication in 13.24 seconds (process running for 14.094)
2026-04-24 10:08:38 [SpringApplicationShutdownHook] INFO io.undertow - stopping server: Undertow - 2.3.23.Final 2026-05-09 09:10:02 [main] INFO o.d.c.sse.listener.SseTopicListener - 初始化SSE主题订阅监听器成功
2026-04-24 10:08:38 [SpringApplicationShutdownHook] INFO o.d.c.core.config.ThreadPoolConfig - ====关闭后台任务任务线程池==== 2026-05-09 09:10:02 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client is preparing to start... v1.9.0
2026-04-24 10:08:38 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource start closing .... 2026-05-09 09:10:03 [main] INFO c.a.s.c.c.r.c.g.SnailJobGrpcClient - gRPC client started connect to server
2026-04-24 10:08:38 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown initiated... 2026-05-09 09:10:03 [main] INFO c.a.s.c.c.rpc.server.SnailGrpcServer - ------> snail-job remoting server start success, grpc = com.aizuda.snailjob.client.common.rpc.server.SnailGrpcServer, port = 28081
2026-04-24 10:08:38 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown completed. 2026-05-09 09:10:03 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client started successfully v1.9.0
2026-04-24 10:08:38 [SpringApplicationShutdownHook] INFO c.b.d.d.d.DefaultDataSourceDestroyer - dynamic-datasource close the datasource named [master] success, 2026-05-09 09:10:04 [main] INFO o.d.s.runner.SystemApplicationRunner - 初始化OSS配置成功
2026-04-24 10:08:38 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource all closed success,bye 2026-05-09 09:10:04 [RMI TCP Connection(6)-192.168.111.1] INFO io.undertow.servlet - Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-04-24 10:08:38 [SpringApplicationShutdownHook] INFO io.undertow.servlet - Destroying Spring FrameworkServlet 'dispatcherServlet' 2026-05-09 09:14:14 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /resource/sse/close],无参数
2026-05-09 09:14:14 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[POST /auth/logout],无参数
2026-05-09 09:14:14 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[POST /auth/logout],耗时:[8]毫秒
2026-05-09 09:14:15 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /auth/code],无参数
2026-05-09 09:14:15 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /auth/tenant/list],无参数
2026-05-09 09:14:15 [XNIO-1 task-4] INFO o.d.c.r.aspectj.RateLimiterAspect - 限制令牌 => 20, 剩余令牌 => 19, 缓存key => 'global:rate_limit:/auth/tenant/list:0:0:0:0:0:0:0:1:'
2026-05-09 09:14:15 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /auth/tenant/list],耗时:[38]毫秒
2026-05-09 09:14:15 [XNIO-1 task-2] INFO o.d.c.r.aspectj.RateLimiterAspect - 限制令牌 => 10, 剩余令牌 => 9, 缓存key => 'global:rate_limit:/auth/code:0:0:0:0:0:0:0:1:'
2026-05-09 09:14:15 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /auth/code],耗时:[294]毫秒
2026-05-09 09:14:15 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /resource/sse/close],耗时:[1081]毫秒
2026-05-09 09:14:22 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[POST /auth/login],参数类型[json],参数:[{"tenantId":"000000","username":"admin","rememberMe":false,"code":"3","uuid":"f138aa7b1b974923b01b4bd78781232e","clientId":"e5cd7e4891bf95d1d19206ce24a7b32e","grantType":"password"}]
2026-05-09 09:14:23 [async-1] INFO o.d.s.s.i.SysLogininforServiceImpl - [0:0:0:0:0:0:0:1]内网IP[admin][Success][登录成功]
2026-05-09 09:14:23 [XNIO-1 task-3] INFO o.d.web.listener.UserActionListener - user doLogin, userId:sys_user:1, token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJibElseTRpcjJFZmpSUjdjVERQdnlxNXZ1M2lkbXJsZyIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IueglOWPkemDqOmXqCIsImRlcHRDYXRlZ29yeSI6IiJ9.uk1CGB6xuPaW8OGcIPGOmA5Fo11mEj20KiUrr11rL9k
2026-05-09 09:14:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[POST /auth/login],耗时:[215]毫秒
2026-05-09 09:14:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/user/getInfo],无参数
2026-05-09 09:14:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/user/getInfo],耗时:[61]毫秒
2026-05-09 09:14:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/menu/getRouters],无参数
2026-05-09 09:14:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/menu/getRouters],耗时:[43]毫秒
2026-05-09 09:14:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /auth/tenant/list],无参数
2026-05-09 09:14:23 [XNIO-1 task-3] INFO o.d.c.r.aspectj.RateLimiterAspect - 限制令牌 => 20, 剩余令牌 => 18, 缓存key => 'global:rate_limit:/auth/tenant/list:0:0:0:0:0:0:0:1:'
2026-05-09 09:14:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /auth/tenant/list],耗时:[3]毫秒
2026-05-09 09:14:23 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /resource/sse],参数类型[param],参数:[{"Authorization":["Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJibElseTRpcjJFZmpSUjdjVERQdnlxNXZ1M2lkbXJsZyIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IueglOWPkemDqOmXqCIsImRlcHRDYXRlZ29yeSI6IiJ9.uk1CGB6xuPaW8OGcIPGOmA5Fo11mEj20KiUrr11rL9k"],"clientid":["e5cd7e4891bf95d1d19206ce24a7b32e"]}]
2026-05-09 09:14:28 [schedule-pool-2] INFO o.d.c.sse.core.SseEmitterManager - SSE发送主题订阅消息topic:global:sse session keys:[1] message:上午好,欢迎登录 water-Vue-Plus 后台管理系统
2026-05-09 09:14:28 [redisson-3-2] INFO o.d.c.sse.listener.SseTopicListener - SSE主题订阅收到消息session keys=[1] message=上午好,欢迎登录 water-Vue-Plus 后台管理系统
2026-05-09 09:14:31 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/dict/data/type/sys_user_sex],无参数
2026-05-09 09:14:31 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/dict/data/type/sys_normal_disable],无参数
2026-05-09 09:14:31 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/dict/data/type/sys_user_sex],耗时:[13]毫秒
2026-05-09 09:14:31 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/dict/data/type/sys_normal_disable],耗时:[13]毫秒
2026-05-09 09:14:31 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/user/deptTree],无参数
2026-05-09 09:14:31 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/user/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:14:31 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/config/configKey/sys.user.initPassword],无参数
2026-05-09 09:14:31 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/config/configKey/sys.user.initPassword],耗时:[9]毫秒
2026-05-09 09:14:31 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/user/deptTree],耗时:[121]毫秒
2026-05-09 09:14:31 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/user/list],耗时:[129]毫秒
2026-05-09 09:14:36 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/user/2047881868870909954],无参数
2026-05-09 09:14:36 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/user/2047881868870909954],耗时:[23]毫秒
2026-05-09 09:14:47 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[PUT /system/user],参数类型[json],参数:[{"userId":"2047881868870909954","deptId":null,"userName":null,"nickName":"111111","phonenumber":"","email":"40624989@qq.com","sex":"0","status":"0","remark":null,"postIds":null,"roleIds":[4],"tenantId":"000000","userType":"app_user","avatar":null,"loginIp":"0:0:0:0:0:0:0:1","loginDate":"2026-05-07 10:53:11","createTime":"2026-04-25 11:34:20","deptName":null,"roles":[],"roleId":null}]
2026-05-09 09:14:47 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[PUT /system/user],耗时:[95]毫秒
2026-05-09 09:14:48 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[PUT /system/user],参数类型[json],参数:[{"userId":"2047881868870909954","deptId":null,"userName":null,"nickName":"111111","phonenumber":"","email":"40624989@qq.com","sex":"0","status":"0","remark":null,"postIds":null,"roleIds":[4],"tenantId":"000000","userType":"app_user","avatar":null,"loginIp":"0:0:0:0:0:0:0:1","loginDate":"2026-05-07 10:53:11","createTime":"2026-04-25 11:34:20","deptName":null,"roles":[],"roleId":null}]
2026-05-09 09:14:48 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[PUT /system/user],耗时:[2]毫秒
2026-05-09 09:14:59 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[PUT /system/user],参数类型[json],参数:[{"userId":"2047881868870909954","deptId":null,"userName":null,"nickName":"111111","phonenumber":"","email":"40624989@qq.com","sex":"0","status":"0","remark":null,"postIds":null,"roleIds":[4],"tenantId":"000000","userType":"app_user","avatar":null,"loginIp":"0:0:0:0:0:0:0:1","loginDate":"2026-05-07 10:53:11","createTime":"2026-04-25 11:34:20","deptName":null,"roles":[],"roleId":null}]
2026-05-09 09:14:59 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[PUT /system/user],耗时:[1]毫秒
2026-05-09 09:15:24 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/user/2047881868870909954],无参数
2026-05-09 09:15:24 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/user/2047881868870909954],耗时:[17]毫秒
2026-05-09 09:15:28 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[PUT /system/user],参数类型[json],参数:[{"userId":"2047881868870909954","deptId":null,"userName":"40624989@qq.com","nickName":"111111","phonenumber":"","email":"40624989@qq.com","sex":"0","status":"0","remark":null,"postIds":null,"roleIds":[4],"tenantId":"000000","userType":"app_user","avatar":null,"loginIp":"0:0:0:0:0:0:0:1","loginDate":"2026-05-07 10:53:11","createTime":"2026-04-25 11:34:20","deptName":null,"roles":[],"roleId":null}]
2026-05-09 09:15:28 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[PUT /system/user],耗时:[113]毫秒
2026-05-09 09:15:28 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/user/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:15:28 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/user/list],耗时:[21]毫秒
2026-05-09 09:17:41 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[POST /app/v1/addDevice],参数类型[json],参数:[{"deviceNo":"sn165165fdfdsa","deviceName":"测试设备二","deviceImg":"","wifiName":"wifi","wifiPassword":"12345678","deviceEm":"dfasdfas","deviceSn":"fdasfsadf","fwVer":"fsdfas","macAddress":"2.285ssadf.fsad"}]
2026-05-09 09:17:41 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[POST /app/v1/addDevice],耗时:[15]毫秒
2026-05-09 09:17:52 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[POST /app/v1/addDevice],参数类型[json],参数:[{"deviceNo":"sn165165fdfdda","deviceName":"测试设备三","deviceImg":"","wifiName":"wifi","wifiPassword":"12345678","deviceEm":"dfasdfas","deviceSn":"fdasfsadf","fwVer":"fsdfas","macAddress":"2.285ssadf.fsad"}]
2026-05-09 09:17:52 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[POST /app/v1/addDevice],耗时:[5]毫秒
2026-05-09 09:18:02 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[POST /app/v1/addDevice],参数类型[json],参数:[{"deviceNo":"sn1651dffffdfdda","deviceName":"测试设备四","deviceImg":"","wifiName":"wifi","wifiPassword":"12345678","deviceEm":"dfasdfas","deviceSn":"fdasfsadf","fwVer":"fsdfas","macAddress":"2.285ssadf.fsad"}]
2026-05-09 09:18:02 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[POST /app/v1/addDevice],耗时:[7]毫秒
2026-05-09 09:18:30 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-05-09 09:18:30 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[21]毫秒
2026-05-09 09:19:03 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-05-09 09:19:03 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[9]毫秒
2026-05-09 09:19:05 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-05-09 09:19:05 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[22]毫秒
2026-05-09 09:19:32 [Thread-5] INFO c.a.s.c.c.window.SlidingRingWindow - JVM is about to exit, emitting data in the Window
2026-05-09 09:19:32 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client about to shutdown v1.9.0
2026-05-09 09:19:32 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log about to shutdown
2026-05-09 09:19:32 [SpringApplicationShutdownHook] INFO c.a.s.c.c.window.SlidingRingWindow - Sliding window is about to exit, emitting data in the Window
2026-05-09 09:19:32 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log has been shutdown
2026-05-09 09:19:32 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client closed successfully v1.9.0
2026-05-09 09:19:41 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2026-05-09 09:19:41 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 11676 (D:\code\water\water-admin\target\classes started by admin in D:\code\water)
2026-05-09 09:19:41 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev"
2026-05-09 09:19:44 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext
2026-05-09 09:19:44 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it
2026-05-09 09:19:44 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting...
2026-05-09 09:19:44 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@1001b435
2026-05-09 09:19:44 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed.
2026-05-09 09:19:44 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success
2026-05-09 09:19:44 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
2026-05-09 09:19:45 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置
2026-05-09 09:19:45 [main] INFO org.redisson.Version - Redisson 3.52.0
2026-05-09 09:19:46 [redisson-netty-1-5] INFO o.r.connection.ConnectionsHolder - 1 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:19:46 [redisson-netty-1-4] INFO o.r.connection.ConnectionsHolder - 8 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:19:47 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:19:47 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:19:47 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:19:47 [main] INFO o.d.common.json.config.JacksonConfig - 初始化 jackson 配置
2026-05-09 09:19:47 [main] INFO c.a.s.c.s.SnailJobClientJobCoreAutoConfiguration - Snail-Job 客户端IP为: 192.168.0.217
2026-05-09 09:19:47 [main] INFO c.b.m.e.s.MybatisPlusApplicationContextAware - Register ApplicationContext instances org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@62e6a3ec
2026-05-09 09:19:51 [main] INFO o.d.w.p.modes.sb.config.BeanConfig - 【warm-flow】加载完成
2026-05-09 09:19:52 [main] INFO io.undertow - starting server: Undertow - 2.3.23.Final
2026-05-09 09:19:52 [main] INFO org.xnio - XNIO version 3.8.16.Final
2026-05-09 09:19:52 [main] INFO org.xnio.nio - XNIO NIO Implementation Version 3.8.16.Final
2026-05-09 09:19:52 [main] INFO org.jboss.threads - JBoss Threads version 3.7.0.Final
2026-05-09 09:19:52 [main] INFO org.dromara.DromaraApplication - Started DromaraApplication in 12.679 seconds (process running for 13.58)
2026-05-09 09:19:52 [main] INFO o.d.c.sse.listener.SseTopicListener - 初始化SSE主题订阅监听器成功
2026-05-09 09:19:52 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client is preparing to start... v1.9.0
2026-05-09 09:19:53 [main] INFO c.a.s.c.c.r.c.g.SnailJobGrpcClient - gRPC client started connect to server
2026-05-09 09:19:53 [main] INFO c.a.s.c.c.rpc.server.SnailGrpcServer - ------> snail-job remoting server start success, grpc = com.aizuda.snailjob.client.common.rpc.server.SnailGrpcServer, port = 28081
2026-05-09 09:19:53 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client started successfully v1.9.0
2026-05-09 09:19:53 [main] INFO o.d.s.runner.SystemApplicationRunner - 初始化OSS配置成功
2026-05-09 09:19:54 [RMI TCP Connection(5)-192.168.111.1] INFO io.undertow.servlet - Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-05-09 09:19:56 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /resource/sse],参数类型[param],参数:[{"Authorization":["Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJibElseTRpcjJFZmpSUjdjVERQdnlxNXZ1M2lkbXJsZyIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IueglOWPkemDqOmXqCIsImRlcHRDYXRlZ29yeSI6IiJ9.uk1CGB6xuPaW8OGcIPGOmA5Fo11mEj20KiUrr11rL9k"],"clientid":["e5cd7e4891bf95d1d19206ce24a7b32e"]}]
2026-05-09 09:20:18 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/user/getInfo],无参数
2026-05-09 09:20:18 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/user/getInfo],耗时:[177]毫秒
2026-05-09 09:20:18 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/menu/getRouters],无参数
2026-05-09 09:20:18 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/menu/getRouters],耗时:[52]毫秒
2026-05-09 09:20:18 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/dict/data/type/sys_user_sex],无参数
2026-05-09 09:20:18 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/dict/data/type/sys_normal_disable],无参数
2026-05-09 09:20:18 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/user/deptTree],无参数
2026-05-09 09:20:18 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/user/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:20:18 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/dict/data/type/sys_normal_disable],耗时:[22]毫秒
2026-05-09 09:20:18 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/dict/data/type/sys_user_sex],耗时:[23]毫秒
2026-05-09 09:20:18 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /auth/tenant/list],无参数
2026-05-09 09:20:18 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/config/configKey/sys.user.initPassword],无参数
2026-05-09 09:20:18 [XNIO-1 task-3] INFO o.d.c.r.aspectj.RateLimiterAspect - 限制令牌 => 20, 剩余令牌 => 19, 缓存key => 'global:rate_limit:/auth/tenant/list:0:0:0:0:0:0:0:1:'
2026-05-09 09:20:18 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/config/configKey/sys.user.initPassword],耗时:[14]毫秒
2026-05-09 09:20:18 [XNIO-1 task-3] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /auth/tenant/list],耗时:[19]毫秒
2026-05-09 09:20:18 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/user/deptTree],耗时:[144]毫秒
2026-05-09 09:20:18 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/user/list],耗时:[158]毫秒
2026-05-09 09:20:19 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /resource/sse],参数类型[param],参数:[{"Authorization":["Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJibElseTRpcjJFZmpSUjdjVERQdnlxNXZ1M2lkbXJsZyIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IueglOWPkemDqOmXqCIsImRlcHRDYXRlZ29yeSI6IiJ9.uk1CGB6xuPaW8OGcIPGOmA5Fo11mEj20KiUrr11rL9k"],"clientid":["e5cd7e4891bf95d1d19206ce24a7b32e"]}]
2026-05-09 09:20:19 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /resource/sse],参数类型[param],参数:[{"Authorization":["Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJibElseTRpcjJFZmpSUjdjVERQdnlxNXZ1M2lkbXJsZyIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IueglOWPkemDqOmXqCIsImRlcHRDYXRlZ29yeSI6IiJ9.uk1CGB6xuPaW8OGcIPGOmA5Fo11mEj20KiUrr11rL9k"],"clientid":["e5cd7e4891bf95d1d19206ce24a7b32e"]}]
2026-05-09 09:20:19 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /resource/sse],耗时:[4]毫秒
2026-05-09 09:20:19 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /resource/sse],参数类型[param],参数:[{"Authorization":["Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJibElseTRpcjJFZmpSUjdjVERQdnlxNXZ1M2lkbXJsZyIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IueglOWPkemDqOmXqCIsImRlcHRDYXRlZ29yeSI6IiJ9.uk1CGB6xuPaW8OGcIPGOmA5Fo11mEj20KiUrr11rL9k"],"clientid":["e5cd7e4891bf95d1d19206ce24a7b32e"]}]
2026-05-09 09:20:19 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /resource/sse],耗时:[0]毫秒
2026-05-09 09:20:22 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /resource/sse],参数类型[param],参数:[{"Authorization":["Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJibElseTRpcjJFZmpSUjdjVERQdnlxNXZ1M2lkbXJsZyIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IueglOWPkemDqOmXqCIsImRlcHRDYXRlZ29yeSI6IiJ9.uk1CGB6xuPaW8OGcIPGOmA5Fo11mEj20KiUrr11rL9k"],"clientid":["e5cd7e4891bf95d1d19206ce24a7b32e"]}]
2026-05-09 09:20:23 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/user/authRole/2047881868870909954],无参数
2026-05-09 09:20:23 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/user/authRole/2047881868870909954],耗时:[29]毫秒
2026-05-09 09:20:27 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:20:28 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/list],耗时:[30]毫秒
2026-05-09 09:20:30 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/4],无参数
2026-05-09 09:20:30 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/4],耗时:[12]毫秒
2026-05-09 09:20:30 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/menu/roleMenuTreeselect/4],无参数
2026-05-09 09:20:31 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/menu/roleMenuTreeselect/4],耗时:[42]毫秒
2026-05-09 09:20:57 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/dict/data/type/sys_show_hide],无参数
2026-05-09 09:20:57 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/menu/list],无参数
2026-05-09 09:20:57 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/dict/data/type/sys_show_hide],耗时:[15]毫秒
2026-05-09 09:20:57 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/menu/list],耗时:[27]毫秒
2026-05-09 09:21:00 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/menu/list],无参数
2026-05-09 09:21:00 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/menu/list],耗时:[12]毫秒
2026-05-09 09:21:00 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/menu/1],无参数
2026-05-09 09:21:00 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/menu/1],耗时:[3]毫秒
2026-05-09 09:21:07 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/dict/data/type/sys_yes_no],无参数
2026-05-09 09:21:07 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/dict/data/type/sys_yes_no],耗时:[7]毫秒
2026-05-09 09:21:07 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/config/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:21:07 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/config/list],耗时:[21]毫秒
2026-05-09 09:21:09 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/dict/type/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:21:09 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/dict/type/list],耗时:[26]毫秒
2026-05-09 09:21:09 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/dict/data/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"],"dictType":["sys_user_sex"]}]
2026-05-09 09:21:09 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/dict/data/list],耗时:[17]毫秒
2026-05-09 09:21:20 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/dict/data/type/wf_business_status],无参数
2026-05-09 09:21:20 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /workflow/task/pageByTaskWait],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:21:20 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/dict/data/type/wf_business_status],耗时:[7]毫秒
2026-05-09 09:21:20 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /workflow/task/pageByTaskWait],耗时:[79]毫秒
2026-05-09 09:21:22 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/user/getInfo],无参数
2026-05-09 09:21:22 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/user/getInfo],耗时:[9]毫秒
2026-05-09 09:21:22 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/menu/getRouters],无参数
2026-05-09 09:21:22 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/menu/getRouters],耗时:[7]毫秒
2026-05-09 09:21:23 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/dict/data/type/sys_normal_disable],无参数
2026-05-09 09:21:23 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/dict/data/type/wf_business_status],无参数
2026-05-09 09:21:23 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/dict/data/type/sys_normal_disable],耗时:[2]毫秒
2026-05-09 09:21:23 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/dict/data/type/wf_business_status],耗时:[1]毫秒
2026-05-09 09:21:23 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /auth/tenant/list],无参数
2026-05-09 09:21:23 [XNIO-1 task-5] INFO o.d.c.r.aspectj.RateLimiterAspect - 限制令牌 => 20, 剩余令牌 => 19, 缓存key => 'global:rate_limit:/auth/tenant/list:0:0:0:0:0:0:0:1:'
2026-05-09 09:21:23 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /workflow/task/pageByTaskWait],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:21:23 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /auth/tenant/list],耗时:[3]毫秒
2026-05-09 09:21:23 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /workflow/task/pageByTaskWait],耗时:[33]毫秒
2026-05-09 09:21:23 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /resource/sse],参数类型[param],参数:[{"Authorization":["Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJibElseTRpcjJFZmpSUjdjVERQdnlxNXZ1M2lkbXJsZyIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IueglOWPkemDqOmXqCIsImRlcHRDYXRlZ29yeSI6IiJ9.uk1CGB6xuPaW8OGcIPGOmA5Fo11mEj20KiUrr11rL9k"],"clientid":["e5cd7e4891bf95d1d19206ce24a7b32e"]}]
2026-05-09 09:21:23 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /resource/sse],参数类型[param],参数:[{"Authorization":["Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJibElseTRpcjJFZmpSUjdjVERQdnlxNXZ1M2lkbXJsZyIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IueglOWPkemDqOmXqCIsImRlcHRDYXRlZ29yeSI6IiJ9.uk1CGB6xuPaW8OGcIPGOmA5Fo11mEj20KiUrr11rL9k"],"clientid":["e5cd7e4891bf95d1d19206ce24a7b32e"]}]
2026-05-09 09:21:23 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /resource/sse],耗时:[0]毫秒
2026-05-09 09:21:23 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /resource/sse],参数类型[param],参数:[{"Authorization":["Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJibElseTRpcjJFZmpSUjdjVERQdnlxNXZ1M2lkbXJsZyIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IueglOWPkemDqOmXqCIsImRlcHRDYXRlZ29yeSI6IiJ9.uk1CGB6xuPaW8OGcIPGOmA5Fo11mEj20KiUrr11rL9k"],"clientid":["e5cd7e4891bf95d1d19206ce24a7b32e"]}]
2026-05-09 09:21:23 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /resource/sse],耗时:[0]毫秒
2026-05-09 09:21:26 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /resource/sse],参数类型[param],参数:[{"Authorization":["Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJibElseTRpcjJFZmpSUjdjVERQdnlxNXZ1M2lkbXJsZyIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IueglOWPkemDqOmXqCIsImRlcHRDYXRlZ29yeSI6IiJ9.uk1CGB6xuPaW8OGcIPGOmA5Fo11mEj20KiUrr11rL9k"],"clientid":["e5cd7e4891bf95d1d19206ce24a7b32e"]}]
2026-05-09 09:21:29 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/dict/data/type/sys_device_type],无参数
2026-05-09 09:21:29 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/dict/data/type/sys_device_type],耗时:[2]毫秒
2026-05-09 09:21:30 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /monitor/online/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:21:30 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /monitor/online/list],耗时:[75]毫秒
2026-05-09 09:21:47 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /monitor/cache],无参数
2026-05-09 09:21:47 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /monitor/cache],耗时:[33]毫秒
2026-05-09 09:22:00 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/dict/data/type/sys_user_sex],无参数
2026-05-09 09:22:00 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/dict/data/type/sys_user_sex],耗时:[2]毫秒
2026-05-09 09:22:00 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/user/deptTree],无参数
2026-05-09 09:22:00 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/user/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:22:00 [XNIO-1 task-4] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/user/deptTree],耗时:[17]毫秒
2026-05-09 09:22:00 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/user/list],耗时:[31]毫秒
2026-05-09 09:22:00 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/config/configKey/sys.user.initPassword],无参数
2026-05-09 09:22:00 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/config/configKey/sys.user.initPassword],耗时:[1]毫秒
2026-05-09 09:22:10 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:22:11 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/list],耗时:[28]毫秒
2026-05-09 09:22:18 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/4],无参数
2026-05-09 09:22:18 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/4],耗时:[7]毫秒
2026-05-09 09:22:18 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/menu/roleMenuTreeselect/4],无参数
2026-05-09 09:22:19 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/menu/roleMenuTreeselect/4],耗时:[9]毫秒
2026-05-09 09:22:32 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[PUT /system/role],参数类型[json],参数:[{"roleId":4,"roleSort":4,"status":"0","roleName":"仅本人","roleKey":"me","menuCheckStrictly":true,"deptCheckStrictly":true,"remark":"","dataScope":"5","menuIds":[5,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511],"deptIds":[],"createTime":"2026-04-24 08:32:08","flag":false,"superAdmin":false}]
2026-05-09 09:22:33 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[PUT /system/role],耗时:[148]毫秒
2026-05-09 09:22:33 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:22:33 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/list],耗时:[14]毫秒
2026-05-09 09:22:41 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[DELETE /system/role/3],无参数
2026-05-09 09:22:41 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[DELETE /system/role/3],耗时:[14]毫秒
2026-05-09 09:22:48 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/authUser/allocatedList],参数类型[param],参数:[{"roleId":["3"],"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:22:48 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/authUser/allocatedList],耗时:[27]毫秒
2026-05-09 09:22:52 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/3],无参数
2026-05-09 09:22:52 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/3],耗时:[11]毫秒
2026-05-09 09:22:52 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/deptTree/3],无参数
2026-05-09 09:22:52 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/deptTree/3],耗时:[20]毫秒
2026-05-09 09:22:57 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/4],无参数
2026-05-09 09:22:57 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/4],耗时:[10]毫秒
2026-05-09 09:22:57 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/deptTree/4],无参数
2026-05-09 09:22:57 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/deptTree/4],耗时:[14]毫秒
2026-05-09 09:23:03 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[PUT /system/role/dataScope],参数类型[json],参数:[{"roleId":4,"roleSort":4,"status":"0","roleName":"仅本人","roleKey":"me","menuCheckStrictly":true,"deptCheckStrictly":true,"remark":"","dataScope":"5","menuIds":[5,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511],"deptIds":[],"createTime":"2026-04-24 08:32:08","flag":false,"superAdmin":false}]
2026-05-09 09:23:03 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[PUT /system/role/dataScope],耗时:[11]毫秒
2026-05-09 09:23:03 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:23:03 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/list],耗时:[22]毫秒
2026-05-09 09:23:33 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/4],无参数
2026-05-09 09:23:33 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/4],耗时:[6]毫秒
2026-05-09 09:23:33 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/deptTree/4],无参数
2026-05-09 09:23:33 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/deptTree/4],耗时:[17]毫秒
2026-05-09 09:23:36 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[PUT /system/role/dataScope],参数类型[json],参数:[{"roleId":4,"roleSort":4,"status":"0","roleName":"仅本人","roleKey":"me","menuCheckStrictly":true,"deptCheckStrictly":true,"remark":"","dataScope":"1","menuIds":[5,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511],"deptIds":[],"createTime":"2026-04-24 08:32:08","flag":false,"superAdmin":false}]
2026-05-09 09:23:36 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[PUT /system/role/dataScope],耗时:[11]毫秒
2026-05-09 09:23:37 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:23:37 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/list],耗时:[22]毫秒
2026-05-09 09:24:07 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/4],无参数
2026-05-09 09:24:07 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/4],耗时:[11]毫秒
2026-05-09 09:24:07 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/deptTree/4],无参数
2026-05-09 09:24:07 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/deptTree/4],耗时:[12]毫秒
2026-05-09 09:24:11 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[PUT /system/role/dataScope],参数类型[json],参数:[{"roleId":4,"roleSort":4,"status":"0","roleName":"仅本人","roleKey":"me","menuCheckStrictly":true,"deptCheckStrictly":true,"remark":"","dataScope":"5","menuIds":[5,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511],"deptIds":[],"createTime":"2026-04-24 08:32:08","flag":false,"superAdmin":false}]
2026-05-09 09:24:11 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[PUT /system/role/dataScope],耗时:[11]毫秒
2026-05-09 09:24:12 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /system/role/list],参数类型[param],参数:[{"pageSize":["10"],"pageNum":["1"]}]
2026-05-09 09:24:12 [XNIO-1 task-5] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /system/role/list],耗时:[12]毫秒
2026-05-09 09:39:58 [Thread-5] INFO c.a.s.c.c.window.SlidingRingWindow - JVM is about to exit, emitting data in the Window
2026-05-09 09:39:58 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client about to shutdown v1.9.0
2026-05-09 09:39:58 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log about to shutdown
2026-05-09 09:39:58 [SpringApplicationShutdownHook] INFO c.a.s.c.c.window.SlidingRingWindow - Sliding window is about to exit, emitting data in the Window
2026-05-09 09:39:58 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log has been shutdown
2026-05-09 09:39:58 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client closed successfully v1.9.0
2026-05-09 09:40:18 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2026-05-09 09:40:18 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 11260 (D:\code\water\water-admin\target\classes started by admin in D:\code\water)
2026-05-09 09:40:18 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev"
2026-05-09 09:40:21 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext
2026-05-09 09:40:21 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it
2026-05-09 09:40:21 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting...
2026-05-09 09:40:21 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@564e9c0b
2026-05-09 09:40:21 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed.
2026-05-09 09:40:21 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success
2026-05-09 09:40:21 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
2026-05-09 09:40:22 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置
2026-05-09 09:40:23 [main] INFO org.redisson.Version - Redisson 3.52.0
2026-05-09 09:40:23 [redisson-netty-1-5] INFO o.r.connection.ConnectionsHolder - 1 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:40:23 [redisson-netty-1-4] INFO o.r.connection.ConnectionsHolder - 8 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:40:24 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:40:24 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:40:24 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:40:24 [main] INFO o.d.common.json.config.JacksonConfig - 初始化 jackson 配置
2026-05-09 09:40:24 [main] INFO c.a.s.c.s.SnailJobClientJobCoreAutoConfiguration - Snail-Job 客户端IP为: 192.168.0.217
2026-05-09 09:40:24 [main] INFO c.b.m.e.s.MybatisPlusApplicationContextAware - Register ApplicationContext instances org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@1bfe3203
2026-05-09 09:40:28 [main] INFO o.d.w.p.modes.sb.config.BeanConfig - 【warm-flow】加载完成
2026-05-09 09:40:29 [main] INFO io.undertow - starting server: Undertow - 2.3.23.Final
2026-05-09 09:40:29 [main] INFO org.xnio - XNIO version 3.8.16.Final
2026-05-09 09:40:29 [main] INFO org.xnio.nio - XNIO NIO Implementation Version 3.8.16.Final
2026-05-09 09:40:29 [main] INFO org.jboss.threads - JBoss Threads version 3.7.0.Final
2026-05-09 09:40:29 [main] INFO org.dromara.DromaraApplication - Started DromaraApplication in 12.61 seconds (process running for 13.283)
2026-05-09 09:40:29 [main] INFO o.d.c.sse.listener.SseTopicListener - 初始化SSE主题订阅监听器成功
2026-05-09 09:40:29 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client is preparing to start... v1.9.0
2026-05-09 09:40:30 [main] INFO c.a.s.c.c.r.c.g.SnailJobGrpcClient - gRPC client started connect to server
2026-05-09 09:40:30 [main] INFO c.a.s.c.c.rpc.server.SnailGrpcServer - ------> snail-job remoting server start success, grpc = com.aizuda.snailjob.client.common.rpc.server.SnailGrpcServer, port = 28081
2026-05-09 09:40:30 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client started successfully v1.9.0
2026-05-09 09:40:31 [main] INFO o.d.s.runner.SystemApplicationRunner - 初始化OSS配置成功
2026-05-09 09:40:31 [RMI TCP Connection(5)-192.168.111.1] INFO io.undertow.servlet - Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-05-09 09:40:34 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /resource/sse],参数类型[param],参数:[{"Authorization":["Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJibElseTRpcjJFZmpSUjdjVERQdnlxNXZ1M2lkbXJsZyIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IueglOWPkemDqOmXqCIsImRlcHRDYXRlZ29yeSI6IiJ9.uk1CGB6xuPaW8OGcIPGOmA5Fo11mEj20KiUrr11rL9k"],"clientid":["e5cd7e4891bf95d1d19206ce24a7b32e"]}]
2026-05-09 09:40:46 [Thread-5] INFO c.a.s.c.c.window.SlidingRingWindow - JVM is about to exit, emitting data in the Window
2026-05-09 09:40:46 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client about to shutdown v1.9.0
2026-05-09 09:40:46 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log about to shutdown
2026-05-09 09:40:46 [SpringApplicationShutdownHook] INFO c.a.s.c.c.window.SlidingRingWindow - Sliding window is about to exit, emitting data in the Window
2026-05-09 09:40:46 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log has been shutdown
2026-05-09 09:40:46 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client closed successfully v1.9.0
2026-05-09 09:40:56 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2026-05-09 09:40:56 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 14948 (D:\code\water\water-admin\target\classes started by admin in D:\code\water)
2026-05-09 09:40:56 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev"
2026-05-09 09:40:59 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext
2026-05-09 09:41:00 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it
2026-05-09 09:41:00 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting...
2026-05-09 09:41:00 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@564e9c0b
2026-05-09 09:41:00 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed.
2026-05-09 09:41:00 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success
2026-05-09 09:41:00 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
2026-05-09 09:41:01 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置
2026-05-09 09:41:01 [main] INFO org.redisson.Version - Redisson 3.52.0
2026-05-09 09:41:02 [redisson-netty-1-5] INFO o.r.connection.ConnectionsHolder - 1 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:41:02 [redisson-netty-1-4] INFO o.r.connection.ConnectionsHolder - 8 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:41:02 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:41:02 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:41:02 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:41:03 [main] INFO o.d.common.json.config.JacksonConfig - 初始化 jackson 配置
2026-05-09 09:41:03 [main] INFO c.a.s.c.s.SnailJobClientJobCoreAutoConfiguration - Snail-Job 客户端IP为: 192.168.0.217
2026-05-09 09:41:03 [main] INFO c.b.m.e.s.MybatisPlusApplicationContextAware - Register ApplicationContext instances org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@1bfe3203
2026-05-09 09:41:07 [main] INFO o.d.w.p.modes.sb.config.BeanConfig - 【warm-flow】加载完成
2026-05-09 09:41:08 [main] INFO io.undertow - starting server: Undertow - 2.3.23.Final
2026-05-09 09:41:08 [main] INFO org.xnio - XNIO version 3.8.16.Final
2026-05-09 09:41:08 [main] INFO org.xnio.nio - XNIO NIO Implementation Version 3.8.16.Final
2026-05-09 09:41:08 [main] INFO org.jboss.threads - JBoss Threads version 3.7.0.Final
2026-05-09 09:41:08 [main] INFO org.dromara.DromaraApplication - Started DromaraApplication in 13.118 seconds (process running for 13.776)
2026-05-09 09:41:08 [main] INFO o.d.c.sse.listener.SseTopicListener - 初始化SSE主题订阅监听器成功
2026-05-09 09:41:08 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client is preparing to start... v1.9.0
2026-05-09 09:41:09 [main] INFO c.a.s.c.c.r.c.g.SnailJobGrpcClient - gRPC client started connect to server
2026-05-09 09:41:09 [main] INFO c.a.s.c.c.rpc.server.SnailGrpcServer - ------> snail-job remoting server start success, grpc = com.aizuda.snailjob.client.common.rpc.server.SnailGrpcServer, port = 28081
2026-05-09 09:41:09 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client started successfully v1.9.0
2026-05-09 09:41:10 [main] INFO o.d.s.runner.SystemApplicationRunner - 初始化OSS配置成功
2026-05-09 09:41:10 [RMI TCP Connection(20)-192.168.111.1] INFO io.undertow.servlet - Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-05-09 09:41:38 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-05-09 09:41:38 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[191]毫秒
2026-05-09 09:42:13 [Thread-5] INFO c.a.s.c.c.window.SlidingRingWindow - JVM is about to exit, emitting data in the Window
2026-05-09 09:42:13 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client about to shutdown v1.9.0
2026-05-09 09:42:13 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log about to shutdown
2026-05-09 09:42:13 [SpringApplicationShutdownHook] INFO c.a.s.c.c.window.SlidingRingWindow - Sliding window is about to exit, emitting data in the Window
2026-05-09 09:42:13 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log has been shutdown
2026-05-09 09:42:13 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client closed successfully v1.9.0
2026-05-09 09:42:13 [SpringApplicationShutdownHook] INFO io.undertow - stopping server: Undertow - 2.3.23.Final
2026-05-09 09:42:13 [SpringApplicationShutdownHook] INFO o.d.c.core.config.ThreadPoolConfig - ====关闭后台任务任务线程池====
2026-05-09 09:42:13 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource start closing ....
2026-05-09 09:42:13 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown initiated...
2026-05-09 09:42:13 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown completed.
2026-05-09 09:42:13 [SpringApplicationShutdownHook] INFO c.b.d.d.d.DefaultDataSourceDestroyer - dynamic-datasource close the datasource named [master] success,
2026-05-09 09:42:13 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource all closed success,bye
2026-05-09 09:42:13 [SpringApplicationShutdownHook] INFO io.undertow.servlet - Destroying Spring FrameworkServlet 'dispatcherServlet'
2026-05-09 09:42:19 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2026-05-09 09:42:19 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 34292 (D:\code\water\water-admin\target\classes started by admin in D:\code\water)
2026-05-09 09:42:19 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev"
2026-05-09 09:42:22 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext
2026-05-09 09:42:22 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it
2026-05-09 09:42:22 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting...
2026-05-09 09:42:23 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@6c4eccd2
2026-05-09 09:42:23 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed.
2026-05-09 09:42:23 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success
2026-05-09 09:42:23 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
2026-05-09 09:42:24 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置
2026-05-09 09:42:24 [main] INFO org.redisson.Version - Redisson 3.52.0
2026-05-09 09:42:24 [redisson-netty-1-5] INFO o.r.connection.ConnectionsHolder - 1 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:42:24 [redisson-netty-1-4] INFO o.r.connection.ConnectionsHolder - 8 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:42:25 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:42:25 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:42:25 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:42:25 [main] INFO o.d.common.json.config.JacksonConfig - 初始化 jackson 配置
2026-05-09 09:42:26 [main] INFO c.a.s.c.s.SnailJobClientJobCoreAutoConfiguration - Snail-Job 客户端IP为: 192.168.0.217
2026-05-09 09:42:26 [main] INFO c.b.m.e.s.MybatisPlusApplicationContextAware - Register ApplicationContext instances org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@65bb9029
2026-05-09 09:42:30 [main] INFO o.d.w.p.modes.sb.config.BeanConfig - 【warm-flow】加载完成
2026-05-09 09:42:31 [main] INFO io.undertow - starting server: Undertow - 2.3.23.Final
2026-05-09 09:42:31 [main] INFO org.xnio - XNIO version 3.8.16.Final
2026-05-09 09:42:31 [main] INFO org.xnio.nio - XNIO NIO Implementation Version 3.8.16.Final
2026-05-09 09:42:31 [main] INFO org.jboss.threads - JBoss Threads version 3.7.0.Final
2026-05-09 09:42:31 [main] INFO org.dromara.DromaraApplication - Started DromaraApplication in 12.491 seconds (process running for 13.272)
2026-05-09 09:42:31 [main] INFO o.d.c.sse.listener.SseTopicListener - 初始化SSE主题订阅监听器成功
2026-05-09 09:42:31 [main] INFO o.d.s.runner.SystemApplicationRunner - 初始化OSS配置成功
2026-05-09 09:42:31 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client is preparing to start... v1.9.0
2026-05-09 09:42:31 [main] INFO c.a.s.c.c.r.c.g.SnailJobGrpcClient - gRPC client started connect to server
2026-05-09 09:42:32 [main] INFO c.a.s.c.c.rpc.server.SnailGrpcServer - ------> snail-job remoting server start success, grpc = com.aizuda.snailjob.client.common.rpc.server.SnailGrpcServer, port = 28081
2026-05-09 09:42:32 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client started successfully v1.9.0
2026-05-09 09:42:32 [RMI TCP Connection(7)-192.168.111.1] INFO io.undertow.servlet - Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-05-09 09:43:11 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-05-09 09:43:11 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[211]毫秒
2026-05-09 09:47:25 [Thread-5] INFO c.a.s.c.c.window.SlidingRingWindow - JVM is about to exit, emitting data in the Window
2026-05-09 09:47:25 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client about to shutdown v1.9.0
2026-05-09 09:47:25 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log about to shutdown
2026-05-09 09:47:25 [SpringApplicationShutdownHook] INFO c.a.s.c.c.window.SlidingRingWindow - Sliding window is about to exit, emitting data in the Window
2026-05-09 09:47:25 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log has been shutdown
2026-05-09 09:47:25 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client closed successfully v1.9.0
2026-05-09 09:47:25 [SpringApplicationShutdownHook] INFO io.undertow - stopping server: Undertow - 2.3.23.Final
2026-05-09 09:47:25 [SpringApplicationShutdownHook] INFO o.d.c.core.config.ThreadPoolConfig - ====关闭后台任务任务线程池====
2026-05-09 09:47:25 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource start closing ....
2026-05-09 09:47:25 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown initiated...
2026-05-09 09:47:25 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown completed.
2026-05-09 09:47:25 [SpringApplicationShutdownHook] INFO c.b.d.d.d.DefaultDataSourceDestroyer - dynamic-datasource close the datasource named [master] success,
2026-05-09 09:47:25 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource all closed success,bye
2026-05-09 09:47:25 [SpringApplicationShutdownHook] INFO io.undertow.servlet - Destroying Spring FrameworkServlet 'dispatcherServlet'
2026-05-09 09:47:29 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2026-05-09 09:47:29 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 11244 (D:\code\water\water-admin\target\classes started by admin in D:\code\water)
2026-05-09 09:47:29 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev"
2026-05-09 09:47:32 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext
2026-05-09 09:47:32 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it
2026-05-09 09:47:32 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting...
2026-05-09 09:47:32 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@564e9c0b
2026-05-09 09:47:32 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed.
2026-05-09 09:47:32 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success
2026-05-09 09:47:32 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
2026-05-09 09:47:34 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置
2026-05-09 09:47:35 [main] INFO org.redisson.Version - Redisson 3.52.0
2026-05-09 09:47:35 [redisson-netty-1-5] INFO o.r.connection.ConnectionsHolder - 1 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:47:35 [redisson-netty-1-4] INFO o.r.connection.ConnectionsHolder - 8 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:47:36 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:47:36 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:47:36 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:47:37 [main] INFO o.d.common.json.config.JacksonConfig - 初始化 jackson 配置
2026-05-09 09:47:37 [main] INFO c.a.s.c.s.SnailJobClientJobCoreAutoConfiguration - Snail-Job 客户端IP为: 192.168.0.217
2026-05-09 09:47:37 [main] INFO c.b.m.e.s.MybatisPlusApplicationContextAware - Register ApplicationContext instances org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@1bfe3203
2026-05-09 09:47:45 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2026-05-09 09:47:45 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 32536 (D:\code\water\water-admin\target\classes started by admin in D:\code\water)
2026-05-09 09:47:45 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev"
2026-05-09 09:47:48 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext
2026-05-09 09:47:48 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it
2026-05-09 09:47:48 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting...
2026-05-09 09:47:48 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@21d478f3
2026-05-09 09:47:48 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed.
2026-05-09 09:47:48 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success
2026-05-09 09:47:48 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
2026-05-09 09:47:50 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置
2026-05-09 09:47:50 [main] INFO org.redisson.Version - Redisson 3.52.0
2026-05-09 09:47:50 [redisson-netty-1-5] INFO o.r.connection.ConnectionsHolder - 1 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:47:50 [redisson-netty-1-4] INFO o.r.connection.ConnectionsHolder - 8 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:47:51 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:47:51 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:47:51 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:47:52 [main] INFO o.d.common.json.config.JacksonConfig - 初始化 jackson 配置
2026-05-09 09:47:52 [main] INFO c.a.s.c.s.SnailJobClientJobCoreAutoConfiguration - Snail-Job 客户端IP为: 192.168.0.217
2026-05-09 09:47:52 [main] INFO c.b.m.e.s.MybatisPlusApplicationContextAware - Register ApplicationContext instances org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@1bfe3203
2026-05-09 09:47:57 [main] INFO o.d.w.p.modes.sb.config.BeanConfig - 【warm-flow】加载完成
2026-05-09 09:47:57 [main] INFO io.undertow - starting server: Undertow - 2.3.23.Final
2026-05-09 09:47:57 [main] INFO org.xnio - XNIO version 3.8.16.Final
2026-05-09 09:47:58 [main] INFO org.xnio.nio - XNIO NIO Implementation Version 3.8.16.Final
2026-05-09 09:47:58 [main] INFO org.jboss.threads - JBoss Threads version 3.7.0.Final
2026-05-09 09:47:58 [main] INFO org.dromara.DromaraApplication - Started DromaraApplication in 13.714 seconds (process running for 14.472)
2026-05-09 09:47:58 [main] INFO o.d.c.sse.listener.SseTopicListener - 初始化SSE主题订阅监听器成功
2026-05-09 09:47:58 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client is preparing to start... v1.9.0
2026-05-09 09:47:58 [main] INFO c.a.s.c.c.r.c.g.SnailJobGrpcClient - gRPC client started connect to server
2026-05-09 09:47:58 [main] INFO c.a.s.c.c.rpc.server.SnailGrpcServer - ------> snail-job remoting server start success, grpc = com.aizuda.snailjob.client.common.rpc.server.SnailGrpcServer, port = 28081
2026-05-09 09:47:59 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client started successfully v1.9.0
2026-05-09 09:47:59 [main] INFO o.d.s.runner.SystemApplicationRunner - 初始化OSS配置成功
2026-05-09 09:47:59 [RMI TCP Connection(21)-192.168.111.1] INFO io.undertow.servlet - Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-05-09 09:48:24 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-05-09 09:48:24 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[186]毫秒
2026-05-09 09:49:55 [Thread-5] INFO c.a.s.c.c.window.SlidingRingWindow - JVM is about to exit, emitting data in the Window
2026-05-09 09:49:55 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client about to shutdown v1.9.0
2026-05-09 09:49:55 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log about to shutdown
2026-05-09 09:49:55 [SpringApplicationShutdownHook] INFO c.a.s.c.c.window.SlidingRingWindow - Sliding window is about to exit, emitting data in the Window
2026-05-09 09:49:55 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log has been shutdown
2026-05-09 09:49:55 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client closed successfully v1.9.0
2026-05-09 09:49:55 [SpringApplicationShutdownHook] INFO io.undertow - stopping server: Undertow - 2.3.23.Final
2026-05-09 09:49:55 [SpringApplicationShutdownHook] INFO o.d.c.core.config.ThreadPoolConfig - ====关闭后台任务任务线程池====
2026-05-09 09:49:55 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource start closing ....
2026-05-09 09:49:55 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown initiated...
2026-05-09 09:49:55 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown completed.
2026-05-09 09:49:55 [SpringApplicationShutdownHook] INFO c.b.d.d.d.DefaultDataSourceDestroyer - dynamic-datasource close the datasource named [master] success,
2026-05-09 09:49:55 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource all closed success,bye
2026-05-09 09:49:55 [SpringApplicationShutdownHook] INFO io.undertow.servlet - Destroying Spring FrameworkServlet 'dispatcherServlet'
2026-05-09 09:50:00 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2026-05-09 09:50:00 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 15312 (D:\code\water\water-admin\target\classes started by admin in D:\code\water)
2026-05-09 09:50:00 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev"
2026-05-09 09:50:03 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext
2026-05-09 09:50:03 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it
2026-05-09 09:50:03 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting...
2026-05-09 09:50:04 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@5367d46f
2026-05-09 09:50:04 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed.
2026-05-09 09:50:04 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success
2026-05-09 09:50:04 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
2026-05-09 09:50:05 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置
2026-05-09 09:50:05 [main] INFO org.redisson.Version - Redisson 3.52.0
2026-05-09 09:50:05 [redisson-netty-1-5] INFO o.r.connection.ConnectionsHolder - 1 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:50:05 [redisson-netty-1-4] INFO o.r.connection.ConnectionsHolder - 8 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:50:06 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:50:06 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:50:06 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:50:06 [main] INFO o.d.common.json.config.JacksonConfig - 初始化 jackson 配置
2026-05-09 09:50:07 [main] INFO c.a.s.c.s.SnailJobClientJobCoreAutoConfiguration - Snail-Job 客户端IP为: 192.168.0.217
2026-05-09 09:50:07 [main] INFO c.b.m.e.s.MybatisPlusApplicationContextAware - Register ApplicationContext instances org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@1bfe3203
2026-05-09 09:50:11 [main] INFO o.d.w.p.modes.sb.config.BeanConfig - 【warm-flow】加载完成
2026-05-09 09:50:12 [main] INFO io.undertow - starting server: Undertow - 2.3.23.Final
2026-05-09 09:50:12 [main] INFO org.xnio - XNIO version 3.8.16.Final
2026-05-09 09:50:12 [main] INFO org.xnio.nio - XNIO NIO Implementation Version 3.8.16.Final
2026-05-09 09:50:12 [main] INFO org.jboss.threads - JBoss Threads version 3.7.0.Final
2026-05-09 09:50:12 [main] INFO org.dromara.DromaraApplication - Started DromaraApplication in 12.908 seconds (process running for 13.548)
2026-05-09 09:50:12 [main] INFO o.d.c.sse.listener.SseTopicListener - 初始化SSE主题订阅监听器成功
2026-05-09 09:50:12 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client is preparing to start... v1.9.0
2026-05-09 09:50:12 [main] INFO c.a.s.c.c.r.c.g.SnailJobGrpcClient - gRPC client started connect to server
2026-05-09 09:50:13 [main] INFO c.a.s.c.c.rpc.server.SnailGrpcServer - ------> snail-job remoting server start success, grpc = com.aizuda.snailjob.client.common.rpc.server.SnailGrpcServer, port = 28081
2026-05-09 09:50:13 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client started successfully v1.9.0
2026-05-09 09:50:13 [main] INFO o.d.s.runner.SystemApplicationRunner - 初始化OSS配置成功
2026-05-09 09:50:14 [RMI TCP Connection(9)-192.168.111.1] INFO io.undertow.servlet - Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-05-09 09:50:18 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-05-09 09:50:18 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[217]毫秒
2026-05-09 09:50:43 [Thread-5] INFO c.a.s.c.c.window.SlidingRingWindow - JVM is about to exit, emitting data in the Window
2026-05-09 09:50:43 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client about to shutdown v1.9.0
2026-05-09 09:50:43 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log about to shutdown
2026-05-09 09:50:43 [SpringApplicationShutdownHook] INFO c.a.s.c.c.window.SlidingRingWindow - Sliding window is about to exit, emitting data in the Window
2026-05-09 09:50:43 [SpringApplicationShutdownHook] INFO c.a.s.c.c.l.report.AbstractLogReport - AsyncReport Log has been shutdown
2026-05-09 09:50:43 [SpringApplicationShutdownHook] INFO c.a.s.c.c.init.SnailJobCloseListener - snail-job client closed successfully v1.9.0
2026-05-09 09:50:43 [SpringApplicationShutdownHook] INFO io.undertow - stopping server: Undertow - 2.3.23.Final
2026-05-09 09:50:43 [SpringApplicationShutdownHook] INFO o.d.c.core.config.ThreadPoolConfig - ====关闭后台任务任务线程池====
2026-05-09 09:50:43 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource start closing ....
2026-05-09 09:50:43 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown initiated...
2026-05-09 09:50:43 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown completed.
2026-05-09 09:50:43 [SpringApplicationShutdownHook] INFO c.b.d.d.d.DefaultDataSourceDestroyer - dynamic-datasource close the datasource named [master] success,
2026-05-09 09:50:43 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource all closed success,bye
2026-05-09 09:50:43 [SpringApplicationShutdownHook] INFO io.undertow.servlet - Destroying Spring FrameworkServlet 'dispatcherServlet'
2026-05-09 09:50:48 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 8.0.3.Final
2026-05-09 09:50:48 [main] INFO org.dromara.DromaraApplication - Starting DromaraApplication using Java 17.0.17 with PID 27588 (D:\code\water\water-admin\target\classes started by admin in D:\code\water)
2026-05-09 09:50:48 [main] INFO org.dromara.DromaraApplication - The following 1 profile is active: "dev"
2026-05-09 09:50:51 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext
2026-05-09 09:50:51 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it
2026-05-09 09:50:51 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting...
2026-05-09 09:50:51 [main] INFO com.zaxxer.hikari.pool.HikariPool - master - Added connection com.mysql.cj.jdbc.ConnectionImpl@5367d46f
2026-05-09 09:50:51 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed.
2026-05-09 09:50:51 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success
2026-05-09 09:50:51 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [1] datasource,primary datasource named [master]
2026-05-09 09:50:52 [main] INFO o.d.common.redis.config.RedisConfig - 初始化 redis 配置
2026-05-09 09:50:52 [main] INFO org.redisson.Version - Redisson 3.52.0
2026-05-09 09:50:53 [redisson-netty-1-5] INFO o.r.connection.ConnectionsHolder - 1 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:50:53 [redisson-netty-1-4] INFO o.r.connection.ConnectionsHolder - 8 connections initialized for localhost/127.0.0.1:6379
2026-05-09 09:50:54 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:50:54 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:50:54 [main] INFO c.a.s.c.j.c.e.b.AbstractScriptExecutor$SnailFileUtils - [FileUtils] [workspace] use user.home as workspace: C:\Users\admin/snailJob/worker
2026-05-09 09:50:54 [main] INFO o.d.common.json.config.JacksonConfig - 初始化 jackson 配置
2026-05-09 09:50:54 [main] INFO c.a.s.c.s.SnailJobClientJobCoreAutoConfiguration - Snail-Job 客户端IP为: 192.168.0.217
2026-05-09 09:50:54 [main] INFO c.b.m.e.s.MybatisPlusApplicationContextAware - Register ApplicationContext instances org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@1bfe3203
2026-05-09 09:50:58 [main] INFO o.d.w.p.modes.sb.config.BeanConfig - 【warm-flow】加载完成
2026-05-09 09:50:59 [main] INFO io.undertow - starting server: Undertow - 2.3.23.Final
2026-05-09 09:50:59 [main] INFO org.xnio - XNIO version 3.8.16.Final
2026-05-09 09:50:59 [main] INFO org.xnio.nio - XNIO NIO Implementation Version 3.8.16.Final
2026-05-09 09:50:59 [main] INFO org.jboss.threads - JBoss Threads version 3.7.0.Final
2026-05-09 09:50:59 [main] INFO org.dromara.DromaraApplication - Started DromaraApplication in 12.544 seconds (process running for 13.162)
2026-05-09 09:50:59 [main] INFO o.d.c.sse.listener.SseTopicListener - 初始化SSE主题订阅监听器成功
2026-05-09 09:50:59 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client is preparing to start... v1.9.0
2026-05-09 09:51:00 [main] INFO c.a.s.c.c.r.c.g.SnailJobGrpcClient - gRPC client started connect to server
2026-05-09 09:51:00 [main] INFO c.a.s.c.c.rpc.server.SnailGrpcServer - ------> snail-job remoting server start success, grpc = com.aizuda.snailjob.client.common.rpc.server.SnailGrpcServer, port = 28081
2026-05-09 09:51:00 [main] INFO c.a.s.c.c.init.SnailJobStartListener - snail-job client started successfully v1.9.0
2026-05-09 09:51:01 [main] INFO o.d.s.runner.SystemApplicationRunner - 初始化OSS配置成功
2026-05-09 09:51:01 [RMI TCP Connection(5)-192.168.111.1] INFO io.undertow.servlet - Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-05-09 09:51:20 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-05-09 09:51:20 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[160]毫秒
2026-05-09 09:52:40 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-05-09 09:52:40 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[15]毫秒
2026-05-09 09:52:41 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]开始请求 => URL[GET /app/v1/deviceList],无参数
2026-05-09 09:52:42 [XNIO-1 task-2] INFO o.d.c.w.i.PlusWebInvokeTimeInterceptor - [PLUS]结束请求 => URL[GET /app/v1/deviceList],耗时:[21]毫秒

View File

@@ -357,6 +357,12 @@
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>water-app</artifactId>
<version>${revision}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@@ -87,6 +87,12 @@
<artifactId>water-demo</artifactId> <artifactId>water-demo</artifactId>
</dependency> </dependency>
<!-- app模块 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>water-app</artifactId>
</dependency>
<!-- 工作流模块 --> <!-- 工作流模块 -->
<dependency> <dependency>
<groupId>org.dromara</groupId> <groupId>org.dromara</groupId>

View File

@@ -15,9 +15,11 @@ import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils; import me.zhyd.oauth.utils.AuthStateUtils;
import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.SystemConstants;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.ForgotLoginBody;
import org.dromara.common.core.domain.model.LoginBody; import org.dromara.common.core.domain.model.LoginBody;
import org.dromara.common.core.domain.model.RegisterBody; import org.dromara.common.core.domain.model.RegisterBody;
import org.dromara.common.core.domain.model.SocialLoginBody; import org.dromara.common.core.domain.model.SocialLoginBody;
import org.dromara.common.core.exception.user.UserException;
import org.dromara.common.core.utils.*; import org.dromara.common.core.utils.*;
import org.dromara.common.encrypt.annotation.ApiEncrypt; import org.dromara.common.encrypt.annotation.ApiEncrypt;
import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.json.utils.JsonUtils;
@@ -40,6 +42,7 @@ import org.dromara.system.service.ISysTenantService;
import org.dromara.web.domain.vo.LoginTenantVo; import org.dromara.web.domain.vo.LoginTenantVo;
import org.dromara.web.domain.vo.LoginVo; import org.dromara.web.domain.vo.LoginVo;
import org.dromara.web.domain.vo.TenantListVo; import org.dromara.web.domain.vo.TenantListVo;
import org.dromara.web.service.ForgotPasswordService;
import org.dromara.web.service.IAuthStrategy; import org.dromara.web.service.IAuthStrategy;
import org.dromara.web.service.SysLoginService; import org.dromara.web.service.SysLoginService;
import org.dromara.web.service.SysRegisterService; import org.dromara.web.service.SysRegisterService;
@@ -75,7 +78,7 @@ public class AuthController {
private final ISysSocialService socialUserService; private final ISysSocialService socialUserService;
private final ISysClientService clientService; private final ISysClientService clientService;
private final ScheduledExecutorService scheduledExecutorService; private final ScheduledExecutorService scheduledExecutorService;
private final ForgotPasswordService forgotPasswordService;
/** /**
* 登录方法 * 登录方法
@@ -83,12 +86,13 @@ public class AuthController {
* @param body 登录信息 * @param body 登录信息
* @return 结果 * @return 结果
*/ */
@ApiEncrypt @ApiEncrypt
@PostMapping("/login") @PostMapping("/login")
public R<LoginVo> login(@RequestBody String body) { public R<LoginVo> login(@RequestBody String body) {
LoginBody loginBody = JsonUtils.parseObject(body, LoginBody.class); LoginBody loginBody = JsonUtils.parseObject(body, LoginBody.class);
ValidatorUtils.validate(loginBody); ValidatorUtils.validate(loginBody);
// 授权类型和客户端id // 授权类型和客户端id
String clientId = loginBody.getClientId(); String clientId = loginBody.getClientId();
String grantType = loginBody.getGrantType(); String grantType = loginBody.getGrantType();
SysClientVo client = clientService.queryByClientId(clientId); SysClientVo client = clientService.queryByClientId(clientId);
@@ -114,6 +118,7 @@ public class AuthController {
return R.ok(loginVo); return R.ok(loginVo);
} }
/** /**
* 获取跳转URL * 获取跳转URL
* *
@@ -136,6 +141,7 @@ public class AuthController {
return R.ok("操作成功", authorizeUrl); return R.ok("操作成功", authorizeUrl);
} }
/** /**
* 前端回调绑定授权(需要token) * 前端回调绑定授权(需要token)
* *
@@ -196,6 +202,7 @@ public class AuthController {
return R.ok(); return R.ok();
} }
/** /**
* 登录页面租户下拉框 * 登录页面租户下拉框
* *
@@ -240,4 +247,19 @@ public class AuthController {
return R.ok(result); return R.ok(result);
} }
/**
* app用户忘记密码
*/
@ApiEncrypt
@PutMapping("/forgot")
public R<Void> forgot(@RequestBody String body) {
ForgotLoginBody loginBody = JsonUtils.parseObject(body, ForgotLoginBody.class);
boolean forgotFlag = forgotPasswordService.forgotPasswordService(loginBody);
if (!forgotFlag){
throw new UserException("忘记密码修改失败");
}
return R.ok();
}
} }

View File

@@ -4,6 +4,7 @@ import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.captcha.generator.CodeGenerator; import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.captcha.generator.MathGenerator; import cn.hutool.captcha.generator.MathGenerator;
import cn.hutool.captcha.generator.RandomGenerator; import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
@@ -52,6 +53,40 @@ public class CaptchaController {
private final CaptchaProperties captchaProperties; private final CaptchaProperties captchaProperties;
private final MailProperties mailProperties; private final MailProperties mailProperties;
/**
* 验证码
*
* @param username 用户手机号
*/
@RateLimiter(key = "#username", time = 60, count = 1)
@GetMapping("/resource/code")
public R<Void> code(@NotBlank(message = "{user.username.not.blank}") String username) {
String key = GlobalConstants.CAPTCHA_CODE_KEY + username;
String code = RandomUtil.randomNumbers(6);
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
if (Validator.isMobile(username)){
// 验证码模板id 自行处理 (查数据库或写死均可)
String templateId = "";
LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put("code", code);
SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
SmsResponse smsResponse = smsBlend.sendMessage(username, templateId, map);
if (!smsResponse.isSuccess()) {
log.error("验证码短信发送异常 => {}", smsResponse);
return R.fail(smsResponse.getData().toString());
}
}else {
emailCodeImpl(username);
}
return R.ok();
}
/** /**
* 短信验证码 * 短信验证码
* *
@@ -97,7 +132,7 @@ public class CaptchaController {
@RateLimiter(key = "#email", time = 60, count = 1) @RateLimiter(key = "#email", time = 60, count = 1)
public void emailCodeImpl(String email) { public void emailCodeImpl(String email) {
String key = GlobalConstants.CAPTCHA_CODE_KEY + email; String key = GlobalConstants.CAPTCHA_CODE_KEY + email;
String code = RandomUtil.randomNumbers(4); String code = RandomUtil.randomNumbers(6);
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
try { try {
MailUtils.sendText(email, "登录验证码", "您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。"); MailUtils.sendText(email, "登录验证码", "您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。");

View File

@@ -0,0 +1,62 @@
package org.dromara.web.service;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.GlobalConstants;
import org.dromara.common.core.domain.model.ForgotLoginBody;
import org.dromara.common.core.exception.user.CaptchaExpireException;
import org.dromara.common.core.exception.user.UserException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.mapper.SysUserMapper;
import org.springframework.stereotype.Service;
@RequiredArgsConstructor
@Service
public class ForgotPasswordService {
private final SysUserMapper userMapper;
public boolean forgotPasswordService(ForgotLoginBody loginBody) {
SysUserVo appUserVo =new SysUserVo();
if(Validator.isEmail(loginBody.getUsername())){
userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getEmail, loginBody.getUsername()));
}else if (Validator.isMobile(loginBody.getUsername())){
appUserVo = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhonenumber, loginBody.getUsername()));
}else {
appUserVo = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, loginBody.getUsername()));
}
if (ObjectUtil.isNull(appUserVo)){
throw new UserException("账号未注册");
}
boolean validateFlag = validateSmsCode(loginBody.getUsername(), loginBody.getSmsCode());
if (!validateFlag){
throw new UserException("验证码无效");
}
appUserVo.setPassword(BCrypt.hashpw(loginBody.getPassword()));
SysUser update = MapstructUtils.convert(appUserVo, SysUser.class);
userMapper.updateById(update);
return userMapper.updateById(update) > 0;
}
/**
* 校验短信验证码
*/
private boolean validateSmsCode(String username, String smsCode) {
String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + username);
if (StringUtils.isBlank(code)) {
throw new CaptchaExpireException();
}
return code.equals(smsCode);
}
}

View File

@@ -1,7 +1,9 @@
package org.dromara.web.service; package org.dromara.web.service;
import cn.hutool.core.lang.Validator;
import cn.hutool.crypto.digest.BCrypt; import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.Data;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.Constants; import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.constant.GlobalConstants; import org.dromara.common.core.constant.GlobalConstants;
@@ -24,6 +26,8 @@ import org.dromara.system.mapper.SysUserMapper;
import org.dromara.system.service.ISysUserService; import org.dromara.system.service.ISysUserService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Date;
/** /**
* 注册校验方法 * 注册校验方法
* *
@@ -44,24 +48,52 @@ public class SysRegisterService {
String tenantId = registerBody.getTenantId(); String tenantId = registerBody.getTenantId();
String username = registerBody.getUsername(); String username = registerBody.getUsername();
String password = registerBody.getPassword(); String password = registerBody.getPassword();
String code = registerBody.getCode();
// 校验用户类型是否存在 // 校验用户类型是否存在
String userType = UserType.getUserType(registerBody.getUserType()).getUserType(); String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
boolean captchaEnabled = captchaProperties.getEnable(); // boolean captchaEnabled = captchaProperties.getEnable();
// 验证码开关 // // 验证码开关
if (captchaEnabled) { // if (captchaEnabled) {
validateCaptcha(tenantId, username, registerBody.getCode(), registerBody.getUuid()); // validateCaptcha(tenantId, username, registerBody.getCode(), registerBody.getUuid());
// }
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + username;
String captcha = RedisUtils.getCacheObject(verifyKey);
if (captcha==null){
throw new CaptchaExpireException();
} }
if (!StringUtils.equalsIgnoreCase(code, captcha)){
throw new CaptchaExpireException();
}
SysUserBo sysUser = new SysUserBo(); SysUserBo sysUser = new SysUserBo();
sysUser.setUserName(username); // sysUser.setUserName(username);
sysUser.setNickName(username);
sysUser.setNickName("用户"+new Date().getTime());
sysUser.setPassword(BCrypt.hashpw(password)); sysUser.setPassword(BCrypt.hashpw(password));
sysUser.setUserType(userType); sysUser.setUserType(userType);
boolean exist;
boolean exist = TenantHelper.dynamic(tenantId, () -> { if(Validator.isEmail(username)){
sysUser.setEmail(username);
exist = TenantHelper.dynamic(tenantId, () -> {
return userMapper.exists(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getEmail, sysUser.getEmail()));
});
}else if(Validator.isMobile(username)) {
sysUser.setPhonenumber(username);
exist = TenantHelper.dynamic(tenantId, () -> {
return userMapper.exists(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getPhonenumber, sysUser.getPhonenumber()));
});
}else {
sysUser.setUserName(username);
exist = TenantHelper.dynamic(tenantId, () -> {
return userMapper.exists(new LambdaQueryWrapper<SysUser>() return userMapper.exists(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getUserName, sysUser.getUserName())); .eq(SysUser::getUserName, sysUser.getUserName()));
}); });
}
if (exist) { if (exist) {
throw new UserException("user.register.save.error", username); throw new UserException("user.register.save.error", username);
} }

View File

@@ -2,6 +2,7 @@ package org.dromara.web.service.impl;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter; import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.BCrypt; import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -57,13 +58,25 @@ public class PasswordAuthStrategy implements IAuthStrategy {
String code = loginBody.getCode(); String code = loginBody.getCode();
String uuid = loginBody.getUuid(); String uuid = loginBody.getUuid();
boolean captchaEnabled = captchaProperties.getEnable(); // boolean captchaEnabled = captchaProperties.getEnable();
// 验证码开关 // // 验证码开关
if (captchaEnabled) { // if (captchaEnabled) {
validateCaptcha(tenantId, username, code, uuid); // validateCaptcha(tenantId, username, code, uuid);
} // }
LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> { LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> {
SysUserVo user = loadUserByUsername(username); SysUserVo user ;
if(Validator.isEmail(username)){
user = loadUserByEmail(username);
}else if (Validator.isMobile(username)){
user = loadUserByPhone(username);
}else {
user = loadUserByUsername(username);
}
loginService.checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword())); loginService.checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword()));
// 此处可根据登录用户的数据不同 自行创建 loginUser // 此处可根据登录用户的数据不同 自行创建 loginUser
return loginService.buildLoginUser(user); return loginService.buildLoginUser(user);
@@ -120,4 +133,28 @@ public class PasswordAuthStrategy implements IAuthStrategy {
return user; return user;
} }
private SysUserVo loadUserByEmail(String username) {
SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getEmail, username));
if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", username);
throw new UserException("user.not.exists", username);
} else if (SystemConstants.DISABLE.equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.", username);
throw new UserException("user.blocked", username);
}
return user;
}
private SysUserVo loadUserByPhone(String username) {
SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhonenumber, username));
if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", username);
throw new UserException("user.not.exists", username);
} else if (SystemConstants.DISABLE.equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.", username);
throw new UserException("user.blocked", username);
}
return user;
}
} }

View File

@@ -133,17 +133,17 @@ redisson:
--- # mail 邮件发送 --- # mail 邮件发送
mail: mail:
enabled: false enabled: true
host: smtp.163.com host: smtp.163.com
port: 465 port: 465
# 是否需要用户名密码验证 # 是否需要用户名密码验证
auth: true auth: true
# 发送方遵循RFC-822标准 # 发送方遵循RFC-822标准
from: xxx@163.com from: watexdevice@163.com
# 用户名注意如果使用foxmail邮箱此处user为qq号 # 用户名注意如果使用foxmail邮箱此处user为qq号
user: xxx@163.com user: watexdevice@163.com
# 密码注意某些邮箱需要为SMTP服务单独设置密码详情查看相关帮助 # 密码注意某些邮箱需要为SMTP服务单独设置密码详情查看相关帮助
pass: xxxxxxxxxx pass: XZVDXjRdVrjiX8N3
# 使用 STARTTLS安全连接STARTTLS是对纯文本通信协议的扩展。 # 使用 STARTTLS安全连接STARTTLS是对纯文本通信协议的扩展。
starttlsEnable: true starttlsEnable: true
# 使用SSL安全连接 # 使用SSL安全连接

View File

@@ -19,7 +19,6 @@ server:
io: 8 io: 8
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载 # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
worker: 256 worker: 256
captcha: captcha:
# 是否启用验证码校验 # 是否启用验证码校验
enable: true enable: true
@@ -120,7 +119,7 @@ security:
# 多租户配置 # 多租户配置
tenant: tenant:
# 是否开启 # 是否开启
enable: true enable: false
# 排除表 # 排除表
excludes: excludes:
- sys_menu - sys_menu
@@ -169,7 +168,7 @@ mybatis-encryptor:
# api接口加密 # api接口加密
api-decrypt: api-decrypt:
# 是否开启全局接口加密 # 是否开启全局接口加密
enabled: true enabled: false
# AES 加密头标识 # AES 加密头标识
headerFlag: encrypt-key headerFlag: encrypt-key
# 响应加密公钥 非对称算法的公私钥 如SM2RSA 使用者请自行更换 # 响应加密公钥 非对称算法的公私钥 如SM2RSA 使用者请自行更换

View File

@@ -1,62 +1 @@
#错误消息 #错误消息
not.null=* 必须填写
user.jcaptcha.error=验证码错误
user.jcaptcha.expire=验证码已失效
user.not.exists=对不起, 您的账号:{0} 不存在.
user.password.not.match=用户不存在/密码错误
user.password.retry.limit.count=密码输入错误{0}次
user.password.retry.limit.exceed=密码输入错误{0}次,账户锁定{1}分钟
user.password.delete=对不起,您的账号:{0} 已被删除
user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
role.blocked=角色已封禁,请联系管理员
user.logout.success=退出成功
length.not.valid=长度必须在{min}到{max}个字符之间
user.username.not.blank=用户名不能为空
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成且必须以非数字开头
user.username.length.valid=账户长度必须在{min}到{max}个字符之间
user.password.not.blank=用户密码不能为空
user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
user.password.not.valid=* 5-50个字符
user.password.format.valid=密码必须包含大写字母、小写字母、数字和特殊字符
user.email.not.valid=邮箱格式错误
user.email.not.blank=邮箱不能为空
user.phonenumber.not.blank=用户手机号不能为空
user.mobile.phone.number.not.valid=手机号格式错误
user.login.success=登录成功
user.register.success=注册成功
user.register.save.error=保存用户 {0} 失败,注册账号已存在
user.register.error=注册失败,请联系系统管理人员
user.notfound=请重新登录
user.forcelogout=管理员强制退出,请重新登录
user.unknown.error=未知错误,请重新登录
auth.grant.type.error=认证权限类型错误
auth.grant.type.blocked=认证权限类型已禁用
auth.grant.type.not.blank=认证权限类型不能为空
auth.clientid.not.blank=认证客户端id不能为空
##文件上传消息
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB
upload.filename.exceed.length=上传的文件名最长{0}个字符
##权限
no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
repeat.submit.message=不允许重复提交,请稍候再试
rate.limiter.message=访问过于频繁,请稍候再试
sms.code.not.blank=短信验证码不能为空
sms.code.retry.limit.count=短信验证码输入错误{0}次
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,账户锁定{1}分钟
email.code.not.blank=邮箱验证码不能为空
email.code.retry.limit.count=邮箱验证码输入错误{0}次
email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,账户锁定{1}分钟
xcx.code.not.blank=小程序[code]不能为空
social.source.not.blank=第三方登录平台[source]不能为空
social.code.not.blank=第三方登录平台[code]不能为空
social.state.not.blank=第三方登录平台[state]不能为空
##租户
tenant.number.not.blank=租户编号不能为空
tenant.not.exists=对不起, 您的租户不存在,请联系管理员
tenant.blocked=对不起,您的租户已禁用,请联系管理员
tenant.expired=对不起,您的租户已过期,请联系管理员

View File

@@ -65,7 +65,7 @@ public interface Constants {
/** /**
* 验证码有效期(分钟) * 验证码有效期(分钟)
*/ */
Integer CAPTCHA_EXPIRATION = 2; Integer CAPTCHA_EXPIRATION = 5;
/** /**
* 顶级父级id * 顶级父级id

View File

@@ -16,6 +16,7 @@ public interface GlobalConstants {
* 验证码 redis key * 验证码 redis key
*/ */
String CAPTCHA_CODE_KEY = GLOBAL_REDIS_KEY + "captcha_codes:"; String CAPTCHA_CODE_KEY = GLOBAL_REDIS_KEY + "captcha_codes:";
String CAPTCHA_EMAIL_CODE_KEY = GLOBAL_REDIS_KEY + "captcha_email_codes:";
/** /**
* 防重提交 redis key * 防重提交 redis key

View File

@@ -0,0 +1,45 @@
package org.dromara.common.core.domain.model;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.validator.constraints.Length;
/**
* 短信登录对象
*
* @author Lion Li
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class ForgotLoginBody extends LoginBody {
/**
* 手机号
*/
@NotBlank(message = "{user.phonenumber.not.blank}")
private String phonenumber;
/**
* 短信code
*/
@NotBlank(message = "{sms.code.not.blank}")
private String smsCode;
/**
* 用户名
*/
@NotBlank(message = "{user.username.not.blank}")
@Length(min = 2, max = 30, message = "{user.username.length.valid}")
private String username;
/**
* 用户密码
*/
@NotBlank(message = "{user.password.not.blank}")
@Length(min = 5, max = 30, message = "{user.password.length.valid}")
// @Pattern(regexp = RegexConstants.PASSWORD, message = "{user.password.format.valid}")
private String password;
}

View File

@@ -33,5 +33,9 @@ public class RegisterBody extends LoginBody {
* 用户类型 * 用户类型
*/ */
private String userType; private String userType;
/**
* 验证码
*/
private String code;
} }

View File

@@ -102,6 +102,10 @@
<groupId>org.dromara</groupId> <groupId>org.dromara</groupId>
<artifactId>water-common-websocket</artifactId> <artifactId>water-common-websocket</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>water-system</artifactId>
</dependency>
</dependencies> </dependencies>

View File

@@ -0,0 +1,306 @@
package org.dromara.app.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.BCrypt;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.app.domain.bo.AppDeviceBo;
import org.dromara.app.domain.bo.AppScheduleBo;
import org.dromara.app.domain.vo.AppDeviceVo;
import org.dromara.app.domain.vo.AppScheduleDetailVo;
import org.dromara.app.domain.vo.AppScheduleVo;
import org.dromara.app.domain.vo.AppSchedulingDeviceVo;
import org.dromara.app.service.IAppDeviceService;
import org.dromara.app.service.IAppScheduleDetailService;
import org.dromara.app.service.IAppScheduleService;
import org.dromara.app.service.IAppSchedulingDeviceService;
import org.dromara.app.service.impl.AppScheduleDetailServiceImpl;
import org.dromara.app.service.impl.AppScheduleServiceImpl;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.ForgotLoginBody;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.enums.LoginType;
import org.dromara.common.core.exception.user.UserException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.encrypt.annotation.ApiEncrypt;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.helper.DataPermissionHelper;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.domain.vo.UserInfoVo;
import org.dromara.system.service.ISysUserService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Slf4j
@RequiredArgsConstructor
@RestController
//@SaCheckLogin
@RequestMapping("/app/v1")
public class AppController extends BaseController {
private final IAppDeviceService appDeviceService;
private final IAppScheduleService appScheduleService;
private final IAppScheduleDetailService appScheduleDetailService;
private final AppScheduleServiceImpl appScheduleServiceimpl;
private final IAppSchedulingDeviceService appSchedulingDeviceService;
private final ISysUserService userService;
/**
*查询设备
*
*/
@GetMapping("/deviceList")
public TableDataInfo<AppDeviceVo> list(AppDeviceBo bo, PageQuery pageQuery) {
bo.setUserId(LoginHelper.getUserId());
return appDeviceService.queryPageList(bo, pageQuery);
}
/**
* 添加设备
*
*/
//@SaCheckRole("appadmin")
@ApiEncrypt
@PostMapping("/addDevice")
public R<Void> addDevice(@RequestBody String body) {
AppDeviceBo appDevic = JsonUtils.parseObject(body, AppDeviceBo.class);
appDevic.setUserId(LoginHelper.getUserId());
Boolean b = appDeviceService.insertByBo(appDevic);
if (b){
return R.ok();
}else {
return R.fail();
}
}
/**
* 获取设备信息
详细信息
*
* @param id 主键
*/
@GetMapping("/device/{id}")
public R<AppDeviceVo> getDeviceInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(appDeviceService.queryById(id));
}
/**
* 修改设备信息
*
*/
// @SaCheckRole("appadmin")
@RepeatSubmit()
@PutMapping("/updateDeviceInfo")
public R<Void> updateDeviceInfo(@Validated @RequestBody AppDeviceBo bo) {
try {
return toAjax(appDeviceService.updateByBo(bo));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 删除设备
*/
@Log(title = "设备信息", businessType = BusinessType.DELETE)
@DeleteMapping("/deleteDevice/{ids}")
public R<Void> removeDevice(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(appDeviceService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 排程关联设备查询
* @param
* @return
*/
@GetMapping("/scheduleDeviceList")
public List<AppDeviceVo> scheduleDeviceList(AppDeviceBo appDeviceBo, AppScheduleBo appScheduleBo) {
List<AppDeviceVo> appDeviceVos = appDeviceService.queryList(appDeviceBo);
List<AppDeviceVo> AppDeviceVoList = new ArrayList();
for (AppDeviceVo appDeviceVo:appDeviceVos){
//查询设备日程冲突
List list = appScheduleServiceimpl.checkConflict(appDeviceVo.getId(), appScheduleBo);
if (list.size()==0){
AppDeviceVoList.add(appDeviceVo);
}
}
return AppDeviceVoList;
}
/**
* 新增排程
*
*/
@SaCheckPermission("app:schedule:add")
@Log(title = "日程排列", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/addschedule")
public R<Void> addSchedule(@Validated(AddGroup.class) @RequestBody AppScheduleBo bo) {
try {
return toAjax(appScheduleService.insertByBo(bo));
} catch (RuntimeException e) {
throw new RuntimeException(e);
}
}
/**
* 排程詳情
* @param
* @param
* @return
*/
@GetMapping("/schedule/{id}")
public R<AppScheduleVo> getScheduleInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
AppScheduleVo appScheduleVo = appScheduleService.queryById(id);
List<AppScheduleDetailVo> list = appScheduleDetailService.queryByScheduleId(appScheduleVo.getId());
appScheduleVo.setDetails(list);
return R.ok(appScheduleVo);
}
/**
* 修改日程排列
*/
@SaCheckPermission("app:schedule:edit")
@Log(title = "日程排列", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/updataschedule")
public R<Void> editSchedule(@Validated(EditGroup.class) @RequestBody AppScheduleBo bo) {
List list = appScheduleService.updateByBo(bo);
if (list.size()==0){
return R.ok();
}else {
return R.fail(list.toString());
}
}
/**
* 删除日程排列
*
* @param ids 主键串
*/
@SaCheckPermission("app:schedule:remove")
@Log(title = "日程排列", businessType = BusinessType.DELETE)
@DeleteMapping("/deleteschedule/{ids}")
public R<Void> removeSchedule(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(appScheduleService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 获取用户信息
*
* @return 用户信息
*/
@GetMapping("/getUserInfo")
public R<UserInfoVo> getUserInfo() {
UserInfoVo userInfoVo = new UserInfoVo();
LoginUser loginUser = LoginHelper.getLoginUser();
SysUserVo user = DataPermissionHelper.ignore(() -> userService.selectUserById(loginUser.getUserId()));
if (ObjectUtil.isNull(user)) {
return R.fail("没有权限访问用户数据!");
}
userInfoVo.setUser(user);
userInfoVo.setPermissions(loginUser.getMenuPermission());
userInfoVo.setRoles(loginUser.getRolePermission());
return R.ok(userInfoVo);
}
/**
* 修改用户
*/
// @SaCheckPermission("system:user:edit")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/updataUser")
public R<Void> editUser( @RequestBody SysUserBo user) {
userService.checkUserAllowed(user.getUserId());
userService.checkUserDataScope(user.getUserId());
if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
}
return toAjax(userService.updateAppUser(user));
}
/**
* 修改登录密码
*/
@RepeatSubmit()
@PutMapping("/updataPassword")
public R<Void> updataPassword(@RequestBody SysUserVo vo) {
Long userId = LoginHelper.getUserId();
SysUserVo sysUserVo = userService.selectUserById(userId);
if (!BCrypt.checkpw(vo.getOldPassword(), sysUserVo.getPassword())){
throw new UserException("user.password.not.match");
}
SysUserBo userBo = new SysUserBo();
userBo.setUserId(userId);
userBo.setPassword(vo.getPassword());
return toAjax(userService.updateUserPas(userBo));
}
/**
* app用户手机号/邮箱找回忘记密码
*/
@ApiEncrypt
@PostMapping("/retrievePassword")
public R<Void> forgot(@RequestBody String body) {
SysUserBo bo = JsonUtils.parseObject(body, SysUserBo.class);
bo.setUserId(LoginHelper.getUserId());
if(Validator.isEmail(bo.getUserName())){
boolean checkPhoneFlag = userService.checkEmailUnique(bo);
if (checkPhoneFlag){
throw new UserException("user.email.not.username");
}
}else if (Validator.isMobile(bo.getUserName())){
boolean checkPhoneFlag = userService.checkPhoneUnique(bo);
if (checkPhoneFlag){
throw new UserException("user.mobile.phone.number.not.username");
}
}
return toAjax(userService.updateUserPas(bo));
}
}

View File

@@ -1,69 +0,0 @@
package org.dromara.demo.controller;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.mail.utils.MailUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
import java.util.Arrays;
/**
* 邮件发送案例
*
* @author Michelle.Chung
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/mail")
public class MailSendController {
/**
* 发送邮件
*
* @param to 接收人
* @param subject 标题
* @param text 内容
*/
@GetMapping("/sendSimpleMessage")
public R<Void> sendSimpleMessage(String to, String subject, String text) {
MailUtils.sendText(to, subject, text);
return R.ok();
}
/**
* 发送邮件(带附件)
*
* @param to 接收人
* @param subject 标题
* @param text 内容
*/
@GetMapping("/sendMessageWithAttachment")
public R<Void> sendMessageWithAttachment(String to, String subject, String text) {
// 附件路径 禁止前端传递 有任意读取系统文件风险
MailUtils.sendText(to, subject, text, new File("/xxx/xxx"));
return R.ok();
}
/**
* 发送邮件(多附件)
*
* @param to 接收人
* @param subject 标题
* @param text 内容
*/
@GetMapping("/sendMessageWithAttachments")
public R<Void> sendMessageWithAttachments(String to, String subject, String text) {
// 附件路径 禁止前端传递 有任意读取系统文件风险
String[] paths = new String[]{"/xxx/xxx", "/xxx/xxx"};
File[] array = Arrays.stream(paths).map(File::new).toArray(File[]::new);
MailUtils.sendText(to, subject, text, array);
return R.ok();
}
}

View File

@@ -1,92 +0,0 @@
package org.dromara.demo.controller;
import cn.hutool.core.thread.ThreadUtil;
import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.domain.R;
import org.dromara.common.redis.utils.RedisUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Duration;
/**
* spring-cache 演示案例
*
* @author Lion Li
*/
// 类级别 缓存统一配置
//@CacheConfig(cacheNames = CacheNames.DEMO_CACHE)
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/cache")
public class RedisCacheController {
/**
* 测试 @Cacheable
* <p>
* 表示这个方法有了缓存的功能,方法的返回值会被缓存下来
* 下一次调用该方法前,会去检查是否缓存中已经有值
* 如果有就直接返回,不调用方法
* 如果没有,就调用方法,然后把结果缓存起来
* 这个注解「一般用在查询方法上」
* <p>
* 重点说明: 缓存注解严谨与其他筛选数据功能一起使用
* 例如: 数据权限注解 会造成 缓存击穿 与 数据不一致问题
* <p>
* cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数
*/
@Cacheable(cacheNames = "demo:cache#60s#10m#20#1", key = "#key", condition = "#key != null")
@GetMapping("/test1")
public R<String> test1(String key, String value) {
return R.ok("操作成功", value);
}
/**
* 测试 @CachePut
* <p>
* 加了@CachePut注解的方法,会把方法的返回值put到缓存里面缓存起来,供其它地方使用
* 它「通常用在新增或者实时更新方法上」
* <p>
* cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数
*/
@CachePut(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null")
@GetMapping("/test2")
public R<String> test2(String key, String value) {
return R.ok("操作成功", value);
}
/**
* 测试 @CacheEvict
* <p>
* 使用了CacheEvict注解的方法,会清空指定缓存
* 「一般用在删除的方法上」
* <p>
* cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数
*/
@CacheEvict(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null")
@GetMapping("/test3")
public R<String> test3(String key, String value) {
return R.ok("操作成功", value);
}
/**
* 测试设置过期时间
* 手动设置过期时间10秒
* 11秒后获取 判断是否相等
*/
@GetMapping("/test6")
public R<Boolean> test6(String key, String value) {
RedisUtils.setCacheObject(key, value);
boolean flag = RedisUtils.expire(key, Duration.ofSeconds(10));
System.out.println("***********" + flag);
ThreadUtil.sleep(11 * 1000);
Object obj = RedisUtils.getCacheObject(key);
return R.ok(value.equals(obj));
}
}

View File

@@ -1,64 +0,0 @@
package org.dromara.demo.controller;
import cn.hutool.core.thread.ThreadUtil;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.lock.executor.RedissonLockExecutor;
import org.dromara.common.core.domain.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalTime;
/**
* 测试分布式锁的样例
*
* @author shenxinquan
*/
@Slf4j
@RestController
@RequestMapping("/demo/redisLock")
public class RedisLockController {
@Autowired
private LockTemplate lockTemplate;
/**
* 测试lock4j 注解
*/
@Lock4j(keys = {"#key"})
@GetMapping("/testLock4j")
public R<String> testLock4j(String key, String value) {
System.out.println("start:" + key + ",time:" + LocalTime.now());
ThreadUtil.sleep(10000);
System.out.println("end :" + key + ",time:" + LocalTime.now());
return R.ok("操作成功", value);
}
/**
* 测试lock4j 工具
*/
@GetMapping("/testLock4jLockTemplate")
public R<String> testLock4jLockTemplate(String key, String value) {
final LockInfo lockInfo = lockTemplate.lock(key, 30000L, 5000L, RedissonLockExecutor.class);
if (null == lockInfo) {
throw new RuntimeException("业务处理中,请稍后再试");
}
// 获取锁成功,处理业务
try {
ThreadUtil.sleep(8000);
System.out.println("执行简单方法1 , 当前线程:" + Thread.currentThread().getName());
} finally {
//释放锁
lockTemplate.releaseLock(lockInfo);
}
//结束
return R.ok("操作成功", value);
}
}

View File

@@ -1,47 +0,0 @@
package org.dromara.demo.controller;
import org.dromara.common.core.domain.R;
import org.dromara.common.redis.utils.RedisUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Redis 发布订阅 演示案例
*
* @author Lion Li
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/redis/pubsub")
public class RedisPubSubController {
/**
* 发布消息
*
* @param key 通道Key
* @param value 发送内容
*/
@GetMapping("/pub")
public R<Void> pub(String key, String value) {
RedisUtils.publish(key, value, consumer -> {
System.out.println("发布通道 => " + key + ", 发送值 => " + value);
});
return R.ok("操作成功");
}
/**
* 订阅消息
*
* @param key 通道Key
*/
@GetMapping("/sub")
public R<Void> sub(String key) {
RedisUtils.subscribe(key, String.class, msg -> {
System.out.println("订阅通道 => " + key + ", 接收值 => " + msg);
});
return R.ok("操作成功");
}
}

View File

@@ -1,64 +0,0 @@
package org.dromara.demo.controller;
import org.dromara.common.core.domain.R;
import org.dromara.common.ratelimiter.annotation.RateLimiter;
import org.dromara.common.ratelimiter.enums.LimitType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 测试分布式限流样例
*
* @author Lion Li
*/
@Slf4j
@RestController
@RequestMapping("/demo/rateLimiter")
public class RedisRateLimiterController {
/**
* 测试全局限流
* 全局影响
*/
@RateLimiter(count = 2, time = 10)
@GetMapping("/test")
public R<String> test(String value) {
return R.ok("操作成功", value);
}
/**
* 测试请求IP限流
* 同一IP请求受影响
*/
@RateLimiter(count = 2, time = 10, limitType = LimitType.IP)
@GetMapping("/testip")
public R<String> testip(String value) {
return R.ok("操作成功", value);
}
/**
* 测试集群实例限流
* 启动两个后端服务互不影响
*/
@RateLimiter(count = 2, time = 10, limitType = LimitType.CLUSTER)
@GetMapping("/testcluster")
public R<String> testcluster(String value) {
return R.ok("操作成功", value);
}
/**
* 测试请求IP限流(key基于参数获取)
* 同一IP请求受影响
*
* 简单变量获取 #变量 复杂表达式 #{#变量 != 1 ? 1 : 0}
*/
@RateLimiter(count = 2, time = 10, limitType = LimitType.IP, key = "#value")
@GetMapping("/testObj")
public R<String> testObj(String value) {
return R.ok("操作成功", value);
}
}

View File

@@ -1,198 +0,0 @@
package org.dromara.demo.controller;
import cn.dev33.satoken.annotation.*;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* SaToken 权限测试 接口文档输出测试
*
* @author AprilWind
*/
@Slf4j
@RestController
@RequestMapping("/demo/saTokenDoc")
public class SaTokenTestController {
// ====================== 基础场景:单一校验规则 ======================
/**
* 场景1仅登录校验无角色/权限限制,只需登录态)
*/
@SaCheckLogin
@GetMapping("/basic/loginOnly")
public R<Void> loginOnly() {
log.info("【场景1】仅登录校验通过");
return R.ok("仅登录校验通过,无需角色/权限");
}
/**
* 场景2单一角色校验AND模式默认
*/
@SaCheckRole("admin")
@GetMapping("/basic/singleRole")
public R<Void> singleRole() {
log.info("【场景2】单一角色(admin)校验通过");
return R.ok("拥有admin角色校验通过");
}
/**
* 场景3单一权限校验AND模式默认
*/
@SaCheckPermission("system:user:view")
@GetMapping("/basic/singlePermission")
public R<Void> singlePermission() {
log.info("【场景3】单一权限(system:user:view)校验通过");
return R.ok("拥有system:user:view权限校验通过");
}
/**
* 场景4忽略所有权限校验SaIgnore优先级最高
*/
@SaIgnore
@SaCheckRole("none_exist") // 该注解会被忽略
@GetMapping("/basic/ignoreAll")
public R<Void> ignoreAll() {
log.info("【场景4】SaIgnore忽略所有权限校验");
return R.ok("SaIgnore生效所有权限校验被忽略");
}
// ====================== 进阶场景多条件组合AND/OR ======================
/**
* 场景5多角色AND模式必须同时拥有所有角色
*/
@SaCheckRole(value = {"admin", "operator"}, mode = SaMode.AND)
@GetMapping("/advance/multiRoleAnd")
public R<Void> multiRoleAnd() {
log.info("【场景5】多角色AND模式(admin+operator)校验通过");
return R.ok("同时拥有admin和operator角色校验通过");
}
/**
* 场景6多角色OR模式拥有任一角色即可
*/
@SaCheckRole(value = {"admin", "test"}, mode = SaMode.OR)
@GetMapping("/advance/multiRoleOr")
public R<Void> multiRoleOr() {
log.info("【场景6】多角色OR模式(admin|test)校验通过");
return R.ok("拥有admin或test角色校验通过");
}
/**
* 场景7多权限AND模式必须同时拥有所有权限
*/
@SaCheckPermission(value = {"system:user:edit", "system:log:view"}, mode = SaMode.AND)
@GetMapping("/advance/multiPermAnd")
public R<Void> multiPermAnd() {
log.info("【场景7】多权限AND模式(system:user:edit+system:log:view)校验通过");
return R.ok("同时拥有system:user:edit和system:log:view权限校验通过");
}
/**
* 场景8多权限OR模式拥有任一权限即可
*/
@SaCheckPermission(value = {"system:user:add", "system:user:delete"}, mode = SaMode.OR)
@GetMapping("/advance/multiPermOr")
public R<Void> multiPermOr() {
log.info("【场景8】多权限OR模式(system:user:add|system:user:delete)校验通过");
return R.ok("拥有system:user:add或system:user:delete权限校验通过");
}
// ====================== 高级场景:通配符/混合组合 ======================
/**
* 场景9权限通配符匹配前缀匹配
* 拥有system:user:* 即可匹配所有用户模块权限
*/
@SaCheckPermission("system:user:*")
@GetMapping("/advanced/permWildcardPrefix")
public R<Void> permWildcardPrefix() {
log.info("【场景9】权限通配符(system:user:*)校验通过");
return R.ok("拥有system:user:*前缀权限,校验通过");
}
/**
* 场景10角色通配符匹配前缀匹配
* 拥有admin_* 即可匹配所有admin开头的角色
*/
@SaCheckRole("admin_*")
@GetMapping("/advanced/roleWildcardPrefix")
public R<Void> roleWildcardPrefix() {
log.info("【场景10】角色通配符(admin_*)校验通过");
return R.ok("拥有admin_*前缀角色,校验通过");
}
/**
* 场景11权限+角色混合AND模式所有条件必须满足
* 需同时满足拥有admin角色 + 拥有system:user:all权限
*/
@SaCheckRole("admin")
@SaCheckPermission("system:user:all")
@GetMapping("/advanced/mixRolePermAnd")
public R<Void> mixRolePermAnd() {
log.info("【场景11】角色+权限混合AND(admin+system:user:all)校验通过");
return R.ok("拥有admin角色且拥有system:user:all权限校验通过");
}
/**
* 场景12权限+角色混合OR模式任一条件满足即可
* 满足任一拥有super_admin角色 | 拥有system:manage权限
*/
@SaCheckRole(value = {"super_admin"}, mode = SaMode.OR)
@SaCheckPermission(value = {"system:manage"}, mode = SaMode.OR)
@GetMapping("/advanced/mixRolePermOr")
public R<Void> mixRolePermOr() {
log.info("【场景12】角色+权限混合OR(super_admin|system:manage)校验通过");
return R.ok("拥有super_admin角色或system:manage权限校验通过");
}
/**
* 场景13orRole参数权限校验失败时兜底角色校验
* 核心逻辑无system:user:export权限时检查是否有admin/operator角色
*/
@SaCheckPermission(value = "system:user:export", orRole = {"admin", "operator"})
@GetMapping("/advanced/permWithOrRole")
public R<Void> permWithOrRole() {
log.info("【场景13】权限+orRole兜底校验通过");
return R.ok("拥有system:user:export权限或拥有admin/operator角色校验通过");
}
// ====================== 特殊场景:临时权限/注解覆盖 ======================
/**
* 场景14SaIgnore局部覆盖方法注解覆盖类注解若有
* 假设类上有@SaCheckLogin方法上@SaIgnore会覆盖
*/
@SaIgnore
@GetMapping("/special/ignoreOverride")
public R<Void> ignoreOverride() {
log.info("【场景14】SaIgnore覆盖类级别权限注解");
return R.ok("方法级SaIgnore覆盖类级别权限校验");
}
/**
* 场景15临时权限校验SaCheckPermission逻辑临时权限>永久权限)
* 注临时权限需通过SaToken API手动设置如 SaHolder.getStpLogic().setTempPermission("system:temp:test")
*/
@SaCheckPermission("system:temp:test")
@GetMapping("/special/tempPermission")
public R<Void> tempPermission() {
log.info("【场景15】临时权限(system:temp:test)校验通过");
return R.ok("临时权限校验通过需先通过API设置临时权限");
}
/**
* 场景16登录类型指定多端登录场景如PC/APP/小程序)
* 注需配合SaToken多账号体系配置
*/
@SaCheckLogin(type = "PC") // 仅校验PC端的登录态
@GetMapping("/special/loginTypeSpecify")
public R<Void> loginTypeSpecify() {
log.info("【场景16】指定登录类型(PC)校验通过");
return R.ok("仅PC端登录态校验通过");
}
}

View File

@@ -1,82 +0,0 @@
package org.dromara.demo.controller;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.LinkedHashMap;
/**
* 短信演示案例
* 请先阅读文档 否则无法使用
*
* @author Lion Li
* @version 4.2.0
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/sms")
public class SmsController {
/**
* 发送短信Aliyun
*
* @param phones 电话号
* @param templateId 模板ID
*/
@GetMapping("/sendAliyun")
public R<Object> sendAliyun(String phones, String templateId) {
LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put("code", "1234");
SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
SmsResponse smsResponse = smsBlend.sendMessage(phones, templateId, map);
return R.ok(smsResponse);
}
/**
* 发送短信Tencent
*
* @param phones 电话号
* @param templateId 模板ID
*/
@GetMapping("/sendTencent")
public R<Object> sendTencent(String phones, String templateId) {
LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
// map.put("2", "测试测试");
map.put("1", "1234");
SmsBlend smsBlend = SmsFactory.getSmsBlend("config2");
SmsResponse smsResponse = smsBlend.sendMessage(phones, templateId, map);
return R.ok(smsResponse);
}
/**
* 添加黑名单
*
* @param phone 手机号
*/
@GetMapping("/addBlacklist")
public R<Object> addBlacklist(String phone){
SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
smsBlend.joinInBlacklist(phone);
return R.ok();
}
/**
* 移除黑名单
*
* @param phone 手机号
*/
@GetMapping("/removeBlacklist")
public R<Object> removeBlacklist(String phone){
SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
smsBlend.removeFromBlacklist(phone);
return R.ok();
}
}

View File

@@ -1,31 +0,0 @@
package org.dromara.demo.controller;
import org.dromara.common.core.domain.R;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* swagger3 用法示例
*
* @author Lion Li
*/
@RestController
@RequestMapping("/swagger/demo")
public class Swagger3DemoController {
/**
* 上传请求
* 必须使用 @RequestPart 注解标注为文件
*
* @param file 文件
*/
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<String> upload(@RequestPart("file") MultipartFile file) {
return R.ok("操作成功", file.getOriginalFilename());
}
}

View File

@@ -1,90 +0,0 @@
package org.dromara.demo.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.dromara.common.core.domain.R;
import org.dromara.common.web.core.BaseController;
import org.dromara.demo.domain.TestDemo;
import org.dromara.demo.mapper.TestDemoMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* 测试批量方法
*
* @author Lion Li
* @date 2021-05-30
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/batch")
public class TestBatchController extends BaseController {
/**
* 为了便于测试 直接引入mapper
*/
private final TestDemoMapper testDemoMapper;
/**
* 新增批量方法 可完美替代 saveBatch 秒级插入上万数据 (对mysql负荷较大)
* <p>
* 3.5.0 版本 增加 rewriteBatchedStatements=true 批处理参数 使 MP 原生批处理可以达到同样的速度
*/
@PostMapping("/add")
// @DS("slave")
public R<Void> add() {
List<TestDemo> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
TestDemo testDemo = new TestDemo();
testDemo.setOrderNum(-1);
testDemo.setTestKey("批量新增");
testDemo.setValue("测试新增");
list.add(testDemo);
}
return toAjax(testDemoMapper.insertBatch(list));
}
/**
* 新增或更新 可完美替代 saveOrUpdateBatch 高性能
* <p>
* 3.5.0 版本 增加 rewriteBatchedStatements=true 批处理参数 使 MP 原生批处理可以达到同样的速度
*/
@PostMapping("/addOrUpdate")
// @DS("slave")
public R<Void> addOrUpdate() {
List<TestDemo> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
TestDemo testDemo = new TestDemo();
testDemo.setOrderNum(-1);
testDemo.setTestKey("批量新增");
testDemo.setValue("测试新增");
list.add(testDemo);
}
testDemoMapper.insertBatch(list);
for (int i = 0; i < list.size(); i++) {
TestDemo testDemo = list.get(i);
testDemo.setTestKey("批量新增或修改");
testDemo.setValue("批量新增或修改");
if (i % 2 == 0) {
testDemo.setId(null);
}
}
return toAjax(testDemoMapper.insertOrUpdateBatch(list));
}
/**
* 删除批量方法
*/
@DeleteMapping()
// @DS("slave")
public R<Void> remove() {
return toAjax(testDemoMapper.delete(new LambdaQueryWrapper<TestDemo>()
.eq(TestDemo::getOrderNum, -1L)));
}
}

View File

@@ -1,147 +0,0 @@
package org.dromara.demo.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.ValidatorUtils;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.core.validate.QueryGroup;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.excel.core.ExcelResult;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.demo.domain.TestDemo;
import org.dromara.demo.domain.bo.TestDemoBo;
import org.dromara.demo.domain.vo.TestDemoImportVo;
import org.dromara.demo.domain.vo.TestDemoVo;
import org.dromara.demo.service.ITestDemoService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* 测试单表Controller
*
* @author Lion Li
* @date 2021-07-26
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/demo")
public class TestDemoController extends BaseController {
private final ITestDemoService testDemoService;
/**
* 查询测试单表列表
*/
@SaCheckPermission("demo:demo:list")
@GetMapping("/list")
public TableDataInfo<TestDemoVo> list(@Validated(QueryGroup.class) TestDemoBo bo, PageQuery pageQuery) {
return testDemoService.queryPageList(bo, pageQuery);
}
/**
* 自定义分页查询
*/
@SaCheckPermission("demo:demo:list")
@GetMapping("/page")
public TableDataInfo<TestDemoVo> page(@Validated(QueryGroup.class) TestDemoBo bo, PageQuery pageQuery) {
return testDemoService.customPageList(bo, pageQuery);
}
/**
* 导入数据
*
* @param file 导入文件
*/
@Log(title = "测试单表", businessType = BusinessType.IMPORT)
@SaCheckPermission("demo:demo:import")
@PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<Void> importData(@RequestPart("file") MultipartFile file) throws Exception {
ExcelResult<TestDemoImportVo> excelResult = ExcelUtil.importExcel(file.getInputStream(), TestDemoImportVo.class, true);
List<TestDemo> list = MapstructUtils.convert(excelResult.getList(), TestDemo.class);
testDemoService.saveBatch(list);
return R.ok(excelResult.getAnalysis());
}
/**
* 导出测试单表列表
*/
@SaCheckPermission("demo:demo:export")
@Log(title = "测试单表", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(@Validated TestDemoBo bo, HttpServletResponse response) {
List<TestDemoVo> list = testDemoService.queryList(bo);
// 测试雪花id导出
// for (TestDemoVo vo : list) {
// vo.setId(1234567891234567893L);
// }
ExcelUtil.exportExcel(list, "测试单表", TestDemoVo.class, response);
}
/**
* 获取测试单表详细信息
*
* @param id 测试ID
*/
@SaCheckPermission("demo:demo:query")
@GetMapping("/{id}")
public R<TestDemoVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("id") Long id) {
return R.ok(testDemoService.queryById(id));
}
/**
* 新增测试单表
*/
@SaCheckPermission("demo:demo:add")
@Log(title = "测试单表", businessType = BusinessType.INSERT)
@RepeatSubmit(interval = 2, timeUnit = TimeUnit.SECONDS, message = "{repeat.submit.message}")
@PostMapping()
public R<Void> add(@RequestBody TestDemoBo bo) {
// 使用校验工具对标 @Validated(AddGroup.class) 注解
// 用于在非 Controller 的地方校验对象
ValidatorUtils.validate(bo, AddGroup.class);
return toAjax(testDemoService.insertByBo(bo));
}
/**
* 修改测试单表
*/
@SaCheckPermission("demo:demo:edit")
@Log(title = "测试单表", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestDemoBo bo) {
return toAjax(testDemoService.updateByBo(bo));
}
/**
* 删除测试单表
*
* @param ids 测试ID串
*/
@SaCheckPermission("demo:demo:remove")
@Log(title = "测试单表", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(testDemoService.deleteWithValidByIds(Arrays.asList(ids), true));
}
}

View File

@@ -1,55 +0,0 @@
package org.dromara.demo.controller;
import org.dromara.common.core.domain.R;
import org.dromara.demo.domain.TestDemoEncrypt;
import org.dromara.demo.mapper.TestDemoEncryptMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* 测试数据库加解密功能
*
* @author Lion Li
*/
@Validated
@RestController
@RequestMapping("/demo/encrypt")
public class TestEncryptController {
@Autowired
private TestDemoEncryptMapper mapper;
@Value("${mybatis-encryptor.enable}")
private Boolean encryptEnable;
/**
* 测试数据库加解密
*
* @param key 测试key
* @param value 测试value
*/
@GetMapping()
public R<Map<String, TestDemoEncrypt>> test(String key, String value) {
if (!encryptEnable) {
throw new RuntimeException("加密功能未开启!");
}
Map<String, TestDemoEncrypt> map = new HashMap<>(2);
TestDemoEncrypt demo = new TestDemoEncrypt();
demo.setTestKey(key);
demo.setValue(value);
mapper.insert(demo);
map.put("加密", demo);
TestDemoEncrypt testDemo = mapper.selectById(demo.getId());
map.put("解密", testDemo);
return R.ok(map);
}
}

View File

@@ -1,172 +0,0 @@
package org.dromara.demo.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.collection.CollUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.dromara.common.excel.core.ExcelResult;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.demo.domain.vo.ExportDemoVo;
import org.dromara.demo.listener.ExportDemoListener;
import org.dromara.demo.service.IExportExcelService;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 测试Excel功能
*
* @author Lion Li
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/excel")
public class TestExcelController {
private final IExportExcelService exportExcelService;
/**
* 单列表多数据
*/
@GetMapping("/exportTemplateOne")
public void exportTemplateOne(HttpServletResponse response) {
Map<String, String> map = new HashMap<>();
map.put("title", "单列表多数据");
map.put("test1", "数据测试1");
map.put("test2", "数据测试2");
map.put("test3", "数据测试3");
map.put("test4", "数据测试4");
map.put("testTest", "666");
List<TestObj> list = new ArrayList<>();
list.add(new TestObj("单列表测试1", "列表测试1", "列表测试2", "列表测试3", "列表测试4"));
list.add(new TestObj("单列表测试2", "列表测试5", "列表测试6", "列表测试7", "列表测试8"));
list.add(new TestObj("单列表测试3", "列表测试9", "列表测试10", "列表测试11", "列表测试12"));
ExcelUtil.exportTemplate(CollUtil.newArrayList(map, list), "单列表.xlsx", "excel/单列表.xlsx", response);
}
/**
* 多列表多数据
*/
@GetMapping("/exportTemplateMuliti")
public void exportTemplateMuliti(HttpServletResponse response) {
Map<String, String> map = new HashMap<>();
map.put("title1", "标题1");
map.put("title2", "标题2");
map.put("title3", "标题3");
map.put("title4", "标题4");
map.put("author", "Lion Li");
List<TestObj1> list1 = new ArrayList<>();
list1.add(new TestObj1("list1测试1", "list1测试2", "list1测试3"));
list1.add(new TestObj1("list1测试4", "list1测试5", "list1测试6"));
list1.add(new TestObj1("list1测试7", "list1测试8", "list1测试9"));
List<TestObj1> list2 = new ArrayList<>();
list2.add(new TestObj1("list2测试1", "list2测试2", "list2测试3"));
list2.add(new TestObj1("list2测试4", "list2测试5", "list2测试6"));
List<TestObj1> list3 = new ArrayList<>();
list3.add(new TestObj1("list3测试1", "list3测试2", "list3测试3"));
List<TestObj1> list4 = new ArrayList<>();
list4.add(new TestObj1("list4测试1", "list4测试2", "list4测试3"));
list4.add(new TestObj1("list4测试4", "list4测试5", "list4测试6"));
list4.add(new TestObj1("list4测试7", "list4测试8", "list4测试9"));
list4.add(new TestObj1("list4测试10", "list4测试11", "list4测试12"));
Map<String, Object> multiListMap = new HashMap<>();
multiListMap.put("map", map);
multiListMap.put("data1", list1);
multiListMap.put("data2", list2);
multiListMap.put("data3", list3);
multiListMap.put("data4", list4);
ExcelUtil.exportTemplateMultiList(multiListMap, "多列表.xlsx", "excel/多列表.xlsx", response);
}
/**
* 导出下拉框
*
* @param response /
*/
@GetMapping("/exportWithOptions")
public void exportWithOptions(HttpServletResponse response) {
exportExcelService.exportWithOptions(response);
}
/**
* 自定义导出
*
* @param response /
*/
@GetMapping("/customExport")
public void customExport(HttpServletResponse response) throws IOException {
exportExcelService.customExport(response);
}
/**
* 多个sheet导出
*/
@GetMapping("/exportTemplateMultiSheet")
public void exportTemplateMultiSheet(HttpServletResponse response) {
List<TestObj1> list1 = new ArrayList<>();
list1.add(new TestObj1("list1测试1", "list1测试2", "list1测试3"));
list1.add(new TestObj1("list1测试4", "list1测试5", "list1测试6"));
List<TestObj1> list2 = new ArrayList<>();
list2.add(new TestObj1("list2测试1", "list2测试2", "list2测试3"));
list2.add(new TestObj1("list2测试4", "list2测试5", "list2测试6"));
List<TestObj1> list3 = new ArrayList<>();
list3.add(new TestObj1("list3测试1", "list3测试2", "list3测试3"));
list3.add(new TestObj1("list3测试4", "list3测试5", "list3测试6"));
List<TestObj1> list4 = new ArrayList<>();
list4.add(new TestObj1("list4测试1", "list4测试2", "list4测试3"));
list4.add(new TestObj1("list4测试4", "list4测试5", "list4测试6"));
List<Map<String, Object>> list = new ArrayList<>();
Map<String, Object> sheetMap1 = new HashMap<>();
sheetMap1.put("data1", list1);
Map<String, Object> sheetMap2 = new HashMap<>();
sheetMap2.put("data2", list2);
Map<String, Object> sheetMap3 = new HashMap<>();
sheetMap3.put("data3", list3);
Map<String, Object> sheetMap4 = new HashMap<>();
sheetMap4.put("data4", list4);
list.add(sheetMap1);
list.add(sheetMap2);
list.add(sheetMap3);
list.add(sheetMap4);
ExcelUtil.exportTemplateMultiSheet(list, "多sheet列表", "excel/多sheet列表.xlsx", response);
}
/**
* 导入表格
*/
@PostMapping(value = "/importWithOptions", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public List<ExportDemoVo> importWithOptions(@RequestPart("file") MultipartFile file) throws Exception {
// 处理解析结果
ExcelResult<ExportDemoVo> excelResult = ExcelUtil.importExcel(file.getInputStream(), ExportDemoVo.class, new ExportDemoListener());
return excelResult.getList();
}
@Data
@AllArgsConstructor
static class TestObj1 {
private String test1;
private String test2;
private String test3;
}
@Data
@AllArgsConstructor
static class TestObj {
private String name;
private String list1;
private String list2;
private String list3;
private String list4;
}
}

View File

@@ -1,71 +0,0 @@
package org.dromara.demo.controller;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.MessageUtils;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
/**
* 测试国际化
*
* @author Lion Li
*/
@Validated
@RestController
@RequestMapping("/demo/i18n")
public class TestI18nController {
/**
* 通过code获取国际化内容
* code为 messages.properties 中的 key
* <p>
* 测试使用 user.register.success
*
* @param code 国际化code
*/
@GetMapping()
public R<Void> get(String code) {
return R.ok(MessageUtils.message(code));
}
/**
* Validator 校验国际化
* 不传值 分别查看异常返回
* <p>
* 测试使用 not.null
*/
@GetMapping("/test1")
public R<Void> test1(@NotBlank(message = "{not.null}") String str) {
return R.ok(str);
}
/**
* Bean 校验国际化
* 不传值 分别查看异常返回
* <p>
* 测试使用 not.null
*/
@GetMapping("/test2")
public R<TestI18nBo> test2(@Validated TestI18nBo bo) {
return R.ok(bo);
}
@Data
public static class TestI18nBo {
@NotBlank(message = "{not.null}")
private String name;
@NotNull(message = "{not.null}")
@Range(min = 0, max = 100, message = "{length.not.valid}")
private Integer age;
}
}

View File

@@ -1,76 +0,0 @@
package org.dromara.demo.controller;
import org.dromara.common.core.domain.R;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.sensitive.annotation.Sensitive;
import org.dromara.common.sensitive.core.SensitiveStrategy;
import lombok.Data;
import org.dromara.common.sensitive.core.SensitiveService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 测试数据脱敏控制器
* <p>
* 默认管理员不过滤
* 需自行根据业务重写实现
*
* @author Lion Li
* @version 3.6.0
* @see SensitiveService
*/
@RestController
@RequestMapping("/demo/sensitive")
public class TestSensitiveController extends BaseController {
/**
* 测试数据脱敏
*/
@GetMapping("/test")
public R<TestSensitive> test() {
TestSensitive testSensitive = new TestSensitive();
testSensitive.setIdCard("210397198608215431");
testSensitive.setPhone("17640125371");
testSensitive.setAddress("北京市朝阳区某某四合院1203室");
testSensitive.setEmail("17640125371@163.com");
testSensitive.setBankCard("6226456952351452853");
return R.ok(testSensitive);
}
@Data
static class TestSensitive {
/**
* 身份证
*/
@Sensitive(strategy = SensitiveStrategy.ID_CARD)
private String idCard;
/**
* 电话
*/
@Sensitive(strategy = SensitiveStrategy.PHONE, roleKey = "common")
private String phone;
/**
* 地址
*/
@Sensitive(strategy = SensitiveStrategy.ADDRESS, perms = "system:user:query")
private String address;
/**
* 邮箱
*/
@Sensitive(strategy = SensitiveStrategy.EMAIL, roleKey = "common", perms = "system:user:query1")
private String email;
/**
* 银行卡
*/
@Sensitive(strategy = SensitiveStrategy.BANK_CARD, roleKey = "common1", perms = "system:user:query")
private String bankCard;
}
}

View File

@@ -1,107 +0,0 @@
package org.dromara.demo.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.core.validate.QueryGroup;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.demo.domain.bo.TestTreeBo;
import org.dromara.demo.domain.vo.TestTreeVo;
import org.dromara.demo.service.ITestTreeService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
/**
* 测试树表Controller
*
* @author Lion Li
* @date 2021-07-26
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/tree")
public class TestTreeController extends BaseController {
private final ITestTreeService testTreeService;
/**
* 查询测试树表列表
*/
@SaCheckPermission("demo:tree:list")
@GetMapping("/list")
public R<List<TestTreeVo>> list(@Validated(QueryGroup.class) TestTreeBo bo) {
List<TestTreeVo> list = testTreeService.queryList(bo);
return R.ok(list);
}
/**
* 导出测试树表列表
*/
@SaCheckPermission("demo:tree:export")
@Log(title = "测试树表", businessType = BusinessType.EXPORT)
@GetMapping("/export")
public void export(@Validated TestTreeBo bo, HttpServletResponse response) {
List<TestTreeVo> list = testTreeService.queryList(bo);
ExcelUtil.exportExcel(list, "测试树表", TestTreeVo.class, response);
}
/**
* 获取测试树表详细信息
*
* @param id 测试树ID
*/
@SaCheckPermission("demo:tree:query")
@GetMapping("/{id}")
public R<TestTreeVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("id") Long id) {
return R.ok(testTreeService.queryById(id));
}
/**
* 新增测试树表
*/
@SaCheckPermission("demo:tree:add")
@Log(title = "测试树表", businessType = BusinessType.INSERT)
@RepeatSubmit
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody TestTreeBo bo) {
return toAjax(testTreeService.insertByBo(bo));
}
/**
* 修改测试树表
*/
@SaCheckPermission("demo:tree:edit")
@Log(title = "测试树表", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestTreeBo bo) {
return toAjax(testTreeService.updateByBo(bo));
}
/**
* 删除测试树表
*
* @param ids 测试树ID串
*/
@SaCheckPermission("demo:tree:remove")
@Log(title = "测试树表", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(testTreeService.deleteWithValidByIds(Arrays.asList(ids), true));
}
}

View File

@@ -1,33 +0,0 @@
package org.dromara.demo.controller;
import org.dromara.common.core.domain.R;
import org.dromara.common.websocket.dto.WebSocketMessageDto;
import org.dromara.common.websocket.utils.WebSocketUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* WebSocket 演示案例
*
* @author zendwang
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/websocket")
@Slf4j
public class WebSocketController {
/**
* 发布消息
*
* @param dto 发送内容
*/
@GetMapping("/send")
public R<Void> send(WebSocketMessageDto dto) throws InterruptedException {
WebSocketUtils.publishMessage(dto);
return R.ok("操作成功");
}
}

View File

@@ -1 +0,0 @@
package org.dromara.demo.controller;

View File

@@ -1,92 +0,0 @@
package org.dromara.demo.controller.queue;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.redis.utils.QueueUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 有界队列 演示案例
* <p>
* 轻量级队列 重量级数据量 请使用 MQ
* <p>
* 集群测试通过 同一个数据只会被消费一次 做好事务补偿
* 集群测试流程 在其中一台发送数据 两端分别调用获取接口 一次获取一条
*
* @author Lion Li
* @version 3.6.0
* @deprecated redisson 新版本已经将队列功能标记删除 一些技术问题无法解决 建议搭建MQ使用
*/
@Deprecated
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/queue/bounded")
public class BoundedQueueController {
/**
* 添加队列数据
*
* @param queueName 队列名
* @param capacity 容量
*/
@GetMapping("/add")
public R<Void> add(String queueName, int capacity) {
// 用完了一定要销毁 否则会一直存在
boolean b = QueueUtils.destroyBoundedQueue(queueName);
log.info("通道: {} , 删除: {}", queueName, b);
// 初始化设置一次即可
if (QueueUtils.trySetBoundedQueueCapacity(queueName, capacity)) {
log.info("通道: {} , 设置容量: {}", queueName, capacity);
} else {
log.info("通道: {} , 设置容量失败", queueName);
return R.fail("操作失败");
}
for (int i = 0; i < 11; i++) {
String data = "data-" + i;
boolean flag = QueueUtils.addBoundedQueueObject(queueName, data);
if (flag == false) {
log.info("通道: {} , 发送数据: {} 失败, 通道已满", queueName, data);
} else {
log.info("通道: {} , 发送数据: {}", queueName, data);
}
}
return R.ok("操作成功");
}
/**
* 删除队列数据
*
* @param queueName 队列名
*/
@GetMapping("/remove")
public R<Void> remove(String queueName) {
String data = "data-" + 5;
if (QueueUtils.removeBoundedQueueObject(queueName, data)) {
log.info("通道: {} , 删除数据: {}", queueName, data);
} else {
return R.fail("操作失败");
}
return R.ok("操作成功");
}
/**
* 获取队列数据
*
* @param queueName 队列名
*/
@GetMapping("/get")
public R<Void> get(String queueName) {
String data;
do {
data = QueueUtils.getBoundedQueueObject(queueName);
log.info("通道: {} , 获取数据: {}", queueName, data);
} while (data != null);
return R.ok("操作成功");
}
}

View File

@@ -1,97 +0,0 @@
package org.dromara.demo.controller.queue;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.redis.utils.QueueUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
/**
* 延迟队列 演示案例
* <p>
* 轻量级队列 重量级数据量 请使用 MQ
* 例如: 创建订单30分钟后过期处理
* <p>
* 集群测试通过 同一个数据只会被消费一次 做好事务补偿
* 集群测试流程 两台集群分别开启订阅 在其中一台发送数据 观察接收消息的规律
*
* @author Lion Li
* @version 3.6.0
* @deprecated redisson 新版本已经将队列功能标记删除 一些技术问题无法解决 建议搭建MQ使用
*/
@Deprecated
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/queue/delayed")
public class DelayedQueueController {
/**
* 订阅队列
*
* @param queueName 队列名
*/
@GetMapping("/subscribe")
public R<Void> subscribe(String queueName) {
log.info("通道: {} 监听中......", queueName);
// 项目初始化设置一次即可
QueueUtils.subscribeBlockingQueue(queueName, (String orderNum) -> {
// 观察接收时间
log.info("通道: {}, 收到数据: {}", queueName, orderNum);
return CompletableFuture.runAsync(() -> {
// 异步处理数据逻辑 不要在上方处理业务逻辑
log.info("数据处理: {}", orderNum);
});
}, true);
return R.ok("操作成功");
}
/**
* 添加队列数据
*
* @param queueName 队列名
* @param orderNum 订单号
* @param time 延迟时间(秒)
*/
@GetMapping("/add")
public R<Void> add(String queueName, String orderNum, Long time) {
QueueUtils.addDelayedQueueObject(queueName, orderNum, time, TimeUnit.SECONDS);
// 观察发送时间
log.info("通道: {} , 发送数据: {}", queueName, orderNum);
return R.ok("操作成功");
}
/**
* 删除队列数据
*
* @param queueName 队列名
* @param orderNum 订单号
*/
@GetMapping("/remove")
public R<Void> remove(String queueName, String orderNum) {
if (QueueUtils.removeDelayedQueueObject(queueName, orderNum)) {
log.info("通道: {} , 删除数据: {}", queueName, orderNum);
} else {
return R.fail("操作失败");
}
return R.ok("操作成功");
}
/**
* 销毁队列
*
* @param queueName 队列名
*/
@GetMapping("/destroy")
public R<Void> destroy(String queueName) {
// 用完了一定要销毁 否则会一直存在
QueueUtils.destroyDelayedQueue(queueName);
return R.ok("操作成功");
}
}

View File

@@ -1,24 +0,0 @@
package org.dromara.demo.controller.queue;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 实体类 注意不允许使用内部类 否则会找不到类
*
* @author Lion Li
* @version 3.6.0
* @deprecated redisson 新版本已经将队列功能标记删除 一些技术问题无法解决 建议搭建MQ使用
*/
@Deprecated
@Data
@NoArgsConstructor
public class PriorityDemo implements Comparable<PriorityDemo> {
private String name;
private Integer orderNum;
@Override
public int compareTo(PriorityDemo other) {
return Integer.compare(getOrderNum(), other.getOrderNum());
}
}

View File

@@ -1,91 +0,0 @@
package org.dromara.demo.controller.queue;
import cn.hutool.core.util.RandomUtil;
import org.dromara.common.core.domain.R;
import org.dromara.common.redis.utils.QueueUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 优先队列 演示案例
* <p>
* 轻量级队列 重量级数据量 请使用 MQ
* <p>
* 集群测试通过 同一个消息只会被消费一次 做好事务补偿
* 集群测试流程 在其中一台发送数据 两端分别调用获取接口 一次获取一条
*
* @author Lion Li
* @version 3.6.0
* @deprecated redisson 新版本已经将队列功能标记删除 一些技术问题无法解决 建议搭建MQ使用
*/
@Deprecated
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/queue/priority")
public class PriorityQueueController {
/**
* 添加队列数据
*
* @param queueName 队列名
*/
@GetMapping("/add")
public R<Void> add(String queueName) {
// 用完了一定要销毁 否则会一直存在
boolean b = QueueUtils.destroyPriorityQueue(queueName);
log.info("通道: {} , 删除: {}", queueName, b);
for (int i = 0; i < 10; i++) {
int randomNum = RandomUtil.randomInt(10);
PriorityDemo data = new PriorityDemo();
data.setName("data-" + i);
data.setOrderNum(randomNum);
if (QueueUtils.addPriorityQueueObject(queueName, data)) {
log.info("通道: {} , 发送数据: {}", queueName, data);
} else {
log.info("通道: {} , 发送数据: {}, 发送失败", queueName, data);
}
}
return R.ok("操作成功");
}
/**
* 删除队列数据
*
* @param queueName 队列名
* @param name 对象名
* @param orderNum 排序号
*/
@GetMapping("/remove")
public R<Void> remove(String queueName, String name, Integer orderNum) {
PriorityDemo data = new PriorityDemo();
data.setName(name);
data.setOrderNum(orderNum);
if (QueueUtils.removePriorityQueueObject(queueName, data)) {
log.info("通道: {} , 删除数据: {}", queueName, data);
} else {
return R.fail("操作失败");
}
return R.ok("操作成功");
}
/**
* 获取队列数据
*
* @param queueName 队列名
*/
@GetMapping("/get")
public R<Void> get(String queueName) {
PriorityDemo data;
do {
data = QueueUtils.getPriorityQueueObject(queueName);
log.info("通道: {} , 获取数据: {}", queueName, data);
} while (data != null);
return R.ok("操作成功");
}
}

View File

@@ -1,68 +0,0 @@
package org.dromara.demo.domain;
import com.baomidou.mybatisplus.annotation.*;
import org.dromara.common.tenant.core.TenantEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* 测试单表对象 test_demo
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("test_demo")
public class TestDemo extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id")
private Long id;
/**
* 部门id
*/
private Long deptId;
/**
* 用户id
*/
private Long userId;
/**
* 排序号
*/
@OrderBy(asc = false, sort = 1)
private Integer orderNum;
/**
* key键
*/
private String testKey;
/**
* 值
*/
private String value;
/**
* 版本
*/
@Version
private Long version;
/**
* 删除标志
*/
@TableLogic
private Long delFlag;
}

View File

@@ -1,29 +0,0 @@
package org.dromara.demo.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import org.dromara.common.encrypt.annotation.EncryptField;
import org.dromara.common.encrypt.enumd.AlgorithmType;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("test_demo")
public class TestDemoEncrypt extends TestDemo {
/**
* key键
*/
// @EncryptField(algorithm=AlgorithmType.SM2, privateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgZSlOvw8FBiH+aFJWLYZP/VRjg9wjfRarTkGBZd/T3N+gCgYIKoEcz1UBgi2hRANCAAR5DGuQwJqkxnbCsP+iPSDoHWIF4RwcR5EsSvT8QPxO1wRkR2IhCkzvRb32x2CUgJFdvoqVqfApFDPZzShqzBwX", publicKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEeQxrkMCapMZ2wrD/oj0g6B1iBeEcHEeRLEr0/ED8TtcEZEdiIQpM70W99sdglICRXb6KlanwKRQz2c0oaswcFw==")
@EncryptField(algorithm = AlgorithmType.RSA, privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBANBBEeueWlXlkkj2+WY5l+IWe42d8b5K28g+G/CFKC/yYAEHtqGlCsBOrb+YBkG9mPzmuYA/n9k0NFIc8E8yY5vZQaroyFBrTTWEzG9RY2f7Y3svVyybs6jpXSUs4xff8abo7wL1Y/wUaeatTViamxYnyTvdTmLm3d+JjRij68rxAgMBAAECgYAB0TnhXraSopwIVRfmboea1b0upl+BUdTJcmci412UjrKr5aE695ZLPkXbFXijVu7HJlyyv94NVUdaMACV7Ku/S2RuNB70M7YJm8rAjHFC3/i2ZeIM60h1Ziy4QKv0XM3pRATlDCDNhC1WUrtQCQSgU8kcp6eUUppruOqDzcY04QJBAPm9+sBP9CwDRgy3e5+V8aZtJkwDstb0lVVV/KY890cydVxiCwvX3fqVnxKMlb+x0YtH0sb9v+71xvK2lGobaRECQQDVePU6r/cCEfpc+nkWF6osAH1f8Mux3rYv2DoBGvaPzV2BGfsLed4neRfCwWNCKvGPCdW+L0xMJg8+RwaoBUPhAkAT5kViqXxFPYWJYd1h2+rDXhMdH3ZSlm6HvDBDdrwlWinr0Iwcx3iSjPV93uHXwm118aUj4fg3LDJMCKxOwBxhAkByrQXfvwOMYygBprRBf/j0plazoWFrbd6lGR0f1uI5IfNnFRPdeFw1DEINZ2Hw+6zEUF44SqRMC+4IYJNc02dBAkBCgy7RvfyV/A7N6kKXxTHauY0v6XwSSvpeKtRJkbIcRWOdIYvaHO9L7cklj3vIEdwjSUp9K4VTBYYlmAz1xh03", publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQQRHrnlpV5ZJI9vlmOZfiFnuNnfG+StvIPhvwhSgv8mABB7ahpQrATq2/mAZBvZj85rmAP5/ZNDRSHPBPMmOb2UGq6MhQa001hMxvUWNn+2N7L1csm7Oo6V0lLOMX3/Gm6O8C9WP8FGnmrU1YmpsWJ8k73U5i5t3fiY0Yo+vK8QIDAQAB")
private String testKey;
/**
* 值
*/
// @EncryptField // 什么也不写走默认yml配置
// @EncryptField(algorithm = AlgorithmType.SM4, password = "10rfylhtccpuyke5")
@EncryptField(algorithm = AlgorithmType.AES, password = "10rfylhtccpuyke5")
private String value;
}

View File

@@ -1,65 +0,0 @@
package org.dromara.demo.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.Version;
import org.dromara.common.tenant.core.TenantEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* 测试树表对象 test_tree
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("test_tree")
public class TestTree extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(value = "id")
private Long id;
/**
* 父ID
*/
private Long parentId;
/**
* 部门id
*/
private Long deptId;
/**
* 用户id
*/
private Long userId;
/**
* 树节点名
*/
private String treeName;
/**
* 版本
*/
@Version
private Long version;
/**
* 删除标志
*/
@TableLogic
private Long delFlag;
}

View File

@@ -1,67 +0,0 @@
package org.dromara.demo.domain.bo;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.demo.domain.TestDemo;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
/**
* 测试单表业务对象 test_demo
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = TestDemo.class, reverseConvertGenerate = false)
public class TestDemoBo extends BaseEntity {
/**
* 主键
*/
@NotNull(message = "主键不能为空", groups = {EditGroup.class})
private Long id;
/**
* 部门id
*/
@NotNull(message = "部门id不能为空", groups = {AddGroup.class, EditGroup.class})
private Long deptId;
/**
* 用户id
*/
@NotNull(message = "用户id不能为空", groups = {AddGroup.class, EditGroup.class})
private Long userId;
/**
* 排序号
*/
@NotNull(message = "排序号不能为空", groups = {AddGroup.class, EditGroup.class})
private Integer orderNum;
/**
* key键
*/
@NotBlank(message = "key键不能为空", groups = {AddGroup.class, EditGroup.class})
private String testKey;
/**
* 值
*/
@NotBlank(message = "值不能为空", groups = {AddGroup.class, EditGroup.class})
private String value;
/**
* 版本
*/
private Long version;
}

View File

@@ -1,54 +0,0 @@
package org.dromara.demo.domain.bo;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.demo.domain.TestTree;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 测试树表业务对象 test_tree
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = TestTree.class, reverseConvertGenerate = false)
public class TestTreeBo extends BaseEntity {
/**
* 主键
*/
@NotNull(message = "主键不能为空", groups = {EditGroup.class})
private Long id;
/**
* 父ID
*/
private Long parentId;
/**
* 部门id
*/
@NotNull(message = "部门id不能为空", groups = {AddGroup.class, EditGroup.class})
private Long deptId;
/**
* 用户id
*/
@NotNull(message = "用户id不能为空", groups = {AddGroup.class, EditGroup.class})
private Long userId;
/**
* 树节点名
*/
@NotBlank(message = "树节点名不能为空", groups = {AddGroup.class, EditGroup.class})
private String treeName;
}

View File

@@ -1 +0,0 @@
package org.dromara.demo.domain;

View File

@@ -1,122 +0,0 @@
package org.dromara.demo.domain.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.dromara.common.core.enums.UserStatus;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.annotation.ExcelEnumFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.common.excel.convert.ExcelEnumConvert;
import java.io.Serial;
import java.io.Serializable;
/**
* 带有下拉选的Excel导出
*
* @author Emil.Zhang
*/
@Data
@ExcelIgnoreUnannotated
@AllArgsConstructor
@NoArgsConstructor
public class ExportDemoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 用户昵称
*/
@ExcelProperty(value = "用户昵称", index = 0)
@NotEmpty(message = "用户昵称不能为空", groups = AddGroup.class)
private String nickName;
/**
* 用户类型
* </p>
* 使用ExcelEnumFormat注解需要进行下拉选的部分
*/
@ExcelProperty(value = "用户类型", index = 1, converter = ExcelEnumConvert.class)
@ExcelEnumFormat(enumClass = UserStatus.class, textField = "info")
@NotEmpty(message = "用户类型不能为空", groups = AddGroup.class)
private String userStatus;
/**
* 性别
* <p>
* 使用ExcelDictFormat注解需要进行下拉选的部分
*/
@ExcelProperty(value = "性别", index = 2, converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_user_sex")
@NotEmpty(message = "性别不能为空", groups = AddGroup.class)
private String gender;
/**
* 手机号
*/
@ExcelProperty(value = "手机号", index = 3)
@NotEmpty(message = "手机号不能为空", groups = AddGroup.class)
private String phoneNumber;
/**
* Email
*/
@ExcelProperty(value = "Email", index = 4)
@NotEmpty(message = "Email不能为空", groups = AddGroup.class)
private String email;
/**
* 省
* <p>
* 级联下拉,仅判断是否选了
*/
@ExcelProperty(value = "", index = 5)
@NotNull(message = "省不能为空", groups = AddGroup.class)
private String province;
/**
* 数据库中的省ID
* </p>
* 处理完毕后再判断是否市正确的值
*/
@NotNull(message = "请勿手动输入", groups = EditGroup.class)
private Integer provinceId;
/**
* 市
* <p>
* 级联下拉
*/
@ExcelProperty(value = "", index = 6)
@NotNull(message = "市不能为空", groups = AddGroup.class)
private String city;
/**
* 数据库中的市ID
*/
@NotNull(message = "请勿手动输入", groups = EditGroup.class)
private Integer cityId;
/**
* 县
* <p>
* 级联下拉
*/
@ExcelProperty(value = "", index = 7)
@NotNull(message = "县不能为空", groups = AddGroup.class)
private String area;
/**
* 数据库中的县ID
*/
@NotNull(message = "请勿手动输入", groups = EditGroup.class)
private Integer areaId;
}

View File

@@ -1,56 +0,0 @@
package org.dromara.demo.domain.vo;
import cn.idev.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.dromara.demo.domain.TestDemo;
/**
* 测试单表业务对象 test_demo
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
@AutoMapper(target = TestDemo.class)
public class TestDemoImportVo {
/**
* 部门id
*/
@NotNull(message = "部门id不能为空")
@ExcelProperty(value = "部门id")
private Long deptId;
/**
* 用户id
*/
@NotNull(message = "用户id不能为空")
@ExcelProperty(value = "用户id")
private Long userId;
/**
* 排序号
*/
@NotNull(message = "排序号不能为空")
@ExcelProperty(value = "排序号")
private Long orderNum;
/**
* key键
*/
@NotBlank(message = "key键不能为空")
@ExcelProperty(value = "key键")
private String testKey;
/**
* 值
*/
@NotBlank(message = "值不能为空")
@ExcelProperty(value = "")
private String value;
}

View File

@@ -1,119 +0,0 @@
package org.dromara.demo.domain.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import org.dromara.common.excel.annotation.ExcelNotation;
import org.dromara.common.excel.annotation.ExcelRequired;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.demo.domain.TestDemo;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 测试单表视图对象 test_demo
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = TestDemo.class)
public class TestDemoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ExcelProperty(value = "主键")
private Long id;
/**
* 部门id
*/
@ExcelRequired
@ExcelProperty(value = "部门id")
private Long deptId;
/**
* 用户id
*/
@ExcelRequired
@ExcelProperty(value = "用户id", index = 5)
private Long userId;
/**
* 排序号
*/
@ExcelRequired
@ExcelProperty(value = "排序号")
private Integer orderNum;
/**
* key键
*/
@ExcelNotation(value = "测试key")
@ExcelProperty(value = "key键")
private String testKey;
/**
* 值
*/
@ExcelNotation(value = "测试value")
@ExcelProperty(value = "")
private String value;
/**
* 创建时间
*/
@ExcelRequired
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "创建时间")
private Date createTime;
/**
* 创建人
*/
@ExcelProperty(value = "创建人")
private Long createBy;
/**
* 创建人账号
*/
@Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "createBy")
@ExcelProperty(value = "创建人账号")
private String createByName;
/**
* 更新时间
*/
@ExcelProperty(value = "更新时间")
private Date updateTime;
/**
* 更新人
*/
@ExcelProperty(value = "更新人")
private Long updateBy;
/**
* 更新人账号
*/
@Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "updateBy")
@ExcelProperty(value = "更新人账号")
private String updateByName;
/**
* 版本
*/
private Long version;
}

View File

@@ -1,64 +0,0 @@
package org.dromara.demo.domain.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.demo.domain.TestTree;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 测试树表视图对象 test_tree
*
* @author Lion Li
* @date 2021-07-26
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = TestTree.class)
public class TestTreeVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
private Long id;
/**
* 父id
*/
@ExcelProperty(value = "父id")
private Long parentId;
/**
* 部门id
*/
@ExcelProperty(value = "部门id")
private Long deptId;
/**
* 用户id
*/
@ExcelProperty(value = "用户id")
private Long userId;
/**
* 树节点名
*/
@ExcelProperty(value = "树节点名")
private String treeName;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
}

View File

@@ -1,68 +0,0 @@
package org.dromara.demo.listener;
import cn.hutool.core.util.NumberUtil;
import cn.idev.excel.context.AnalysisContext;
import org.dromara.common.core.utils.ValidatorUtils;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.core.DefaultExcelListener;
import org.dromara.common.excel.core.DropDownOptions;
import org.dromara.demo.domain.vo.ExportDemoVo;
import java.util.List;
/**
* Excel带下拉框的解析处理器
*
* @author Emil.Zhang
*/
public class ExportDemoListener extends DefaultExcelListener<ExportDemoVo> {
public ExportDemoListener() {
// 显示使用构造函数,否则将导致空指针
super(true);
}
@Override
public void invoke(ExportDemoVo data, AnalysisContext context) {
// 先校验必填
ValidatorUtils.validate(data, AddGroup.class);
// 处理级联下拉的部分
String province = data.getProvince();
String city = data.getCity();
String area = data.getArea();
// 本行用户选择的省
List<String> thisRowSelectedProvinceOption = DropDownOptions.analyzeOptionValue(province);
if (thisRowSelectedProvinceOption.size() == 2) {
String provinceIdStr = thisRowSelectedProvinceOption.get(1);
if (NumberUtil.isNumber(provinceIdStr)) {
// 严格要求数据的话可以在这里做与数据库相关的判断
// 例如判断省信息是否在数据库中存在等建议结合RedisCache做缓存10s减少数据库调用
data.setProvinceId(Integer.parseInt(provinceIdStr));
}
}
// 本行用户选择的市
List<String> thisRowSelectedCityOption = DropDownOptions.analyzeOptionValue(city);
if (thisRowSelectedCityOption.size() == 2) {
String cityIdStr = thisRowSelectedCityOption.get(1);
if (NumberUtil.isNumber(cityIdStr)) {
data.setCityId(Integer.parseInt(cityIdStr));
}
}
// 本行用户选择的县
List<String> thisRowSelectedAreaOption = DropDownOptions.analyzeOptionValue(area);
if (thisRowSelectedAreaOption.size() == 2) {
String areaIdStr = thisRowSelectedAreaOption.get(1);
if (NumberUtil.isNumber(areaIdStr)) {
data.setAreaId(Integer.parseInt(areaIdStr));
}
}
// 处理完毕以后判断是否符合规则
ValidatorUtils.validate(data, EditGroup.class);
// 添加到处理结果中
getExcelResult().getList().add(data);
}
}

View File

@@ -1,13 +0,0 @@
package org.dromara.demo.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.demo.domain.TestDemoEncrypt;
/**
* 测试加密功能
*
* @author Lion Li
*/
public interface TestDemoEncryptMapper extends BaseMapperPlus<TestDemoEncrypt, TestDemoEncrypt> {
}

View File

@@ -1,64 +0,0 @@
package org.dromara.demo.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.common.mybatis.annotation.DataColumn;
import org.dromara.common.mybatis.annotation.DataPermission;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.demo.domain.TestDemo;
import org.dromara.demo.domain.vo.TestDemoVo;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
/**
* 测试单表Mapper接口
*
* @author Lion Li
* @date 2021-07-26
*/
public interface TestDemoMapper extends BaseMapperPlus<TestDemo, TestDemoVo> {
@DataPermission({
@DataColumn(key = "deptName", value = "dept_id"),
@DataColumn(key = "userName", value = "user_id")
})
Page<TestDemoVo> customPageList(@Param("page") Page<TestDemo> page, @Param("ew") Wrapper<TestDemo> wrapper);
@Override
@DataPermission({
@DataColumn(key = "deptName", value = "dept_id"),
@DataColumn(key = "userName", value = "user_id")
})
default <P extends IPage<TestDemoVo>> P selectVoPage(IPage<TestDemo> page, Wrapper<TestDemo> wrapper) {
return selectVoPage(page, wrapper, this.currentVoClass());
}
@Override
@DataPermission({
@DataColumn(key = "deptName", value = "dept_id"),
@DataColumn(key = "userName", value = "user_id")
})
default List<TestDemoVo> selectVoList(Wrapper<TestDemo> wrapper) {
return selectVoList(wrapper, this.currentVoClass());
}
@Override
@DataPermission(value = {
@DataColumn(key = "deptName", value = "dept_id"),
@DataColumn(key = "userName", value = "user_id")
}, joinStr = "AND")
List<TestDemo> selectByIds(@Param(Constants.COLL) Collection<? extends Serializable> idList);
@Override
@DataPermission({
@DataColumn(key = "deptName", value = "dept_id"),
@DataColumn(key = "userName", value = "user_id")
})
int updateById(@Param(Constants.ENTITY) TestDemo entity);
}

View File

@@ -1,21 +0,0 @@
package org.dromara.demo.mapper;
import org.dromara.common.mybatis.annotation.DataColumn;
import org.dromara.common.mybatis.annotation.DataPermission;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.demo.domain.TestTree;
import org.dromara.demo.domain.vo.TestTreeVo;
/**
* 测试树表Mapper接口
*
* @author Lion Li
* @date 2021-07-26
*/
@DataPermission({
@DataColumn(key = "deptName", value = "dept_id"),
@DataColumn(key = "userName", value = "user_id")
})
public interface TestTreeMapper extends BaseMapperPlus<TestTree, TestTreeVo> {
}

View File

@@ -1 +0,0 @@
package org.dromara.demo.mapper;

View File

@@ -1,27 +0,0 @@
package org.dromara.demo.service;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 导出下拉框Excel示例
*
* @author Emil.Zhang
*/
public interface IExportExcelService {
/**
* 导出下拉框
*
* @param response /
*/
void exportWithOptions(HttpServletResponse response);
/**
* 自定义导出
*
* @param response /
*/
void customExport(HttpServletResponse response) throws IOException;
}

View File

@@ -1,71 +0,0 @@
package org.dromara.demo.service;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.demo.domain.TestDemo;
import org.dromara.demo.domain.bo.TestDemoBo;
import org.dromara.demo.domain.vo.TestDemoVo;
import java.util.Collection;
import java.util.List;
/**
* 测试单表Service接口
*
* @author Lion Li
* @date 2021-07-26
*/
public interface ITestDemoService {
/**
* 查询单个
*
* @return
*/
TestDemoVo queryById(Long id);
/**
* 查询列表
*/
TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery);
/**
* 自定义分页查询
*/
TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo, PageQuery pageQuery);
/**
* 查询列表
*/
List<TestDemoVo> queryList(TestDemoBo bo);
/**
* 根据新增业务对象插入测试单表
*
* @param bo 测试单表新增业务对象
* @return
*/
Boolean insertByBo(TestDemoBo bo);
/**
* 根据编辑业务对象修改测试单表
*
* @param bo 测试单表编辑业务对象
* @return
*/
Boolean updateByBo(TestDemoBo bo);
/**
* 校验并删除数据
*
* @param ids 主键集合
* @param isValid 是否校验,true-删除前校验,false-不校验
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 批量保存
*/
Boolean saveBatch(List<TestDemo> list);
}

View File

@@ -1,52 +0,0 @@
package org.dromara.demo.service;
import org.dromara.demo.domain.bo.TestTreeBo;
import org.dromara.demo.domain.vo.TestTreeVo;
import java.util.Collection;
import java.util.List;
/**
* 测试树表Service接口
*
* @author Lion Li
* @date 2021-07-26
*/
public interface ITestTreeService {
/**
* 查询单个
*
* @return
*/
TestTreeVo queryById(Long id);
/**
* 查询列表
*/
List<TestTreeVo> queryList(TestTreeBo bo);
/**
* 根据新增业务对象插入测试树表
*
* @param bo 测试树表新增业务对象
* @return
*/
Boolean insertByBo(TestTreeBo bo);
/**
* 根据编辑业务对象修改测试树表
*
* @param bo 测试树表编辑业务对象
* @return
*/
Boolean updateByBo(TestTreeBo bo);
/**
* 校验并删除数据
*
* @param ids 主键集合
* @param isValid 是否校验,true-删除前校验,false-不校验
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -1,297 +0,0 @@
package org.dromara.demo.service.impl;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.idev.excel.write.metadata.WriteSheet;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.SystemConstants;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.file.FileUtils;
import org.dromara.common.excel.core.DropDownOptions;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.excel.utils.ExcelWriterWrapper;
import org.dromara.demo.domain.vo.ExportDemoVo;
import org.dromara.demo.service.IExportExcelService;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 导出下拉框Excel示例
*
* @author Emil.Zhang
*/
@Service
@RequiredArgsConstructor
public class ExportExcelServiceImpl implements IExportExcelService {
@Override
public void exportWithOptions(HttpServletResponse response) {
// 创建表格数据,业务中一般通过数据库查询
List<ExportDemoVo> excelDataList = new ArrayList<>();
for (int i = 0; i < 3; i++) {
// 模拟数据库中的一条数据
ExportDemoVo everyRowData = new ExportDemoVo();
everyRowData.setNickName("用户-" + i);
everyRowData.setUserStatus(SystemConstants.NORMAL);
everyRowData.setGender("1");
everyRowData.setPhoneNumber(String.format("175%08d", i));
everyRowData.setEmail(String.format("175%08d", i) + "@163.com");
everyRowData.setProvinceId(i);
everyRowData.setCityId(i);
everyRowData.setAreaId(i);
excelDataList.add(everyRowData);
}
// 通过@ExcelIgnoreUnannotated配合@ExcelProperty合理显示需要的列
// 并通过@DropDown注解指定下拉值或者通过创建ExcelOptions来指定下拉框
// 使用ExcelOptions时建议指定列index防止出现下拉列解析不对齐
// 首先从数据库中查询下拉框内的可选项
// 这里模拟查询结果
List<DemoCityData> provinceList = getProvinceList(),
cityList = getCityList(provinceList),
areaList = getAreaList(cityList);
int provinceIndex = 5, cityIndex = 6, areaIndex = 7;
DropDownOptions provinceToCity = DropDownOptions.buildLinkedOptions(
provinceList,
provinceIndex,
cityList,
cityIndex,
DemoCityData::getId,
DemoCityData::getPid,
everyOptions -> DropDownOptions.createOptionValue(
everyOptions.getName(),
everyOptions.getId()
)
);
DropDownOptions cityToArea = DropDownOptions.buildLinkedOptions(
cityList,
cityIndex,
areaList,
areaIndex,
DemoCityData::getId,
DemoCityData::getPid,
everyOptions -> DropDownOptions.createOptionValue(
everyOptions.getName(),
everyOptions.getId()
)
);
// 把所有的下拉框存储
List<DropDownOptions> options = new ArrayList<>();
options.add(provinceToCity);
options.add(cityToArea);
// 到此为止所有的下拉框可选项已全部配置完毕
// 接下来需要将Excel中的展示数据转换为对应的下拉选
List<ExportDemoVo> outList = StreamUtils.toList(excelDataList, everyRowData -> {
// 只需要处理没有使用@ExcelDictFormat注解的下拉框
// 一般来说,可以直接在数据库查询即查询出省市县信息,这里通过模拟操作赋值
everyRowData.setProvince(buildOptions(provinceList, everyRowData.getProvinceId()));
everyRowData.setCity(buildOptions(cityList, everyRowData.getCityId()));
everyRowData.setArea(buildOptions(areaList, everyRowData.getAreaId()));
return everyRowData;
});
ExcelUtil.exportExcel(outList, "下拉框示例", ExportDemoVo.class, response, options);
}
private String buildOptions(List<DemoCityData> cityDataList, Integer id) {
Map<Integer, List<DemoCityData>> groupByIdMap =
cityDataList.stream().collect(Collectors.groupingBy(DemoCityData::getId));
if (groupByIdMap.containsKey(id)) {
DemoCityData demoCityData = groupByIdMap.get(id).get(0);
return DropDownOptions.createOptionValue(demoCityData.getName(), demoCityData.getId());
} else {
return StrUtil.EMPTY;
}
}
/**
* 模拟查询数据库操作
*
* @return /
*/
private List<DemoCityData> getProvinceList() {
List<DemoCityData> provinceList = new ArrayList<>();
// 实际业务中一般采用数据库读取的形式,这里直接拼接创建
provinceList.add(new DemoCityData(0, null, "P100000"));
provinceList.add(new DemoCityData(1, null, "P200000"));
provinceList.add(new DemoCityData(2, null, "P300000"));
return provinceList;
}
/**
* 模拟查找数据库操作,需要连带查询出省的数据
*
* @param provinceList 模拟的父省数据
* @return /
*/
private List<DemoCityData> getCityList(List<DemoCityData> provinceList) {
List<DemoCityData> cityList = new ArrayList<>();
// 实际业务中一般采用数据库读取的形式,这里直接拼接创建
cityList.add(new DemoCityData(0, 0, "C110000"));
cityList.add(new DemoCityData(1, 0, "C120000"));
cityList.add(new DemoCityData(2, 1, "C210000"));
cityList.add(new DemoCityData(3, 1, "C220000"));
cityList.add(new DemoCityData(4, 1, "C230000"));
selectParentData(provinceList, cityList);
return cityList;
}
/**
* 模拟查找数据库操作,需要连带查询出市的数据
*
* @param cityList 模拟的父市数据
* @return /
*/
private List<DemoCityData> getAreaList(List<DemoCityData> cityList) {
List<DemoCityData> areaList = new ArrayList<>();
int minCount = 500;
int maxCount = 10000;
// 实际业务中一般采用数据库读取的形式,这里直接拼接创建
for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) {
areaList.add(new DemoCityData(areaList.size(), 0, String.format("A11%04d", i)));
}
for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) {
areaList.add(new DemoCityData(areaList.size(), 1, String.format("A12%04d", i)));
}
for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) {
areaList.add(new DemoCityData(areaList.size(), 2, String.format("A21%04d", i)));
}
for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) {
areaList.add(new DemoCityData(areaList.size(), 3, String.format("A22%04d", i)));
}
for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) {
areaList.add(new DemoCityData(areaList.size(), 4, String.format("A23%04d", i)));
}
selectParentData(cityList, areaList);
return areaList;
}
/**
* 模拟数据库的查询父数据操作
*
* @param parentList /
* @param sonList /
*/
private void selectParentData(List<DemoCityData> parentList, List<DemoCityData> sonList) {
Map<Integer, List<DemoCityData>> parentGroupByIdMap =
parentList.stream().collect(Collectors.groupingBy(DemoCityData::getId));
sonList.forEach(everySon -> {
if (parentGroupByIdMap.containsKey(everySon.getPid())) {
everySon.setPData(parentGroupByIdMap.get(everySon.getPid()).get(0));
}
});
}
/**
* 模拟的数据库省市县
*/
@Data
private static class DemoCityData {
/**
* 数据库id字段
*/
private Integer id;
/**
* 数据库pid字段
*/
private Integer pid;
/**
* 数据库name字段
*/
private String name;
/**
* MyBatisPlus连带查询父数据
*/
private DemoCityData pData;
public DemoCityData(Integer id, Integer pid, String name) {
this.id = id;
this.pid = pid;
this.name = name;
}
}
@Override
public void customExport(HttpServletResponse response) throws IOException {
String filename = ExcelUtil.encodingFilename("自定义导出");
FileUtils.setAttachmentResponseHeader(response, filename);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
ExcelUtil.exportExcel(ExportDemoVo.class, response.getOutputStream(), wrapper -> {
// 创建表格数据,业务中一般通过数据库查询
List<ExportDemoVo> excelDataList = new ArrayList<>();
for (int i = 0; i < 30; i++) {
// 模拟数据库中的一条数据
ExportDemoVo everyRowData = new ExportDemoVo();
everyRowData.setNickName("用户-" + i);
everyRowData.setUserStatus(SystemConstants.NORMAL);
everyRowData.setGender("1");
everyRowData.setPhoneNumber(String.format("175%08d", i));
everyRowData.setEmail(String.format("175%08d", i) + "@163.com");
everyRowData.setProvinceId(i);
everyRowData.setCityId(i);
everyRowData.setAreaId(i);
excelDataList.add(everyRowData);
}
// 创建表格
WriteSheet sheet = ExcelWriterWrapper.sheetBuilder("自定义导出demo")
// 合并单元格
// .registerWriteHandler(new CellMergeStrategy(excelDataList, true))
.build();
wrapper.write(excelDataList, sheet);
List<ExportDemoVo> excelDataList2 = new ArrayList<>();
for (int i = 0; i < 20; i++) {
int index = 1000 + i;
// 模拟数据库中的一条数据
ExportDemoVo everyRowData = new ExportDemoVo();
everyRowData.setNickName("用户-" + index);
everyRowData.setUserStatus(SystemConstants.NORMAL);
everyRowData.setGender("1");
everyRowData.setPhoneNumber(String.format("175%08d", index));
everyRowData.setEmail(String.format("175%08d", index) + "@163.com");
everyRowData.setProvinceId(index);
everyRowData.setCityId(index);
everyRowData.setAreaId(index);
excelDataList2.add(everyRowData);
}
wrapper.write(excelDataList2, sheet);
// 或者在同一个excel中创建多个表格
// WriteSheet sheet2 = ExcelWriterWrapper.sheetBuilder("自定义导出demo2").build();
// wrapper.write(excelDataList2, sheet2);
});
}
}

View File

@@ -1,118 +0,0 @@
package org.dromara.demo.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.demo.domain.TestDemo;
import org.dromara.demo.domain.bo.TestDemoBo;
import org.dromara.demo.domain.vo.TestDemoVo;
import org.dromara.demo.mapper.TestDemoMapper;
import org.dromara.demo.service.ITestDemoService;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 测试单表Service业务层处理
*
* @author Lion Li
* @date 2021-07-26
*/
@RequiredArgsConstructor
@Service
public class TestDemoServiceImpl implements ITestDemoService {
private final TestDemoMapper baseMapper;
@Override
public TestDemoVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
@Override
public TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo);
Page<TestDemoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 自定义分页查询
*/
@Override
public TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo);
Page<TestDemoVo> result = baseMapper.customPageList(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<TestDemoVo> queryList(TestDemoBo bo) {
return baseMapper.selectVoList(buildQueryWrapper(bo));
}
private LambdaQueryWrapper<TestDemo> buildQueryWrapper(TestDemoBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<TestDemo> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getDeptId() != null, TestDemo::getDeptId, bo.getDeptId());
lqw.eq(bo.getUserId() != null, TestDemo::getUserId, bo.getUserId());
lqw.like(StringUtils.isNotBlank(bo.getTestKey()), TestDemo::getTestKey, bo.getTestKey());
lqw.eq(StringUtils.isNotBlank(bo.getValue()), TestDemo::getValue, bo.getValue());
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
TestDemo::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
lqw.orderByAsc(TestDemo::getId);
return lqw;
}
@Override
public Boolean insertByBo(TestDemoBo bo) {
TestDemo add = MapstructUtils.convert(bo, TestDemo.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
@Override
public Boolean updateByBo(TestDemoBo bo) {
TestDemo update = MapstructUtils.convert(bo, TestDemo.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*
* @param entity 实体类数据
*/
private void validEntityBeforeSave(TestDemo entity) {
//TODO 做一些数据校验,如唯一约束
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// 做一些业务上的校验,判断是否需要校验
List<TestDemo> list = baseMapper.selectByIds(ids);
if (list.size() != ids.size()) {
throw new ServiceException("您没有删除权限!");
}
}
return baseMapper.deleteByIds(ids) > 0;
}
@Override
public Boolean saveBatch(List<TestDemo> list) {
return baseMapper.insertBatch(list);
}
}

View File

@@ -1,90 +0,0 @@
package org.dromara.demo.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.demo.domain.TestTree;
import org.dromara.demo.domain.bo.TestTreeBo;
import org.dromara.demo.domain.vo.TestTreeVo;
import org.dromara.demo.mapper.TestTreeMapper;
import org.dromara.demo.service.ITestTreeService;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 测试树表Service业务层处理
*
* @author Lion Li
* @date 2021-07-26
*/
// @DS("slave") // 切换从库查询
@RequiredArgsConstructor
@Service
public class TestTreeServiceImpl implements ITestTreeService {
private final TestTreeMapper baseMapper;
@Override
public TestTreeVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
// @DS("slave") // 切换从库查询
@Override
public List<TestTreeVo> queryList(TestTreeBo bo) {
LambdaQueryWrapper<TestTree> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<TestTree> buildQueryWrapper(TestTreeBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<TestTree> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getDeptId() != null, TestTree::getDeptId, bo.getDeptId());
lqw.eq(bo.getUserId() != null, TestTree::getUserId, bo.getUserId());
lqw.like(StringUtils.isNotBlank(bo.getTreeName()), TestTree::getTreeName, bo.getTreeName());
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
TestTree::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
lqw.orderByAsc(TestTree::getId);
return lqw;
}
@Override
public Boolean insertByBo(TestTreeBo bo) {
TestTree add = MapstructUtils.convert(bo, TestTree.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
@Override
public Boolean updateByBo(TestTreeBo bo) {
TestTree update = MapstructUtils.convert(bo, TestTree.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*
* @param entity 实体类数据
*/
private void validEntityBeforeSave(TestTree entity) {
//TODO 做一些数据校验,如唯一约束
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

View File

@@ -1 +0,0 @@
package org.dromara.demo.service.impl;

View File

@@ -1 +0,0 @@
package org.dromara.demo.service;

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.demo.mapper.TestDemoMapper">
<select id="customPageList" resultType="org.dromara.demo.domain.vo.TestDemoVo">
SELECT * FROM test_demo ${ew.customSqlSegment}
</select>
</mapper>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.demo.mapper.TestTreeMapper">
</mapper>

View File

@@ -1,3 +0,0 @@
java包使用 `.` 分割 resource 目录使用 `/` 分割
<br>
此文件目的 防止文件夹粘连找不到 `xml` 文件

View File

@@ -3,8 +3,8 @@ gen:
# 作者 # 作者
author: Lion Li author: Lion Li
# 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
packageName: org.dromara.water packageName: org.dromara.app
# 自动去除表前缀默认是false # 自动去除表前缀默认是false
autoRemovePre: false autoRemovePre: false
# 表前缀(生成类名不会包含表前缀,多个用逗号分隔) # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
tablePrefix: sys_ tablePrefix: app_

View File

@@ -108,6 +108,8 @@ public class SysUserBo extends BaseEntity {
*/ */
private String userIds; private String userIds;
private String code;
/** /**
* 排除不查询的用户(工作流用) * 排除不查询的用户(工作流用)
*/ */

View File

@@ -84,8 +84,8 @@ public class SysUserVo implements Serializable {
/** /**
* 密码 * 密码
*/ */
@JsonIgnore //@JsonIgnore
@JsonProperty //@JsonProperty
private String password; private String password;
/** /**
@@ -139,4 +139,7 @@ public class SysUserVo implements Serializable {
*/ */
private Long roleId; private Long roleId;
private String oldPassword;
} }

View File

@@ -228,4 +228,8 @@ public interface ISysUserService {
* @return 结果 * @return 结果
*/ */
List<SysUserVo> selectUserListByDept(Long deptId); List<SysUserVo> selectUserListByDept(Long deptId);
int updateAppUser(SysUserBo user);
int updateUserPas(SysUserBo userBo);
} }

View File

@@ -3,8 +3,10 @@ package org.dromara.system.service.impl;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -14,13 +16,17 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.constant.GlobalConstants;
import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.SystemConstants;
import org.dromara.common.core.domain.dto.UserDTO; import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.exception.user.CaptchaExpireException;
import org.dromara.common.core.service.UserService; import org.dromara.common.core.service.UserService;
import org.dromara.common.core.utils.*; import org.dromara.common.core.utils.*;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.SysUser; import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.SysUserPost; import org.dromara.system.domain.SysUserPost;
@@ -357,6 +363,66 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
throw new ServiceException("修改用户{}信息失败", user.getUserName()); throw new ServiceException("修改用户{}信息失败", user.getUserName());
} }
return flag; return flag;
}
@Override
public int updateAppUser(SysUserBo user) {
SysUser sysUser = MapstructUtils.convert(user, SysUser.class);
sysUser.setUserId(LoginHelper.getUserId());
// 防止错误更新后导致的数据误删除
boolean b =true;
if (StringUtils.isNotEmpty(user.getPhonenumber())){
b = validateSmsCode(user.getPhonenumber(), user.getCode());
}
// if (StringUtils.isNotEmpty(user.getUserName()) && Validator.isMobile(user.getUserName())){
// b = validateSmsCode(user.getUserName(), user.getCode());
// }
if (b){
// String hashpw = BCrypt.hashpw(user.getPassword());
// sysUser.setPassword(hashpw);
int flag = baseMapper.updateById(sysUser);
if (flag < 1) {
throw new ServiceException("修改用户{}信息失败", user.getUserName());
}
return flag;
}else {
return 0;
}
}
@Override
public int updateUserPas(SysUserBo user) {
SysUser sysUser = MapstructUtils.convert(user, SysUser.class);
sysUser.setUserId(LoginHelper.getUserId());
// 防止错误更新后导致的数据误删除
boolean b =true;
if (StringUtils.isNotEmpty(user.getUserName()) && Validator.isMobile(user.getUserName())){
b = validateSmsCode(user.getUserName(), user.getCode());
}
if (b){
String hashpw = BCrypt.hashpw(user.getPassword());
sysUser.setPassword(hashpw);
int flag = baseMapper.updateById(sysUser);
if (flag < 1) {
throw new ServiceException("修改用户{}密码失败", user.getUserName());
}
return flag;
}else {
return 0;
}
}
/**
* 校验短信验证码
*/
private boolean validateSmsCode( String phonenumber, String smsCode) {
String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + phonenumber);
if (StringUtils.isBlank(code)) {
throw new CaptchaExpireException();
}
return code.equals(smsCode);
} }
/** /**