mirror of
https://github.com/hpd840321/starRiverProperty.git
synced 2026-06-09 08:20:31 +08:00
feat: add service config templates and extraction script
Former-commit-id: 1de24b7eb79676d1aba9d799a58c5a753290cf52
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
||||
2026-05-01 09:04:54.516 INFO 2350110 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@11b94e1f: startup date [Fri May 01 09:04:54 CST 2026]; root of context hierarchy
|
||||
2026-05-01 09:04:55.025 INFO 2350110 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
|
||||
2026-05-01 09:04:55.161 INFO 2350110 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$bfb56f03] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|
||||
2026-05-01 09:06:56.929 INFO 2369891 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1af5258a: startup date [Fri May 01 09:06:56 CST 2026]; root of context hierarchy
|
||||
2026-05-01 09:06:57.454 INFO 2369891 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
|
||||
2026-05-01 09:06:57.589 INFO 2369891 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$458573b2] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|
||||
2026-05-01 09:09:11.126 INFO 2398157 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@11b94e1f: startup date [Fri May 01 09:09:11 CST 2026]; root of context hierarchy
|
||||
2026-05-01 09:09:11.658 INFO 2398157 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
|
||||
2026-05-01 09:09:11.786 INFO 2398157 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$bfb56f03] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|
||||
2026-05-01 09:11:55.543 INFO 2422452 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@8d4f3ea: startup date [Fri May 01 09:11:55 CST 2026]; root of context hierarchy
|
||||
2026-05-01 09:11:56.085 INFO 2422452 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
|
||||
2026-05-01 09:11:56.251 INFO 2422452 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$fd73c5e7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|
||||
2026-05-01 09:39:43.342 INFO 2707482 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1ca8f300: startup date [Fri May 01 09:39:43 CST 2026]; root of context hierarchy
|
||||
2026-05-01 09:39:43.895 INFO 2707482 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
|
||||
2026-05-01 09:39:44.030 INFO 2707482 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$fd878d1d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|
||||
2026-05-01 09:40:09.489 INFO 2715657 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@11b94e1f: startup date [Fri May 01 09:40:09 CST 2026]; root of context hierarchy
|
||||
2026-05-01 09:40:09.989 INFO 2715657 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
|
||||
2026-05-01 09:40:10.119 INFO 2715657 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$bfb56f03] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|
||||
2026-05-01 09:42:59.749 INFO 2740611 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@11b94e1f: startup date [Fri May 01 09:42:59 CST 2026]; root of context hierarchy
|
||||
2026-05-01 09:43:00.296 INFO 2740611 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
|
||||
2026-05-01 09:43:00.440 INFO 2740611 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$bfb56f03] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|
||||
2026-05-01 09:44:54.553 INFO 2762141 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@8d4f3ea: startup date [Fri May 01 09:44:54 CST 2026]; root of context hierarchy
|
||||
2026-05-01 09:44:55.070 INFO 2762141 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
|
||||
2026-05-01 09:44:55.194 INFO 2762141 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$fd73c5e7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|
||||
2026-05-01 10:06:11.259 INFO 2989479 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@8d4f3ea: startup date [Fri May 01 10:06:11 CST 2026]; root of context hierarchy
|
||||
2026-05-01 10:06:11.823 INFO 2989479 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
|
||||
2026-05-01 10:06:11.969 INFO 2989479 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$fd73c5e7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|
||||
2026-05-01 10:12:29.746 INFO 3058557 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@8d4f3ea: startup date [Fri May 01 10:12:29 CST 2026]; root of context hierarchy
|
||||
2026-05-01 10:12:30.160 INFO 3058557 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
|
||||
2026-05-01 10:12:30.315 INFO 3058557 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$9f47d511] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|
||||
2026-05-01 10:15:35.243 INFO 3090857 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@11b94e1f: startup date [Fri May 01 10:15:35 CST 2026]; root of context hierarchy
|
||||
2026-05-01 10:15:35.741 INFO 3090857 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
|
||||
2026-05-01 10:15:35.865 INFO 3090857 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$e903ef56] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|
||||
2026-05-01 10:55:13.521 INFO 3505858 --- [main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@11b94e1f: startup date [Fri May 01 10:55:13 CST 2026]; root of context hierarchy
|
||||
2026-05-01 10:55:14.131 INFO 3505858 --- [main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
|
||||
2026-05-01 10:55:14.290 INFO 3505858 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$ddba3097] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
|
||||
+27
-22
@@ -383,47 +383,52 @@ public class DateUtils {
|
||||
case 0:
|
||||
nowStartTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
|
||||
nowEndTime = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
|
||||
timeList.add(new StartTimeAndEndTime(Long.valueOf(nowStartTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
Long.valueOf(nowEndTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
nowStartTime.getDayOfMonth() + "号"));
|
||||
timeList.add(
|
||||
new StartTimeAndEndTime(Long.valueOf(nowStartTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
Long.valueOf(nowEndTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
nowStartTime.getDayOfMonth() + "号"));
|
||||
for (i = 1; i < cycleNum; i++) {
|
||||
LocalDateTime firstDay = nowStartTime.minusDays(i);
|
||||
LocalDateTime lastDay = nowEndTime.minusDays(i);
|
||||
timeList.add(new StartTimeAndEndTime(Long.valueOf(firstDay.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
Long.valueOf(lastDay.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
firstDay.getDayOfMonth() + "号"));
|
||||
timeList.add(
|
||||
new StartTimeAndEndTime(Long.valueOf(firstDay.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
Long.valueOf(lastDay.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
firstDay.getDayOfMonth() + "号"));
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
nowMonday = LocalDateTime.of(LocalDate.now(), LocalTime.MIN).with(DayOfWeek.MONDAY);
|
||||
nowSunday = LocalDateTime.of(LocalDate.now(), LocalTime.MAX).with(DayOfWeek.SUNDAY);
|
||||
timeList.add(new StartTimeAndEndTime(Long.valueOf(nowMonday.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
Long.valueOf(nowSunday.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
nowMonday.get(WeekFields.ISO.weekOfWeekBasedYear()) + "周"));
|
||||
timeList
|
||||
.add(new StartTimeAndEndTime(Long.valueOf(nowMonday.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
Long.valueOf(nowSunday.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
nowMonday.get(WeekFields.ISO.weekOfWeekBasedYear()) + "周"));
|
||||
for (j = 1; j < cycleNum; j++) {
|
||||
LocalDateTime lastMonday = nowMonday.minusWeeks(j);
|
||||
LocalDateTime lastSunday = nowSunday.minusWeeks(j);
|
||||
timeList.add(new StartTimeAndEndTime(Long.valueOf(lastMonday.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
Long.valueOf(lastSunday.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
lastMonday.get(WeekFields.ISO.weekOfWeekBasedYear()) + "周"));
|
||||
timeList.add(
|
||||
new StartTimeAndEndTime(Long.valueOf(lastMonday.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
Long.valueOf(lastSunday.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
lastMonday.get(WeekFields.ISO.weekOfWeekBasedYear()) + "周"));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
nowFirstDay =
|
||||
LocalDateTime.of(LocalDate.now(), LocalTime.MIN).with(TemporalAdjusters.firstDayOfMonth());
|
||||
nowLastDay =
|
||||
LocalDateTime.of(LocalDate.now(), LocalTime.MAX).with(TemporalAdjusters.lastDayOfMonth());
|
||||
timeList.add(new StartTimeAndEndTime(Long.valueOf(nowFirstDay.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
Long.valueOf(nowLastDay.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
nowFirstDay.get(ChronoField.MONTH_OF_YEAR) + "月"));
|
||||
nowLastDay = LocalDateTime.of(LocalDate.now(), LocalTime.MAX).with(TemporalAdjusters.lastDayOfMonth());
|
||||
timeList.add(
|
||||
new StartTimeAndEndTime(Long.valueOf(nowFirstDay.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
Long.valueOf(nowLastDay.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
nowFirstDay.get(ChronoField.MONTH_OF_YEAR) + "月"));
|
||||
for (k = 1; k < cycleNum; k++) {
|
||||
LocalDateTime firstDay =
|
||||
LocalDateTime.now().minusMonths(k).with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
|
||||
LocalDateTime firstDay = LocalDateTime.now().minusMonths(k)
|
||||
.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
|
||||
LocalDateTime lastDay =
|
||||
LocalDateTime.now().minusMonths(k).with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
|
||||
timeList.add(new StartTimeAndEndTime(Long.valueOf(firstDay.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
Long.valueOf(lastDay.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
firstDay.get(ChronoField.MONTH_OF_YEAR) + "月"));
|
||||
timeList.add(
|
||||
new StartTimeAndEndTime(Long.valueOf(firstDay.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
Long.valueOf(lastDay.toInstant(ZoneOffset.of("+8")).toEpochMilli()),
|
||||
firstDay.get(ChronoField.MONTH_OF_YEAR) + "月"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
+1
-7
@@ -4,11 +4,5 @@ import cn.cloudwalk.elevator.person.dto.TenantVisitorFloorPolicyDto;
|
||||
|
||||
public interface TenantVisitorFloorPolicyDao {
|
||||
|
||||
/**
|
||||
* 查询租户级启用中的 INTERSECT_ALLOWLIST 策略(building_id 为空)。
|
||||
*
|
||||
* @param businessId 机构 ID
|
||||
* @return 无配置时 null
|
||||
*/
|
||||
TenantVisitorFloorPolicyDto selectEnabledTenantDefault(String businessId);
|
||||
TenantVisitorFloorPolicyDto selectEnabledByOrgId(String orgId);
|
||||
}
|
||||
|
||||
+9
@@ -7,6 +7,7 @@ public class TenantVisitorFloorPolicyDto {
|
||||
|
||||
private String id;
|
||||
private String businessId;
|
||||
private String orgId;
|
||||
private String policyType;
|
||||
private String allowZoneIds;
|
||||
private String buildingId;
|
||||
@@ -29,6 +30,14 @@ public class TenantVisitorFloorPolicyDto {
|
||||
this.businessId = businessId;
|
||||
}
|
||||
|
||||
public String getOrgId() {
|
||||
return orgId;
|
||||
}
|
||||
|
||||
public void setOrgId(String orgId) {
|
||||
this.orgId = orgId;
|
||||
}
|
||||
|
||||
public String getPolicyType() {
|
||||
return policyType;
|
||||
}
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ public class TenantVisitorFloorPolicyDaoImpl implements TenantVisitorFloorPolicy
|
||||
private TenantVisitorFloorPolicyMapper tenantVisitorFloorPolicyMapper;
|
||||
|
||||
@Override
|
||||
public TenantVisitorFloorPolicyDto selectEnabledTenantDefault(String businessId) {
|
||||
return this.tenantVisitorFloorPolicyMapper.selectEnabledTenantDefault(businessId);
|
||||
public TenantVisitorFloorPolicyDto selectEnabledByOrgId(String orgId) {
|
||||
return this.tenantVisitorFloorPolicyMapper.selectEnabledByOrgId(orgId);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-4
@@ -5,8 +5,5 @@ import org.apache.ibatis.annotations.Param;
|
||||
|
||||
public interface TenantVisitorFloorPolicyMapper {
|
||||
|
||||
/**
|
||||
* 租户级默认策略:building_id 为空,启用,INTERSECT_ALLOWLIST。
|
||||
*/
|
||||
TenantVisitorFloorPolicyDto selectEnabledTenantDefault(@Param("businessId") String businessId);
|
||||
TenantVisitorFloorPolicyDto selectEnabledByOrgId(@Param("orgId") String orgId);
|
||||
}
|
||||
|
||||
+8
-8
@@ -3,16 +3,16 @@
|
||||
|
||||
<mapper namespace="cn.cloudwalk.elevator.person.mapper.TenantVisitorFloorPolicyMapper">
|
||||
|
||||
<select id="selectEnabledTenantDefault" resultType="cn.cloudwalk.elevator.person.dto.TenantVisitorFloorPolicyDto">
|
||||
<select id="selectEnabledByOrgId" resultType="cn.cloudwalk.elevator.person.dto.TenantVisitorFloorPolicyDto">
|
||||
SELECT id,
|
||||
business_id AS businessId,
|
||||
policy_type AS policyType,
|
||||
allow_zone_ids AS allowZoneIds,
|
||||
building_id AS buildingId,
|
||||
enabled AS enabled,
|
||||
policy_version AS policyVersion
|
||||
org_id AS orgId,
|
||||
policy_type AS policyType,
|
||||
allow_zone_ids AS allowZoneIds,
|
||||
building_id AS buildingId,
|
||||
enabled AS enabled,
|
||||
policy_version AS policyVersion
|
||||
FROM tenant_visitor_floor_policy
|
||||
WHERE business_id = #{businessId,jdbcType=VARCHAR}
|
||||
WHERE org_id = #{orgId,jdbcType=VARCHAR}
|
||||
AND enabled = 1
|
||||
AND policy_type = 'INTERSECT_ALLOWLIST'
|
||||
AND (building_id IS NULL OR building_id = '')
|
||||
|
||||
@@ -43,6 +43,102 @@
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk</groupId>
|
||||
<artifactId>cwos-java-sdk-resource</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>cn.cloudwalk</groupId>
|
||||
<artifactId>cwos-portal-interface</artifactId>
|
||||
</exclusion>
|
||||
<!-- 部分私服 POM 仍传递 stub,双保险 -->
|
||||
<exclusion>
|
||||
<groupId>cn.cloudwalk</groupId>
|
||||
<artifactId>cwos-device-pkg-stub</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- 自行声明 portal,排除 V2 引入的 stub / validator 6.x / validation starter,贴近 V1 lib -->
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk</groupId>
|
||||
<artifactId>cwos-portal-interface</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>cn.cloudwalk</groupId>
|
||||
<artifactId>cwos-device-pkg-stub</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- V1 fat-jar 中出现的扩展链(历史 starter 传递) -->
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cloudwalk-device-manager-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cloudwalk-device-manager-interface</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cwos-common-aks-interface</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cwos-device-authentication-interface</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk</groupId>
|
||||
<artifactId>cloudwalk-device-sdk-protocol-entity</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
|
||||
</dependency>
|
||||
<!-- V1 fat-jar 中与本业务相邻出现的扩展库(补齐后与 baseline multiset 更接近) -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.module</groupId>
|
||||
<artifactId>jackson-module-afterburner</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okio</groupId>
|
||||
<artifactId>okio</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.opencsv</groupId>
|
||||
<artifactId>opencsv</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
@@ -81,6 +177,27 @@
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
<!-- V1 fat-jar 中独立出现的 Netflix / Consul starters(与 OpenFeign 并存) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-consul</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-ribbon</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
|
||||
+15
-15
@@ -1,15 +1,15 @@
|
||||
package cn.cloudwalk.elevator;
|
||||
|
||||
import cn.cloudwalk.cloud.context.CloudwalkSessionContextHolder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/** 未扫描 {@code cn.cloudwalk.web} 时,等价于 LocaleConfiguration 中的 SessionHolder Bean。 */
|
||||
@Configuration
|
||||
public class CloudwalkSessionHolderConfiguration {
|
||||
|
||||
@Bean
|
||||
public CloudwalkSessionContextHolder cloudwalkSessionContextHolder() {
|
||||
return new CloudwalkSessionContextHolder();
|
||||
}
|
||||
}
|
||||
package cn.cloudwalk.elevator;
|
||||
|
||||
import cn.cloudwalk.cloud.context.CloudwalkSessionContextHolder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/** 未扫描 {@code cn.cloudwalk.web} 时,等价于 LocaleConfiguration 中的 SessionHolder Bean。 */
|
||||
@Configuration
|
||||
public class CloudwalkSessionHolderConfiguration {
|
||||
|
||||
@Bean
|
||||
public CloudwalkSessionContextHolder cloudwalkSessionContextHolder() {
|
||||
return new CloudwalkSessionContextHolder();
|
||||
}
|
||||
}
|
||||
|
||||
+10
-11
@@ -38,8 +38,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* 设备异步任务:推进绑定进度、按楼层增删人员/规则;{@code updateFloors} 在楼层维度使用有界线程池并行远程调用,并按 Future 完成顺序推进
|
||||
* {@code bindDevices},与走查约定 §9 一致。
|
||||
* 设备异步任务:推进绑定进度、按楼层增删人员/规则;{@code updateFloors} 在楼层维度使用有界线程池并行远程调用,并按 Future 完成顺序推进 {@code bindDevices},与走查约定 §9 一致。
|
||||
*/
|
||||
@Service
|
||||
public class AcsDeviceTaskServiceImpl extends AbstractAcsDeviceService implements AcsDeviceTaskService {
|
||||
@@ -81,18 +80,17 @@ public class AcsDeviceTaskServiceImpl extends AbstractAcsDeviceService implement
|
||||
}
|
||||
|
||||
/**
|
||||
* 约定 §3.5:楼层级有界并行发起远程调用;本方法内按原列表顺序 {@code get()} Future,
|
||||
* 与串行时一致地「每成功一层 → 重读任务行并 BIND_DEVICES+1」。
|
||||
* 约定 §3.5:楼层级有界并行发起远程调用;本方法内按原列表顺序 {@code get()} Future, 与串行时一致地「每成功一层 → 重读任务行并 BIND_DEVICES+1」。
|
||||
*/
|
||||
private void runAddFloorsInBoundedParallel(AcsRestructureBindingParam param, List<AcsPassRuleImageResultDto> addFloors,
|
||||
CloudwalkCallContext context) throws ServiceException {
|
||||
private void runAddFloorsInBoundedParallel(AcsRestructureBindingParam param,
|
||||
List<AcsPassRuleImageResultDto> addFloors, CloudwalkCallContext context) throws ServiceException {
|
||||
for (int i = 0; i < addFloors.size(); i += UPDATE_FLOORS_FLOOR_PARALLEL) {
|
||||
int end = Math.min(i + UPDATE_FLOORS_FLOOR_PARALLEL, addFloors.size());
|
||||
List<Callable<Integer>> batch = new ArrayList<>();
|
||||
for (int j = i; j < end; j++) {
|
||||
final AcsPassRuleImageResultDto addFloor = addFloors.get(j);
|
||||
batch.add(
|
||||
() -> FeignThreadLocalUtil.callWithContext(context, () -> addOneFloorStep(addFloor, param, context)));
|
||||
batch.add(() -> FeignThreadLocalUtil.callWithContext(context,
|
||||
() -> addOneFloorStep(addFloor, param, context)));
|
||||
}
|
||||
List<Future<Integer>> futures;
|
||||
try {
|
||||
@@ -129,8 +127,8 @@ public class AcsDeviceTaskServiceImpl extends AbstractAcsDeviceService implement
|
||||
List<Callable<Integer>> batch = new ArrayList<>();
|
||||
for (int j = i; j < end; j++) {
|
||||
final String delFloorId = delFloorIds.get(j);
|
||||
batch.add(
|
||||
() -> FeignThreadLocalUtil.callWithContext(context, () -> delOneFloorStep(delFloorId, param, ruleMap, context)));
|
||||
batch.add(() -> FeignThreadLocalUtil.callWithContext(context,
|
||||
() -> delOneFloorStep(delFloorId, param, ruleMap, context)));
|
||||
}
|
||||
List<Future<Integer>> futures;
|
||||
try {
|
||||
@@ -260,7 +258,8 @@ public class AcsDeviceTaskServiceImpl extends AbstractAcsDeviceService implement
|
||||
try {
|
||||
this.imageRuleRefDao.deleteByOrgAndLabel(dto);
|
||||
} catch (DataAccessException e) {
|
||||
this.logger.error("updateFloors deleteByOrgAndLabel 失败 delFloorId={} {}", delFloorId, e.getMessage());
|
||||
this.logger.error("updateFloors deleteByOrgAndLabel 失败 delFloorId={} {}", delFloorId,
|
||||
e.getMessage());
|
||||
throw new ServiceException("76260540", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
+5
-8
@@ -411,8 +411,7 @@ public class AcsElevatorDeviceServiceImpl extends AbstractAcsPassService impleme
|
||||
ArrayList<String> deviceIds = new ArrayList<>();
|
||||
HashMap<String, DeviceResult> mapDevice = new HashMap<>();
|
||||
if (!CollectionUtils.isEmpty(deviceList)) {
|
||||
deviceList.forEach(
|
||||
device -> deviceIds.add(((AcsElevatorDeviceResultDTO)device).getDeviceId()));
|
||||
deviceList.forEach(device -> deviceIds.add(((AcsElevatorDeviceResultDTO)device).getDeviceId()));
|
||||
DeviceQueryParam queryParam = new DeviceQueryParam();
|
||||
queryParam.setBusinessId(context.getCompany().getCompanyId());
|
||||
queryParam.setIds(deviceIds);
|
||||
@@ -441,8 +440,8 @@ public class AcsElevatorDeviceServiceImpl extends AbstractAcsPassService impleme
|
||||
DeviceResult deviceResult;
|
||||
if (!floor2.getZoneId()
|
||||
.equals(((AcsElevatorDeviceResultDTO)deviceList.get(i)).getCurrentFloorId())
|
||||
|| ObjectUtils.isEmpty((deviceResult = mapDevice
|
||||
.get(((AcsElevatorDeviceResultDTO)deviceList.get(i)).getDeviceId())))) {
|
||||
|| ObjectUtils.isEmpty((deviceResult =
|
||||
mapDevice.get(((AcsElevatorDeviceResultDTO)deviceList.get(i)).getDeviceId())))) {
|
||||
continue;
|
||||
}
|
||||
if ("2".equals(deviceResult.getOnlineStatus())) {
|
||||
@@ -518,8 +517,7 @@ public class AcsElevatorDeviceServiceImpl extends AbstractAcsPassService impleme
|
||||
List deviceList = this.acsElevatorDeviceDao.listByZoneIds(listDto);
|
||||
if (!CollectionUtils.isEmpty(deviceList)) {
|
||||
ArrayList<String> deviceIds = new ArrayList<>();
|
||||
deviceList.forEach(
|
||||
device -> deviceIds.add(((AcsElevatorDeviceResultDTO)device).getDeviceId()));
|
||||
deviceList.forEach(device -> deviceIds.add(((AcsElevatorDeviceResultDTO)device).getDeviceId()));
|
||||
HashMap<String, DeviceResult> mapDevice = new HashMap<>();
|
||||
DeviceQueryParam queryParam = new DeviceQueryParam();
|
||||
queryParam.setBusinessId(context.getCompany().getCompanyId());
|
||||
@@ -549,8 +547,7 @@ public class AcsElevatorDeviceServiceImpl extends AbstractAcsPassService impleme
|
||||
}
|
||||
DeviceResult deviceResult =
|
||||
mapDevice.get(((AcsElevatorDeviceResultDTO)deviceList.get(i)).getDeviceId());
|
||||
result.setParentId(
|
||||
((AcsElevatorDeviceResultDTO)deviceList.get(i)).getCurrentBuildingId());
|
||||
result.setParentId(((AcsElevatorDeviceResultDTO)deviceList.get(i)).getCurrentBuildingId());
|
||||
if (ObjectUtils.isEmpty(deviceResult)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 设备域服务层:电梯设备查询/编辑、设备任务(含楼层变更)、设备侧设置与图库应用绑定等编排。
|
||||
* <p>
|
||||
* 同包名在 data 模块中承担 DAO/Mapper;此处仅放接口、入参出参与 {@code impl} 实现,表结构见 data 包说明。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.device;
|
||||
/**
|
||||
* 设备域服务层:电梯设备查询/编辑、设备任务(含楼层变更)、设备侧设置与图库应用绑定等编排。
|
||||
* <p>
|
||||
* 同包名在 data 模块中承担 DAO/Mapper;此处仅放接口、入参出参与 {@code impl} 实现,表结构见 data 包说明。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.device;
|
||||
|
||||
+1
@@ -13,6 +13,7 @@ import org.springframework.stereotype.Component;
|
||||
public class MqttFeignClientFallback implements MqttFeignClient {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec 不返回降级业务结果,直接抛错以暴露下游不可用
|
||||
*/
|
||||
@Override
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 电梯识别记录 MQTT 推送:经 {@code cloudwalk-device-thirdparty} 等下游将消息发布到业务 topic,供大屏/第三方订阅。
|
||||
* <p>
|
||||
* 与 {@code record} 域协作:在人员识别记录落库后异步组装载荷并调用发布接口。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.mqtt;
|
||||
/**
|
||||
* 电梯识别记录 MQTT 推送:经 {@code cloudwalk-device-thirdparty} 等下游将消息发布到业务 topic,供大屏/第三方订阅。
|
||||
* <p>
|
||||
* 与 {@code record} 域协作:在人员识别记录落库后异步组装载荷并调用发布接口。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.mqtt;
|
||||
|
||||
+2
-1
@@ -1,7 +1,8 @@
|
||||
package cn.cloudwalk.elevator.mqtt.param;
|
||||
|
||||
/**
|
||||
* 推送到 MQTT 的电梯记录载荷:在 {@link cn.cloudwalk.elevator.record.dto.AcsElevatorRecordAddDTO} 基础上补全人名、开门流水 id、是否访客等,序列化为 {@code data} 字段内容。
|
||||
* 推送到 MQTT 的电梯记录载荷:在 {@link cn.cloudwalk.elevator.record.dto.AcsElevatorRecordAddDTO} 基础上补全人名、开门流水 id、是否访客等,序列化为
|
||||
* {@code data} 字段内容。
|
||||
*/
|
||||
public class AcsElevatorRecordMqttParam {
|
||||
private String openDoorId;
|
||||
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* 电梯应用业务编排层({@code cw-elevator-application-service}):领域服务接口与实现、远程调用、异步与任务推进。
|
||||
* <p>
|
||||
* 与 {@code cw-elevator-application-data} 的持久化、{@code cw-elevator-application-web} 的 HTTP 入口分工协作;
|
||||
* 本模块内可依赖对外 Feign 契约(如 {@code intelligent-cwoscomponent-interface}),但不应向上依赖 Web 层。
|
||||
*/
|
||||
package cn.cloudwalk.elevator;
|
||||
/**
|
||||
* 电梯应用业务编排层({@code cw-elevator-application-service}):领域服务接口与实现、远程调用、异步与任务推进。
|
||||
* <p>
|
||||
* 与 {@code cw-elevator-application-data} 的持久化、{@code cw-elevator-application-web} 的 HTTP 入口分工协作; 本模块内可依赖对外 Feign 契约(如
|
||||
* {@code intelligent-cwoscomponent-interface}),但不应向上依赖 Web 层。
|
||||
*/
|
||||
package cn.cloudwalk.elevator;
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 通行/人员规则与图库规则引用:规则增删、与区域/标签/组织维度的组合,及与设备任务的协作。
|
||||
* <p>
|
||||
* 与 {@code person} 包在“按人下发”和“按规则下发”两种路径上常共同出现在设备任务流中。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.passrule;
|
||||
/**
|
||||
* 通行/人员规则与图库规则引用:规则增删、与区域/标签/组织维度的组合,及与设备任务的协作。
|
||||
* <p>
|
||||
* 与 {@code person} 包在“按人下发”和“按规则下发”两种路径上常共同出现在设备任务流中。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.passrule;
|
||||
|
||||
+59
-20
@@ -195,24 +195,24 @@ public class PersonRuleServiceImpl extends AbstractAcsPassService implements Per
|
||||
if (CollectionUtils.isEmpty(hostFloors)) {
|
||||
return CloudwalkResult.fail("76260531", getMessage("76260531"));
|
||||
}
|
||||
List<String> effectiveFloors = hostFloors;
|
||||
TenantVisitorFloorPolicyDto policy =
|
||||
this.tenantVisitorFloorPolicyDao.selectEnabledTenantDefault(context.getCompany().getCompanyId());
|
||||
if (policy != null && policy.getEnabled() != null && policy.getEnabled().intValue() == 1) {
|
||||
List<String> allow = parseAllowZoneIds(policy.getAllowZoneIds());
|
||||
if (!CollectionUtils.isEmpty(allow)) {
|
||||
Set<String> allowSet = new HashSet<>(allow);
|
||||
List<String> intersected = intersectPreserveHostOrder(hostFloors, allowSet);
|
||||
if (intersected.isEmpty()) {
|
||||
return CloudwalkResult.fail("76260532", getMessage("76260532"));
|
||||
}
|
||||
effectiveFloors = intersected;
|
||||
this.logger.info(
|
||||
"租户访客楼层策略求交 businessId={} personId={} visitorId={} policyId={} policyVersion={} effectiveSize={}",
|
||||
context.getCompany().getCompanyId(), param.getPersonId(), param.getVisitorId(),
|
||||
policy.getId(), policy.getPolicyVersion(), Integer.valueOf(intersected.size()));
|
||||
List<String> effectiveFloors;
|
||||
TenantVisitorFloorPolicyDto policy = findPolicyByOrgIds(personResult.getOrganizationIds());
|
||||
if (policy != null) {
|
||||
effectiveFloors = resolveEffectiveFloors(callerProvidedFloors ? param.getFloorIds() : hostFloors,
|
||||
hostFloors, policy, param.getPersonId());
|
||||
} else {
|
||||
effectiveFloors = hostFloors;
|
||||
Set<String> hostSet = new HashSet<>(hostFloors);
|
||||
List<String> outliers =
|
||||
param.getFloorIds().stream().filter(f -> !hostSet.contains(f)).collect(Collectors.toList());
|
||||
if (!outliers.isEmpty()) {
|
||||
this.logger.warn("UC-02 传入非被访人授权楼层 businessId={} personId={} outliers={}",
|
||||
context.getCompany().getCompanyId(), param.getPersonId(), outliers);
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isEmpty(effectiveFloors)) {
|
||||
return CloudwalkResult.fail("76260531", getMessage("76260531"));
|
||||
}
|
||||
param.setFloorIds(effectiveFloors);
|
||||
}
|
||||
if (CollectionUtils.isEmpty(param.getFloorIds())) {
|
||||
@@ -274,6 +274,47 @@ public class PersonRuleServiceImpl extends AbstractAcsPassService implements Per
|
||||
return CloudwalkResult.success(Boolean.valueOf(true));
|
||||
}
|
||||
|
||||
private TenantVisitorFloorPolicyDto findPolicyByOrgIds(List<String> orgIds) {
|
||||
if (CollectionUtils.isEmpty(orgIds)) {
|
||||
return null;
|
||||
}
|
||||
for (String orgId : orgIds) {
|
||||
TenantVisitorFloorPolicyDto p = this.tenantVisitorFloorPolicyDao.selectEnabledByOrgId(orgId);
|
||||
if (p != null && p.getEnabled() != null && p.getEnabled().intValue() == 1) {
|
||||
List<String> allow = parseAllowZoneIds(p.getAllowZoneIds());
|
||||
if (!CollectionUtils.isEmpty(allow)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<String> resolveEffectiveFloors(List<String> fallbackFloorsUnused, List<String> hostFloors,
|
||||
TenantVisitorFloorPolicyDto policy, String personId) throws ServiceException {
|
||||
String rawJson = policy.getAllowZoneIds();
|
||||
List<String> allow = parseAllowZoneIds(rawJson);
|
||||
if (CollectionUtils.isEmpty(allow)) {
|
||||
if (!StringUtils.isBlank(rawJson)) {
|
||||
this.logger.error("allow_zone_ids JSON 无效或为空,策略失效 orgId={} policyId={} raw={}", policy.getOrgId(),
|
||||
policy.getId(), rawJson);
|
||||
}
|
||||
return fallbackFloorsUnused;
|
||||
}
|
||||
Set<String> hostSet = new HashSet<>(hostFloors);
|
||||
List<String> unknownAllow = allow.stream().filter(a -> !hostSet.contains(a)).collect(Collectors.toList());
|
||||
if (!unknownAllow.isEmpty()) {
|
||||
this.logger.error(
|
||||
"策略配置错误:allow 包含不在被访人 floorList 中的 zoneId!"
|
||||
+ "orgId={} policyId={} personId={} unknownAllow={} hostFloors={}",
|
||||
policy.getOrgId(), policy.getId(), personId, unknownAllow, hostFloors);
|
||||
throw new ServiceException("76260533", "策略配置了被访人无权访问的楼层,请联系管理员");
|
||||
}
|
||||
this.logger.info("策略生效 orgId={} policyId={} v={} allowSize={} hostSize={}", policy.getOrgId(), policy.getId(),
|
||||
policy.getPolicyVersion(), Integer.valueOf(allow.size()), Integer.valueOf(hostFloors.size()));
|
||||
return allow;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 allow_zone_ids JSON;无效或空则返回空列表(等同未配置有效策略)。
|
||||
*/
|
||||
@@ -288,14 +329,12 @@ public class PersonRuleServiceImpl extends AbstractAcsPassService implements Per
|
||||
}
|
||||
return list.stream().filter(Objects::nonNull).filter(s -> !s.isEmpty()).collect(Collectors.toList());
|
||||
} catch (Exception e) {
|
||||
this.logger.warn("allow_zone_ids JSON 无效,按无策略处理: {}", e.getMessage());
|
||||
this.logger.error("allow_zone_ids JSON 无效,按无策略处理: {}", e.getMessage());
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> intersectPreserveHostOrder(List<String> hostFloors, Set<String> allowSet) {
|
||||
return hostFloors.stream().filter(allowSet::contains).collect(Collectors.toList());
|
||||
}
|
||||
// intersectPreserveHostOrder removed in favor of org-policy-based resolution
|
||||
|
||||
public CloudwalkResult<Boolean> edit(AcsPersonEditParam param, CloudwalkCallContext context)
|
||||
throws ServiceException {
|
||||
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* 人员与人员-规则服务:人员增删、与区域/父级人员关系、及与设备侧同步相关的编排。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.person;
|
||||
/**
|
||||
* 人员与人员-规则服务:人员增删、与区域/父级人员关系、及与设备侧同步相关的编排。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.person;
|
||||
|
||||
+2
-2
@@ -91,8 +91,8 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
* <p>
|
||||
* 新增记录时通过 {@link cn.cloudwalk.elevator.util.RestTemplateUtil} 请求 {@code ninca-crk-std} 的
|
||||
* {@code intelligent/three/visitor/record/query},用识别 id 反查是否访客及被访人;该路径与
|
||||
* {@link cn.cloudwalk.elevator.visitor.client.VisitorFeignClient} 所映射的
|
||||
* {@code /intelligent/visitor/record/query} 为两套接口,本处固定走「three」版 HTTP。
|
||||
* {@link cn.cloudwalk.elevator.visitor.client.VisitorFeignClient} 所映射的 {@code /intelligent/visitor/record/query}
|
||||
* 为两套接口,本处固定走「three」版 HTTP。
|
||||
* <p>
|
||||
* {@link MqttService} 为识别结果 MQTT 推送能力,本类已注入但<strong>未直接调用</strong>;若需与入库联动,可在监听
|
||||
* {@link cn.cloudwalk.elevator.record.result.VisitorRecordPushEvent} 的处理器中显式
|
||||
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* 电梯通行/识别记录业务:查询、落库、统计,并与访客中心(HTTP「three」线或 Feign「intelligent」线)、域事件、可选 MQTT 推送协同。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.record;
|
||||
/**
|
||||
* 电梯通行/识别记录业务:查询、落库、统计,并与访客中心(HTTP「three」线或 Feign「intelligent」线)、域事件、可选 MQTT 推送协同。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.record;
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 访客主数据与识别记录查询:通过 Feign 调用 {@code ninca-crk-std} 等标准访客服务,为电梯业务侧提供访客档案与到访记录。
|
||||
* <p>
|
||||
* 本包内为入参/出参模型与客户端;业务组装与调用方在 record 等域中完成。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.visitor;
|
||||
/**
|
||||
* 访客主数据与识别记录查询:通过 Feign 调用 {@code ninca-crk-std} 等标准访客服务,为电梯业务侧提供访客档案与到访记录。
|
||||
* <p>
|
||||
* 本包内为入参/出参模型与客户端;业务组装与调用方在 record 等域中完成。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.visitor;
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 区域(园区/楼栋/楼层等)树与下一级树查询,供设备、通行与前端级联选择使用。
|
||||
* <p>
|
||||
* 多通过 Feign 拉取平台区域数据并在本包内做组装与 {@code result} 封装。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.zone;
|
||||
/**
|
||||
* 区域(园区/楼栋/楼层等)树与下一级树查询,供设备、通行与前端级联选择使用。
|
||||
* <p>
|
||||
* 多通过 Feign 拉取平台区域数据并在本包内做组装与 {@code result} 封装。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.zone;
|
||||
|
||||
@@ -13,12 +13,13 @@
|
||||
<artifactId>cw-elevator-application-starter</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>cw-elevator-application-starter</name>
|
||||
<description>可执行 Spring Boot 入口:repackage 为单 JAR 发布包(对齐历史 V1 starter 形态)。</description>
|
||||
<description>可执行入口:显式依赖与 V1 嵌套 pom 一致;传递依赖由 cw-elevator-application-web 等子模块提供。</description>
|
||||
|
||||
<properties>
|
||||
<alibaba.eclipse.codestyle.path>${project.basedir}/../../docs/style/alibaba-eclipse-codestyle.xml</alibaba.eclipse.codestyle.path>
|
||||
</properties>
|
||||
|
||||
<!-- 与 cw-elevator-application-V1.0.0.20211103/.../cw-elevator-application-starter/pom.xml 显式依赖集合一致 -->
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -32,22 +33,14 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<!-- V1 嵌套 lib 中含 cache / freemarker starter -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-cache</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk</groupId>
|
||||
<artifactId>cloudwalk-device-sdk-protocol-entity</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.elevator</groupId>
|
||||
@@ -63,10 +56,31 @@
|
||||
|
||||
<build>
|
||||
<finalName>${elevator.release.finalName}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>${project.basedir}/../deploy/v2-maven</directory>
|
||||
<includes>
|
||||
<include>bootstrap.properties</include>
|
||||
<include>application.properties</include>
|
||||
<include>application-access-control.properties</include>
|
||||
</includes>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>net.revelc.code.formatter</groupId>
|
||||
|
||||
-5
@@ -1,20 +1,15 @@
|
||||
package cn.cloudwalk.elevator;
|
||||
|
||||
import cn.cloudwalk.event.EnableCloudwalkEvent;
|
||||
import cn.cloudwalk.ribbon.NincaCrkStdRibbonConfiguration;
|
||||
import com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cloud.netflix.feign.EnableFeignClients;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonClients;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
@RibbonClients({
|
||||
@org.springframework.cloud.netflix.ribbon.RibbonClient(name = "${feign.ninca-crk-std.name:ninca-crk-std}", configuration = NincaCrkStdRibbonConfiguration.class)
|
||||
})
|
||||
@EnableCloudwalkEvent
|
||||
@EnableAsync
|
||||
@EnableCaching
|
||||
|
||||
+66
-72
@@ -1,72 +1,66 @@
|
||||
package cn.cloudwalk.elevator.config;
|
||||
|
||||
import cn.cloudwalk.elevator.integration.davinci.OpenFeignFileStorageManager;
|
||||
import cn.cloudwalk.intelligent.davinci.common.exception.DavinciServiceException;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.bean.part.dto.PartFinishDTO;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.bean.part.dto.PartInitDTO;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.bean.part.dto.PartInitResultDTO;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.manager.FilePartManager;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.manager.FileStorageManager;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.manager.impl.FilePartManagerImpl;
|
||||
import feign.Client;
|
||||
import feign.codec.Decoder;
|
||||
import feign.codec.Encoder;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.netflix.feign.FeignClientsConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Configuration
|
||||
@Import(FeignClientsConfiguration.class)
|
||||
public class DavinciStorageBeansConfiguration {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DavinciStorageBeansConfiguration.class);
|
||||
|
||||
@Bean
|
||||
public FileStorageManager fileStorageManager(
|
||||
@Value("${feign.davinci-portal.name:davinci-portal}") String serviceName,
|
||||
Decoder decoder,
|
||||
Encoder encoder,
|
||||
Client client) {
|
||||
return new OpenFeignFileStorageManager(serviceName, decoder, encoder, client);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilePartManager filePartManager(
|
||||
@Value("${feign.davinci-portal.name:davinci-portal}") String serviceName,
|
||||
Decoder decoder,
|
||||
Encoder encoder,
|
||||
Client client) {
|
||||
try {
|
||||
return new FilePartManagerImpl(serviceName, decoder, encoder, client);
|
||||
} catch (NoClassDefFoundError e) {
|
||||
LOGGER.warn("Davinci FilePartManager init failed, fallback to noop: {}", e.toString());
|
||||
return new NoopFilePartManager();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class NoopFilePartManager implements FilePartManager {
|
||||
private static final String CODE = "ELEVATOR_DAVINCI_DISABLED";
|
||||
private static final String MSG = "davinci multipart upload is unavailable in current runtime";
|
||||
|
||||
@Override
|
||||
public PartInitResultDTO init(PartInitDTO paramPartInitDTO) throws DavinciServiceException {
|
||||
throw new DavinciServiceException(CODE, MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PartInitResultDTO append(String paramString1, Integer paramInteger, String paramString2,
|
||||
org.springframework.web.multipart.MultipartFile paramMultipartFile)
|
||||
throws DavinciServiceException {
|
||||
throw new DavinciServiceException(CODE, MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String finish(PartFinishDTO paramPartFinishDTO) throws DavinciServiceException {
|
||||
throw new DavinciServiceException(CODE, MSG);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
package cn.cloudwalk.elevator.config;
|
||||
|
||||
import cn.cloudwalk.elevator.integration.davinci.OpenFeignFileStorageManager;
|
||||
import cn.cloudwalk.intelligent.davinci.common.exception.DavinciServiceException;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.bean.part.dto.PartFinishDTO;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.bean.part.dto.PartInitDTO;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.bean.part.dto.PartInitResultDTO;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.manager.FilePartManager;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.manager.FileStorageManager;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.manager.impl.FilePartManagerImpl;
|
||||
import feign.Client;
|
||||
import feign.codec.Decoder;
|
||||
import feign.codec.Encoder;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.netflix.feign.FeignClientsConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Configuration
|
||||
@Import(FeignClientsConfiguration.class)
|
||||
public class DavinciStorageBeansConfiguration {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DavinciStorageBeansConfiguration.class);
|
||||
|
||||
@Bean
|
||||
public FileStorageManager fileStorageManager(
|
||||
@Value("${feign.davinci-portal.name:davinci-portal}") String serviceName, Decoder decoder, Encoder encoder,
|
||||
Client client) {
|
||||
return new OpenFeignFileStorageManager(serviceName, decoder, encoder, client);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilePartManager filePartManager(@Value("${feign.davinci-portal.name:davinci-portal}") String serviceName,
|
||||
Decoder decoder, Encoder encoder, Client client) {
|
||||
try {
|
||||
return new FilePartManagerImpl(serviceName, decoder, encoder, client);
|
||||
} catch (NoClassDefFoundError e) {
|
||||
LOGGER.warn("Davinci FilePartManager init failed, fallback to noop: {}", e.toString());
|
||||
return new NoopFilePartManager();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class NoopFilePartManager implements FilePartManager {
|
||||
private static final String CODE = "ELEVATOR_DAVINCI_DISABLED";
|
||||
private static final String MSG = "davinci multipart upload is unavailable in current runtime";
|
||||
|
||||
@Override
|
||||
public PartInitResultDTO init(PartInitDTO paramPartInitDTO) throws DavinciServiceException {
|
||||
throw new DavinciServiceException(CODE, MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PartInitResultDTO append(String paramString1, Integer paramInteger, String paramString2,
|
||||
org.springframework.web.multipart.MultipartFile paramMultipartFile) throws DavinciServiceException {
|
||||
throw new DavinciServiceException(CODE, MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String finish(PartFinishDTO paramPartFinishDTO) throws DavinciServiceException {
|
||||
throw new DavinciServiceException(CODE, MSG);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package cn.cloudwalk.elevator.debug;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 启动期打印关键配置的命中来源,便于排查配置覆盖链路。始终执行;调度/开关见 {@link ElevatorProbeConstants}(不使用 {@code elevator.config.probe.enabled})。
|
||||
*/
|
||||
@Component
|
||||
public class ConfigSourceProbeRunner implements ApplicationRunner {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigSourceProbeRunner.class);
|
||||
|
||||
private final ConfigurableEnvironment environment;
|
||||
|
||||
public ConfigSourceProbeRunner(ConfigurableEnvironment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) {
|
||||
List<String> keys = Arrays.asList("spring.application.name", "spring.profiles.active", "server.port",
|
||||
"spring.cloud.consul.host", "spring.cloud.consul.port", "spring.cloud.consul.enabled",
|
||||
"spring.cloud.consul.discovery.enabled", "spring.cloud.consul.discovery.register",
|
||||
"spring.cloud.consul.discovery.instance-id", "spring.cloud.consul.discovery.ip-address",
|
||||
"spring.cloud.client.ip-address", "feign.cwos-portal.name", "feign.ninca-common.name",
|
||||
"feign.ninca-crk-std.name", "feign.component-organization.name", "feign.mqtt.name",
|
||||
"cwos-portal.ribbon.NIWSServerListClassName", "ninca-common.ribbon.NIWSServerListClassName",
|
||||
"ninca-common-component-organization.ribbon.NIWSServerListClassName",
|
||||
"ninca-crk-std.ribbon.NIWSServerListClassName", "cwos-portal.ribbon.listOfServers",
|
||||
"ninca-common.ribbon.listOfServers", "ninca-common-component-organization.ribbon.listOfServers",
|
||||
"ninca-crk-std.ribbon.listOfServers", "ninca-crk-std.ip");
|
||||
|
||||
LOGGER.debug("===== CONFIG SOURCE PROBE START =====");
|
||||
for (String key : keys) {
|
||||
String value = environment.getProperty(key);
|
||||
LOGGER.debug("probe key={} value={}", key, value);
|
||||
for (PropertySource<?> source : environment.getPropertySources()) {
|
||||
Object candidate = source.getProperty(key);
|
||||
if (candidate != null) {
|
||||
LOGGER.debug("probe key={} source={} sourceValue={}", key, source.getName(), candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGGER.debug("===== CONFIG SOURCE PROBE END =====");
|
||||
}
|
||||
}
|
||||
+307
@@ -0,0 +1,307 @@
|
||||
package cn.cloudwalk.elevator.debug;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
/**
|
||||
* 启动后延迟请求 Consul {@code /v1/health/service/<name>},逐实例输出注册地址与检查摘要;并与 JVM 内 Ribbon 列表对照。 探针始终启用,延迟见
|
||||
* {@link ElevatorProbeConstants#CONSUL_HTTP_PROBE_DELAY_SECONDS};Consul 地址仍取自 {@code spring.cloud.consul.host|port}。
|
||||
*
|
||||
* <p>
|
||||
* 开始时核对<strong>本进程</strong>({@code spring.application.name})在 Consul 中的登记与健康状态。
|
||||
*/
|
||||
@Component
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
public class ConsulUpstreamHealthProbeRunner implements ApplicationListener<ContextRefreshedEvent>, DisposableBean {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConsulUpstreamHealthProbeRunner.class);
|
||||
|
||||
private static final int CONNECT_TIMEOUT_MS = 3000;
|
||||
private static final int READ_TIMEOUT_MS = 8000;
|
||||
|
||||
private static final int CHECKS_SUMMARY_MAX_CHARS = 360;
|
||||
|
||||
private final AtomicBoolean scheduled = new AtomicBoolean(false);
|
||||
|
||||
private volatile ScheduledExecutorService scheduler;
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Value("${spring.cloud.consul.host:127.0.0.1}")
|
||||
private String consulHost;
|
||||
|
||||
@Value("${spring.cloud.consul.port:8500}")
|
||||
private int consulPort;
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
ScheduledExecutorService s = scheduler;
|
||||
if (s != null) {
|
||||
s.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
if (event.getApplicationContext().getParent() != null) {
|
||||
return;
|
||||
}
|
||||
if (!scheduled.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(r -> {
|
||||
Thread t = new Thread(r, "elevator-consul-probe");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
this.scheduler = exec;
|
||||
exec.schedule(this::probeAll, ElevatorProbeConstants.CONSUL_HTTP_PROBE_DELAY_SECONDS, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private void probeAll() {
|
||||
LOGGER.debug(
|
||||
"===== CONSUL UPSTREAM HEALTH PROBE START base=http://{}:{} (passing=true for upstream list) =====",
|
||||
consulHost, consulPort);
|
||||
ObjectMapper mapper = objectMapper != null ? objectMapper : new ObjectMapper();
|
||||
probeLocalServiceRegistration(mapper);
|
||||
for (String service : ElevatorUpstreamServiceNames.CONSUL_HEALTH_NAMES) {
|
||||
try {
|
||||
String url = String.format("http://%s:%d/v1/health/service/%s?passing=true", consulHost, consulPort,
|
||||
urlEncodePathSegment(service));
|
||||
HttpBodyResult res = httpGet(url);
|
||||
if (res.code >= 400) {
|
||||
LOGGER.warn("consulProbe service={} httpStatus={} bodySnippet={}", service, res.code,
|
||||
abbrevForLog(res.body, 240));
|
||||
continue;
|
||||
}
|
||||
int n = parseAndLogHealthServiceJson(mapper, res.body, "upstream-passing", service);
|
||||
if (n < 0) {
|
||||
LOGGER.warn("consulProbe service={} passingInstances=PARSE_ERROR bodySnippet={}", service,
|
||||
abbrevForLog(res.body, 240));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("consulProbe service={} failed: {}", service, e.toString());
|
||||
}
|
||||
}
|
||||
LOGGER.debug("===== CONSUL UPSTREAM HEALTH PROBE END =====");
|
||||
}
|
||||
|
||||
/**
|
||||
* 核对当前应用配置的 Consul 地址上,本服务 serviceId(与 {@code spring.application.name} 默认一致)是否可查;并对比 passing 与全量实例。
|
||||
*/
|
||||
private void probeLocalServiceRegistration(ObjectMapper mapper) {
|
||||
String appName = environment.getProperty("spring.application.name", "elevator-app");
|
||||
LOGGER.debug("===== CONSUL LOCAL SERVICE REGISTRATION PROBE START (this serviceId={}) =====", appName);
|
||||
LOGGER.debug(
|
||||
"consulProbe local merged: spring.cloud.consul.enabled={} discovery.enabled={} discovery.register={} "
|
||||
+ "prefer-ip-address={}",
|
||||
environment.getProperty("spring.cloud.consul.enabled"),
|
||||
environment.getProperty("spring.cloud.consul.discovery.enabled"),
|
||||
environment.getProperty("spring.cloud.consul.discovery.register"),
|
||||
environment.getProperty("spring.cloud.consul.discovery.prefer-ip-address"));
|
||||
LOGGER.debug(
|
||||
"consulProbe local merged: server.port={} discovery.instance-id={} discovery.ip-address={} "
|
||||
+ "spring.cloud.client.ip-address={}",
|
||||
environment.getProperty("server.port"),
|
||||
environment.getProperty("spring.cloud.consul.discovery.instance-id"),
|
||||
environment.getProperty("spring.cloud.consul.discovery.ip-address"),
|
||||
environment.getProperty("spring.cloud.client.ip-address"));
|
||||
|
||||
logConsulAgentSelf(mapper);
|
||||
|
||||
int passing = fetchAndLogHealthService(mapper, appName, true, "local-passing");
|
||||
int allChecks = fetchAndLogHealthService(mapper, appName, false, "local-all");
|
||||
|
||||
LOGGER.debug("consulProbe localService={} summary passingEntries={} allEntries={}", appName, passing,
|
||||
allChecks);
|
||||
|
||||
if (passing < 0 || allChecks < 0) {
|
||||
LOGGER.warn("consulProbe localService={} could not read /v1/health/service (see errors above); skip "
|
||||
+ "registration assert.", appName);
|
||||
} else if (allChecks == 0) {
|
||||
LOGGER.warn(
|
||||
"consulProbe localService={} ZERO entries from GET /v1/health/service/{} — not registered under this "
|
||||
+ "name, wrong Consul address (see spring.cloud.consul.host merge), or catalog lag. Compare with "
|
||||
+ "Consul UI service name (exact match).",
|
||||
appName, appName);
|
||||
} else if (passing == 0) {
|
||||
LOGGER.warn("consulProbe localService={} has health entries ({}) but passing=0 — registration exists; "
|
||||
+ "fix health checks or agent connectivity.", appName, allChecks);
|
||||
} else {
|
||||
LOGGER.debug("consulProbe localService={} registration OK: passing={}", appName, passing);
|
||||
}
|
||||
LOGGER.debug("===== CONSUL LOCAL SERVICE REGISTRATION PROBE END =====");
|
||||
}
|
||||
|
||||
private void logConsulAgentSelf(ObjectMapper mapper) {
|
||||
try {
|
||||
String url = String.format("http://%s:%d/v1/agent/self", consulHost, consulPort);
|
||||
HttpBodyResult res = httpGet(url);
|
||||
if (res.code >= 400) {
|
||||
LOGGER.warn("consulProbe agent/self httpStatus={} bodySnippet={}", res.code,
|
||||
abbrevForLog(res.body, 200));
|
||||
return;
|
||||
}
|
||||
JsonNode root = mapper.readTree(res.body);
|
||||
String dc = root.path("Config").path("Datacenter").asText("");
|
||||
String nodeName = root.path("Config").path("NodeName").asText("");
|
||||
String memberAddr = root.path("Member").path("Addr").asText("");
|
||||
String memberName = root.path("Member").path("Name").asText("");
|
||||
LOGGER.debug(
|
||||
"consulProbe agent/self datacenter={} nodeName={} memberAddr={} memberName={} "
|
||||
+ "(compare spring.cloud.consul.host to reach expected Consul agent)",
|
||||
dc, nodeName, memberAddr, memberName);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("consulProbe agent/self failed: {}", e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET health/service with optional {@code ?passing=true}; parse body and log each instance; return entry count or
|
||||
* -1.
|
||||
*/
|
||||
private int fetchAndLogHealthService(ObjectMapper mapper, String serviceName, boolean passingOnly, String scope) {
|
||||
try {
|
||||
String path = urlEncodePathSegment(serviceName);
|
||||
String url = String.format("http://%s:%d/v1/health/service/%s", consulHost, consulPort, path);
|
||||
if (passingOnly) {
|
||||
url += "?passing=true";
|
||||
}
|
||||
HttpBodyResult res = httpGet(url);
|
||||
if (res.code >= 400) {
|
||||
LOGGER.warn("consulProbe health/service scope={} service={} passingOnly={} httpStatus={} snippet={}",
|
||||
scope, serviceName, passingOnly, res.code, abbrevForLog(res.body, 200));
|
||||
return -1;
|
||||
}
|
||||
return parseAndLogHealthServiceJson(mapper, res.body, scope, serviceName);
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("consulProbe health/service scope={} service={} passingOnly={} failed: {}", scope, serviceName,
|
||||
passingOnly, e.toString());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static HttpBodyResult httpGet(String urlString) throws java.io.IOException {
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
conn = (HttpURLConnection)new URL(urlString).openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setConnectTimeout(CONNECT_TIMEOUT_MS);
|
||||
conn.setReadTimeout(READ_TIMEOUT_MS);
|
||||
int code = conn.getResponseCode();
|
||||
InputStream in = code >= 400 ? conn.getErrorStream() : conn.getInputStream();
|
||||
String body = in == null ? "" : StreamUtils.copyToString(in, StandardCharsets.UTF_8);
|
||||
return new HttpBodyResult(code, body);
|
||||
} finally {
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class HttpBodyResult {
|
||||
final int code;
|
||||
final String body;
|
||||
|
||||
HttpBodyResult(int code, String body) {
|
||||
this.code = code;
|
||||
this.body = body;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses Consul {@code /v1/health/service/...} JSON array; logs one DEBUG line per entry with Service Address:Port
|
||||
* and Checks summary.
|
||||
*
|
||||
* @return array size, or -1 on parse error
|
||||
*/
|
||||
private int parseAndLogHealthServiceJson(ObjectMapper mapper, String body, String scope, String queriedService) {
|
||||
if (body == null || body.isEmpty()) {
|
||||
LOGGER.debug("consulProbe summary scope={} queriedService={} entryCount=0", scope, queriedService);
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
JsonNode root = mapper.readTree(body);
|
||||
if (root == null || !root.isArray()) {
|
||||
return -1;
|
||||
}
|
||||
int n = root.size();
|
||||
LOGGER.debug("consulProbe summary scope={} queriedService={} entryCount={}", scope, queriedService, n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
JsonNode item = root.get(i);
|
||||
JsonNode svc = item.path("Service");
|
||||
JsonNode node = item.path("Node");
|
||||
String sid = svc.path("ID").asText("");
|
||||
String sname = svc.path("Service").asText("");
|
||||
String addr = svc.path("Address").asText("");
|
||||
int port = svc.path("Port").asInt(0);
|
||||
String nodeId = node.path("Node").asText("");
|
||||
String checksTxt = summarizeChecks(item.path("Checks"));
|
||||
LOGGER.debug(
|
||||
"consulProbe instance scope={} queriedService={} service={} id={} endpoint={}:{} node={} checks=[{}]",
|
||||
scope, queriedService, sname, sid, addr, port, nodeId, checksTxt);
|
||||
}
|
||||
return n;
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("consulProbe parse failed scope={} queriedService={} err={}", scope, queriedService,
|
||||
e.toString());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static String summarizeChecks(JsonNode checks) {
|
||||
if (checks == null || !checks.isArray()) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (JsonNode c : checks) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(';');
|
||||
}
|
||||
sb.append(c.path("CheckID").asText("")).append(':').append(c.path("Status").asText(""));
|
||||
}
|
||||
String t = sb.toString();
|
||||
return t.length() <= CHECKS_SUMMARY_MAX_CHARS ? t : t.substring(0, CHECKS_SUMMARY_MAX_CHARS) + "…";
|
||||
}
|
||||
|
||||
private static String urlEncodePathSegment(String raw) {
|
||||
try {
|
||||
return URLEncoder.encode(raw, StandardCharsets.UTF_8.name()).replace("+", "%20");
|
||||
} catch (java.io.UnsupportedEncodingException e) {
|
||||
return raw;
|
||||
}
|
||||
}
|
||||
|
||||
private static String abbrevForLog(String s, int maxChars) {
|
||||
if (s == null) {
|
||||
return "";
|
||||
}
|
||||
String t = s.replace("\r\n", " ").replace('\n', ' ').trim();
|
||||
return t.length() <= maxChars ? t : t.substring(0, maxChars) + "…";
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package cn.cloudwalk.elevator.debug;
|
||||
|
||||
/**
|
||||
* 电梯诊断探针调度常量(写死,不通过 application.properties 配置开关/间隔)。 调整排障节奏时仅改本类,不再使用 {@code elevator.*.probe.*} 属性。
|
||||
*/
|
||||
public final class ElevatorProbeConstants {
|
||||
|
||||
/** 根上下文 {@link org.springframework.context.event.ContextRefreshedEvent} 之后,首次拉取 Consul /v1/health 的延迟。 */
|
||||
public static final int CONSUL_HTTP_PROBE_DELAY_SECONDS = 20;
|
||||
|
||||
/**
|
||||
* Ribbon 各 Feign 客户端 {@link com.netflix.loadbalancer.ILoadBalancer} 快照的延迟;略大于 Consul 探针,减少两路日志交错。
|
||||
*/
|
||||
public static final int RIBBON_LOAD_BALANCER_PROBE_DELAY_SECONDS = 22;
|
||||
|
||||
/** 0 表示仅打一次 delayed-initial 快照;大于 0 时按该间隔秒数重复。 */
|
||||
public static final int RIBBON_PROBE_REPEAT_SECONDS = 0;
|
||||
|
||||
private ElevatorProbeConstants() {}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package cn.cloudwalk.elevator.debug;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 启动早期打印诊断探针摘要与独立日志文件名模式,便于一次性对照 {@code *-probe.log}。探针固定启用,调度见 {@link ElevatorProbeConstants}。
|
||||
*/
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class ElevatorProbeSummaryRunner implements ApplicationRunner {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ElevatorProbeSummaryRunner.class);
|
||||
|
||||
@Value("${logging.file:elevator-app}")
|
||||
private String loggingFile;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) {
|
||||
LOGGER.debug("===== ELEVATOR DIAGNOSTIC PROBES always on (see {}) cn.cloudwalk.elevator.debug DEBUG + "
|
||||
+ "org.springframework.cloud.consul / com.netflix.loadbalancer / org.springframework.cloud.client.discovery DEBUG "
|
||||
+ "duplicated in <logging.path>/{}-probe.log; consulDelay={}s ribbonDelay={}s ribbonRepeat={}s =====",
|
||||
ElevatorProbeConstants.class.getSimpleName(), loggingFile,
|
||||
ElevatorProbeConstants.CONSUL_HTTP_PROBE_DELAY_SECONDS,
|
||||
ElevatorProbeConstants.RIBBON_LOAD_BALANCER_PROBE_DELAY_SECONDS,
|
||||
ElevatorProbeConstants.RIBBON_PROBE_REPEAT_SECONDS);
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package cn.cloudwalk.elevator.debug;
|
||||
|
||||
/**
|
||||
* 与 Feign/Ribbon、{@code collect_elevator_runtime_evidence.sh}、Consul {@code /v1/health/service/...} 探针对齐的上游 <strong>服务
|
||||
* id</strong>(即在 Consul 中的注册名,也是 Ribbon {@code client} 名,须与 {@code feign.*.name} 解析结果一致)。
|
||||
*
|
||||
* <p>
|
||||
* 前四项与运维脚本中的循环列表一致。第五项为 MQTT 第三方 Feign 默认名({@code feign.mqtt.name},默认 {@code cloudwalk-device-thirdparty}),便于与门户/通用/crk
|
||||
* 主线并列排障;若现场改写 {@code feign.mqtt.name},须保持 Consul 注册名与之一致,否则探针仍可按需改配置或扩展列表。
|
||||
*/
|
||||
public final class ElevatorUpstreamServiceNames {
|
||||
|
||||
private ElevatorUpstreamServiceNames() {}
|
||||
|
||||
public static final String[] CONSUL_HEALTH_NAMES = new String[] {"cwos-portal", "ninca-common",
|
||||
"ninca-common-component-organization", "ninca-crk-std", "cloudwalk-device-thirdparty"};
|
||||
}
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
package cn.cloudwalk.elevator.debug;
|
||||
|
||||
import com.netflix.loadbalancer.ILoadBalancer;
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import com.netflix.loadbalancer.ServerList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 运行期打印各 Feign/Ribbon 客户端的 {@link ILoadBalancer} 实例与当前 Server 列表,用于定位 「Load balancer does not have available server」:区分
|
||||
* Consul 发现为空、静态 listOfServers 未生效、或尚未触发懒加载。
|
||||
*
|
||||
* <p>
|
||||
* 始终注册;首次快照延迟见 {@link ElevatorProbeConstants#RIBBON_LOAD_BALANCER_PROBE_DELAY_SECONDS},重复间隔见
|
||||
* {@link ElevatorProbeConstants#RIBBON_PROBE_REPEAT_SECONDS}(不再使用 {@code elevator.ribbon.probe.*})。
|
||||
*
|
||||
* <p>
|
||||
* 同延迟窗口输出 {@link ServerList} 实现类与 {@link DiscoveryClient#getInstances},与 Consul HTTP 探针、logback 双写的 Netflix 日志交叉验证。
|
||||
*/
|
||||
@Component
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
public class RibbonLoadBalancerProbeRunner implements ApplicationListener<ContextRefreshedEvent>, DisposableBean {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RibbonLoadBalancerProbeRunner.class);
|
||||
|
||||
private final AtomicBoolean scheduled = new AtomicBoolean(false);
|
||||
|
||||
private volatile ScheduledExecutorService scheduler;
|
||||
|
||||
@Autowired(required = false)
|
||||
private SpringClientFactory springClientFactory;
|
||||
|
||||
@Autowired(required = false)
|
||||
private DiscoveryClient discoveryClient;
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
ScheduledExecutorService s = scheduler;
|
||||
if (s != null) {
|
||||
s.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
if (event.getApplicationContext().getParent() != null) {
|
||||
return;
|
||||
}
|
||||
if (!scheduled.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
if (springClientFactory == null) {
|
||||
LOGGER.warn("RIBBON PROBE SKIPPED: SpringClientFactory not available");
|
||||
return;
|
||||
}
|
||||
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(r -> {
|
||||
Thread t = new Thread(r, "elevator-ribbon-probe");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
this.scheduler = exec;
|
||||
int delay = ElevatorProbeConstants.RIBBON_LOAD_BALANCER_PROBE_DELAY_SECONDS;
|
||||
int repeat = ElevatorProbeConstants.RIBBON_PROBE_REPEAT_SECONDS;
|
||||
exec.schedule(() -> {
|
||||
logRibbonSnapshot("delayed-initial");
|
||||
logDiscoverySnapshot("delayed-initial");
|
||||
if (repeat > 0) {
|
||||
exec.scheduleAtFixedRate(() -> {
|
||||
logRibbonSnapshot("repeat");
|
||||
logDiscoverySnapshot("repeat");
|
||||
}, repeat, repeat, TimeUnit.SECONDS);
|
||||
}
|
||||
}, delay, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private void logRibbonSnapshot(String phase) {
|
||||
LOGGER.debug("===== RIBBON LOAD BALANCER PROBE START ({}) =====", phase);
|
||||
for (String client : ElevatorUpstreamServiceNames.CONSUL_HEALTH_NAMES) {
|
||||
try {
|
||||
ILoadBalancer lb = springClientFactory.getLoadBalancer(client);
|
||||
if (lb == null) {
|
||||
LOGGER.warn("probe client={} loadBalancer=null", client);
|
||||
continue;
|
||||
}
|
||||
List<Server> servers = lb.getAllServers();
|
||||
int n = servers == null ? 0 : servers.size();
|
||||
String desc = servers == null ? "null"
|
||||
: servers.stream().map(Server::getHostPort).collect(Collectors.joining(","));
|
||||
try {
|
||||
@SuppressWarnings("rawtypes")
|
||||
ServerList sl = springClientFactory.getInstance(client, ServerList.class);
|
||||
LOGGER.debug(
|
||||
"probe client={} serverListClass={} (ConsulServerList vs ConfigurationBasedServerList)", client,
|
||||
sl == null ? "null" : sl.getClass().getName());
|
||||
} catch (RuntimeException ex) {
|
||||
LOGGER.debug("probe client={} serverListClass lookup failed: {}", client, ex.toString());
|
||||
}
|
||||
if (servers != null) {
|
||||
for (Server s : servers) {
|
||||
LOGGER.debug(
|
||||
"ribbonProbe instance client={} host={} port={} zone={} readyToServe={} alive={} "
|
||||
+ "hostPort={}",
|
||||
client, s.getHost(), s.getPort(), s.getZone(), s.isReadyToServe(), s.isAlive(),
|
||||
s.getHostPort());
|
||||
}
|
||||
}
|
||||
LOGGER.debug("probe client={} serverCount={} servers=[{}] lbClass={}", client, n, desc,
|
||||
lb.getClass().getName());
|
||||
} catch (RuntimeException e) {
|
||||
LOGGER.warn("probe client={} failed: {}", client, e.toString());
|
||||
}
|
||||
}
|
||||
LOGGER.debug("===== RIBBON LOAD BALANCER PROBE END ({}) =====", phase);
|
||||
}
|
||||
|
||||
/**
|
||||
* 与 Consul HTTP 探针对照:同一 serviceId 在 {@link DiscoveryClient} 中可见的实例(JVM 内发现视图)。
|
||||
*/
|
||||
private void logDiscoverySnapshot(String phase) {
|
||||
LOGGER.debug("===== DISCOVERY CLIENT PROBE START ({}) =====", phase);
|
||||
if (discoveryClient == null) {
|
||||
LOGGER.debug("discoveryProbe DiscoveryClient=null (skip)");
|
||||
LOGGER.debug("===== DISCOVERY CLIENT PROBE END ({}) =====", phase);
|
||||
return;
|
||||
}
|
||||
LOGGER.debug("discoveryProbe discoveryClientClass={}", discoveryClient.getClass().getName());
|
||||
Set<String> serviceIds = new LinkedHashSet<>();
|
||||
serviceIds.add(environment.getProperty("spring.application.name", "elevator-app"));
|
||||
for (String u : ElevatorUpstreamServiceNames.CONSUL_HEALTH_NAMES) {
|
||||
serviceIds.add(u);
|
||||
}
|
||||
for (String serviceId : serviceIds) {
|
||||
try {
|
||||
List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
|
||||
int c = instances == null ? 0 : instances.size();
|
||||
LOGGER.debug("discoveryProbe summary phase={} serviceId={} instanceCount={}", phase, serviceId, c);
|
||||
if (instances != null) {
|
||||
for (ServiceInstance inst : instances) {
|
||||
LOGGER.debug(
|
||||
"discoveryProbe instance phase={} serviceId={} host={} port={} uri={} secure={} "
|
||||
+ "metadata={}",
|
||||
phase, serviceId, inst.getHost(), inst.getPort(), inst.getUri(), inst.isSecure(),
|
||||
inst.getMetadata());
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
LOGGER.warn("discoveryProbe serviceId={} failed: {}", serviceId, e.toString());
|
||||
}
|
||||
}
|
||||
LOGGER.debug("===== DISCOVERY CLIENT PROBE END ({}) =====", phase);
|
||||
}
|
||||
}
|
||||
+228
-228
@@ -1,228 +1,228 @@
|
||||
package cn.cloudwalk.elevator.integration.davinci;
|
||||
|
||||
import cn.cloudwalk.intelligent.davinci.common.exception.DavinciServiceException;
|
||||
import cn.cloudwalk.intelligent.davinci.common.result.DavinciResult;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.bean.file.dto.FileRemoveDTO;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.feign.FileManagerFeign;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.feign.OuterCallFeignClient;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.manager.FileStorageManager;
|
||||
import feign.Client;
|
||||
import feign.Feign;
|
||||
import feign.Response;
|
||||
import feign.codec.Decoder;
|
||||
import feign.codec.Encoder;
|
||||
import feign.form.spring.SpringFormEncoder;
|
||||
import feign.okhttp.OkHttpClient;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.cloud.netflix.feign.support.SpringMvcContract;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 与 davinci-manager-storage 中逻辑一致,但固定使用 {@link SpringMvcContract}(OpenFeign)。
|
||||
* 避免依赖 Nexus 仍带 Netflix 引用的旧 {@code FileStorageManagerImpl} 字节码导致 NoClassDefFoundError。
|
||||
*/
|
||||
public class OpenFeignFileStorageManager implements FileStorageManager {
|
||||
|
||||
private final FileManagerFeign fileManagerFeign;
|
||||
private final FileManagerFeign fileManagerRestFeign;
|
||||
|
||||
public OpenFeignFileStorageManager(String serviceName, Decoder decoder, Encoder encoder, Client client) {
|
||||
String url = "http://" + serviceName + "/portal/fileManager";
|
||||
|
||||
this.fileManagerFeign = Feign.builder().client(client).decode404().encoder(new SpringFormEncoder())
|
||||
.decoder(decoder).contract(new SpringMvcContract()).target(FileManagerFeign.class, url);
|
||||
|
||||
this.fileManagerRestFeign = Feign.builder().client(client).decode404().encoder(encoder).decoder(decoder)
|
||||
.contract(new SpringMvcContract()).target(FileManagerFeign.class, url);
|
||||
}
|
||||
|
||||
static void assertSafeHttpUrl(String urlString) throws DavinciServiceException {
|
||||
if (StringUtils.isEmpty(urlString)) {
|
||||
throw new DavinciServiceException("INVALID_URL", "URL 为空");
|
||||
}
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(urlString);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new DavinciServiceException("INVALID_URL", "URL 非法");
|
||||
}
|
||||
String scheme = uri.getScheme();
|
||||
if (scheme == null || (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme))) {
|
||||
throw new DavinciServiceException("INVALID_URL", "仅允许 http 或 https 协议");
|
||||
}
|
||||
String host = uri.getHost();
|
||||
if (StringUtils.isEmpty(host)) {
|
||||
throw new DavinciServiceException("INVALID_URL", "缺少主机名");
|
||||
}
|
||||
String lowerHost = host.toLowerCase(Locale.ROOT);
|
||||
if ("localhost".equals(lowerHost) || lowerHost.endsWith(".local")) {
|
||||
throw new DavinciServiceException("INVALID_URL", "禁止访问该主机");
|
||||
}
|
||||
if ("metadata.google.internal".equalsIgnoreCase(host)) {
|
||||
throw new DavinciServiceException("INVALID_URL", "禁止访问该主机");
|
||||
}
|
||||
try {
|
||||
InetAddress[] all = InetAddress.getAllByName(host);
|
||||
for (InetAddress addr : all) {
|
||||
if (addr.isAnyLocalAddress() || addr.isLoopbackAddress() || addr.isLinkLocalAddress()
|
||||
|| addr.isSiteLocalAddress() || addr.isMulticastAddress()) {
|
||||
throw new DavinciServiceException("INVALID_URL", "禁止访问内网或保留地址");
|
||||
}
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
throw new DavinciServiceException("INVALID_URL", "无法解析主机");
|
||||
}
|
||||
}
|
||||
|
||||
private static void requireDavinciResult(DavinciResult<?> result, String op) throws DavinciServiceException {
|
||||
if (result == null) {
|
||||
throw new DavinciServiceException("NULL_RESULT", "Davinci-portal 返回空结果: " + op);
|
||||
}
|
||||
}
|
||||
|
||||
private static InputStream attachResponseClose(InputStream bodyStream, Response response) {
|
||||
return new FilterInputStream(bodyStream) {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
super.close();
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fileUpload(MultipartFile file) throws DavinciServiceException {
|
||||
DavinciResult<String> result = this.fileManagerFeign.fileUpload(file);
|
||||
requireDavinciResult(result, "fileUpload");
|
||||
if (result.isSuccess()) {
|
||||
return result.getData();
|
||||
}
|
||||
throw new DavinciServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fileUpload(String moduleCategory, MultipartFile file) throws DavinciServiceException {
|
||||
DavinciResult<String> result = this.fileManagerFeign.fileUpload(moduleCategory, file);
|
||||
requireDavinciResult(result, "fileUpload(module)");
|
||||
if (result.isSuccess()) {
|
||||
return result.getData();
|
||||
}
|
||||
throw new DavinciServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String bigFileUpload(MultipartFile file) throws DavinciServiceException {
|
||||
DavinciResult<String> result = this.fileManagerFeign.bigFileUpload(file);
|
||||
requireDavinciResult(result, "bigFileUpload");
|
||||
if (result.isSuccess()) {
|
||||
return result.getData();
|
||||
}
|
||||
throw new DavinciServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String bigFileUpload(String moduleCategory, MultipartFile file) throws DavinciServiceException {
|
||||
DavinciResult<String> result = this.fileManagerFeign.bigFileUpload(moduleCategory, file);
|
||||
requireDavinciResult(result, "bigFileUpload(module)");
|
||||
if (result.isSuccess()) {
|
||||
return result.getData();
|
||||
}
|
||||
throw new DavinciServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] fileDownload(String path) throws DavinciServiceException {
|
||||
try (Response response = this.fileManagerFeign.fileDownload(path)) {
|
||||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
if (response.body() == null) {
|
||||
return null;
|
||||
}
|
||||
try (InputStream inputStream = response.body().asInputStream()) {
|
||||
return IOUtils.toByteArray(inputStream);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new DavinciServiceException("FILE_DOWNLOAD_IO", "调用Davinci-portal服务,获取文件流接口异常");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream fileDownloadStream(String path) throws DavinciServiceException {
|
||||
Response response = this.fileManagerFeign.fileDownload(path);
|
||||
try {
|
||||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
if (response.body() == null) {
|
||||
response.close();
|
||||
return null;
|
||||
}
|
||||
return attachResponseClose(response.body().asInputStream(), response);
|
||||
} catch (IOException e) {
|
||||
if (response != null) {
|
||||
response.close();
|
||||
}
|
||||
throw new DavinciServiceException("FILE_DOWNLOAD_IO", "调用Davinci-portal服务,获取文件流接口异常");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileBase64(String path) throws DavinciServiceException {
|
||||
if (StringUtils.isEmpty(path)) {
|
||||
return "";
|
||||
}
|
||||
DavinciResult<String> result = this.fileManagerFeign.getFileData(path);
|
||||
requireDavinciResult(result, "getFileData");
|
||||
if (result.isSuccess()) {
|
||||
return result.getData();
|
||||
}
|
||||
throw new DavinciServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> remove(FileRemoveDTO dto) throws DavinciServiceException {
|
||||
DavinciResult<List<String>> result = this.fileManagerRestFeign.remove(dto);
|
||||
requireDavinciResult(result, "remove");
|
||||
if (result.isSuccess()) {
|
||||
return result.getData();
|
||||
}
|
||||
throw new DavinciServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream fileDownLoadWithAbsoluteUrl(String url) throws DavinciServiceException {
|
||||
assertSafeHttpUrl(url);
|
||||
OuterCallFeignClient feignClient = Feign.builder().client(new OkHttpClient()).target(OuterCallFeignClient.class,
|
||||
url);
|
||||
Response response;
|
||||
try {
|
||||
response = feignClient.downLoad();
|
||||
} catch (RuntimeException e) {
|
||||
throw new DavinciServiceException("OUTER_DOWNLOAD", "拉取远程文件失败");
|
||||
}
|
||||
try {
|
||||
if (response.body() == null) {
|
||||
response.close();
|
||||
return null;
|
||||
}
|
||||
return attachResponseClose(response.body().asInputStream(), response);
|
||||
} catch (IOException e) {
|
||||
response.close();
|
||||
throw new DavinciServiceException("OUTER_DOWNLOAD", "读取远程文件流失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
package cn.cloudwalk.elevator.integration.davinci;
|
||||
|
||||
import cn.cloudwalk.intelligent.davinci.common.exception.DavinciServiceException;
|
||||
import cn.cloudwalk.intelligent.davinci.common.result.DavinciResult;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.bean.file.dto.FileRemoveDTO;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.feign.FileManagerFeign;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.feign.OuterCallFeignClient;
|
||||
import cn.cloudwalk.intelligent.davinci.storage.manager.FileStorageManager;
|
||||
import feign.Client;
|
||||
import feign.Feign;
|
||||
import feign.Response;
|
||||
import feign.codec.Decoder;
|
||||
import feign.codec.Encoder;
|
||||
import feign.form.spring.SpringFormEncoder;
|
||||
import feign.okhttp.OkHttpClient;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.cloud.netflix.feign.support.SpringMvcContract;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 与 davinci-manager-storage 中逻辑一致,但固定使用 {@link SpringMvcContract}(OpenFeign)。 避免依赖 Nexus 仍带 Netflix 引用的旧
|
||||
* {@code FileStorageManagerImpl} 字节码导致 NoClassDefFoundError。
|
||||
*/
|
||||
public class OpenFeignFileStorageManager implements FileStorageManager {
|
||||
|
||||
private final FileManagerFeign fileManagerFeign;
|
||||
private final FileManagerFeign fileManagerRestFeign;
|
||||
|
||||
public OpenFeignFileStorageManager(String serviceName, Decoder decoder, Encoder encoder, Client client) {
|
||||
String url = "http://" + serviceName + "/portal/fileManager";
|
||||
|
||||
this.fileManagerFeign = Feign.builder().client(client).decode404().encoder(new SpringFormEncoder())
|
||||
.decoder(decoder).contract(new SpringMvcContract()).target(FileManagerFeign.class, url);
|
||||
|
||||
this.fileManagerRestFeign = Feign.builder().client(client).decode404().encoder(encoder).decoder(decoder)
|
||||
.contract(new SpringMvcContract()).target(FileManagerFeign.class, url);
|
||||
}
|
||||
|
||||
static void assertSafeHttpUrl(String urlString) throws DavinciServiceException {
|
||||
if (StringUtils.isEmpty(urlString)) {
|
||||
throw new DavinciServiceException("INVALID_URL", "URL 为空");
|
||||
}
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(urlString);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new DavinciServiceException("INVALID_URL", "URL 非法");
|
||||
}
|
||||
String scheme = uri.getScheme();
|
||||
if (scheme == null || (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme))) {
|
||||
throw new DavinciServiceException("INVALID_URL", "仅允许 http 或 https 协议");
|
||||
}
|
||||
String host = uri.getHost();
|
||||
if (StringUtils.isEmpty(host)) {
|
||||
throw new DavinciServiceException("INVALID_URL", "缺少主机名");
|
||||
}
|
||||
String lowerHost = host.toLowerCase(Locale.ROOT);
|
||||
if ("localhost".equals(lowerHost) || lowerHost.endsWith(".local")) {
|
||||
throw new DavinciServiceException("INVALID_URL", "禁止访问该主机");
|
||||
}
|
||||
if ("metadata.google.internal".equalsIgnoreCase(host)) {
|
||||
throw new DavinciServiceException("INVALID_URL", "禁止访问该主机");
|
||||
}
|
||||
try {
|
||||
InetAddress[] all = InetAddress.getAllByName(host);
|
||||
for (InetAddress addr : all) {
|
||||
if (addr.isAnyLocalAddress() || addr.isLoopbackAddress() || addr.isLinkLocalAddress()
|
||||
|| addr.isSiteLocalAddress() || addr.isMulticastAddress()) {
|
||||
throw new DavinciServiceException("INVALID_URL", "禁止访问内网或保留地址");
|
||||
}
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
throw new DavinciServiceException("INVALID_URL", "无法解析主机");
|
||||
}
|
||||
}
|
||||
|
||||
private static void requireDavinciResult(DavinciResult<?> result, String op) throws DavinciServiceException {
|
||||
if (result == null) {
|
||||
throw new DavinciServiceException("NULL_RESULT", "Davinci-portal 返回空结果: " + op);
|
||||
}
|
||||
}
|
||||
|
||||
private static InputStream attachResponseClose(InputStream bodyStream, Response response) {
|
||||
return new FilterInputStream(bodyStream) {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
super.close();
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fileUpload(MultipartFile file) throws DavinciServiceException {
|
||||
DavinciResult<String> result = this.fileManagerFeign.fileUpload(file);
|
||||
requireDavinciResult(result, "fileUpload");
|
||||
if (result.isSuccess()) {
|
||||
return result.getData();
|
||||
}
|
||||
throw new DavinciServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fileUpload(String moduleCategory, MultipartFile file) throws DavinciServiceException {
|
||||
DavinciResult<String> result = this.fileManagerFeign.fileUpload(moduleCategory, file);
|
||||
requireDavinciResult(result, "fileUpload(module)");
|
||||
if (result.isSuccess()) {
|
||||
return result.getData();
|
||||
}
|
||||
throw new DavinciServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String bigFileUpload(MultipartFile file) throws DavinciServiceException {
|
||||
DavinciResult<String> result = this.fileManagerFeign.bigFileUpload(file);
|
||||
requireDavinciResult(result, "bigFileUpload");
|
||||
if (result.isSuccess()) {
|
||||
return result.getData();
|
||||
}
|
||||
throw new DavinciServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String bigFileUpload(String moduleCategory, MultipartFile file) throws DavinciServiceException {
|
||||
DavinciResult<String> result = this.fileManagerFeign.bigFileUpload(moduleCategory, file);
|
||||
requireDavinciResult(result, "bigFileUpload(module)");
|
||||
if (result.isSuccess()) {
|
||||
return result.getData();
|
||||
}
|
||||
throw new DavinciServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] fileDownload(String path) throws DavinciServiceException {
|
||||
try (Response response = this.fileManagerFeign.fileDownload(path)) {
|
||||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
if (response.body() == null) {
|
||||
return null;
|
||||
}
|
||||
try (InputStream inputStream = response.body().asInputStream()) {
|
||||
return IOUtils.toByteArray(inputStream);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new DavinciServiceException("FILE_DOWNLOAD_IO", "调用Davinci-portal服务,获取文件流接口异常");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream fileDownloadStream(String path) throws DavinciServiceException {
|
||||
Response response = this.fileManagerFeign.fileDownload(path);
|
||||
try {
|
||||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
if (response.body() == null) {
|
||||
response.close();
|
||||
return null;
|
||||
}
|
||||
return attachResponseClose(response.body().asInputStream(), response);
|
||||
} catch (IOException e) {
|
||||
if (response != null) {
|
||||
response.close();
|
||||
}
|
||||
throw new DavinciServiceException("FILE_DOWNLOAD_IO", "调用Davinci-portal服务,获取文件流接口异常");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileBase64(String path) throws DavinciServiceException {
|
||||
if (StringUtils.isEmpty(path)) {
|
||||
return "";
|
||||
}
|
||||
DavinciResult<String> result = this.fileManagerFeign.getFileData(path);
|
||||
requireDavinciResult(result, "getFileData");
|
||||
if (result.isSuccess()) {
|
||||
return result.getData();
|
||||
}
|
||||
throw new DavinciServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> remove(FileRemoveDTO dto) throws DavinciServiceException {
|
||||
DavinciResult<List<String>> result = this.fileManagerRestFeign.remove(dto);
|
||||
requireDavinciResult(result, "remove");
|
||||
if (result.isSuccess()) {
|
||||
return result.getData();
|
||||
}
|
||||
throw new DavinciServiceException(result.getCode(), result.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream fileDownLoadWithAbsoluteUrl(String url) throws DavinciServiceException {
|
||||
assertSafeHttpUrl(url);
|
||||
OuterCallFeignClient feignClient =
|
||||
Feign.builder().client(new OkHttpClient()).target(OuterCallFeignClient.class, url);
|
||||
Response response;
|
||||
try {
|
||||
response = feignClient.downLoad();
|
||||
} catch (RuntimeException e) {
|
||||
throw new DavinciServiceException("OUTER_DOWNLOAD", "拉取远程文件失败");
|
||||
}
|
||||
try {
|
||||
if (response.body() == null) {
|
||||
response.close();
|
||||
return null;
|
||||
}
|
||||
return attachResponseClose(response.body().asInputStream(), response);
|
||||
} catch (IOException e) {
|
||||
response.close();
|
||||
throw new DavinciServiceException("OUTER_DOWNLOAD", "读取远程文件流失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
package cn.cloudwalk.ribbon;
|
||||
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
import com.netflix.loadbalancer.ConfigurationBasedServerList;
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import com.netflix.loadbalancer.ServerList;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 为 Feign 客户端 {@code ninca-crk-std} 强制使用配置型 ServerList,避免 Consul 发现返回空列表时覆盖
|
||||
* {@code ninca-crk-std.ribbon.listOfServers}(Edgware 下常见「Load balancer does not have available server」)。
|
||||
*/
|
||||
@Configuration
|
||||
public class NincaCrkStdRibbonConfiguration {
|
||||
|
||||
@Bean
|
||||
public ServerList<Server> ribbonServerList(IClientConfig config) {
|
||||
ConfigurationBasedServerList list = new ConfigurationBasedServerList();
|
||||
list.initWithNiwsConfig(config);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
+37
-3
@@ -5,8 +5,8 @@
|
||||
|
||||
<springProperty scope="context" name="fileName" source="logging.file" defaultValue="default"/>
|
||||
|
||||
<!--myibatis log configure-->
|
||||
<logger name="com.apache.ibatis" level="DEBUG"/>
|
||||
<!-- MyBatis 3:logger 名为 org.apache.ibatis.* -->
|
||||
<logger name="org.apache.ibatis" level="DEBUG"/>
|
||||
<logger name="java.sql.Connection" level="DEBUG"/>
|
||||
<logger name="java.sql.Statement" level="DEBUG"/>
|
||||
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
|
||||
@@ -48,7 +48,41 @@
|
||||
<!-- </triggeringPolicy> -->
|
||||
</appender>
|
||||
|
||||
<!-- 日志输出级别 -->
|
||||
<!-- 电梯诊断探针专用文件:与主日志同内容双写(additivity=true:仍走 root→控制台与 ${fileName}.log,并额外写入 ${fileName}-probe.log) -->
|
||||
<appender name="PROBE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<File>${LOG_PATH}/${fileName}-probe.log</File>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<FileNamePattern>${LOG_PATH}/${fileName}-probe.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
|
||||
<MaxHistory>14</MaxHistory>
|
||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||
<maxFileSize>20MB</maxFileSize>
|
||||
</timeBasedFileNamingAndTriggeringPolicy>
|
||||
</rollingPolicy>
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%thread] %-5level %logger{50}:%line - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 探针类:生产环境关闭 debug 输出,提升至 WARN;仍写入 -probe.log 便于异常排障 -->
|
||||
<logger name="cn.cloudwalk.elevator.debug" level="WARN" additivity="true">
|
||||
<appender-ref ref="PROBE"/>
|
||||
</logger>
|
||||
|
||||
<!-- 探针对照框架包统一提升至 WARN,关闭 debug 噪音 -->
|
||||
<logger name="org.springframework.cloud.consul" level="WARN" additivity="true">
|
||||
<appender-ref ref="PROBE"/>
|
||||
</logger>
|
||||
|
||||
<logger name="com.netflix.loadbalancer" level="WARN" additivity="true">
|
||||
<appender-ref ref="PROBE"/>
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.cloud.client.discovery" level="WARN" additivity="true">
|
||||
<appender-ref ref="PROBE"/>
|
||||
</logger>
|
||||
|
||||
<!-- 日志输出级别(默认 INFO;部署 application.properties 可再覆盖) -->
|
||||
<root level="INFO">
|
||||
<appender-ref ref="S"/>
|
||||
<appender-ref ref="R"/>
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 设备与通行相关 HTTP 入口:设备网关查询、电梯码、通行记录等 {@code /device/v2/} 下接口。
|
||||
* <p>
|
||||
* 负责表单/JSON 与业务 {@code param} 的转换,业务规则与远程协作放在 service 层。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.handler.device;
|
||||
/**
|
||||
* 设备与通行相关 HTTP 入口:设备网关查询、电梯码、通行记录等 {@code /device/v2/} 下接口。
|
||||
* <p>
|
||||
* 负责表单/JSON 与业务 {@code param} 的转换,业务规则与远程协作放在 service 层。
|
||||
*/
|
||||
package cn.cloudwalk.elevator.handler.device;
|
||||
|
||||
+14
-2
@@ -55,9 +55,21 @@ public class AcsPersonController extends AbstractCloudwalkController {
|
||||
AcsPersonAddVisitorParam param =
|
||||
(AcsPersonAddVisitorParam)BeanCopyUtils.copyProperties(form, AcsPersonAddVisitorParam.class);
|
||||
try {
|
||||
return this.personRuleService.addVisitor(param, getCloudwalkContext());
|
||||
String businessId = getCloudwalkContext().getCompany().getCompanyId();
|
||||
this.LOGGER.info(
|
||||
"访客派梯接口请求开始 businessId={} personId={} visitorId={} requestFloorSize={} beginTime={} endTime={}",
|
||||
businessId, form.getPersonId(), form.getVisitorId(),
|
||||
Integer.valueOf(form.getFloorIds() == null ? 0 : form.getFloorIds().size()), form.getBegVisitorTime(),
|
||||
form.getEndVisitorTime());
|
||||
CloudwalkResult<Boolean> result = this.personRuleService.addVisitor(param, getCloudwalkContext());
|
||||
this.LOGGER.info("访客派梯接口请求结束 businessId={} personId={} visitorId={} success={} code={} message={}",
|
||||
businessId, form.getPersonId(), form.getVisitorId(), Boolean.valueOf(result.isSuccess()),
|
||||
result.getCode(), result.getMessage());
|
||||
return result;
|
||||
} catch (ServiceException e) {
|
||||
this.LOGGER.error("根据被访人添加访客派梯权限失败,原因:", (Throwable)e);
|
||||
this.LOGGER.error("访客派梯接口异常 businessId={} personId={} visitorId={},原因:",
|
||||
getCloudwalkContext().getCompany().getCompanyId(), form.getPersonId(), form.getVisitorId(),
|
||||
(Throwable)e);
|
||||
return CloudwalkResult.fail("76260521", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,539 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<!-- 与 V1 运行包 META-INF/maven/.../cw-elevator-application-starter/pom.xml 声明的父坐标一致(私服缺失时在仓库内自建) -->
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.5.17.RELEASE</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<groupId>cn.cloudwalk.elevator</groupId>
|
||||
<artifactId>cw-elevator-application</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>cw-elevator-application (parent BOM)</name>
|
||||
<description>V1 父 POM 真源:dependencyManagement / 插件版本;继承 Spring Boot 1.5.17。业务 reactor 见 cw-elevator-application-reactor。</description>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<cloudwalk.internal.version>3.7.2-Brussels-SRX</cloudwalk.internal.version>
|
||||
<cloudwalk.legacy.public.version>3.7.2-Brussels-SRX</cloudwalk.legacy.public.version>
|
||||
<intelligent.cwoscomponent.version>2.9.2-xinghewan</intelligent.cwoscomponent.version>
|
||||
<fastjson.version>1.2.73</fastjson.version>
|
||||
<guava.version>20.0</guava.version>
|
||||
<poi.version>3.15</poi.version>
|
||||
<ant.version>1.9.6</ant.version>
|
||||
<thumbnailator.version>0.4.8</thumbnailator.version>
|
||||
<commons-io.version>2.5</commons-io.version>
|
||||
<commons-lang3.version>3.5</commons-lang3.version>
|
||||
<zip4j.version>2.6.2</zip4j.version>
|
||||
<zxing.version>3.3.3</zxing.version>
|
||||
<pagehelper.version>5.1.2</pagehelper.version>
|
||||
<pagehelper-spring-boot.version>1.2.5</pagehelper-spring-boot.version>
|
||||
<shardingsphere.version>4.0.0</shardingsphere.version>
|
||||
<mybatis.version>3.4.6</mybatis.version>
|
||||
<mybatis-spring.version>1.3.2</mybatis-spring.version>
|
||||
<mybatis-spring-boot.version>1.3.1</mybatis-spring-boot.version>
|
||||
<javax.servlet-api.version>3.1.0</javax.servlet-api.version>
|
||||
<javax.annotation-api.version>1.3.2</javax.annotation-api.version>
|
||||
<jsr305.version>3.0.2</jsr305.version>
|
||||
<cwos.sdk.resource.version>1.0.0-SNAPSHOT</cwos.sdk.resource.version>
|
||||
<cwos.sdk.event.version>1.5.0-SNAPSHOT</cwos.sdk.event.version>
|
||||
<intelligent.lock.version>1.1.1-SNAPSHOT</intelligent.lock.version>
|
||||
<davinci.manager.storage.version>1.1.7-SNAPSHOT</davinci.manager.storage.version>
|
||||
<nexus.baseUrl>http://192.168.3.12</nexus.baseUrl>
|
||||
<nexus.public.repo>${nexus.baseUrl}/repository/maven-public/</nexus.public.repo>
|
||||
<!-- JDK 8 可运行;勿改为 2.24+(需更高 JVM 运行插件) -->
|
||||
<formatter.maven.plugin.version>2.16.0</formatter.maven.plugin.version>
|
||||
<!-- 单独构建本 BOM 时用 elevator 聚合根的上级 docs;子模块由 reactor 覆盖此属性 -->
|
||||
<alibaba.eclipse.codestyle.path>${project.basedir}/../../docs/style/alibaba-eclipse-codestyle.xml</alibaba.eclipse.codestyle.path>
|
||||
<!-- V1 lib 中为 1.3.5/1.4.6 一代,非 SR6 默认的 1.3.6/1.4.7 -->
|
||||
<spring-cloud.version>Edgware.SR3</spring-cloud.version>
|
||||
<!-- V1 fat-jar 内 Spring Framework 为 4.3.29 -->
|
||||
<spring.version>4.3.29.RELEASE</spring.version>
|
||||
<!-- V1 lib 中 Jackson 多为 2.11.2(与 Boot 1.5 默认 2.8 并存形态对齐) -->
|
||||
<jackson.version>2.11.2</jackson.version>
|
||||
<!-- V1 lib:kafka-clients-2.3.0 -->
|
||||
<kafka.version>2.3.0</kafka.version>
|
||||
<jsoup.version>1.9.2</jsoup.version>
|
||||
<reflections.version>0.9.9-RC2</reflections.version>
|
||||
<gson.version>2.8.5</gson.version>
|
||||
<commons-fileupload.version>1.3.1</commons-fileupload.version>
|
||||
<javax.mail.version>1.4.4</javax.mail.version>
|
||||
<ehcache.version>2.10.5</ehcache.version>
|
||||
<opencsv.version>2.3</opencsv.version>
|
||||
<!-- V1 与 pagehelper 传递的 1.0 不同 -->
|
||||
<jsqlparser.version>1.2</jsqlparser.version>
|
||||
<commons-collections4.v1parity.version>4.1</commons-collections4.v1parity.version>
|
||||
<commons-compress.v1parity.version>1.9</commons-compress.v1parity.version>
|
||||
<cloudwalk.device.manager.version>2.0.2</cloudwalk.device.manager.version>
|
||||
<aliyun.sdk.core.version>3.2.8</aliyun.sdk.core.version>
|
||||
<aliyun.sdk.dysmsapi.version>1.1.0</aliyun.sdk.dysmsapi.version>
|
||||
<!-- V1 lib 中与旧 Feign okhttp 链共存的 OkHttp 修订版 -->
|
||||
<okhttp3.version>3.2.0</okhttp3.version>
|
||||
<okio.version>1.6.0</okio.version>
|
||||
<!-- spring-cloud-starter-openfeign 1.4.x 栈 -->
|
||||
<feign.version>9.5.0</feign.version>
|
||||
<feign-form.version>3.0.3</feign-form.version>
|
||||
<!-- 与 V1 fat-jar 中 cw-elevator-application-starter/pom.xml 一致 -->
|
||||
<spring-boot-maven-plugin.version>1.3.3.RELEASE</spring-boot-maven-plugin.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<!-- 覆盖 BOM,使嵌套 jar 坐标与 V1 运行包一致(Edgware.SR3 仍可能与样本略有出入,此处钉死样本中出现的修订版) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter</artifactId>
|
||||
<version>1.3.5.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-consul</artifactId>
|
||||
<version>1.3.5.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
|
||||
<version>1.3.5.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-commons</artifactId>
|
||||
<version>1.3.5.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-context</artifactId>
|
||||
<version>1.3.5.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-consul-core</artifactId>
|
||||
<version>1.3.5.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-consul-discovery</artifactId>
|
||||
<version>1.3.5.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix-core</artifactId>
|
||||
<version>1.4.6.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-archaius</artifactId>
|
||||
<version>1.4.6.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
|
||||
<version>1.4.6.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
|
||||
<version>1.4.6.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
|
||||
<version>1.4.6.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
<version>1.4.6.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-ribbon</artifactId>
|
||||
<version>1.4.6.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix-hystrix-dashboard</artifactId>
|
||||
<version>1.4.6.RELEASE</version>
|
||||
</dependency>
|
||||
<!-- OpenFeign / form:与 V1 lib、dependency:list 一致,显式钉死避免传递链升级到 10.x -->
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
<version>${feign.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-hystrix</artifactId>
|
||||
<version>${feign.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-slf4j</artifactId>
|
||||
<version>${feign.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-okhttp</artifactId>
|
||||
<version>${feign.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign.form</groupId>
|
||||
<artifactId>feign-form</artifactId>
|
||||
<version>${feign-form.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign.form</groupId>
|
||||
<artifactId>feign-form-spring</artifactId>
|
||||
<version>${feign-form.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.kafka</groupId>
|
||||
<artifactId>kafka-clients</artifactId>
|
||||
<version>${kafka.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>${gson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>${commons-fileupload.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
<version>${javax.mail.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
<version>${ehcache.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.opencsv</groupId>
|
||||
<artifactId>opencsv</artifactId>
|
||||
<version>${opencsv.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
<version>${commons-collections4.v1parity.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>${commons-compress.v1parity.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.jsqlparser</groupId>
|
||||
<artifactId>jsqlparser</artifactId>
|
||||
<version>${jsqlparser.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>${jsoup.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
<version>${reflections.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||
<version>${aliyun.sdk.core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
|
||||
<version>${aliyun.sdk.dysmsapi.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cloudwalk-device-manager-common</artifactId>
|
||||
<version>${cloudwalk.device.manager.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cloudwalk-device-manager-interface</artifactId>
|
||||
<version>${cloudwalk.device.manager.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cwos-common-aks-interface</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cwos-device-authentication-interface</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk</groupId>
|
||||
<artifactId>cwos-portal-interface</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk</groupId>
|
||||
<artifactId>cloudwalk-device-sdk-protocol-entity</artifactId>
|
||||
<version>2.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.module</groupId>
|
||||
<artifactId>jackson-module-afterburner</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.archaius</groupId>
|
||||
<artifactId>archaius-core</artifactId>
|
||||
<version>0.6.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${okhttp3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okio</groupId>
|
||||
<artifactId>okio</artifactId>
|
||||
<version>${okio.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cloudwalk-common-result</artifactId>
|
||||
<version>${cloudwalk.legacy.public.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cloudwalk-common-web</artifactId>
|
||||
<version>${cloudwalk.legacy.public.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cloudwalk-common-service</artifactId>
|
||||
<version>${cloudwalk.internal.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cloudwalk-common-event</artifactId>
|
||||
<version>${cloudwalk.internal.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cloudwalk-common-serial</artifactId>
|
||||
<version>${cloudwalk.legacy.public.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.intelligent</groupId>
|
||||
<artifactId>intelligent-cwoscomponent-interface</artifactId>
|
||||
<version>${intelligent.cwoscomponent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.intelligent</groupId>
|
||||
<artifactId>intelligent-cwoscomponent-rest</artifactId>
|
||||
<version>${intelligent.cwoscomponent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk</groupId>
|
||||
<artifactId>cwos-java-sdk-resource</artifactId>
|
||||
<version>${cwos.sdk.resource.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.cloud</groupId>
|
||||
<artifactId>cwos-sdk-event</artifactId>
|
||||
<version>${cwos.sdk.event.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.intelligent</groupId>
|
||||
<artifactId>cloudwalk-intelligent-component-lock</artifactId>
|
||||
<version>${intelligent.lock.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.intelligent</groupId>
|
||||
<artifactId>davinci-manager-storage</artifactId>
|
||||
<version>${davinci.manager.storage.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.ant</groupId>
|
||||
<artifactId>ant</artifactId>
|
||||
<version>${ant.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.coobird</groupId>
|
||||
<artifactId>thumbnailator</artifactId>
|
||||
<version>${thumbnailator.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons-io.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.lingala.zip4j</groupId>
|
||||
<artifactId>zip4j</artifactId>
|
||||
<version>${zip4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>${zxing.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper</artifactId>
|
||||
<version>${pagehelper.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-autoconfigure</artifactId>
|
||||
<version>${pagehelper-spring-boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.shardingsphere</groupId>
|
||||
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
|
||||
<version>${shardingsphere.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
<version>${mybatis.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-spring</artifactId>
|
||||
<version>${mybatis-spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>${mybatis-spring-boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>${javax.servlet-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
<version>${javax.annotation-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<version>${jsr305.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.el</groupId>
|
||||
<artifactId>javax.el-api</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>javax.el</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>nexus-public</id>
|
||||
<name>Nexus maven-public</name>
|
||||
<url>${nexus.public.repo}</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>nexus-public-plugins</id>
|
||||
<name>Nexus maven-public</name>
|
||||
<url>${nexus.public.repo}</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- V1 starter 显式使用 1.3.3;与 Boot 1.5 依赖并存时可产出与历史一致的 lib/ 布局 -->
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>net.revelc.code.formatter</groupId>
|
||||
<artifactId>formatter-maven-plugin</artifactId>
|
||||
<version>${formatter.maven.plugin.version}</version>
|
||||
<configuration>
|
||||
<configFile>${alibaba.eclipse.codestyle.path}</configFile>
|
||||
<lineEnding>LF</lineEnding>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
||||
@@ -13,7 +13,7 @@
|
||||
| 目录 | JAR | 端口(见配置首行) |
|
||||
|------|-----|-------------------|
|
||||
| `v1-legacy/` | `cw-elevator-application-V1.0.0.20211103.jar` | **18080** |
|
||||
| `v2-maven/` | `cw-elevator-application-2.0.0.jar` | **18081** |
|
||||
| `v2-maven/` | `cw-elevator-application-2.0.7.jar` | **18081** |
|
||||
|
||||
**`application.properties`**:在验证环境常用的 JDBC / Redis / Ribbon / Kafka / 端口等覆盖(数据库为生产还原时,请把 **jdbc-url、账号** 指到承载还原库的实例)。
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
## 一次性同步 JAR
|
||||
|
||||
在 **`deploy/`** 下执行(需已存在 V1 原始 JAR;V2 优先用 `releases/v2.0.0/`,否则用 `cw-elevator-application-starter/target/`):
|
||||
在 **`deploy/`** 下执行(需已存在 V1 原始 JAR;V2 优先用 **`releases/cw-elevator-application-V<版本>.<日期>/`** 中最新的同名 JAR,其次兼容旧路径 `releases/v<版本>/`,否则用 `cw-elevator-application-starter/target/`):
|
||||
|
||||
```bash
|
||||
./sync-jars.sh
|
||||
@@ -60,7 +60,7 @@ cd v2-maven && ./run.sh
|
||||
|
||||
### Feign `ninca-crk-std`(Ribbon)
|
||||
|
||||
在 **`spring.cloud.consul.discovery.enabled=false`**(与 V1 对齐)时,不从 Consul 拉 **`ninca-crk-std`** 实例,需在 **`application.properties`** 中配置 **Ribbon 静态列表**(`ninca-crk-std.ribbon.*` 与 `ninca-crk-std.ip`),按环境改成可访问的 **`主机:端口`**。Maven 构建的 `cw-elevator-application-2.0.0.jar` 另含 `NincaCrkStdRibbonConfiguration`,避免 Edgware 下静态列表被忽略。
|
||||
在 **`spring.cloud.consul.discovery.enabled=false`**(与 V1 对齐)时,不从 Consul 拉 **`ninca-crk-std`** 实例,需在 **`application.properties`** 中配置 **Ribbon 静态列表**(`ninca-crk-std.ribbon.*` 与 `ninca-crk-std.ip`),按环境改成可访问的 **`主机:端口`**。Maven 构建的 `cw-elevator-application-2.0.7.jar` 另含 `NincaCrkStdRibbonConfiguration`,避免 Edgware 下静态列表被忽略。
|
||||
|
||||
## Redis 与 `SPRING_APPLICATION_JSON`
|
||||
|
||||
@@ -100,6 +100,17 @@ fat JAR 的 `classpath:/application.properties` 会带内网旧 **host** 与 **p
|
||||
- 额外 JVM:
|
||||
`ELEVATOR_JAVA_OPTS="-Xmx512m" ./run.sh`
|
||||
|
||||
## 发布包与「星中心」扁平目录对齐
|
||||
|
||||
执行 `./scripts/release-cw-elevator-application.sh <版本>` 生成的 **`releases/cw-elevator-application-V<版本>.<日期>/`**(日期默认当天 `YYYYMMDD`,可用 **`RELEASE_DATE_LABEL`** 覆盖)除 **`ddl/`** 外,**发布根目录**(与历史运行包 **`cw-elevator-application-V1.0.0.20211103`** 同层习惯)包含:
|
||||
|
||||
- **`bootstrap.properties`、`application.properties`、`application-access-control.properties`**(与 `deploy/v2-maven/` 同源;与 JAR、`start.sh` 同目录,**不再单独建 `config/`**)。
|
||||
- **`start.sh` / `stop.sh`**(对齐现场启停脚本)、**`cw-elevator-application.service`**(`WorkingDirectory`/`ExecStart` 中占位路径默认为 `/path/to/cw-elevator-application`,部署前请替换为实际目录)。
|
||||
- **`run.sh`**、**`common-java.sh`**(供 `run.sh` source)。
|
||||
- **`collect_elevator_runtime_evidence.sh`**:与仓库根 `scripts/` 同源,置于发布包根目录;现场只读采集进程参数、配置快照、日志关键行、Consul 健康与 KV,输出 `tar.gz`(用法见脚本头注释)。
|
||||
|
||||
默认还会生成同名 **`releases/cw-elevator-application-V<版本>.<日期>.zip**`;不需要 zip 时:`RELEASE_MAKE_ZIP=0 ./scripts/release-cw-elevator-application.sh <版本>`。
|
||||
|
||||
## Shell 脚本换行(若出现 `bash\r`)
|
||||
|
||||
在 Windows 或某些编辑器下保存成 **CRLF** 会导致 `#!/usr/bin/env bash\r`。仓库根已有 **`.editorconfig`** 约束 `*.sh` 使用 **LF**;若再出现可执行:
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
[Unit]
|
||||
Description=cw-elevator-application __REL_VER__ (Maven V2 fat jar)
|
||||
After=network.target remote-fs.target nss-lookup.target
|
||||
|
||||
[Service]
|
||||
# 将 WorkingDirectory、ExecStart、ExecStop 中的路径占位改为实际部署绝对路径(与 JAR、start.sh、properties 同目录)。
|
||||
PIDFile=/run/cw-elevator-application-__REL_VER__.pid
|
||||
ExecStartPre=/bin/rm -f /run/cw-elevator-application-__REL_VER__.pid
|
||||
ExecStart=/bin/bash __DEPLOY_DIR__/start.sh
|
||||
ExecStop=/bin/bash __DEPLOY_DIR__/stop.sh
|
||||
ExecReload=/bin/kill -s HUP $MAINPID
|
||||
KillSignal=SIGQUIT
|
||||
TimeoutStopSec=5
|
||||
KillMode=process
|
||||
PrivateTmp=true
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
StandardOutput=null
|
||||
StandardError=null
|
||||
WorkingDirectory=__DEPLOY_DIR__
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
# 与「星中心」V1 部署习惯对齐:本脚本与 __JAR_NAME__、bootstrap/application*.properties 位于同一目录。
|
||||
# 覆盖 JVM:设置环境变量 ELEVATOR_JAVA_OPTS(可选);指定 Java:JAVA_HOME 或 JAVA_CMD。
|
||||
set -euo pipefail
|
||||
dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||
cd "$dir"
|
||||
JAR="__JAR_NAME__"
|
||||
if [[ ! -f "$JAR" ]]; then
|
||||
echo "ERROR: 未找到 ${JAR}(当前目录 $(pwd))" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "${JAVA_CMD:-}" ]]; then
|
||||
JAVA_EXEC="$JAVA_CMD"
|
||||
elif [[ -n "${JAVA_HOME:-}" && -x "${JAVA_HOME}/bin/java" ]]; then
|
||||
JAVA_EXEC="${JAVA_HOME}/bin/java"
|
||||
else
|
||||
JAVA_EXEC="/usr/lib/jvm/java-8-openjdk-amd64/bin/java"
|
||||
fi
|
||||
if [[ -z "${ELEVATOR_JAVA_OPTS:-}" ]]; then
|
||||
ELEVATOR_JAVA_OPTS="-Xmx3072m -Xms3072m -Xmn1024m"
|
||||
fi
|
||||
# shellcheck disable=SC2086
|
||||
exec "$JAVA_EXEC" $ELEVATOR_JAVA_OPTS -jar "$JAR"
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
# 停止与本目录 __JAR_NAME__ 对应的 Java 进程(仅匹配命令行中含该 JAR 名的进程)。
|
||||
set -euo pipefail
|
||||
JAR="__JAR_NAME__"
|
||||
# shellcheck disable=SC2009
|
||||
pid=$(ps -ef | grep '[j]ava' | grep "$JAR" | awk '{print $2}' || true)
|
||||
if [[ -n "${pid}" ]]; then
|
||||
kill -9 $pid
|
||||
fi
|
||||
@@ -12,8 +12,21 @@ MAVEN="$(cd "$DEPLOY/.." && pwd)"
|
||||
REPO="$(cd "$MAVEN/.." && pwd)"
|
||||
|
||||
V1_SRC="${REPO}/cw-elevator-application-V1.0.0.20211103/cw-elevator-application-V1.0.0.20211103.jar"
|
||||
V2_REL="${MAVEN}/releases/v2.0.0/cw-elevator-application-2.0.0.jar"
|
||||
V2_TGT="${MAVEN}/cw-elevator-application-starter/target/cw-elevator-application-2.0.0.jar"
|
||||
V2_VER="${V2_VER:-2.0.7}"
|
||||
V2_JAR_NAME="cw-elevator-application-${V2_VER}.jar"
|
||||
V2_TGT="${MAVEN}/cw-elevator-application-starter/target/${V2_JAR_NAME}"
|
||||
# 发布目录命名:cw-elevator-application-V<版本>.<YYYYMMDD>/(与 V1 运行包风格一致)
|
||||
V2_BUNDLE="$(ls -1dt "${MAVEN}/releases"/cw-elevator-application-V"${V2_VER}".* 2>/dev/null | head -1 || true)"
|
||||
V2_REL=""
|
||||
if [[ -n "${V2_BUNDLE}" ]]; then
|
||||
V2_REL="${V2_BUNDLE}/${V2_JAR_NAME}"
|
||||
fi
|
||||
if [[ -z "${V2_REL}" || ! -f "${V2_REL}" ]]; then
|
||||
V2_LEGACY="${MAVEN}/releases/v${V2_VER}/${V2_JAR_NAME}"
|
||||
if [[ -f "${V2_LEGACY}" ]]; then
|
||||
V2_REL="${V2_LEGACY}"
|
||||
fi
|
||||
fi
|
||||
PATCH_V1_DATA="${PARITY_PATCH_V1_DATA:-0}"
|
||||
DATA_NEW="${MAVEN}/cw-elevator-application-data/target/cw-elevator-application-data-2.0-SNAPSHOT.jar"
|
||||
|
||||
@@ -29,13 +42,14 @@ if [[ -f "$V2_TGT" ]]; then
|
||||
elif [[ -f "$V2_REL" ]]; then
|
||||
V2_SRC="$V2_REL"
|
||||
else
|
||||
echo "ERROR: 未找到 V2 JAR(请先 mvn package 或放入 releases):" >&2
|
||||
echo " $V2_TGT 或 $V2_REL" >&2
|
||||
echo "ERROR: 未找到 V2 JAR(请先 mvn package,或运行 scripts/release-cw-elevator-application.sh ${V2_VER}):" >&2
|
||||
echo " ${V2_TGT}" >&2
|
||||
echo " 或 releases/cw-elevator-application-V${V2_VER}.<日期>/${V2_JAR_NAME}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
install -m0644 "$V1_SRC" "${DEPLOY}/v1-legacy/cw-elevator-application-V1.0.0.20211103.jar"
|
||||
install -m0644 "$V2_SRC" "${DEPLOY}/v2-maven/cw-elevator-application-2.0.0.jar"
|
||||
install -m0644 "$V2_SRC" "${DEPLOY}/v2-maven/${V2_JAR_NAME}"
|
||||
|
||||
V1_OUT="${DEPLOY}/v1-legacy/cw-elevator-application-V1.0.0.20211103.jar"
|
||||
if [[ "$PATCH_V1_DATA" == "1" ]]; then
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# 来源:星河湾星中星/星中心/cw-elevator-application-V1.0.0.20211103/application-access-control.properties(生产门禁 access-control 参数)
|
||||
# profile=access-control 时与本目录 application.properties 合并加载;勿随意删减与分表相关项。
|
||||
# \u56FE\u7247\u524D\u7F00
|
||||
cloudwalk.elevator.common.relativePrefix=/cwos-portal/portal/fileManager/imgByPath?path=
|
||||
# \u6570\u636E\u5E93sharding\u914D\u7F6E
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# 与 V1 运行包 cw-elevator-application-V1.0.0.20211103/bootstrap.properties 中 Consul 段对齐。
|
||||
# Dubbo/ZooKeeper:V1 fat-jar 内含 dubbo 注册地址,本 Maven V2 工程未使用 Dubbo,故不写 zookeeper 段。
|
||||
# Consul 宿主机按本环境(局域网 Docker)覆盖。
|
||||
spring.cloud.consul.host=192.168.3.12
|
||||
server.port=16112
|
||||
server.tomcat.uri-encoding=UTF-8
|
||||
spring.application.name=elevator-app
|
||||
spring.profiles.active=access-control
|
||||
# consul\u914D\u7F6E
|
||||
spring.cloud.consul.host=371bfca4972c43d2aefcf302d0a4a277
|
||||
spring.cloud.consul.port=8500
|
||||
spring.cloud.consul.enabled=true
|
||||
spring.cloud.consul.discovery.register=true
|
||||
@@ -10,5 +12,7 @@ spring.cloud.consul.discovery.prefer-ip-address=true
|
||||
spring.cloud.consul.discovery.instance-id=${spring.application.name}-${spring.cloud.client.ipAddress}:${server.port}
|
||||
spring.cloud.consul.discovery.ip-address=${spring.cloud.client.ipAddress}
|
||||
spring.cloud.consul.discovery.deregister=false
|
||||
|
||||
spring.profiles.active=access-control
|
||||
# zookeeper\u914D\u7F6E
|
||||
dubbo.registry.address=zookeeper://10.0.22.207:2181
|
||||
dubbo.protocol.port=16107
|
||||
dubbo.provider.version=1.0
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+56
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration debug="false" scan="true">
|
||||
<property name="CONTEXT_NAME" value="api.1.0.0"/>
|
||||
<contextName>${CONTEXT_NAME}</contextName>
|
||||
|
||||
<springProperty scope="context" name="fileName" source="logging.file" defaultValue="default"/>
|
||||
|
||||
<!--myibatis log configure-->
|
||||
<logger name="com.apache.ibatis" level="DEBUG"/>
|
||||
<logger name="java.sql.Connection" level="DEBUG"/>
|
||||
<logger name="java.sql.Statement" level="DEBUG"/>
|
||||
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="S" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
|
||||
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%thread] %-5level %logger{50}:%line - %msg%n</pattern>
|
||||
<!-- 设置字符集 -->
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 按照每天生成日志文件 -->
|
||||
<appender name="R" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<File>${LOG_PATH}/${fileName}.log</File>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!--日志文件输出的文件名-->
|
||||
<FileNamePattern>${LOG_PATH}/${fileName}.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
|
||||
<!--日志文件保留天数-->
|
||||
<MaxHistory>7</MaxHistory>
|
||||
<!--日志文件大小 -->
|
||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||
<maxFileSize>50MB</maxFileSize>
|
||||
</timeBasedFileNamingAndTriggeringPolicy>
|
||||
</rollingPolicy>
|
||||
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
|
||||
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%thread] %-5level %logger{50}:%line - %msg%n</pattern>
|
||||
<!-- 设置字符集 -->
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
|
||||
<!--日志文件最大的大小-->
|
||||
<!-- <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> -->
|
||||
<!-- <MaxFileSize>10MB</MaxFileSize> -->
|
||||
<!-- </triggeringPolicy> -->
|
||||
</appender>
|
||||
|
||||
<!-- 日志输出级别 -->
|
||||
<root level="INFO">
|
||||
<appender-ref ref="S"/>
|
||||
<appender-ref ref="R"/>
|
||||
</root>
|
||||
</configuration>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
Manifest-Version: 1.0
|
||||
Implementation-Title: cw-elevator-application-starter
|
||||
Implementation-Version: 2.0-SNAPSHOT
|
||||
Archiver-Version: Plexus Archiver
|
||||
Built-By: zebra
|
||||
Implementation-Vendor-Id: cn.cloudwalk.elevator
|
||||
Spring-Boot-Version: 1.5.17.RELEASE
|
||||
Implementation-Vendor: Pivotal Software, Inc.
|
||||
Main-Class: org.springframework.boot.loader.JarLauncher
|
||||
Start-Class: cn.cloudwalk.elevator.ElevatorApplication
|
||||
Spring-Boot-Classes: BOOT-INF/classes/
|
||||
Spring-Boot-Lib: BOOT-INF/lib/
|
||||
Created-By: Apache Maven 3.9.10
|
||||
Build-Jdk: 1.8.0_482
|
||||
Implementation-URL: http://projects.spring.io/spring-boot/cw-elevator-
|
||||
application-reactor/cw-elevator-application-starter/
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
#Generated by Apache Maven
|
||||
#Wed Apr 29 12:15:25 CST 2026
|
||||
version=2.0-SNAPSHOT
|
||||
groupId=cn.cloudwalk.elevator
|
||||
artifactId=cw-elevator-application-starter
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>cn.cloudwalk.elevator</groupId>
|
||||
<artifactId>cw-elevator-application-reactor</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>cw-elevator-application-starter</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>cw-elevator-application-starter</name>
|
||||
<description>可执行 Spring Boot 入口:repackage 为单 JAR 发布包(对齐历史 V1 starter 形态)。</description>
|
||||
|
||||
<properties>
|
||||
<alibaba.eclipse.codestyle.path>${project.basedir}/../../docs/style/alibaba-eclipse-codestyle.xml</alibaba.eclipse.codestyle.path>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-cache</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk</groupId>
|
||||
<artifactId>cloudwalk-device-sdk-protocol-entity</artifactId>
|
||||
<version>2.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.cloudwalk.elevator</groupId>
|
||||
<artifactId>cw-elevator-application-web</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${elevator.release.finalName}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>net.revelc.code.formatter</groupId>
|
||||
<artifactId>formatter-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user