.gitignore
@@ -15,7 +15,7 @@ target *.yaml *.yml #*.yaml #*.yml *.log.DS_Store **/.DS_Store xp-robotaxi-itinerary-boot/src/main/resources/application-local.yml
New file @@ -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 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()); } } 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> xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/DecodingException.java
File was deleted 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); xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/DataUpdateHandlerConfig.java
File was deleted 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(); // } } xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MultipartFilterConfig.java
File was deleted 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; } xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/MybatisPlusConfig.java
File was deleted xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/TransactionConfiguration.java
File was deleted 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() + "}"; // } // } //} 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); // } //} xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/constant/I18nKeyConstant.java
File was deleted xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/controller/HttpTestController.java
New file @@ -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()); } } } xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/enums/SignatureType.java
File was deleted xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HMACSHA1.java
File was deleted xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/HexUtil.java
File was deleted xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ResourceUtil.java
File was deleted xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SHA1Util.java
File was deleted xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/SignatureUtils.java
File was deleted xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/util/ThreadLocalSHA1.java
File was deleted xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/utils/MinistryOfTransport.java
New file @@ -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; } } xp-robotaxi-traffic-control-boot/src/main/resources/application-local.yml
New file @@ -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 xp-robotaxi-traffic-control-boot/src/main/resources/bootstrap.yml
New file @@ -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} xp-robotaxi-traffic-control-boot/src/main/resources/logback.xml.bak
File was deleted 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<>());