Commit 1d418ca8e80762bc68e90398807269ac171f0e43

Authored by 王彪总
1 parent 0675583f

fix(config): 更新配置文件和修复分页计算问题

- 在.gitignore中添加.mcp.json文件忽略
- 更新application-dev.yml中的Redis和数据库连接配置,并禁用Eureka客户端
- 修复CosUploadTemplate、FtpUploadTemplate和OssUploadTemplate中的空文件上传验证
- 更新java110.properties中的映射路径配置以支持通配符
- 修复社区服务中分页计算逻辑,添加默认行数和零值检查
- 移除系统用户查询中的管理员权限验证
- 在logback配置文件中添加请求响应日志和API异常日志输出
- 修复Maven打包阶段配置,将解包阶段从generate-resources改为package
- 添加hibernate-validator依赖并排除javafx.base冲突
- 扩展文件上传组件以支持multipart文件上传和IP地址获取功能
java110-core/src/main/java/com/java110/core/cache/Java110RedisConfig.java
@@ -138,7 +138,7 @@ public class Java110RedisConfig extends CachingConfigurerSupport { @@ -138,7 +138,7 @@ public class Java110RedisConfig extends CachingConfigurerSupport {
138 public RedisCacheConfiguration redisCacheConfiguration() { 138 public RedisCacheConfiguration redisCacheConfiguration() {
139 139
140 RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig(); 140 RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
141 - configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new JdkSerializationRedisSerializer())).entryTtl(Duration.ofSeconds(30)); 141 + configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new JdkSerializationRedisSerializer())).entryTtl(Duration.ofSeconds(300));
142 return configuration; 142 return configuration;
143 143
144 144
java110-core/src/main/java/com/java110/core/trace/Java110RestTemplateInterceptor.java
1 package com.java110.core.trace; 1 package com.java110.core.trace;
2 2
3 -import com.java110.core.log.LoggerFactory;  
4 import com.java110.dto.trace.TraceAnnotationsDto; 3 import com.java110.dto.trace.TraceAnnotationsDto;
5 import com.java110.dto.trace.TraceDto; 4 import com.java110.dto.trace.TraceDto;
6 import com.java110.utils.constant.CommonConstant; 5 import com.java110.utils.constant.CommonConstant;
7 -import org.slf4j.Logger;  
8 import org.springframework.http.HttpHeaders; 6 import org.springframework.http.HttpHeaders;
9 import org.springframework.http.HttpRequest; 7 import org.springframework.http.HttpRequest;
10 import org.springframework.http.client.ClientHttpRequestExecution; 8 import org.springframework.http.client.ClientHttpRequestExecution;
@@ -19,11 +17,9 @@ import java.io.IOException; @@ -19,11 +17,9 @@ import java.io.IOException;
19 */ 17 */
20 @Component 18 @Component
21 public class Java110RestTemplateInterceptor implements ClientHttpRequestInterceptor { 19 public class Java110RestTemplateInterceptor implements ClientHttpRequestInterceptor {
22 - private static Logger logger = LoggerFactory.getLogger(Java110RestTemplateInterceptor.class);  
23 20
24 @Override 21 @Override
25 public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { 22 public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
26 - logger.debug("进入拦截器" + new String(body));  
27 TraceDto traceDto = Java110TraceFactory.getTraceDto(); 23 TraceDto traceDto = Java110TraceFactory.getTraceDto();
28 if (traceDto != null) { 24 if (traceDto != null) {
29 HttpHeaders httpHeaders = request.getHeaders(); 25 HttpHeaders httpHeaders = request.getHeaders();
@@ -31,10 +27,12 @@ public class Java110RestTemplateInterceptor implements ClientHttpRequestIntercep @@ -31,10 +27,12 @@ public class Java110RestTemplateInterceptor implements ClientHttpRequestIntercep
31 httpHeaders.remove(CommonConstant.PARENT_SPAN_ID); 27 httpHeaders.remove(CommonConstant.PARENT_SPAN_ID);
32 httpHeaders.add(CommonConstant.TRACE_ID, traceDto.getTraceId()); 28 httpHeaders.add(CommonConstant.TRACE_ID, traceDto.getTraceId());
33 httpHeaders.add(CommonConstant.PARENT_SPAN_ID, traceDto.getId()); 29 httpHeaders.add(CommonConstant.PARENT_SPAN_ID, traceDto.getId());
  30 + Java110TraceFactory.putAnnotations(TraceAnnotationsDto.VALUE_SERVER_SEND);
  31 + ClientHttpResponse clientHttpResponse = execution.execute(request, body);
  32 + Java110TraceFactory.putAnnotations(TraceAnnotationsDto.VALUE_SERVER_RECEIVE);
  33 + return clientHttpResponse;
34 } 34 }
35 - Java110TraceFactory.putAnnotations(TraceAnnotationsDto.VALUE_SERVER_SEND);  
36 - ClientHttpResponse clientHttpResponse = execution.execute(request, body);  
37 - Java110TraceFactory.putAnnotations(TraceAnnotationsDto.VALUE_SERVER_RECEIVE);  
38 - return clientHttpResponse; 35 + //追踪未开启时直接放行,避免不必要的ThreadLocal操作和Annotation对象创建
  36 + return execution.execute(request, body);
39 } 37 }
40 } 38 }
java110-core/src/main/java/com/java110/core/trace/Java110TraceSqlInterceptor.java
@@ -34,6 +34,11 @@ public class Java110TraceSqlInterceptor implements Interceptor { @@ -34,6 +34,11 @@ public class Java110TraceSqlInterceptor implements Interceptor {
34 34
35 @Override 35 @Override
36 public Object intercept(Invocation invocation) throws Throwable { 36 public Object intercept(Invocation invocation) throws Throwable {
  37 + //追踪开关未打开时直接放行,避免不必要的SQL解析和参数提取开销
  38 + if (Java110TraceFactory.getTraceDto() == null) {
  39 + return invocation.proceed();
  40 + }
  41 +
37 MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; 42 MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
38 Object parameterObject = null; 43 Object parameterObject = null;
39 if (invocation.getArgs().length > 1) { 44 if (invocation.getArgs().length > 1) {
java110-db/src/main/java/com/java110/db/DruidDataSourceConfig.java
@@ -65,11 +65,20 @@ public class DruidDataSourceConfig { @@ -65,11 +65,20 @@ public class DruidDataSourceConfig {
65 //配置获取连接等待超时的时间 65 //配置获取连接等待超时的时间
66 dataSource.setMaxWait(maxWait); 66 dataSource.setMaxWait(maxWait);
67 67
68 - // 配置Druid的SQL监控和日志打印  
69 - dataSource.setLogAbandoned(true);  
70 - dataSource.setRemoveAbandoned(true);  
71 - dataSource.setRemoveAbandonedTimeout(180);  
72 - dataSource.setFilters("stat,log4j2"); // 配置Log4j2作为日志实现 68 + //连接验证 - 防止使用已断开的连接
  69 + dataSource.setValidationQuery("SELECT 1");
  70 + dataSource.setTestWhileIdle(true);
  71 + dataSource.setTestOnBorrow(true);
  72 + dataSource.setTestOnReturn(false);
  73 + dataSource.setTimeBetweenEvictionRunsMillis(60000);
  74 + dataSource.setMinEvictableIdleTimeMillis(300000);
  75 +
  76 + //PSCache - 缓存PreparedStatement避免重复解析SQL
  77 + dataSource.setPoolPreparedStatements(true);
  78 + dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
  79 +
  80 + // 配置Druid的SQL监控,移除log4j2减少日志开销
  81 + dataSource.setFilters("stat");
73 82
74 83
75 84
java110-db/src/main/java/com/java110/db/Java110MybatisInterceptor.java
@@ -24,6 +24,10 @@ import org.springframework.http.*; @@ -24,6 +24,10 @@ import org.springframework.http.*;
24 import java.sql.Timestamp; 24 import java.sql.Timestamp;
25 import java.text.DateFormat; 25 import java.text.DateFormat;
26 import java.util.*; 26 import java.util.*;
  27 +import java.util.concurrent.ExecutorService;
  28 +import java.util.concurrent.LinkedBlockingQueue;
  29 +import java.util.concurrent.ThreadPoolExecutor;
  30 +import java.util.concurrent.TimeUnit;
27 31
28 @Intercepts({ 32 @Intercepts({
29 @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, 33 @Signature(type = Executor.class, method = "update", args = {MappedStatement.class,
@@ -32,6 +36,17 @@ import java.util.*; @@ -32,6 +36,17 @@ import java.util.*;
32 public class Java110MybatisInterceptor implements Interceptor { 36 public class Java110MybatisInterceptor implements Interceptor {
33 private static Logger logger = LoggerFactory.getLogger(Java110MybatisInterceptor.class); 37 private static Logger logger = LoggerFactory.getLogger(Java110MybatisInterceptor.class);
34 38
  39 + private static final ExecutorService ASYNC_LOG_EXECUTOR = new ThreadPoolExecutor(
  40 + 2, 4, 60L, TimeUnit.SECONDS,
  41 + new LinkedBlockingQueue<>(1000),
  42 + r -> {
  43 + Thread t = new Thread(r, "async-tx-log");
  44 + t.setDaemon(true);
  45 + return t;
  46 + },
  47 + new ThreadPoolExecutor.CallerRunsPolicy()
  48 + );
  49 +
35 IQueryServiceDAO queryServiceDAOImpl; 50 IQueryServiceDAO queryServiceDAOImpl;
36 RestTemplate restTemplate; 51 RestTemplate restTemplate;
37 52
@@ -106,7 +121,7 @@ public class Java110MybatisInterceptor implements Interceptor { @@ -106,7 +121,7 @@ public class Java110MybatisInterceptor implements Interceptor {
106 logText.put("preValue", preValues); 121 logText.put("preValue", preValues);
107 logText.put("afterValue", afterValues); 122 logText.put("afterValue", afterValues);
108 123
109 - OrderItemDto orderItemDto = new OrderItemDto(); 124 + final OrderItemDto orderItemDto = new OrderItemDto();
110 orderItemDto.setbId("-1"); 125 orderItemDto.setbId("-1");
111 orderItemDto.setAction("DEL"); 126 orderItemDto.setAction("DEL");
112 orderItemDto.setActionObj(tmpTable.trim()); 127 orderItemDto.setActionObj(tmpTable.trim());
@@ -114,17 +129,22 @@ public class Java110MybatisInterceptor implements Interceptor { @@ -114,17 +129,22 @@ public class Java110MybatisInterceptor implements Interceptor {
114 orderItemDto.setServiceName(ApplicationContextFactory.getApplicationName()); 129 orderItemDto.setServiceName(ApplicationContextFactory.getApplicationName());
115 orderItemDto.setoId(Java110TransactionalFactory.getOId()); 130 orderItemDto.setoId(Java110TransactionalFactory.getOId());
116 131
117 - String url = ServiceConstant.SERVICE_ORDER_URL + "/order/oIdApi/createOrderItem";  
118 - HttpHeaders httpHeaders = new HttpHeaders();  
119 - HttpEntity httpEntity = new HttpEntity(orderItemDto.toString(), httpHeaders);  
120 - if(Environment.isStartBootWay()){  
121 - url = ServiceConstant.BOOT_SERVICE_ORDER_URL + "/order/oIdApi/createOrderItem";  
122 - }  
123 - ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);  
124 -  
125 - if (responseEntity.getStatusCode() != HttpStatus.OK) {  
126 - throw new IllegalArgumentException("注册事务回滚日志失败" + responseEntity);  
127 - } 132 + final boolean isBoot = Environment.isStartBootWay();
  133 + final RestTemplate rt = this.restTemplate;
  134 + ASYNC_LOG_EXECUTOR.submit(() -> {
  135 + try {
  136 + String url = isBoot ? ServiceConstant.BOOT_SERVICE_ORDER_URL : ServiceConstant.SERVICE_ORDER_URL;
  137 + url += "/order/oIdApi/createOrderItem";
  138 + HttpHeaders httpHeaders = new HttpHeaders();
  139 + HttpEntity httpEntity = new HttpEntity(orderItemDto.toString(), httpHeaders);
  140 + ResponseEntity<String> responseEntity = rt.exchange(url, HttpMethod.POST, httpEntity, String.class);
  141 + if (responseEntity.getStatusCode() != HttpStatus.OK) {
  142 + logger.error("异步注册事务回滚日志失败(DEL): {}", responseEntity.getBody());
  143 + }
  144 + } catch (Exception e) {
  145 + logger.error("异步注册事务回滚日志异常(DEL)", e);
  146 + }
  147 + });
128 } 148 }
129 149
130 /** 150 /**
@@ -168,7 +188,7 @@ public class Java110MybatisInterceptor implements Interceptor { @@ -168,7 +188,7 @@ public class Java110MybatisInterceptor implements Interceptor {
168 logText.put("preValue", preValues); 188 logText.put("preValue", preValues);
169 logText.put("afterValue", afterValues); 189 logText.put("afterValue", afterValues);
170 190
171 - OrderItemDto orderItemDto = new OrderItemDto(); 191 + final OrderItemDto orderItemDto = new OrderItemDto();
172 orderItemDto.setbId("-1"); 192 orderItemDto.setbId("-1");
173 orderItemDto.setAction("MOD"); 193 orderItemDto.setAction("MOD");
174 orderItemDto.setActionObj(tmpTable.trim()); 194 orderItemDto.setActionObj(tmpTable.trim());
@@ -176,18 +196,22 @@ public class Java110MybatisInterceptor implements Interceptor { @@ -176,18 +196,22 @@ public class Java110MybatisInterceptor implements Interceptor {
176 orderItemDto.setServiceName(ApplicationContextFactory.getApplicationName()); 196 orderItemDto.setServiceName(ApplicationContextFactory.getApplicationName());
177 orderItemDto.setoId(Java110TransactionalFactory.getOId()); 197 orderItemDto.setoId(Java110TransactionalFactory.getOId());
178 198
179 - String url = ServiceConstant.SERVICE_ORDER_URL + "/order/oIdApi/createOrderItem";  
180 - HttpHeaders httpHeaders = new HttpHeaders();  
181 - HttpEntity httpEntity = new HttpEntity(orderItemDto.toString(), httpHeaders);  
182 - ResponseEntity<String> responseEntity = null;  
183 - if(Environment.isStartBootWay()){  
184 - url = ServiceConstant.BOOT_SERVICE_ORDER_URL + "/order/oIdApi/createOrderItem";  
185 - }  
186 - responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);  
187 -  
188 - if (responseEntity.getStatusCode() != HttpStatus.OK) {  
189 - throw new IllegalArgumentException("注册事务回滚日志失败" + responseEntity);  
190 - } 199 + final boolean isBoot = Environment.isStartBootWay();
  200 + final RestTemplate rt = this.restTemplate;
  201 + ASYNC_LOG_EXECUTOR.submit(() -> {
  202 + try {
  203 + String url = isBoot ? ServiceConstant.BOOT_SERVICE_ORDER_URL : ServiceConstant.SERVICE_ORDER_URL;
  204 + url += "/order/oIdApi/createOrderItem";
  205 + HttpHeaders httpHeaders = new HttpHeaders();
  206 + HttpEntity httpEntity = new HttpEntity(orderItemDto.toString(), httpHeaders);
  207 + ResponseEntity<String> responseEntity = rt.exchange(url, HttpMethod.POST, httpEntity, String.class);
  208 + if (responseEntity.getStatusCode() != HttpStatus.OK) {
  209 + logger.error("异步注册事务回滚日志失败(MOD): {}", responseEntity.getBody());
  210 + }
  211 + } catch (Exception e) {
  212 + logger.error("异步注册事务回滚日志异常(MOD)", e);
  213 + }
  214 + });
191 } 215 }
192 216
193 private void dealReturnMap(Map<String, Object> map) { 217 private void dealReturnMap(Map<String, Object> map) {
@@ -241,7 +265,7 @@ public class Java110MybatisInterceptor implements Interceptor { @@ -241,7 +265,7 @@ public class Java110MybatisInterceptor implements Interceptor {
241 logText.put("preValue", preValues); 265 logText.put("preValue", preValues);
242 logText.put("afterValue", afterValues); 266 logText.put("afterValue", afterValues);
243 267
244 - OrderItemDto orderItemDto = new OrderItemDto(); 268 + final OrderItemDto orderItemDto = new OrderItemDto();
245 orderItemDto.setbId("-1"); 269 orderItemDto.setbId("-1");
246 orderItemDto.setAction("ADD"); 270 orderItemDto.setAction("ADD");
247 orderItemDto.setActionObj(tmpTable.trim()); 271 orderItemDto.setActionObj(tmpTable.trim());
@@ -249,17 +273,22 @@ public class Java110MybatisInterceptor implements Interceptor { @@ -249,17 +273,22 @@ public class Java110MybatisInterceptor implements Interceptor {
249 orderItemDto.setServiceName(ApplicationContextFactory.getApplicationName()); 273 orderItemDto.setServiceName(ApplicationContextFactory.getApplicationName());
250 orderItemDto.setoId(Java110TransactionalFactory.getOId()); 274 orderItemDto.setoId(Java110TransactionalFactory.getOId());
251 275
252 - String url = ServiceConstant.SERVICE_ORDER_URL + "/order/oIdApi/createOrderItem";  
253 - HttpHeaders httpHeaders = new HttpHeaders();  
254 - HttpEntity httpEntity = new HttpEntity(orderItemDto.toString(), httpHeaders);  
255 - if(Environment.isStartBootWay()){  
256 - url = ServiceConstant.BOOT_SERVICE_ORDER_URL + "/order/oIdApi/createOrderItem";  
257 - }  
258 - ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);  
259 -  
260 - if (responseEntity.getStatusCode() != HttpStatus.OK) {  
261 - throw new IllegalArgumentException("注册事务回滚日志失败" + responseEntity);  
262 - } 276 + final boolean isBoot = Environment.isStartBootWay();
  277 + final RestTemplate rt = this.restTemplate;
  278 + ASYNC_LOG_EXECUTOR.submit(() -> {
  279 + try {
  280 + String url = isBoot ? ServiceConstant.BOOT_SERVICE_ORDER_URL : ServiceConstant.SERVICE_ORDER_URL;
  281 + url += "/order/oIdApi/createOrderItem";
  282 + HttpHeaders httpHeaders = new HttpHeaders();
  283 + HttpEntity httpEntity = new HttpEntity(orderItemDto.toString(), httpHeaders);
  284 + ResponseEntity<String> responseEntity = rt.exchange(url, HttpMethod.POST, httpEntity, String.class);
  285 + if (responseEntity.getStatusCode() != HttpStatus.OK) {
  286 + logger.error("异步注册事务回滚日志失败(ADD): {}", responseEntity.getBody());
  287 + }
  288 + } catch (Exception e) {
  289 + logger.error("异步注册事务回滚日志异常(ADD)", e);
  290 + }
  291 + });
263 292
264 } 293 }
265 294
java110-interface/src/main/resources/logback-prod.xml
1 <?xml version="1.0" encoding="UTF-8"?> 1 <?xml version="1.0" encoding="UTF-8"?>
2 <configuration scan="true" scanPeriod="60 seconds"> 2 <configuration scan="true" scanPeriod="60 seconds">
3 3
4 -<!-- <include resource="org/springframework/boot/logging/logback/base.xml"/>--> 4 + <!-- 异步日志appender,大幅减少日志I/O对业务的阻塞 -->
  5 + <appender name="ASYNC_STDOUT" class="ch.qos.logback.classic.AsyncAppender">
  6 + <queueSize>512</queueSize>
  7 + <discardingThreshold>0</discardingThreshold>
  8 + <neverBlock>true</neverBlock>
  9 + <appender-ref ref="STDOUT_FILE"/>
  10 + </appender>
5 11
6 <!-- 控制台输出 --> 12 <!-- 控制台输出 -->
7 <appender name="STDOUT_FILE" class="ch.qos.logback.core.ConsoleAppender"> 13 <appender name="STDOUT_FILE" class="ch.qos.logback.core.ConsoleAppender">
8 <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> 14 <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
9 - <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->  
10 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> 15 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
11 </encoder> 16 </encoder>
12 </appender> 17 </appender>
13 18
14 - <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">  
15 - <File>./logs/debug.log</File>  
16 - <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
17 - <fileNamePattern>./logs/debug-%d{yyyyMMdd}.log.%i</fileNamePattern>  
18 - <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">  
19 - <maxFileSize>500MB</maxFileSize>  
20 - </timeBasedFileNamingAndTriggeringPolicy>  
21 - <maxHistory>2</maxHistory>  
22 - </rollingPolicy>  
23 - <layout class="ch.qos.logback.classic.PatternLayout">  
24 - <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n  
25 - </Pattern>  
26 - </layout> 19 + <appender name="ASYNC_INFO" class="ch.qos.logback.classic.AsyncAppender">
  20 + <queueSize>512</queueSize>
  21 + <discardingThreshold>0</discardingThreshold>
  22 + <neverBlock>true</neverBlock>
  23 + <appender-ref ref="INFO_FILE"/>
27 </appender> 24 </appender>
28 25
29 <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 26 <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  27 + <immediateFlush>false</immediateFlush>
30 <File>./logs/info.log</File> 28 <File>./logs/info.log</File>
31 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 29 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
32 <fileNamePattern>./logs/info-%d{yyyyMMdd}.log.%i</fileNamePattern> 30 <fileNamePattern>./logs/info-%d{yyyyMMdd}.log.%i</fileNamePattern>
@@ -36,33 +34,44 @@ @@ -36,33 +34,44 @@
36 <maxHistory>2</maxHistory> 34 <maxHistory>2</maxHistory>
37 </rollingPolicy> 35 </rollingPolicy>
38 <layout class="ch.qos.logback.classic.PatternLayout"> 36 <layout class="ch.qos.logback.classic.PatternLayout">
39 - <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n  
40 - </Pattern> 37 + <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n</Pattern>
41 </layout> 38 </layout>
42 </appender> 39 </appender>
43 40
  41 + <appender name="ASYNC_ERROR" class="ch.qos.logback.classic.AsyncAppender">
  42 + <queueSize>256</queueSize>
  43 + <discardingThreshold>0</discardingThreshold>
  44 + <neverBlock>false</neverBlock>
  45 + <appender-ref ref="ERROR_FILE"/>
  46 + </appender>
  47 +
44 <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 48 <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
45 <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 49 <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
46 <level>ERROR</level> 50 <level>ERROR</level>
47 </filter> 51 </filter>
48 <File>./logs/error.log</File> 52 <File>./logs/error.log</File>
49 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 53 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
50 - <fileNamePattern>${LOG_PATH}/error-%d{yyyyMMdd}.log.%i  
51 - </fileNamePattern> 54 + <fileNamePattern>${LOG_PATH}/error-%d{yyyyMMdd}.log.%i</fileNamePattern>
52 <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> 55 <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
53 <maxFileSize>500MB</maxFileSize> 56 <maxFileSize>500MB</maxFileSize>
54 </timeBasedFileNamingAndTriggeringPolicy> 57 </timeBasedFileNamingAndTriggeringPolicy>
55 <maxHistory>2</maxHistory> 58 <maxHistory>2</maxHistory>
56 </rollingPolicy> 59 </rollingPolicy>
57 <layout class="ch.qos.logback.classic.PatternLayout"> 60 <layout class="ch.qos.logback.classic.PatternLayout">
58 - <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n  
59 -  
60 - </Pattern> 61 + <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n</Pattern>
61 </layout> 62 </layout>
62 </appender> 63 </appender>
63 64
64 <!-- 请求响应日志 --> 65 <!-- 请求响应日志 -->
  66 + <appender name="ASYNC_REQUEST" class="ch.qos.logback.classic.AsyncAppender">
  67 + <queueSize>512</queueSize>
  68 + <discardingThreshold>0</discardingThreshold>
  69 + <neverBlock>true</neverBlock>
  70 + <appender-ref ref="REQUEST_FILE"/>
  71 + </appender>
  72 +
65 <appender name="REQUEST_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 73 <appender name="REQUEST_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  74 + <immediateFlush>false</immediateFlush>
66 <File>./logs/request.log</File> 75 <File>./logs/request.log</File>
67 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 76 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
68 <fileNamePattern>./logs/request-%d{yyyyMMdd}.log.%i</fileNamePattern> 77 <fileNamePattern>./logs/request-%d{yyyyMMdd}.log.%i</fileNamePattern>
@@ -77,6 +86,13 @@ @@ -77,6 +86,13 @@
77 </appender> 86 </appender>
78 87
79 <!-- API异常日志单独输出 --> 88 <!-- API异常日志单独输出 -->
  89 + <appender name="ASYNC_API_ERROR" class="ch.qos.logback.classic.AsyncAppender">
  90 + <queueSize>256</queueSize>
  91 + <discardingThreshold>0</discardingThreshold>
  92 + <neverBlock>false</neverBlock>
  93 + <appender-ref ref="API_ERROR_FILE"/>
  94 + </appender>
  95 +
80 <appender name="API_ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 96 <appender name="API_ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
81 <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 97 <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
82 <level>ERROR</level> 98 <level>ERROR</level>
@@ -95,53 +111,40 @@ @@ -95,53 +111,40 @@
95 </appender> 111 </appender>
96 112
97 <logger name="org.springframework" level="ERROR"> 113 <logger name="org.springframework" level="ERROR">
98 - <appender-ref ref="STDOUT_FILE"/>  
99 - </logger>  
100 -  
101 - <!--myibatis log configure-->  
102 - <logger name="com.apache.ibatis" level="ERROR">  
103 - <appender-ref ref="STDOUT_FILE"/>  
104 - </logger>  
105 -  
106 - <logger name="org.mybatis" level="ERROR">  
107 - <appender-ref ref="STDOUT_FILE"/>  
108 - </logger>  
109 - <logger name="druid.sql.Statement" level="ERROR">  
110 - <appender-ref ref="STDOUT_FILE"/>  
111 - </logger>  
112 - <logger name="druid.sql.ResultSet" level="ERROR">  
113 - <appender-ref ref="STDOUT_FILE"/> 114 + <appender-ref ref="ASYNC_STDOUT"/>
114 </logger> 115 </logger>
115 116
  117 + <!-- MyBatis/Druid SQL日志在生产环境关闭 -->
  118 + <logger name="com.apache.ibatis" level="ERROR"/>
  119 + <logger name="org.mybatis" level="ERROR"/>
  120 + <logger name="druid.sql.Statement" level="ERROR"/>
  121 + <logger name="druid.sql.ResultSet" level="ERROR"/>
  122 + <logger name="druid.sql.Connection" level="ERROR"/>
116 123
117 <logger name="com.java110" level="INFO"> 124 <logger name="com.java110" level="INFO">
118 - <appender-ref ref="STDOUT_FILE"/> 125 + <appender-ref ref="ASYNC_STDOUT"/>
119 </logger> 126 </logger>
120 127
121 <!-- API请求/响应/异常日志 --> 128 <!-- API请求/响应/异常日志 -->
122 <logger name="com.java110.api.aop" level="INFO" additivity="false"> 129 <logger name="com.java110.api.aop" level="INFO" additivity="false">
123 - <appender-ref ref="STDOUT_FILE"/>  
124 - <appender-ref ref="REQUEST_FILE"/>  
125 - <appender-ref ref="API_ERROR_FILE"/>  
126 - <appender-ref ref="ERROR_FILE"/> 130 + <appender-ref ref="ASYNC_STDOUT"/>
  131 + <appender-ref ref="ASYNC_REQUEST"/>
  132 + <appender-ref ref="ASYNC_API_ERROR"/>
  133 + <appender-ref ref="ASYNC_ERROR"/>
127 </logger> 134 </logger>
128 135
129 - <logger name="io.shardingsphere" level="ERROR">  
130 - <appender-ref ref="STDOUT_FILE"/>  
131 - </logger> 136 + <logger name="io.shardingsphere" level="ERROR"/>
132 137
133 - <logger name="org.thymeleaf" level="ERROR">  
134 - <appender-ref ref="STDOUT_FILE"/>  
135 - </logger> 138 + <logger name="org.thymeleaf" level="ERROR"/>
136 139
137 - <logger name="org.apache.kafka" level="ERROR">  
138 - <appender-ref ref="STDOUT_FILE"/>  
139 - </logger> 140 + <logger name="org.apache.kafka" level="ERROR"/>
  141 +
  142 + <logger name="org.quartz" level="ERROR"/>
140 143
141 <root level="INFO"> 144 <root level="INFO">
142 - <appender-ref ref="STDOUT_FILE"/>  
143 - <appender-ref ref="INFO_FILE"/>  
144 - <appender-ref ref="ERROR_FILE"/> 145 + <appender-ref ref="ASYNC_STDOUT"/>
  146 + <appender-ref ref="ASYNC_INFO"/>
  147 + <appender-ref ref="ASYNC_ERROR"/>
145 </root> 148 </root>
146 149
147 </configuration> 150 </configuration>
java110-interface/src/main/resources/logback.xml
1 <?xml version="1.0" encoding="UTF-8"?> 1 <?xml version="1.0" encoding="UTF-8"?>
2 <configuration scan="true" scanPeriod="60 seconds"> 2 <configuration scan="true" scanPeriod="60 seconds">
3 3
4 - <!--<include resource="org/springframework/boot/logging/logback/base.xml"/>--> 4 + <!-- 异步日志appender,减少日志I/O对业务的阻塞 -->
  5 + <appender name="ASYNC_STDOUT" class="ch.qos.logback.classic.AsyncAppender">
  6 + <queueSize>512</queueSize>
  7 + <discardingThreshold>0</discardingThreshold>
  8 + <neverBlock>true</neverBlock>
  9 + <appender-ref ref="STDOUT_FILE"/>
  10 + </appender>
5 11
6 <!-- 控制台输出 --> 12 <!-- 控制台输出 -->
7 <appender name="STDOUT_FILE" class="ch.qos.logback.core.ConsoleAppender"> 13 <appender name="STDOUT_FILE" class="ch.qos.logback.core.ConsoleAppender">
8 <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> 14 <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
9 - <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->  
10 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> 15 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
11 </encoder> 16 </encoder>
12 </appender> 17 </appender>
13 18
14 - <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">  
15 - <File>./logs/debug.log</File>  
16 - <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
17 - <fileNamePattern>./logs/debug-%d{yyyyMMdd}.log.%i</fileNamePattern>  
18 - <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">  
19 - <maxFileSize>500MB</maxFileSize>  
20 - </timeBasedFileNamingAndTriggeringPolicy>  
21 - <maxHistory>2</maxHistory>  
22 - </rollingPolicy>  
23 - <layout class="ch.qos.logback.classic.PatternLayout">  
24 - <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n  
25 - </Pattern>  
26 - </layout> 19 + <appender name="ASYNC_INFO" class="ch.qos.logback.classic.AsyncAppender">
  20 + <queueSize>512</queueSize>
  21 + <discardingThreshold>0</discardingThreshold>
  22 + <neverBlock>true</neverBlock>
  23 + <appender-ref ref="INFO_FILE"/>
27 </appender> 24 </appender>
28 25
29 <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 26 <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  27 + <immediateFlush>false</immediateFlush>
30 <File>./logs/info.log</File> 28 <File>./logs/info.log</File>
31 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 29 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
32 <fileNamePattern>./logs/info-%d{yyyyMMdd}.log.%i</fileNamePattern> 30 <fileNamePattern>./logs/info-%d{yyyyMMdd}.log.%i</fileNamePattern>
@@ -36,33 +34,44 @@ @@ -36,33 +34,44 @@
36 <maxHistory>2</maxHistory> 34 <maxHistory>2</maxHistory>
37 </rollingPolicy> 35 </rollingPolicy>
38 <layout class="ch.qos.logback.classic.PatternLayout"> 36 <layout class="ch.qos.logback.classic.PatternLayout">
39 - <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n  
40 - </Pattern> 37 + <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n</Pattern>
41 </layout> 38 </layout>
42 </appender> 39 </appender>
43 40
  41 + <appender name="ASYNC_ERROR" class="ch.qos.logback.classic.AsyncAppender">
  42 + <queueSize>256</queueSize>
  43 + <discardingThreshold>0</discardingThreshold>
  44 + <neverBlock>false</neverBlock>
  45 + <appender-ref ref="ERROR_FILE"/>
  46 + </appender>
  47 +
44 <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 48 <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
45 <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 49 <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
46 <level>ERROR</level> 50 <level>ERROR</level>
47 </filter> 51 </filter>
48 <File>./logs/error.log</File> 52 <File>./logs/error.log</File>
49 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 53 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
50 - <fileNamePattern>${LOG_PATH}/error-%d{yyyyMMdd}.log.%i  
51 - </fileNamePattern> 54 + <fileNamePattern>${LOG_PATH}/error-%d{yyyyMMdd}.log.%i</fileNamePattern>
52 <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> 55 <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
53 <maxFileSize>500MB</maxFileSize> 56 <maxFileSize>500MB</maxFileSize>
54 </timeBasedFileNamingAndTriggeringPolicy> 57 </timeBasedFileNamingAndTriggeringPolicy>
55 <maxHistory>2</maxHistory> 58 <maxHistory>2</maxHistory>
56 </rollingPolicy> 59 </rollingPolicy>
57 <layout class="ch.qos.logback.classic.PatternLayout"> 60 <layout class="ch.qos.logback.classic.PatternLayout">
58 - <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n  
59 -  
60 - </Pattern> 61 + <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n</Pattern>
61 </layout> 62 </layout>
62 </appender> 63 </appender>
63 64
64 <!-- 请求响应日志 --> 65 <!-- 请求响应日志 -->
  66 + <appender name="ASYNC_REQUEST" class="ch.qos.logback.classic.AsyncAppender">
  67 + <queueSize>512</queueSize>
  68 + <discardingThreshold>0</discardingThreshold>
  69 + <neverBlock>true</neverBlock>
  70 + <appender-ref ref="REQUEST_FILE"/>
  71 + </appender>
  72 +
65 <appender name="REQUEST_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 73 <appender name="REQUEST_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  74 + <immediateFlush>false</immediateFlush>
66 <File>./logs/request.log</File> 75 <File>./logs/request.log</File>
67 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 76 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
68 <fileNamePattern>./logs/request-%d{yyyyMMdd}.log.%i</fileNamePattern> 77 <fileNamePattern>./logs/request-%d{yyyyMMdd}.log.%i</fileNamePattern>
@@ -76,7 +85,14 @@ @@ -76,7 +85,14 @@
76 </layout> 85 </layout>
77 </appender> 86 </appender>
78 87
79 - <!-- API异常日志单独输出 --> 88 + <!-- API异常日志 -->
  89 + <appender name="ASYNC_API_ERROR" class="ch.qos.logback.classic.AsyncAppender">
  90 + <queueSize>256</queueSize>
  91 + <discardingThreshold>0</discardingThreshold>
  92 + <neverBlock>false</neverBlock>
  93 + <appender-ref ref="API_ERROR_FILE"/>
  94 + </appender>
  95 +
80 <appender name="API_ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 96 <appender name="API_ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
81 <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 97 <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
82 <level>ERROR</level> 98 <level>ERROR</level>
@@ -94,57 +110,38 @@ @@ -94,57 +110,38 @@
94 </layout> 110 </layout>
95 </appender> 111 </appender>
96 112
97 - <logger name="org.springframework" level="ERROR">  
98 - <appender-ref ref="STDOUT_FILE"/>  
99 - </logger>  
100 - <logger name="org.quartz" level="DEBUG">  
101 - <appender-ref ref="STDOUT_FILE"/>  
102 - </logger>  
103 - <logger name="com.java110.order" level="ERROR">  
104 - <appender-ref ref="STDOUT_FILE"/>  
105 - </logger> 113 + <!-- Spring框架日志 -->
  114 + <logger name="org.springframework" level="ERROR"/>
106 115
  116 + <!-- MyBatis/Druid SQL日志关闭,避免大量DEBUG日志 -->
  117 + <logger name="com.apache.ibatis" level="ERROR"/>
  118 + <logger name="org.mybatis" level="ERROR"/>
  119 + <logger name="druid.sql.Statement" level="ERROR"/>
  120 + <logger name="druid.sql.ResultSet" level="ERROR"/>
  121 + <logger name="druid.sql.Connection" level="ERROR"/>
107 122
108 - <logger name="org.mybatis" level="DEBUG">  
109 - <appender-ref ref="STDOUT_FILE"/>  
110 - </logger>  
111 - <logger name="druid.sql.Statement" level="DEBUG" additivity="false">  
112 - <appender-ref ref="STDOUT_FILE"/>  
113 - </logger>  
114 - <logger name="druid.sql.ResultSet" level="DEBUG" additivity="false">  
115 - <appender-ref ref="STDOUT_FILE"/>  
116 - </logger>  
117 - <logger name="druid.sql.Connection" level="DEBUG" additivity="false">  
118 - <appender-ref ref="STDOUT_FILE"/>  
119 - </logger>  
120 -  
121 -  
122 - <logger name="com.java110" level="DEBUG">  
123 - <appender-ref ref="STDOUT_FILE"/> 123 + <!-- 业务日志 INFO级别 -->
  124 + <logger name="com.java110" level="INFO">
  125 + <appender-ref ref="ASYNC_STDOUT"/>
124 </logger> 126 </logger>
125 127
126 <!-- API请求/响应/异常日志 --> 128 <!-- API请求/响应/异常日志 -->
127 <logger name="com.java110.api.aop" level="INFO" additivity="false"> 129 <logger name="com.java110.api.aop" level="INFO" additivity="false">
128 - <appender-ref ref="STDOUT_FILE"/>  
129 - <appender-ref ref="REQUEST_FILE"/>  
130 - <appender-ref ref="API_ERROR_FILE"/>  
131 - <appender-ref ref="ERROR_FILE"/>  
132 - </logger>  
133 -  
134 - <logger name="org.thymeleaf" level="ERROR">  
135 - <appender-ref ref="STDOUT_FILE"/>  
136 - </logger>  
137 -  
138 - <logger name="org.apache.kafka" level="ERROR">  
139 - <appender-ref ref="STDOUT_FILE"/> 130 + <appender-ref ref="ASYNC_STDOUT"/>
  131 + <appender-ref ref="ASYNC_REQUEST"/>
  132 + <appender-ref ref="ASYNC_API_ERROR"/>
  133 + <appender-ref ref="ASYNC_ERROR"/>
140 </logger> 134 </logger>
141 135
  136 + <logger name="io.shardingsphere" level="ERROR"/>
  137 + <logger name="org.thymeleaf" level="ERROR"/>
  138 + <logger name="org.apache.kafka" level="ERROR"/>
  139 + <logger name="org.quartz" level="ERROR"/>
142 140
143 <root level="INFO"> 141 <root level="INFO">
144 - <appender-ref ref="STDOUT_FILE"/>  
145 - <appender-ref ref="DEBUG_FILE"/>  
146 - <appender-ref ref="INFO_FILE"/>  
147 - <appender-ref ref="ERROR_FILE"/> 142 + <appender-ref ref="ASYNC_STDOUT"/>
  143 + <appender-ref ref="ASYNC_INFO"/>
  144 + <appender-ref ref="ASYNC_ERROR"/>
148 </root> 145 </root>
149 146
150 </configuration> 147 </configuration>
service-api/src/main/java/com/java110/api/listener/CmdListener.java
@@ -4,13 +4,16 @@ import com.alibaba.fastjson.JSONObject; @@ -4,13 +4,16 @@ import com.alibaba.fastjson.JSONObject;
4 import com.aliyuncs.utils.StringUtils; 4 import com.aliyuncs.utils.StringUtils;
5 import com.java110.core.annotation.Java110Listener; 5 import com.java110.core.annotation.Java110Listener;
6 import com.java110.core.context.DataFlowContext; 6 import com.java110.core.context.DataFlowContext;
  7 +import com.java110.core.context.Environment;
7 import com.java110.core.event.service.api.ServiceDataFlowEvent; 8 import com.java110.core.event.service.api.ServiceDataFlowEvent;
8 import com.java110.core.log.LoggerFactory; 9 import com.java110.core.log.LoggerFactory;
9 import com.java110.dto.order.OrderDto; 10 import com.java110.dto.order.OrderDto;
10 import com.java110.dto.system.AppService; 11 import com.java110.dto.system.AppService;
11 import com.java110.intf.job.IDataBusInnerServiceSMO; 12 import com.java110.intf.job.IDataBusInnerServiceSMO;
  13 +import com.java110.service.smo.ICmdServiceSMO;
12 import com.java110.utils.constant.CommonConstant; 14 import com.java110.utils.constant.CommonConstant;
13 import com.java110.utils.constant.ServiceCodeConstant; 15 import com.java110.utils.constant.ServiceCodeConstant;
  16 +import com.java110.utils.factory.ApplicationContextFactory;
14 import com.java110.utils.util.StringUtil; 17 import com.java110.utils.util.StringUtil;
15 import com.java110.vo.ResultVo; 18 import com.java110.vo.ResultVo;
16 import org.slf4j.Logger; 19 import org.slf4j.Logger;
@@ -19,6 +22,7 @@ import org.springframework.http.*; @@ -19,6 +22,7 @@ import org.springframework.http.*;
19 import org.springframework.web.client.HttpStatusCodeException; 22 import org.springframework.web.client.HttpStatusCodeException;
20 import org.springframework.web.client.RestTemplate; 23 import org.springframework.web.client.RestTemplate;
21 24
  25 +import java.util.HashMap;
22 import java.util.Map; 26 import java.util.Map;
23 27
24 @Java110Listener("cmdListener") 28 @Java110Listener("cmdListener")
@@ -45,16 +49,7 @@ public class CmdListener extends AbstractServiceApiListener { @@ -45,16 +49,7 @@ public class CmdListener extends AbstractServiceApiListener {
45 49
46 AppService service = event.getAppService(); 50 AppService service = event.getAppService();
47 Map<String, String> reqHeader = context.getRequestCurrentHeaders(); 51 Map<String, String> reqHeader = context.getRequestCurrentHeaders();
48 - HttpHeaders header = new HttpHeaders();  
49 - for (String key : context.getRequestCurrentHeaders().keySet()) {  
50 - if("user-name".equals(key)){  
51 - continue;  
52 - }  
53 - if("userName".equals(key)){  
54 - continue;  
55 - }  
56 - header.add(key, reqHeader.get(key));  
57 - } 52 +
58 if (reqHeader.containsKey(CommonConstant.USER_ID) 53 if (reqHeader.containsKey(CommonConstant.USER_ID)
59 && (!reqJson.containsKey("userId") || StringUtil.isEmpty(reqJson.getString("userId")))) { 54 && (!reqJson.containsKey("userId") || StringUtil.isEmpty(reqJson.getString("userId")))) {
60 reqJson.put("userId", reqHeader.get(CommonConstant.USER_ID)); 55 reqJson.put("userId", reqHeader.get(CommonConstant.USER_ID));
@@ -76,48 +71,62 @@ public class CmdListener extends AbstractServiceApiListener { @@ -76,48 +71,62 @@ public class CmdListener extends AbstractServiceApiListener {
76 reqJson.put("userName", reqHeader.get(CommonConstant.LOGIN_USER_NAME)); 71 reqJson.put("userName", reqHeader.get(CommonConstant.LOGIN_USER_NAME));
77 } 72 }
78 73
79 - HttpEntity<String> httpEntity = new HttpEntity<String>(reqJson.toJSONString(), header);  
80 - String orgRequestUrl = context.getRequestHeaders().get("REQUEST_URL");  
81 -  
82 String serviceCode = service.getServiceCode(); 74 String serviceCode = service.getServiceCode();
83 -  
84 serviceCode = serviceCode.startsWith("/") ? serviceCode : ("/" + serviceCode); 75 serviceCode = serviceCode.startsWith("/") ? serviceCode : ("/" + serviceCode);
85 76
86 - String requestUrl = service.getUrl() + "/cmd" + serviceCode;  
87 - //  
88 ResponseEntity responseEntity = null; 77 ResponseEntity responseEntity = null;
89 - if (!StringUtil.isNullOrNone(orgRequestUrl)) {  
90 - String param = orgRequestUrl.contains("?") ? orgRequestUrl.substring(orgRequestUrl.indexOf("?") + 1, orgRequestUrl.length()) : "";  
91 - requestUrl += ("?" + param);  
92 - }  
93 - try {  
94 - responseEntity = restTemplate.exchange(requestUrl, HttpMethod.POST, httpEntity, String.class);  
95 - HttpHeaders headers = responseEntity.getHeaders();  
96 - String oId = "-1";  
97 - if (headers.containsKey(OrderDto.O_ID)) {  
98 - oId = headers.get(OrderDto.O_ID).get(0);  
99 - }  
100 78
  79 + // Boot模式下直接调用CmdServiceSMO,避免HTTP loopback开销
  80 + if (Environment.isStartBootWay()) {
  81 + try {
  82 + Map<String, String> headers = new HashMap<>();
  83 + headers.put(CommonConstant.HTTP_SERVICE, serviceCode);
  84 + headers.put(CommonConstant.HTTP_METHOD, CommonConstant.HTTP_METHOD_POST);
  85 + ICmdServiceSMO cmdServiceSMO = ApplicationContextFactory.getBean("cmdServiceSMOImpl", ICmdServiceSMO.class);
  86 + responseEntity = cmdServiceSMO.cmd(reqJson.toJSONString(), headers);
  87 + } catch (Exception e) {
  88 + logger.error("Boot模式直接调用cmd失败【{}】", serviceCode, e);
  89 + responseEntity = new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
  90 + }
  91 + } else {
  92 + // 微服务模式下走HTTP调用
  93 + HttpHeaders header = new HttpHeaders();
  94 + for (String key : context.getRequestCurrentHeaders().keySet()) {
  95 + if("user-name".equals(key)){
  96 + continue;
  97 + }
  98 + if("userName".equals(key)){
  99 + continue;
  100 + }
  101 + header.add(key, reqHeader.get(key));
  102 + }
101 103
102 - } catch (HttpStatusCodeException e) { //这里spring 框架 在4XX 或 5XX 时抛出 HttpServerErrorException 异常,需要重新封装一下  
103 - logger.error("请求下游服务【" + requestUrl + "】异常,参数为" + httpEntity + e.getResponseBodyAsString(), e);  
104 - String body = e.getResponseBodyAsString(); 104 + HttpEntity<String> httpEntity = new HttpEntity<String>(reqJson.toJSONString(), header);
  105 + String orgRequestUrl = context.getRequestHeaders().get("REQUEST_URL");
105 106
106 - if (StringUtil.isJsonObject(body)) {  
107 - JSONObject bodyObj = JSONObject.parseObject(body);  
108 - if (bodyObj.containsKey("message") && !StringUtil.isEmpty(bodyObj.getString("message"))) {  
109 - body = bodyObj.getString("message"); 107 + String requestUrl = service.getUrl() + "/cmd" + serviceCode;
  108 + if (!StringUtil.isNullOrNone(orgRequestUrl)) {
  109 + String param = orgRequestUrl.contains("?") ? orgRequestUrl.substring(orgRequestUrl.indexOf("?") + 1, orgRequestUrl.length()) : "";
  110 + requestUrl += ("?" + param);
  111 + }
  112 + try {
  113 + responseEntity = restTemplate.exchange(requestUrl, HttpMethod.POST, httpEntity, String.class);
  114 + } catch (HttpStatusCodeException e) {
  115 + logger.error("请求下游服务【" + requestUrl + "】异常,参数为" + httpEntity + e.getResponseBodyAsString(), e);
  116 + String body = e.getResponseBodyAsString();
  117 + if (StringUtil.isJsonObject(body)) {
  118 + JSONObject bodyObj = JSONObject.parseObject(body);
  119 + if (bodyObj.containsKey("message") && !StringUtil.isEmpty(bodyObj.getString("message"))) {
  120 + body = bodyObj.getString("message");
  121 + }
110 } 122 }
  123 + responseEntity = new ResponseEntity<String>(body, e.getStatusCode());
111 } 124 }
112 - responseEntity = new ResponseEntity<String>(body, e.getStatusCode());  
113 } 125 }
114 126
115 - logger.debug("API 服务调用下游服务请求:{},返回为:{}", httpEntity, responseEntity);  
116 -  
117 if (responseEntity.getStatusCode() != HttpStatus.OK) { 127 if (responseEntity.getStatusCode() != HttpStatus.OK) {
118 responseEntity = ResultVo.createResponseEntity(ResultVo.CODE_ERROR, String.valueOf(responseEntity.getBody())); 128 responseEntity = ResultVo.createResponseEntity(ResultVo.CODE_ERROR, String.valueOf(responseEntity.getBody()));
119 context.setResponseEntity(responseEntity); 129 context.setResponseEntity(responseEntity);
120 -  
121 return; 130 return;
122 } 131 }
123 if (StringUtils.isEmpty(responseEntity.getBody() + "")) { 132 if (StringUtils.isEmpty(responseEntity.getBody() + "")) {
service-api/src/main/java/com/java110/api/smo/impl/ApiServiceSMOImpl.java
@@ -15,6 +15,7 @@ import com.java110.core.factory.GenerateCodeFactory; @@ -15,6 +15,7 @@ import com.java110.core.factory.GenerateCodeFactory;
15 import com.java110.core.log.LoggerFactory; 15 import com.java110.core.log.LoggerFactory;
16 import com.java110.core.smo.ISaveTransactionLogSMO; 16 import com.java110.core.smo.ISaveTransactionLogSMO;
17 import com.java110.core.trace.Java110TraceLog; 17 import com.java110.core.trace.Java110TraceLog;
  18 +import com.java110.service.smo.ICmdServiceSMO;
18 import com.java110.dto.order.OrderDto; 19 import com.java110.dto.order.OrderDto;
19 import com.java110.dto.system.AppRoute; 20 import com.java110.dto.system.AppRoute;
20 import com.java110.dto.system.AppService; 21 import com.java110.dto.system.AppService;
@@ -42,6 +43,7 @@ import org.springframework.stereotype.Service; @@ -42,6 +43,7 @@ import org.springframework.stereotype.Service;
42 import org.springframework.web.client.HttpStatusCodeException; 43 import org.springframework.web.client.HttpStatusCodeException;
43 44
44 import java.util.Date; 45 import java.util.Date;
  46 +import java.util.HashMap;
45 import java.util.List; 47 import java.util.List;
46 import java.util.Map; 48 import java.util.Map;
47 49
@@ -613,21 +615,24 @@ public class ApiServiceSMOImpl extends LoggerEngine implements IApiServiceSMO { @@ -613,21 +615,24 @@ public class ApiServiceSMOImpl extends LoggerEngine implements IApiServiceSMO {
613 requestUrl += ("?" + param); 615 requestUrl += ("?" + param);
614 } 616 }
615 try { 617 try {
616 - //todo http的方式调用微服务,相应的java类可以到相应微服务下的cmd下根据serviceCode 的寻找  
617 - //todo 这里会调用到 java110-service 模块下的 CmdApi 类,这个类各个微服务都会集成 618 + // Boot模式下直接调用CmdServiceSMO,避免HTTP loopback开销(~400ms)
618 if (Environment.isStartBootWay()) { 619 if (Environment.isStartBootWay()) {
  620 + Map<String, String> headers = new HashMap<>();
  621 + headers.put(CommonConstant.HTTP_SERVICE, serviceCode);
  622 + headers.put(CommonConstant.HTTP_METHOD, CommonConstant.HTTP_METHOD_POST);
  623 + ICmdServiceSMO cmdServiceSMO = ApplicationContextFactory.getBean("cmdServiceSMOImpl", ICmdServiceSMO.class);
  624 + responseEntity = cmdServiceSMO.cmd(reqJson.toJSONString(), headers);
  625 + } else {
619 requestUrl = Environment.BOOT_PATH + requestUrl; 626 requestUrl = Environment.BOOT_PATH + requestUrl;
620 restTemplate = ApplicationContextFactory.getBean("outRestTemplate", RestTemplate.class); 627 restTemplate = ApplicationContextFactory.getBean("outRestTemplate", RestTemplate.class);
621 responseEntity = restTemplate.exchange(requestUrl, HttpMethod.POST, httpEntity, String.class); 628 responseEntity = restTemplate.exchange(requestUrl, HttpMethod.POST, httpEntity, String.class);
622 - } else {  
623 - requestUrl = appService.getUrl() + requestUrl;  
624 - restTemplate = ApplicationContextFactory.getBean("restTemplate", RestTemplate.class);  
625 - responseEntity = restTemplate.exchange(requestUrl, HttpMethod.POST, httpEntity, String.class);  
626 } 629 }
627 - HttpHeaders headers = responseEntity.getHeaders();  
628 - String oId = "-1";  
629 - if (headers.containsKey(OrderDto.O_ID)) {  
630 - oId = headers.get(OrderDto.O_ID).get(0); 630 + if (responseEntity != null) {
  631 + HttpHeaders headers = responseEntity.getHeaders();
  632 + String oId = "-1";
  633 + if (headers.containsKey(OrderDto.O_ID)) {
  634 + oId = headers.get(OrderDto.O_ID).get(0);
  635 + }
631 } 636 }
632 637
633 } catch (HttpStatusCodeException e) { //todo 这里spring 框架 在4XX 或 5XX 时抛出 HttpServerErrorException 异常,需要重新封装一下 638 } catch (HttpStatusCodeException e) { //todo 这里spring 框架 在4XX 或 5XX 时抛出 HttpServerErrorException 异常,需要重新封装一下
@@ -641,6 +646,9 @@ public class ApiServiceSMOImpl extends LoggerEngine implements IApiServiceSMO { @@ -641,6 +646,9 @@ public class ApiServiceSMOImpl extends LoggerEngine implements IApiServiceSMO {
641 } 646 }
642 } 647 }
643 responseEntity = new ResponseEntity<String>(body, e.getStatusCode()); 648 responseEntity = new ResponseEntity<String>(body, e.getStatusCode());
  649 + } catch (Exception e) {
  650 + logger.error("直接调用cmd异常【{}】", serviceCode, e);
  651 + responseEntity = new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
644 } 652 }
645 653
646 logger.debug("API 服务调用下游服务请求:{},返回为:{}", httpEntity, responseEntity); 654 logger.debug("API 服务调用下游服务请求:{},返回为:{}", httpEntity, responseEntity);
service-common/src/main/java/com/java110/common/smo/impl/AttendanceLogInnerServiceSMOImpl.java
@@ -70,9 +70,15 @@ public class AttendanceLogInnerServiceSMOImpl extends BaseServiceSMO implements @@ -70,9 +70,15 @@ public class AttendanceLogInnerServiceSMOImpl extends BaseServiceSMO implements
70 return attendanceLogs; 70 return attendanceLogs;
71 } 71 }
72 String imgUrl = MappingCache.getValue(MappingConstant.FILE_DOMAIN, "IMG_PATH"); 72 String imgUrl = MappingCache.getValue(MappingConstant.FILE_DOMAIN, "IMG_PATH");
  73 + if (imgUrl == null) {
  74 + imgUrl = "";
  75 + }
73 76
74 for (AttendanceLogDto tmpAttendanceLogDto : attendanceLogs) { 77 for (AttendanceLogDto tmpAttendanceLogDto : attendanceLogs) {
75 - tmpAttendanceLogDto.setFacePath(imgUrl + tmpAttendanceLogDto.getFacePath()); 78 + String facePath = tmpAttendanceLogDto.getFacePath();
  79 + if (facePath != null && !facePath.isEmpty()) {
  80 + tmpAttendanceLogDto.setFacePath(imgUrl + facePath);
  81 + }
76 } 82 }
77 83
78 return attendanceLogs; 84 return attendanceLogs;
springboot/src/main/java/com/java110/boot/BootApplicationStart.java
@@ -149,9 +149,9 @@ public class BootApplicationStart { @@ -149,9 +149,9 @@ public class BootApplicationStart {
149 149
150 //设置超时时间 150 //设置超时时间
151 HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); 151 HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
152 - httpRequestFactory.setConnectionRequestTimeout(10000);  
153 - httpRequestFactory.setConnectTimeout(10000);  
154 - httpRequestFactory.setReadTimeout(10000); 152 + httpRequestFactory.setConnectionRequestTimeout(3000);
  153 + httpRequestFactory.setConnectTimeout(3000);
  154 + httpRequestFactory.setReadTimeout(5000);
155 restTemplate.setRequestFactory(httpRequestFactory); 155 restTemplate.setRequestFactory(httpRequestFactory);
156 return restTemplate; 156 return restTemplate;
157 } 157 }
@@ -178,9 +178,9 @@ public class BootApplicationStart { @@ -178,9 +178,9 @@ public class BootApplicationStart {
178 restTemplate.getInterceptors().add(java110RestTemplateInterceptor); 178 restTemplate.getInterceptors().add(java110RestTemplateInterceptor);
179 //设置超时时间 179 //设置超时时间
180 HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); 180 HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
181 - httpRequestFactory.setConnectionRequestTimeout(10000);  
182 - httpRequestFactory.setConnectTimeout(10000);  
183 - httpRequestFactory.setReadTimeout(10000); 181 + httpRequestFactory.setConnectionRequestTimeout(3000);
  182 + httpRequestFactory.setConnectTimeout(3000);
  183 + httpRequestFactory.setReadTimeout(5000);
184 restTemplate.setRequestFactory(httpRequestFactory); 184 restTemplate.setRequestFactory(httpRequestFactory);
185 return restTemplate; 185 return restTemplate;
186 } 186 }
springboot/src/main/resources/application-prod.yml
@@ -2,6 +2,10 @@ server: @@ -2,6 +2,10 @@ server:
2 port: 8008 2 port: 8008
3 tomcat: 3 tomcat:
4 uri-encoding: UTF-8 4 uri-encoding: UTF-8
  5 + threads:
  6 + max: 200
  7 + min-spare: 20
  8 + accept-count: 100
5 spring: 9 spring:
6 servlet: 10 servlet:
7 multipart: 11 multipart:
@@ -29,15 +33,15 @@ spring: @@ -29,15 +33,15 @@ spring:
29 activiti: 33 activiti:
30 database-schema-update: false 34 database-schema-update: false
31 datasource: 35 datasource:
32 - url: jdbc:mysql://rm-2zeo2635t3c592h2ywo.mysql.rds.aliyuncs.com:3306/estate?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 36 + url: jdbc:mysql://rm-2zeo2635t3c592h2ywo.mysql.rds.aliyuncs.com:3306/estate?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false&cachePrepStmts=true&useServerPrepStmts=true&cacheCallableStmts=true&prepStmtCacheSize=256&prepStmtCacheSqlLimit=2048&socketTimeout=30000&connectTimeout=10000
33 username: estate 37 username: estate
34 password: MySQL57@123 38 password: MySQL57@123
35 type: com.alibaba.druid.pool.DruidDataSource 39 type: com.alibaba.druid.pool.DruidDataSource
36 driver-class-name: com.mysql.cj.jdbc.Driver 40 driver-class-name: com.mysql.cj.jdbc.Driver
37 druid: 41 druid:
38 - initial-size: 5  
39 - max-active: 20  
40 - min-idle: 5 42 + initial-size: 10
  43 + max-active: 50
  44 + min-idle: 10
41 max-wait: 60000 45 max-wait: 60000
42 46
43 eureka: 47 eureka: