From ff81ea1b22aa35776012233f0e3c8b4073faee69 Mon Sep 17 00:00:00 2001
From: “mitao” <“2763622819@qq.com”>
Date: 星期五, 10 四月 2026 22:47:27 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'
---
xp-robotaxi-itinerary-boot/src/main/resources/application-local.yml | 108 ++++
xp-robotaxi-traffic-control-boot/src/main/resources/application-local.yml | 114 ++++
.gitignore | 4
xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/FeignLoggingAspect.java | 221 ++++++---
xp-robotaxi-traffic-control-boot/src/main/resources/bootstrap.yml | 160 ++++++
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpPointServiceImpl.java | 6
xp-robotaxi-traffic-control-boot/pom.xml | 47 --
xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MyLocaleResolver.java | 10
xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java | 315 +++++++------
/dev/null | 222 ---------
xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/TrafficControlApplication.java | 6
xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/controller/HttpTestController.java | 36 +
xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/utils/MinistryOfTransport.java | 106 ++++
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java | 2
xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MessageLocalConfig.java | 11
15 files changed, 858 insertions(+), 510 deletions(-)
diff --git a/.gitignore b/.gitignore
index e8734d7..bdc7f8a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,7 +15,7 @@
target
-*.yaml
-*.yml
+#*.yaml
+#*.yml
*.log.DS_Store
**/.DS_Store
diff --git a/xp-robotaxi-itinerary-boot/src/main/resources/application-local.yml b/xp-robotaxi-itinerary-boot/src/main/resources/application-local.yml
new file mode 100644
index 0000000..f39136b
--- /dev/null
+++ b/xp-robotaxi-itinerary-boot/src/main/resources/application-local.yml
@@ -0,0 +1,108 @@
+spring:
+ config:
+ activate:
+ on-profile: local
+ autoconfigure:
+ exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
+ redis:
+ database: 99
+ host: r-bp1ip8die60uuo3ovypd.redis.rds.aliyuncs.com
+ password: syAktm2x9uDusoF_
+ port: 6379
+ data:
+ mongodb:
+ host: dds-bp1f4a38f3cccad4-pub.mongodb.rds.aliyuncs.com
+ port: 3717
+ database: xp_robotaxi
+ username: xp_robotaxi
+ password: hDXSBe_hs0d5KxUf
+ shardingsphere:
+ datasource:
+ names: xp0
+ xp0:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://pc-bp1o444934f546768po.rwlb.rds.aliyuncs.com:3306/xp_rt_order?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: xp_rt_order
+ password: JLZtAI_BL4Lv5mbE
+ druid:
+ initial-size: 10
+ min-idle: 10
+ max-active: 100
+ max-wait: 60000
+ time-between-eviction-runs-millis: 60000
+ min-evictable-idle-time-millis: 300000
+ validation-query: SELECT 1
+ test-while-idle: true
+ test-on-borrow: false
+ test-on-return: false
+ pool-prepared-statements: true
+ max-pool-prepared-statement-per-connection-size: 20
+ filters: stat,wall,log4j
+ connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
+ remove-abandoned: true
+ remove-abandoned-timeout: 1800
+ log-abandoned: true
+ stat-view-servlet:
+ enabled: true
+ url-pattern: /druid/*
+ login-username: admin
+ login-password: admin
+ reset-enable: false
+ wall:
+ config:
+ multi-statement-allow: false
+ rules:
+ sharding:
+ tables:
+ sys_oper_log:
+ actual-data-nodes: xp0.sys_oper_log_${0..9}
+ table-strategy:
+ standard:
+ sharding-column: userId
+ sharding-algorithm-name: sys-oper-log-inline
+ key-generate-strategy:
+ column: oper_id
+ key-generator-name: snowflake
+ xp_agreement_app_user:
+ actual-data-nodes: xp0.xp_agreement_app_user_${0..9}
+ table-strategy:
+ standard:
+ sharding-column: app_user_id
+ sharding-algorithm-name: xp-agreement-app-user-inline
+ key-generate-strategy:
+ column: id
+ key-generator-name: snowflake
+ xp_point:
+ actual-data-nodes: xp0.xp_point_${0..9}
+ table-strategy:
+ standard:
+ sharding-column: electronic_area_id
+ sharding-algorithm-name: xp-point-inline
+ key-generate-strategy:
+ column: id
+ key-generator-name: snowflake
+ sharding-algorithms:
+ sys-oper-log-inline:
+ type: INLINE
+ props:
+ algorithm-expression: sys_oper_log_${userId % 10}
+ xp-agreement-app-user-inline:
+ type: INLINE
+ props:
+ algorithm-expression: xp_agreement_app_user_${app_user_id % 10}
+ xp-point-inline:
+ type: INLINE
+ props:
+ algorithm-expression: xp_point_${electronic_area_id % 10}
+ key-generators:
+ snowflake:
+ type: SNOWFLAKE
+ single-table:
+ default-data-source-name: xp0
+ props:
+ sql-show: true
+ sql-simple: true
+
+seata:
+ enabled: false
diff --git a/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpPointServiceImpl.java b/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpPointServiceImpl.java
index 933ec77..0cffd2f 100644
--- a/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpPointServiceImpl.java
+++ b/xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpPointServiceImpl.java
@@ -303,7 +303,10 @@
List<XpPoint> list = this.baseMapper.listAll(query);
for (XpPoint xpPoint : list) {
String pointPictures = xpPoint.getPointPictures();
+ log.info("pointPictures:{}", pointPictures);
if (StringUtils.isNotBlank(pointPictures)) {
+ log.info("pointPictures进入处理:{}", pointPictures);
+
JSONArray jsonArray = JSONArray.parseArray(pointPictures);
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
@@ -313,12 +316,15 @@
String downloadUrl ="";
try {
downloadUrl = aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true);
+ log.info("downloadUrl:{}", downloadUrl);
} catch (UnsupportedEncodingException e) {
log.error("获取图片下载地址失败", e);
}
jsonObject.put("url", downloadUrl);
}
+ log.info("jsonArray:{}", jsonArray);
xpPoint.setPointPictures(JSONArray.toJSONString(jsonArray));
+ log.info("xpPoint:{}", xpPoint.getPointPictures());
}
}
diff --git a/xp-robotaxi-traffic-control-boot/pom.xml b/xp-robotaxi-traffic-control-boot/pom.xml
index 349b4f1..42565f1 100644
--- a/xp-robotaxi-traffic-control-boot/pom.xml
+++ b/xp-robotaxi-traffic-control-boot/pom.xml
@@ -127,53 +127,6 @@
<artifactId>log4j-core</artifactId>
<version>2.25.3</version>
</dependency>
- <!-- easypoi -->
- <!-- Apache POI 核心依赖 -->
- <dependency>
- <groupId>org.apache.poi</groupId>
- <artifactId>poi</artifactId>
- <version>5.2.3</version>
- </dependency>
-
- <!-- Apache POI OOXML 支持(用于 .xlsx 文件) -->
- <dependency>
- <groupId>org.apache.poi</groupId>
- <artifactId>poi-ooxml</artifactId>
- <version>5.2.3</version>
- </dependency>
-
- <!-- Apache POI XMLBeans(可选,用于复杂 XML 处理) -->
- <dependency>
- <groupId>org.apache.xmlbeans</groupId>
- <artifactId>xmlbeans</artifactId>
- <version>5.1.1</version>
- </dependency>
- <dependency>
- <groupId>cn.afterturn</groupId>
- <artifactId>easypoi-base</artifactId>
- <version>4.4.0</version>
- <exclusions>
- <exclusion>
- <artifactId>guava</artifactId>
- <groupId>com.google.guava</groupId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>cn.afterturn</groupId>
- <artifactId>easypoi-web</artifactId>
- <version>4.4.0</version>
- </dependency>
- <dependency>
- <groupId>cn.afterturn</groupId>
- <artifactId>easypoi-annotation</artifactId>
- <version>4.4.0</version>
- </dependency>
- <dependency>
- <groupId>com.xiaopeng.logan</groupId>
- <artifactId>xp-evi-oss-sdk</artifactId>
- <version>1.0.1-SNAPSHOT</version>
- </dependency>
</dependencies>
<build>
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/DecodingException.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/DecodingException.java
deleted file mode 100644
index a1416fd..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/DecodingException.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.xiaopeng.trafficControl;
-
-/**
- * 解码处理异常类</br>
- */
-public class DecodingException extends RuntimeException {
- private static final long serialVersionUID = 1L;
-
- public DecodingException(String message) {
- super(message);
- }
-
- public DecodingException(Throwable cause) {
- super(cause);
- }
-
-}
\ No newline at end of file
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/TrafficControlApplication.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/TrafficControlApplication.java
index e9fe0df..2e5e963 100644
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/TrafficControlApplication.java
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/TrafficControlApplication.java
@@ -3,24 +3,20 @@
import com.xiaopeng.common.security.annotation.EnableCustomConfig;
import com.xiaopeng.common.security.annotation.EnableRyFeignClients;
import com.xiaopeng.common.swagger.annotation.EnableCustomSwagger2;
-import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
-import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* 交通监管模块
*/
@EnableCustomConfig
-@MapperScan({"com.xiaopeng.trafficControl.mapper"})
@EnableCustomSwagger2
@EnableRyFeignClients
@SpringBootApplication
-@EnableScheduling//开启定时任务
+@EnableScheduling
@ServletComponentScan
-@EnableTransactionManagement//开启事务
public class TrafficControlApplication {
public static void main(String[] args) {
SpringApplication.run(TrafficControlApplication.class, args);
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/DataUpdateHandlerConfig.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/DataUpdateHandlerConfig.java
deleted file mode 100644
index cc030b6..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/DataUpdateHandlerConfig.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.xiaopeng.trafficControl.config;
-
-import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
-import com.xiaopeng.common.core.utils.StringUtils;
-import com.xiaopeng.common.security.utils.SecurityUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.ibatis.reflection.MetaObject;
-import org.springframework.context.annotation.Configuration;
-
-import java.time.LocalDateTime;
-
-/**
- * @author xiaochen
- * @ClassName DataUpdateInterceptor
- * @Description 数据更新操作处理
- * @date 2021-12-15
- * <p>
- * 注意,之前在此处注入了 JwtTokenUtils
- * <p>
- * 造成spring循环依赖,项目支棱不起来
- */
-@Slf4j
-@Configuration
-public class DataUpdateHandlerConfig implements MetaObjectHandler {
-
- /**
- * 新增数据执行
- *
- * @param metaObject
- */
- @Override
- public void insertFill(MetaObject metaObject) {
- String userName = "";
- try{
- // 获取登录信息
- userName = SecurityUtils.getLoginUser().getSysUser().getNickName();
- log.info("DataUpdateInterceptor insertFill");
- } catch (Exception e) {
- log.error("DataUpdateInterceptor insertFill error:{}", e.getMessage());
- }
- if (StringUtils.isNotBlank(userName)) {
- this.setFieldValByName("createBy", userName, metaObject);
- this.setFieldValByName("updateBy", userName, metaObject);
- } else {
- this.setFieldValByName("createBy", userName, metaObject);
- this.setFieldValByName("updateBy", userName, metaObject);
- }
- this.setFieldValByName("createTime", LocalDateTime.now(), metaObject);
- this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
- }
-
- /**
- * 修改数据执行
- *
- * @param metaObject
- */
- @Override
- public void updateFill(MetaObject metaObject) {
- String userName = "";
- try{
- // 获取登录信息
- userName = SecurityUtils.getLoginUser().getSysUser().getNickName();
- log.info("DataUpdateInterceptor insertFill");
- } catch (Exception e) {
- log.error("DataUpdateInterceptor insertFill error:{}", e.getMessage());
- }
- this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
- this.setFieldValByName("updateBy", userName, metaObject);
-
- }
-}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MessageLocalConfig.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MessageLocalConfig.java
index 37ce6c2..90c5212 100644
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MessageLocalConfig.java
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MessageLocalConfig.java
@@ -6,7 +6,6 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.util.StringUtils;
-import org.springframework.web.servlet.LocaleResolver;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
@@ -17,6 +16,7 @@
*/
@Configuration
public class MessageLocalConfig {
+
@Bean
public MessageSourceProperties messageSourceProperties() {
@@ -29,6 +29,7 @@
properties.setUseCodeAsDefaultMessage(true);
return properties;
}
+
@Bean
public MessageSource messageSource(MessageSourceProperties properties) {
@@ -51,9 +52,9 @@
}
- @Bean//注册国际化组件
- public LocaleResolver localeResolver(){
- return new MyLocaleResolver();
- }
+// @Bean//注册国际化组件
+// public LocaleResolver localeResolver(){
+// return new MyLocaleResolver();
+// }
}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MultipartFilterConfig.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MultipartFilterConfig.java
deleted file mode 100644
index 3810404..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MultipartFilterConfig.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.xiaopeng.trafficControl.config;
-
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import javax.servlet.*;
-import javax.servlet.http.HttpServletRequest;
-import java.io.IOException;
-
-
-/**
- * 修复 multipart 文件上传被 ReplaceRequestFilter 破坏的问题。
- * <p>
- * ReplaceRequestFilter(来自 request-wrapper jar,logan-starter-core 传递依赖)
- * 会读取 request 的 InputStream 来包装请求体,导致后续 Spring 解析 multipart 时
- * 抛出 "Stream closed" 异常。
- * <p>
- * 解决方案:注册一个高优先级 Filter,对 multipart 请求提前触发 Servlet 容器的
- * multipart 解析(通过调用 request.getParts()),使文件数据被缓存到临时文件中。
- * 这样即使后续 ReplaceRequestFilter 消费了 InputStream,multipart 数据仍然可用。
- */
-@Slf4j
-@Configuration
-public class MultipartFilterConfig {
-
- private static final String MULTIPART = "multipart/";
- @Bean
- public FilterRegistrationBean<Filter> earlyMultipartParsingFilter() {
- FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
- registration.setFilter(new EarlyMultipartParsingFilter());
- registration.addUrlPatterns("/*");
- // 确保在 ReplaceRequestFilter 之前执行
- registration.setOrder(Integer.MIN_VALUE + 10);
- registration.setName("earlyMultipartParsingFilter");
- return registration;
- }
- /**
- * 在 filter 链最前面对 multipart 请求提前解析,
- * 让 Tomcat 将文件数据缓存到磁盘,避免后续 filter 消费 InputStream 导致 Stream closed。
- */
- static class EarlyMultipartParsingFilter implements Filter {
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- throws IOException, ServletException {
- if (request instanceof HttpServletRequest) {
- HttpServletRequest httpRequest = (HttpServletRequest) request;
- String contentType = httpRequest.getContentType();
- if (contentType != null && contentType.toLowerCase().startsWith(MULTIPART)) {
- // 提前触发 multipart 解析,Tomcat 会将 parts 缓存
- try {
- httpRequest.getParts();
- } catch (Exception e) {
- log.warn("Early multipart parsing failed, will retry later: {}", e.getMessage());
- }
- }
- }
- chain.doFilter(request, response);
- }
- }
-
-}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MyLocaleResolver.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MyLocaleResolver.java
index f23bb21..cc06b0b 100644
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MyLocaleResolver.java
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MyLocaleResolver.java
@@ -27,12 +27,10 @@
}
//如果请求不为空
//If the request is not empty.
- if(!StringUtils.isEmpty(language)){
- if (language.equals("1")) {
- locale = new Locale("zh", "CN");
- } else if (language.equals("2")) {
- locale = new Locale("en", "US");
- }
+ if (language.equals("1")) {
+ locale = new Locale("zh", "CN");
+ } else if (language.equals("2")) {
+ locale = new Locale("en", "US");
}
return locale;
}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MybatisPlusConfig.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MybatisPlusConfig.java
deleted file mode 100644
index 4642647..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MybatisPlusConfig.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.xiaopeng.trafficControl.config;
-
-import com.baomidou.mybatisplus.annotation.DbType;
-import com.baomidou.mybatisplus.core.config.GlobalConfig;
-import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
-import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * @author xiaochen
- * @ClassName MybatisPlusConfig
- * @Description MybatisPlus相关配置
- * @date 2020-09-22 11:22、
- * 直接以实现类作为bean的注入(有事务管理的类)
- * @EnableTransactionManagement(proxyTargetClass = true)
- */
-@Configuration
-public class MybatisPlusConfig {
- private final DataUpdateHandlerConfig dataUpdateHandler;
-
- @Autowired
- public MybatisPlusConfig(DataUpdateHandlerConfig dataUpdateHandler) {
- this.dataUpdateHandler = dataUpdateHandler;
- }
-
- /**
- * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题
- */
- @Bean
- public MybatisPlusInterceptor mybatisPlusInterceptor() {
- MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
- interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
- return interceptor;
- }
-
- /**
- * 自动填充功能
- *
- * @return
- */
- @Bean
- public GlobalConfig globalConfig() {
- GlobalConfig globalConfig = new GlobalConfig();
- globalConfig.setMetaObjectHandler(dataUpdateHandler);
- return globalConfig;
- }
-
-
-}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/TransactionConfiguration.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/TransactionConfiguration.java
deleted file mode 100644
index a814162..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/TransactionConfiguration.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.xiaopeng.trafficControl.config;
-
-import javax.sql.DataSource;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jdbc.datasource.DataSourceTransactionManager;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.annotation.EnableTransactionManagement;
-
-/**
- * 分布式事务配置
- */
-@Configuration
-@EnableTransactionManagement
-public class TransactionConfiguration {
-
- @Bean
- public PlatformTransactionManager txManager(final DataSource dataSource) {
- return new DataSourceTransactionManager(dataSource);
- }
-
- @Bean
- public JdbcTemplate jdbcTemplate(final DataSource dataSource) {
- return new JdbcTemplate(dataSource);
- }
-}
\ No newline at end of file
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/FeignLoggingAspect.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/FeignLoggingAspect.java
index a2da7be..d4ebd88 100644
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/FeignLoggingAspect.java
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/FeignLoggingAspect.java
@@ -1,83 +1,138 @@
-package com.xiaopeng.trafficControl.config.log;
-
-import com.alibaba.fastjson2.JSON;
-import lombok.extern.slf4j.Slf4j;
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.reflect.MethodSignature;
-import org.springframework.stereotype.Component;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-
-/**
- * Feign 调用日志切面
- *
- * <p>拦截所有带 @FeignClient 注解的接口方法,记录:
- * <ul>
- * <li>调用的接口类名 + 方法名</li>
- * <li>入参(JSON 序列化)</li>
- * <li>出参(JSON 序列化)</li>
- * <li>耗时(ms)</li>
- * <li>异常信息(含完整堆栈)</li>
- * </ul>
- */
-@Slf4j
-@Aspect
-@Component
-public class FeignLoggingAspect {
-
- /**
- * 拦截所有带 @FeignClient 注解的接口的所有方法
- */
- @Around("within(@org.springframework.cloud.openfeign.FeignClient *)")
- public Object logFeignCall(ProceedingJoinPoint pjp) throws Throwable {
- return doLog(pjp);
- }
-
- private Object doLog(ProceedingJoinPoint pjp) throws Throwable {
- MethodSignature signature = (MethodSignature) pjp.getSignature();
- Method method = signature.getMethod();
- // 使用接口声明类名,避免打印动态代理类名(如 $Proxy270)
- String className = signature.getDeclaringType().getSimpleName();
- String methodName = method.getName();
- String fullMethod = className + "#" + methodName;
-
- Object[] args = pjp.getArgs();
- String argsJson = safeToJson(args);
-
- log.info("[Feign] >>> 调用开始 | method={} | args={}", fullMethod, argsJson);
-
- long start = System.currentTimeMillis();
- try {
- Object result = pjp.proceed();
- long elapsed = System.currentTimeMillis() - start;
- String resultJson = safeToJson(result);
- log.info("[Feign] <<< 调用成功 | method={} | elapsed={}ms | result={}", fullMethod, elapsed, resultJson);
- return result;
- } catch (Throwable ex) {
- long elapsed = System.currentTimeMillis() - start;
- log.error("[Feign] <<< 调用异常 | method={} | elapsed={}ms | error={} | args={}",
- fullMethod, elapsed, ex.getMessage(), argsJson, ex);
- throw ex;
- }
- }
-
- /**
- * 安全序列化为 JSON,避免序列化失败导致日志切面本身抛异常
- */
- private String safeToJson(Object obj) {
- if (obj == null) {
- return "null";
- }
- try {
- if (obj instanceof Object[]) {
- return JSON.toJSONString(Arrays.asList((Object[]) obj));
- }
- return JSON.toJSONString(obj);
- } catch (Exception e) {
- return "[序列化失败: " + obj.getClass().getSimpleName() + "]";
- }
- }
-}
+//package com.xiaopeng.trafficControl.config.log;
+//
+//import com.alibaba.fastjson2.JSON;
+//import com.xiaopeng.common.log.config.LogHeaderProperties;
+//import lombok.extern.slf4j.Slf4j;
+//import org.aspectj.lang.ProceedingJoinPoint;
+//import org.aspectj.lang.annotation.Around;
+//import org.aspectj.lang.annotation.Aspect;
+//import org.aspectj.lang.reflect.MethodSignature;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.stereotype.Component;
+//import org.springframework.web.context.request.RequestContextHolder;
+//import org.springframework.web.context.request.ServletRequestAttributes;
+//
+//import javax.servlet.http.HttpServletRequest;
+//import java.lang.reflect.Method;
+//import java.util.Arrays;
+//import java.util.Enumeration;
+//import java.util.List;
+//
+///**
+// * Feign 调用日志切面
+// *
+// * <p>拦截所有带 @FeignClient 注解的接口方法,记录:
+// * <ul>
+// * <li>调用的接口类名 + 方法名</li>
+// * <li>入参(JSON 序列化)</li>
+// * <li>出参(JSON 序列化)</li>
+// * <li>耗时(ms)</li>
+// * <li>异常信息(含完整堆栈)</li>
+// * </ul>
+// */
+//@Slf4j
+//@Aspect
+//@Component
+//public class FeignLoggingAspect {
+//
+// @Autowired
+// private LogHeaderProperties logHeaderProperties;
+//
+// /**
+// * 拦截所有带 @FeignClient 注解的接口的所有方法
+// */
+// @Around("within(@org.springframework.cloud.openfeign.FeignClient *)")
+// public Object logFeignCall(ProceedingJoinPoint pjp) throws Throwable {
+// return doLog(pjp);
+// }
+//
+// private Object doLog(ProceedingJoinPoint pjp) throws Throwable {
+// MethodSignature signature = (MethodSignature) pjp.getSignature();
+// Method method = signature.getMethod();
+// // 使用接口声明类名,避免打印动态代理类名(如 $Proxy270)
+// String className = signature.getDeclaringType().getSimpleName();
+// String methodName = method.getName();
+// String fullMethod = className + "#" + methodName;
+//
+// Object[] args = pjp.getArgs();
+// String argsJson = safeToJson(args);
+// String headerStr = extractCurrentHeaders();
+//
+// if (headerStr != null) {
+// log.info("[Feign] >>> 调用开始 | method={} | headers={} | args={}", fullMethod, headerStr, argsJson);
+// } else {
+// log.info("[Feign] >>> 调用开始 | method={} | args={}", fullMethod, argsJson);
+// }
+//
+// long start = System.currentTimeMillis();
+// try {
+// Object result = pjp.proceed();
+// long elapsed = System.currentTimeMillis() - start;
+// String resultJson = safeToJson(result);
+// log.info("[Feign] <<< 调用成功 | method={} | elapsed={}ms | result={}", fullMethod, elapsed, resultJson);
+// return result;
+// } catch (Throwable ex) {
+// long elapsed = System.currentTimeMillis() - start;
+// log.error("[Feign] <<< 调用异常 | method={} | elapsed={}ms | error={} | args={}",
+// fullMethod, elapsed, ex.getMessage(), argsJson, ex);
+// throw ex;
+// }
+// }
+//
+// /**
+// * 安全序列化为 JSON,避免序列化失败导致日志切面本身抛异常
+// */
+// private String safeToJson(Object obj) {
+// if (obj == null) {
+// return "null";
+// }
+// try {
+// if (obj instanceof Object[]) {
+// return JSON.toJSONString(Arrays.asList((Object[]) obj));
+// }
+// return JSON.toJSONString(obj);
+// } catch (Exception e) {
+// return "[序列化失败: " + obj.getClass().getSimpleName() + "]";
+// }
+// }
+//
+// /**
+// * 从当前请求上下文中提取请求头信息
+// */
+// private String extractCurrentHeaders() {
+// if (!logHeaderProperties.isEnabled()) {
+// return null;
+// }
+// try {
+// ServletRequestAttributes attrs = (ServletRequestAttributes)
+// RequestContextHolder.getRequestAttributes();
+// if (attrs == null) return "{}";
+// HttpServletRequest request = attrs.getRequest();
+// List<String> names = logHeaderProperties.getNames();
+// StringBuilder sb = new StringBuilder("{");
+// boolean first = true;
+// if (names != null && !names.isEmpty()) {
+// for (String name : names) {
+// String value = request.getHeader(name);
+// if (value != null) {
+// if (!first) sb.append(", ");
+// first = false;
+// sb.append(name).append("=").append(value);
+// }
+// }
+// } else {
+// Enumeration<String> headerNames = request.getHeaderNames();
+// while (headerNames != null && headerNames.hasMoreElements()) {
+// String name = headerNames.nextElement();
+// String value = request.getHeader(name);
+// if (!first) sb.append(", ");
+// first = false;
+// sb.append(name).append("=").append(value);
+// }
+// }
+// return sb.append("}").toString();
+// } catch (Exception e) {
+// return "{error: " + e.getMessage() + "}";
+// }
+// }
+//}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java
index 5c46133..f70057c 100644
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java
@@ -1,139 +1,176 @@
-package com.xiaopeng.trafficControl.config.log;
-
-import lombok.extern.slf4j.Slf4j;
-import org.slf4j.MDC;
-import org.springframework.core.Ordered;
-import org.springframework.core.annotation.Order;
-import org.springframework.http.MediaType;
-import org.springframework.stereotype.Component;
-import org.springframework.web.filter.OncePerRequestFilter;
-import org.springframework.web.util.ContentCachingRequestWrapper;
-import org.springframework.web.util.ContentCachingResponseWrapper;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * 请求/响应日志过滤器
- * 打印:traceId、method、uri、queryString、请求体、响应状态、耗时、响应体
- */
-@Slf4j
-@Component
-@Order(Ordered.HIGHEST_PRECEDENCE + 10)
-public class RequestResponseLoggingFilter extends OncePerRequestFilter {
-
- /** 不打印 body 的路径前缀(健康检查、actuator 等) */
- private static final Set<String> EXCLUDE_PATHS = new HashSet<>(Arrays.asList(
- "/actuator", "/healthcheck", "/health", "/prometheus"
- ));
-
- /** 只对这些 Content-Type 打印 body(避免打印二进制流) */
- private static final Set<String> LOGGABLE_CONTENT_TYPES = new HashSet<>(Arrays.asList(
- MediaType.APPLICATION_JSON_VALUE,
- MediaType.APPLICATION_JSON_UTF8_VALUE,
- MediaType.TEXT_PLAIN_VALUE,
- MediaType.TEXT_XML_VALUE,
- MediaType.APPLICATION_XML_VALUE,
- "application/x-www-form-urlencoded"
- ));
-
- private static final int MAX_BODY_LENGTH = 2000;
-
- @Override
- protected boolean shouldNotFilter(HttpServletRequest request) {
- String uri = request.getRequestURI();
- return EXCLUDE_PATHS.stream().anyMatch(uri::startsWith);
- }
-
- @Override
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
- FilterChain chain) throws ServletException, IOException {
- // 初始化 MDC(Filter 先于 Interceptor 执行,在此统一设置)
- String traceId = request.getHeader("X-Trace-Id");
- if (traceId == null || traceId.isEmpty()) {
- traceId = java.util.UUID.randomUUID().toString().replace("-", "");
- }
- MDC.put("traceId", traceId);
- MDC.put("clientIp", getClientIp(request));
- MDC.put("requestUri", request.getRequestURI());
- response.setHeader("X-Trace-Id", traceId);
-
- ContentCachingRequestWrapper reqWrapper = new ContentCachingRequestWrapper(request);
- ContentCachingResponseWrapper respWrapper = new ContentCachingResponseWrapper(response);
-
- long start = System.currentTimeMillis();
- try {
- chain.doFilter(reqWrapper, respWrapper);
- } finally {
- long cost = System.currentTimeMillis() - start;
- logRequest(reqWrapper);
- logResponse(respWrapper, cost);
- // 必须把响应体写回,否则客户端收不到数据
- respWrapper.copyBodyToResponse();
- MDC.clear();
- }
- }
-
- private String getClientIp(HttpServletRequest request) {
- String ip = request.getHeader("X-Forwarded-For");
- if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
- return ip.split(",")[0].trim();
- }
- ip = request.getHeader("X-Real-IP");
- if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
- return ip;
- }
- return request.getRemoteAddr();
- }
-
- private void logRequest(ContentCachingRequestWrapper request) {
- String traceId = MDC.get("traceId");
- String uri = request.getRequestURI();
- String query = request.getQueryString();
- String method = request.getMethod();
- String body = extractBody(request.getContentAsByteArray(), request.getContentType());
-
- log.info(">>> [{}] {} {}{} | body={}",
- traceId,
- method,
- uri,
- query != null ? "?" + query : "",
- body);
- }
-
- private void logResponse(ContentCachingResponseWrapper response, long cost) {
- String traceId = MDC.get("traceId");
- int status = response.getStatus();
- String body = extractBody(response.getContentAsByteArray(), response.getContentType());
-
- log.info("<<< [{}] status={} cost={}ms | body={}",
- traceId, status, cost, body);
- }
-
- private String extractBody(byte[] bodyBytes, String contentType) {
- if (bodyBytes == null || bodyBytes.length == 0) {
- return "";
- }
- if (!isLoggableContentType(contentType)) {
- return "[binary, " + bodyBytes.length + " bytes]";
- }
- String body = new String(bodyBytes, StandardCharsets.UTF_8);
- if (body.length() > MAX_BODY_LENGTH) {
- body = body.substring(0, MAX_BODY_LENGTH) + "...(truncated)";
- }
- return body;
- }
-
- private boolean isLoggableContentType(String contentType) {
- if (contentType == null) return true;
- String ct = contentType.toLowerCase();
- return LOGGABLE_CONTENT_TYPES.stream().anyMatch(ct::contains);
- }
-}
+//package com.xiaopeng.trafficControl.config.log;
+//
+//import com.xiaopeng.common.log.config.LogHeaderProperties;
+//import lombok.extern.slf4j.Slf4j;
+//import org.slf4j.MDC;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.core.Ordered;
+//import org.springframework.core.annotation.Order;
+//import org.springframework.http.MediaType;
+//import org.springframework.stereotype.Component;
+//import org.springframework.web.filter.OncePerRequestFilter;
+//import org.springframework.web.util.ContentCachingRequestWrapper;
+//import org.springframework.web.util.ContentCachingResponseWrapper;
+//
+//import javax.servlet.FilterChain;
+//import javax.servlet.ServletException;
+//import javax.servlet.http.HttpServletRequest;
+//import javax.servlet.http.HttpServletResponse;
+//import java.io.IOException;
+//import java.nio.charset.StandardCharsets;
+//import java.util.*;
+//
+///**
+// * 请求/响应日志过滤器
+// * 打印:traceId、method、uri、queryString、请求体、响应状态、耗时、响应体
+// */
+//@Slf4j
+//@Component
+//@Order(Ordered.HIGHEST_PRECEDENCE + 10)
+//public class RequestResponseLoggingFilter extends OncePerRequestFilter {
+//
+// @Autowired
+// private LogHeaderProperties logHeaderProperties;
+//
+// /** 不打印 body 的路径前缀(健康检查、actuator 等) */
+// private static final Set<String> EXCLUDE_PATHS = new HashSet<>(Arrays.asList(
+// "/actuator", "/healthcheck", "/health", "/prometheus"
+// ));
+//
+// /** 只对这些 Content-Type 打印 body(避免打印二进制流) */
+// private static final Set<String> LOGGABLE_CONTENT_TYPES = new HashSet<>(Arrays.asList(
+// MediaType.APPLICATION_JSON_VALUE,
+// MediaType.APPLICATION_JSON_UTF8_VALUE,
+// MediaType.TEXT_PLAIN_VALUE,
+// MediaType.TEXT_XML_VALUE,
+// MediaType.APPLICATION_XML_VALUE,
+// "application/x-www-form-urlencoded"
+// ));
+//
+// private static final int MAX_BODY_LENGTH = 2000;
+//
+// @Override
+// protected boolean shouldNotFilter(HttpServletRequest request) {
+// String uri = request.getRequestURI();
+// return EXCLUDE_PATHS.stream().anyMatch(uri::startsWith);
+// }
+//
+// @Override
+// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
+// FilterChain chain) throws ServletException, IOException {
+// // 初始化 MDC(Filter 先于 Interceptor 执行,在此统一设置)
+// String traceId = request.getHeader("X-Trace-Id");
+// if (traceId == null || traceId.isEmpty()) {
+// traceId = UUID.randomUUID().toString().replace("-", "");
+// }
+// MDC.put("traceId", traceId);
+// MDC.put("clientIp", getClientIp(request));
+// MDC.put("requestUri", request.getRequestURI());
+// response.setHeader("X-Trace-Id", traceId);
+//
+// ContentCachingRequestWrapper reqWrapper = new ContentCachingRequestWrapper(request);
+// ContentCachingResponseWrapper respWrapper = new ContentCachingResponseWrapper(response);
+//
+// long start = System.currentTimeMillis();
+// try {
+// chain.doFilter(reqWrapper, respWrapper);
+// } finally {
+// long cost = System.currentTimeMillis() - start;
+// logRequest(reqWrapper);
+// logResponse(respWrapper, cost);
+// // 必须把响应体写回,否则客户端收不到数据
+// respWrapper.copyBodyToResponse();
+// MDC.clear();
+// }
+// }
+//
+// private String getClientIp(HttpServletRequest request) {
+// String ip = request.getHeader("X-Forwarded-For");
+// if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
+// return ip.split(",")[0].trim();
+// }
+// ip = request.getHeader("X-Real-IP");
+// if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
+// return ip;
+// }
+// return request.getRemoteAddr();
+// }
+//
+// private void logRequest(ContentCachingRequestWrapper request) {
+// String traceId = MDC.get("traceId");
+// String uri = request.getRequestURI();
+// String query = request.getQueryString();
+// String method = request.getMethod();
+// String body = extractBody(request.getContentAsByteArray(), request.getContentType());
+//
+// if (logHeaderProperties.isEnabled()) {
+// String headers = extractHeaders(request);
+// log.info(">>> [{}] {} {}{} | headers={} | body={}",
+// traceId, method, uri,
+// query != null ? "?" + query : "",
+// headers, body);
+// } else {
+// log.info(">>> [{}] {} {}{} | body={}",
+// traceId, method, uri,
+// query != null ? "?" + query : "",
+// body);
+// }
+// }
+//
+// private String extractHeaders(HttpServletRequest request) {
+// List<String> names = logHeaderProperties.getNames();
+// StringBuilder sb = new StringBuilder("{");
+// boolean first = true;
+// if (names != null && !names.isEmpty()) {
+// // 只打印配置的请求头
+// for (String name : names) {
+// String value = request.getHeader(name);
+// if (value != null) {
+// if (!first) sb.append(", ");
+// first = false;
+// sb.append(name).append("=").append(value);
+// }
+// }
+// } else {
+// // 未配置则打印全部请求头
+// Enumeration<String> headerNames = request.getHeaderNames();
+// while (headerNames != null && headerNames.hasMoreElements()) {
+// String name = headerNames.nextElement();
+// String value = request.getHeader(name);
+// if (!first) sb.append(", ");
+// first = false;
+// sb.append(name).append("=").append(value);
+// }
+// }
+// return sb.append("}").toString();
+// }
+//
+// private void logResponse(ContentCachingResponseWrapper response, long cost) {
+// String traceId = MDC.get("traceId");
+// int status = response.getStatus();
+// String body = extractBody(response.getContentAsByteArray(), response.getContentType());
+//
+// log.info("<<< [{}] status={} cost={}ms | body={}",
+// traceId, status, cost, body);
+// }
+//
+// private String extractBody(byte[] bodyBytes, String contentType) {
+// if (bodyBytes == null || bodyBytes.length == 0) {
+// return "";
+// }
+// if (!isLoggableContentType(contentType)) {
+// return "[binary, " + bodyBytes.length + " bytes]";
+// }
+// String body = new String(bodyBytes, StandardCharsets.UTF_8);
+// if (body.length() > MAX_BODY_LENGTH) {
+// body = body.substring(0, MAX_BODY_LENGTH) + "...(truncated)";
+// }
+// return body;
+// }
+//
+// private boolean isLoggableContentType(String contentType) {
+// if (contentType == null) return true;
+// String ct = contentType.toLowerCase();
+// return LOGGABLE_CONTENT_TYPES.stream().anyMatch(ct::contains);
+// }
+//}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/constant/I18nKeyConstant.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/constant/I18nKeyConstant.java
deleted file mode 100644
index dff7880..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/constant/I18nKeyConstant.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.xiaopeng.trafficControl.constant;
-
-/**
- * @author MiTao
- * @date 2026-02-06 17:34
- * 国际化消息键常量
- *
- */
-public interface I18nKeyConstant {
- //========== 小程序业务流程 ==========
- String ORDER_NOT_EXISTS = "order.not.exists";
- String VEHICLE_NOT_EXISTS = "vehicle.not.exists";
-
- // ========== 车辆导入相关 ==========
- String VEHICLE_IMPORT_FAILED = "vehicle.import.failed";
- String VEHICLE_IMPORT_DATA_EMPTY = "vehicle.import.data.empty";
- String VEHICLE_IMPORT_FIELDS_REQUIRED = "vehicle.import.fields.required";
-
- // ========== 车队删除相关 ==========
- String FLEET_DELETE_HAS_BOUND_VEHICLE_OR_USER = "fleet.delete.has.bound.vehicle.or.user";
-
- // ========== 车辆运营相关 ==========
- String VEHICLE_OPERATION_INFO_INCOMPLETE = "vehicle.operation.info.incomplete";
- String VEHICLE_BATCH_OPERATION_CONDITION_NOT_MET = "vehicle.batch.operation.condition.not.met";
- String VEHICLE_TIME_EXPIRED = "vehicle.time.expired";
-
- // ========== 车队相关 ==========
- String FLEET_OPERATION_USER_BOUND_V1 = "fleet.operation.user.bound.v1";
- String FLEET_OPERATION_USER_BOUND_2 = "fleet.operation.user.bound.v2";
- String FLEET_VEHICLE_BOUND_V1 = "fleet.vehicle.bound.v1";
- String FLEET_VEHICLE_BOUND_V2 = "fleet.vehicle.bound.v2";
-
- // ========== 车辆开关车门 ==========
- String VEHICLE_NOT_P_GEAR = "vehicle.not.p.gear";
- String VEHICLE_DISTANCE_TOO_LONG = "vehicle.distance.too.long";
-
-
- // ========== 车辆温度控制 ==========
- String VEHICLE_TEMPERATURE_UP = "vehicle.temperature.up";
-
- String VEHICLE_TEMPERATURE_DOWN = "vehicle.temperature.down";
-
- // ========== 车辆新增/编辑校验 ==========
- String VEHICLE_CODE_INVALID = "vehicle.code.invalid";
- String VEHICLE_CODE_EXISTS = "vehicle.code.exists";
- String VEHICLE_VIN_INVALID = "vehicle.vin.invalid";
- String VEHICLE_VIN_EXISTS = "vehicle.vin.exists";
- String VEHICLE_PLATE_INVALID = "vehicle.plate.invalid";
- String VEHICLE_PLATE_EXISTS = "vehicle.plate.exists";
- String VEHICLE_COLOR_INVALID = "vehicle.color.invalid";
- String VEHICLE_ELECTRONIC_NOT_EXISTS = "vehicle.electronic.not.exists";
-
- // ========== 车辆导入校验 ==========
- String VEHICLE_IMPORT_VALIDATE_FAIL = "vehicle.import.validate.fail";
- String VEHICLE_IMPORT_CODE_INVALID = "vehicle.import.code.invalid";
- String VEHICLE_IMPORT_VIN_INVALID = "vehicle.import.vin.invalid";
- String VEHICLE_IMPORT_PLATE_INVALID = "vehicle.import.plate.invalid";
- String VEHICLE_IMPORT_COLOR_INVALID = "vehicle.import.color.invalid";
- String VEHICLE_IMPORT_CODE_DUPLICATE = "vehicle.import.code.duplicate";
- String VEHICLE_IMPORT_VIN_DUPLICATE = "vehicle.import.vin.duplicate";
- String VEHICLE_IMPORT_PLATE_DUPLICATE = "vehicle.import.plate.duplicate";
- String VEHICLE_IMPORT_CODE_EXISTS = "vehicle.import.code.exists";
- String VEHICLE_IMPORT_VIN_EXISTS = "vehicle.import.vin.exists";
- String VEHICLE_IMPORT_PLATE_EXISTS = "vehicle.import.plate.exists";
-
- // ========== 车辆删除相关 ==========
- String VEHICLE_DELETE_HAS_BOUND_FLEET = "vehicle.delete.has.bound.fleet";
-
-}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/controller/HttpTestController.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/controller/HttpTestController.java
new file mode 100644
index 0000000..4693eac
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/controller/HttpTestController.java
@@ -0,0 +1,36 @@
+package com.xiaopeng.trafficControl.controller;
+
+
+import com.xiaopeng.common.core.domain.R;
+import com.xiaopeng.trafficControl.utils.MinistryOfTransport;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+@RestController
+@RequestMapping("/")
+public class HttpTestController {
+
+ @Resource
+ private MinistryOfTransport ministryOfTransport;
+
+
+ /**
+ * 测试上传数据接口
+ * 用于验证上传数据的准确性
+ * 模拟交通部接口
+ */
+ @ResponseBody
+ @RequestMapping("/base/v0.1/testPush")
+ public R<String> testPush(){
+ try {
+ String token = ministryOfTransport.getToken();
+ return R.ok(token);
+ }catch (Exception e){
+ e.printStackTrace();
+ return R.fail(e.getMessage());
+ }
+ }
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/enums/SignatureType.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/enums/SignatureType.java
deleted file mode 100644
index d1871c4..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/enums/SignatureType.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.xiaopeng.trafficControl.enums;
-
-/** 签名类型枚举 */
-public enum SignatureType {
- MD5("MD5"), SHA1("SHA1"), SHA256("SHA256");
- private String value;
-
- private SignatureType(String value) {
- this.value = value;
- }
-
- public String getValue() {
- return value;
- }
-}
\ No newline at end of file
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HMACSHA1.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HMACSHA1.java
deleted file mode 100644
index b2d23d9..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HMACSHA1.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.xiaopeng.trafficControl.util;
-
-
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-
-public class HMACSHA1 {
-
- private static final String MAC_NAME = "HmacSHA1";
- private static final String ENCODING = "UTF-8";
-
- /**
- * 使用 HMAC-SHA1 签名方法对对encryptText进行签名
- *
- * @param encryptText 被签名的字符串
- * @param encryptKey 密钥
- * @return
- * @throws Exception
- */
- public static byte[] HmacSHA1Encrypt(String encryptText, String encryptKey) throws Exception {
- byte[] data = encryptKey.getBytes(ENCODING);
- // 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
- Mac mac = Mac.getInstance(MAC_NAME);
- SecretKey secretKey = new SecretKeySpec(data, MAC_NAME);
- // 生成一个指定 Mac 算法 的 Mac 对象
- // 用给定密钥初始化 Mac 对象
- mac.init(secretKey);
-
- byte[] text = encryptText.getBytes(ENCODING);
- // 完成 Mac 操作
- return mac.doFinal(text);
- }
-
-}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HexUtil.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HexUtil.java
deleted file mode 100644
index b845c1d..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HexUtil.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.xiaopeng.trafficControl.util;
-
-import com.xiaopeng.trafficControl.DecodingException;
-import org.apache.commons.codec.DecoderException;
-import org.apache.commons.codec.binary.Hex;
-
-
-/**
- * 与字节16进制相关的工具类<br/>
- */
-public class HexUtil {
- /** 将十六进制字符串转成字节数组 */
- public static byte[] toHexBytes(String hexText) {
- try {
- return Hex.decodeHex(hexText.toCharArray());
- } catch (DecoderException e) {
- throw new DecodingException(e);
- }
- }
-
- /** 将字节数组转成十六进制字符串(字母小写) */
- public static String toLowerCase(byte[] hex) {
- return new String(Hex.encodeHex(hex, true));
- }
-
- /** 将字节数组转成十六进制字符串(字母大写) */
- public static String toUpperCase(byte[] hex) {
- return new String(Hex.encodeHex(hex, false));
- }
-
- /** 将字节数组转成整数 */
- public static int hashToInt(byte[] hash) {
- return (int) (hash[3] << 24 | hash[2] << 16 | hash[1] << 8 | hash[0]);
- }
-
-}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ResourceUtil.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ResourceUtil.java
deleted file mode 100644
index 162dda6..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ResourceUtil.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.xiaopeng.trafficControl.util;
-
-import java.io.*;
-import java.lang.reflect.Method;
-import java.net.URL;
-
-/**
- * 资源工具类
- * @author binghuoliu
- *
- */
-public class ResourceUtil {
-
- /**
- * 读取classpath下的文件<br>
- * 读取classpath下的文件 一般用于读取classpath下的配置文件,注意读取的配置文件路径是相对传入参数clazz的load入路径. 例:<br>
- * ClassTest c1;//假设c1是从/usr/local/classpath/ 载入<br>
- * ClassTest c2;//假设c2是从/home/classpath/ 载入<br>
- * ............<br>
- * loadConfigFile("a.xml",c1.class);//从/usr/local/classpath1/下寻找a.xml<br>
- * loadConfigFile("a.xml",c2.class);//从/home/classpath/下寻找a.xml<br>
- * @param resource 资源路径
- * @param clazz
- * @return InputStream 文件的inputstram,如果找不到则返回null
- */
- @SuppressWarnings("unchecked")
- public static InputStream loadConfigFile(String resource, Class clazz) {
- ClassLoader classLoader = null;
- try {
- Method method = Thread.class.getMethod("getContextClassLoader");
- classLoader = (ClassLoader) method.invoke(Thread.currentThread());
- } catch (Exception e) {
- throw new RuntimeException("loadConfigFile error: ", e);
- }
- if (classLoader == null) {
- classLoader = clazz.getClassLoader();
- }
- try {
- if (classLoader != null) {
- URL url = classLoader.getResource(resource);
- if (url == null) {
- System.out.println("Can not find resource:" + resource);
- return null;
- }
- if (url.toString().startsWith("jar:file:")) {
- System.out.println("Get resource \"" + resource + "\" from jar:\t" + url.toString());
- return clazz.getResourceAsStream(resource.startsWith("/") ? resource : "/" + resource);
- } else {
- System.out.println("Get resource \"" + resource + "\" from:\t" + url.toString());
- return new FileInputStream(new File(url.toURI()));
- }
- }
- } catch (Exception e) {
- throw new RuntimeException("loadConfigFile error: ", e);
- }
- return null;
- }
-
- /**
- * 释放资源(有异常抛出)
- * @param closeable
- * @throws IOException
- */
- public static void close(Closeable closeable) throws IOException {
- if (closeable != null) {
- closeable.close();
- }
- }
-
- /**
- * 以优雅的形式释放资源(内部吃掉了异常)
- * @param closeable
- */
- public static void closeGracefully(Closeable closeable) {
- if (closeable != null) {
- try {
- closeable.close();
- } catch (IOException e) {
- }
- }
- }
-}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SHA1Util.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SHA1Util.java
deleted file mode 100644
index d123471..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SHA1Util.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package com.xiaopeng.trafficControl.util;
-
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel;
-
-/**
- * 该API支持线程安全<br/>
- */
-public class SHA1Util {
- // --------------------------计算SHA1大写字符串----------------------------------------------
- /**
- * 计算出文件的SHA1大写字符串
- *
- * @param file
- * @return
- * @throws IOException
- */
- public static String getSHA1UpperString(File file) throws IOException {
- return HexUtil.toUpperCase(getSHA1Bytes(file));
- }
-
- /**
- * 计算出SHA1后十六进制结果(大写)
- *
- * @param s
- * @return
- */
- public static String getSHA1UpperString(String s) {
- try {
- return getSHA1UpperString(s.getBytes("UTF-8"));
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * 计算出SHA1后十六进制结果(大写)
- *
- * @param bytes
- * @return
- */
- public static String getSHA1UpperString(byte[] bytes) {
- return HexUtil.toUpperCase(getSHA1Bytes(bytes));
- }
-
- // --------------------------计算SHA1小写字符串----------------------------------------------
- /**
- * 计算出文件的SHA1小写字符串
- *
- * @param file
- * @return
- * @throws IOException
- */
- public static String getSHA1LowerString(File file) throws IOException {
- return HexUtil.toLowerCase(getSHA1Bytes(file));
- }
-
- /**
- * 计算出SHA1后十六进制结果(小写)
- *
- * @param s
- * @return
- */
- public static String getSHA1LowerString(String s) {
- try {
- return getSHA1LowerString(s.getBytes("UTF-8"));
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * 计算出SHA1后十六进制结果(小写)
- *
- * @param bytes
- * @return
- */
- public static String getSHA1LowerString(byte[] bytes) {
- return HexUtil.toLowerCase(getSHA1Bytes(bytes));
- }
-
- // ------------------------计算出SHA1的byte[]------------------------------------------------
- public static byte[] getSHA1Bytes(byte[] bytes) {
- ThreadLocalSHA1.current().update(bytes);
- return ThreadLocalSHA1.current().digest();
- }
-
- public static byte[] getSHA1Bytes(File file) throws IOException {
- FileInputStream in = null;
- FileChannel ch = null;
- try {
- in = new FileInputStream(file);
- ch = in.getChannel();
-
- MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
-
- ThreadLocalSHA1.current().update(byteBuffer);
- return ThreadLocalSHA1.current().digest();
- } finally {
- ResourceUtil.closeGracefully(ch);
- ResourceUtil.closeGracefully(in);
- }
- }
-
- // ------------------------------------------------------------------------
- public static boolean checkPassword(String originContent, String sha1Content) {
- String s = getSHA1LowerString(originContent);
- return s.equals(sha1Content);
- }
-
- // ------------------------------------------------------------------------
-
-}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SignatureUtils.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SignatureUtils.java
deleted file mode 100644
index 950e47c..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SignatureUtils.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package com.xiaopeng.trafficControl.util;
-
-import com.xiaopeng.unifiedverification.util.md5.MD5Util;
-import com.xiaopeng.unifiedverification.util.sha256.SHA256Util;
-import com.xiaopeng.trafficControl.enums.SignatureType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.TreeMap;
-
-public class SignatureUtils {
- private static final Logger LOGGER = LoggerFactory.getLogger(SignatureUtils.class);
-
- /**
- * 通用签名方法,签名算法为SHA1<br/>
- * 签名原文拼装规则:<br/>
- * ①paraMap按key的自然排序,并按key1+value1+key2+value2的规则拼接,中间无分隔符<br/>
- * ②在第①步骤组装的String前面追加appid的值<br/>
- * ③在第①步骤组装的String后面追加appSecret的值<br/>
- *
- * @param appId 业务系统唯一标识
- * @param paraMap 所需要传递的参数map
- * @param appSecret 分配给业务系统的秘钥
- * @return
- */
- public static String getSignatureSHA1(String appId, Map<String, String> paraMap, String appSecret) {
- return getSignature(appId, paraMap, appSecret, SignatureType.SHA1);
- }
-
- /**
- * 通用签名方法<br/>
- * 签名原文拼装规则:<br/>
- * ①paraMap按key的自然排序,并按key1+value1+key2+value2的规则拼接,中间无分隔符<br/>
- * ②在第①步骤组装的String前面追加appid的值<br/>
- * ③在第①步骤组装的String后面追加appSecret的值<br/>
- *
- * @param appId 业务系统唯一标识
- * @param paraMap 所需要传递的参数map
- * @param appSecret 分配给业务系统的秘钥
- * @param signatureType 签名算法类型(参考SignatureType)
- * @return
- */
- public static String getSignature(String appId, Map<String, String> paraMap, String appSecret,
- SignatureType signatureType) {
- String originStr = buildAllSignatureOriginStr(appId, paraMap, appSecret);
- LOGGER.info("originStr: {}", originStr);
- return getSignature(originStr, signatureType);
- }
-
- // ------------------------------------------------------------------------------------------
-
- /**
- * 构造计算签名的完整消息内容<br/>
- */
- public static String buildAllSignatureOriginStr(String appId, Map<String, String> paraMap, String appSecret) {
- StringBuilder sb = new StringBuilder(128);
- String result = sb.append(appId).append(buildMiddleSignatureOriginStr(paraMap)).append(appSecret).toString(); // 用于签名的原文
-
- return result;
- }
-
- /**
- * 构造计算签名的中间消息内容<br/>
- */
- public static String buildMiddleSignatureOriginStr(Map<String, String> map) {
- if (map.isEmpty()) {
- return "";
- }
-
- Map<String, String> treeMap = new TreeMap<String, String>(new Comparator<String>() {
- public int compare(String obj1, String obj2) {
- // 升序排序
- return obj1.compareTo(obj2);
- }
- });
-
- treeMap.putAll(map);
-
- Iterator<Map.Entry<String, String>> iter = treeMap.entrySet().iterator();
- StringBuilder stringBuilder = new StringBuilder(128);
-
- while (iter.hasNext()) {
- Map.Entry<String, String> entry = iter.next();
-
- stringBuilder.append(entry.getKey()).append(entry.getValue());
- }
-
- return stringBuilder.toString();
- }
-
- /**
- * 计算签名
- *
- * @param originStr
- * 用于签名的原始内容
- * @param signatureType
- * 签名算法类型(参考SignatureType)
- * @return 签名值
- */
- public static String getSignature(String originStr, SignatureType signatureType) {
- if (SignatureType.MD5 == signatureType) {
- return MD5Util.getMD5LowerString(originStr);
- } else if (SignatureType.SHA1 == signatureType) {
- return SHA1Util.getSHA1LowerString(originStr);
- } else if (SignatureType.SHA256 == signatureType) {
- return SHA256Util.getSHA256LowerString(originStr);
- } else { // 默认用SHA1
- return SHA1Util.getSHA1LowerString(originStr);
- }
- }
-}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ThreadLocalSHA1.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ThreadLocalSHA1.java
deleted file mode 100644
index 9907197..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ThreadLocalSHA1.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.xiaopeng.trafficControl.util;
-
-import java.security.MessageDigest;
-
-/**
- * SHA1算法计算散列值的ThreadLocal,避免多线程场景下的线程安全问题<br/>
- */
-public class ThreadLocalSHA1 {
- private static final ThreadLocal<MessageDigest> localFormat = new ThreadLocal<MessageDigest>() {
- protected MessageDigest initialValue() {
- try {
- return MessageDigest.getInstance("SHA1");
- } catch (Exception e) {
- System.err.println(SHA1Util.class.getName() + "初始化失败,MessageDigest不支持SHA1Util。");
- e.printStackTrace();
-
- return null;
- }
- };
- };
-
- /** 获取当前线程对应的实例 */
- public static MessageDigest current() {
- return localFormat.get();
- }
-}
\ No newline at end of file
diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/utils/MinistryOfTransport.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/utils/MinistryOfTransport.java
new file mode 100644
index 0000000..1aab373
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/utils/MinistryOfTransport.java
@@ -0,0 +1,106 @@
+package com.xiaopeng.trafficControl.utils;
+
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.crypto.digest.MD5;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.http.HttpUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+
+/**
+ * 交通部接口对接
+ */
+@Slf4j
+@Component
+public class MinistryOfTransport {
+
+ /**
+ * 公司名称:广州易点智慧出行科技有限公司
+ *
+ * 平台简称:“有鹏出行”
+ * 标识:XPQCB67N
+ * key:gEhROt7lg4DEBanR
+ *
+ * 对接ip:127.0.0.1,125.71.236.64,47.98.173.145,116.62.136.48,39.108.249.22,47.105.208.135,47.112.126.81,114.55.179.11,39.170.77.50,120.26.242.215
+ *
+ * 接口地址:https://wycapi.jtj.gz.gov.cn/api/app/common/binapi
+ */
+
+ private final String companyId = "4401XPQCB67N";//公司标识
+
+ private final String platform = "XPQC";
+
+ private final String key = "gEhROt7lg4DEBanR";
+
+ private final String url = "https://wycapi.jtj.gz.gov.cn/api/app/common/binapi";
+
+ @Value("${xp.file.path}")
+ private String filePath;
+
+
+ /**
+ * 获取token
+ * @return
+ */
+ public String getToken(){
+ //通过上传文件的方式获取token
+ String format = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
+ String fileName = platform + "_TOKEN_ACCESS_REQ_" + format + ".json";
+ File file = FileUtil.file(filePath + fileName);
+ if(!file.exists()){
+ file.getParentFile().mkdirs();
+ try {
+ file.createNewFile();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ file.setReadable(true, false);//设置读取权限
+ file.setWritable(true, false);//设置写入权限
+ }
+ JSONObject body = new JSONObject();
+ JSONArray items = new JSONArray();
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("platform", platform);
+ jsonObject.put("key", key);
+ items.add(jsonObject);
+ body.put("items", items);
+ log.info("获取token请求参数 {}", body.toJSONString());
+ file = FileUtil.writeUtf8String(body.toJSONString(), file);
+ String md5 = MD5.create().digestHex(file);
+ HttpRequest post = HttpUtil.createPost(url);
+ post.contentType("multipart/form-data;boundary=inputstream");
+ post.header("binfile-md5", md5);
+ post.header("binfile-gzip", "false");
+ post.header("binfile-auth", "5cd4be8cf03842a6b4c3246011e3482e");
+ post.form("binFile", file);
+ post.form("filename", fileName);
+ HttpResponse execute = post.execute();
+ if(!execute.isOk()){
+ log.info("获取token失败:{}", execute.body());
+ return execute.body();
+ }
+ InputStream inputStream = execute.bodyStream();
+ //读取inputStream流转成file文件
+ File resultFile = FileUtil.file(filePath + "token_response_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")) + ".json");
+ resultFile.getParentFile().mkdirs();
+ FileUtil.writeFromStream(inputStream, resultFile);
+ String responseContent = FileUtil.readUtf8String(resultFile);
+ log.info("获取token成功 {}", responseContent);
+ return responseContent;
+ }
+
+
+
+}
diff --git a/xp-robotaxi-traffic-control-boot/src/main/resources/application-local.yml b/xp-robotaxi-traffic-control-boot/src/main/resources/application-local.yml
new file mode 100644
index 0000000..4f40872
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/resources/application-local.yml
@@ -0,0 +1,114 @@
+spring:
+ config:
+ activate:
+ on-profile: local
+ autoconfigure:
+ exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
+ redis:
+ database: 99
+ host: r-bp1ip8die60uuo3ovypd.redis.rds.aliyuncs.com
+ password: syAktm2x9uDusoF_
+ port: 6379
+ data:
+ mongodb:
+ host: dds-bp1f4a38f3cccad4-pub.mongodb.rds.aliyuncs.com
+ port: 3717
+ database: xp_robotaxi
+ username: xp_robotaxi
+ password: hDXSBe_hs0d5KxUf
+ shardingsphere:
+ props:
+ sql.show: true
+ show-sql: true
+ datasource:
+ names: xp0
+ xp0:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://pc-bp1o444934f546768po.rwlb.rds.aliyuncs.com:3306/xp_rt_operation?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: xp_rt_operation
+ password: g0Tw2f_KoNlmW21M
+ druid:
+ initial-size: 10
+ min-idle: 10
+ max-active: 100
+ max-wait: 60000
+ time-between-eviction-runs-millis: 60000
+ min-evictable-idle-time-millis: 300000
+ validation-query: SELECT 1
+ test-while-idle: true
+ test-on-borrow: false
+ test-on-return: false
+ pool-prepared-statements: true
+ max-pool-prepared-statement-per-connection-size: 20
+ filters: stat,wall,log4j
+ connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
+ remove-abandoned: true
+ remove-abandoned-timeout: 1800
+ log-abandoned: true
+ stat-view-servlet:
+ enabled: true
+ url-pattern: /druid/*
+ login-username: admin
+ login-password: admin
+ reset-enable: false
+ wall:
+ config:
+ multi-statement-allow: false
+ rules:
+ sharding:
+ tables:
+ sys_oper_log:
+ actual-data-nodes: xp0.sys_oper_log_${0..9}
+ table-strategy:
+ standard:
+ sharding-column: userId
+ sharding-algorithm-name: sys-oper-log-inline
+ key-generate-strategy:
+ column: oper_id
+ key-generator-name: snowflake
+ xp_agreement_app_user:
+ actual-data-nodes: xp0.xp_agreement_app_user_${0..9}
+ table-strategy:
+ standard:
+ sharding-column: app_user_id
+ sharding-algorithm-name: xp-agreement-app-user-inline
+ key-generate-strategy:
+ column: id
+ key-generator-name: snowflake
+ xp_point:
+ actual-data-nodes: xp0.xp_point_${0..9}
+ table-strategy:
+ standard:
+ sharding-column: electronic_area_id
+ sharding-algorithm-name: xp-point-inline
+ key-generate-strategy:
+ column: id
+ key-generator-name: snowflake
+ sharding-algorithms:
+ sys-oper-log-inline:
+ type: INLINE
+ props:
+ algorithm-expression: sys_oper_log_${userId % 10}
+ xp-agreement-app-user-inline:
+ type: INLINE
+ props:
+ algorithm-expression: xp_agreement_app_user_${app_user_id % 10}
+ xp-point-inline:
+ type: INLINE
+ props:
+ algorithm-expression: xp_point_${electronic_area_id % 10}
+ key-generators:
+ snowflake:
+ type: SNOWFLAKE
+
+
+# swagger配置
+swagger:
+ title: 合规监管接口文档
+ enabled: true
+ license: Powered By xiaopeng
+ licenseUrl: http://127.0.0.1:5800/doc.html
+
+seata:
+ enabled: false
diff --git a/xp-robotaxi-traffic-control-boot/src/main/resources/bootstrap.yml b/xp-robotaxi-traffic-control-boot/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..737fc18
--- /dev/null
+++ b/xp-robotaxi-traffic-control-boot/src/main/resources/bootstrap.yml
@@ -0,0 +1,160 @@
+server:
+ port: 6110
+ tomcat:
+ basedir: /data/tomcat
+# Spring
+spring:
+ application:
+ # 应用名称
+ name: xp-robotaxi-traffic-control-boot
+ main:
+ allow-bean-definition-overriding: true
+ allow-circular-references: true
+ profiles:
+ # 环境配置
+ active: dev
+# active: prod
+---
+spring:
+ config:
+ activate:
+ on-profile: dev
+ cloud:
+ nacos:
+ discovery:
+ # 服务注册地址
+ server-addr: 192.168.110.80:8848
+ service: ${spring.application.name}
+ group: DEFAULT_GROUP
+ namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
+ username: nacos
+ password: nacos
+ config:
+ # 配置中心地址
+ server-addr: 192.168.110.80:8848
+ namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
+ group: DEFAULT_GROUP
+ name: ${spring.application.name}
+ username: nacos
+ password: nacos
+ # 配置文件格式
+ file-extension: yml
+ # 共享配置
+ shared-configs:
+ - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
+---
+seata:
+ enabled: true
+ application-id: ${spring.application.name}
+ tx-service-group: seata_tx_group #此处配置自定义的seata事务分组名称
+ enable-auto-data-source-proxy: false #关闭数据库代理
+ service:
+ vgroup-mapping:
+ seata_tx_group: default
+ data-source-proxy-mode: AT
+ config:
+ type: nacos
+ nacos:
+ # 开发环境
+ server-addr: 192.168.110.80:8848
+ namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
+ group: DEFAULT_GROUP
+ data-id: seata-server.properties
+ username: nacos
+ password: nacos
+ # 生产环境
+ # server-addr: 192.168.0.137:8848,192.168.0.123:8848
+ # namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
+ # group: DEFAULT_GROUP
+ # data-id: seata-server.properties
+ # username: nacos
+ # password: nacos
+ registry:
+ type: nacos
+ nacos:
+ application: seata-server
+ # 开发环境
+ server-addr: 192.168.110.80:8848
+ namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
+ group: DEFAULT_GROUP
+ username: nacos
+ password: nacos
+ # 生产环境
+ # server-addr: 192.168.0.137:8848,192.168.0.123:8848
+ # namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
+ # group: DEFAULT_GROUP
+ # username: nacos
+ # password: nacos
+ cloud:
+ nacos:
+ discovery:
+ # 开发环境
+ server-addr: 192.168.110.80:8848
+ namespace: 5185ac4b-6369-48eb-a21b-a7cbc441c5f1
+ group: DEFAULT_GROUP
+ application: seata-server #Nacos 中 Seata 名称
+ username: nacos
+ password: nacos
+ # 生产环境
+ # server-addr: 192.168.0.137:8848,192.168.0.123:8848
+ # namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
+ # group: DEFAULT_GROUP
+ # application: seata-server #Nacos 中 Seata 名称
+ # username: nacos
+ # password: nacos
+ sentinel:
+ transport:
+ dashboard: 192.168.0.137:8080 # Sentinel控制台地址
+ eager: true
+---
+spring:
+ config:
+ activate:
+ on-profile: prod
+ cloud:
+ nacos:
+ discovery:
+ # 服务注册地址
+ server-addr: 192.168.0.137:8848,192.168.0.123:8848
+ service: ${spring.application.name}
+ group: DEFAULT_GROUP
+ namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
+ username: nacos
+ password: nacos
+ config:
+ # 配置中心地址
+ server-addr: 192.168.0.137:8848,192.168.0.123:8848
+ namespace: c6cf40b5-44e8-43f9-be61-8d10fa830e2a
+ username: nacos
+ password: nacos
+ group: DEFAULT_GROUP
+ name: ${spring.application.name}
+ # 配置文件格式
+ file-extension: yml
+ # 共享配置
+ shared-configs:
+ - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
+---
+spring:
+ config:
+ activate:
+ on-profile: test
+ cloud:
+ nacos:
+ discovery:
+ # 服务注册地址
+ server-addr: 127.0.0.1:8848
+ service: ${spring.application.name}
+ group: DEFAULT_GROUP
+ namespace: 96712c7a-480b-4f40-b783-39f00f3b33ce
+ config:
+ # 配置中心地址
+ server-addr: 127.0.0.1:8848
+ namespace: 96712c7a-480b-4f40-b783-39f00f3b33ce
+ group: DEFAULT_GROUP
+ name: ${spring.application.name}
+ # 配置文件格式
+ file-extension: yml
+ # 共享配置
+ shared-configs:
+ - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
\ No newline at end of file
diff --git a/xp-robotaxi-traffic-control-boot/src/main/resources/logback.xml.bak b/xp-robotaxi-traffic-control-boot/src/main/resources/logback.xml.bak
deleted file mode 100644
index 14a129a..0000000
--- a/xp-robotaxi-traffic-control-boot/src/main/resources/logback.xml.bak
+++ /dev/null
@@ -1,222 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,比如: 如果设置为WARN,则低于WARN的信息都不会输出 -->
-<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
-<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
-<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
-<configuration scan="true" scanPeriod="10 seconds">
- <contextName>logback</contextName>
-
- <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使"${}"来使用变量。 -->
- <property name="log.path" value="/data/log/app/ruoyi-account"/>
-
- <!--0. 日志格式和颜色渲染 -->
- <!-- 彩色日志依赖的渲染类 -->
- <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
- <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
- <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
- <!-- 彩色日志格式 -->
- <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
-
- <!--1. 输出到控制台-->
- <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
- <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
- <level>debug</level>
- </filter>
- <encoder>
- <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
- <!-- 设置字符集 -->
- <charset>UTF-8</charset>
- </encoder>
- </appender>
-
- <!--2. 输出到文档-->
- <!-- 2.1 level为 DEBUG 日志,时间滚动输出 -->
- <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <!-- 正在记录的日志文档的路径及文档名 -->
- <file>${log.path}/debug.log</file>
- <!--日志文档输出格式-->
- <encoder>
- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
- <charset>UTF-8</charset> <!-- 设置字符集 -->
- </encoder>
- <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <!-- 日志归档 -->
- <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
- <maxFileSize>100MB</maxFileSize>
- </timeBasedFileNamingAndTriggeringPolicy>
- <!--日志文档保留天数-->
- <maxHistory>15</maxHistory>
- </rollingPolicy>
- <!-- 此日志文档只记录debug级别的 -->
- <filter class="ch.qos.logback.classic.filter.LevelFilter">
- <level>debug</level>
- <onMatch>ACCEPT</onMatch>
- <onMismatch>DENY</onMismatch>
- </filter>
- </appender>
-
- <!-- 2.2 level为 INFO 日志,时间滚动输出 -->
- <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <!-- 正在记录的日志文档的路径及文档名 -->
- <file>${log.path}/info.log</file>
- <!--日志文档输出格式-->
- <encoder>
- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
- <charset>UTF-8</charset>
- </encoder>
- <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <!-- 每天日志归档路径以及格式 -->
- <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
- <maxFileSize>100MB</maxFileSize>
- </timeBasedFileNamingAndTriggeringPolicy>
- <!--日志文档保留天数-->
- <maxHistory>15</maxHistory>
- </rollingPolicy>
- <!-- 此日志文档只记录info级别的 -->
- <filter class="ch.qos.logback.classic.filter.LevelFilter">
- <level>info</level>
- <onMatch>ACCEPT</onMatch>
- <onMismatch>DENY</onMismatch>
- </filter>
- </appender>
-
- <!-- 2.3 level为 WARN 日志,时间滚动输出 -->
- <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <!-- 正在记录的日志文档的路径及文档名 -->
- <file>${log.path}/warn.log</file>
- <!--日志文档输出格式-->
- <encoder>
- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
- <charset>UTF-8</charset> <!-- 此处设置字符集 -->
- </encoder>
- <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
- <maxFileSize>100MB</maxFileSize>
- </timeBasedFileNamingAndTriggeringPolicy>
- <!--日志文档保留天数-->
- <maxHistory>15</maxHistory>
- </rollingPolicy>
- <!-- 此日志文档只记录warn级别的 -->
- <filter class="ch.qos.logback.classic.filter.LevelFilter">
- <level>warn</level>
- <onMatch>ACCEPT</onMatch>
- <onMismatch>DENY</onMismatch>
- </filter>
- </appender>
-
- <!-- 2.4 level为 ERROR 日志,时间滚动输出 -->
- <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <!-- 正在记录的日志文档的路径及文档名 -->
- <file>${log.path}/error.log</file>
- <!--日志文档输出格式-->
- <encoder>
- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
- <charset>UTF-8</charset> <!-- 此处设置字符集 -->
- </encoder>
- <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
- <maxFileSize>100MB</maxFileSize>
- </timeBasedFileNamingAndTriggeringPolicy>
- <!--日志文档保留天数-->
- <maxHistory>15</maxHistory>
- </rollingPolicy>
- <!-- 此日志文档只记录ERROR级别的 -->
- <filter class="ch.qos.logback.classic.filter.LevelFilter">
- <level>ERROR</level>
- <onMatch>ACCEPT</onMatch>
- <onMismatch>DENY</onMismatch>
- </filter>
- </appender>
-
- <!-- 2.5 所有 除了DEBUG级别的其它高于DEBUG的 日志,记录到一个文件 -->
- <appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <!-- 正在记录的日志文档的路径及文档名 -->
- <file>${log.path}/all.log</file>
- <!--日志文档输出格式-->
- <encoder>
- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
- <charset>UTF-8</charset> <!-- 此处设置字符集 -->
- </encoder>
- <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
- <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/all-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
- <maxFileSize>100MB</maxFileSize>
- </timeBasedFileNamingAndTriggeringPolicy>
- <!--日志文档保留天数-->
- <maxHistory>15</maxHistory>
- </rollingPolicy>
- <!-- 此日志文档记录除了DEBUG级别的其它高于DEBUG的 -->
- <filter class="ch.qos.logback.classic.filter.LevelFilter">
- <level>DEBUG</level>
- <onMatch>DENY</onMatch>
- <onMismatch>ACCEPT</onMismatch>
- </filter>
- </appender>
-
- <!--
- <logger>用来设置某一个包或者具体的某一个类的日志打印级别、
- 以及指定<appender>。<logger>仅有一个name属性,
- 一个可选的level和一个可选的addtivity属性。
- name:用来指定受此logger约束的某一个包或者具体的某一个类。
- level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
- 还有一个特殊值INHERITED或者同义词NULL,代表强制执行上级的级别。
- 如果未设置此属性,那么当前logger将会继承上级的级别。
- addtivity:是否向上级logger传递打印信息。默认是true。
- <logger name="org.springframework.web" level="info"/>
- <logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
- -->
-
- <!--
- root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
- level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
- 不能设置为INHERITED或者同义词NULL。默认是DEBUG
- 可以包含零个或多个元素,标识这个appender将会添加到这个logger。
- -->
-
- <!-- 4 最终的策略:
- 基本策略(root级) + 根据profile在启动时, logger标签中定制化package日志级别(优先级高于上面的root级)-->
- <springProfile name="dev">
- <root level="info">
- <appender-ref ref="CONSOLE" />
- <appender-ref ref="DEBUG_FILE" />
- <appender-ref ref="INFO_FILE" />
- <appender-ref ref="WARN_FILE" />
- <appender-ref ref="ERROR_FILE" />
- <appender-ref ref="ALL_FILE" />
- </root>
- <logger name="com.stylefeng.guns.modular.system.dao" level="debug"/>
- </springProfile>
-
- <springProfile name="test">
- <root level="info">
- <appender-ref ref="CONSOLE" />
- <appender-ref ref="DEBUG_FILE" />
- <appender-ref ref="INFO_FILE" />
- <appender-ref ref="WARN_FILE" />
- <appender-ref ref="ERROR_FILE" />
- <appender-ref ref="ALL_FILE" />
- </root>
- </springProfile>
-
- <springProfile name="prod">
- <root level="info">
- <!-- 生产环境最好不配置console写文件 -->
- <appender-ref ref="DEBUG_FILE" />
- <appender-ref ref="INFO_FILE" />
- <appender-ref ref="WARN_FILE" />
- <appender-ref ref="ERROR_FILE" />
- <appender-ref ref="ALL_FILE" />
- </root>
- </springProfile>
-
-</configuration>
diff --git a/xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java b/xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
index 44fc656..5dbc8f0 100644
--- a/xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
+++ b/xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
@@ -770,7 +770,7 @@
@PostMapping("/inner/vehicle/queryVehiclePositionByVin")
public R<List<String>> queryVehiclePositionByVin(@RequestBody VehiclePositionByVinDto dto){
List<XpVehicle> list = xpVehicleService.list(new LambdaQueryWrapper<XpVehicle>().eq(XpVehicle::getState, 0)
- .eq(XpVehicle::getOperatingStatus, 1).eq(XpVehicle::getElectronicId, dto.getFenceId()).in(XpVehicle::getVehicleVin,
+ .eq(XpVehicle::getOperatingStatus, 1).eq(XpVehicle::getVehicleType,2).eq(XpVehicle::getElectronicId, dto.getFenceId()).in(XpVehicle::getVehicleVin,
dto.getVinList()));
if(list.isEmpty()){
return R.ok(new ArrayList<>());
--
Gitblit v1.7.1