[Octopus] modify project to SpringBoot version

This commit is contained in:
zeaslity
2023-06-14 11:21:31 +08:00
parent 6d569b2d3d
commit 282e70d942
64 changed files with 485 additions and 189 deletions

View File

@@ -27,6 +27,10 @@
<artifactId>oshi-core-java11</artifactId>
<version>6.4.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
</dependencies>

View File

@@ -1,13 +1,13 @@
package io.wdd.common;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//import org.springframework.boot.SpringApplication;
//import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CommonApplication {
public static void main(String[] args) {
SpringApplication.run(CommonApplication.class, args);
}
}
//@SpringBootApplication
//public class CommonApplication {
//
// public static void main(String[] args) {
// SpringApplication.run(CommonApplication.class, args);
// }
//
//}

View File

@@ -1,34 +0,0 @@
package io.wdd.common.beans.agent;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class AgentOperationMessage {
/**
* 执行Agent Operation操作的类型
*/
private AgentOperationType opType;
/**
* 需要执行的目标时间,
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime operationTime;
/**
* 期望升级到的目标版本
*/
private String updateVersion;
}

View File

@@ -1,18 +0,0 @@
package io.wdd.common.beans.agent;
public enum AgentOperationType {
// 上报版本信息
VERSION,
// 上报核心信息
INFO,
REBOOT,
UPDATE,
//关键操作,关闭Agent 只能通过此种方式完成
SHUTDOWN
}

View File

@@ -1,76 +0,0 @@
package io.wdd.common.beans.executor;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.wdd.common.utils.TimeUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.time.LocalDateTime;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class ExecutionMessage {
/**
* 2023年2月22日
* 是否需要返回 命令行的处理调用结果
* 通过 MQ返回
*/
@JsonProperty(defaultValue = "false")
boolean needResultReplay;
/**
* 2023年2月22日
* 是否是长时间持续执行任务
*/
@JsonProperty(defaultValue = "false")
boolean durationTask;
/**
* 用于区分 ExecutionMessage的类型
* 直接执行预定函数,则为 Nacos配置中的 方法名称,例如 AgentUpdate AgentReboot
*/
private String type;
/**
* 只有一行的命令行
*/
private List<String> singleLineCommand;
/**
* add in 2023-1-17
* 页面定时脚本任务 需要传递完整的命令列表
*/
private List<List<String>> multiLineCommand;
/**
* 词条执行命令的返回结果在Redis中的ResultKey
*/
private String resultKey;
/**
* 生成 Command结果的 resultKey
*
* @param topicName
* @return
*/
public static String GetResultKey(String topicName) {
return topicName + "-Execution:" + TimeUtils.currentTimeStringFullSplit();
}
/**
* 延迟执行任务执行的Key为未来的生成这个和Key
*
* @param topicName
* @param futureExecutionTime
* @return
*/
public static String GetFutureResultKey(String topicName, LocalDateTime futureExecutionTime) {
return topicName + "-Execution:" + TimeUtils.localDateTimeString(futureExecutionTime);
}
}

View File

@@ -1,40 +0,0 @@
package io.wdd.common.beans.rabbitmq;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class OctopusMessage {
String uuid;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime init_time;
/**
* 执行操作的类型
*/
OctopusMessageType type;
// server send message content
Object content;
// agent reply message content
Object result;
/**
* Agent 完成操作的时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime ac_time;
}

View File

@@ -1,19 +0,0 @@
package io.wdd.common.beans.rabbitmq;
public enum OctopusMessageType {
// agent initialization
INIT,
// important things agent should do with itself
AGENT,
// common shell or order execution
EXECUTOR,
// update or report agent status
STATUS
//
}

View File

@@ -1,48 +0,0 @@
package io.wdd.common.beans.response;
import lombok.Data;
@Data
public class R<T> {
int code;
String msg;
T data;
private R(int code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public R() {
}
public static <T> R<T> ok(T data) {
return resetResult(data, ResultStat.SUCCESS);
}
public static <T> R<T> okNoData() {
return new R();
}
public static <T> R<T> failed(T data) {
return resetResult(data, ResultStat.FAILED);
}
// access from inner
private static <T> R<T> resetResult(T data, ResultStat resultStat) {
return new R(resultStat.getCode(), resultStat.getDescription(), data);
}
// access to public
public static <T> R<T> resetResult(int code, String msg, T data) {
return new R<>(code
, msg, data);
}
}

View File

@@ -1,31 +0,0 @@
package io.wdd.common.beans.response;
public enum ResultStat {
SUCCESS(1000, "success"),
FAILED(5001, "failed"),
VALIDATE_FAILED(1002, "参数校验失败"),
PARAM_ERROR(1003, "请求参数错误!"),
BAD(5001, "all error !");
int code;
String description;
ResultStat(int code, String description){
this.code = code;
this.description = description;
}
public int getCode() {
return code;
}
public String getDescription(){
return description;
}
}

View File

@@ -1,32 +0,0 @@
package io.wdd.common.beans.status;
import lombok.Getter;
import lombok.Setter;
/**
* AgentHealthy状态描述实体类
* Agent存货状态描述
*/
@Getter
public enum AgentHealthyStatusEnum {
FAILED("FAILED", "Agent存活状态为 失败"),
HEALTHY("HEALTHY", "Agent存活状态为 存活"),
UNKNOWN("UNKNOWN", "Agent存活状态 未知");
String status;
String description;
AgentHealthyStatusEnum(String status, String description) {
this.description = description;
this.status = status;
}
}

View File

@@ -1,41 +0,0 @@
package io.wdd.common.beans.status;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class AgentStatus {
private static final String AGENT_STATUS_KEY_SUFFIX = "-Status";
public static String getRedisStatusKey(String agentTopicName) {
return agentTopicName+AGENT_STATUS_KEY_SUFFIX;
}
String time;
String agentName;
String agentTopicName;
CpuInfo cpuInfo;
MemoryInfo memoryInfo;
List<DiskInfo> diskStoreInfo;
List<NetworkInfo> networkInfo;
AgentSystemInfo osInfo;
AppStatusInfo appStatus;
}

View File

@@ -1,48 +0,0 @@
package io.wdd.common.beans.status;
import io.wdd.common.utils.TimeUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import oshi.software.os.OperatingSystem;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class AgentSystemInfo {
String osInfo;
String family;
String manufacturer;
String bootTime;
String upTime;
public static AgentSystemInfo mapFromOHSISystem(OperatingSystem os) {
return AgentSystemInfo.builder()
.osInfo(String.valueOf(os.getVersionInfo()))
.family(os.getFamily())
.manufacturer(os.getManufacturer())
.bootTime(TimeUtils.localDateTimeString(
LocalDateTime.ofInstant(
Instant.ofEpochSecond(os.getSystemBootTime()),
ZoneId.of("UTC+8")
)
))
.upTime(TimeUtils.toRelative(os.getSystemUptime()*1000, 3))
.build();
}
}

View File

@@ -1,28 +0,0 @@
package io.wdd.common.beans.status;
public enum AppStatusEnum {
HEALTHY("Healthy", "app is running"),
FAILURE("Failure", "app is failed"),
NOT_INSTALL("NotInstall", "app not installed");
String name;
String description;
AppStatusEnum(String name, String description) {
this.name = name;
this.description = description;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
}

View File

@@ -1,22 +0,0 @@
package io.wdd.common.beans.status;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.util.Set;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class AppStatusInfo {
Set<String> Healthy;
Set<String> Failure;
Set<String> NotInstall;
}

View File

@@ -1,192 +0,0 @@
package io.wdd.common.beans.status;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import oshi.hardware.CentralProcessor;
import java.text.DecimalFormat;
@AllArgsConstructor
@Data
@NoArgsConstructor
public class CpuInfo {
private static final DecimalFormat LOAD_FORMAT = new DecimalFormat("#.00");
private static final double GHZ_UNIT = 1000000000d;
/**
* CPU总线程
*/
private Integer cpuTotal;
/**
* CPU核心数
*/
private Integer coreTotal;
/**
* CPU总数 计算方式理论上为 cpuTotal * 100
*/
private double cpuUsageTotol;
/**
* CPU系统使用率
*/
private double systemCpuUsage;
/**
* CPU用户使用率
*/
private double userCpuUsage;
/**
* CPU当前等待率
*/
private double wait;
/**
* CPU当前空闲率
*/
private double free;
/**
* CPU型号信息
*/
private CpuModel cpuModel;
private double maxFreq;
private double[] runFreq;
private double[] cpuLoadAverage;
private double[] systemLoadAverage;
public CpuInfo(CentralProcessor processor, long waitingTime) {
this.init(processor, waitingTime);
}
/**
* 获取每个CPU核心的tick计算方式为 100 * tick / totalCpu
*
* @param tick tick
* @param totalCpu CPU总数
* @return 平均每个CPU核心的tick
* @since 5.7.12
*/
private static double formatDouble(long tick, long totalCpu) {
if (0 == totalCpu) {
return 0D;
}
return Double.parseDouble(LOAD_FORMAT.format(tick <= 0 ? 0 : (100d * tick / totalCpu)));
}
private static double formatDouble(double doubleNum) {
return Double.parseDouble(LOAD_FORMAT.format(doubleNum));
}
private static double[] formatCpuLoadAverage(double[] cpuLoadAverage) {
double[] result = new double[cpuLoadAverage.length];
for (int i = 0; i < cpuLoadAverage.length; i++) {
result[i] = formatDouble(cpuLoadAverage[i]);
}
return result;
}
private static double formatCpuFrequency(long freq){
return Double.parseDouble(LOAD_FORMAT.format(freq / GHZ_UNIT));
}
private static double[] formatCpuFrequencyList(long[] freqList){
int length = freqList.length;
double[] result = new double[length];
for (int i = 0; i < length; i++) {
result[i] = formatCpuFrequency(freqList[i]);
}
return result;
}
/**
* 获取指定等待时间内系统CPU 系统使用率、用户使用率、利用率等等 相关信息
*
* @param processor {@link CentralProcessor}
* @param waitingTime 设置等待时间,单位毫秒
* @since 5.7.12
*/
private void init(CentralProcessor processor, long waitingTime) {
final CpuTicks ticks = new CpuTicks(processor, waitingTime);
//this.ticks = ticks;
// base core info
this.cpuTotal = processor.getLogicalProcessorCount();
this.coreTotal = processor.getPhysicalProcessorCount();
// cpu information
this.cpuModel = mapFromProcessorIdentifier(processor.getProcessorIdentifier());
final long totalCpu = ticks.totalCpu();
this.cpuUsageTotol = totalCpu;
// cpu frequency
this.maxFreq = formatCpuFrequency(processor.getMaxFreq());
this.runFreq = formatCpuFrequencyList(processor.getCurrentFreq());
// cpu usage
this.systemCpuUsage = formatDouble(ticks.cSys, totalCpu);
this.userCpuUsage = formatDouble(ticks.user, totalCpu);
this.wait = formatDouble(ticks.ioWait, totalCpu);
this.free = formatDouble(ticks.idle, totalCpu);
// system load average
this.systemLoadAverage = processor.getSystemLoadAverage(3);
// cpu load average
this.cpuLoadAverage = formatCpuLoadAverage(processor.getProcessorCpuLoad(waitingTime));
}
private CpuModel mapFromProcessorIdentifier(CentralProcessor.ProcessorIdentifier id) {
return CpuModel.builder()
.cpu64bit(id.isCpu64bit())
.name(id.getName())
.identifier(id.getIdentifier())
.microArch(id.getMicroarchitecture())
.vendor(id.getVendor())
.build();
}
/**
* CPU型号信息
*/
//private CpuTicks ticks;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
private static class CpuModel {
String name;
String vendor;
String microArch;
boolean cpu64bit;
String identifier;
}
}

View File

@@ -1,100 +0,0 @@
package io.wdd.common.beans.status;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import oshi.hardware.CentralProcessor;
import oshi.util.Util;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CpuTicks {
long idle;
long nice;
long irq;
long softIrq;
long steal;
long cSys;
long user;
long ioWait;
private static int IDLEIndex;
private static int NICEIndex;
private static int IRQIndex;
private static int SOFTIRQIndex;
private static int STEALIndex;
private static int SYSTEMIndex;
private static int USERIndex;
private static int IOWAITIndex;
static {
IDLEIndex = CentralProcessor.TickType.IDLE.getIndex();
NICEIndex = CentralProcessor.TickType.NICE.getIndex();
IRQIndex =CentralProcessor.TickType.IRQ.getIndex();
SOFTIRQIndex = CentralProcessor.TickType.SOFTIRQ.getIndex();
STEALIndex = CentralProcessor.TickType.STEAL.getIndex();
SYSTEMIndex = CentralProcessor.TickType.SYSTEM.getIndex();
USERIndex = CentralProcessor.TickType.USER.getIndex();
IOWAITIndex = CentralProcessor.TickType.IOWAIT.getIndex();
}
/**
* 构造等待时间为用于计算在一定时长内的CPU负载情况如传入1000表示最近1秒的负载情况
*
* @param processor {@link CentralProcessor}
* @param waitingTime 设置等待时间,单位毫秒
*/
public CpuTicks(CentralProcessor processor, long waitingTime) {
// CPU信息
final long[] prevTicks = processor.getSystemCpuLoadTicks();
// 这里必须要设置延迟
Util.sleep(waitingTime);
final long[] ticks = processor.getSystemCpuLoadTicks();
this.idle = tick(prevTicks, ticks, IDLEIndex);
this.nice = tick(prevTicks, ticks, NICEIndex);
this.irq = tick(prevTicks, ticks, IRQIndex);
this.softIrq = tick(prevTicks, ticks, SOFTIRQIndex);
this.steal = tick(prevTicks, ticks, STEALIndex);
this.cSys = tick(prevTicks, ticks, SYSTEMIndex);
this.user = tick(prevTicks, ticks, USERIndex);
this.ioWait = tick(prevTicks, ticks, IOWAITIndex);
}
/**
* 获取CPU总的使用率
*
* @return CPU总使用率
*/
public long totalCpu() {
return Math.max(user + nice + cSys + idle + ioWait + irq + softIrq + steal, 0);
}
/**
* 获取一段时间内的CPU负载标记差
*
* @param prevTicks 开始的ticks
* @param ticks 结束的ticks
* @param tickType tick类型
* @return 标记差
* @since 5.7.12
*/
private static long tick(long[] prevTicks, long[] ticks, int index) {
return ticks[index] - prevTicks[index];
}
}

View File

@@ -1,71 +0,0 @@
package io.wdd.common.beans.status;
import io.wdd.common.utils.FormatUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import oshi.hardware.HWDiskStore;
import java.util.List;
import java.util.stream.Collectors;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class DiskInfo {
String name;
String model;
String serial;
String size;
private List<PartitionInfo> partitionInfoList;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
private static class PartitionInfo{
String path;
String type;
String size;
String mountPoint;
}
public static List<DiskInfo> mapFromDiskStore(List<HWDiskStore> hwDiskStoreList){
return hwDiskStoreList.stream().map(
hwDiskStore -> DiskInfo.builder()
.name(hwDiskStore.getName())
.model(hwDiskStore.getModel())
.serial(hwDiskStore.getSerial())
.size(FormatUtils.formatData(hwDiskStore.getSize()))
.partitionInfoList(
// partition should also be got from stream
hwDiskStore.getPartitions().stream().map(partition -> DiskInfo.PartitionInfo.builder()
.path(partition.getIdentification())
.size(FormatUtils.formatData(partition.getSize()))
.type(partition.getType())
.mountPoint(partition.getMountPoint())
.build()
).collect(Collectors.toList())
)
.build()
).collect(Collectors.toList());
}
}

View File

@@ -1,47 +0,0 @@
package io.wdd.common.beans.status;
import io.wdd.common.utils.FormatUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import oshi.hardware.GlobalMemory;
import oshi.hardware.VirtualMemory;
@NoArgsConstructor
@AllArgsConstructor
@Data
@SuperBuilder(toBuilder = true)
public class MemoryInfo {
String total;
String usage;
String available;
String memoryType;
String swapTotal;
String swapAvailable;
String swapUsage;
public static MemoryInfo build(GlobalMemory memory) {
VirtualMemory virtualMemory = memory.getVirtualMemory();
return MemoryInfo.builder()
.memoryType(memory.getPhysicalMemory().get(0).getMemoryType())
.total(FormatUtils.formatData(memory.getTotal()))
.available(FormatUtils.formatData(memory.getAvailable()))
.usage(FormatUtils.formatData(memory.getTotal() - memory.getAvailable()))
.swapTotal(FormatUtils.formatData(virtualMemory.getSwapTotal()))
.swapUsage(FormatUtils.formatData(virtualMemory.getSwapUsed()))
.swapAvailable(FormatUtils.formatData(virtualMemory.getSwapTotal() - virtualMemory.getSwapUsed()))
.build();
}
}

View File

@@ -1,18 +0,0 @@
package io.wdd.common.beans.status;
import lombok.Data;
/**
* 没时间整这些,反正大一点数据也无所谓 不是吗
*/
@Deprecated
@Data
public class MetricStatus {
CpuInfo cpuInfo;
MemoryInfo memoryInfo;
AppStatusInfo appStatus;
}

View File

@@ -1,108 +0,0 @@
package io.wdd.common.beans.status;
import io.wdd.common.utils.FormatUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import oshi.hardware.NetworkIF;
import java.util.List;
import java.util.stream.Collectors;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class NetworkInfo {
private String name;
private String displayName;
private String macAddr;
private String mtu;
private String[] innerIpv4Addr;
private String publicIpv4Addr;
private String[] innerIpv6Addr;
private String publicIpv6Addr;
/**
* 过去1s内的网速接收速率
*/
private String recvSpeed;
/**
* 过去1s内的网速发送速率
*/
private String sendSpeed;
private String trafficRecv;
private String trafficSend;
public static NetworkInfo mapFromNetworkIF(NetworkIF networkIF) {
return NetworkInfo
.builder()
.name(networkIF.getName())
.displayName(networkIF.getDisplayName())
.mtu(String.valueOf(networkIF.getMTU()))
.macAddr(networkIF.getMacaddr())
.innerIpv4Addr(generateIPDICRFromNetworkIFList(
networkIF,
4
))
.innerIpv6Addr(generateIPDICRFromNetworkIFList(
networkIF,
6
))
.trafficSend(FormatUtils.formatData(networkIF.getBytesSent()))
.trafficRecv(FormatUtils.formatData(networkIF.getBytesRecv())
)
.build();
}
public static List<NetworkInfo> mapFromNetworkIFS(List<NetworkIF> networkIFList) {
return networkIFList
.stream()
.map(
networkIF -> NetworkInfo
.builder()
.name(networkIF.getName())
.displayName(networkIF.getDisplayName())
.mtu(String.valueOf(networkIF.getMTU()))
.macAddr(networkIF.getMacaddr())
.innerIpv4Addr(generateIPDICRFromNetworkIFList(
networkIF,
4
))
.innerIpv6Addr(generateIPDICRFromNetworkIFList(
networkIF,
6
))
.trafficSend(FormatUtils.formatData(networkIF.getBytesSent()))
.trafficRecv(FormatUtils.formatData(networkIF.getBytesRecv())
)
.build())
.collect(Collectors.toList());
}
private static String[] generateIPDICRFromNetworkIFList(NetworkIF networkIF, int Ipv4OrIpv6) {
String[] iPAddr;
Short[] subnetMasks;
if (Ipv4OrIpv6 == 4) {
iPAddr = networkIF.getIPv4addr();
subnetMasks = networkIF.getSubnetMasks();
} else {
iPAddr = networkIF.getIPv6addr();
subnetMasks = networkIF.getPrefixLengths();
}
String[] result = new String[iPAddr.length];
for (int index = 0; index < iPAddr.length; index++) {
result[index] = iPAddr[index] + "/" + subnetMasks[index];
}
return result;
}
}

View File

@@ -1,36 +0,0 @@
package io.wdd.common.beans.status;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder(toBuilder = true)
public class OctopusStatusMessage {
// below two will be used by both server and agent
// 存储所有Agent的实时健康状态 1代表健康 0代表失败
public static final String ALL_AGENT_STATUS_REDIS_KEY = "ALL_AGENT_HEALTHY_STATUS";
public static final String HEALTHY_STATUS_MESSAGE_TYPE = "ping";
public static final String ALL_STATUS_MESSAGE_TYPE = "all";
public static final String METRIC_STATUS_MESSAGE_TYPE = "metric";
public static final String APP_STATUS_MESSAGE_TYPE = "app";
/**
* which kind of status should be return
* metric => short time message
* all => all agent status message
* healthy => check for healthy
* */
String type;
String agentTopicName;
int metricRepeatCount;
int metricRepeatPinch;
}

View File

@@ -1,264 +0,0 @@
package io.wdd.common.handler;
import com.google.common.collect.Maps;
import io.wdd.common.beans.response.R;
import io.wdd.common.beans.response.ResultStat;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.support.ListenerExecutionFailedException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.*;
/**
* 自定义 全局异常处理类
* 全局处理响应数据的全局处理类继承ResponseBodyAdvice接口重写其中的方法
* (带有@RequestMapping注解的方法上抛出的异常都会拦截在此统一处理并统一返回数据格式
*/
@RestControllerAdvice
@Slf4j(topic = "Global Exception")
public class GlobalExceptionHandler {
@Autowired
private MyMessageSource messageSource;
/**
* 全局异常拦截方法
* 这里拦截此异常,将异常中的信息提取返回有效信息!
*
* @param e SpringBoot参数校验(valid)过程中,检验失败会产生此异常,在此处拦截
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public R<Object> MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
// 从异常对象中拿到ObjectError对象获取所有的错误信息
List<ObjectError> objectError = e
.getBindingResult()
.getAllErrors();
// 然后提取错误提示信息进行返回
HashMap<Integer, String> errorMap = new HashMap<>();
objectError.forEach(objectError1 -> errorMap.put(
objectError.indexOf(objectError1),
objectError1.getDefaultMessage()
));
// 使用标准化返回体返回数据
return R.resetResult(
ResultStat.VALIDATE_FAILED.getCode(),
ResultStat.VALIDATE_FAILED.getDescription(),
errorMap
);
//return errorMap;
}
/**
* @param exception 参数类型错误,拦截器
* @return
*/
@ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
public Object methodArgumentNotValidException(MethodArgumentTypeMismatchException exception) {
//按需重新封装需要返回的错误信息
Map<String, String> invalidMap = new LinkedHashMap(99);
//解析原错误信息,封装后返回,此处返回非法的字段名称,原始值,错误信息
invalidMap.put(
exception
.getParameter()
.getParameterName(),
ResultStat.PARAM_ERROR.getDescription()
);
R<Map<String, String>> vo = new R<>();
vo.setCode(ResultStat.PARAM_ERROR.getCode());
vo.setMsg(getLocaleMsg(ResultStat.PARAM_ERROR.getDescription()));
vo.setData(invalidMap);
log.debug(
exception.getMessage(),
exception
);
return vo;
}
/**
* 处理此种异常
*
* @param httpRequestMethodNotSupportedException
*/
@ExceptionHandler(value = {HttpRequestMethodNotSupportedException.class})
public void methodNotMatchHandler(HttpRequestMethodNotSupportedException httpRequestMethodNotSupportedException) {
log.error(
httpRequestMethodNotSupportedException.getMessage()
);
}
@ExceptionHandler(value = {ListenerExecutionFailedException.class})
public void listenerExecutionFailedExceptionHandler(ListenerExecutionFailedException e) {
log.error(e.getMessage());
}
/**
* 拦截数据库异常
*
* @param exception 数据库异常
* @return
*/
@ExceptionHandler(value = {SQLException.class, DuplicateKeyException.class})
public R<String> sqlExceptionHandler(SQLException exception) {
R<String> vo = new R<>();
vo.setCode(ResultStat.PARAM_ERROR.getCode());
vo.setMsg(getLocaleMsg(ResultStat.PARAM_ERROR.getDescription()));
if (exception instanceof SQLIntegrityConstraintViolationException) {
vo.setData("Data already exsit ! 操作失败!");
} else {
vo.setData("数据库异常,操作失败!");
}
log.debug(
exception.getMessage(),
exception
);
return vo;
}
@ExceptionHandler(MyRuntimeException.class)
public R<Object> interceptMyRuntimeE(MyRuntimeException exception) {
R<Object> R = new R<>();
ResultStat status = exception.getStatus();
if (status != null) {
R.setMsg(getLocaleMsg(
exception.getMessage(),
exception.getParams()
));
R.setCode(status.getCode());
R.setData(exception.getData());
} else {
R.setCode(ResultStat.FAILED.getCode());
R.setMsg(getLocaleMsg(
exception.getMessage(),
exception.getParams()
));
R.setData(null);
}
return R;
}
// /**
// *
// * 统一Spring Security的认证错误
// * */
// @ExceptionHandler(value = BadCredentialsException.class)
// public R<Object> badCredentialsException(BadCredentialsException exception){
//
// log.error(exception.getDescription());
//
// return R.failed(ResultStat.USER_AUTH_FAILED);
// }
/**
* validate 验证错误handle
*/
@ExceptionHandler(value = BindException.class)
public Object bindExceptionHandler(BindException exception) {
//按需重新封装需要返回的错误信息
Map<String, String> invalidMap = Maps.newLinkedHashMap();
//解析原错误信息,封装后返回,此处返回非法的字段名称,原始值,错误信息
if (exception != null) {
List<FieldError> fieldErrors = exception
.getBindingResult()
.getFieldErrors();
fieldErrors
.stream()
.sorted(Comparator.comparing(FieldError::getCode))
.forEach(error -> {
String defaultMessage = error.getDefaultMessage();
String finalMessage = defaultMessage;
if (defaultMessage != null && defaultMessage.startsWith("{") && defaultMessage.endsWith("}")) {
finalMessage = messageSource.getMessage(defaultMessage.substring(
1,
defaultMessage.length() - 1
));
}
if (StringUtils.isNotEmpty(invalidMap.get(error.getField()))) {
invalidMap.put(
error.getField(),
invalidMap.get(error.getField()) + "," + finalMessage
);
} else {
invalidMap.put(
error.getField(),
finalMessage
);
}
});
}
R<Map<String, String>> vo = new R<>();
vo.setCode(ResultStat.VALIDATE_FAILED.getCode());
vo.setMsg(getLocaleMsg(ResultStat.VALIDATE_FAILED.getDescription()));
vo.setData(invalidMap);
log.debug(
exception.getMessage(),
exception
);
return vo;
}
/**
* 默认异常统一处理 Exception
*/
@ExceptionHandler(value = Exception.class)
public Object exceptionHandel(Exception e) {
return getResponseVO(
e,
getLocaleMsg("系统错误,请联系管理员")
);
}
private Object getResponseVO(Exception e, String msg) {
R<String> R = new R<>();
R.setCode(ResultStat.FAILED.getCode());
R.setMsg(msg);
R.setMsg(e.getMessage());
// 此处修改不要打印 错误 e
log.error(
e.getMessage(),
e
);
return R;
}
private String getLocaleMsg(String msgCode, Object... params) {
return messageSource.getMessage(
msgCode,
params
);
}
}

View File

@@ -1,69 +0,0 @@
package io.wdd.common.handler;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Locale;
@Component
public class MyMessageSource {
@Resource
private MessageSource messageSource;
public MyMessageSource() {
}
public String getMessage(String code, Object... params) {
return this.getMessage(code, (Object[])null, params);
}
public String getMessageIgnoreMissMatch(String code, Object... params) {
Locale locale = LocaleContextHolder.getLocale();
String message = this.messageSource.getMessage(code, (Object[])null, code, locale);
return this.parse(message, true, params);
}
public String getMessage(String code, Object[] args, Object... params) {
return this.getMessage(code, args, code, params);
}
public String getMessage(String code, Object[] args, String defaultMessage, Object... params) {
Locale locale = LocaleContextHolder.getLocale();
String message = this.messageSource.getMessage(code, args, defaultMessage, locale);
return this.parse(message, false, params);
}
private String parse(String s, boolean ingoreParamsMissMath, Object... params) {
if (s == null) {
return null;
} else if (params == null) {
return s;
} else {
String[] splits = s.split("\\{}", -1);
if (splits.length != params.length + 1) {
if (ingoreParamsMissMath) {
return s;
} else {
throw new IllegalArgumentException("The number of parameters is inconsistent with the parameter value");
}
} else if (splits.length == 1) {
return s;
} else {
StringBuilder stringBuilder = new StringBuilder();
for(int i = 0; i < splits.length; ++i) {
String split = splits[i];
stringBuilder.append(split);
if (i < params.length) {
stringBuilder.append(params[i]);
}
}
return stringBuilder.toString();
}
}
}
}

View File

@@ -1,43 +0,0 @@
package io.wdd.common.handler;
import io.wdd.common.beans.response.ResultStat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyRuntimeException extends RuntimeException {
private Object data;
private ResultStat status;
private Object[] params;
public MyRuntimeException(String msg) {
super(msg);
}
public MyRuntimeException(String msg, Object... params) {
super(msg);
this.params = params;
}
public MyRuntimeException(ResultStat status, Object data, String msg, Object... params) {
super(msg == null ? status.getDescription() : msg);
this.data = data;
this.status = status;
this.params = params;
}
public MyRuntimeException(Throwable cause) {
super(cause);
}
public MyRuntimeException(Throwable cause, String msg) {
super(msg, cause);
}
}

View File

@@ -1,64 +0,0 @@
package io.wdd.common.utils;
import org.springframework.util.unit.DataSize;
/**
* 数据单位封装<p>
* 此类来自于Spring-framework
*
* <pre>
* BYTES 1B 2^0 1
* KILOBYTES 1KB 2^10 1,024
* MEGABYTES 1MB 2^20 1,048,576
* GIGABYTES 1GB 2^30 1,073,741,824
* TERABYTES 1TB 2^40 1,099,511,627,776
* </pre>
*
* @author Sam BrannenStephane Nicoll
* @since 5.3.10
*/
public enum DataUnit {
/**
* Bytes, 后缀表示为: {@code B}.
*/
BYTES("B", DataSize.ofBytes(1)),
/**
* Kilobytes, 后缀表示为: {@code KB}.
*/
KILOBYTES("KB", DataSize.ofKilobytes(1)),
/**
* Megabytes, 后缀表示为: {@code MB}.
*/
MEGABYTES("MB", DataSize.ofMegabytes(1)),
/**
* Gigabytes, 后缀表示为: {@code GB}.
*/
GIGABYTES("GB", DataSize.ofGigabytes(1)),
/**
* Terabytes, 后缀表示为: {@code TB}.
*/
TERABYTES("TB", DataSize.ofTerabytes(1));
public static final String[] UNIT_NAMES = new String[]{"B", "KB", "MB", "GB", "TB", "PB", "EB"};
private final String suffix;
private final DataSize size;
DataUnit(String suffix, DataSize size) {
this.suffix = suffix;
this.size = size;
}
DataSize size() {
return this.size;
}
}

View File

@@ -1,33 +0,0 @@
package io.wdd.common.utils;
import java.text.DecimalFormat;
public class FormatUtils {
/**
* 格式化输出百分比
*
* @param rate
* @return
*/
public static String formatRate(double rate) {
return new DecimalFormat("#.##%").format(rate);
}
/**
* 格式化输出大小 B/KB/MB...
*
* @param size
* @return
*/
public static String formatData(long size) {
if (size <= 0L) {
return "0B";
} else {
int digitGroups = Math.min(DataUnit.UNIT_NAMES.length - 1, (int) (Math.log10((double) size) / Math.log10(1024.0D)));
return (new DecimalFormat("#,##0.##")).format((double) size / Math.pow(1024.0D, digitGroups)) + " " + DataUnit.UNIT_NAMES[digitGroups];
}
}
}

View File

@@ -1,117 +0,0 @@
package io.wdd.common.utils;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class FunctionReader {
public static List<List<String>> ReadFileToCommandList(String functionFilePath) {
// https://www.digitalocean.com/community/tutorials/java-read-file-line-by-line
List<List<String>> result = null;
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(functionFilePath));
result = doReadContent(
result,
bufferedReader
);
} catch (IOException e) {
throw new RuntimeException(e);
}
return result;
}
public static List<List<String>> ReadStringToCommandList(String functionContent) {
List<List<String>> result = null;
try {
// 构造一个 buffered Reader
BufferedReader bufferedReader = new BufferedReader(
new StringReader(functionContent)
);
// 执行read操作
result = doReadContent(
result,
bufferedReader
);
} catch (IOException e) {
throw new RuntimeException(e);
}
return result;
}
/**
* 实际解析从前端传入的 脚本命令, 将其转换为 List<List<String>>
*
* @param result
* @param bufferedReader
* @return
* @throws IOException
*/
private static List<List<String>> doReadContent(List<List<String>> result, BufferedReader bufferedReader) throws IOException {
String line = bufferedReader.readLine();
if (line != null) {
result = new ArrayList<>(64);
}
while (line != null) {
if (!StringUtils.isEmpty(line)) {
result.add(SplitSpaceIndentToCommandList(line));
}
line = bufferedReader.readLine();
}
return result;
}
public static List<String> SplitSpaceIndentToCommandList(String commandLine) {
return Arrays
.stream(commandLine
.split(" "))
.collect(Collectors.toList());
}
public static List<String> SplitCommaIndentToCommandList(String commandLine) {
// 需要进行归一化,去除掉多余的空格
return Arrays
.stream(commandLine.split(","))
.map(
split -> split.replace(
" ",
""
)
)
.collect(Collectors.toList());
}
}

View File

@@ -1,32 +0,0 @@
package io.wdd.common.utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.wdd.common.beans.rabbitmq.OctopusMessage;
import io.wdd.common.handler.MyRuntimeException;
import org.springframework.amqp.core.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class MessageUtils {
@Autowired
ObjectMapper objectMapper;
public static OctopusMessage convert(Message message) {
OctopusMessage octopusMessage;
ObjectMapper objectMapper = new ObjectMapper();
try {
octopusMessage = objectMapper.readValue(message.getBody(), OctopusMessage.class);
} catch (IOException e) {
throw new MyRuntimeException(e.getMessage());
}
return octopusMessage;
}
}

View File

@@ -1,41 +0,0 @@
package io.wdd.common.utils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Configuration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Configuration
public class OctopusObjectMapperConfig {
public static Jackson2ObjectMapperBuilderCustomizer common() {
return jacksonObjectMapperBuilder -> {
//若POJO对象的属性值为null序列化时不进行显示
jacksonObjectMapperBuilder.serializationInclusion(JsonInclude.Include.NON_NULL);
//针对于Date类型文本格式化
jacksonObjectMapperBuilder.simpleDateFormat("yyyy-MM-dd");
//
jacksonObjectMapperBuilder.failOnEmptyBeans(false);
jacksonObjectMapperBuilder.failOnUnknownProperties(false);
jacksonObjectMapperBuilder.autoDetectFields(true);
//针对于JDK新时间类。序列化时带有T的问题自定义格式化字符串
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
jacksonObjectMapperBuilder.modules(javaTimeModule);
};
}
}

View File

@@ -1,37 +0,0 @@
package io.wdd.common.utils;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
@Deprecated
public class OctopusRabbitTemplateConfig {
@Resource
RabbitTemplate rabbitTemplate;
@Bean
public MessageConverter octopusMessageConverter() {
JsonMapper jsonMapper = new JsonMapper();
jsonMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
return new Jackson2JsonMessageConverter(jsonMapper,
"io.wdd.common.beans.rabbitmq");
}
@Bean
public AmqpTemplate OctopusRabbitTemplate(ConnectionFactory connectionFactory) {
rabbitTemplate.setMessageConverter(octopusMessageConverter());
return rabbitTemplate;
}
}

View File

@@ -1,231 +0,0 @@
package io.wdd.common.utils;
import org.apache.commons.lang3.ObjectUtils;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class TimeUtils {
private static final ZoneId SYSTEM_TIME_ZONE_ID = ZoneId.of("UTC+8");
/**
* https://memorynotfound.com/calculate-relative-time-time-ago-java/
* <p>
* calculate relative time from now on
* like 5 days, 3 hours, 16 minutes level 3
*/
private static final Map<String, Long> times = new LinkedHashMap<>();
private static final String FULL_SPLIT_TIME_FORMAT = "yyyy-MM-dd-HH-mm-ss";
private static final String COMMON_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
/**
* 在五秒误差内的一个统一时间
*/
private static LocalDateTime UNIFORM_TIME;
static {
times.put(
"year",
TimeUnit.DAYS.toMillis(365)
);
times.put(
"month",
TimeUnit.DAYS.toMillis(30)
);
times.put(
"week",
TimeUnit.DAYS.toMillis(7)
);
times.put(
"day",
TimeUnit.DAYS.toMillis(1)
);
times.put(
"hour",
TimeUnit.HOURS.toMillis(1)
);
times.put(
"minute",
TimeUnit.MINUTES.toMillis(1)
);
times.put(
"second",
TimeUnit.SECONDS.toMillis(1)
);
}
public static ByteBuffer currentTimeByteBuffer() {
byte[] timeBytes = LocalDateTime
.now(SYSTEM_TIME_ZONE_ID)
.format(DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT))
.getBytes(StandardCharsets.UTF_8);
return ByteBuffer.wrap(timeBytes);
}
public static LocalDateTime currentTime() {
return LocalDateTime.now(SYSTEM_TIME_ZONE_ID);
}
/**
* @return 获取五秒时间误差内的统一时间
*/
public static String UniformFormatTimeString() {
if (ObjectUtils.isEmpty(UNIFORM_TIME)) {
UNIFORM_TIME = currentTime();
return currentFormatTimeString();
}
// 旧的时间和新时间之家误差小于5秒那么使用同一个时间
if (UNIFORM_TIME
.plusSeconds(5)
.isAfter(currentTime())) {
UNIFORM_TIME = currentTime();
}
return localDateTimeFormatString(UNIFORM_TIME);
}
/**
* @return 格式化 去掉时间中的毫秒数
*/
public static LocalDateTime currentFormatTime() {
DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT);
String format = LocalDateTime
.now(SYSTEM_TIME_ZONE_ID)
.format(ofPattern);
return LocalDateTime.parse(format, ofPattern);
}
/**
* @return UTC+8 [ yyyy-MM-dd-HH-mm-ss ] Time String
*/
public static String currentFormatTimeString() {
return currentFormatTime()
.format(DateTimeFormatter.ofPattern(FULL_SPLIT_TIME_FORMAT));
}
public static LocalDateTime cvFromDate(Date date) {
// fix bug
if (null == date) {
return null;
}
return LocalDateTime.ofInstant(date.toInstant(),
SYSTEM_TIME_ZONE_ID);
}
/**
* @return UTC+8 [ yyyy-MM-dd HH:mm:ss ] Time String
*/
public static String currentTimeString() {
return LocalDateTime
.now(SYSTEM_TIME_ZONE_ID)
.format(DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT));
}
/**
* @return UTC+8 [ yyyy-MM-dd-HH-mm-ss ] Time String
*/
public static String currentTimeStringFullSplit() {
return LocalDateTime
.now(SYSTEM_TIME_ZONE_ID)
.format(DateTimeFormatter.ofPattern(FULL_SPLIT_TIME_FORMAT));
}
/**
* 输出格式为 COMMON_TIME_FORMAT "yyyy-MM-dd HH:mm:ss"
*
* @param time
* @return
*/
public static String localDateTimeString(LocalDateTime time) {
return time.format(DateTimeFormatter.ofPattern(COMMON_TIME_FORMAT));
}
/**
* 输出格式为 FULL_SPLIT_TIME_FORMAT "yyyy-MM-dd-HH-mm-ss"
*
* @param time
* @return
*/
public static String localDateTimeFormatString(LocalDateTime time) {
return time.format(DateTimeFormatter.ofPattern(FULL_SPLIT_TIME_FORMAT));
}
public static String toRelative(long duration, int maxLevel) {
StringBuilder res = new StringBuilder();
int level = 0;
for (Map.Entry<String, Long> time : times.entrySet()) {
long timeDelta = duration / time.getValue();
if (timeDelta > 0) {
res
.append(timeDelta)
.append(" ")
.append(time.getKey())
.append(timeDelta > 1 ? "s" : "")
.append(", ");
duration -= time.getValue() * timeDelta;
level++;
}
if (level == maxLevel) {
break;
}
}
if ("".equals(res.toString())) {
return "0 seconds ago";
} else {
res.setLength(res.length() - 2);
res.append(" ago");
return res.toString();
}
}
public static String toRelative(long duration) {
return toRelative(
duration,
times.size()
);
}
public static String toRelative(Date start, Date end) {
assert start.after(end);
return toRelative(end.getTime() - start.getTime());
}
public static String toRelative(Date start, Date end, int level) {
assert start.after(end);
return toRelative(
end.getTime() - start.getTime(),
level
);
}
}