Initial commit: reorganized source tree

- backend/: 13 Maven modules (cw-elevator-application, cloudwalk-cloud, intelligent-cwoscomponent, ninca-crk, etc.)
- frontend/: 4 Vue projects (elevator-front, cwos-portal, alarm-front, front_acs) + decompiled + scripts
- scripts/: build, test-env, tools (Docker Compose, service templates, API parity)
- docs/: AGENTS.md, superpowers specs, architecture docs
- .gitignore: standard Java/Maven exclusions

Moved from legacy maven-*/ root layout to backend/ organized structure.
This commit is contained in:
hpd840321
2026-05-09 09:00:12 +08:00
commit 7b2bd307f1
7260 changed files with 612980 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,18 @@
# V1/V2 加载顺序与最终清单摘要
## 加载顺序
- 优先级采用: external > jar(在未显式 `--spring.config.location` 的前提下)
- V1: 三个配置文件 external=Y, jar=Y
- V2.0.4: 三个配置文件 external=Y, jar=Y
## 关键结论
- V1 `spring.cloud.consul.discovery.enabled` = `false`
- V2 `spring.cloud.consul.discovery.enabled` = `true`
- V1 `spring.cloud.consul.host` = `10.128.161.95`
- V2 `spring.cloud.consul.host` = `10.0.22.102`
## 输出文件
- `/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/docs/testing/config-load-compare/v1-effective-20260429-221913.json`
- `/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/docs/testing/config-load-compare/v2-effective-20260429-221913.json`
- `/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/docs/testing/config-load-compare/v1-v2-diff-20260429-221913.md`
- `/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/docs/testing/config-load-compare/load-order-summary-20260429-221913.md`
@@ -0,0 +1,15 @@
# 加载顺序复测(V2使用V1属性)
- 顺序: external > jar(未显式spring.config.location
- V1 discovery.enabled=false
- V2 discovery.enabled=false
- V1 consul.host=10.128.161.95
- V2 consul.host=371bfca4972c43d2aefcf302d0a4a277
- 差异键数量=11
## 文件
- /media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/docs/testing/config-load-compare/v1-effective-20260429-224315.json
- /media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/docs/testing/config-load-compare/v2-effective-v1props-20260429-224315.json
- /media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/docs/testing/config-load-compare/v1-v2-v1props-diff-20260429-224315.md
- /media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/docs/testing/config-load-compare/load-order-summary-v1props-20260429-224315.md
@@ -0,0 +1,219 @@
{
"tag": "V1",
"base_dir": "/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/cw-elevator-application-V1.0.0.20211103",
"jar": "/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/cw-elevator-application-V1.0.0.20211103/cw-elevator-application-V1.0.0.20211103.jar",
"order_assumption": "external > jar (未显式spring.config.location时)",
"file_presence": {
"bootstrap.properties": {
"external": true,
"jar": true
},
"application.properties": {
"external": true,
"jar": true
},
"application-access-control.properties": {
"external": true,
"jar": true
}
},
"focus_keys": {
"spring.application.name": {
"value": "elevator-app",
"source": "external"
},
"spring.profiles.active": {
"value": "access-control",
"source": "external"
},
"spring.cloud.consul.host": {
"value": "10.128.161.95",
"source": "external"
},
"spring.cloud.consul.port": {
"value": "8500",
"source": "external"
},
"spring.cloud.consul.enabled": {
"value": "true",
"source": "external"
},
"spring.cloud.consul.discovery.enabled": {
"value": "false",
"source": "external"
},
"spring.cloud.consul.discovery.register": {
"value": "true",
"source": "external"
},
"spring.cloud.consul.config.enabled": {
"value": "<unset>",
"source": "unset"
},
"feign.cwos-portal.name": {
"value": "cwos-portal",
"source": "external"
},
"feign.ninca-common.name": {
"value": "ninca-common",
"source": "external"
},
"feign.component-organization.name": {
"value": "ninca-common-component-organization",
"source": "external"
},
"cwos-portal.ribbon.NIWSServerListClassName": {
"value": "<unset>",
"source": "unset"
},
"cwos-portal.ribbon.listOfServers": {
"value": "<unset>",
"source": "unset"
},
"ninca-common.ribbon.NIWSServerListClassName": {
"value": "<unset>",
"source": "unset"
},
"ninca-common.ribbon.listOfServers": {
"value": "<unset>",
"source": "unset"
}
},
"effective_all_keys": {
"spring.cloud.consul.discovery.enabled": "false",
"feign.ninca-common.name": "ninca-common",
"ninca.update.floor.pool.allowCoreThreadTimeOut": "true",
"sendRecord.token.appKey": "293e2d708f0143c2957b702cef44d951",
"ninca.update.floor.pool.corePoolSize": "5",
"cloudwalk.access-control.common.device-category-array[0]": "4",
"cloudwalk.access-control.common.device-category-array[5]": "11",
"feign.component-organization.name": "ninca-common-component-organization",
"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds": "10000",
"spring.cloud.consul.discovery.instance-id": "${spring.application.name}-${spring.cloud.client.ipAddress}:${server.port}",
"spring.redis.timeout": "0",
"spring.messages.basename": "access-control",
"spring.shardingsphere.datasource.ds0.type": "com.zaxxer.hikari.HikariDataSource",
"spring.cloud.consul.discovery.register": "true",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.table-strategy.standard.precise-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"cloudwalk.datafield.securityKey": "d4b2aabc97394a12a27fc3cca6cd9ba1",
"cloudwalk.access-control.common.publish-opendoor-service-code": "access-control",
"spring.shardingsphere.datasource.ds0.maximum-pool-size": "20",
"cloudwalk.serial.enable": "true",
"cloudwalk.access-control.common.device-category-array[1]": "5",
"spring.redis.host": "127.0.0.1",
"spring.shardingsphere.datasource.ds0.pool-name": "ds0-pool",
"person.name.space": "recordEvent",
"spring.profiles.active": "access-control",
"management.health.redis.enabled": "false",
"management.health.db.enabled": "false",
"cloudwalk.serial.serial-redis-key": "CLOUDWALK-ACS-SERIAL-KEY",
"spring.application.name": "elevator-app",
"dubbo.protocol.port": "16107",
"spring.shardingsphere.datasource.ds0.driver-class-name": "com.mysql.jdbc.Driver",
"spring.shardingsphere.sharding.binding-tables": "IT_ACS_ELEVATOR_RECORD,IT_ACS_RECOG_RECORD",
"spring.cloud.consul.discovery.prefer-ip-address": "true",
"cloudwalk.event.bootstrap-servers": "10.128.161.95:9092",
"cloudwalk.access-control.common.face-compare-THRESHOLD": "80",
"spring.http.encoding.charset": "UTF-8",
"spring.shardingsphere.datasource.ds0.password": "123456",
"mybatis.mapper-locations": "classpath*:cn/cloudwalk/elevator/**/*.xml",
"ribbon.ReadTimeout": "10000",
"lockWatchdogTimeout": "21000",
"cloudwalk.elevator.common.relativePrefix": "/cwos-portal/portal/fileManager/imgByPath?path=",
"spring.shardingsphere.props.sql.show": "false",
"intelligent.lock.enable": "true",
"mybatis.config-location": "classpath:mapper/mybatis-config.xml",
"spring.redis.pool.max-idle": "1",
"spring.cloud.consul.host": "10.128.161.95",
"feign.ninca-crk-std.name": "ninca-crk-std",
"cloudwalk.access-control.common.face-capture-interval-milliseconds": "3000",
"spring.redis.pool.max-wait": "10",
"elevator.application.time": "600",
"dubbo.provider.version": "1.0",
"feign.hystrix.enable": "true",
"spring.shardingsphere.datasource.ds0.auto-commit": "true",
"cloudwalk.serial.serial-length": "8",
"spring.mvc.throw-exception-if-no-handler-found": "true",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.executable-class": "cn.cloudwalk.service.ninca.accesscontrol.common.job.executable.AcsRecordStatisticsByDayJob",
"cloudwalk.access-control.common.device-category-array[2]": "7",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.actual-data-nodes": "ds0.IT_ACS_RECOG_RECORD_$->{2020..2022}",
"floor.building.id": "605560539791228928",
"spring.shardingsphere.datasource.ds0.jdbc-url": "jdbc:mysql://192.168.3.12:3307/cw-elevator-application?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true",
"feign.mqtt.name": "cloudwalk-device-thirdparty",
"sendRecord.token.corpId": "53db867a8bb747a1bd04dd1afcad8ca6",
"spring.messages.encoding": "utf-8",
"cloudwalk.serial.serial-type": "redis",
"spring.shardingsphere.sharding.default-data-source-name": "ds0",
"cloudwalk.access-control.common.face-capture-time-expired-milliseconds": "300000",
"elevator.application.keyA": "5B7DEF88FF04",
"spring.http.encoding.force": "true",
"spring.redis.pool.max-active": "10",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.priority": "1",
"ninca.update.floor.pool.queueCapacity": "100000",
"ribbon.ConnectTimeout": "10000",
"cloudwalk.access-control.common.device-atrr-map.ACS_FACE_REG_THRESHOLD": "75",
"spring.http.multipart.max-request-size": "200MB",
"logging.config": "classpath:logs/logback.xml",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.group": "ACCESS-CONTROL_GROUP",
"cloudwalk.datafield.encrypt": "AES",
"spring.http.multipart.max-file-size": "200MB",
"dubbo.registry.address": "zookeeper://10.128.161.95:2181",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.table-strategy.standard.precise-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"logging.path": "logs",
"server.port": "16112",
"cloudwalk.access-control.common.device-controller-array[0]": "mqtt",
"spring.cloud.consul.discovery.deregister": "false",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.table-strategy.standard.range-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"cloudwalk.access-control.common.device-category-array[3]": "2",
"spring.shardingsphere.datasource.ds0.minimum-idle": "5",
"spring.shardingsphere.datasource.names": "ds0",
"sendRecord.token.appSecret": "5f6995009b864669b52041b8f5dc4625",
"logging.level.root": "info",
"intelligent.lock.config.default-wait-time": "10000",
"spring.cloud.consul.port": "8500",
"logging.file": "${spring.application.name}",
"ribbon.okhttp.enabled": "true",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.cron-expression": "0 10 0 * * ?",
"feign.davinci-portal.name": "cwos-portal",
"sendRecord.boolean": "true",
"ninca-crk-std.ip": "10.128.161.95:16106",
"spring.mvc.locale": "zh_CN",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.description": "AcsRecordStatisticsByDay job is starting.........",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.table-strategy.standard.range-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"feign.resource.name": "cwos-portal",
"spring.redis.port": "6379",
"cloudwalk.datafield.enable": "true",
"logging.level.cn.cloudwalk": "info",
"cloudwalk.event.group-id": "cw-elevator-application-1",
"cloudwalk.access-control.common.face-capture-open-door-fail-milliseconds": "600000",
"spring.shardingsphere.datasource.ds0.username": "root",
"cloudwalk.spring.cache.expires": "CACHE_NAME_APPLICATIONIDS#21600,ACS_DeviceTypesCache#7200,ACS_DeviceTypeFeaturesCache#7200,ACS_DeviceAttrsCache#7200,ACS_RecordStatisticsCache#90000,ACS_AreaTreeCache#60",
"spring.messages.always-use-message-format": "true",
"spring.redis.database": "5",
"spring.shardingsphere.datasource.ds0.max-lifetime": "1765000",
"cloudwalk.access-control.common.device-category-array[4]": "8",
"cloudwalk.access-control.common.publish-opendoor-switch": "false",
"feign.device.name": "cwos-portal",
"feign.cwos-portal.name": "cwos-portal",
"ninca.update.floor.pool.maxPoolSize": "5",
"spring.cloud.consul.enabled": "true",
"sendRecord.ip": "hrec.star-river.com:32165",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.name": "AcsRecordStatisticsByDayJob",
"cloudwalk.event.handler-executor-config.core-pool-size": "10",
"elevator.application.key": "xinghewan",
"ninca.update.floor.pool.keepAliveSeconds": "150",
"spring.redis.pool.min-idle": "0",
"spring.cloud.consul.discovery.ip-address": "${spring.cloud.client.ipAddress}",
"feign.okhttp.enable": "true",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.table-strategy.standard.sharding-column": "RECOGNITION_TIME",
"spring.shardingsphere.datasource.ds0.connection-timeout": "60000",
"cloudwalk.event.handler-executor-config.maximum-pool-size": "30",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.table-strategy.standard.sharding-column": "RECOGNITION_TIME",
"feign.httpclient.enable": "false",
"spring.http.encoding.enabled": "true",
"ribbon.http.client.enabled": "false",
"spring.redis.password": "1qaz!QAZ",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.actual-data-nodes": "ds0.IT_ACS_ELEVATOR_RECORD_$->{2020..2022}",
"server.tomcat.uri-encoding": "UTF-8"
}
}
@@ -0,0 +1,195 @@
{
"tag": "V1",
"base_dir": "/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/cw-elevator-application-V1.0.0.20211103",
"jar": "/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/cw-elevator-application-V1.0.0.20211103/cw-elevator-application-V1.0.0.20211103.jar",
"order": "external>jar",
"file_presence": {
"bootstrap.properties": {
"external": true,
"jar": true
},
"application.properties": {
"external": true,
"jar": true
},
"application-access-control.properties": {
"external": true,
"jar": true
}
},
"focus_keys": {
"spring.cloud.consul.host": {
"value": "10.128.161.95",
"source": "external"
},
"spring.cloud.consul.port": {
"value": "8500",
"source": "external"
},
"spring.cloud.consul.discovery.enabled": {
"value": "false",
"source": "external"
},
"spring.cloud.consul.config.enabled": {
"value": "<unset>",
"source": "unset"
},
"feign.cwos-portal.name": {
"value": "cwos-portal",
"source": "external"
},
"feign.ninca-common.name": {
"value": "ninca-common",
"source": "external"
},
"feign.component-organization.name": {
"value": "ninca-common-component-organization",
"source": "external"
},
"cwos-portal.ribbon.NIWSServerListClassName": {
"value": "<unset>",
"source": "unset"
},
"cwos-portal.ribbon.listOfServers": {
"value": "<unset>",
"source": "unset"
}
},
"effective_all_keys": {
"logging.level.root": "info",
"logging.config": "classpath:logs/logback.xml",
"management.health.redis.enabled": "false",
"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds": "10000",
"cloudwalk.event.handler-executor-config.core-pool-size": "10",
"spring.cloud.consul.discovery.instance-id": "${spring.application.name}-${spring.cloud.client.ipAddress}:${server.port}",
"ninca.update.floor.pool.queueCapacity": "100000",
"person.name.space": "recordEvent",
"spring.redis.pool.max-active": "10",
"spring.cloud.consul.discovery.enabled": "false",
"sendRecord.token.appSecret": "5f6995009b864669b52041b8f5dc4625",
"spring.cloud.consul.enabled": "true",
"ninca.update.floor.pool.maxPoolSize": "5",
"cloudwalk.serial.serial-length": "8",
"server.port": "16112",
"spring.shardingsphere.datasource.names": "ds0",
"elevator.application.key": "xinghewan",
"spring.redis.password": "1qaz!QAZ",
"spring.mvc.throw-exception-if-no-handler-found": "true",
"logging.file": "${spring.application.name}",
"feign.component-organization.name": "ninca-common-component-organization",
"cloudwalk.spring.cache.expires": "CACHE_NAME_APPLICATIONIDS#21600,ACS_DeviceTypesCache#7200,ACS_DeviceTypeFeaturesCache#7200,ACS_DeviceAttrsCache#7200,ACS_RecordStatisticsCache#90000,ACS_AreaTreeCache#60",
"feign.mqtt.name": "cloudwalk-device-thirdparty",
"spring.shardingsphere.datasource.ds0.connection-timeout": "60000",
"ninca.update.floor.pool.keepAliveSeconds": "150",
"feign.cwos-portal.name": "cwos-portal",
"spring.shardingsphere.datasource.ds0.password": "123456",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.table-strategy.standard.sharding-column": "RECOGNITION_TIME",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.table-strategy.standard.precise-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"floor.building.id": "605560539791228928",
"spring.messages.basename": "access-control",
"spring.cloud.consul.port": "8500",
"ribbon.http.client.enabled": "false",
"sendRecord.ip": "hrec.star-river.com:32165",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.cron-expression": "0 10 0 * * ?",
"sendRecord.token.corpId": "53db867a8bb747a1bd04dd1afcad8ca6",
"cloudwalk.serial.serial-redis-key": "CLOUDWALK-ACS-SERIAL-KEY",
"cloudwalk.datafield.enable": "true",
"elevator.application.time": "600",
"cloudwalk.access-control.common.device-category-array[5]": "11",
"spring.messages.always-use-message-format": "true",
"spring.mvc.locale": "zh_CN",
"feign.ninca-crk-std.name": "ninca-crk-std",
"sendRecord.token.appKey": "293e2d708f0143c2957b702cef44d951",
"ribbon.ConnectTimeout": "10000",
"spring.cloud.consul.discovery.deregister": "false",
"spring.redis.timeout": "0",
"spring.shardingsphere.sharding.default-data-source-name": "ds0",
"spring.redis.database": "5",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.executable-class": "cn.cloudwalk.service.ninca.accesscontrol.common.job.executable.AcsRecordStatisticsByDayJob",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.description": "AcsRecordStatisticsByDay job is starting.........",
"logging.level.cn.cloudwalk": "info",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.priority": "1",
"spring.profiles.active": "access-control",
"spring.http.encoding.force": "true",
"spring.redis.pool.max-wait": "10",
"cloudwalk.access-control.common.device-controller-array[0]": "mqtt",
"cloudwalk.event.group-id": "cw-elevator-application-1",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.table-strategy.standard.precise-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"sendRecord.boolean": "true",
"logging.path": "logs",
"ribbon.okhttp.enabled": "true",
"spring.shardingsphere.datasource.ds0.username": "root",
"spring.redis.port": "6379",
"feign.hystrix.enable": "true",
"spring.http.multipart.max-request-size": "200MB",
"feign.device.name": "cwos-portal",
"elevator.application.keyA": "5B7DEF88FF04",
"cloudwalk.datafield.securityKey": "d4b2aabc97394a12a27fc3cca6cd9ba1",
"spring.cloud.consul.discovery.ip-address": "${spring.cloud.client.ipAddress}",
"cloudwalk.access-control.common.device-atrr-map.ACS_FACE_REG_THRESHOLD": "75",
"cloudwalk.access-control.common.face-compare-THRESHOLD": "80",
"cloudwalk.datafield.encrypt": "AES",
"management.health.db.enabled": "false",
"server.tomcat.uri-encoding": "UTF-8",
"spring.shardingsphere.datasource.ds0.max-lifetime": "1765000",
"mybatis.mapper-locations": "classpath*:cn/cloudwalk/elevator/**/*.xml",
"intelligent.lock.config.default-wait-time": "10000",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.table-strategy.standard.sharding-column": "RECOGNITION_TIME",
"ninca.update.floor.pool.corePoolSize": "5",
"spring.http.multipart.max-file-size": "200MB",
"ribbon.ReadTimeout": "10000",
"cloudwalk.access-control.common.device-category-array[2]": "7",
"cloudwalk.access-control.common.publish-opendoor-switch": "false",
"dubbo.provider.version": "1.0",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.actual-data-nodes": "ds0.IT_ACS_ELEVATOR_RECORD_$->{2020..2022}",
"spring.cloud.consul.host": "10.128.161.95",
"cloudwalk.access-control.common.face-capture-open-door-fail-milliseconds": "600000",
"cloudwalk.access-control.common.device-category-array[3]": "2",
"feign.davinci-portal.name": "cwos-portal",
"spring.shardingsphere.datasource.ds0.pool-name": "ds0-pool",
"cloudwalk.elevator.common.relativePrefix": "/cwos-portal/portal/fileManager/imgByPath?path=",
"spring.redis.host": "127.0.0.1",
"spring.shardingsphere.props.sql.show": "false",
"spring.shardingsphere.sharding.binding-tables": "IT_ACS_ELEVATOR_RECORD,IT_ACS_RECOG_RECORD",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.table-strategy.standard.range-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"spring.shardingsphere.datasource.ds0.auto-commit": "true",
"spring.messages.encoding": "utf-8",
"spring.redis.pool.min-idle": "0",
"spring.shardingsphere.datasource.ds0.jdbc-url": "jdbc:mysql://192.168.3.12:3307/cw-elevator-application?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true",
"spring.application.name": "elevator-app",
"cloudwalk.serial.serial-type": "redis",
"feign.okhttp.enable": "true",
"mybatis.config-location": "classpath:mapper/mybatis-config.xml",
"spring.redis.pool.max-idle": "1",
"cloudwalk.access-control.common.face-capture-interval-milliseconds": "3000",
"cloudwalk.serial.enable": "true",
"spring.cloud.consul.discovery.prefer-ip-address": "true",
"cloudwalk.access-control.common.face-capture-time-expired-milliseconds": "300000",
"dubbo.protocol.port": "16107",
"intelligent.lock.enable": "true",
"lockWatchdogTimeout": "21000",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.actual-data-nodes": "ds0.IT_ACS_RECOG_RECORD_$->{2020..2022}",
"ninca.update.floor.pool.allowCoreThreadTimeOut": "true",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.group": "ACCESS-CONTROL_GROUP",
"spring.cloud.consul.discovery.register": "true",
"feign.httpclient.enable": "false",
"spring.shardingsphere.datasource.ds0.driver-class-name": "com.mysql.jdbc.Driver",
"spring.http.encoding.charset": "UTF-8",
"ninca-crk-std.ip": "10.128.161.95:16106",
"spring.http.encoding.enabled": "true",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.table-strategy.standard.range-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"cloudwalk.event.handler-executor-config.maximum-pool-size": "30",
"spring.shardingsphere.datasource.ds0.minimum-idle": "5",
"spring.shardingsphere.datasource.ds0.maximum-pool-size": "20",
"cloudwalk.event.bootstrap-servers": "10.128.161.95:9092",
"spring.shardingsphere.datasource.ds0.type": "com.zaxxer.hikari.HikariDataSource",
"dubbo.registry.address": "zookeeper://10.128.161.95:2181",
"feign.ninca-common.name": "ninca-common",
"feign.resource.name": "cwos-portal",
"cloudwalk.access-control.common.device-category-array[4]": "8",
"cloudwalk.access-control.common.device-category-array[0]": "4",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.name": "AcsRecordStatisticsByDayJob",
"cloudwalk.access-control.common.device-category-array[1]": "5",
"cloudwalk.access-control.common.publish-opendoor-service-code": "access-control"
}
}
@@ -0,0 +1,28 @@
# V1 vs V2.0.4 最终加载差异
- 生成时间: 2026-04-29T22:19:14.387292
- 加载顺序假设: external > jar (未显式spring.config.location时)
## 关键键差异
- `spring.cloud.consul.host`: V1=`10.128.161.95`(external) | V2=`10.0.22.102`(external)
- `spring.cloud.consul.discovery.enabled`: V1=`false`(external) | V2=`true`(external)
## 全量差异键统计
- 差异键数量: 12
## 前50个差异键
- `cloudwalk.event.bootstrap-servers`: V1=`10.128.161.95:9092` | V2=`371bfca4972c43d2aefcf302d0a4a277:9092,44700995ee904679a7ad5afddcf93bb5:9092,0837a70b5fab47569391828f5feb2561:9092`
- `dubbo.registry.address`: V1=`zookeeper://10.128.161.95:2181` | V2=`zookeeper://10.0.22.207:2181`
- `logging.path`: V1=`logs` | V2=`/data/cwos/cw-elevator-application-V1.0.0.20211103/logs`
- `ninca-crk-std.ip`: V1=`10.128.161.95:16106` | V2=`10.0.22.102:16106`
- `spring.cloud.consul.discovery.enabled`: V1=`false` | V2=`true`
- `spring.cloud.consul.host`: V1=`10.128.161.95` | V2=`10.0.22.102`
- `spring.redis.host`: V1=`127.0.0.1` | V2=`redis_01.redis_ip`
- `spring.shardingsphere.datasource.ds0.jdbc-url`: V1=`jdbc:mysql://192.168.3.12:3307/cw-elevator-application?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true` | V2=`jdbc:mysql://mysql_01.mysql_ip:3306/cw-elevator-application?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true`
- `spring.shardingsphere.datasource.ds0.password`: V1=`123456` | V2=`1qaz!QAZ`
- `spring.shardingsphere.datasource.ds0.username`: V1=`root` | V2=`cloudwalk`
- `spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.actual-data-nodes`: V1=`ds0.IT_ACS_ELEVATOR_RECORD_$->{2020..2022}` | V2=`ds0.IT_ACS_ELEVATOR_RECORD_$->{2020..2030}`
- `spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.actual-data-nodes`: V1=`ds0.IT_ACS_RECOG_RECORD_$->{2020..2022}` | V2=`ds0.IT_ACS_RECOG_RECORD_$->{2020..2030}`
@@ -0,0 +1,27 @@
# V1 vs V2(使用V1属性打包) 差异
- 差异键数量: 11
## 关键键
- `spring.cloud.consul.host`: V1=`10.128.161.95`(external) | V2=`371bfca4972c43d2aefcf302d0a4a277`(external)
- `spring.cloud.consul.port`: V1=`8500`(external) | V2=`8500`(external)
- `spring.cloud.consul.discovery.enabled`: V1=`false`(external) | V2=`false`(external)
- `spring.cloud.consul.config.enabled`: V1=`<unset>`(unset) | V2=`<unset>`(unset)
- `feign.cwos-portal.name`: V1=`cwos-portal`(external) | V2=`cwos-portal`(external)
- `feign.ninca-common.name`: V1=`ninca-common`(external) | V2=`ninca-common`(external)
- `feign.component-organization.name`: V1=`ninca-common-component-organization`(external) | V2=`ninca-common-component-organization`(external)
- `cwos-portal.ribbon.NIWSServerListClassName`: V1=`<unset>`(unset) | V2=`<unset>`(unset)
- `cwos-portal.ribbon.listOfServers`: V1=`<unset>`(unset) | V2=`<unset>`(unset)
## 前50个全量差异
- `cloudwalk.event.bootstrap-servers`: V1=`10.128.161.95:9092` | V2=`371bfca4972c43d2aefcf302d0a4a277:9092,44700995ee904679a7ad5afddcf93bb5:9092,0837a70b5fab47569391828f5feb2561:9092`
- `dubbo.registry.address`: V1=`zookeeper://10.128.161.95:2181` | V2=`zookeeper://10.0.22.207:2181`
- `logging.path`: V1=`logs` | V2=`/data/cwos/cw-elevator-application-V1.0.0.20211103/logs`
- `ninca-crk-std.ip`: V1=`10.128.161.95:16106` | V2=`10.0.22.102:16106`
- `spring.cloud.consul.host`: V1=`10.128.161.95` | V2=`371bfca4972c43d2aefcf302d0a4a277`
- `spring.redis.host`: V1=`127.0.0.1` | V2=`redis_01.redis_ip`
- `spring.shardingsphere.datasource.ds0.jdbc-url`: V1=`jdbc:mysql://192.168.3.12:3307/cw-elevator-application?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true` | V2=`jdbc:mysql://mysql_01.mysql_ip:3306/cw-elevator-application?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true`
- `spring.shardingsphere.datasource.ds0.password`: V1=`123456` | V2=`1qaz!QAZ`
- `spring.shardingsphere.datasource.ds0.username`: V1=`root` | V2=`cloudwalk`
- `spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.actual-data-nodes`: V1=`ds0.IT_ACS_ELEVATOR_RECORD_$->{2020..2022}` | V2=`ds0.IT_ACS_ELEVATOR_RECORD_$->{2020..2030}`
- `spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.actual-data-nodes`: V1=`ds0.IT_ACS_RECOG_RECORD_$->{2020..2022}` | V2=`ds0.IT_ACS_RECOG_RECORD_$->{2020..2030}`
@@ -0,0 +1,219 @@
{
"tag": "V2.0.4",
"base_dir": "/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/maven-cw-elevator-application/deploy/v2-maven",
"jar": "/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/maven-cw-elevator-application/releases/v2.0.4/cw-elevator-application-2.0.4.jar",
"order_assumption": "external > jar (未显式spring.config.location时)",
"file_presence": {
"bootstrap.properties": {
"external": true,
"jar": true
},
"application.properties": {
"external": true,
"jar": true
},
"application-access-control.properties": {
"external": true,
"jar": true
}
},
"focus_keys": {
"spring.application.name": {
"value": "elevator-app",
"source": "external"
},
"spring.profiles.active": {
"value": "access-control",
"source": "external"
},
"spring.cloud.consul.host": {
"value": "10.0.22.102",
"source": "external"
},
"spring.cloud.consul.port": {
"value": "8500",
"source": "external"
},
"spring.cloud.consul.enabled": {
"value": "true",
"source": "external"
},
"spring.cloud.consul.discovery.enabled": {
"value": "true",
"source": "external"
},
"spring.cloud.consul.discovery.register": {
"value": "true",
"source": "external"
},
"spring.cloud.consul.config.enabled": {
"value": "<unset>",
"source": "unset"
},
"feign.cwos-portal.name": {
"value": "cwos-portal",
"source": "external"
},
"feign.ninca-common.name": {
"value": "ninca-common",
"source": "external"
},
"feign.component-organization.name": {
"value": "ninca-common-component-organization",
"source": "external"
},
"cwos-portal.ribbon.NIWSServerListClassName": {
"value": "<unset>",
"source": "unset"
},
"cwos-portal.ribbon.listOfServers": {
"value": "<unset>",
"source": "unset"
},
"ninca-common.ribbon.NIWSServerListClassName": {
"value": "<unset>",
"source": "unset"
},
"ninca-common.ribbon.listOfServers": {
"value": "<unset>",
"source": "unset"
}
},
"effective_all_keys": {
"spring.cloud.consul.discovery.enabled": "true",
"feign.ninca-common.name": "ninca-common",
"ninca.update.floor.pool.allowCoreThreadTimeOut": "true",
"sendRecord.token.appKey": "293e2d708f0143c2957b702cef44d951",
"ninca.update.floor.pool.corePoolSize": "5",
"cloudwalk.access-control.common.device-category-array[0]": "4",
"cloudwalk.access-control.common.device-category-array[5]": "11",
"feign.component-organization.name": "ninca-common-component-organization",
"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds": "10000",
"spring.cloud.consul.discovery.instance-id": "${spring.application.name}-${spring.cloud.client.ipAddress}:${server.port}",
"spring.redis.timeout": "0",
"spring.messages.basename": "access-control",
"spring.shardingsphere.datasource.ds0.type": "com.zaxxer.hikari.HikariDataSource",
"spring.cloud.consul.discovery.register": "true",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.table-strategy.standard.precise-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"cloudwalk.datafield.securityKey": "d4b2aabc97394a12a27fc3cca6cd9ba1",
"cloudwalk.access-control.common.publish-opendoor-service-code": "access-control",
"spring.shardingsphere.datasource.ds0.maximum-pool-size": "20",
"cloudwalk.serial.enable": "true",
"cloudwalk.access-control.common.device-category-array[1]": "5",
"spring.redis.host": "redis_01.redis_ip",
"spring.shardingsphere.datasource.ds0.pool-name": "ds0-pool",
"person.name.space": "recordEvent",
"spring.profiles.active": "access-control",
"management.health.redis.enabled": "false",
"management.health.db.enabled": "false",
"cloudwalk.serial.serial-redis-key": "CLOUDWALK-ACS-SERIAL-KEY",
"spring.application.name": "elevator-app",
"dubbo.protocol.port": "16107",
"spring.shardingsphere.datasource.ds0.driver-class-name": "com.mysql.jdbc.Driver",
"spring.shardingsphere.sharding.binding-tables": "IT_ACS_ELEVATOR_RECORD,IT_ACS_RECOG_RECORD",
"spring.cloud.consul.discovery.prefer-ip-address": "true",
"cloudwalk.event.bootstrap-servers": "371bfca4972c43d2aefcf302d0a4a277:9092,44700995ee904679a7ad5afddcf93bb5:9092,0837a70b5fab47569391828f5feb2561:9092",
"cloudwalk.access-control.common.face-compare-THRESHOLD": "80",
"spring.http.encoding.charset": "UTF-8",
"spring.shardingsphere.datasource.ds0.password": "1qaz!QAZ",
"mybatis.mapper-locations": "classpath*:cn/cloudwalk/elevator/**/*.xml",
"ribbon.ReadTimeout": "10000",
"lockWatchdogTimeout": "21000",
"cloudwalk.elevator.common.relativePrefix": "/cwos-portal/portal/fileManager/imgByPath?path=",
"spring.shardingsphere.props.sql.show": "false",
"intelligent.lock.enable": "true",
"mybatis.config-location": "classpath:mapper/mybatis-config.xml",
"spring.redis.pool.max-idle": "1",
"spring.cloud.consul.host": "10.0.22.102",
"feign.ninca-crk-std.name": "ninca-crk-std",
"cloudwalk.access-control.common.face-capture-interval-milliseconds": "3000",
"spring.redis.pool.max-wait": "10",
"elevator.application.time": "600",
"dubbo.provider.version": "1.0",
"feign.hystrix.enable": "true",
"spring.shardingsphere.datasource.ds0.auto-commit": "true",
"cloudwalk.serial.serial-length": "8",
"spring.mvc.throw-exception-if-no-handler-found": "true",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.executable-class": "cn.cloudwalk.service.ninca.accesscontrol.common.job.executable.AcsRecordStatisticsByDayJob",
"cloudwalk.access-control.common.device-category-array[2]": "7",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.actual-data-nodes": "ds0.IT_ACS_RECOG_RECORD_$->{2020..2030}",
"floor.building.id": "605560539791228928",
"spring.shardingsphere.datasource.ds0.jdbc-url": "jdbc:mysql://mysql_01.mysql_ip:3306/cw-elevator-application?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true",
"feign.mqtt.name": "cloudwalk-device-thirdparty",
"sendRecord.token.corpId": "53db867a8bb747a1bd04dd1afcad8ca6",
"spring.messages.encoding": "utf-8",
"cloudwalk.serial.serial-type": "redis",
"spring.shardingsphere.sharding.default-data-source-name": "ds0",
"cloudwalk.access-control.common.face-capture-time-expired-milliseconds": "300000",
"elevator.application.keyA": "5B7DEF88FF04",
"spring.http.encoding.force": "true",
"spring.redis.pool.max-active": "10",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.priority": "1",
"ninca.update.floor.pool.queueCapacity": "100000",
"ribbon.ConnectTimeout": "10000",
"cloudwalk.access-control.common.device-atrr-map.ACS_FACE_REG_THRESHOLD": "75",
"spring.http.multipart.max-request-size": "200MB",
"logging.config": "classpath:logs/logback.xml",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.group": "ACCESS-CONTROL_GROUP",
"cloudwalk.datafield.encrypt": "AES",
"spring.http.multipart.max-file-size": "200MB",
"dubbo.registry.address": "zookeeper://10.0.22.207:2181",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.table-strategy.standard.precise-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"logging.path": "/data/cwos/cw-elevator-application-V1.0.0.20211103/logs",
"server.port": "16112",
"cloudwalk.access-control.common.device-controller-array[0]": "mqtt",
"spring.cloud.consul.discovery.deregister": "false",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.table-strategy.standard.range-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"cloudwalk.access-control.common.device-category-array[3]": "2",
"spring.shardingsphere.datasource.ds0.minimum-idle": "5",
"spring.shardingsphere.datasource.names": "ds0",
"sendRecord.token.appSecret": "5f6995009b864669b52041b8f5dc4625",
"logging.level.root": "info",
"intelligent.lock.config.default-wait-time": "10000",
"spring.cloud.consul.port": "8500",
"logging.file": "${spring.application.name}",
"ribbon.okhttp.enabled": "true",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.cron-expression": "0 10 0 * * ?",
"feign.davinci-portal.name": "cwos-portal",
"sendRecord.boolean": "true",
"ninca-crk-std.ip": "10.0.22.102:16106",
"spring.mvc.locale": "zh_CN",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.description": "AcsRecordStatisticsByDay job is starting.........",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.table-strategy.standard.range-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"feign.resource.name": "cwos-portal",
"spring.redis.port": "6379",
"cloudwalk.datafield.enable": "true",
"logging.level.cn.cloudwalk": "info",
"cloudwalk.event.group-id": "cw-elevator-application-1",
"cloudwalk.access-control.common.face-capture-open-door-fail-milliseconds": "600000",
"spring.shardingsphere.datasource.ds0.username": "cloudwalk",
"cloudwalk.spring.cache.expires": "CACHE_NAME_APPLICATIONIDS#21600,ACS_DeviceTypesCache#7200,ACS_DeviceTypeFeaturesCache#7200,ACS_DeviceAttrsCache#7200,ACS_RecordStatisticsCache#90000,ACS_AreaTreeCache#60",
"spring.messages.always-use-message-format": "true",
"spring.redis.database": "5",
"spring.shardingsphere.datasource.ds0.max-lifetime": "1765000",
"cloudwalk.access-control.common.device-category-array[4]": "8",
"cloudwalk.access-control.common.publish-opendoor-switch": "false",
"feign.device.name": "cwos-portal",
"feign.cwos-portal.name": "cwos-portal",
"ninca.update.floor.pool.maxPoolSize": "5",
"spring.cloud.consul.enabled": "true",
"sendRecord.ip": "hrec.star-river.com:32165",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.name": "AcsRecordStatisticsByDayJob",
"cloudwalk.event.handler-executor-config.core-pool-size": "10",
"elevator.application.key": "xinghewan",
"ninca.update.floor.pool.keepAliveSeconds": "150",
"spring.redis.pool.min-idle": "0",
"spring.cloud.consul.discovery.ip-address": "${spring.cloud.client.ipAddress}",
"feign.okhttp.enable": "true",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.table-strategy.standard.sharding-column": "RECOGNITION_TIME",
"spring.shardingsphere.datasource.ds0.connection-timeout": "60000",
"cloudwalk.event.handler-executor-config.maximum-pool-size": "30",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.table-strategy.standard.sharding-column": "RECOGNITION_TIME",
"feign.httpclient.enable": "false",
"spring.http.encoding.enabled": "true",
"ribbon.http.client.enabled": "false",
"spring.redis.password": "1qaz!QAZ",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.actual-data-nodes": "ds0.IT_ACS_ELEVATOR_RECORD_$->{2020..2030}",
"server.tomcat.uri-encoding": "UTF-8"
}
}
@@ -0,0 +1,195 @@
{
"tag": "V2.0.4-with-V1-props",
"base_dir": "/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/maven-cw-elevator-application/deploy/v2-maven",
"jar": "/media/zebra/9e8fa357-7db6-4d70-88ed-d5de5a059a663/星河湾星中星/反编译/maven-cw-elevator-application/releases/v2.0.4/cw-elevator-application-2.0.4.jar",
"order": "external>jar",
"file_presence": {
"bootstrap.properties": {
"external": true,
"jar": true
},
"application.properties": {
"external": true,
"jar": true
},
"application-access-control.properties": {
"external": true,
"jar": true
}
},
"focus_keys": {
"spring.cloud.consul.host": {
"value": "371bfca4972c43d2aefcf302d0a4a277",
"source": "external"
},
"spring.cloud.consul.port": {
"value": "8500",
"source": "external"
},
"spring.cloud.consul.discovery.enabled": {
"value": "false",
"source": "external"
},
"spring.cloud.consul.config.enabled": {
"value": "<unset>",
"source": "unset"
},
"feign.cwos-portal.name": {
"value": "cwos-portal",
"source": "external"
},
"feign.ninca-common.name": {
"value": "ninca-common",
"source": "external"
},
"feign.component-organization.name": {
"value": "ninca-common-component-organization",
"source": "external"
},
"cwos-portal.ribbon.NIWSServerListClassName": {
"value": "<unset>",
"source": "unset"
},
"cwos-portal.ribbon.listOfServers": {
"value": "<unset>",
"source": "unset"
}
},
"effective_all_keys": {
"logging.level.root": "info",
"logging.config": "classpath:logs/logback.xml",
"management.health.redis.enabled": "false",
"hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds": "10000",
"cloudwalk.event.handler-executor-config.core-pool-size": "10",
"spring.cloud.consul.discovery.instance-id": "${spring.application.name}-${spring.cloud.client.ipAddress}:${server.port}",
"ninca.update.floor.pool.queueCapacity": "100000",
"person.name.space": "recordEvent",
"spring.redis.pool.max-active": "10",
"spring.cloud.consul.discovery.enabled": "false",
"sendRecord.token.appSecret": "5f6995009b864669b52041b8f5dc4625",
"spring.cloud.consul.enabled": "true",
"ninca.update.floor.pool.maxPoolSize": "5",
"cloudwalk.serial.serial-length": "8",
"server.port": "16112",
"spring.shardingsphere.datasource.names": "ds0",
"spring.redis.password": "1qaz!QAZ",
"elevator.application.key": "xinghewan",
"spring.mvc.throw-exception-if-no-handler-found": "true",
"logging.file": "${spring.application.name}",
"feign.component-organization.name": "ninca-common-component-organization",
"cloudwalk.spring.cache.expires": "CACHE_NAME_APPLICATIONIDS#21600,ACS_DeviceTypesCache#7200,ACS_DeviceTypeFeaturesCache#7200,ACS_DeviceAttrsCache#7200,ACS_RecordStatisticsCache#90000,ACS_AreaTreeCache#60",
"feign.mqtt.name": "cloudwalk-device-thirdparty",
"spring.shardingsphere.datasource.ds0.connection-timeout": "60000",
"ninca.update.floor.pool.keepAliveSeconds": "150",
"feign.cwos-portal.name": "cwos-portal",
"spring.shardingsphere.datasource.ds0.password": "1qaz!QAZ",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.table-strategy.standard.sharding-column": "RECOGNITION_TIME",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.table-strategy.standard.precise-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"floor.building.id": "605560539791228928",
"spring.messages.basename": "access-control",
"spring.cloud.consul.port": "8500",
"ribbon.http.client.enabled": "false",
"sendRecord.ip": "hrec.star-river.com:32165",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.cron-expression": "0 10 0 * * ?",
"sendRecord.token.corpId": "53db867a8bb747a1bd04dd1afcad8ca6",
"cloudwalk.serial.serial-redis-key": "CLOUDWALK-ACS-SERIAL-KEY",
"cloudwalk.datafield.enable": "true",
"elevator.application.time": "600",
"cloudwalk.access-control.common.device-category-array[5]": "11",
"spring.messages.always-use-message-format": "true",
"spring.mvc.locale": "zh_CN",
"feign.ninca-crk-std.name": "ninca-crk-std",
"sendRecord.token.appKey": "293e2d708f0143c2957b702cef44d951",
"ribbon.ConnectTimeout": "10000",
"spring.cloud.consul.discovery.deregister": "false",
"spring.redis.timeout": "0",
"spring.shardingsphere.sharding.default-data-source-name": "ds0",
"spring.redis.database": "5",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.executable-class": "cn.cloudwalk.service.ninca.accesscontrol.common.job.executable.AcsRecordStatisticsByDayJob",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.description": "AcsRecordStatisticsByDay job is starting.........",
"logging.level.cn.cloudwalk": "info",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.priority": "1",
"spring.profiles.active": "access-control",
"spring.http.encoding.force": "true",
"spring.redis.pool.max-wait": "10",
"cloudwalk.access-control.common.device-controller-array[0]": "mqtt",
"cloudwalk.event.group-id": "cw-elevator-application-1",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.table-strategy.standard.precise-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"sendRecord.boolean": "true",
"logging.path": "/data/cwos/cw-elevator-application-V1.0.0.20211103/logs",
"ribbon.okhttp.enabled": "true",
"spring.shardingsphere.datasource.ds0.username": "cloudwalk",
"spring.redis.port": "6379",
"feign.hystrix.enable": "true",
"spring.http.multipart.max-request-size": "200MB",
"feign.device.name": "cwos-portal",
"elevator.application.keyA": "5B7DEF88FF04",
"cloudwalk.datafield.securityKey": "d4b2aabc97394a12a27fc3cca6cd9ba1",
"spring.cloud.consul.discovery.ip-address": "${spring.cloud.client.ipAddress}",
"cloudwalk.access-control.common.device-atrr-map.ACS_FACE_REG_THRESHOLD": "75",
"cloudwalk.access-control.common.face-compare-THRESHOLD": "80",
"cloudwalk.datafield.encrypt": "AES",
"management.health.db.enabled": "false",
"server.tomcat.uri-encoding": "UTF-8",
"spring.shardingsphere.datasource.ds0.max-lifetime": "1765000",
"mybatis.mapper-locations": "classpath*:cn/cloudwalk/elevator/**/*.xml",
"intelligent.lock.config.default-wait-time": "10000",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.table-strategy.standard.sharding-column": "RECOGNITION_TIME",
"ninca.update.floor.pool.corePoolSize": "5",
"spring.http.multipart.max-file-size": "200MB",
"ribbon.ReadTimeout": "10000",
"cloudwalk.access-control.common.device-category-array[2]": "7",
"cloudwalk.access-control.common.publish-opendoor-switch": "false",
"dubbo.provider.version": "1.0",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.actual-data-nodes": "ds0.IT_ACS_ELEVATOR_RECORD_$->{2020..2030}",
"spring.cloud.consul.host": "371bfca4972c43d2aefcf302d0a4a277",
"cloudwalk.access-control.common.face-capture-open-door-fail-milliseconds": "600000",
"cloudwalk.access-control.common.device-category-array[3]": "2",
"feign.davinci-portal.name": "cwos-portal",
"spring.shardingsphere.datasource.ds0.pool-name": "ds0-pool",
"cloudwalk.elevator.common.relativePrefix": "/cwos-portal/portal/fileManager/imgByPath?path=",
"spring.redis.host": "redis_01.redis_ip",
"spring.shardingsphere.props.sql.show": "false",
"spring.shardingsphere.sharding.binding-tables": "IT_ACS_ELEVATOR_RECORD,IT_ACS_RECOG_RECORD",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.table-strategy.standard.range-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"spring.shardingsphere.datasource.ds0.auto-commit": "true",
"spring.messages.encoding": "utf-8",
"spring.redis.pool.min-idle": "0",
"spring.shardingsphere.datasource.ds0.jdbc-url": "jdbc:mysql://mysql_01.mysql_ip:3306/cw-elevator-application?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true",
"spring.application.name": "elevator-app",
"cloudwalk.serial.serial-type": "redis",
"feign.okhttp.enable": "true",
"mybatis.config-location": "classpath:mapper/mybatis-config.xml",
"spring.redis.pool.max-idle": "1",
"cloudwalk.access-control.common.face-capture-interval-milliseconds": "3000",
"cloudwalk.serial.enable": "true",
"spring.cloud.consul.discovery.prefer-ip-address": "true",
"cloudwalk.access-control.common.face-capture-time-expired-milliseconds": "300000",
"dubbo.protocol.port": "16107",
"intelligent.lock.enable": "true",
"lockWatchdogTimeout": "21000",
"spring.shardingsphere.sharding.tables.IT_ACS_RECOG_RECORD.actual-data-nodes": "ds0.IT_ACS_RECOG_RECORD_$->{2020..2030}",
"ninca.update.floor.pool.allowCoreThreadTimeOut": "true",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.group": "ACCESS-CONTROL_GROUP",
"spring.cloud.consul.discovery.register": "true",
"feign.httpclient.enable": "false",
"spring.shardingsphere.datasource.ds0.driver-class-name": "com.mysql.jdbc.Driver",
"spring.http.encoding.charset": "UTF-8",
"ninca-crk-std.ip": "10.0.22.102:16106",
"spring.http.encoding.enabled": "true",
"spring.shardingsphere.sharding.tables.IT_ACS_ELEVATOR_RECORD.table-strategy.standard.range-algorithm-class-name": "cn.cloudwalk.elevator.YearlyShardingAlgorithm",
"cloudwalk.event.handler-executor-config.maximum-pool-size": "30",
"spring.shardingsphere.datasource.ds0.minimum-idle": "5",
"spring.shardingsphere.datasource.ds0.maximum-pool-size": "20",
"cloudwalk.event.bootstrap-servers": "371bfca4972c43d2aefcf302d0a4a277:9092,44700995ee904679a7ad5afddcf93bb5:9092,0837a70b5fab47569391828f5feb2561:9092",
"spring.shardingsphere.datasource.ds0.type": "com.zaxxer.hikari.HikariDataSource",
"dubbo.registry.address": "zookeeper://10.0.22.207:2181",
"feign.ninca-common.name": "ninca-common",
"feign.resource.name": "cwos-portal",
"cloudwalk.access-control.common.device-category-array[4]": "8",
"cloudwalk.access-control.common.device-category-array[0]": "4",
"cloudwalk.access-control.schedual.jobs.AcsRecordStatisticsByDayJob.name": "AcsRecordStatisticsByDayJob",
"cloudwalk.access-control.common.device-category-array[1]": "5",
"cloudwalk.access-control.common.publish-opendoor-service-code": "access-control"
}
}
@@ -0,0 +1,109 @@
# Consul 可访问且「有清单」仍拿不到 IP/端口 — 走查结果(证据执行)
**证据根**[`maven-cw-elevator-application/logs/evidence/`](../../maven-cw-elevator-application/logs/evidence/)
**主日志**[`elevator-app.log`](../../maven-cw-elevator-application/logs/evidence/elevator-app.log)
**配置探针**[`elevator-app-probe.log`](../../maven-cw-elevator-application/logs/evidence/elevator-app-probe.log)
**Consul 快照(示例)**[`elevator-evidence-20260430-113912/consul-health-ninca-common-component-organization.json`](../../maven-cw-elevator-application/logs/evidence/elevator-evidence-20260430-113912/consul-health-ninca-common-component-organization.json)
本文对应走查计划的四项核对:**客户端名**、**Ribbon 初始化时序**、**ConsulServerList vs ConfigurationBased**、**bootstrap 多源合并**。结论与 [`elevator-evidence-v1-v2-diff-20260430.md`](elevator-evidence-v1-v2-diff-20260430.md) §6–§10、[`elevator-service-instance-missing-investigation.md`](elevator-service-instance-missing-investigation.md) 一致并细化到可 grep 的行级证据。
### 本服务是否注册到 Consul、与探针日志
- **拉不到上游 IP** 常见原因是 **Ribbon 客户端名 / listOfServers / 时序**(见下文),**不等价于**本机未注册;但仍应单独核实 **本进程** 在 Consul 的登记名是否与 `spring.application.name` 一致、健康是否 **passing**
- 诊断探针 **默认始终运行**(无 `elevator.*.probe` 开关);Consul HTTP 首次延迟见源码 [`ElevatorProbeConstants`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/elevator/debug/ElevatorProbeConstants.java)。[`ConsulUpstreamHealthProbeRunner`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/elevator/debug/ConsulUpstreamHealthProbeRunner.java) 会请求本服务 **`/v1/health/service/<spring.application.name>`**`passing=true` 与全量各一遍,并 **逐实例** DEBUG)、上游同名列表,以及 **`/v1/agent/self`**。
- [`RibbonLoadBalancerProbeRunner`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/elevator/debug/RibbonLoadBalancerProbeRunner.java) 在同一延迟窗口输出各 client 的 **`ServerList` 实现类**、`ILoadBalancer`、**`DiscoveryClient.getInstances`**(本服务 + `ElevatorUpstreamServiceNames`)明细。
- [`logback.xml`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/resources/logs/logback.xml) 将 **`org.springframework.cloud.consul`**、**`com.netflix.loadbalancer`**、**`org.springframework.cloud.client.discovery`** 与 **`cn.cloudwalk.elevator.debug`** 均按 **DEBUG** **双写**到 **`${logging.file}-probe.log`**(与自建 `consulProbe` / `ribbonProbe` / `discoveryProbe` 及框架行对照)。
---
## 1. 报错栈中的 Ribbon client 名 vs Consul 注册名
**核对方法**:在出错 JVM 日志中搜索 **`Load balancer does not have available server for client:`** 或 **`for client:`**,将后缀字符串与 Consul UI / `/v1/health/service/<name>`**Service** 名 **逐字**比对(含 `ninca-common-` 前缀)。
### 本仓库证据包结论
| 项目 | 结论 |
|------|------|
| `for client:` 在本份 `elevator-app.log` 中 | **仅出现** `ninca-crk-std`(大量重复),**未出现** `component-organization` |
| Feign 逻辑名 `component-organization` | `feign.component-organization.name=ninca-common-component-organization`(探针:`file:``classpath:` 均为该值) |
| Ribbon 实际客户端名 | `Client: ninca-common-component-organization``ConsulServerList{serviceId='ninca-common-component-organization'}` |
| Consul | `ninca-common-component-organization` 健康快照为 **3** 个 passing 实例,与日志中三台 `:17016` 一致 |
**与人对齐时的表述**:若微信群截图写 **`for client: component-organization`**,而本电梯进程配置将 Feign **解析服务名**设为 **`ninca-common-component-organization`**,则二者 **不是** 同一 Ribbon client;对方环境若在 **`component-organization`** 名下查实例会得到 **0 台**,即使 Consul 里注册的是 **`ninca-common-component-organization`**。结论:**先看报错里的精确 client 字符串**,再对 Consul 注册名。
---
## 2. DynamicServerListLoadBalancer 初始化与 `Servers=[]` 时间序
**核对方法**:对关心的 client 搜索 **`DynamicServerListLoadBalancer for client <name> initialized`**,并向上查看同一 client 的 **`current list of Servers=[...]`**;若在列表仍为空窗口内发生首次 Feign 调用,会抛 **no available server**
### `ninca-common-component-organization`Consul 路径)
| 时间(日志) | 事件 |
|--------------|------|
| `11:16:33.087` | `Client: ninca-common-component-organization`,首次 `current list of Servers=[]``ServerList:null` |
| `11:16:33.097` | `DynamicServerListLoadBalancer for client ninca-common-component-organization initialized`,已为 **3 台** `:17016``ConsulServerList{serviceId='ninca-common-component-organization'}` |
**10ms** 内由空列表变为三台;若首次 RPC 落在此窗口仍可能失败(计划中的「首轮请求早于填充」风险)。
### `ninca-crk-std`ConfigurationBased 路径)
| 时间(日志) | 事件 |
|--------------|------|
| `11:16:34.109` | `Client: ninca-crk-std``Servers=[]``ServerList:null` |
| `11:16:34.111` | `DynamicServerListLoadBalancer for client ninca-crk-std initialized`**仍为** `Servers=[]``ServerList:ConfigurationBasedServerList` |
| `11:16:34.346` 起 | 连续 **`no available server for client: ninca-crk-std`** |
本证据包中 **no-server 全部归因于 `ninca-crk-std`**,且发生在 **`ninca-common-component-organization` 已填充三台之后**,说明主因不是「Consul 查错 organization 名」,而是 **`ninca-crk-std` 的静态 Ribbon 列表未配置**(见下节)。
同一全量日志内 **第二次启动**(约 `11:43`)后 `ninca-crk-std` 可出现非空列表,详见 [`elevator-evidence-v1-v2-diff-20260430.md`](elevator-evidence-v1-v2-diff-20260430.md) §6.2。
---
## 3. ConsulServerList 与 ConfigurationBasedServerList`ninca-crk-std` 与 `listOfServers` / `ip`
| 客户端 | ServerList 实现 | 列表来源 |
|--------|-----------------|----------|
| `ninca-common-component-organization` | `ConsulServerList` | Consul `serviceId=ninca-common-component-organization` |
| `ninca-crk-std` | `ConfigurationBasedServerList` | Ribbon 属性(如 `ninca-crk-std.ribbon.listOfServers`),**不**自动使用 `ninca-crk-std.ip` |
代码侧:[`NincaCrkStdRibbonConfiguration`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/ribbon/NincaCrkStdRibbonConfiguration.java) 为 `ninca-crk-std` 固定注册 `ConfigurationBasedServerList`
**探针(`elevator-app-probe.log`):**
- `ninca-crk-std.ribbon.listOfServers value=null`
- `ninca-crk-std.ip=10.0.22.102:16106``file:` / `classpath:` 一致)
因此即 Consul 上 `ninca-crk-std` **passing=3**Ribbon 仍可能 **`Servers=[]`**,与 Consul 是否正常无关,除非另行配置 **`ribbon.listOfServers`** 或改变 ServerList 策略。部署模板对照:V1 legacy 含显式 `ninca-crk-std.ribbon.listOfServers` 段;V2 模板以 `ninca-crk-std.ip` 为主,见 [`deploy/v1-legacy/application.properties`](../../maven-cw-elevator-application/deploy/v1-legacy/application.properties) 与 [`deploy/v2-maven/application.properties`](../../maven-cw-elevator-application/deploy/v2-maven/application.properties)。
---
## 4. `file:./bootstrap` 与 `classpath:/bootstrap` 对 Consul 的合并结果
**来源**[`elevator-app-probe.log`](../../maven-cw-elevator-application/logs/evidence/elevator-app-probe.log) 中 `ConfigSourceProbeRunner` 行。
| 键 | Environment 合并结果 | `file:./bootstrap.properties` | `classpath:/bootstrap.properties` |
|----|------------------------|--------------------------------|-------------------------------------|
| `spring.cloud.consul.host` | `10.0.22.102` | `10.0.22.102` | 主机名(与磁盘不一致) |
| `spring.cloud.consul.discovery.enabled` | `true` | `true` | `false` |
**走查要点**:以 **`spring.application.*` 合并后的 `value=`** 为准核对「进程连的 Consul」是否与运维在浏览器里看的地址一致;磁盘与 jar 内嵌 bootstrap **并存**时,以最终 Environment 为准(本样本下 host 为 **10.0.22.102**、发现 **启用**)。证据目录内亦有 [`bootstrap.properties`](../../maven-cw-elevator-application/logs/evidence/elevator-evidence-20260430-113912/bootstrap.properties) 快照可与现场比对。
---
## 5. 建议的可复现 grep(本地)
```bash
# 锁定所有「for client:」后的客户端名(去重)
grep -E 'for client:' maven-cw-elevator-application/logs/evidence/elevator-app.log | sed -n 's/.*for client: \([^ ]*\).*/\1/p' | sort -u
# 各客户端初始化与非空列表
grep 'DynamicServerListLoadBalancer for client' maven-cw-elevator-application/logs/evidence/elevator-app.log
# 区分 Consul 与配置型列表
grep -E 'ConsulServerList|ConfigurationBasedServerList' maven-cw-elevator-application/logs/evidence/elevator-app.log
```
---
**延伸阅读**[`elevator-v1-v2-init-timing-config-audit.md`](elevator-v1-v2-init-timing-config-audit.md)(初始化顺序与探针)、[`elevator-evidence-v1-v2-diff-20260430.md`](elevator-evidence-v1-v2-diff-20260430.md) §9`listOfServers` vs `ninca-crk-std.ip`)。
@@ -0,0 +1,46 @@
# 从 multiset 差值中扣减「仅 V1 基准包多出」的条目(每行一条坐标或 unresolved:文件名,末尾可选次数,默认 1)。
# 产品线模块保留 2.0-SNAPSHOT,不自降级为 1.0-SNAPSHOT。
cn.cloudwalk.elevator:cw-elevator-application-common:1.0-SNAPSHOT 1
cn.cloudwalk.elevator:cw-elevator-application-data:1.0-SNAPSHOT 1
cn.cloudwalk.elevator:cw-elevator-application-service:1.0-SNAPSHOT 1
cn.cloudwalk.elevator:cw-elevator-application-web:1.0-SNAPSHOT 1
# V1 运行包误入的 Maven/Mojo 构建泄漏(V2 故意不打入)
org.apache.maven.wagon:wagon-provider-api:1.0-beta-2 1
org.apache.maven:maven-artifact-manager:2.0.5 1
org.apache.maven:maven-artifact:2.0.5 1
org.apache.maven:maven-model:2.0.5 1
org.apache.maven:maven-plugin-api:2.0.5 1
org.apache.maven:maven-profile:2.0.5 1
org.apache.maven:maven-project:2.0.5 1
org.apache.maven:maven-repository-metadata:2.0.5 1
org.apache.maven:maven-settings:2.0.5 1
org.codehaus.plexus:plexus-container-default:1.0-alpha-9 1
org.codehaus.plexus:plexus-utils:1.1 1
org.jfrog.jade.plugins.common:jade-plugin-common:1.3.8 1
org.jfrog.maven.annomojo:maven-plugin-anno:1.4.1 1
org.reflections:reflections-maven:0.9.9-RC2 1
# 私服父 POM 不可解析,运行时亦不强制依赖
org.springside:springside-core:4.2.3-GA 1
# V1 嵌套 jar 无 pom.properties,脚本记为 unresolved;与 V2 侧解析坐标不对等时放行
unresolved:annotations-2.0.0.jar 1
unresolved:ant-1.6.5.jar 1
unresolved:ant-apache-bsf-1.9.4.jar 1
unresolved:ant-jakarta-oro-1.6.1.jar 1
unresolved:ant-nodeps-1.8.1.jar 1
unresolved:asm-5.0.3.jar 1
unresolved:asm-analysis-5.0.3.jar 1
unresolved:asm-tree-5.0.3.jar 1
unresolved:asm-util-5.0.3.jar 1
unresolved:bsf-2.4.0.jar 1
unresolved:classworlds-1.1-alpha-2.jar 1
unresolved:feign-core-8.18.0.jar 1
unresolved:feign-okhttp-8.18.0.jar 1
unresolved:hamcrest-core-1.3.jar 1
unresolved:jdom-1.1.2.jar 1
unresolved:junit-4.12.jar 1
unresolved:lombok-1.16.18.jar 1
unresolved:parboiled-core-1.1.7.jar 1
unresolved:parboiled-java-1.1.7.jar 1
unresolved:pegdown-1.6.0.jar 1
unresolved:xpp3-1.1.3.4-RC8.jar 1
unresolved:xstream-1.1.3.jar 1
@@ -0,0 +1,15 @@
# 从 multiset 差值中扣减「仅当前构建多出」的条目。
cn.cloudwalk.elevator:cw-elevator-application-common:2.0-SNAPSHOT 1
cn.cloudwalk.elevator:cw-elevator-application-data:2.0-SNAPSHOT 1
cn.cloudwalk.elevator:cw-elevator-application-service:2.0-SNAPSHOT 1
cn.cloudwalk.elevator:cw-elevator-application-web:2.0-SNAPSHOT 1
com.google.code.findbugs:jsr305:3.0.2 1
io.github.openfeign:feign-okhttp:9.5.0 1
javax.annotation:javax.annotation-api:1.3.2 1
net.bytebuddy:byte-buddy-dep:1.9.6 1
org.hibernate.validator:hibernate-validator:6.0.22.Final 1
org.jctools:jctools-core:2.1.1 1
unresolved:annotations-2.0.1.jar 1
unresolved:asm-7.3.1.jar 1
unresolved:asm-commons-7.0.jar 1
unresolved:lombok-1.16.22.jar 1
@@ -0,0 +1,869 @@
# cw-elevator-application V1 fat-jar 与 V2 fat-jar 依赖差异核对
**生成方式**:脚本 `scripts/generate_v1_v2_elevator_dependency_diff.py`(可重复执行覆盖本文件)。
## 样本路径
- **V1**`cw-elevator-application-V1.0.0.20211103/cw-elevator-application-V1.0.0.20211103.jar`
- **V2**`maven-cw-elevator-application/cw-elevator-application-starter/target/cw-elevator-application-2.0.0.jar`
| 指标 | V1 | V2 |
|------|----|----|
| 嵌套 jar 条目数(lib / BOOT-INF/lib | 269 | 242 |
| 解析出唯一坐标 `groupId:artifactId:version` 数 | 269 | 242 |
| 同名 GA、两侧均有解析且 version 集合不一致(§2.2.1)条数 | — | **4** |
| 与 Maven `dependency:list`runtime)条目数 | — | 242 |
---
## 1. Maven 方式(仅 V2 reactor
`maven-cw-elevator-application` 下执行:`mvn -pl cw-elevator-application-starter -am dependency:list -DincludeScope=runtime -Dsort=true -DoutputFile=target/v2-maven-deps.txt``-am` 时每个子模块写各自的 `target/`**§1.1 使用 starter 模块文件**`cw-elevator-application-starter/target/v2-maven-deps.txt`
**说明**:历史 **V1 运行包** 当前仓库无对应 **1.0** 聚合工程可一键 `dependency:list`V1 的 Maven 坐标视图见 **§2 二进制嵌套 JAR 的 pom.properties**。
### 1.1 V2 `dependency:list` 全量(runtime
| # | groupId | artifactId | version | scope |
|---|---------|--------------|---------|-------|
| 1 | `ch.qos.logback` | `logback-classic` | `1.1.11` | `compile` |
| 2 | `ch.qos.logback` | `logback-core` | `1.1.11` | `compile` |
| 3 | `cn.cloudwalk` | `cloudwalk-device-sdk-protocol-entity` | `2.2.0` | `compile` |
| 4 | `cn.cloudwalk` | `cwos-java-sdk-resource` | `1.0.0-SNAPSHOT` | `compile` |
| 5 | `cn.cloudwalk` | `cwos-portal-interface` | `1.0.0-SNAPSHOT` | `compile` |
| 6 | `cn.cloudwalk.cloud` | `cloudwalk-common-event` | `3.7.2-Brussels-SRX` | `compile` |
| 7 | `cn.cloudwalk.cloud` | `cloudwalk-common-result` | `3.7.2-Brussels-SRX` | `compile` |
| 8 | `cn.cloudwalk.cloud` | `cloudwalk-common-serial` | `3.7.2-Brussels-SRX` | `compile` |
| 9 | `cn.cloudwalk.cloud` | `cloudwalk-common-service` | `3.7.2-Brussels-SRX` | `compile` |
| 10 | `cn.cloudwalk.cloud` | `cloudwalk-common-web` | `3.7.2-Brussels-SRX` | `compile` |
| 11 | `cn.cloudwalk.cloud` | `cloudwalk-device-manager-common` | `2.0.2` | `compile` |
| 12 | `cn.cloudwalk.cloud` | `cloudwalk-device-manager-interface` | `2.0.2` | `compile` |
| 13 | `cn.cloudwalk.cloud` | `cwos-common-aks-interface` | `1.0.0-SNAPSHOT` | `compile` |
| 14 | `cn.cloudwalk.cloud` | `cwos-component-resource-data` | `1.0.0-SNAPSHOT` | `compile` |
| 15 | `cn.cloudwalk.cloud` | `cwos-component-resource-interface` | `1.0.0-SNAPSHOT` | `compile` |
| 16 | `cn.cloudwalk.cloud` | `cwos-device-authentication-interface` | `1.0.0-SNAPSHOT` | `compile` |
| 17 | `cn.cloudwalk.cloud` | `cwos-sdk-event` | `1.5.0-SNAPSHOT` | `compile` |
| 18 | `cn.cloudwalk.elevator` | `cw-elevator-application-common` | `2.0-SNAPSHOT` | `compile` |
| 19 | `cn.cloudwalk.elevator` | `cw-elevator-application-data` | `2.0-SNAPSHOT` | `compile` |
| 20 | `cn.cloudwalk.elevator` | `cw-elevator-application-service` | `2.0-SNAPSHOT` | `compile` |
| 21 | `cn.cloudwalk.elevator` | `cw-elevator-application-web` | `2.0-SNAPSHOT` | `compile` |
| 22 | `cn.cloudwalk.intelligent` | `cloudwalk-intelligent-component-lock` | `1.1.1-SNAPSHOT` | `compile` |
| 23 | `cn.cloudwalk.intelligent` | `davinci-manager-common` | `1.1.7-SNAPSHOT` | `compile` |
| 24 | `cn.cloudwalk.intelligent` | `davinci-manager-storage` | `1.1.7-SNAPSHOT` | `compile` |
| 25 | `cn.cloudwalk.intelligent` | `intelligent-cwoscomponent-interface` | `2.9.2-xinghewan` | `compile` |
| 26 | `cn.cloudwalk.intelligent` | `intelligent-cwoscomponent-rest` | `2.9.2-xinghewan` | `compile` |
| 27 | `com.alibaba` | `fastjson` | `1.2.73` | `compile` |
| 28 | `com.aliyun` | `aliyun-java-sdk-core` | `3.2.8` | `compile` |
| 29 | `com.aliyun` | `aliyun-java-sdk-dysmsapi` | `1.1.0` | `compile` |
| 30 | `com.ecwid.consul` | `consul-api` | `1.3.0` | `compile` |
| 31 | `com.fasterxml` | `classmate` | `1.3.4` | `compile` |
| 32 | `com.fasterxml.jackson.core` | `jackson-annotations` | `2.11.2` | `compile` |
| 33 | `com.fasterxml.jackson.core` | `jackson-core` | `2.11.2` | `compile` |
| 34 | `com.fasterxml.jackson.core` | `jackson-databind` | `2.11.2` | `compile` |
| 35 | `com.fasterxml.jackson.dataformat` | `jackson-dataformat-yaml` | `2.11.2` | `compile` |
| 36 | `com.fasterxml.jackson.datatype` | `jackson-datatype-jsr310` | `2.11.2` | `compile` |
| 37 | `com.fasterxml.jackson.module` | `jackson-module-afterburner` | `2.11.2` | `compile` |
| 38 | `com.github.jsqlparser` | `jsqlparser` | `1.2` | `compile` |
| 39 | `com.github.luben` | `zstd-jni` | `1.4.0-1` | `compile` |
| 40 | `com.github.pagehelper` | `pagehelper` | `5.1.2` | `compile` |
| 41 | `com.github.pagehelper` | `pagehelper-spring-boot-autoconfigure` | `1.2.5` | `compile` |
| 42 | `com.github.virtuald` | `curvesapi` | `1.04` | `compile` |
| 43 | `com.google.code.findbugs` | `annotations` | `2.0.1` | `compile` |
| 44 | `com.google.code.findbugs` | `jsr305` | `3.0.2` | `compile` |
| 45 | `com.google.code.gson` | `gson` | `2.8.5` | `compile` |
| 46 | `com.google.guava` | `guava` | `20.0` | `compile` |
| 47 | `com.google.zxing` | `core` | `3.3.3` | `compile` |
| 48 | `com.netflix.archaius` | `archaius-core` | `0.6.6` | `compile` |
| 49 | `com.netflix.hystrix` | `hystrix-core` | `1.5.12` | `compile` |
| 50 | `com.netflix.hystrix` | `hystrix-javanica` | `1.5.12` | `compile` |
| 51 | `com.netflix.hystrix` | `hystrix-metrics-event-stream` | `1.5.12` | `compile` |
| 52 | `com.netflix.hystrix` | `hystrix-serialization` | `1.5.12` | `runtime` |
| 53 | `com.netflix.netflix-commons` | `netflix-commons-util` | `0.1.1` | `runtime` |
| 54 | `com.netflix.netflix-commons` | `netflix-statistics` | `0.1.1` | `runtime` |
| 55 | `com.netflix.ribbon` | `ribbon` | `2.2.5` | `compile` |
| 56 | `com.netflix.ribbon` | `ribbon-core` | `2.2.5` | `compile` |
| 57 | `com.netflix.ribbon` | `ribbon-httpclient` | `2.2.5` | `compile` |
| 58 | `com.netflix.ribbon` | `ribbon-loadbalancer` | `2.2.5` | `compile` |
| 59 | `com.netflix.ribbon` | `ribbon-transport` | `2.2.5` | `runtime` |
| 60 | `com.netflix.servo` | `servo-core` | `0.10.1` | `runtime` |
| 61 | `com.netflix.servo` | `servo-internal` | `0.10.1` | `runtime` |
| 62 | `com.squareup.okhttp3` | `okhttp` | `3.2.0` | `compile` |
| 63 | `com.squareup.okio` | `okio` | `1.6.0` | `compile` |
| 64 | `com.sun.jersey` | `jersey-client` | `1.19.1` | `runtime` |
| 65 | `com.sun.jersey` | `jersey-core` | `1.19.1` | `runtime` |
| 66 | `com.sun.jersey.contribs` | `jersey-apache-client4` | `1.19.1` | `runtime` |
| 67 | `com.zaxxer` | `HikariCP` | `2.5.1` | `compile` |
| 68 | `commons-codec` | `commons-codec` | `1.10` | `compile` |
| 69 | `commons-collections` | `commons-collections` | `3.2.2` | `runtime` |
| 70 | `commons-configuration` | `commons-configuration` | `1.8` | `compile` |
| 71 | `commons-fileupload` | `commons-fileupload` | `1.3.1` | `compile` |
| 72 | `commons-io` | `commons-io` | `2.5` | `compile` |
| 73 | `commons-lang` | `commons-lang` | `2.6` | `compile` |
| 74 | `commons-logging` | `commons-logging` | `1.2` | `compile` |
| 75 | `de.ruedigermoeller` | `fst` | `2.56` | `compile` |
| 76 | `dom4j` | `dom4j` | `1.6.1` | `compile` |
| 77 | `io.github.openfeign` | `feign-core` | `9.5.0` | `compile` |
| 78 | `io.github.openfeign` | `feign-hystrix` | `9.5.0` | `compile` |
| 79 | `io.github.openfeign` | `feign-okhttp` | `9.5.0` | `compile` |
| 80 | `io.github.openfeign` | `feign-slf4j` | `9.5.0` | `compile` |
| 81 | `io.github.openfeign.form` | `feign-form` | `3.0.3` | `compile` |
| 82 | `io.github.openfeign.form` | `feign-form-spring` | `3.0.3` | `compile` |
| 83 | `io.netty` | `netty-buffer` | `4.1.33.Final` | `compile` |
| 84 | `io.netty` | `netty-codec` | `4.1.33.Final` | `compile` |
| 85 | `io.netty` | `netty-codec-dns` | `4.1.33.Final` | `compile` |
| 86 | `io.netty` | `netty-common` | `4.1.33.Final` | `compile` |
| 87 | `io.netty` | `netty-handler` | `4.1.33.Final` | `compile` |
| 88 | `io.netty` | `netty-resolver` | `4.1.33.Final` | `compile` |
| 89 | `io.netty` | `netty-resolver-dns` | `4.1.33.Final` | `compile` |
| 90 | `io.netty` | `netty-transport` | `4.1.33.Final` | `compile` |
| 91 | `io.projectreactor` | `reactor-core` | `2.0.8.RELEASE` | `compile` |
| 92 | `io.projectreactor` | `reactor-stream` | `2.0.8.RELEASE` | `compile` |
| 93 | `io.reactivex` | `rxjava` | `1.2.0` | `compile` |
| 94 | `io.reactivex` | `rxnetty` | `0.4.9` | `runtime` |
| 95 | `io.reactivex` | `rxnetty-contexts` | `0.4.9` | `runtime` |
| 96 | `io.reactivex` | `rxnetty-servo` | `0.4.9` | `runtime` |
| 97 | `io.reactivex.rxjava2` | `rxjava` | `2.1.13` | `compile` |
| 98 | `javax.activation` | `activation` | `1.1` | `compile` |
| 99 | `javax.annotation` | `javax.annotation-api` | `1.3.2` | `compile` |
| 100 | `javax.cache` | `cache-api` | `1.0.0` | `compile` |
| 101 | `javax.inject` | `javax.inject` | `1` | `runtime` |
| 102 | `javax.mail` | `mail` | `1.4.4` | `compile` |
| 103 | `javax.validation` | `validation-api` | `1.1.0.Final` | `compile` |
| 104 | `javax.ws.rs` | `jsr311-api` | `1.1.1` | `runtime` |
| 105 | `joda-time` | `joda-time` | `2.9.9` | `compile` |
| 106 | `mysql` | `mysql-connector-java` | `5.1.47` | `compile` |
| 107 | `net.bytebuddy` | `byte-buddy` | `1.9.6` | `compile` |
| 108 | `net.bytebuddy` | `byte-buddy-dep` | `1.9.6` | `compile` |
| 109 | `net.coobird` | `thumbnailator` | `0.4.8` | `compile` |
| 110 | `net.lingala.zip4j` | `zip4j` | `2.6.2` | `compile` |
| 111 | `net.sf.ehcache` | `ehcache` | `2.10.5` | `compile` |
| 112 | `net.sf.opencsv` | `opencsv` | `2.3` | `compile` |
| 113 | `org.antlr` | `antlr4-runtime` | `4.7.2` | `compile` |
| 114 | `org.apache.ant` | `ant` | `1.9.6` | `compile` |
| 115 | `org.apache.ant` | `ant-launcher` | `1.9.6` | `compile` |
| 116 | `org.apache.commons` | `commons-collections4` | `4.1` | `compile` |
| 117 | `org.apache.commons` | `commons-compress` | `1.9` | `compile` |
| 118 | `org.apache.commons` | `commons-lang3` | `3.5` | `compile` |
| 119 | `org.apache.commons` | `commons-pool2` | `2.4.3` | `compile` |
| 120 | `org.apache.httpcomponents` | `httpclient` | `4.5.6` | `compile` |
| 121 | `org.apache.httpcomponents` | `httpcore` | `4.4.10` | `compile` |
| 122 | `org.apache.kafka` | `kafka-clients` | `2.3.0` | `compile` |
| 123 | `org.apache.poi` | `poi` | `3.15` | `compile` |
| 124 | `org.apache.poi` | `poi-ooxml` | `3.15` | `compile` |
| 125 | `org.apache.poi` | `poi-ooxml-schemas` | `3.15` | `compile` |
| 126 | `org.apache.shardingsphere` | `encrypt-core-merge` | `4.0.0` | `compile` |
| 127 | `org.apache.shardingsphere` | `encrypt-core-rewrite` | `4.0.0` | `compile` |
| 128 | `org.apache.shardingsphere` | `sharding-core-api` | `4.0.0` | `compile` |
| 129 | `org.apache.shardingsphere` | `sharding-core-common` | `4.0.0` | `compile` |
| 130 | `org.apache.shardingsphere` | `sharding-core-entry` | `4.0.0` | `compile` |
| 131 | `org.apache.shardingsphere` | `sharding-core-execute` | `4.0.0` | `compile` |
| 132 | `org.apache.shardingsphere` | `sharding-core-merge` | `4.0.0` | `compile` |
| 133 | `org.apache.shardingsphere` | `sharding-core-rewrite` | `4.0.0` | `compile` |
| 134 | `org.apache.shardingsphere` | `sharding-core-route` | `4.0.0` | `compile` |
| 135 | `org.apache.shardingsphere` | `sharding-jdbc-core` | `4.0.0` | `compile` |
| 136 | `org.apache.shardingsphere` | `sharding-jdbc-spring-boot-starter` | `4.0.0` | `compile` |
| 137 | `org.apache.shardingsphere` | `sharding-spring-boot-util` | `4.0.0` | `compile` |
| 138 | `org.apache.shardingsphere` | `sharding-transaction-core` | `4.0.0` | `compile` |
| 139 | `org.apache.shardingsphere` | `shardingsphere-execute` | `4.0.0` | `compile` |
| 140 | `org.apache.shardingsphere` | `shardingsphere-merge` | `4.0.0` | `compile` |
| 141 | `org.apache.shardingsphere` | `shardingsphere-rewrite-engine` | `4.0.0` | `compile` |
| 142 | `org.apache.shardingsphere` | `shardingsphere-spi` | `4.0.0` | `compile` |
| 143 | `org.apache.shardingsphere` | `shardingsphere-sql-parser-engine` | `4.0.0` | `compile` |
| 144 | `org.apache.shardingsphere` | `shardingsphere-sql-parser-mysql` | `4.0.0` | `compile` |
| 145 | `org.apache.shardingsphere` | `shardingsphere-sql-parser-oracle` | `4.0.0` | `compile` |
| 146 | `org.apache.shardingsphere` | `shardingsphere-sql-parser-postgresql` | `4.0.0` | `compile` |
| 147 | `org.apache.shardingsphere` | `shardingsphere-sql-parser-relation` | `4.0.0` | `compile` |
| 148 | `org.apache.shardingsphere` | `shardingsphere-sql-parser-spi` | `4.0.0` | `compile` |
| 149 | `org.apache.shardingsphere` | `shardingsphere-sql-parser-sql92` | `4.0.0` | `compile` |
| 150 | `org.apache.shardingsphere` | `shardingsphere-sql-parser-sqlserver` | `4.0.0` | `compile` |
| 151 | `org.apache.tomcat` | `tomcat-annotations-api` | `8.5.34` | `compile` |
| 152 | `org.apache.tomcat` | `tomcat-jdbc` | `8.5.34` | `compile` |
| 153 | `org.apache.tomcat` | `tomcat-juli` | `8.5.34` | `compile` |
| 154 | `org.apache.tomcat.embed` | `tomcat-embed-core` | `8.5.34` | `compile` |
| 155 | `org.apache.tomcat.embed` | `tomcat-embed-el` | `8.5.34` | `compile` |
| 156 | `org.apache.tomcat.embed` | `tomcat-embed-websocket` | `8.5.34` | `compile` |
| 157 | `org.apache.xmlbeans` | `xmlbeans` | `2.6.0` | `compile` |
| 158 | `org.aspectj` | `aspectjweaver` | `1.8.13` | `compile` |
| 159 | `org.bouncycastle` | `bcpkix-jdk15on` | `1.55` | `compile` |
| 160 | `org.bouncycastle` | `bcprov-jdk15on` | `1.55` | `compile` |
| 161 | `org.codehaus.groovy` | `groovy` | `indy` | `2.4.5` |
| 162 | `org.freemarker` | `freemarker` | `2.3.28` | `compile` |
| 163 | `org.hdrhistogram` | `HdrHistogram` | `2.1.9` | `compile` |
| 164 | `org.hibernate` | `hibernate-validator` | `5.3.6.Final` | `compile` |
| 165 | `org.hibernate.validator` | `hibernate-validator` | `6.0.22.Final` | `compile` |
| 166 | `org.javassist` | `javassist` | `3.21.0-GA` | `compile` |
| 167 | `org.jboss.logging` | `jboss-logging` | `3.3.2.Final` | `compile` |
| 168 | `org.jctools` | `jctools-core` | `2.1.1` | `compile` |
| 169 | `org.jodd` | `jodd-bean` | `3.7.1` | `compile` |
| 170 | `org.jodd` | `jodd-core` | `3.7.1` | `compile` |
| 171 | `org.jsoup` | `jsoup` | `1.9.2` | `compile` |
| 172 | `org.jvnet` | `animal-sniffer-annotation` | `1.0` | `compile` |
| 173 | `org.lz4` | `lz4-java` | `1.6.0` | `compile` |
| 174 | `org.mybatis` | `mybatis` | `3.4.6` | `compile` |
| 175 | `org.mybatis` | `mybatis-spring` | `1.3.2` | `compile` |
| 176 | `org.mybatis.spring.boot` | `mybatis-spring-boot-autoconfigure` | `1.3.1` | `compile` |
| 177 | `org.mybatis.spring.boot` | `mybatis-spring-boot-starter` | `1.3.1` | `compile` |
| 178 | `org.objenesis` | `objenesis` | `2.1` | `compile` |
| 179 | `org.ow2.asm` | `asm` | `7.3.1` | `compile` |
| 180 | `org.ow2.asm` | `asm-commons` | `7.0` | `compile` |
| 181 | `org.projectlombok` | `lombok` | `1.16.22` | `compile` |
| 182 | `org.reactivestreams` | `reactive-streams` | `1.0.2` | `compile` |
| 183 | `org.redisson` | `redisson` | `2.15.2` | `compile` |
| 184 | `org.redisson` | `redisson-spring-boot-starter` | `2.15.2` | `compile` |
| 185 | `org.redisson` | `redisson-spring-data-18` | `2.15.2` | `compile` |
| 186 | `org.reflections` | `reflections` | `0.9.9-RC2` | `compile` |
| 187 | `org.slf4j` | `jcl-over-slf4j` | `1.7.25` | `compile` |
| 188 | `org.slf4j` | `jul-to-slf4j` | `1.7.25` | `compile` |
| 189 | `org.slf4j` | `log4j-over-slf4j` | `1.7.25` | `compile` |
| 190 | `org.slf4j` | `slf4j-api` | `1.7.25` | `compile` |
| 191 | `org.springframework` | `spring-aop` | `4.3.29.RELEASE` | `compile` |
| 192 | `org.springframework` | `spring-aspects` | `4.3.29.RELEASE` | `compile` |
| 193 | `org.springframework` | `spring-beans` | `4.3.29.RELEASE` | `compile` |
| 194 | `org.springframework` | `spring-context` | `4.3.29.RELEASE` | `compile` |
| 195 | `org.springframework` | `spring-context-support` | `4.3.29.RELEASE` | `compile` |
| 196 | `org.springframework` | `spring-core` | `4.3.29.RELEASE` | `compile` |
| 197 | `org.springframework` | `spring-expression` | `4.3.29.RELEASE` | `compile` |
| 198 | `org.springframework` | `spring-jdbc` | `4.3.29.RELEASE` | `compile` |
| 199 | `org.springframework` | `spring-oxm` | `4.3.29.RELEASE` | `compile` |
| 200 | `org.springframework` | `spring-tx` | `4.3.29.RELEASE` | `compile` |
| 201 | `org.springframework` | `spring-web` | `4.3.29.RELEASE` | `compile` |
| 202 | `org.springframework` | `spring-webmvc` | `4.3.29.RELEASE` | `compile` |
| 203 | `org.springframework.boot` | `spring-boot` | `1.5.17.RELEASE` | `compile` |
| 204 | `org.springframework.boot` | `spring-boot-actuator` | `1.5.17.RELEASE` | `compile` |
| 205 | `org.springframework.boot` | `spring-boot-autoconfigure` | `1.5.17.RELEASE` | `compile` |
| 206 | `org.springframework.boot` | `spring-boot-starter` | `1.5.17.RELEASE` | `compile` |
| 207 | `org.springframework.boot` | `spring-boot-starter-actuator` | `1.5.17.RELEASE` | `compile` |
| 208 | `org.springframework.boot` | `spring-boot-starter-aop` | `1.5.17.RELEASE` | `compile` |
| 209 | `org.springframework.boot` | `spring-boot-starter-cache` | `1.5.17.RELEASE` | `compile` |
| 210 | `org.springframework.boot` | `spring-boot-starter-data-redis` | `1.5.17.RELEASE` | `compile` |
| 211 | `org.springframework.boot` | `spring-boot-starter-freemarker` | `1.5.17.RELEASE` | `compile` |
| 212 | `org.springframework.boot` | `spring-boot-starter-jdbc` | `1.5.17.RELEASE` | `compile` |
| 213 | `org.springframework.boot` | `spring-boot-starter-logging` | `1.5.17.RELEASE` | `compile` |
| 214 | `org.springframework.boot` | `spring-boot-starter-tomcat` | `1.5.17.RELEASE` | `compile` |
| 215 | `org.springframework.boot` | `spring-boot-starter-web` | `1.5.17.RELEASE` | `compile` |
| 216 | `org.springframework.cloud` | `spring-cloud-commons` | `1.3.5.RELEASE` | `compile` |
| 217 | `org.springframework.cloud` | `spring-cloud-consul-core` | `1.3.5.RELEASE` | `compile` |
| 218 | `org.springframework.cloud` | `spring-cloud-consul-discovery` | `1.3.5.RELEASE` | `compile` |
| 219 | `org.springframework.cloud` | `spring-cloud-context` | `1.3.5.RELEASE` | `compile` |
| 220 | `org.springframework.cloud` | `spring-cloud-netflix-core` | `1.4.6.RELEASE` | `compile` |
| 221 | `org.springframework.cloud` | `spring-cloud-netflix-hystrix-dashboard` | `1.4.6.RELEASE` | `compile` |
| 222 | `org.springframework.cloud` | `spring-cloud-starter` | `1.3.5.RELEASE` | `compile` |
| 223 | `org.springframework.cloud` | `spring-cloud-starter-consul` | `1.3.5.RELEASE` | `compile` |
| 224 | `org.springframework.cloud` | `spring-cloud-starter-consul-discovery` | `1.3.5.RELEASE` | `compile` |
| 225 | `org.springframework.cloud` | `spring-cloud-starter-netflix-archaius` | `1.4.6.RELEASE` | `compile` |
| 226 | `org.springframework.cloud` | `spring-cloud-starter-netflix-hystrix` | `1.4.6.RELEASE` | `compile` |
| 227 | `org.springframework.cloud` | `spring-cloud-starter-netflix-hystrix-dashboard` | `1.4.6.RELEASE` | `compile` |
| 228 | `org.springframework.cloud` | `spring-cloud-starter-netflix-ribbon` | `1.4.6.RELEASE` | `compile` |
| 229 | `org.springframework.cloud` | `spring-cloud-starter-openfeign` | `1.4.6.RELEASE` | `compile` |
| 230 | `org.springframework.cloud` | `spring-cloud-starter-ribbon` | `1.4.6.RELEASE` | `compile` |
| 231 | `org.springframework.data` | `spring-data-commons` | `1.13.16.RELEASE` | `compile` |
| 232 | `org.springframework.data` | `spring-data-keyvalue` | `1.2.16.RELEASE` | `compile` |
| 233 | `org.springframework.data` | `spring-data-redis` | `1.8.16.RELEASE` | `compile` |
| 234 | `org.springframework.security` | `spring-security-crypto` | `4.2.9.RELEASE` | `compile` |
| 235 | `org.springframework.security` | `spring-security-rsa` | `1.0.3.RELEASE` | `compile` |
| 236 | `org.webjars` | `d3js` | `3.4.11` | `compile` |
| 237 | `org.webjars` | `jquery` | `2.1.1` | `compile` |
| 238 | `org.xerial.snappy` | `snappy-java` | `1.1.7.3` | `compile` |
| 239 | `org.yaml` | `snakeyaml` | `1.17` | `compile` |
| 240 | `redis.clients` | `jedis` | `2.9.0` | `compile` |
| 241 | `stax` | `stax-api` | `1.0.1` | `compile` |
| 242 | `xml-apis` | `xml-apis` | `1.4.01` | `compile` |
---
## 2. 二进制方式(嵌套 JAR + pom.properties
- **V1**`lib/*.jar`
- **V2**:自动检测为 `lib/*.jar`(与 spring-boot-maven-plugin 1.3.x + Boot 1.5 一致时为 `lib/`)。
对每个嵌套 jar 读取 `META-INF/maven/**/pom.properties` 得到 `groupId:artifactId:version`;无法读取时记为 `?:?:?`(多为无 Maven 元数据的第三方包)。
### 2.1 仅在 V1 出现的坐标(相对 V2 二进制集合)
**共 41 项**
| groupId:artifactId:version | V1 嵌套路径 |
|------------------------------|-------------|
| `cn.cloudwalk.elevator:cw-elevator-application-common:1.0-SNAPSHOT` | `lib/cw-elevator-application-common-1.0-SNAPSHOT.jar` |
| `cn.cloudwalk.elevator:cw-elevator-application-data:1.0-SNAPSHOT` | `lib/cw-elevator-application-data-1.0-SNAPSHOT.jar` |
| `cn.cloudwalk.elevator:cw-elevator-application-service:1.0-SNAPSHOT` | `lib/cw-elevator-application-service-1.0-SNAPSHOT.jar` |
| `cn.cloudwalk.elevator:cw-elevator-application-web:1.0-SNAPSHOT` | `lib/cw-elevator-application-web-1.0-SNAPSHOT.jar` |
| `org.apache.maven.wagon:wagon-provider-api:1.0-beta-2` | `lib/wagon-provider-api-1.0-beta-2.jar` |
| `org.apache.maven:maven-artifact-manager:2.0.5` | `lib/maven-artifact-manager-2.0.5.jar` |
| `org.apache.maven:maven-artifact:2.0.5` | `lib/maven-artifact-2.0.5.jar` |
| `org.apache.maven:maven-model:2.0.5` | `lib/maven-model-2.0.5.jar` |
| `org.apache.maven:maven-plugin-api:2.0.5` | `lib/maven-plugin-api-2.0.5.jar` |
| `org.apache.maven:maven-profile:2.0.5` | `lib/maven-profile-2.0.5.jar` |
| `org.apache.maven:maven-project:2.0.5` | `lib/maven-project-2.0.5.jar` |
| `org.apache.maven:maven-repository-metadata:2.0.5` | `lib/maven-repository-metadata-2.0.5.jar` |
| `org.apache.maven:maven-settings:2.0.5` | `lib/maven-settings-2.0.5.jar` |
| `org.codehaus.plexus:plexus-container-default:1.0-alpha-9` | `lib/plexus-container-default-1.0-alpha-9.jar` |
| `org.codehaus.plexus:plexus-utils:1.1` | `lib/plexus-utils-1.1.jar` |
| `org.jfrog.jade.plugins.common:jade-plugin-common:1.3.8` | `lib/jade-plugin-common-1.3.8.jar` |
| `org.jfrog.maven.annomojo:maven-plugin-anno:1.4.1` | `lib/maven-plugin-anno-1.4.1.jar` |
| `org.reflections:reflections-maven:0.9.9-RC2` | `lib/reflections-maven-0.9.9-RC2.jar` |
| `org.springside:springside-core:4.2.3-GA` | `lib/springside-core-4.2.3-GA.jar` |
| `unresolved:annotations-2.0.0.jar` | `lib/annotations-2.0.0.jar` |
| `unresolved:ant-1.6.5.jar` | `lib/ant-1.6.5.jar` |
| `unresolved:ant-apache-bsf-1.9.4.jar` | `lib/ant-apache-bsf-1.9.4.jar` |
| `unresolved:ant-jakarta-oro-1.6.1.jar` | `lib/ant-jakarta-oro-1.6.1.jar` |
| `unresolved:ant-nodeps-1.8.1.jar` | `lib/ant-nodeps-1.8.1.jar` |
| `unresolved:asm-5.0.3.jar` | `lib/asm-5.0.3.jar` |
| `unresolved:asm-analysis-5.0.3.jar` | `lib/asm-analysis-5.0.3.jar` |
| `unresolved:asm-tree-5.0.3.jar` | `lib/asm-tree-5.0.3.jar` |
| `unresolved:asm-util-5.0.3.jar` | `lib/asm-util-5.0.3.jar` |
| `unresolved:bsf-2.4.0.jar` | `lib/bsf-2.4.0.jar` |
| `unresolved:classworlds-1.1-alpha-2.jar` | `lib/classworlds-1.1-alpha-2.jar` |
| `unresolved:feign-core-8.18.0.jar` | `lib/feign-core-8.18.0.jar` |
| `unresolved:feign-okhttp-8.18.0.jar` | `lib/feign-okhttp-8.18.0.jar` |
| `unresolved:hamcrest-core-1.3.jar` | `lib/hamcrest-core-1.3.jar` |
| `unresolved:jdom-1.1.2.jar` | `lib/jdom-1.1.2.jar` |
| `unresolved:junit-4.12.jar` | `lib/junit-4.12.jar` |
| `unresolved:lombok-1.16.18.jar` | `lib/lombok-1.16.18.jar` |
| `unresolved:parboiled-core-1.1.7.jar` | `lib/parboiled-core-1.1.7.jar` |
| `unresolved:parboiled-java-1.1.7.jar` | `lib/parboiled-java-1.1.7.jar` |
| `unresolved:pegdown-1.6.0.jar` | `lib/pegdown-1.6.0.jar` |
| `unresolved:xpp3-1.1.3.4-RC8.jar` | `lib/xpp3-1.1.3.4-RC8.jar` |
| `unresolved:xstream-1.1.3.jar` | `lib/xstream-1.1.3.jar` |
### 2.2 仅在 V2 出现的坐标(相对 V1 二进制集合)
**共 14 项**
| groupId:artifactId:version | V2 嵌套路径 |
|------------------------------|-------------|
| `cn.cloudwalk.elevator:cw-elevator-application-common:2.0-SNAPSHOT` | `lib/cw-elevator-application-common-2.0-SNAPSHOT.jar` |
| `cn.cloudwalk.elevator:cw-elevator-application-data:2.0-SNAPSHOT` | `lib/cw-elevator-application-data-2.0-SNAPSHOT.jar` |
| `cn.cloudwalk.elevator:cw-elevator-application-service:2.0-SNAPSHOT` | `lib/cw-elevator-application-service-2.0-SNAPSHOT.jar` |
| `cn.cloudwalk.elevator:cw-elevator-application-web:2.0-SNAPSHOT` | `lib/cw-elevator-application-web-2.0-SNAPSHOT.jar` |
| `com.google.code.findbugs:jsr305:3.0.2` | `lib/jsr305-3.0.2.jar` |
| `io.github.openfeign:feign-okhttp:9.5.0` | `lib/feign-okhttp-9.5.0.jar` |
| `javax.annotation:javax.annotation-api:1.3.2` | `lib/javax.annotation-api-1.3.2.jar` |
| `net.bytebuddy:byte-buddy-dep:1.9.6` | `lib/byte-buddy-dep-1.9.6.jar` |
| `org.hibernate.validator:hibernate-validator:6.0.22.Final` | `lib/hibernate-validator-6.0.22.Final.jar` |
| `org.jctools:jctools-core:2.1.1` | `lib/jctools-core-2.1.1.jar` |
| `unresolved:annotations-2.0.1.jar` | `lib/annotations-2.0.1.jar` |
| `unresolved:asm-7.3.1.jar` | `lib/asm-7.3.1.jar` |
| `unresolved:asm-commons-7.0.jar` | `lib/asm-commons-7.0.jar` |
| `unresolved:lombok-1.16.22.jar` | `lib/lombok-1.16.22.jar` |
### 2.2.1 同名构件(groupId:artifactId)在 V1 与 V2 中的版本集合差异
由嵌套 jar 的 `pom.properties` 聚合:若同一 **GA** 在 V1、V2 中均能解析出版本,且 **version 集合不同**,则单独列出(与 §2.1 / §2.2 中分列的 `g:a:v` 键互为补充)。**不含**仅一侧出现的 GA。
**共 4 项**
| groupId:artifactId | V1 version(s) | V2 version(s) |
|--------------------|---------------|---------------|
| `cn.cloudwalk.elevator:cw-elevator-application-common` | `1.0-SNAPSHOT` | `2.0-SNAPSHOT` |
| `cn.cloudwalk.elevator:cw-elevator-application-data` | `1.0-SNAPSHOT` | `2.0-SNAPSHOT` |
| `cn.cloudwalk.elevator:cw-elevator-application-service` | `1.0-SNAPSHOT` | `2.0-SNAPSHOT` |
| `cn.cloudwalk.elevator:cw-elevator-application-web` | `1.0-SNAPSHOT` | `2.0-SNAPSHOT` |
### 2.3 两边均存在且坐标一致的依赖
**共 228 项**(名称版本完全一致)。
<details>
<summary>展开长表</summary>
| groupId:artifactId:version |
|------------------------------|
| `ch.qos.logback:logback-classic:1.1.11` |
| `ch.qos.logback:logback-core:1.1.11` |
| `cn.cloudwalk.cloud:cloudwalk-common-event:3.7.2-Brussels-SRX` |
| `cn.cloudwalk.cloud:cloudwalk-common-result:3.7.2-Brussels-SRX` |
| `cn.cloudwalk.cloud:cloudwalk-common-serial:3.7.2-Brussels-SRX` |
| `cn.cloudwalk.cloud:cloudwalk-common-service:3.7.2-Brussels-SRX` |
| `cn.cloudwalk.cloud:cloudwalk-common-web:3.7.2-Brussels-SRX` |
| `cn.cloudwalk.cloud:cloudwalk-device-manager-common:2.0.2` |
| `cn.cloudwalk.cloud:cloudwalk-device-manager-interface:2.0.2` |
| `cn.cloudwalk.cloud:cwos-common-aks-interface:1.0.0-SNAPSHOT` |
| `cn.cloudwalk.cloud:cwos-component-resource-data:1.0.0-SNAPSHOT` |
| `cn.cloudwalk.cloud:cwos-component-resource-interface:1.0.0-SNAPSHOT` |
| `cn.cloudwalk.cloud:cwos-device-authentication-interface:1.0.0-SNAPSHOT` |
| `cn.cloudwalk.cloud:cwos-sdk-event:1.5.0-SNAPSHOT` |
| `cn.cloudwalk.intelligent:cloudwalk-intelligent-component-lock:1.1.1-SNAPSHOT` |
| `cn.cloudwalk.intelligent:davinci-manager-common:1.1.7-SNAPSHOT` |
| `cn.cloudwalk.intelligent:davinci-manager-storage:1.1.7-SNAPSHOT` |
| `cn.cloudwalk.intelligent:intelligent-cwoscomponent-interface:2.9.2-xinghewan` |
| `cn.cloudwalk.intelligent:intelligent-cwoscomponent-rest:2.9.2-xinghewan` |
| `cn.cloudwalk:cloudwalk-device-sdk-protocol-entity:2.2.0` |
| `cn.cloudwalk:cwos-java-sdk-resource:1.0.0-SNAPSHOT` |
| `cn.cloudwalk:cwos-portal-interface:1.0.0-SNAPSHOT` |
| `com.alibaba:fastjson:1.2.73` |
| `com.aliyun:aliyun-java-sdk-core:3.2.8` |
| `com.aliyun:aliyun-java-sdk-dysmsapi:1.1.0` |
| `com.fasterxml.jackson.core:jackson-annotations:2.11.2` |
| `com.fasterxml.jackson.core:jackson-core:2.11.2` |
| `com.fasterxml.jackson.core:jackson-databind:2.11.2` |
| `com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.11.2` |
| `com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.11.2` |
| `com.fasterxml.jackson.module:jackson-module-afterburner:2.11.2` |
| `com.fasterxml:classmate:1.3.4` |
| `com.github.jsqlparser:jsqlparser:1.2` |
| `com.github.pagehelper:pagehelper-spring-boot-autoconfigure:1.2.5` |
| `com.github.pagehelper:pagehelper:5.1.2` |
| `com.github.virtuald:curvesapi:1.04` |
| `com.google.code.gson:gson:2.8.5` |
| `com.google.guava:guava:20.0` |
| `com.google.zxing:core:3.3.3` |
| `com.squareup.okhttp3:okhttp:3.2.0` |
| `com.squareup.okio:okio:1.6.0` |
| `com.sun.jersey.contribs:jersey-apache-client4:1.19.1` |
| `com.sun.jersey:jersey-client:1.19.1` |
| `com.sun.jersey:jersey-core:1.19.1` |
| `com.zaxxer:HikariCP:2.5.1` |
| `commons-codec:commons-codec:1.10` |
| `commons-collections:commons-collections:3.2.2` |
| `commons-configuration:commons-configuration:1.8` |
| `commons-fileupload:commons-fileupload:1.3.1` |
| `commons-io:commons-io:2.5` |
| `commons-lang:commons-lang:2.6` |
| `commons-logging:commons-logging:1.2` |
| `de.ruedigermoeller:fst:2.56` |
| `io.github.openfeign.form:feign-form-spring:3.0.3` |
| `io.github.openfeign.form:feign-form:3.0.3` |
| `io.github.openfeign:feign-core:9.5.0` |
| `io.github.openfeign:feign-hystrix:9.5.0` |
| `io.github.openfeign:feign-slf4j:9.5.0` |
| `io.netty:netty-buffer:4.1.33.Final` |
| `io.netty:netty-codec-dns:4.1.33.Final` |
| `io.netty:netty-codec:4.1.33.Final` |
| `io.netty:netty-common:4.1.33.Final` |
| `io.netty:netty-handler:4.1.33.Final` |
| `io.netty:netty-resolver-dns:4.1.33.Final` |
| `io.netty:netty-resolver:4.1.33.Final` |
| `io.netty:netty-transport:4.1.33.Final` |
| `javax.cache:cache-api:1.0.0` |
| `javax.mail:mail:1.4.4` |
| `javax.validation:validation-api:1.1.0.Final` |
| `javax.ws.rs:jsr311-api:1.1.1` |
| `joda-time:joda-time:2.9.9` |
| `net.bytebuddy:byte-buddy:1.9.6` |
| `net.coobird:thumbnailator:0.4.8` |
| `net.lingala.zip4j:zip4j:2.6.2` |
| `net.sf.ehcache:ehcache:2.10.5` |
| `net.sf.opencsv:opencsv:2.3` |
| `org.antlr:antlr4-runtime:4.7.2` |
| `org.apache.commons:commons-collections4:4.1` |
| `org.apache.commons:commons-compress:1.9` |
| `org.apache.commons:commons-lang3:3.5` |
| `org.apache.commons:commons-pool2:2.4.3` |
| `org.apache.httpcomponents:httpclient:4.5.6` |
| `org.apache.httpcomponents:httpcore:4.4.10` |
| `org.apache.shardingsphere:encrypt-core-merge:4.0.0` |
| `org.apache.shardingsphere:encrypt-core-rewrite:4.0.0` |
| `org.apache.shardingsphere:sharding-core-api:4.0.0` |
| `org.apache.shardingsphere:sharding-core-common:4.0.0` |
| `org.apache.shardingsphere:sharding-core-entry:4.0.0` |
| `org.apache.shardingsphere:sharding-core-execute:4.0.0` |
| `org.apache.shardingsphere:sharding-core-merge:4.0.0` |
| `org.apache.shardingsphere:sharding-core-rewrite:4.0.0` |
| `org.apache.shardingsphere:sharding-core-route:4.0.0` |
| `org.apache.shardingsphere:sharding-jdbc-core:4.0.0` |
| `org.apache.shardingsphere:sharding-jdbc-spring-boot-starter:4.0.0` |
| `org.apache.shardingsphere:sharding-spring-boot-util:4.0.0` |
| `org.apache.shardingsphere:sharding-transaction-core:4.0.0` |
| `org.apache.shardingsphere:shardingsphere-execute:4.0.0` |
| `org.apache.shardingsphere:shardingsphere-merge:4.0.0` |
| `org.apache.shardingsphere:shardingsphere-rewrite-engine:4.0.0` |
| `org.apache.shardingsphere:shardingsphere-spi:4.0.0` |
| `org.apache.shardingsphere:shardingsphere-sql-parser-engine:4.0.0` |
| `org.apache.shardingsphere:shardingsphere-sql-parser-mysql:4.0.0` |
| `org.apache.shardingsphere:shardingsphere-sql-parser-oracle:4.0.0` |
| `org.apache.shardingsphere:shardingsphere-sql-parser-postgresql:4.0.0` |
| `org.apache.shardingsphere:shardingsphere-sql-parser-relation:4.0.0` |
| `org.apache.shardingsphere:shardingsphere-sql-parser-spi:4.0.0` |
| `org.apache.shardingsphere:shardingsphere-sql-parser-sql92:4.0.0` |
| `org.apache.shardingsphere:shardingsphere-sql-parser-sqlserver:4.0.0` |
| `org.hdrhistogram:HdrHistogram:2.1.9` |
| `org.hibernate:hibernate-validator:5.3.6.Final` |
| `org.javassist:javassist:3.21.0-GA` |
| `org.jboss.logging:jboss-logging:3.3.2.Final` |
| `org.jsoup:jsoup:1.9.2` |
| `org.jvnet:animal-sniffer-annotation:1.0` |
| `org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:1.3.1` |
| `org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1` |
| `org.mybatis:mybatis-spring:1.3.2` |
| `org.mybatis:mybatis:3.4.6` |
| `org.redisson:redisson-spring-boot-starter:2.15.2` |
| `org.redisson:redisson-spring-data-18:2.15.2` |
| `org.redisson:redisson:2.15.2` |
| `org.reflections:reflections:0.9.9-RC2` |
| `org.slf4j:jcl-over-slf4j:1.7.25` |
| `org.slf4j:jul-to-slf4j:1.7.25` |
| `org.slf4j:log4j-over-slf4j:1.7.25` |
| `org.slf4j:slf4j-api:1.7.25` |
| `org.springframework.boot:spring-boot-actuator:1.5.17.RELEASE` |
| `org.springframework.boot:spring-boot-autoconfigure:1.5.17.RELEASE` |
| `org.springframework.boot:spring-boot-starter-actuator:1.5.17.RELEASE` |
| `org.springframework.boot:spring-boot-starter-aop:1.5.17.RELEASE` |
| `org.springframework.boot:spring-boot-starter-cache:1.5.17.RELEASE` |
| `org.springframework.boot:spring-boot-starter-data-redis:1.5.17.RELEASE` |
| `org.springframework.boot:spring-boot-starter-freemarker:1.5.17.RELEASE` |
| `org.springframework.boot:spring-boot-starter-jdbc:1.5.17.RELEASE` |
| `org.springframework.boot:spring-boot-starter-logging:1.5.17.RELEASE` |
| `org.springframework.boot:spring-boot-starter-tomcat:1.5.17.RELEASE` |
| `org.springframework.boot:spring-boot-starter-web:1.5.17.RELEASE` |
| `org.springframework.boot:spring-boot-starter:1.5.17.RELEASE` |
| `org.springframework.boot:spring-boot:1.5.17.RELEASE` |
| `org.springframework.cloud:spring-cloud-commons:1.3.5.RELEASE` |
| `org.springframework.cloud:spring-cloud-consul-core:1.3.5.RELEASE` |
| `org.springframework.cloud:spring-cloud-consul-discovery:1.3.5.RELEASE` |
| `org.springframework.cloud:spring-cloud-context:1.3.5.RELEASE` |
| `org.springframework.cloud:spring-cloud-netflix-core:1.4.6.RELEASE` |
| `org.springframework.cloud:spring-cloud-netflix-hystrix-dashboard:1.4.6.RELEASE` |
| `org.springframework.cloud:spring-cloud-starter-consul-discovery:1.3.5.RELEASE` |
| `org.springframework.cloud:spring-cloud-starter-consul:1.3.5.RELEASE` |
| `org.springframework.cloud:spring-cloud-starter-netflix-archaius:1.4.6.RELEASE` |
| `org.springframework.cloud:spring-cloud-starter-netflix-hystrix-dashboard:1.4.6.RELEASE` |
| `org.springframework.cloud:spring-cloud-starter-netflix-hystrix:1.4.6.RELEASE` |
| `org.springframework.cloud:spring-cloud-starter-netflix-ribbon:1.4.6.RELEASE` |
| `org.springframework.cloud:spring-cloud-starter-openfeign:1.4.6.RELEASE` |
| `org.springframework.cloud:spring-cloud-starter-ribbon:1.4.6.RELEASE` |
| `org.springframework.cloud:spring-cloud-starter:1.3.5.RELEASE` |
| `org.springframework.data:spring-data-commons:1.13.16.RELEASE` |
| `org.springframework.data:spring-data-keyvalue:1.2.16.RELEASE` |
| `org.springframework.data:spring-data-redis:1.8.16.RELEASE` |
| `org.springframework.security:spring-security-rsa:1.0.3.BUILD-SNAPSHOT` |
| `org.webjars:d3js:3.4.11` |
| `org.webjars:jquery:2.1.1` |
| `org.yaml:snakeyaml:1.17` |
| `redis.clients:jedis:2.9.0` |
| `unresolved:activation-1.1.jar` |
| `unresolved:ant-1.9.6.jar` |
| `unresolved:ant-launcher-1.9.6.jar` |
| `unresolved:archaius-core-0.6.6.jar` |
| `unresolved:aspectjweaver-1.8.13.jar` |
| `unresolved:bcpkix-jdk15on-1.55.jar` |
| `unresolved:bcprov-jdk15on-1.55.jar` |
| `unresolved:consul-api-1.3.0.jar` |
| `unresolved:dom4j-1.6.1.jar` |
| `unresolved:freemarker-2.3.28.jar` |
| `unresolved:groovy-2.4.5-indy.jar` |
| `unresolved:hystrix-core-1.5.12.jar` |
| `unresolved:hystrix-javanica-1.5.12.jar` |
| `unresolved:hystrix-metrics-event-stream-1.5.12.jar` |
| `unresolved:hystrix-serialization-1.5.12.jar` |
| `unresolved:javax.inject-1.jar` |
| `unresolved:jodd-bean-3.7.1.jar` |
| `unresolved:jodd-core-3.7.1.jar` |
| `unresolved:kafka-clients-2.3.0.jar` |
| `unresolved:lz4-java-1.6.0.jar` |
| `unresolved:mysql-connector-java-5.1.47.jar` |
| `unresolved:netflix-commons-util-0.1.1.jar` |
| `unresolved:netflix-statistics-0.1.1.jar` |
| `unresolved:objenesis-2.1.jar` |
| `unresolved:poi-3.15.jar` |
| `unresolved:poi-ooxml-3.15.jar` |
| `unresolved:poi-ooxml-schemas-3.15.jar` |
| `unresolved:reactive-streams-1.0.2.jar` |
| `unresolved:reactor-core-2.0.8.RELEASE.jar` |
| `unresolved:reactor-stream-2.0.8.RELEASE.jar` |
| `unresolved:ribbon-2.2.5.jar` |
| `unresolved:ribbon-core-2.2.5.jar` |
| `unresolved:ribbon-httpclient-2.2.5.jar` |
| `unresolved:ribbon-loadbalancer-2.2.5.jar` |
| `unresolved:ribbon-transport-2.2.5.jar` |
| `unresolved:rxjava-1.2.0.jar` |
| `unresolved:rxjava-2.1.13.jar` |
| `unresolved:rxnetty-0.4.9.jar` |
| `unresolved:rxnetty-contexts-0.4.9.jar` |
| `unresolved:rxnetty-servo-0.4.9.jar` |
| `unresolved:servo-core-0.10.1.jar` |
| `unresolved:servo-internal-0.10.1.jar` |
| `unresolved:snappy-java-1.1.7.3.jar` |
| `unresolved:spring-aop-4.3.29.RELEASE.jar` |
| `unresolved:spring-aspects-4.3.29.RELEASE.jar` |
| `unresolved:spring-beans-4.3.29.RELEASE.jar` |
| `unresolved:spring-context-4.3.29.RELEASE.jar` |
| `unresolved:spring-context-support-4.3.29.RELEASE.jar` |
| `unresolved:spring-core-4.3.29.RELEASE.jar` |
| `unresolved:spring-expression-4.3.29.RELEASE.jar` |
| `unresolved:spring-jdbc-4.3.29.RELEASE.jar` |
| `unresolved:spring-oxm-4.3.29.RELEASE.jar` |
| `unresolved:spring-security-crypto-4.2.9.RELEASE.jar` |
| `unresolved:spring-tx-4.3.29.RELEASE.jar` |
| `unresolved:spring-web-4.3.29.RELEASE.jar` |
| `unresolved:spring-webmvc-4.3.29.RELEASE.jar` |
| `unresolved:stax-api-1.0.1.jar` |
| `unresolved:tomcat-annotations-api-8.5.34.jar` |
| `unresolved:tomcat-embed-core-8.5.34.jar` |
| `unresolved:tomcat-embed-el-8.5.34.jar` |
| `unresolved:tomcat-embed-websocket-8.5.34.jar` |
| `unresolved:tomcat-jdbc-8.5.34.jar` |
| `unresolved:tomcat-juli-8.5.34.jar` |
| `unresolved:xml-apis-1.4.01.jar` |
| `unresolved:xmlbeans-2.6.0.jar` |
| `unresolved:zstd-jni-1.4.0-1.jar` |
</details>
### 2.4 V2 二进制坐标 vs Maven dependency:list
- **版本字符串不一致**:例如 reactor 在 `dependency:list` 中为 **`2.0-SNAPSHOT`**,而 fat-jar 内嵌模块 **`cw-elevator-application-*-2.0.6.jar`** 的 `pom.properties`**`2.0.6`**,字符串比对会视为「仅一侧存在」,属**同名构件不同表述**,非缺失依赖。
- **在 dependency:list 中但不在嵌套 jar 元数据中的**:多为 **仅存在于解析树、与本模块 jar 文件命名不一致**,需对照 §1 表格。
- **未解析 `unresolved:*`**:见 §3,此类条目不参与坐标相等判断。
- **仅在 Maven listruntime**71 项
|坐标|
|----|
| `com.ecwid.consul:consul-api:1.3.0` |
| `com.github.luben:zstd-jni:1.4.0-1` |
| `com.google.code.findbugs:annotations:2.0.1` |
| `com.netflix.archaius:archaius-core:0.6.6` |
| `com.netflix.hystrix:hystrix-core:1.5.12` |
| `com.netflix.hystrix:hystrix-javanica:1.5.12` |
| `com.netflix.hystrix:hystrix-metrics-event-stream:1.5.12` |
| `com.netflix.hystrix:hystrix-serialization:1.5.12` |
| `com.netflix.netflix-commons:netflix-commons-util:0.1.1` |
| `com.netflix.netflix-commons:netflix-statistics:0.1.1` |
| `com.netflix.ribbon:ribbon-core:2.2.5` |
| `com.netflix.ribbon:ribbon-httpclient:2.2.5` |
| `com.netflix.ribbon:ribbon-loadbalancer:2.2.5` |
| `com.netflix.ribbon:ribbon-transport:2.2.5` |
| `com.netflix.ribbon:ribbon:2.2.5` |
| `com.netflix.servo:servo-core:0.10.1` |
| `com.netflix.servo:servo-internal:0.10.1` |
| `dom4j:dom4j:1.6.1` |
| `io.projectreactor:reactor-core:2.0.8.RELEASE` |
| `io.projectreactor:reactor-stream:2.0.8.RELEASE` |
| `io.reactivex.rxjava2:rxjava:2.1.13` |
| `io.reactivex:rxjava:1.2.0` |
| `io.reactivex:rxnetty-contexts:0.4.9` |
| `io.reactivex:rxnetty-servo:0.4.9` |
| `io.reactivex:rxnetty:0.4.9` |
| `javax.activation:activation:1.1` |
| `javax.inject:javax.inject:1` |
| `mysql:mysql-connector-java:5.1.47` |
| `org.apache.ant:ant-launcher:1.9.6` |
| `org.apache.ant:ant:1.9.6` |
| `org.apache.kafka:kafka-clients:2.3.0` |
| `org.apache.poi:poi-ooxml-schemas:3.15` |
| `org.apache.poi:poi-ooxml:3.15` |
| `org.apache.poi:poi:3.15` |
| `org.apache.tomcat.embed:tomcat-embed-core:8.5.34` |
| `org.apache.tomcat.embed:tomcat-embed-el:8.5.34` |
| `org.apache.tomcat.embed:tomcat-embed-websocket:8.5.34` |
| `org.apache.tomcat:tomcat-annotations-api:8.5.34` |
| `org.apache.tomcat:tomcat-jdbc:8.5.34` |
| `org.apache.tomcat:tomcat-juli:8.5.34` |
| `org.apache.xmlbeans:xmlbeans:2.6.0` |
| `org.aspectj:aspectjweaver:1.8.13` |
| `org.bouncycastle:bcpkix-jdk15on:1.55` |
| `org.bouncycastle:bcprov-jdk15on:1.55` |
| `org.codehaus.groovy:groovy:indy` |
| `org.freemarker:freemarker:2.3.28` |
| `org.jodd:jodd-bean:3.7.1` |
| `org.jodd:jodd-core:3.7.1` |
| `org.lz4:lz4-java:1.6.0` |
| `org.objenesis:objenesis:2.1` |
| `org.ow2.asm:asm-commons:7.0` |
| `org.ow2.asm:asm:7.3.1` |
| `org.projectlombok:lombok:1.16.22` |
| `org.reactivestreams:reactive-streams:1.0.2` |
| `org.springframework.security:spring-security-crypto:4.2.9.RELEASE` |
| `org.springframework.security:spring-security-rsa:1.0.3.RELEASE` |
| `org.springframework:spring-aop:4.3.29.RELEASE` |
| `org.springframework:spring-aspects:4.3.29.RELEASE` |
| `org.springframework:spring-beans:4.3.29.RELEASE` |
| `org.springframework:spring-context-support:4.3.29.RELEASE` |
| `org.springframework:spring-context:4.3.29.RELEASE` |
| `org.springframework:spring-core:4.3.29.RELEASE` |
| `org.springframework:spring-expression:4.3.29.RELEASE` |
| `org.springframework:spring-jdbc:4.3.29.RELEASE` |
| `org.springframework:spring-oxm:4.3.29.RELEASE` |
| `org.springframework:spring-tx:4.3.29.RELEASE` |
| `org.springframework:spring-web:4.3.29.RELEASE` |
| `org.springframework:spring-webmvc:4.3.29.RELEASE` |
| `org.xerial.snappy:snappy-java:1.1.7.3` |
| `stax:stax-api:1.0.1` |
| `xml-apis:xml-apis:1.4.01` |
- **仅在二进制坐标集合**:71 项
|坐标|
|----|
| `org.springframework.security:spring-security-rsa:1.0.3.BUILD-SNAPSHOT` |
| `unresolved:activation-1.1.jar` |
| `unresolved:annotations-2.0.1.jar` |
| `unresolved:ant-1.9.6.jar` |
| `unresolved:ant-launcher-1.9.6.jar` |
| `unresolved:archaius-core-0.6.6.jar` |
| `unresolved:asm-7.3.1.jar` |
| `unresolved:asm-commons-7.0.jar` |
| `unresolved:aspectjweaver-1.8.13.jar` |
| `unresolved:bcpkix-jdk15on-1.55.jar` |
| `unresolved:bcprov-jdk15on-1.55.jar` |
| `unresolved:consul-api-1.3.0.jar` |
| `unresolved:dom4j-1.6.1.jar` |
| `unresolved:freemarker-2.3.28.jar` |
| `unresolved:groovy-2.4.5-indy.jar` |
| `unresolved:hystrix-core-1.5.12.jar` |
| `unresolved:hystrix-javanica-1.5.12.jar` |
| `unresolved:hystrix-metrics-event-stream-1.5.12.jar` |
| `unresolved:hystrix-serialization-1.5.12.jar` |
| `unresolved:javax.inject-1.jar` |
| `unresolved:jodd-bean-3.7.1.jar` |
| `unresolved:jodd-core-3.7.1.jar` |
| `unresolved:kafka-clients-2.3.0.jar` |
| `unresolved:lombok-1.16.22.jar` |
| `unresolved:lz4-java-1.6.0.jar` |
| `unresolved:mysql-connector-java-5.1.47.jar` |
| `unresolved:netflix-commons-util-0.1.1.jar` |
| `unresolved:netflix-statistics-0.1.1.jar` |
| `unresolved:objenesis-2.1.jar` |
| `unresolved:poi-3.15.jar` |
| `unresolved:poi-ooxml-3.15.jar` |
| `unresolved:poi-ooxml-schemas-3.15.jar` |
| `unresolved:reactive-streams-1.0.2.jar` |
| `unresolved:reactor-core-2.0.8.RELEASE.jar` |
| `unresolved:reactor-stream-2.0.8.RELEASE.jar` |
| `unresolved:ribbon-2.2.5.jar` |
| `unresolved:ribbon-core-2.2.5.jar` |
| `unresolved:ribbon-httpclient-2.2.5.jar` |
| `unresolved:ribbon-loadbalancer-2.2.5.jar` |
| `unresolved:ribbon-transport-2.2.5.jar` |
| `unresolved:rxjava-1.2.0.jar` |
| `unresolved:rxjava-2.1.13.jar` |
| `unresolved:rxnetty-0.4.9.jar` |
| `unresolved:rxnetty-contexts-0.4.9.jar` |
| `unresolved:rxnetty-servo-0.4.9.jar` |
| `unresolved:servo-core-0.10.1.jar` |
| `unresolved:servo-internal-0.10.1.jar` |
| `unresolved:snappy-java-1.1.7.3.jar` |
| `unresolved:spring-aop-4.3.29.RELEASE.jar` |
| `unresolved:spring-aspects-4.3.29.RELEASE.jar` |
| `unresolved:spring-beans-4.3.29.RELEASE.jar` |
| `unresolved:spring-context-4.3.29.RELEASE.jar` |
| `unresolved:spring-context-support-4.3.29.RELEASE.jar` |
| `unresolved:spring-core-4.3.29.RELEASE.jar` |
| `unresolved:spring-expression-4.3.29.RELEASE.jar` |
| `unresolved:spring-jdbc-4.3.29.RELEASE.jar` |
| `unresolved:spring-oxm-4.3.29.RELEASE.jar` |
| `unresolved:spring-security-crypto-4.2.9.RELEASE.jar` |
| `unresolved:spring-tx-4.3.29.RELEASE.jar` |
| `unresolved:spring-web-4.3.29.RELEASE.jar` |
| `unresolved:spring-webmvc-4.3.29.RELEASE.jar` |
| `unresolved:stax-api-1.0.1.jar` |
| `unresolved:tomcat-annotations-api-8.5.34.jar` |
| `unresolved:tomcat-embed-core-8.5.34.jar` |
| `unresolved:tomcat-embed-el-8.5.34.jar` |
| `unresolved:tomcat-embed-websocket-8.5.34.jar` |
| `unresolved:tomcat-jdbc-8.5.34.jar` |
| `unresolved:tomcat-juli-8.5.34.jar` |
| `unresolved:xml-apis-1.4.01.jar` |
| `unresolved:xmlbeans-2.6.0.jar` |
| `unresolved:zstd-jni-1.4.0-1.jar` |
---
## 3. 无法解析 pom.properties 的嵌套 JAR(仅列文件名)
- **V1** 未解析条目:**88**
- `activation-1.1.jar`
- `annotations-2.0.0.jar`
- `ant-1.6.5.jar`
- `ant-1.9.6.jar`
- `ant-apache-bsf-1.9.4.jar`
- `ant-jakarta-oro-1.6.1.jar`
- `ant-launcher-1.9.6.jar`
- `ant-nodeps-1.8.1.jar`
- `archaius-core-0.6.6.jar`
- `asm-5.0.3.jar`
- `asm-analysis-5.0.3.jar`
- `asm-tree-5.0.3.jar`
- `asm-util-5.0.3.jar`
- `aspectjweaver-1.8.13.jar`
- `bcpkix-jdk15on-1.55.jar`
- `bcprov-jdk15on-1.55.jar`
- `bsf-2.4.0.jar`
- `classworlds-1.1-alpha-2.jar`
- `consul-api-1.3.0.jar`
- `dom4j-1.6.1.jar`
- `feign-core-8.18.0.jar`
- `feign-okhttp-8.18.0.jar`
- `freemarker-2.3.28.jar`
- `groovy-2.4.5-indy.jar`
- `hamcrest-core-1.3.jar`
- `hystrix-core-1.5.12.jar`
- `hystrix-javanica-1.5.12.jar`
- `hystrix-metrics-event-stream-1.5.12.jar`
- `hystrix-serialization-1.5.12.jar`
- `javax.inject-1.jar`
- `jdom-1.1.2.jar`
- `jodd-bean-3.7.1.jar`
- `jodd-core-3.7.1.jar`
- `junit-4.12.jar`
- `kafka-clients-2.3.0.jar`
- `lombok-1.16.18.jar`
- `lz4-java-1.6.0.jar`
- `mysql-connector-java-5.1.47.jar`
- `netflix-commons-util-0.1.1.jar`
- `netflix-statistics-0.1.1.jar`
- `objenesis-2.1.jar`
- `parboiled-core-1.1.7.jar`
- `parboiled-java-1.1.7.jar`
- `pegdown-1.6.0.jar`
- `poi-3.15.jar`
- `poi-ooxml-3.15.jar`
- `poi-ooxml-schemas-3.15.jar`
- `reactive-streams-1.0.2.jar`
- `reactor-core-2.0.8.RELEASE.jar`
- `reactor-stream-2.0.8.RELEASE.jar`
- … 省略 38 条
- **V2** 未解析条目:**70**
- `activation-1.1.jar`
- `annotations-2.0.1.jar`
- `ant-1.9.6.jar`
- `ant-launcher-1.9.6.jar`
- `archaius-core-0.6.6.jar`
- `asm-7.3.1.jar`
- `asm-commons-7.0.jar`
- `aspectjweaver-1.8.13.jar`
- `bcpkix-jdk15on-1.55.jar`
- `bcprov-jdk15on-1.55.jar`
- `consul-api-1.3.0.jar`
- `dom4j-1.6.1.jar`
- `freemarker-2.3.28.jar`
- `groovy-2.4.5-indy.jar`
- `hystrix-core-1.5.12.jar`
- `hystrix-javanica-1.5.12.jar`
- `hystrix-metrics-event-stream-1.5.12.jar`
- `hystrix-serialization-1.5.12.jar`
- `javax.inject-1.jar`
- `jodd-bean-3.7.1.jar`
- `jodd-core-3.7.1.jar`
- `kafka-clients-2.3.0.jar`
- `lombok-1.16.22.jar`
- `lz4-java-1.6.0.jar`
- `mysql-connector-java-5.1.47.jar`
- `netflix-commons-util-0.1.1.jar`
- `netflix-statistics-0.1.1.jar`
- `objenesis-2.1.jar`
- `poi-3.15.jar`
- `poi-ooxml-3.15.jar`
- `poi-ooxml-schemas-3.15.jar`
- `reactive-streams-1.0.2.jar`
- `reactor-core-2.0.8.RELEASE.jar`
- `reactor-stream-2.0.8.RELEASE.jar`
- `ribbon-2.2.5.jar`
- `ribbon-core-2.2.5.jar`
- `ribbon-httpclient-2.2.5.jar`
- `ribbon-loadbalancer-2.2.5.jar`
- `ribbon-transport-2.2.5.jar`
- `rxjava-1.2.0.jar`
- `rxjava-2.1.13.jar`
- `rxnetty-0.4.9.jar`
- `rxnetty-contexts-0.4.9.jar`
- `rxnetty-servo-0.4.9.jar`
- `servo-core-0.10.1.jar`
- `servo-internal-0.10.1.jar`
- `snappy-java-1.1.7.3.jar`
- `spring-aop-4.3.29.RELEASE.jar`
- `spring-aspects-4.3.29.RELEASE.jar`
- `spring-beans-4.3.29.RELEASE.jar`
- … 省略 20 条
@@ -0,0 +1,217 @@
# 电梯生产证据包差异分析(2026-04-30)
**证据根目录**(仓库内):[`maven-cw-elevator-application/logs/evidence/`](../../maven-cw-elevator-application/logs/evidence/)
本文基于 `collect_elevator_runtime_evidence.sh` 现场采集产出的三份时间戳目录,对**制品真实版本**、**本地配置**、**Consul 健康实例**、**日志关键行**与 **jcmd** 作对比。与历史排查主线的关系见 [`elevator-service-instance-missing-investigation.md`](elevator-service-instance-missing-investigation.md)。
---
## 1. 三份目录与「版本指纹」
| 目录 | 采集时间(`collected-at.txt` | `jar-path.txt` 展示名 | `jar.sha256.txt` | `jar-tf.txt` 内模块版本(lib | 说明 |
|------|-------------------------------|------------------------|------------------|--------------------------------|------|
| `elevator-evidence-20260430-112820` | 2026-04-30T11:28:20+0800 | `.../cw-elevator-application-V1.0.0.20211103.jar` | `8da5978a7b34...90544908` | **无**(当次未成功生成 `jar-tf` | 与 113912 **同一 JAR 字节**(见 sha256 |
| `elevator-evidence-20260430-113912` | 2026-04-30T11:39:12+0800 | 同上 | **同上** | 含 `cw-elevator-application-*-**2.0.7**.jar` | 可确认 fat-jar 内为 **Maven 2.0.7 发布结构** |
| `elevator-evidence-20260430-114350` | 2026-04-30T11:43:50+0800 | 同上 | `c087067de3f6...8942054`**不同** | 含 `cw-elevator-application-*-**1.0-SNAPSHOT**.jar` | **第三套制品**:与 113912 非同一文件;内嵌为 **SNAPSHOT 构件** |
**核心结论(勿仅看文件路径名)**
- 三份 `jar-path.txt` 的**文件名**均为历史目录 `cw-elevator-application-V1.0.0.20211103.jar`,但 **112820/113912 与 114350 的 sha256 不同**,说明现场曾**替换过**该路径上的 JAR 或 114350 采自**另一时刻/已换包**。
- **112820 与 113912** 的 sha256 **一致**,不是「V1 代码 vs V2 代码」的两套包,而是**同一物理 JAR 的两次采集**;区别仅在于 113912 多出了 `jar-tf.txt` / `java-version.txt` 等,用于认定模块版本为 **2.0.7**
- **114350** 代表另一制品:**内嵌 1.0-SNAPSHOT**,不得与「正式发布 2.0.7」混为一谈。
**JDK**113912、114350 的 `java-version.txt` 均为 **OpenJDK 1.8.0_41**(路径脚本写死 `/data/cwos/java`)。
---
## 2. 主轴对比:112820 ↔ 113912(同一 JAR、两轮采集)
| 维度 | 112820 | 113912 | 结论 |
|------|--------|--------|------|
| 磁盘 `application.properties` | 内容一致 | 一致 | `diff` **无差异** |
| 磁盘 `bootstrap.properties` | 一致 | 一致 | **无差异** |
| `proc-cmdline.txt` | `java -jar ... cw-elevator-application-V1.0.0.20211103.jar`(含 JDWP | **相同** | **无差异** |
| Consul `/v1/health/service/...?passing=true` | 各服务 **passing 数组长度均为 3** | **相同** | **无差异** |
| `elevator-app.log.keylines.txt` | 与 113912 同一时期的日志摘录 | 内容一致(同一日志切片) | **无实质环境差异** |
**小结**:此轴不宜表述为「V1 与 V2 运行态对比」,应表述为 **同一 2.0.7 制品(sha256 一致)在短时间内的两次证据归档**,第二次补充了 `jar tf` 与 JDK 版本文件。
---
## 3. 主轴对比:113912 ↔ 114350(两套不同 JAR
| 维度 | 113912 | 114350 | 结论 |
|------|--------|--------|------|
| `jar.sha256.txt` | `8da5978a...` | `c087067d...` | **不同文件** |
| fat-jar 内 `lib/cw-elevator-application-*.jar` | `*-2.0.7.jar` | `*-1.0-SNAPSHOT.jar` | **版本线不同** |
| 解压 `jar-application.properties.txt`BOOT-INF 内嵌默认) | `logging.level.*=debug``logging.path=/data/cwos/cw-elevator-application-V1.0.0.20211103/logs` | `logging.level.*=info``logging.path=logs` | **打包内嵌默认配置不同**(与磁盘目录 `application.properties` 可能再叠加覆盖) |
| 磁盘 `application.properties`(采集快照) | 需与 114350 目录单独比对 | | 以各目录下同名文件为准 |
**部署含义**
- **114350** 更符合「本地 Maven reactor **SNAPSHOT** 打出 fat-jar」的内嵌特征(`1.0-SNAPSHOT` + 内嵌 properties 为相对 `logs`)。
- **113912** 更符合「**发布流程 2.0.7**」打入的内嵌与 lib 版本。
若现场长期沿用目录名 `cw-elevator-application-V1.0.0.20211103` 仅替换 JAR,会出现「路径像 V1、内容实为 2.0.7 或 SNAPSHOT」——**必须以 sha256 + `jar tf` 为准**。
---
## 4. jcmd
三份目录的 `jcmd-system-properties.txt` 均为 **Attach 失败**`AttachNotSupportedException: Unable to open socket file`),无法对比进程内最终 system properties。后续现场需满足 JVM attach 条件后再采一次(或使用启动参数导出),否则 Ribbon/Feign 运行态只能依赖日志与磁盘配置。
---
## 5. 日志与 Ribbon 行为(三份 keylines 共性)
**112820 / 113912**`elevator-app.log.keylines.txt` 中可见一致现象(与 [`elevator-service-instance-missing-investigation.md`](elevator-service-instance-missing-investigation.md) 一致):
- **Consul 注册**`elevator-app` 成功注册(带 HTTP health)。
- **配置探针**:磁盘 `./bootstrap.properties``spring.cloud.consul.discovery.enabled=true`classpath 内嵌为 **false**(多源并存)。
- **`ninca-crk-std`**`DynamicServerListLoadBalancer` 使用 **`ConfigurationBasedServerList`**,但 **current list of Servers=[]**,随后出现 **`Load balancer does not have available server for client: ninca-crk-std`**。
- **其他客户端**(如 `cwos-portal``ninca-common`)日志中可见 Consul 解析出的 **3 台**实例。
**差异排查方向**(非本次证据目录两两 diff,而是现象归因):重点核对 **`ninca-crk-std` 的 Ribbon 静态列表 / `NincaCrkStdRibbonConfiguration` 生效路径**与 Consul 列表是否交替覆盖,详见上述 investigation 文档。
**114350**`elevator-app.log.keylines.txt` 与 113912 **文件不完全相同**`diff` 有差异),如需逐行对比可在本地对两份 keylines 执行 `diff -u`
---
## 6. `logs/evidence/elevator-app.log` 全量日志专项排查
**逐项走查(客户端名 / 时序 / Consul vs ConfigurationBased / bootstrap**:见 [`consul-ribbon-no-server-walkthrough.md`](consul-ribbon-no-server-walkthrough.md)。
针对 [`maven-cw-elevator-application/logs/evidence/elevator-app.log`](../../maven-cw-elevator-application/logs/evidence/elevator-app.log) 进行额外统计与时间线复盘:
### 6.1 关键信号统计
- `Load balancer does not have available server for client: ninca-crk-std`**290** 次
- `ConfigurationBasedServerList`**1** 次
- `ConsulServerList`**7** 次
- 探针启动信号(`CONFIG SOURCE PROBE START` / `RIBBON...PROBE` / `CONSUL...PROBE` / `ELEVATOR DIAGNOSTIC PROBES`):仅 **2** 条(其中可见的为 `CONFIG SOURCE PROBE START`
### 6.2 时间线(同一日志内存在两次启动)
1. **第一次启动窗口(11:16**
- `11:16:24` Tomcat 启动、Consul 注册;
- `11:16:24` ConfigSourceProbeRunner 打印:`ninca-crk-std.ribbon.listOfServers value=null``ninca-crk-std.ip=10.0.22.102:16106`
- `11:16:34` `ninca-crk-std` 初始化为 `ConfigurationBasedServerList`,但 `current list of Servers=[]`
- 随后大量出现 `Load balancer does not have available server for client: ninca-crk-std`
2. **第二次启动窗口(11:43**
- `11:43:24` 再次出现 Tomcat 启动与 Consul 注册(说明同一日志内发生过重启);
- `11:43:35` `ninca-crk-std` 初始化时已是 `current list of Servers=[...:16106 x3]`
- 第二次窗口未见与第一次同规模的“空列表 + 连续 no available server”模式。
### 6.3 结合证据包的解释
- `112820` / `113912` 与第一次窗口行为一致,暴露出 `ninca-crk-std` 在该时段未拿到可用服务列表;
- `114350` 对应另一制品(`1.0-SNAPSHOT`)后,日志中出现 `ninca-crk-std` 能初始化出 3 台服务的信号;
- 因三份 Consul 健康快照均显示 `ninca-crk-std` passing=3,可初步排除「Consul 没有实例」这一外因,更可能是客户端侧配置/初始化时序/构件差异导致。
---
## 7. Consul 健康快照
三份目录中下列服务的 **passing 实例数(JSON 数组长度)一致**:均为 **3**`elevator-app``cwos-portal``ninca-common``ninca-common-component-organization``ninca-crk-std``cloudwalk-device-thirdparty`)。
说明:**本次采集窗口内** Consul 侧上游实例数量**未**成为三份包之间的差异变量;与 JVM 内 Ribbon 列表为空等问题需从 **客户端配置与负载均衡初始化顺序** 侧继续查。
---
## 8. 建议的后续动作
1. **命名归档**:在证据目录或工单中显式标注 **JAR sha256****`jar tf``cw-elevator-application-*` 版本**,避免「V1 目录名」误导。
2. **修复 jcmd 采集**:解决 attach 权限 / JVM 参数后重采,补齐 **进程内** `ribbon.*` / `feign.*`
3. **`ninca-crk-std`**:按 investigation 文档与 **下节第 1 条** 优先验证 `ribbon.listOfServers``ninca-crk-std.ip` 的关系。
---
## 9. 综合证据 + 日志 + 多进程后的「下一步方向」
### 9.1 已对齐的事实(减少走弯路)
| 来源 | 结论 |
|------|------|
| 三份 `consul-health-*.json` | 各上游(含 `ninca-crk-std`**passing 均为 3** |
| `ps-ef.txt`(随证据采集) | 各业务为**独立 Java 进程**;`ninca-crk-std` 在目标环境以**单独进程**形式存在(与电梯进程不同) |
| `proc-cmdline.txt` | 电梯进程为 `java -jar`,工作目录下 **`cw-elevator-application-V1.0.0.20211103.jar`**(文件名可与真实字节不一致,须看 sha256) |
| `elevator-app.log` | **同一日志两次启动**:首次 **11:16** `ninca-crk-std` 负载均衡 **Servers=[]**;重启后 **11:43** 同客户端出现 **3 台 :16106**,说明问题偏 **客户端 Ribbon 配置/初始化时序**,而非「现场没有 `ninca-crk-std` 进程」 |
### 9.2 优先验证:Ribbon 静态列表键 ≠ 业务 `ninca-crk-std.ip`
证据包内 **`application.properties`**(及仓库 [`deploy/v2-maven/application.properties`](../../maven-cw-elevator-application/deploy/v2-maven/application.properties))仅有:
- `ninca-crk-std.ip=10.0.22.102:16106`(供业务代码等使用)
而探针行显示:
- `ninca-crk-std.ribbon.listOfServers value=null`
电梯侧对 `ninca-crk-std` 使用 [`NincaCrkStdRibbonConfiguration`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/ribbon/NincaCrkStdRibbonConfiguration.java),其 `ConfigurationBasedServerList` **从 Ribbon 标准配置**(如 `ninca-crk-std.ribbon.listOfServers`)取服务器列表;**与 `ninca-crk-std.ip` 无自动绑定**`ninca-crk-std.ip` 在业务类中如 `AcsElevatorRecordServiceImpl``@Value` 使用)。
对照 [`deploy/v1-legacy/application.properties`](../../maven-cw-elevator-application/deploy/v1-legacy/application.properties) 中显式:
- `ninca-crk-std.ribbon.NIWSServerListClassName=...`
- `ninca-crk-std.ribbon.listOfServers=...`
**建议下一步(配置侧,变更须评审与灰度)**
1. 在**现场**与 **v2 部署模板**中显式增加与现场一致的 **`ninca-crk-std.ribbon.listOfServers`**(可填与日志中负载均衡最终一致的 **三台主机:16106**,或与 Consul 解析一致的主机名列表),使 **首次启动**即不为空;并与 `ninca-crk-std.ip` 的业务语义对齐(同一可达入口集合)。
2. 重启后对照日志:首次出现 `DynamicServerListLoadBalancer for client ninca-crk-std initialized`**`current list of Servers`** 是否直接非空。
### 9.3 观测与采集强化(不改业务契约前提下)
1. **对照 Ribbon / Consul 探针**(当前代码库默认**始终**运行;延迟见 `ElevatorProbeConstants`):在 `*-probe.log` 中查 **ribbonProbe instance**、**consulProbe instance** 行,与 JVM 及 Consul API 对照(见 [`scripts/collect_elevator_runtime_evidence.sh`](../../scripts/collect_elevator_runtime_evidence.sh))。
2. **修复 jcmd Attach**:解决 `jcmd-system-properties.txt` 中的 `AttachNotSupportedException` 后重采,便于核对 **进程内最终** `ribbon.*` / `feign.*`(与磁盘 properties 是否一致)。
### 9.4 仍建议对照的仓库文档
- [`elevator-service-instance-missing-investigation.md`](elevator-service-instance-missing-investigation.md)Ribbon 双路径(Consul vs ConfigurationBased)与现象描述。
- 若调整 `listOfServers`,需在变更说明中记录 **与对外 HTTP/Feign 契约不变**(仅内部路由与配置)。
---
## 10. `elevator-app-probe.log` 同步分析(仓库内样本)
**文件**[`maven-cw-elevator-application/logs/evidence/elevator-app-probe.log`](../../maven-cw-elevator-application/logs/evidence/elevator-app-probe.log)(与主日志同一次启动窗口 **2026-04-30 11:16:24**,仅含 `cn.cloudwalk.elevator.debug` 包输出。)
### 10.1 探针开关(首行汇总)
本证据文件采自 **2026-04-30** 进程;当时摘要行仍描述 **config / ribbon / consul** 三开关。当前仓库实现为:**三类探针默认全开**,调度仅改源码 [`ElevatorProbeConstants`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/elevator/debug/ElevatorProbeConstants.java)**不再**使用 `elevator.*.probe.enabled`
- **`configProbe=true`**`ConfigSourceProbeRunner` 已执行(本文件主体)。
- **`ribbonProbe=false`**:当时未启用 Ribbon 探针属性,故本文件中**无** `ribbonProbe instance` 等行(非当前代码行为)。
- **`consulProbe=false`**:当时未启用 Consul HTTP 探针,故本文件中**无** `consulProbe instance` 等行(非当前代码行为)。
新版进程应在延迟(Consul 约 20s、Ribbon 约 22s)后于 `*-probe.log` 中出现 **consulProbe** / **ribbonProbe** 明细;与 `elevator-app.log` 中 Netflix Ribbon 行交叉验证时**无需**再开属性开关。
### 10.2 配置源冲突(与主日志 / keylines 一致)
| 键 | 合并后 `getProperty` | 并存来源 |
|----|----------------------|----------|
| `spring.cloud.consul.host` | `10.0.22.102` | 磁盘 `file:./bootstrap`**IP**`classpath:/bootstrap`**主机名** |
| `spring.cloud.consul.discovery.enabled` | `true` | 磁盘为 **true**classpath 为 **false**(最终以 Environment 合并结果为准,探针 `value=`**true** |
### 10.3 Ribbon 相关键在 Environment 中的显式值
- `*.ribbon.NIWSServerListClassName`**均为 `null`**(探针未解析到属性文件中的覆盖字符串)。
- `*.ribbon.listOfServers`**均为 `null`**。
- `ninca-crk-std.ip`**`10.0.22.102:16106`**`file:``classpath:` 一致)。
与 [`NincaCrkStdRibbonConfiguration`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/ribbon/NincaCrkStdRibbonConfiguration.java) + 主日志中 **`ConfigurationBasedServerList` 且 Servers=[]** 的现象一并阅读:**Environment 层未出现 `ninca-crk-std.ribbon.listOfServers`**,与「仅靠业务键 `ninca-crk-std.ip`」并存。
### 10.4 小结
| 项目 | 结论 |
|------|------|
| 本文件作用 | 专用 **`elevator-app-probe.log`**,避免在主日志中筛选探针类 |
| 本次样本覆盖范围 | **仅 ConfigSource**(当时未开 Ribbon/Consul 探针);新版本默认可见全量探针 |
| 与排查关系 | 历史样本解释「旧证据缺 Ribbon/Consul 行」;现行构建以 `ElevatorProbeConstants` 为准,深层 Ribbon 行为仍可对照 **`elevator-app.log`** 中 `DynamicServerListLoadBalancer` |
---
**延伸(不改现场属性文件的审核备忘)**[`elevator-v1-v2-init-timing-config-audit.md`](elevator-v1-v2-init-timing-config-audit.md)(初始化时序、探针顺序、jcmd attach、V1/V2 模板对照)。
---
**文档生成说明**:基于仓库内已检入的 `logs/evidence` 快照文件;若现场重新采集,请更新本文件名中的日期或新增一篇并列保留历史结论。
@@ -0,0 +1,114 @@
# 电梯应用「服务实例缺失」排查结论(2026-04-30)
本文档落实排查计划:锁定运行形态、Ribbon ServerList 行为、Consul 健康实例、最小风险修复分支。
## 1. 运行版本与配置目录
### 1.1 仓库内 Maven 验证日志(`maven-cw-elevator-application/logs/elevator-app.log`
- **Tomcat 端口**`18081`(与 `deploy/README.md`**v2-maven** 并行对拍端口一致)。
- **Profile**`access-control`
- **Kafka**`192.168.3.12:9092`(本地验证栈)。
- **结论**:该日志对应 **本机/验证环境** 启动的 **Maven 构建版 V2 JAR**(非生产星中心 V1 目录),用于 API 对拍或本地联调。
### 1.2 生产侧采集证据(`artifacts/elevator-evidence-20260430-000038/`
- **JAR**`星中心/cw-elevator-application-V1.0.0.20211103/cw-elevator-application-V1.0.0.20211103.jar`V1 fat-jar)。
- **`start.sh`**`java -jar cw-elevator-application-V1.0.0.20211103.jar`**未**附加 `--spring.config.location`
- **`bootstrap.properties`(现场快照)**`spring.cloud.consul.discovery.enabled=false`Consul host 为 **主机名**(与发布包内 IP 形式不同)。
- **`application.properties`(现场快照)**:含 `feign.*.name`、业务参数、`ninca-crk-std.ip`**未见** `ninca-crk-std.ribbon.listOfServers`(与 [`deploy/v1-legacy/application.properties`](../../maven-cw-elevator-application/deploy/v1-legacy/application.properties) 中显式 Ribbon 静态段不一致时,行为依赖 JAR 版本与配置合并)。
**结论**:排查时需区分 **(A) 本仓库 Maven V2 + deploy/v2-maven** 与 **(B) 星中心 V1 fat-jar + 同目录配置**,二者 Consul/Ribbon 生效路径不同;勿混用日志归因。
---
## 2. `ninca-crk-std` 的 Ribbon ServerList 是否稳定
### 2.1 日志统计(同一 `elevator-app.log`
| 模式 | 日志特征 | 次数(近似) |
|------|-----------|----------------|
| Consul 发现 | `ServerList:ConsulServerList{serviceId='ninca-crk-std'` | **19** |
| 配置型列表 | 后续行出现 `ServerList:com.netflix.loadbalancer.ConfigurationBasedServerList@…`,且实例列表含静态地址(如 `10.128.161.95:16106` | **多条**`ConfigurationBasedServerList@` 在全日志约 **66** 处,含换行续行;并非全部为同一客户端,但 `ninca-crk-std` 存在两种初始化交替) |
### 2.2 代码与配置依据
- [`NincaCrkStdRibbonConfiguration`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/ribbon/NincaCrkStdRibbonConfiguration.java) 强制使用 `ConfigurationBasedServerList`,注释说明用于避免 Consul 返回空列表时覆盖静态 `listOfServers`
- **事实**:日志仍出现 **`ConsulServerList`**,说明在部分生命周期/上下文刷新路径下,负载均衡仍会按 **Consul** 解析;**不稳定**,与「仅静态 Ribbon」预期不完全一致。
### 2.3 次要现象(同一日志)
- 即使走 `ConfigurationBasedServerList` 且实例为 `10.128.161.95:16106`,仍可能出现 **`Connection refused`**(对端未监听或网络不通),与「无实例」不同,需区分。
---
## 3. Consul 侧是否存在依赖服务实例(验证环境实测)
**`http://192.168.3.12:8500`**(仓库 `deploy` 文档中的本地 Consul)执行:
`GET /v1/health/service/<service>?passing=true`
| 服务名 | 结果 |
|--------|------|
| `cwos-portal` | `[]` |
| `ninca-common` | `[]` |
| `ninca-common-component-organization` | `[]` |
| `ninca-crk-std` | `[]` |
| `elevator-app` | **有** passing 实例(摘录响应中含 `elevator-app` 注册信息) |
**结论**:当前验证用 Consul 上 **四个上游均无健康实例**。若应用侧 **`spring.cloud.consul.discovery.enabled=true`**(早期发布包曾在 `bootstrap` 中如此配置;当前基线见 [`deploy/v2-maven/bootstrap.properties`](../../maven-cw-elevator-application/deploy/v2-maven/bootstrap.properties)),Ribbon 走 **`ConsulServerList`** 时会出现 **`Load balancer does not have available server`**,这与实测一致。
生产环境请在 **目标 Consul 地址**上重复上述 HTTP 检查([`scripts/collect_elevator_runtime_evidence.sh`](../../scripts/collect_elevator_runtime_evidence.sh) 已内置相同请求)。
---
## 4. 最小风险修复分支(二选一)
### 分支 A:禁用 Consul 客户端发现 + 静态 Ribbon(与 `deploy/v1-legacy`、较新发布包中对齐)
1. 设置 **`spring.cloud.consul.discovery.enabled=false`**(仍可保留 `consul.enabled=true` 用于配置中心等其他用途,以现场为准)。
2.**`application.properties`**(与 JAR 同目录或 Consul KV,以实际生效源为准)为各 Feign 客户端补充 **`*.ribbon.NIWSServerListClassName=com.netflix.loadbalancer.ConfigurationBasedServerList`** 与 **`*.ribbon.listOfServers=host:port`**(至少覆盖:`cwos-portal``ninca-common``ninca-common-component-organization``ninca-crk-std`)。
3. **`ninca-crk-std`**:与 [`deploy/v1-legacy/application.properties`](../../maven-cw-elevator-application/deploy/v1-legacy/application.properties) 一致,配置 `ninca-crk-std.ribbon.*``ninca-crk-std.ip`Maven V2 已含 `NincaCrkStdRibbonConfiguration`,仍需保证 **静态列表属性**在运行期可见。
4. 配置来源探针 **默认已运行**[`ConfigSourceProbeRunner`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/elevator/debug/ConfigSourceProbeRunner.java));在 `*-probe.log` 核对 `*.ribbon.listOfServers` 的最终来源(无需再设 `elevator.config.probe.enabled`)。
### 分支 B:启用 Consul 服务发现
1. 保持 **`spring.cloud.consul.discovery.enabled=true`**。
2.**同一 Consul** 上确保四个服务 **注册成功且健康检查 passing**;服务名须与 `feign.*.name` 一致(如 `cwos-portal``ninca-common` 等)。
3. **不要求**静态 `listOfServers`;若仍报错,用 Consul UI/API 核对实例与健康检查脚本。
### 版本选择提示
- **较早的发布包(如 v2.0.1v2.0.3**`bootstrap` 中曾 **`discovery.enabled=true`**,在无上游注册的环境下更易触发本问题。
- **v2.0.4 及以后发布包****`discovery.enabled=false`**,与「静态 Ribbon」分支一致。
### `deploy/v2-maven/run.sh` 注意
当前 [`run.sh`](../../maven-cw-elevator-application/deploy/v2-maven/run.sh) 仅 **`java -jar`**,不注入 `file:./application.properties`。若未通过 Consul KV 提供 Ribbon 键,则依赖 JAR 内默认配置 —— 本地「仅 Consul、无上游」时仍会失败。验证/对拍时请确保 **外置 `application.properties` 与 JAR 同目录****显式 `--spring.config.location=...`**(以团队约定为准)。
---
## 5. 建议的只读复核命令(现场)
1. **进程与 JAR**`ps -ef | grep cw-elevator-application`;确认 **工作目录**与 **JAR 文件名**V1 vs V2)。
2. **Consul**`curl -s "http://<consul>:8500/v1/health/service/<feign服务名>?passing=true"`
3. **日志关键字**`ConsulServerList``ConfigurationBasedServerList``Load balancer does not have available server`
---
## 6. 一次性评估:应用内探针与对照方式
以下均在 **`cn.cloudwalk.elevator.debug`** 包内输出(WARN 用于异常路径),并 **双写** 主日志与 **`*-probe.log`**(见 `logs/logback.xml`);**默认始终启用**,调度见源码 **`ElevatorProbeConstants`**(不再使用 `elevator.*.probe.enabled`)。**Spring Cloud Consul**、**Netflix loadbalancer**、**Discovery** 相关 logger 在 `logback.xml` 中按 **DEBUG** 双写到 `*-probe.log`(与 `cn.cloudwalk.elevator.debug` 一致)。
| 探针 | 作用 | 与其他探针对照 |
|------|------|----------------|
| `ConfigSourceProbeRunner` | 启动期打印 Consul/Feign/Ribbon 关键键的 **value****PropertySource** 命中链 | 确认 `discovery.enabled``*.ribbon.listOfServers` 是否被 KV/本地覆盖 |
| `RibbonLoadBalancerProbeRunner` | 延迟后打印各 Ribbon 客户端 **实例级 host/port****`serverCount`** | **Consul passing=0 且此处也为 0**:多为静态配置未生效或未调用;**Consul>0 此处仍 0**:重点查 `NIWSServerListClassName` / 懒加载 |
| `ConsulUpstreamHealthProbeRunner` | 延迟 HTTP:**本服务**与上游 **`/v1/health/service/...`** **逐实例**endpoint、checks 摘要)、**`/v1/agent/self`** | 与上一行 **交叉验证**:区分「注册侧无实例」与「应用侧 Ribbon 未吃到地址」 |
启动时会打一行 **`ELEVATOR DIAGNOSTIC PROBES always on`** 汇总。进程外仍建议配合 [`scripts/collect_elevator_runtime_evidence.sh`](../../scripts/collect_elevator_runtime_evidence.sh) 做完整证据包。
**一次性阅读顺序**`*-probe.log` 中先 **CONFIG SOURCE** →(延迟后)**CONSUL** → **RIBBON**,再对照主日志中的业务异常时间线。
---
**文档维护**:若发行包 `bootstrap``run.sh` 再变更,请同步更新第 4 节与「版本选择提示」。
@@ -0,0 +1,71 @@
# 电梯 V1 / V2:初始化时序与配置审核备忘(不改现场属性文件)
**约束**:本文档仅做**代码与模板对照**、**启动与探针时序**说明;**不修改**现场 `bootstrap.properties` / `application.properties`
**关联**:证据与日志结论见 [`elevator-evidence-v1-v2-diff-20260430.md`](elevator-evidence-v1-v2-diff-20260430.md)Ribbon 现象见 [`elevator-service-instance-missing-investigation.md`](elevator-service-instance-missing-investigation.md)。
---
## 1. 仓库内「V1 模板」与「V2 模板」指代
| 指代 | 路径 | 用途 |
|------|------|------|
| V1 部署参考 | [`deploy/v1-legacy/application.properties`](../../maven-cw-elevator-application/deploy/v1-legacy/application.properties) | 同目录 fat-jar、Consul 发现关闭场景下的 **显式** `ninca-crk-std.ribbon.listOfServers` 示例 |
| V2 部署参考 | [`deploy/v2-maven/application.properties`](../../maven-cw-elevator-application/deploy/v2-maven/application.properties)、[`bootstrap.properties`](../../maven-cw-elevator-application/deploy/v2-maven/bootstrap.properties) | 当前 Maven 发布包拷贝来源;**含** `ninca-crk-std.ip`**默认不含** `ninca-crk-std.ribbon.listOfServers`(与 V1 示例段不同) |
现场实际生效属性以**磁盘文件 + Consul KV + 内嵌 classpath** 合并为准;证据包中探针已打印多源并存现象。
---
## 2. 应用入口与 Ribbon 绑定(代码层,与属性文件无关)
> **基线更新**v2.0.17 已清理 `@RibbonClient` 和 `NincaCrkStdRibbonConfiguration`Ribbon 配置完全通过 `application.properties` 控制。下文为 v2.0.16 之前的状态,保留供参考。
- 入口(当前):[`AppApplication`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/elevator/AppApplication.java)
-`@RibbonClient`/`@RibbonClients` 注解。
- 入口(历史 v2.0.16 前):`ElevatorApplication.java`
- 曾存在 `@RibbonClient(name = "${feign.ninca-crk-std.name:ninca-crk-std}", configuration = NincaCrkStdRibbonConfiguration.class)`
- `ninca-crk-std` 配置(历史):`NincaCrkStdRibbonConfiguration.java`(已删除)
- 使用 **`ConfigurationBasedServerList`**`initWithNiwsConfig`**Ribbon 约定键**(如 `ninca-crk-std.ribbon.listOfServers`)取列表。
- 业务键 **`ninca-crk-std.ip`**(如 `AcsElevatorRecordServiceImpl`**不自动写入** Ribbon ServerList;二者语义分离。
**审核结论**:在未改属性文件的前提下,若需证明「仅 ip、无 listOfServers」与空列表的因果关系,应依赖**日志中的 ServerList 初始化行** + **ConfigSourceProbe** 已打印的 `ninca-crk-std.ribbon.listOfServers value=null`(证据包已包含)。
---
## 3. 探针与启动时序(已实现的审查手段)
以下组件**默认均启用**(无 `elevator.*.probe` 开关);延迟秒数见 [`ElevatorProbeConstants`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/elevator/debug/ElevatorProbeConstants.java)。顺序由 Spring `@Order` / `ApplicationRunner` / `ApplicationListener` 决定:
| 组件 | 触发时机 | 顺序要点 |
|------|-----------|----------|
| [`ElevatorProbeSummaryRunner`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/elevator/debug/ElevatorProbeSummaryRunner.java) | `ApplicationRunner` | `@Order(HIGHEST_PRECEDENCE)`:最先一批 Runner |
| [`ConfigSourceProbeRunner`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/elevator/debug/ConfigSourceProbeRunner.java) | `ApplicationRunner` | 默认顺序;打印 **file vs classpath** 的配置源 |
| [`RibbonLoadBalancerProbeRunner`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/elevator/debug/RibbonLoadBalancerProbeRunner.java) | `ContextRefreshedEvent` | `@Order(LOWEST_PRECEDENCE)` + **延迟** `RIBBON_LOAD_BALANCER_PROBE_DELAY_SECONDS` |
| [`ConsulUpstreamHealthProbeRunner`](../../maven-cw-elevator-application/cw-elevator-application-starter/src/main/java/cn/cloudwalk/elevator/debug/ConsulUpstreamHealthProbeRunner.java) | 同上 | **延迟** `CONSUL_HTTP_PROBE_DELAY_SECONDS`(先于 Ribbon 数秒,减少日志交错) |
**审核结论**ConfigSource 探针回答「**合并后的 Environment 里键值与来源**」;Ribbon/Consul 探针回答「**延迟若干秒后**负载均衡与 Consul HTTP 是否一致」。与「首次请求才创建 LoadBalancer」的懒加载配合时,**日志时间戳**比单次启动瞬间的配置快照更能说明时序问题(见全量 `elevator-app.log` 中 11:16 vs 11:43 两次启动)。
---
## 4. jcmd attach 失败时的排查动作(不改属性)
采集脚本已输出 **`jcmd-attach-diagnose.txt`**(进程用户、`/tmp/hsperfdata_*`、cmdline 中与 attach 相关的 token)。常见修复:
1. **与 Java 进程同一用户**执行 `jcmd`(例如进程属 `cwos` 而当前为 `root` 时:`sudo -u cwos /data/cwos/java/bin/jcmd <PID> VM.system_properties`)。
2. 检查 **`/tmp/hsperfdata_<user>/<pid>`** 是否存在、权限是否正常。
3. 确认启动参数中是否包含 **`-XX:+DisableAttachMechanism`**(若有则需调整 **启动脚本/JVM 参数**,不属于应用 properties)。
4. JDWP`-Xdebug` / `-Xrunjdwp`)一般**不**单独阻断 attach;仍以用户与 hsperfdata 为主因居多。
---
## 5. 下一步「仅从审核角度」的建议清单(不写回属性文件)
1. 对照**本次证据包**与全量日志:确认 `ninca-crk-std` 首次出现 **`ConfigurationBasedServerList` + Servers=[]** 的线程与时间,是否与首次 Feign 调用/懒加载一致。
2. 对照 **V1 legacy 模板**与 **v2-maven 模板**中 **`ninca-crk-std.ribbon.*` 段的差异**,形成变更评审材料(**实施与否由现场窗口决定**,本文不修改文件)。
3. 复采证据时带上 **`jcmd-attach-diagnose.txt`** 与成功时的 **`jcmd-system-properties.txt`**,补齐进程内 `ribbon.*` 最终值。
4. 短时开启 **Ribbon / Consul 探针**(仅运行时开关,不改磁盘 properties 内容亦可由运维在启动命令注入 `-D`)用于一次性对照——若政策禁止任何参数变更,则仅依赖现有日志与 Consul JSON。
---
**文档性质**:研发侧审核备忘;不作为未经评审的生产变更指令。
@@ -0,0 +1,19 @@
release-visitor-noauth-verify-v20260430/
├── README.md
├── 操作手册.md
├── 执行流程设计-简化版.md
├── 打包说明.txt
├── MANIFEST.txt
├── python/
│ ├── quick_verify_visitor_floor_policy.py
│ ├── requirements.txt
│ └── requirements-min.txt
├── report/
│ └── .gitkeep
└── sql/
├── 黄平访客ID手工查询.sql
├── 租户访客策略基线核查.sql
├── 批量样本筛选-多公司多部门.sql
├── 人工核查最终楼层结果.sql
├── 标准批量25访客-执行后核验.sql
└── batch_cases.csv
@@ -0,0 +1,105 @@
# 访客无鉴权策略验证发布包(v20260430)
## 1. 发布目标
本目录为“黄平访问蒙海文”无鉴权策略验证的**版本化发布包**,用于生产执行、结果留痕与归档。
当前对应代码发布版本:`cw-elevator-application-2.0.9`
## 2. 包内文件
- `README.md`:发布说明(本文件)
- `操作手册.md`:完整操作步骤与判定规则
- `执行流程设计-简化版.md`:先明确流程再执行的最小闭环方案(推荐先读)
- `sql/黄平访客ID手工查询.sql`:生产手工查询黄平访客 ID 的 SQL
- `sql/批量样本筛选-多公司多部门.sql`:筛选多个公司/多个部门被访人样本 SQL
- `sql/人工核查最终楼层结果.sql`:自定义访客 ID 集合时执行后核验
- `sql/标准批量25访客-执行后核验.sql`:§4.0 单行命令固定 25 名访客号段后的执行后核验
- `python/quick_verify_visitor_floor_policy.py`:执行脚本快照(支持纯 HTTP;可选连组织库/电梯库)
- `python/requirements.txt``requests` + `pymysql`(预置样本拉取、`--verify-local-db`
- `python/requirements-min.txt`:仅 `requests`(不连库时)
- `report/`:脚本输出 JSON 汇总(打包时排除 `*.json` 历史文件)
- `打包说明.txt`:生产机 `pip install`、一键 zip、全量预置命令示例
- `MANIFEST.txt`:交付清单
## 3. 关键基线参数
- 被访人(蒙海文)`personId=964454497399468032`
- 访客(黄平)`personId=1102270499947507712`
- 租户 `businessId=2524639890ba4f2cba9ba1a4eeaa4015`
- 策略语义(**规范**):未传 **`floorIds`** 时,生效楼层为 **`PersonService.detail``floorList`**;租户策略须已在组织 **`detail`** 中以 **`allow_zone_ids` 替代**写入(**非** ∩)。详见 [`visitor-registration-business-flow.md`](../visitor-registration-business-flow.md)、[`租户组织人员访客-数据模型与用例.md`](../../architecture/租户组织人员访客-数据模型与用例.md)、[`2026-05-06` 规格](../../superpowers/specs/2026-05-06-tenant-visitor-policy-organization-implementation.md)。
## 4. 测试执行(一行命令)
以下参数已由交付侧与现场环境对齐:**组织** `http://10.0.22.207:8089`**电梯** `http://10.0.22.207:16112`**25 名测试访客** `personId` 为连续号段 `9199000100000000001``9199000100000000025`(预置脚本内置 25 个被访人样本,本命令**不访问 MySQL**)。
**操作:** 打开解压后的发布包目录(能看到子目录 `python/`),**只粘贴下面整行**,回车执行(自动安装缺失的 `requests` 并跑预置 25 人批量无鉴权探测):
```bash
python3 -m pip install -q -r python/requirements-min.txt && python3 python/quick_verify_visitor_floor_policy.py --mode noauth-probe --org-base-url "http://10.0.22.207:8089" --elevator-base-url "http://10.0.22.207:16112" --use-preset-cases --visitor-person-ids "$(python3 -c 'print(",".join(str(9199000100000000000+i) for i in range(1,26)))')" --probe-with-businessid --batch-output-summary "batch-preset-static-$(date +%Y%m%d-%H%M%S).json"
```
汇总 JSON`report/` 目录下文件名形如 `batch-preset-static-<时间戳>.json`
**执行后须查库分析:** 在目标环境 **`cw-elevator-application`** 库运行 `sql/标准批量25访客-执行后核验.sql`,将每名访客的 **`active_row_count``zone_id`** 与 JSON 中的 `derived.floor_count``derived.floors` 对齐;具体操作与判定要点见 **`操作手册.md` §4.0.1、§4.6**。
---
### 附录 A:单样本(广发基金基线)
```bash
python3 python/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--business-id "2524639890ba4f2cba9ba1a4eeaa4015" \
--meng-person-id "964454497399468032" \
--visitor-person-id "1102270499947507712" \
--probe-with-businessid
```
该访客为存量人员:库表核验易与历史 `image_rule_ref` 混在一起;若以「本轮新增访客 + 证据」为目标,请以 **§4 一行批量号段 `919900…`** 为主。**操作手册 §4.2** 对上述边界有全文说明。
### 附录 B:连 MySQL 拉样本 / 库表比对
需与 HTTP 同属一套库的地址与账号由运维另行提供,不由本 README 承载;禁止使用与目标环境不一致的数据库串联验证。
### 附录 C`sql/batch_cases.csv` 批量
```bash
python3 python/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--batch-input-csv "sql/batch_cases.csv" \
--visitor-person-ids "1102270499947507712,1102270499947507713,1102270499947507714" \
--visitor-names "黄志平A,黄志平B,黄志平C" \
--probe-with-businessid \
--batch-output-summary "batch-from-csv-$(date +%Y%m%d-%H%M%S).json"
```
### 附录 D:人员导出 CSV 自动筛选
```bash
python3 python/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--batch-source-person-csv "../_cw_is_person__202604302030.csv" \
--exclude-business-ids "2524639890ba4f2cba9ba1a4eeaa4015" \
--sample-companies 3 \
--sample-persons-per-company 2 \
--visitor-person-ids "1102270499947507712,1102270499947507713,1102270499947507714" \
--visitor-names "黄志平A,黄志平B,黄志平C" \
--probe-with-businessid \
--batch-output-summary "batch-from-export-$(date +%Y%m%d-%H%M%S).json"
```
说明:导出 CSV 需含列 `BUSINESS_ID`,`ID`,`IS_DEL`,`NAME`(等);无部门列时汇总中 `department` 可能为空。
## 5. 输出位置
脚本输出(均在发布包下 `report/` 目录):
- 单样本:`quick-verify-<timestamp>.json`
- 标准批量:见 §4`batch-preset-static-*.json`
- 其他批量:`--batch-output-summary` 指定名;默认 `batch-summary.json`
@@ -0,0 +1,2 @@
# 仅调用组织/电梯 HTTP,不连 MySQL
requests>=2.28.0,<3
@@ -0,0 +1,5 @@
# 生产验证机:Python 3.8+
# 仅 HTTP 探测:pip install -r requirements-min.txt
requests>=2.28.0,<3
# 可选(--fetch-preset-from-org-db / --verify-local-db
pymysql>=1.0.0,<2
@@ -0,0 +1,4 @@
business_id,meng_person_id,company,department
2524639890ba4f2cba9ba1a4eeaa4015,964454497399468032,广发基金,示例部门A
replace-business-id-2,replace-person-id-2,示例公司2,示例部门B
replace-business-id-3,replace-person-id-3,示例公司3,示例部门C
1 business_id meng_person_id company department
2 2524639890ba4f2cba9ba1a4eeaa4015 964454497399468032 广发基金 示例部门A
3 replace-business-id-2 replace-person-id-2 示例公司2 示例部门B
4 replace-business-id-3 replace-person-id-3 示例公司3 示例部门C
@@ -0,0 +1,49 @@
-- 用途:脚本执行后,人工核查访客最终楼层权限
-- 说明:
-- * 「已授权楼层」= image_rule_ref 中 person_delete = 0 的行(与 passRule/image 可查到的楼层一致)
-- * person_delete = 1 为撤销/作废,不参与当前授权
-- 将 IN (...) 中的访客 person_id 替换为本次执行的访客集合
-- 主查:仅已授权楼层(推荐与接口 / JSON derived.floors 对拍)
SELECT
irr.person_id,
irr.business_id,
irr.zone_id,
irr.zone_name,
irr.last_update_time
FROM `cw-elevator-application`.`image_rule_ref` irr
WHERE irr.person_id IN (
'1102270499947507712'
-- ,'替换为其他访客personId'
)
AND irr.person_delete = 0
ORDER BY irr.person_id, irr.zone_id;
-- 明细(含已撤销历史行,核对 person_delete / 时间线时用)
SELECT
irr.person_id,
irr.business_id,
irr.zone_id,
irr.zone_name,
irr.person_delete,
irr.create_time,
irr.last_update_time
FROM `cw-elevator-application`.`image_rule_ref` irr
WHERE irr.person_id IN (
'1102270499947507712'
-- ,'替换为其他访客personId'
)
ORDER BY irr.person_id, irr.last_update_time DESC, irr.zone_id;
-- 可选:统计每个访客当前「已授权」楼层数量(person_delete = 0
SELECT
irr.person_id,
COUNT(1) AS floor_count
FROM `cw-elevator-application`.`image_rule_ref` irr
WHERE irr.person_id IN (
'1102270499947507712'
-- ,'替换为其他访客personId'
)
AND irr.person_delete = 0
GROUP BY irr.person_id
ORDER BY irr.person_id;
@@ -0,0 +1,35 @@
-- 用途:从组织库筛选“多个公司 + 多个部门”的被访人样本
-- MySQL:连接主机/端口/账号按**当前环境**填写(开发与生产分离;不要用开发库导出的样本去打生产)
--
-- 已与 component-organization 典型结构对齐(2026-04-30 开发库 INFORMATION_SCHEMA 核对):
-- cw_is_person 人员主键列为 ID(无 person_id);删除标记 IS_DEL(无 deleted);
-- 无 labels/business_name/organization_name 列;访客身份通过 cw_is_person_label_ref + cw_is_label 识别。
-- 连接参数可复制 maven-cw-elevator-application/tools/visitor_floor_verification/.env.visitor_verify(勿提交密钥)。
SELECT
p.BUSINESS_ID AS business_id,
p.ID AS meng_person_id,
COALESCE(parent_org.NAME, '') AS company,
COALESCE(o.NAME, '') AS department
FROM `component-organization`.`cw_is_person` p
INNER JOIN `component-organization`.`cw_is_person_organization_ref` r ON r.PERSON_ID = p.ID
LEFT JOIN `component-organization`.`cw_is_organization` o ON o.ID = r.ORG_ID
LEFT JOIN `component-organization`.`cw_is_organization` parent_org ON parent_org.ID = o.PARENT_ID
WHERE (p.IS_DEL = 0 OR p.IS_DEL IS NULL)
AND p.BUSINESS_ID IS NOT NULL
AND p.BUSINESS_ID <> ''
AND NOT EXISTS (
SELECT 1
FROM `component-organization`.`cw_is_person_label_ref` lr
INNER JOIN `component-organization`.`cw_is_label` lb ON lb.ID = lr.LABEL_ID
WHERE lr.PERSON_ID = p.ID
AND lb.BUSINESS_ID = p.BUSINESS_ID
AND lb.NAME = '访客'
)
ORDER BY p.BUSINESS_ID, department, p.LAST_UPDATE_TIME DESC;
-- 建议导出后人工抽样:
-- 1) 至少 3 个 business_id
-- 2) 每个 business_id 至少 2 个不同 department
-- 3) 生成 batch_cases.csv,列头固定为:
-- business_id,meng_person_id,company,department
@@ -0,0 +1,58 @@
-- 用途:`README`/操作手册 §4.0 标准单行批量跑完后,在电梯库核查写库是否与接口侧一致
-- 库:`cw-elevator-application`
-- 表:`image_rule_ref`(访客 person_id 维度楼层规则)
-- 访客清单:与本包约定的 91990001000000000019199000100000000025 完全一致;若现场改用其它 personId,请改下方 expected 子查询或直接用 `sql/人工核查最终楼层结果.sql`。
-- ------------------------------------------------------------------
-- A) 每名访客当前「有效」规则行数 + 最近一次更新时间(核对 JSON 里的 floor_count / 时间点)
-- ------------------------------------------------------------------
SELECT
e.visitor_person_id,
SUM(CASE WHEN irr.person_delete = 0 THEN 1 ELSE 0 END) AS active_row_count,
MAX(CASE WHEN irr.person_delete = 0 THEN irr.last_update_time END) AS latest_active_update_ms
FROM (
SELECT '9199000100000000001' AS visitor_person_id
UNION ALL SELECT '9199000100000000002'
UNION ALL SELECT '9199000100000000003'
UNION ALL SELECT '9199000100000000004'
UNION ALL SELECT '9199000100000000005'
UNION ALL SELECT '9199000100000000006'
UNION ALL SELECT '9199000100000000007'
UNION ALL SELECT '9199000100000000008'
UNION ALL SELECT '9199000100000000009'
UNION ALL SELECT '9199000100000000010'
UNION ALL SELECT '9199000100000000011'
UNION ALL SELECT '9199000100000000012'
UNION ALL SELECT '9199000100000000013'
UNION ALL SELECT '9199000100000000014'
UNION ALL SELECT '9199000100000000015'
UNION ALL SELECT '9199000100000000016'
UNION ALL SELECT '9199000100000000017'
UNION ALL SELECT '9199000100000000018'
UNION ALL SELECT '9199000100000000019'
UNION ALL SELECT '9199000100000000020'
UNION ALL SELECT '9199000100000000021'
UNION ALL SELECT '9199000100000000022'
UNION ALL SELECT '9199000100000000023'
UNION ALL SELECT '9199000100000000024'
UNION ALL SELECT '9199000100000000025'
) e
LEFT JOIN `cw-elevator-application`.`image_rule_ref` irr
ON irr.person_id = e.visitor_person_id
GROUP BY e.visitor_person_id
ORDER BY e.visitor_person_id;
-- ------------------------------------------------------------------
-- B) 有效规则明细(与报告 `derived.floors` 比对 zone_id;按人+时间排序)
-- ------------------------------------------------------------------
SELECT
irr.person_id,
irr.zone_id,
irr.zone_name,
irr.person_delete,
irr.business_id,
irr.create_time,
irr.last_update_time
FROM `cw-elevator-application`.`image_rule_ref` irr
WHERE irr.person_id BETWEEN '9199000100000000001' AND '9199000100000000025'
ORDER BY irr.person_id, irr.last_update_time DESC, irr.zone_id;
@@ -0,0 +1,43 @@
-- 租户访客楼层策略最小核查 SQL(执行前确认数据库实例为电梯业务库)
-- 目标租户:广发基金 business_id = 2524639890ba4f2cba9ba1a4eeaa4015
-- 1) 表结构与索引确认
SHOW CREATE TABLE tenant_visitor_floor_policy;
-- 2) 广发租户策略主检查
SELECT id,
business_id,
policy_type,
allow_zone_ids,
building_id,
enabled,
policy_version,
updated_at,
remark
FROM tenant_visitor_floor_policy
WHERE business_id = '2524639890ba4f2cba9ba1a4eeaa4015'
ORDER BY updated_at DESC, policy_version DESC;
-- 3) 同租户是否存在多条默认策略(building_id 为空)
SELECT business_id, COUNT(*) AS cnt
FROM tenant_visitor_floor_policy
WHERE business_id = '2524639890ba4f2cba9ba1a4eeaa4015'
AND (building_id IS NULL OR building_id = '')
GROUP BY business_id
HAVING COUNT(*) > 1;
-- 4) enabled 与 policy_type 分布
SELECT policy_type, enabled, COUNT(*) AS cnt
FROM tenant_visitor_floor_policy
WHERE business_id = '2524639890ba4f2cba9ba1a4eeaa4015'
GROUP BY policy_type, enabled
ORDER BY cnt DESC;
-- 5) allow_zone_ids 是否包含 28F zone_id
SELECT id, allow_zone_ids
FROM tenant_visitor_floor_policy
WHERE business_id = '2524639890ba4f2cba9ba1a4eeaa4015'
AND enabled = 1
AND policy_type = 'INTERSECT_ALLOWLIST'
AND allow_zone_ids LIKE '%605560545117995008%';
@@ -0,0 +1,18 @@
-- 访客:黄平(手机号 13926442944)手工查询 SQL
-- 已确认库表:component-organization.cw_is_person
SELECT
person_id,
name,
mobile,
business_id,
labels,
deleted,
create_time,
update_time
FROM `component-organization`.`cw_is_person`
WHERE business_id = '2524639890ba4f2cba9ba1a4eeaa4015'
AND name = '黄平'
AND mobile = '13926442944'
ORDER BY update_time DESC;
@@ -0,0 +1,31 @@
发布包目录(源码内):
docs/testing/release-visitor-noauth-verify-v20260430
一、测试执行(单行,与 README「4」一致;在解压后的发布包根目录执行,须有子目录 python/)
python3 -m pip install -q -r python/requirements-min.txt && python3 python/quick_verify_visitor_floor_policy.py --mode noauth-probe --org-base-url "http://10.0.22.207:8089" --elevator-base-url "http://10.0.22.207:16112" --use-preset-cases --visitor-person-ids "$(python3 -c 'print(",".join(str(9199000100000000000+i) for i in range(1,26)))')" --probe-with-businessid --batch-output-summary "batch-preset-static-$(date +%Y%m%d-%H%M%S).json"
二、一键打包(在仓库根「源码」目录执行,排除本地 report 里的 JSON 痕迹与 __pycache__
STAMP=$(date +%Y%m%d-%H%M%S)
OUT="docs/testing/release-visitor-noauth-verify-v20260430-prod-${STAMP}.zip"
zip -r "$OUT" docs/testing/release-visitor-noauth-verify-v20260430 \
-x 'docs/testing/release-visitor-noauth-verify-v20260430/report/*.json' \
-x '*.pyc' -x '*__pycache__*' -x '*.pyo'
unzip -l "$OUT" | tail -5
echo "written: $OUT"
三、解压到测试机后的目录示例
mkdir -p ~/visitor-noauth-verify && cd ~/visitor-noauth-verify
unzip -q release-visitor-noauth-verify-v20260430-prod-*.zip
cd docs/testing/release-visitor-noauth-verify-v20260430
(在此目录执行上文「一行命令」)
四、打包前自检
1) python/quick_verify_visitor_floor_policy.py、requirements*.txt 存在
2) sql/、README.md 与交付地址/访客号段约定一致
3) MANIFEST.txt 与目录一致
五、选配:连 MySQL 等参数由运维另表提供,不写死于此文件;勿用开发与目标不一致的库串联 HTTP。
@@ -0,0 +1,90 @@
# 访客楼层策略验证执行流程(简化版)
## 1. 目标
按固定顺序完成两组验证,并输出汇总结果:
1. **基线组(广发基金)**:新增“黄平访客 -> 被访人蒙海文(`personId=964454497399468032`)”,再查询该访客楼层权限;
2. **对照组(其他公司多样本)**:从数据库筛选多个公司/多个部门被访人,分别新增“黄志平访客”,再查询各自楼层权限;
3. 最终输出“每个样本是否成功、楼层数量与楼层清单”。
> 说明:本流程强调顺序和可复核性,不再依赖复杂自动推断。
## 2. 统一原则
- 只以 `personId` 作为最终查询键,不以姓名直接判定权限。
- 姓名查询仅用于“定位候选人”,不用于最终业务判定。
- 判定顺序固定:**先写(add/visitor),再读(passRule/image**。
## 3. 执行总流程(必须按顺序)
### 步骤A:准备参数与样本
- 访客固定:黄平/黄志平(按现场实际确认对应 `visitorPersonId`
- 先准备两类样本:
- 样本1(广发基金基线):`businessId=252463...`,被访人 `964454497399468032`
- 样本2(多公司多部门对照):在**与目标验证环境一致**的组织库/MySQL 上筛选多个公司和部门被访人(禁止使用开发库数据去打生产接口)
### 步骤B:执行样本1(广发基金基线)
1.`add/visitor` 新增访客;
2. 紧接着调 `passRule/image` 查询楼层;
3. 记录基线组结果(期望仅 `28F`,若策略开启)。
### 步骤C:执行样本2(多公司多部门)
对每个被访人样本重复:
1.`add/visitor` 新增“黄志平访客”;
2.`passRule/image` 查询该访客楼层;
3. 记录结果到汇总表。
### 步骤D:输出总结果
按样本输出字段:
- 公司
- 部门
- 被访人 `personId`
- 访客 `personId`
- `add/visitor` 结果码
- 楼层数量
- 楼层清单
## 4. 异常分流(必须遵守)
### 4.1 add/visitor 失败(任何样本)
结论:该样本不具备“策略生效验证条件”。
动作:
1. 查同时间窗口服务日志;
2. 定位具体失败点(远程超时、依赖服务不可用、SQL异常等);
3. 修复后仅重跑失败样本。
### 4.2 add/visitor 成功但楼层不符
动作:
1. 查策略读取日志(`policyDecision``allowFloorSize``effectiveFloorSize`);
2. 查策略表配置是否匹配租户;
3.`image_rule_ref` 当前 `person_delete=0` 记录是否包含历史残留。
## 5. 为什么采用该顺序
- 先做广发基金基线,可快速判断策略主路径是否正常;
- 再做多公司多部门对照,可评估是否存在租户间差异或历史规则干扰;
- 最后统一汇总,避免单条日志或单个样本误导结论。
## 6. 推荐命令模板(单样本)
```bash
python3 python/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--business-id "2524639890ba4f2cba9ba1a4eeaa4015" \
--meng-person-id "964454497399468032" \
--visitor-person-id "1102270499947507712" \
--probe-with-businessid
```
> 多样本场景建议外层脚本循环调用本命令,并将结果JSON汇总为一张表。
@@ -0,0 +1,194 @@
# 访客无鉴权策略验证-操作手册(发布版)
## 1. 适用范围
- 目标:验证无鉴权模式下访客接口是否可调用,以及“黄平访问蒙海文”是否触发策略。
- 环境:生产环境(建议低峰时段执行)。
- 对应版本:`cw-elevator-application-2.0.9`
- 建议先读:`执行流程设计-简化版.md`(先定流程,再执行)
## 2. 前置条件
1. Python 3.8+
2. **推荐(与 §4.0 一致)**`python3 -m pip install -r python/requirements-min.txt`(安装 `requests`)。若仅单笔安装亦可:`python3 -m pip install requests`
3. 关键参数确认:
- `businessId=2524639890ba4f2cba9ba1a4eeaa4015`
- `蒙海文personId=964454497399468032`
- `黄平personId=1102270499947507712`
- `黄平姓名=黄平``手机号=13926442944`(仅用于人工核对)
说明:
- 被访者ID参数为 `--meng-person-id`,默认即 `964454497399468032`,可按现场覆盖。
## 3. 手工 SQL(访客 ID 复核)
见:`sql/黄平访客ID手工查询.sql`
## 3.1 策略基线核查 SQL(必须先执行)
见:`sql/租户访客策略基线核查.sql`
重点核验:
- `business_id='2524639890ba4f2cba9ba1a4eeaa4015'`
- `policy_type='INTERSECT_ALLOWLIST'`
- `enabled=1`
- `allow_zone_ids` 包含 `605560545117995008`28F
- 同租户 `building_id` 为空的默认策略仅 1 条
- 策略语义(**规范**):启用策略时 **`allow_zone_ids` 在组织 `detail` 以「替代」写入 `floorList`**;电梯 **`addVisitor`** 仅透传 **`detail.floorList`**UC-01)或请求 **`floorIds`**UC-02),**不与 allow 求交**。失效场景以 **`76260531`** 等为准(历史 **`76260532`** 交集失败路径已废止)。详见 [`visitor-registration-business-flow.md`](../visitor-registration-business-flow.md)、[`租户组织人员访客-数据模型与用例.md`](../../architecture/租户组织人员访客-数据模型与用例.md)。
## 3.2 多公司多部门样本筛选 SQL(第二步)
见:`sql/批量样本筛选-多公司多部门.sql`
筛选结果请保存为 `sql/batch_cases.csv`,列头要求:
`business_id,meng_person_id,company,department`
## 4. 执行步骤
### 4.0 标准预置 25 人批量(推荐,单行命令)
在发布包根目录(见 4.1)下**复制整行**执行即可(与 `README.md` §4 相同;不写占位符:组织/电梯 URL 与访客号段已由交付对齐):
```bash
python3 -m pip install -q -r python/requirements-min.txt && python3 python/quick_verify_visitor_floor_policy.py --mode noauth-probe --org-base-url "http://10.0.22.207:8089" --elevator-base-url "http://10.0.22.207:16112" --use-preset-cases --visitor-person-ids "$(python3 -c 'print(",".join(str(9199000100000000000+i) for i in range(1,26)))')" --probe-with-businessid --batch-output-summary "batch-preset-static-$(date +%Y%m%d-%H%M%S).json"
```
结果见 `report/batch-preset-static-*.json`
### 4.0.1 执行后数据库核验(必须)
在完成 §4.0 且已拿到批量 JSON 后,于**与本环境电梯服务写入同一套库的** MySQL(`cw-elevator-application`)执行:
`sql/标准批量25访客-执行后核验.sql`
**如何对照判断「是否跑成功」**
1. 打开本轮 `report/batch-preset-static-*.json`,对每条样本看 `steps.add_visitor.business_ok``derived.floor_count``grade`
2.**`add_visitor` 业务成功** 且 `passRule/image` HTTP 大体正常的样本,在同一库中期望:查询 **A** 中该行访客的 **`active_row_count` ≥ 1**(租户策略或写库链路正常时,`person_delete=0` 的规则行应与接口返回楼层有对应);**全部为 0** 则重点排查写库延迟、租户/访客 ID 不真实、或网关虽 200 实际未打到目标实例。
3. 查询 **B** 与 JSON 内 `derived.floors[].zoneId` 做逐项比对;若库中 `person_delete=1` 的历史行较多,结合 `last_update_time` 看是否为本次执行产生的新生效行。
4. 若访客号段与本包约定不一致(非 `919900…`),请改用 `sql/人工核查最终楼层结果.sql`,将 `IN (...)` 换为当天 JSON 中全部 `resolved_visitor_person_id`
### 4.1 进入发布目录
```bash
cd docs/testing/release-visitor-noauth-verify-v20260430
```
### 4.2 样本1(广发基金基线)执行
本节「黄平 + 蒙海文」样本用于:**无鉴权下探针是否可走通**,以及 **`passRule/image` 返回是否与租户策略语义一致**。它**不是用来**证明「在本次执行中产出了全新访客主数据」——`add/visitor` 传入的是已在组织/电梯侧建档的访客 `personId` 时,写库常为**续约/补齐规则**`image_rule_ref` 里的行常与**历史登记**混在一起。
若验收目标是「必须先有真实新增访客,再验证派梯」,请:
- **优先**:走 **§4.0** 约定号段 **`9199000100000000001``…0025`** 的批量预置链路(租户内已预置对应用人,`image_rule_ref` 证据与 JSON 对齐);
- 或:业务流程上**新开一名访客**,再将其 `visitorPersonId` 交给本脚本;查库时对 `last_update_time` 与脚本 JSON 顶层 **`started_at`** 做对时(仅能辅助说明「本轮是否写过」)。
```bash
python3 python/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--business-id "2524639890ba4f2cba9ba1a4eeaa4015" \
--meng-person-id "964454497399468032" \
--visitor-person-id "1102270499947507712" \
--probe-with-businessid
```
### 4.3 样本2(其他公司多部门)执行
在与**当前验证目标环境一致**的 MySQL 上执行 `sql/批量样本筛选-多公司多部门.sql`(或等价查询),导出被访人到 `sql/batch_cases.csv`。**禁止**用开发环境数据库导出样本却去打生产 HTTP。**开发环境快照仅可用于开发联调**,生产走查必须使用生产侧数据或手写/审批过的样本 CSV。
```bash
python3 python/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--batch-input-csv "sql/batch_cases.csv" \
--visitor-person-ids "<访客ID1>,<访客ID2>,<访客ID3>" \
--visitor-names "黄志平A,黄志平B,黄志平C" \
--probe-with-businessid
```
建议最少覆盖:
- 3 个不同公司;
- 每公司 2 个不同部门被访人。
若已导出 `docs/testing/_cw_is_person__202604302030.csv`,可直接自动筛选(排除广发基金):
```bash
python3 python/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--batch-source-person-csv "../_cw_is_person__202604302030.csv" \
--exclude-business-ids "2524639890ba4f2cba9ba1a4eeaa4015" \
--sample-companies 3 \
--sample-persons-per-company 2 \
--visitor-person-ids "<访客ID1>,<访客ID2>,<访客ID3>" \
--visitor-names "黄志平A,黄志平B,黄志平C" \
--probe-with-businessid
```
说明:
- 自动筛选依赖列:`BUSINESS_ID`,`ID`,`NAME`;若存在 **`IS_DEL`**,脚本会**跳过已删除行**`IS_DEL≠0` 或与 `true`/`1` 等价)。
- 该 CSV 若无标准部门列,汇总中 `department` 将为空。
### 4.4 结果判定
脚本 `noauth-probe` 对每条样本计算 `grade`(单样本写入 `quick-verify-*.json`;批量写入每条 `results[]`):
- `grade=high_risk`:任一步均未出现 401/403,且 **`add/visitor` 的 HTTP 成功(&lt;300)且接口业务码判定为成功**(`business_ok`),判定高风险放开(安全问题成立)。若仅 HTTP 200 但业务失败,归为 `needs_review`,不是 `high_risk`
- `grade=expected_block`**人员详情、`add/visitor``passRule/image` 任一步**出现 401/403,视为无鉴权被拦截,符合安全预期。
- `grade=needs_review`:未出现 401/403,但未达到上述「放行且业务成功」条件(例如网关超时、业务码失败等),需人工复核。
- `grade=failed`(批量中单条可出现):访客 `personId` 无法解析且无内置兜底等情况,脚本未完成调链;不按上述安全三档解释,需先看 `summary`/JSON 报错原因。
### 4.5 汇总输出(必须)
最终按样本输出表格(建议 CSV/Markdown;字段可从批量 JSON **`results[]`** 各条中取):
- 公司:`sample.company`
- 部门:`sample.department`
- 被访人 `personId``args.meng_person_id`
- 访客 `personId``args.resolved_visitor_person_id`
- **`add/visitor` 业务码**`steps.add_visitor.business_code`(及 `http_status`
- **`passRule/image`**`steps.passrule_image` 内的 `business_code` / `http_status`
- 楼层数量:`derived.floor_count`
- 楼层清单:`derived.floors`(元素含 `zoneId`/`zoneName`
- 安全分档:`grade``summary`
控制台会摘要打印 `company/department``addCode``floorCount`;完整以 JSON 为准。
批量汇总文件:**默认** `report/batch-summary.json`;若使用了 `--batch-output-summary`(如 §4.0 的 `batch-preset-static-*.json`),则路径为 **`report/` + 传入文件名**。
### 4.6 人工 SQL 核查最终结果(最后一步)
- §4.0 固定 25 号段:**优先**执行 `sql/标准批量25访客-执行后核验.sql`
- 其它访客清单或单笔核对:执行 `sql/人工核查最终楼层结果.sql`,自行替换 `IN (...)`
核查要点:
- 按本次访客ID集合过滤,确认 `person_delete=0` 的有效规则;
- 对比 `zone_id` 与脚本输出楼层清单;
- 如存在历史残留,结合 `create_time` / **`last_update_time`**`image_rule_ref`)判定最新记录。
### 4.7 业务侧整改后关键日志检查点
本版整改聚焦业务策略链路,不调整鉴权逻辑。应用日志需出现:
- 策略决策日志(`PersonRuleServiceImpl`)含字段:
- `policyDecision``hostFloorSize``allowFloorSize``effectiveFloorSize`(有一条覆盖生效日志中占位名为 `effectiveSize`,与同次决策中的楼层数量一致)、`policyId``policyVersion`
失败路径上的告警亦多为 `WARN`/`INFO`(如「访客派梯楼层决策失败-…」「allow_zone_ids JSON 无效」),便于在无 DEBUG 前提下排查。**是否仍存在「仅为探针、且仍为 DEBUG」的日志行,请以当前发布包镜像实际 `logback` 与源码为准逐项核对**。
## 5. 证据留档
至少归档以下内容:
1. 执行命令
2. 脚本输出摘要(控制台)
3. 生成的 JSON**单样本** `report/quick-verify-*.json`**标准批量** `report/batch-preset-static-*.json` 或其他 `--batch-output-summary` 指定名
4. **`sql/标准批量25访客-执行后核验.sql`(或等价)查询导出**与其它 SQL 核验结果一并留档
5. 关键接口返回截图/日志
@@ -0,0 +1,162 @@
# 访客无鉴权策略验证-生产操作手册
## 1. 文档目的
本手册用于生产环境执行以下验证并留痕:
- 在**无鉴权模式**下调用访客相关接口,确认是否存在放开风险。
- 验证“黄平(访客)访问蒙海文(被访人)”是否触发访客楼层策略。
- 输出可审计报告(JSON)用于归档与发布。
本手册基于已确认信息:
- 被访人(蒙海文)`personId=964454497399468032`
- 访客(黄平)`personId=1102270499947507712`
- 租户 `businessId=2524639890ba4f2cba9ba1a4eeaa4015`
---
## 2. 目录与交付件
本发布包目录:
- `docs/testing/release-visitor-noauth-verify/访客无鉴权策略验证-生产操作手册.md`
- `docs/testing/release-visitor-noauth-verify/黄平访客ID手工查询.sql`
执行脚本(仓库已有,已按无鉴权流程更新):
- `maven-cw-elevator-application/tools/visitor_floor_verification/scripts/quick_verify_visitor_floor_policy.py`
---
## 3. 验证范围
本次仅验证以下调用链:
1. `POST /component/person/detail`
2. `POST /elevator/person/add/visitor`
3. `POST /elevator/passRule/image`
请求模式:
- `noauth-probe`(不传 Authorization/loginid/platformuserid/applicationid
- 可选保留 `businessid` 头:`--probe-with-businessid`
---
## 4. 前置条件
### 4.1 运行环境
- 可访问生产网络的 Linux 主机
- Python 3.8+
- 已拉取本仓库代码
### 4.2 依赖安装
```bash
cd maven-cw-elevator-application/tools/visitor_floor_verification
python3 -m pip install -r requirements.txt
```
---
## 5. 参数基线
建议使用以下固定参数:
- `org-base-url``http://10.0.22.207:8089`(按现场网关/portal入口可调整)
- `elevator-base-url``http://10.0.22.207:16112`
- `business-id``2524639890ba4f2cba9ba1a4eeaa4015`
- `meng-person-id``964454497399468032`
- `visitor-person-id``1102270499947507712`
说明:
- 当前脚本内置默认 `--meng-person-id=964454497399468032`,可不显式传参。
---
## 6. 标准执行命令
```bash
python3 maven-cw-elevator-application/tools/visitor_floor_verification/scripts/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--business-id "2524639890ba4f2cba9ba1a4eeaa4015" \
--visitor-person-id "1102270499947507712" \
--probe-with-businessid
```
---
## 7. 输出与结果判定
脚本终端会输出:
- `mode`
- `grade`
- `summary`
- `report`(报告文件路径)
- `add_visitor_status/code`
- `passrule_image_status/code`
报告文件输出目录:
- `maven-cw-elevator-application/tools/visitor_floor_verification/report/quick-verify-<timestamp>.json`
### 7.1 关键判定规则
#### A. 无鉴权风险判定(noauth-probe
- `grade=high_risk``add/visitor` 在无鉴权下业务成功,判定高风险放开。
- `grade=expected_block`:返回 401/403,判定符合安全预期。
- `grade=needs_review`:非拦截但未成功,需人工复核网关策略。
#### B. 策略触发判定
-`add/visitor` 成功,且 `passRule/image` 回读到楼层数据,判定策略触发成功。
-`add/visitor` 返回 `76260532`,表示策略求交为空(策略生效但无可放行楼层)。
---
## 8. 黄平访客ID手工复核
可执行以下命令打印 SQL 模板:
```bash
python3 maven-cw-elevator-application/tools/visitor_floor_verification/scripts/quick_verify_visitor_floor_policy.py \
--print-visitor-sql-only \
--org-base-url "http://10.0.22.207:8089" \
--elevator-base-url "http://10.0.22.207:16112" \
--visitor-person-id "dummy"
```
或直接使用本包 SQL 文件:
- `docs/testing/release-visitor-noauth-verify/黄平访客ID手工查询.sql`
---
## 9. 发布归档建议
建议将以下文件打包归档:
1. 本操作手册
2. SQL 文件
3. 实际执行命令记录
4. `quick-verify-<timestamp>.json` 报告
5. 关键日志截图(含执行时间与业务码)
建议包名:
- `visitor-noauth-verify-<yyyyMMdd-HHmm>.zip`
---
## 10. 风险提示
- 本流程为生产探测,务必在低峰窗口执行。
- 无鉴权探测若成功,属于安全风险项,应立即同步网关/服务鉴权负责人处理。
- 所有返回结果以现场实际响应为准,需保留原始响应证据。
@@ -0,0 +1,20 @@
-- 访客:黄平(手机号 13926442944)手工查询 SQL
-- 场景:生产环境复核/确认访客 person_id
-- 已知租户:2524639890ba4f2cba9ba1a4eeaa4015
-- 已确认库表:component-organization.cw_is_person
SELECT
person_id,
name,
mobile,
business_id,
labels,
deleted,
create_time,
update_time
FROM `component-organization`.`cw_is_person`
WHERE business_id = '2524639890ba4f2cba9ba1a4eeaa4015'
AND name = '黄平'
AND mobile = '13926442944'
ORDER BY update_time DESC;
@@ -0,0 +1,105 @@
# 租户访客默认楼层(广发及后续租户定制)与「不影响其他公司」的边界说明
## 1. 目标表述
| 诉求 | 含义 |
|------|------|
| **定制** | 某租户希望:访客在 **不传 `floorIds`** 时,仅开通 **接待层等默认楼层**(与员工本人多层权限区分)。 |
| **不影响未定义公司** | 未启用该能力的租户 / 机构,行为与改造前一致:**不因他人策略误伤**。 |
实现落点:**组织** `ImgPersonServiceImpl#detail`(将策略 **`allow_zone_ids` 替代写入 `floorList`**+ 电梯 **`PersonRuleServiceImpl#addVisitor`****透传** `detail.floorList`,**不**读策略表、**不** ∩)。策略数据表仍可在组织侧或迁移期参照 `tenant_visitor_floor_policy`(历史上在电梯库)。详见 `visitor-registration-business-flow.md``docs/superpowers/specs/2026-05-06-tenant-visitor-policy-organization-implementation.md`
---
## 2. 当前实现下的真实隔离粒度(必读)
### 2.1 策略生效键:**`business_id`(机构/租户 ID**
- **规范**:策略行仍按租户维度启用;组织侧策略服务读取时与 **`companyId`Header `businessid`** 及被访人 **`organizationIds`** 对齐。
- 电梯 **`addVisitor`** **不再**调用 **`TenantVisitorFloorPolicyDao`**。
### 2.2 「未定义」租户的行为 — **不受影响**
```mermaid
flowchart LR
subgraph T1["租户 A:未命中租户访客策略"]
A1[addVisitor floorIds 空]
A2[detailfloorList = listByImageId 原始楼层]
A4[effectiveFloors = detail.floorList]
A1 --> A2 --> A4
end
subgraph T2["租户 B:策略命中"]
B1[detailfloorList = allow_zone_ids 替代结果]
B1 --> B2[addVisitor 透传]
end
```
- **未命中策略**`detail` 返回 **`listByImageId` 遍历楼层**,与其它租户一致。
**未单独配置策略的 `business_id`**:行为与改造前「无收紧」一致。
### 2.3 「广发定制」与同一 `business_id` 下其他部门 — **当前同属租户级策略**
-**星河湾中心**与 **广发基金**等业务共用一个 **`business_id`**(现场组织库 `cw_is_organization.BUSINESS_ID` 相同),则 **库中一条租户默认策略会对该 ID 下全部主体生效**,**无法**仅靠配置表做到「只收紧广发公司、不收紧同租户下其他公司」。
- **产品级隔离选项(需实施选型,超出当前表结构默认能力)**:
- **拆租户**:广发使用 **独立 `business_id`**(独立机构树),策略只插入该行;或
- **演进能力**:使用/扩展 **`building_id`** 维度的策略行(表已预留列,需扩展 Mapper 查询与产品规则);或
- **调用方传 `floorIds`**:由 BFF 预先收窄;电梯 **UC-02** 以请求为准。
---
## 3. 业务流程图(规范)
```mermaid
flowchart TD
Start([POST /elevator/person/add/visitor]) --> Empty{floorIds 空?}
Empty -- 否 --> UseIn[UC-02 effective = 请求 floorIds]
Empty -- 是 --> Det[PersonService.detailfloorList 已含组织侧策略替代]
Det --> HF{floorList 非空?}
HF -- 否 --> E31[76260531]
HF -- 是 --> UseIn2[UC-01 effective = detail.floorList]
UseIn --> Zone[首层→楼栋→imageStoreId]
UseIn2 --> Zone
Zone --> IRR[写 image_rule_ref personId=visitorId]
IRR --> Bind[图库 batchBind visitorId]
Bind --> OK([成功])
```
---
## 4. 时序图(不传 floorIds
```mermaid
sequenceDiagram
participant Caller as 调用方/BFF
participant API as AcsPersonController
participant PR as PersonRuleServiceImpl
participant PS as PersonService 组件
participant Ir as ImageRuleRefDao
participant IS as ImageStorePersonService
Caller->>API: visitorId, personId(被访人), floorIds=[]
API->>PR: addVisitor
PR->>PS: detail(personId, businessId)
PS-->>PR: PersonResult.floorList(组织已替代)
Note over PR: effectiveFloors = floorList;电梯不读策略表
PR->>Ir: insertList 每层默认规则 visitorId
PR->>IS: batchBind(visitorId, 访期)
IS-->>PR: ok
PR-->>API: success
```
---
## 5. 与测试矩阵的关系
- **自动化快照**按 **`business_id`** 拉策略与人员;若需验证「无策略租户」,使用 **第二 `business_id`** 套件或 **空策略库**
- **每部门 10 名员工**:验证「同一策略下不同被访人」在 **detail** 得到的 **`floorList`(替代后)** 多样性;**不**等价于「按公司隔离策略」。
---
## 6. 文档索引
- 租户 / 组织 / 人员 / 访客 ER、表关系与用例:`docs/architecture/租户组织人员访客-数据模型与用例.md`
- 楼层与 API 字段:`docs/testing/visitor-registration-business-flow.md`
- 服务层逐步说明:`cw-elevator-application-service/docs/08-visitor-registration-and-elevator-auth.md`
- 测试方案:`docs/testing/visitor-registration-floor-validation.md`
@@ -0,0 +1,123 @@
# 访客注册与派梯:被访人、访客与楼层 — 源码级业务流程
> 本文与 `**cw-elevator-application-service/docs/08-visitor-registration-and-elevator-auth.md**` 互补:08 偏「接口步骤清单」,本文强调 **被访人 / 访客 / 楼层** 三者关系与 **类方法落点**。电梯应用不负责完整「访客档案登记 UI」,但 `**add/visitor` 显式依赖两条人员主键**。
---
## 1. 术语(避免混用)
| 称呼 | HTTP / 参数字段 | 含义 | 数据哪里来 |
| ----------- | ----------------------------- | ----------------------------------------------------- | -------------------------------------------- |
| **访客** | `visitorId` | 已在**平台人员体系**存在的档案 ID(登记/同步发生在访客业务或 CWOS 组件侧) | 组织库 `cw_is_person` 等;常打 **「访客」标签** |
| **被访人(员工)** | `personId` | **接待访客的员工**,用于在 **未传 `floorIds`** 时拉取其可派梯楼层 | 同库在职人员,与 `cw_is_person_organization_ref` 挂组织 |
| **生效楼层** | 内部 `param.floorIds`(可能由服务端改写) | 最终写入 `**image_rule_ref`**、绑定图库的 **楼层 zoneId 列表**(雪花串) | 见 §3 |
**易错点**`personId` **不是**访客 ID,而是**被访员工** ID。
---
## 2. 端到端角色关系(产品语义)
```mermaid
flowchart LR
subgraph 登记域["登记域(多在外部/组件)"]
V["访客档案 visitorId"]
H["员工档案 personId\n被访人"]
end
subgraph 电梯域["电梯应用"]
A["POST /elevator/person/add/visitor"]
R["image_rule_ref\npersonId=visitorId"]
end
H -->|Feign detail 取 floorList| A
V --> A
A --> R
```
- **访客要访问的是员工(被访人)** → API 上体现为:用 `**personId`** 定位被访人,用 `**visitorId**` 定位访客档案。
- **电梯侧写规则**:按 `**visitorId`** 在各区写入规则引用(`ImageRuleRefAddDto.personId = visitorId`),**不是**写在被访人名下。
---
## 3. 楼层从哪里来(核心业务逻辑)
实现类:`**PersonRuleServiceImpl#addVisitor`**`person/impl/PersonRuleServiceImpl.java`)。
### 3.1 调用方 **传入非空 `floorIds`**
- **跳过**被访人详情与租户策略整段。
- **直接使用**调用方给出的楼层列表作为 `**effectiveFloors`**(需非空,否则 `76260531`)。
- **责任**:楼层合法性、是否仍应受租户策略约束,由调用方或上游 BFF 保证(产品文档另有说明)。
### 3.2 调用方 **未传 / 空 `floorIds`(常见访客路径)**
1. `**PersonService#detail`**Feign,组件 `**/component/person/detail**`
- 入参:`PersonDetailParam.id = param.getPersonId()`**被访人**)、`businessId = context.getCompany().getCompanyId()`
- 出参:`**PersonResult.getFloorList()`** → 记为 `**hostFloors**`(字符串列表,元素为电梯域认可的 **zoneId**,雪花形态,与 `**image_rule_ref.zone_id`** 一致)。
2. **失败分支**
- detail 失败 / 无数据 / `**hostFloors` 为空** → `**76260531`**(无可用楼层依据)。
3. **租户默认策略(可选收窄)**
- `**TenantVisitorFloorPolicyDao#selectEnabledTenantDefault(companyId)`** → 表 `**tenant_visitor_floor_policy**`
- 条件:`enabled=1``policy_type=INTERSECT_ALLOWLIST`、租户级默认(`building_id` 空)。
- `**allow_zone_ids**`JSON 字符串数组,解析为 `**allowSet**`
- **生效楼层**`**effectiveFloors = hostFloors 按原顺序过滤,仅保留 ∈ allowSet`**`intersectPreserveHostOrder`)。
- 若交集 **为空**`**76260532`**(与租户允许楼层无交集)。
4. **首层 → 楼栋 → 图库**
-`**effectiveFloors.get(0)`**`**ZoneService#page**``**ZoneResult**`,再 `**deviceImageStoreDao.getByBuildingId(首层 parentId)**``**imageStoreId**`
5. **逐层写规则 + 绑访客图库**
- 对每个 floorId`**imageRuleRefDao.getDefaultByZoneId`** → 组装 `**ImageRuleRefAddDto**``**personId = param.getVisitorId()**`(访客)。
- `**imageStorePersonService.batchBind**`:把 **访客** 绑到该楼栋图库,访期 `**begVisitorTime` / `endVisitorTime`**。
- `**updateGroupPersonRef**`:同步组人员引用。
### 3.3 小结公式
- **无显式 floorIds 时**
\text{effectiveFloors} = \begin{cases}
\text{hostFloors} & \text{无启用策略或 allow 为空}
\text{hostFloors} \cap \text{allowzoneids} & \text{策略启用且 allow 非空}
\end{cases}
- **交集为空** → `**76260532`****hostFloors 为空** → `**76260531`**。
---
## 4. 与「访客注册」一词的边界
| 步骤 | 是否在电梯仓实现 |
| ------------------------------------ | ------------------ |
| 访客姓名/证件/人脸建档、预约单 | **否**(外部系统 / 组件) |
| 拿到 `**visitorId` + 被访员工 `personId`** | 前置条件 |
| **派梯授权**(写规则 + 绑图库) | **是**`addVisitor` |
因此:**完整「访客注册」业务** = 外部登记 + **本接口授权**;本文楼层逻辑仅覆盖授权链。
---
## 5. 关键源码索引
| 步骤 | 类 / 方法 |
| ------- | ---------------------------------------------------------- |
| HTTP 入口 | `AcsPersonController``/elevator/person/add/visitor` |
| 聚合逻辑 | `PersonRuleServiceImpl#addVisitor` |
| 被访人楼层 | `PersonService#detail``PersonResult#getFloorList` |
| 租户策略 | `TenantVisitorFloorPolicyDao#selectEnabledTenantDefault` |
| 策略表 | `tenant_visitor_floor_policy` |
| 规则落库 | `ImageRuleRefDao#getDefaultByZoneId` / `insertList` |
| 图库 | `ImageStorePersonService#batchBind``updateGroupPersonRef` |
---
## 6. 测试数据在建模上的要求
- **每条用例**应能指向:**组织 / 部门**、**一名被访员工(host**、**一名访客(visitor**。
- 导出脚本从 DB 解析:**员工** = 部门下在职人员;**访客** = 带「访客」标签的人员池,按套件 `**business_id`** 过滤,与用例 **轮询配对**(避免同源语义缺失)。
- 详见 `**tools/visitor_floor_verification/config/test_matrix.json`** 与导出快照 `**host_employee` / `visitor_for_api**` 字段。
@@ -0,0 +1,151 @@
# 访客注册(派梯开通)与可达楼层验证 — 测试方案与计划
## 0. 关联文档
- **租户 / 组织 / 人员 / 访客 ER 与表关系**:`docs/architecture/租户组织人员访客-数据模型与用例.md`
- **被访人 / 访客 / 楼层逻辑(源码走查)**:`docs/testing/visitor-registration-business-flow.md`
- **服务层逐步说明与活动图(与 08 同谱系)**:`maven-cw-elevator-application/cw-elevator-application-service/docs/08-visitor-registration-and-elevator-auth.md`
- **租户定制默认楼层 vs 未定义租户隔离边界(流程图/时序图)**:`docs/testing/tenant-visitor-default-floor-isolation.md`
### 0.1 数据模型(测试矩阵 v3)
- **`export_settings.employees_per_department`**:每部门导出员工人数(默认 **10**),写入快照 **`host_employees`**。
- **`visitor_resolution.pool_limit`**:访客标签池上限(与 **`visitor_pool_limit`** 取大)。
- **`personId`(被访人)**:**员工**;导出按部门取最多 N 人写入 **`host_employees[]`**N 见矩阵 `employees_per_department`)。
- **`visitorId`(访客)**:**访客档案**(「访客」标签);导出为 **每名员工** 分配 **`visitor_for_api`**(全局槽位轮询);`test_matrix.json` 中部门级 **`visitor_person_id`** 可令该部门全部员工共用同一访客。
---
## 1. 背景与范围
### 1.1 业务链路(电梯应用)
- **接口**`POST /elevator/person/add/visitor`,请求体 `floorIds` **为空**时,服务内部:
1. Feign 调用组织组件 `**/component/person/detail`**,取被访人 `**floorList`**(雪花 `zone_id` 字符串列表)。
2. 查询 `**tenant_visitor_floor_policy**`(租户默认策略,`business_id` = 登录上下文机构)。
3. 策略为 `**INTERSECT_ALLOWLIST**` 且启用时:**生效楼层 = `floorList ∩ allow_zone_ids`**(顺序保留被访人顺序)。
4. 交集为空 → 业务码 `**76260532**`;否则按生效楼层写 `**image_rule_ref**` 并绑图库。
- **回读验收**`POST /elevator/passRule/image``personId` = 访客 ID,从 `**data[]`** 读取 `zoneId` / `zoneName`
### 1.2 当前库内策略现状(重要)
- `**tenant_visitor_floor_policy`** 按 `**business_id**` 维度生效;现场 `**cw-elevator-application**` 中为租户 `**2524639890ba4f2cba9ba1a4eeaa4015**`(与组织库 `**cw_is_organization.BUSINESS_ID**` 一致)配置了广发接待层 **28F** 对应 `**zone_id`**。
- **含义**:凡使用该 `**business_id`** 登录的星河湾/星中心主体(含非「广发」名字的部门),在未显式传 `floorIds` 时**同样**适用「与 allowlist 求交」——验收与风险评估时需写明该前提;若产品上要「仅广发主体生效」,需另行产品设计(如楼栋/机构维度策略扩展),**不在本脚本假定范围内**。
### 1.3 现场组织库事实(`component-organization`
- `**BUSINESS_ID = 2524639890ba4f2cba9ba1a4eeaa4015`**:根机构 `**星河湾中心`**,其下含 **[28-38F]广发基金管理有限公司** 及其 **9 个子部门**(合计 **10** 个节点:1 公司 + 9 部门),为本方案 **「广发基金套件」** 覆盖对象。
- `**BUSINESS_ID = 9f19a307b3ea4854bf2d7dafe69649c9`**:仅 `**默认根节点`**;现场 `**cw_is_person**` 侧未见该租户人员——**联调用例若依赖在职被访人**,可能无法执行;保留为「策略缺失对照」说明项。
- **命名**:文中「星河湾中心」为现场 **`cw_is_organization`** 根节点 **`NAME`** 示例;口语「星河湾集团」等与库内节点全称不一定一一对应,请以现场 **`NAME`/`ID`** 为准。租户 / 组织 / 人员 / 访客 ER 与术语见 [`docs/architecture/租户组织人员访客-数据模型与用例.md`](../architecture/租户组织人员访客-数据模型与用例.md)。
---
## 2. 测试层级定义
| 层级 | 名称 | 手段 | 产出 |
| ------ | ------ | --------------------------------------------------------- | ----------------------- |
| **L0** | 数据导出 | MySQL 读组织、策略、样例人员 | `catalog_snapshot.json` |
| **L1** | 静态一致性 | 校验导出 JSON 内 suite 与策略字段口径 | 控制台 / 报告一节 |
| **L2** | 联机楼层验收 | 调用 `**add/visitor`**`floorIds=[]`+ `**passRule/image`** | Markdown 报告 |
| **L3** | 可选扩展 | 对接组件 `**/component/person/detail`** 预计算交集(需另行网关/脚本权限) | 未默认启用 |
说明:**被访人 `floorList` 不可仅从电梯库推导**(以组件为准),故 **L2** 以「开通结果 + 回读楼层」为权威验收;若需预知交集,须 **L3** 或人工查组件。
---
## 3. 测试套件与用例矩阵(摘要)
### 3.1 `guangfa_fund_10` — 广发基金管理有限公司 subtree(10)
| # | 组织 ID(节选) | 名称 |
| ---- | ---------------------------------------- | --------------------------- |
| 1 | `488b8ad049bb43408a6fbcc50bcb89ac` | [28-38F]广发基金管理有限公司 |
| 210 | 其子部门(含 `32F-广发外包``信息技术部``公司领导` 等共 9 个) | 见 `config/test_matrix.json` |
**每条用例**:同一租户上下文(Header `businessid`)下,指定 **被访人 `personId`**(从该部门导出 **1 名在职人员**)、**访客 `personId`**(测试账号)、访客有效期;不传 `**floorIds**`
**期望类型(L2**
- **成功路径**`add/visitor` 返回成功码;`passRule/image``**zoneName` 均落在策略允许集合对应的楼层展示名**(现场允清单示例:**28F**,正则可在脚本中用 `--allowed-zone-name-regex` 约束)。
- **失败路径**:若组件返回的被访人 `**floorList`** 与 `**allow_zone_ids`** 无交集 → `**76260532**`,记为 **EXPECTED_FAIL**,断言业务码而非楼层列表。
### 3.2 `xinghewan_star_center` — 星河湾 / 星中心代表部门(非广发字样)
`**星河湾中心`** 根下选取包含 **「星河湾」「星中心」** 语义的部门若干(示例:**星河湾集团总部**、**星中心物管公司**),每部门 **1** 名被访人样例。
**期望**:与 **3.1** 相同租户策略下,仍应按「求交」结果开通或失败(不得以「非广发」跳过策略)。
### 3.3 `tenant_secondary` — 第二 `BUSINESS_ID`(对照)
- **目的**:无 `**tenant_visitor_floor_policy`** 行时,行为应与「未收窄」一致(以组件 `**floorList`** 为准);现场若无人员,标记 **SKIP**
---
## 4. 测试数据约定
| 数据项 | 来源 | 说明 |
| -------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `business_id` | Header `**businessid`** | 与 DB `**tenant_visitor_floor_policy.business_id`**、组织 `**BUSINESS_ID**` 一致 |
| 被访人 `personId` | MySQL `cw_is_person` + `cw_is_person_organization_ref` | 导出脚本按 `**ORG_ID**`**每部门 1 人** |
| 访客 `personId` | 测试环境固定账号 | **环境变量 `VISITOR_TEST_PERSON_ID`**(或脚本参数);勿用生产真实访客随意写入 |
| 访客有效期 | `begVisitorTime` / `endVisitorTime` | 毫秒时间戳;避免重叠冲突可调脚本 `--window-days` |
| 允许楼层参照 | `tenant_visitor_floor_policy.allow_zone_ids` + `cw_is_area``cwos_portal` | 展示名校验用 `**zoneName**`(如 **28F**) |
详细字段级快照见仓库 `**maven-cw-elevator-application/tools/visitor_floor_verification/data/`**(导出生成)。
---
## 5. 准入 / 准出标准
**准入**
- 电梯服务可访问(`BASE_URL`);网关鉴权头 `**ELEVATOR_HEADER_*`** 已配置;
- MySQL 可从运行脚本环境访问(导出阶段);
- 已书面确认:**租户级策略** 对全体使用该 `business_id` 的主体生效。
**准出**
- `catalog_snapshot.json` 生成成功且含三类套件定义;
- L2 报告:**通过率 / SKIP / FAIL** 可区分;失败附 `**code`** 与响应摘要;
-`**EXPECTED_FAIL`**(交集为空)类用例,业务码符合 `**76260532**`
---
## 6. 执行顺序建议
1. `python scripts/export_catalog.py` → 刷新快照(依赖 DB)。
2. 复核快照内 `**sample_host_person_id**` 是否为在职账号。
3. `python scripts/run_visitor_floor_suite.py --phase report`(仅导出校验)或 `**--phase live**`(联机)。
4. 归档报告 `**report/visitor-floor-suite-<timestamp>.md**`
---
## 7. 仓库内工件路径(索引)
| 工件 | 路径 |
| ----------------------------- | ---------------------------------------------------------------------------------------- |
| 测试方案与计划(本文档) | `docs/testing/visitor-registration-floor-validation.md` |
| 套件矩阵(广发10 + 星河湾/星中心 + 第二租户占位) | `maven-cw-elevator-application/tools/visitor_floor_verification/config/test_matrix.json` |
| **导出快照(建议纳入变更或由内网生成)** | `.../tools/visitor_floor_verification/data/catalog_snapshot.json` |
| 导出脚本 | `.../scripts/export_catalog.py` |
| 报告 / 联机执行脚本 | `.../scripts/run_visitor_floor_suite.py` |
| 报告输出目录 | `.../tools/visitor_floor_verification/report/` |
策略初始化 SQL(广发 28F allowlist)见 `docs/sql/tenant_visitor_floor_policy_init_guangfa_fund.sql`
---
## 8. 风险与限制
- **重复开通**:同一访客短期内多次 `add/visitor` 可能叠加规则或触发远端校验失败;建议使用 **专用测试访客** 或拉长有效期区间。
- **环境与生产**:口令与 URL **勿提交仓库**;快照 JSON 若含真实 ID,纳入内部介质分发策略。
- **策略维度**:当前库表 **无「仅广发」机构字段**;跨部门验收等价验证「同一租户策略」。
@@ -0,0 +1,307 @@
# 广发基金访客被访楼层接口生产验证操作文档
## 1. 目标与范围
本文用于生产环境验证以下事项:
- 广发基金租户下,访客开通接口在不传 `floorIds` 时,是否按被访人楼层与租户策略进行处理。
- 验证对象固定为广发基金员工 **蒙海文** 的关联信息(`personId``businessId``floorList`)。
- 输出可审计的执行记录,包含输入参数、返回结果、结论与留痕。
说明:本操作仅做接口调用和数据核验,不修改生产配置、不执行策略变更 SQL。
## 2. 前置条件
### 2.1 必备信息
- 电梯服务地址:`ELEVATOR_BASE_URL`(示例:`http://<host>:16112`)。
- 组织服务地址:`ORG_BASE_URL`(示例:`http://<host>:17016` 或网关地址)。
- 广发基金租户 `businessId``2524639890ba4f2cba9ba1a4eeaa4015`
- 测试访客 `visitorId`(专用测试账号,避免使用真实业务访客)。
- 鉴权头(按现场网关要求):`authorization``loginid``platformuserid``applicationid`
### 2.2 风险提示
- 生产环境调用会产生真实接口访问日志,请在低峰时段执行。
- `add/visitor` 会写入访客通行规则,建议只使用测试访客并设置短期有效期。
- 若现场策略已变更,需先复核 `tenant_visitor_floor_policy` 再执行。
## 3. 蒙海文关联信息确认(必做)
先确认“蒙海文”在组织服务中的关键关联信息,作为后续请求入参依据。
### 3.1 确认项清单
- 员工姓名:蒙海文
- 员工 `personId``<MENG_HAI_WEN_PERSON_ID>`
- 员工 `businessId``2524639890ba4f2cba9ba1a4eeaa4015`
- 员工 `floorList``["..."]`(至少 1 个楼层 ID
### 3.2 被访人详情接口请求模板(输入参数)
接口:`POST /component/person/detail`
请求头模板:
```text
Content-Type: application/json
businessid: 2524639890ba4f2cba9ba1a4eeaa4015
authorization: Bearer <TOKEN>
loginid: <LOGIN_ID>
platformuserid: <PLATFORM_USER_ID>
applicationid: <APPLICATION_ID>
```
请求体模板:
```json
{
"id": "<MENG_HAI_WEN_PERSON_ID>",
"businessId": "2524639890ba4f2cba9ba1a4eeaa4015"
}
```
`curl` 示例:
```bash
curl -sS -X POST "${ORG_BASE_URL}/component/person/detail" \
-H "Content-Type: application/json" \
-H "businessid: 2524639890ba4f2cba9ba1a4eeaa4015" \
-H "authorization: Bearer <TOKEN>" \
-H "loginid: <LOGIN_ID>" \
-H "platformuserid: <PLATFORM_USER_ID>" \
-H "applicationid: <APPLICATION_ID>" \
-d '{
"id":"<MENG_HAI_WEN_PERSON_ID>",
"businessId":"2524639890ba4f2cba9ba1a4eeaa4015"
}'
```
验收要点:
- `data.name` 为“蒙海文”。
- `data.businessId``2524639890ba4f2cba9ba1a4eeaa4015`
- `data.floorList` 非空并记录原始值。
## 4. 租户策略基线确认(建议)
用于确认广发基金策略是否启用,避免误判。
参考策略脚本:`docs/sql/tenant_visitor_floor_policy_init_guangfa_fund.sql`
关键期望:
- `business_id='2524639890ba4f2cba9ba1a4eeaa4015'`
- `policy_type='INTERSECT_ALLOWLIST'`
- `enabled=1`
- `allow_zone_ids``605560545117995008`28F
示例查询(电梯库):
```sql
SELECT business_id, policy_type, allow_zone_ids, enabled, policy_version, updated_at
FROM tenant_visitor_floor_policy
WHERE business_id = '2524639890ba4f2cba9ba1a4eeaa4015';
```
## 5. 访客开通接口验证(核心)
### 5.1 请求信息(输入参数)
接口:`POST /elevator/person/add/visitor`
请求头:与第 3 节一致,`businessid` 固定为 `2524639890ba4f2cba9ba1a4eeaa4015`
请求体模板(验证“自动按被访人楼层处理”时,`floorIds` 置空或不传):
```json
{
"visitorId": "<TEST_VISITOR_PERSON_ID>",
"personId": "<MENG_HAI_WEN_PERSON_ID>",
"begVisitorTime": <BEGIN_TS_MS>,
"endVisitorTime": <END_TS_MS>,
"floorIds": []
}
```
时间戳示例(毫秒):
- `begVisitorTime`: 当前时间
- `endVisitorTime`: 当前时间 + 1 天
`curl` 示例:
```bash
curl -sS -X POST "${ELEVATOR_BASE_URL}/elevator/person/add/visitor" \
-H "Content-Type: application/json" \
-H "businessid: 2524639890ba4f2cba9ba1a4eeaa4015" \
-H "authorization: Bearer <TOKEN>" \
-H "loginid: <LOGIN_ID>" \
-H "platformuserid: <PLATFORM_USER_ID>" \
-H "applicationid: <APPLICATION_ID>" \
-d '{
"visitorId":"<TEST_VISITOR_PERSON_ID>",
"personId":"<MENG_HAI_WEN_PERSON_ID>",
"begVisitorTime":<BEGIN_TS_MS>,
"endVisitorTime":<END_TS_MS>,
"floorIds":[]
}'
```
期望:
- 返回成功码(常见 `code=0``success=true`,以现场协议为准)。
- 若返回 `76260532`,表示求交后无可开通楼层,需按“预期失败”流程记录。
## 6. 回读访客楼层权限验证
### 6.1 回读接口请求模板(输入参数)
接口:`POST /elevator/passRule/image`
请求体模板:
```json
{
"personId": "<TEST_VISITOR_PERSON_ID>",
"businessId": "2524639890ba4f2cba9ba1a4eeaa4015",
"imageStoreIds": [],
"includeOrganizations": [],
"includeLabels": []
}
```
`curl` 示例:
```bash
curl -sS -X POST "${ELEVATOR_BASE_URL}/elevator/passRule/image" \
-H "Content-Type: application/json" \
-H "businessid: 2524639890ba4f2cba9ba1a4eeaa4015" \
-H "authorization: Bearer <TOKEN>" \
-H "loginid: <LOGIN_ID>" \
-H "platformuserid: <PLATFORM_USER_ID>" \
-H "applicationid: <APPLICATION_ID>" \
-d '{
"personId":"<TEST_VISITOR_PERSON_ID>",
"businessId":"2524639890ba4f2cba9ba1a4eeaa4015",
"imageStoreIds":[],
"includeOrganizations":[],
"includeLabels":[]
}'
```
### 6.2 判定规则
- 成功判定:
- `add/visitor` 成功。
- `passRule/image` 返回 `data[]` 非空。
- 返回楼层(`zoneId` / `zoneName`)符合当前租户策略和被访人 `floorList` 的交集预期。
- 预期失败判定:
- `add/visitor` 返回 `76260532`(交集为空),记录为预期失败,不记为系统缺陷。
- 异常失败判定:
- 鉴权失败(401/403)。
- 参数格式错误(400)。
- 下游服务不可达、超时、5xx。
## 7. 标准执行顺序
1. 记录执行人、时间窗、目标环境与业务单号。
2.`/component/person/detail`,确认并记录蒙海文信息。
3. (建议)执行策略查询,确认 allowlist 状态。
4.`/elevator/person/add/visitor` 开通测试访客。
5.`/elevator/passRule/image` 回读访客楼层。
6. 依据第 6.2 节判定并形成结论。
## 8. 现场结论记录模板(复制填写)
### 8.1 基本信息
- 执行时间:
- 执行环境:
- 执行人:
- 工单/需求编号:
### 8.2 蒙海文关联信息核对结果
- 姓名:蒙海文
- `personId`
- `businessId`
- `floorList`
- 核对结论(通过/不通过):
### 8.3 接口调用记录
1) `/component/person/detail`
- 请求参数摘要:
- 响应摘要:
- 结果判定:
2) `/elevator/person/add/visitor`
- 请求参数摘要(含 `visitorId``personId`、时间窗):
- 响应摘要(含业务码):
- 结果判定:
3) `/elevator/passRule/image`
- 请求参数摘要:
- 响应摘要(含 `zoneId/zoneName`):
- 结果判定:
### 8.4 最终结论
- 结论:通过 / 预期失败 / 失败
- 失败原因分类:
- 后续处理建议:
## 9. 附件留痕要求
至少保留以下附件(脱敏后归档):
- 三次接口请求与响应(建议 JSON 文件各 1 份)。
- 关键日志截图(包含时间戳与业务码)。
- 本文档第 8 节填写后的结果页。
建议命名:`gf-visitor-floor-verify-<yyyyMMdd-HHmm>-<executor>.zip`
## 10. 方案B:Python 脚本一键模拟(完整实现)
仓库已提供可执行脚本:
- `maven-cw-elevator-application/tools/visitor_floor_verification/scripts/simulate_gf_visitor_flow.py`
### 10.1 安装依赖
```bash
cd maven-cw-elevator-application/tools/visitor_floor_verification
python3 -m pip install -r requirements.txt
```
### 10.2 设置请求头环境变量
```bash
export ELEVATOR_HEADER_AUTHORIZATION='Bearer <TOKEN>'
export ELEVATOR_HEADER_LOGINID='<LOGIN_ID>'
export ELEVATOR_HEADER_PLATFORMUSERID='<PLATFORM_USER_ID>'
export ELEVATOR_HEADER_APPLICATIONID='<APPLICATION_ID>'
```
说明:`businessid` 由脚本参数 `--business-id` 自动注入,同时也会写入 `ELEVATOR_HEADER_BUSINESSID`
### 10.3 执行脚本
```bash
python3 scripts/simulate_gf_visitor_flow.py \
--org-base-url "http://<ORG_HOST>:<ORG_PORT>" \
--elevator-base-url "http://<ELEVATOR_HOST>:<ELEVATOR_PORT>" \
--meng-person-id "<MENG_HAI_WEN_PERSON_ID>" \
--visitor-person-id "<TEST_VISITOR_PERSON_ID>" \
--business-id "2524639890ba4f2cba9ba1a4eeaa4015" \
--window-hours 24 \
--strict-name-check
```
### 10.4 输出与判定
- 控制台会打印三步调用的关键摘要(详情 code、回读 data 条数、是否全通过)。
- 报告文件自动生成到:
- `maven-cw-elevator-application/tools/visitor_floor_verification/report/gf-visitor-sim-<timestamp>.json`
- 若脚本退出码为 `0` 表示检查通过;退出码为 `1` 表示存在未通过项,需查看报告里的 `checks``steps` 字段。
@@ -0,0 +1,140 @@
# 访客接口无鉴权调用评估与生产快测方案
## 1. 目标
- 基于生产日志评估“无鉴权调用访客接口”的真实边界。
- 给出生产可执行的快测方案,验证访客楼层策略是否生效。
- 通过脚本同时支持:
- `auth`:标准鉴权验证(正式验收路径)
- `noauth-probe`:无鉴权探测(安全风险判定,不作业务通过依据)
## 2. 日志证据与边界结论
日志来源:
- `maven-cw-elevator-application/logs/访客相关接口日志分析/日志分析/访客调用楼层放开接口清单.md`
- `maven-cw-elevator-application/logs/访客相关接口日志分析/日志分析/10.0.22.209/202604301713/logs/elevator-app.log`
关键证据:
- 文档中同时存在“JWT 调用”和“无鉴权(username)调用”样本。
- 但同批日志中的 `PersonRuleServiceImpl:196` 记录可见 `CloudwalkCallContext` 已包含:
- `company.companyId`
- `user.callerName`
- 部分请求带 `ext.value.authorization`JWT 场景)
边界判定:
1. 观察到的“无 Authorization header”不能直接等价为“外部匿名可裸调”。
2. 更可能是平台或网关已注入上下文后触发的内部调用路径。
3. 生产对外验证必须以 `auth` 模式为准。
4. `noauth-probe` 仅用于探测当前网关/应用是否放开了不应放开的入口。
## 3. 快测脚本与模式
脚本路径:
- `maven-cw-elevator-application/tools/visitor_floor_verification/scripts/quick_verify_visitor_floor_policy.py`
### 3.1 auth 模式(正式)
三步调用:
1. `POST /component/person/detail`
2. `POST /elevator/person/add/visitor`
3. `POST /elevator/passRule/image`
请求头采用 `ELEVATOR_HEADER_*`authorization/loginid/platformuserid/applicationid+ `businessid`
### 3.2 noauth-probe 模式(探测)
- 仅发送 `Content-Type`,可选附加 `businessid`
- 不发送 Authorization、loginid、platformuserid、applicationid。
- 输出状态码/业务码用于判定“是否存在风险放开”。
## 4. 结果分级规则
### 4.1 auth 模式
- 通过:
- 三步 HTTP 均成功返回;
- `add/visitor` 业务成功,或返回 `76260532`(交集为空,预期失败);
- `passRule/image` 返回可解析数据。
- 失败:
- HTTP 4xx/5xx、超时、响应不可解析;
- 关键业务码异常且不属于 `76260532`
### 4.2 noauth-probe 模式
- 预期拦截(正常):
- 返回 401/403,或明确鉴权失败业务码。
- 安全异常(高风险):
- 返回 2xx 且业务成功(特别是 `add/visitor` 成功)。
- 待排查:
- 返回 2xx 但业务失败且错误语义不清晰,需要结合网关策略判断。
## 5. 运行方式
先准备头信息(auth 模式):
```bash
cd maven-cw-elevator-application/tools/visitor_floor_verification
python3 -m pip install -r requirements.txt
export ELEVATOR_HEADER_AUTHORIZATION='Bearer <TOKEN>'
export ELEVATOR_HEADER_LOGINID='<LOGIN_ID>'
export ELEVATOR_HEADER_PLATFORMUSERID='<PLATFORM_USER_ID>'
export ELEVATOR_HEADER_APPLICATIONID='<APPLICATION_ID>'
```
也可使用模板文件:
- `maven-cw-elevator-application/tools/visitor_floor_verification/.env.quick_verify.example`
例如:
```bash
set -a
source .env.quick_verify
set +a
```
auth 模式(正式验收):
```bash
python3 scripts/quick_verify_visitor_floor_policy.py \
--mode auth \
--org-base-url "http://<ORG_HOST>:<ORG_PORT>" \
--elevator-base-url "http://<ELEVATOR_HOST>:<ELEVATOR_PORT>" \
--meng-person-id "<MENG_HAI_WEN_PERSON_ID>" \
--visitor-person-id "<TEST_VISITOR_PERSON_ID>" \
--business-id "2524639890ba4f2cba9ba1a4eeaa4015" \
--strict-name-check
```
noauth-probe 模式(可选一次):
```bash
python3 scripts/quick_verify_visitor_floor_policy.py \
--mode noauth-probe \
--org-base-url "http://<ORG_HOST>:<ORG_PORT>" \
--elevator-base-url "http://<ELEVATOR_HOST>:<ELEVATOR_PORT>" \
--meng-person-id "<MENG_HAI_WEN_PERSON_ID>" \
--visitor-person-id "<TEST_VISITOR_PERSON_ID>" \
--business-id "2524639890ba4f2cba9ba1a4eeaa4015" \
--probe-with-businessid
```
## 6. 报告与留痕
脚本输出:
- 控制台摘要(模式、三步状态、业务码、风险级别)
- 报告文件:`report/quick-verify-<timestamp>.json`
建议归档:
- 本次执行命令
- 报告 JSON
- 对应时段接口日志摘录
- 最终分级(通过 / 预期拦截 / 高风险)