refactor
This commit is contained in:
60
budd-server/pom.xml
Normal file
60
budd-server/pom.xml
Normal file
@@ -0,0 +1,60 @@
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>io.github.ehlxr</groupId>
|
||||
<artifactId>budd</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<artifactId>budd-server</artifactId>
|
||||
<name>budd-server</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.spring4all</groupId>
|
||||
<artifactId>swagger-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.ehlxr</groupId>
|
||||
<artifactId>budd-common</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-08-29 18:32.
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@ServletComponentScan("io.github.ehlxr.filter")
|
||||
public class BuddServerApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BuddServerApplication.class, args);
|
||||
}
|
||||
}
|
141
budd-server/src/main/java/io/github/ehlxr/aop/LogRequestAop.java
Normal file
141
budd-server/src/main/java/io/github/ehlxr/aop/LogRequestAop.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.aop;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import io.github.ehlxr.common.Constant;
|
||||
import io.github.ehlxr.util.JsonUtils;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
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.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 请求日志记录
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-08-17 22:03.
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class LogRequestAop {
|
||||
private static final Logger log = LoggerFactory.getLogger(LogRequestAop.class);
|
||||
|
||||
// private final AliyunLogManager aliyunLogManager;
|
||||
// /**
|
||||
// * aliyun log 配置
|
||||
// */
|
||||
// @Value("${aliyun.log.project:}")
|
||||
// private String projcet;
|
||||
// @Value("${aliyun.log.logstore.request:}")
|
||||
// private String logStore;
|
||||
// @Value("${aliyun.log.topic:}")
|
||||
// private String topic;
|
||||
|
||||
// @Autowired
|
||||
// public LogRequestAop(AliyunLogManager aliyunLogManager) {
|
||||
// this.aliyunLogManager = aliyunLogManager;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 切入点
|
||||
*/
|
||||
@Pointcut("execution(public * io.github.ehlxr.*Controller.*(..)) && !@annotation(io.github.ehlxr.annotations.NoRequestLog)")
|
||||
// @Pointcut("@within(org.springframework.web.bind.annotation.RestController) && !@annotation(com.tzld.piaoquan.incentive.annotations.NoRequestLog)")
|
||||
public void requestLog() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 前置操作
|
||||
*/
|
||||
@Before("requestLog()")
|
||||
public void beforeLog() {
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
|
||||
|
||||
request.setAttribute(Constant.REQUEST_START_TIME, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* 后置操作
|
||||
*/
|
||||
@AfterReturning(pointcut = "requestLog()", returning = "returnValue")
|
||||
public void afterReturning(JoinPoint point, Object returnValue) {
|
||||
logRecord(point, JsonUtils.obj2String(returnValue));
|
||||
}
|
||||
|
||||
@AfterThrowing(pointcut = "requestLog()", throwing = "ex")
|
||||
public void afterThrowing(JoinPoint point, Exception ex) {
|
||||
logRecord(point, ex.getMessage());
|
||||
}
|
||||
|
||||
private void logRecord(JoinPoint point, String message) {
|
||||
try {
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
|
||||
|
||||
Long startTime = (Long) request.getAttribute(Constant.REQUEST_START_TIME);
|
||||
if (Objects.isNull(startTime)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String query = request.getQueryString();
|
||||
String uri = request.getRequestURI();
|
||||
|
||||
Map<String, Object> logMap = new HashMap<>(8);
|
||||
logMap.put("url", Strings.isNullOrEmpty(query) ? uri : uri + "?" + query);
|
||||
logMap.put("method", request.getMethod());
|
||||
logMap.put("header", getHeaders(request));
|
||||
logMap.put("elapsedTime", String.valueOf(System.currentTimeMillis() - startTime));
|
||||
logMap.put("clientIp", request.getRemoteAddr());
|
||||
logMap.put("requestBody", JsonUtils.obj2String(point.getArgs()));
|
||||
logMap.put(Constant.LOG_TRACE_ID, Strings.nullToEmpty(MDC.get(Constant.LOG_TRACE_ID)));
|
||||
logMap.put("responseBody", message);
|
||||
|
||||
// aliyunLogManager.sendLog(projcet, logStore, topic, logMap);
|
||||
} catch (Exception e) {
|
||||
log.error("log report request error", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getHeaders(HttpServletRequest request) {
|
||||
return Collections.list(request.getHeaderNames())
|
||||
.stream()
|
||||
.collect(Collectors.toMap(
|
||||
name -> name,
|
||||
request::getHeader)).toString();
|
||||
}
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
package io.github.ehlxr.config;
|
||||
|
||||
|
||||
import io.github.ehlxr.util.SendAlarmUtil;
|
||||
import io.github.ehlxr.util.Try;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 项目初始化
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2020/4/22.
|
||||
*/
|
||||
@Component
|
||||
public class Initialization implements ApplicationRunner {
|
||||
private static final Logger log = LoggerFactory.getLogger(Initialization.class);
|
||||
|
||||
@Value("${aliyun.oss.endpoint:}")
|
||||
private String endpoint;
|
||||
@Value("${aliyun.oss.accesskey.id:}")
|
||||
private String accessKeyId;
|
||||
@Value("${aliyun.oss.accesskey.secret:}")
|
||||
private String accessKeySecret;
|
||||
@Value("${aliyun.oss.bucket:}")
|
||||
private String bucket;
|
||||
@Value("${aliyun.oss.key-path:}")
|
||||
private String keyPath;
|
||||
@Value("${aliyun.oss.url-lifetime:0}")
|
||||
private Long urlLifetime;
|
||||
|
||||
@Value("${lk.jmeter.cmd:}")
|
||||
private String jmeterCmd;
|
||||
@Value("${location:}")
|
||||
private String location;
|
||||
|
||||
@Value("${lk.dingtalk-url:}")
|
||||
private String dingtalkUrl;
|
||||
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) {
|
||||
// 初始化阿里云 OSS 配置信息
|
||||
// AliyunOssConfig config = AliyunOssConfig.newBuilder()
|
||||
// .endpoint(endpoint)
|
||||
// .accessKeyId(accessKeyId)
|
||||
// .accessKeySecret(accessKeySecret)
|
||||
// .bucketName(bucket)
|
||||
// .keyPath(keyPath)
|
||||
// .urlLifetime(urlLifetime)
|
||||
// .build();
|
||||
// log.info("aliyun oss config {}", config);
|
||||
// FileUploadUtil.init(config);
|
||||
//
|
||||
// if (!"develop".equals(location) && !"PRO2".equals(location)) {
|
||||
// try {
|
||||
// ExecShell.execShellCommand(jmeterCmd);
|
||||
// } catch (Exception e) {
|
||||
// log.error("exec jmeter cmd error {}", e.getMessage());
|
||||
// }
|
||||
// }
|
||||
|
||||
// 预警信息发送初始化
|
||||
Try.of(() -> SendAlarmUtil.init(dingtalkUrl))
|
||||
.trap(e -> log.warn("int SendAlarmUtil error: {}", e.getMessage()))
|
||||
.run();
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.controller;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-08-29 18:45.
|
||||
*/
|
||||
@RestController
|
||||
@Api(tags = "测试辅助接口")
|
||||
public class IndexController {
|
||||
|
||||
/**
|
||||
* 健康检测
|
||||
*/
|
||||
@ApiOperation(value = "健康检测", notes = "健康检测")
|
||||
@GetMapping("/healthcheck")
|
||||
public String healthcheck() {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
package io.github.ehlxr.filter;
|
||||
|
||||
import io.github.ehlxr.common.Constant;
|
||||
import io.github.ehlxr.util.IdUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* auth filter
|
||||
*
|
||||
* @author supeng
|
||||
* @date 2020/08/31
|
||||
*/
|
||||
@Order(value = 1)
|
||||
@WebFilter(filterName = "customFilter", urlPatterns = {"/api/*"})
|
||||
public class CustomFilter implements Filter {
|
||||
private static final Logger log = LoggerFactory.getLogger(CustomFilter.class);
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) {
|
||||
log.info("customFilter init");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
MDC.put(Constant.LOG_TRACE_ID, String.valueOf(IdUtil.localId()));
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
MDC.remove(Constant.LOG_TRACE_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
log.info("customFilter destroy");
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
package io.github.ehlxr.handler;
|
||||
|
||||
import io.github.ehlxr.common.Constant;
|
||||
import io.github.ehlxr.common.Result;
|
||||
import io.github.ehlxr.enums.CodeEnum;
|
||||
import io.github.ehlxr.exception.ServiceDataException;
|
||||
import org.assertj.core.util.Strings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.multipart.MultipartException;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2020/4/20.
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseBody
|
||||
public Result<?> defaultExceptionHandler(HttpServletRequest request, Exception e) {
|
||||
log.error("request: {}, exception: ", request.getRequestURI(), e);
|
||||
|
||||
// SendAlarmUtil.send(String.format("未知异常 request: %s, exception: %s", request.getRequestURI(), ExceptionUtils.getStackTrace(e)),
|
||||
// (t, u) -> log.info("send exception message to dingtalk result {} ", t, u));
|
||||
|
||||
String msg = CodeEnum.UNKNOWN_EXCEPTION.getMessage();
|
||||
String traceId = MDC.get(Constant.LOG_TRACE_ID);
|
||||
if (!Strings.isNullOrEmpty(traceId)) {
|
||||
msg = String.format("%s(%s)", msg, traceId);
|
||||
}
|
||||
|
||||
return Result.of(CodeEnum.UNKNOWN_EXCEPTION.getCode(), null, msg);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ServiceDataException.class)
|
||||
@ResponseBody
|
||||
public Result<?> serviceDataExceptionHandler(HttpServletRequest request, ServiceDataException e) {
|
||||
log.error("request: {} service exception: ", request.getRequestURI(), e);
|
||||
|
||||
// SendAlarmUtil.send(String.format("业务异常 request: %s, service exception: %s", request.getRequestURI(), ExceptionUtils.getStackTrace(e)),
|
||||
// (t, u) -> log.info("send service exception message to dingtalk result {} ", t, u));
|
||||
|
||||
String msg = e.getMessage();
|
||||
String traceId = MDC.get(Constant.LOG_TRACE_ID);
|
||||
if (!Strings.isNullOrEmpty(traceId)) {
|
||||
msg = String.format("%s(%s)", msg, traceId);
|
||||
}
|
||||
|
||||
return Result.of(e.getCode(), null, msg);
|
||||
}
|
||||
|
||||
@ExceptionHandler(MultipartException.class)
|
||||
public String handleError(MultipartException e, RedirectAttributes redirectAttributes) {
|
||||
redirectAttributes.addFlashAttribute("message", e.getCause().getMessage());
|
||||
return "redirect:/uploadStatus";
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.interceptor;
|
||||
|
||||
import io.github.ehlxr.common.Constant;
|
||||
import io.github.ehlxr.util.IdUtil;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 日志 traceid Interceptor
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2020-12-23 11:23.
|
||||
*/
|
||||
public class TraceInterceptor extends HandlerInterceptorAdapter {
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
MDC.put(Constant.LOG_TRACE_ID, String.valueOf(IdUtil.localId()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
||||
MDC.remove(Constant.LOG_TRACE_ID);
|
||||
}
|
||||
}
|
17
budd-server/src/main/resources/application-dev.yml
Normal file
17
budd-server/src/main/resources/application-dev.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
server:
|
||||
port: 8081
|
||||
|
||||
springfox:
|
||||
documentation:
|
||||
enabled: true
|
||||
swagger:
|
||||
base-package: io.github.ehlxr
|
||||
base-path: /**
|
||||
contact:
|
||||
email: xrv@live.com
|
||||
name: rtg
|
||||
url: https://ehlxr.me
|
||||
description: swagger of budd server
|
||||
exclude-path: /error, /ops/**
|
||||
title: budd swagger
|
||||
version: 0.0.1-SNAPSHOT
|
18
budd-server/src/main/resources/application.yml
Normal file
18
budd-server/src/main/resources/application.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
application:
|
||||
name: budd
|
||||
|
||||
server:
|
||||
tomcat:
|
||||
uri-encoding: UTF-8
|
||||
accept-count: 1000
|
||||
connection-timeout: 30000
|
||||
servlet:
|
||||
context-path: /budd
|
||||
session:
|
||||
timeout: 60
|
||||
logging:
|
||||
file:
|
||||
path: /Users/ehlxr/logs/${spring.application.name}
|
264
budd-server/src/main/resources/logback-spring.xml
Normal file
264
budd-server/src/main/resources/logback-spring.xml
Normal file
@@ -0,0 +1,264 @@
|
||||
<?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">
|
||||
<!--<include resource="org/springframework/boot/logging/logback/base.xml"/>-->
|
||||
|
||||
<contextName>logback</contextName>
|
||||
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
|
||||
<!-- <property name="LOG_PATH" value="${logging.file.path}" />-->
|
||||
|
||||
<springProperty name="LOG_PATH" source="logging.file.path"/>
|
||||
<!--<springProperty name="ALIYUN_LOG_ENDPOINT" source="aliyun.log.endpoint"/>-->
|
||||
<!--<springProperty name="ALIYUN_LOG_ACCESSKEYID" source="aliyun.log.accessKeyId"/>-->
|
||||
<!--<springProperty name="ALIYUN_LOG_ACCESSKEYSECRET" source="aliyun.log.accessKeySecret"/>-->
|
||||
<!--<springProperty name="ALIYUN_LOG_PROJECT" source="aliyun.log.project"/>-->
|
||||
<!--<springProperty name="ALIYUN_LOG_LOGSTORE_INFO" source="aliyun.log.logstore.info"/>-->
|
||||
<!--<springProperty name="ALIYUN_LOG_LOGSTORE_ERROR" source="aliyun.log.logstore.error"/>-->
|
||||
|
||||
<!-- 彩色日志 -->
|
||||
<!-- 彩色日志依赖的渲染类 -->
|
||||
<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([%X{logTraceId}]){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
|
||||
<!--<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([%X{√logTraceId}]){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(at %class.%method){cyan} \\(%file:%line\\) %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>-->
|
||||
|
||||
<!--输出到控制台-->
|
||||
<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>
|
||||
|
||||
<!--输出到文件-->
|
||||
<!-- 时间滚动输出 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 [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志归档 -->
|
||||
<fileNamePattern>${LOG_PATH}/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>
|
||||
|
||||
<!-- 时间滚动输出 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 [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 每天日志归档路径以及格式 -->
|
||||
<fileNamePattern>${LOG_PATH}/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>
|
||||
|
||||
<!-- 时间滚动输出 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 [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_PATH}/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>
|
||||
|
||||
<!-- 时间滚动输出 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 [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_PATH}/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>
|
||||
<!--
|
||||
<appender name="ALIYUN_LOG_INFO" class="com.aliyun.openservices.log.logback.LoghubAppender">
|
||||
<endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>
|
||||
<accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>
|
||||
<accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>
|
||||
<project>${ALIYUN_LOG_PROJECT}</project>
|
||||
<logStore>${ALIYUN_LOG_LOGSTORE_INFO}</logStore>
|
||||
|
||||
<totalSizeInBytes>104857600</totalSizeInBytes>
|
||||
<maxBlockMs>0</maxBlockMs>
|
||||
<ioThreadCount>8</ioThreadCount>
|
||||
<batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>
|
||||
<batchCountThreshold>4096</batchCountThreshold>
|
||||
<lingerMs>2000</lingerMs>
|
||||
<retries>10</retries>
|
||||
<baseRetryBackoffMs>100</baseRetryBackoffMs>
|
||||
<maxRetryBackoffMs>50000</maxRetryBackoffMs>
|
||||
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
|
||||
<timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>
|
||||
<timeZone>Asia/Shanghai</timeZone>
|
||||
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
|
||||
<mdcFields>logTraceId</mdcFields>
|
||||
</appender>
|
||||
|
||||
<appender name="ALIYUN_LOG_ERROR" class="com.aliyun.openservices.log.logback.LoghubAppender">
|
||||
<endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>
|
||||
<accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>
|
||||
<accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>
|
||||
<project>${ALIYUN_LOG_PROJECT}</project>
|
||||
<logStore>${ALIYUN_LOG_LOGSTORE_ERROR}</logStore>
|
||||
|
||||
<totalSizeInBytes>104857600</totalSizeInBytes>
|
||||
<maxBlockMs>0</maxBlockMs>
|
||||
<ioThreadCount>8</ioThreadCount>
|
||||
<batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>
|
||||
<batchCountThreshold>4096</batchCountThreshold>
|
||||
<lingerMs>2000</lingerMs>
|
||||
<retries>10</retries>
|
||||
<baseRetryBackoffMs>100</baseRetryBackoffMs>
|
||||
<maxRetryBackoffMs>50000</maxRetryBackoffMs>
|
||||
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
|
||||
<timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>
|
||||
<timeZone>Asia/Shanghai</timeZone>
|
||||
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>ERROR</level>
|
||||
</filter>
|
||||
|
||||
<mdcFields>logTraceId</mdcFields>
|
||||
</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"/>-->
|
||||
<!--
|
||||
使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
|
||||
第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
|
||||
第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
|
||||
-->
|
||||
|
||||
<!--
|
||||
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
|
||||
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
|
||||
不能设置为INHERITED或者同义词NULL。默认是DEBUG
|
||||
可以包含零个或多个元素,标识这个appender将会添加到这个logger。
|
||||
-->
|
||||
|
||||
<springProfile name="dev">
|
||||
<logger name="io.github.ehlxr" level="debug"/>
|
||||
</springProfile>
|
||||
<!--<logger name="com.netflix.discovery.shared.resolver.aws.ConfigClusterResolver" level="warn"/>-->
|
||||
|
||||
<!-- 可用来获取 StatusManager 中的状态 -->
|
||||
<!--<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener"/>-->
|
||||
<!-- 解决 aliyun loghub debug模式下循环发送的问题 -->
|
||||
<logger name="org.apache.http.impl.conn.Wire" level="WARN"/>
|
||||
<!--aliyun loghub 为了防止进程退出时,内存中的数据丢失,请加上此选项-->
|
||||
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
|
||||
|
||||
<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="ALIYUN_LOG_INFO"/>-->
|
||||
<!--<appender-ref ref="ALIYUN_LOG_ERROR"/>-->
|
||||
</root>
|
||||
</configuration>
|
Reference in New Issue
Block a user