parent
37b57fa577
commit
19605826f8
7
pom.xml
7
pom.xml
|
@ -130,6 +130,13 @@
|
||||||
<version>6.1.5</version>
|
<version>6.1.5</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>mockwebserver</artifactId>
|
||||||
|
<version>4.12.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package com.cmhi.magent.annotation.impl;
|
package com.cmhi.magent.annotation.impl;
|
||||||
|
|
||||||
import com.cmhi.magent.annotation.AutoExternString;
|
import com.cmhi.magent.annotation.AutoExternString;
|
||||||
|
import com.cmhi.magent.common.BaseEnum;
|
||||||
|
import com.cmhi.magent.common.ErrorCode;
|
||||||
import com.cmhi.magent.common.UtilsFormatType;
|
import com.cmhi.magent.common.UtilsFormatType;
|
||||||
|
import com.cmhi.magent.exception.CommonErrorCodeException;
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
import com.fasterxml.jackson.databind.BeanProperty;
|
import com.fasterxml.jackson.databind.BeanProperty;
|
||||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
|
||||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
|
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
|
||||||
|
@ -12,7 +14,6 @@ import org.springframework.boot.jackson.JsonComponent;
|
||||||
import oshi.util.FormatUtil;
|
import oshi.util.FormatUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code AutoExternStringJsonProcess} 是一个 Jackson 自定义序列化器,用于处理 {@link AutoExternString} 注解的字段。
|
* {@code AutoExternStringJsonProcess} 是一个 Jackson 自定义序列化器,用于处理 {@link AutoExternString} 注解的字段。
|
||||||
|
@ -148,18 +149,34 @@ public class AutoExternStringJsonProcess extends JsonSerializer<Number> implemen
|
||||||
jsonGenerator.writeString(formattedValue);
|
jsonGenerator.writeString(formattedValue);
|
||||||
} else if (formatType == UtilsFormatType.FORMAT_ENUM) {
|
} else if (formatType == UtilsFormatType.FORMAT_ENUM) {
|
||||||
try {
|
try {
|
||||||
// 将字段值转换为枚举实例
|
if (!enumClass.isEnum()) {
|
||||||
Method fromValueMethod = enumClass.getMethod("fromValue", int.class);
|
throw new CommonErrorCodeException(ErrorCode.ERR_PARAMS);
|
||||||
Enum<?> enumInstance = (Enum<?>) fromValueMethod.invoke(null, (int) value);
|
}
|
||||||
|
|
||||||
|
int index = (int) value;
|
||||||
|
|
||||||
|
if (index < 0 || index >= enumClass.getEnumConstants().length) {
|
||||||
|
throw new CommonErrorCodeException(ErrorCode.ERR_NOSUCHITEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isBaseEnumImplemented = false;
|
||||||
|
for (Class<?> iface : enumClass.getInterfaces()) {
|
||||||
|
if (iface.equals(BaseEnum.class)) {
|
||||||
|
isBaseEnumImplemented = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBaseEnumImplemented) {
|
||||||
|
BaseEnum baseEnum = (BaseEnum) enumClass.getEnumConstants()[index];
|
||||||
|
jsonGenerator.writeString(baseEnum.getDescription());
|
||||||
|
} else {
|
||||||
|
jsonGenerator.writeString(enumClass.getEnumConstants()[index].toString());
|
||||||
|
}
|
||||||
|
|
||||||
// 调用枚举实例的描述方法
|
|
||||||
Method method = enumClass.getMethod("getDescription");
|
|
||||||
String description = (String) method.invoke(enumInstance);
|
|
||||||
|
|
||||||
// 写入描述字符串
|
|
||||||
jsonGenerator.writeString(description);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException("Failed to convert enum value to description", e);
|
throw new CommonErrorCodeException(ErrorCode.ERR_NOSUCHITEM);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
jsonGenerator.writeString(numericValue.toString());
|
jsonGenerator.writeString(numericValue.toString());
|
||||||
|
@ -188,8 +205,12 @@ public class AutoExternStringJsonProcess extends JsonSerializer<Number> implemen
|
||||||
AutoExternString annotation = property.getAnnotation(AutoExternString.class);
|
AutoExternString annotation = property.getAnnotation(AutoExternString.class);
|
||||||
if (annotation != null) {
|
if (annotation != null) {
|
||||||
// 根据注解配置创建新的序列化器
|
// 根据注解配置创建新的序列化器
|
||||||
return new AutoExternStringJsonProcess(annotation.prefix(), annotation.suffix(), annotation.format(), annotation.units(),
|
return new AutoExternStringJsonProcess(annotation.prefix(),
|
||||||
annotation.enumClass(), true);
|
annotation.suffix(),
|
||||||
|
annotation.format(),
|
||||||
|
annotation.units(),
|
||||||
|
annotation.enumClass(),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 如果字段不存在注解,返回默认实例
|
// 如果字段不存在注解,返回默认实例
|
||||||
|
|
|
@ -71,8 +71,7 @@ public final class ConstValue {
|
||||||
* <li>简化形式的IPv6地址:如 {@code ::1} 或 {@code 2001:db8::1}</li>
|
* <li>简化形式的IPv6地址:如 {@code ::1} 或 {@code 2001:db8::1}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public static final String IP_ADDRESS_REGEX =
|
public static final String IP_ADDRESS_REGEX = "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$" +
|
||||||
"^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$" +
|
|
||||||
"|^([\\da-fA-F]{1,4}:){7}[\\da-fA-F]{1,4}$" +
|
"|^([\\da-fA-F]{1,4}:){7}[\\da-fA-F]{1,4}$" +
|
||||||
"|^::([\\da-fA-F]{1,4}:){0,6}[\\da-fA-F]{1,4}$" +
|
"|^::([\\da-fA-F]{1,4}:){0,6}[\\da-fA-F]{1,4}$" +
|
||||||
"|^([\\da-fA-F]{1,4}:){1,7}:$" +
|
"|^([\\da-fA-F]{1,4}:){1,7}:$" +
|
||||||
|
|
|
@ -148,8 +148,10 @@ public class CommonConfigure {
|
||||||
*/
|
*/
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
private void initGlobalValue() {
|
private void initGlobalValue() {
|
||||||
log.info("Current: tokenExpiredOfSeconds = {}, allowPasswdRetryTimes = {}, showSqlCommand = {}", tokenExpiredOfSeconds,
|
log.info("Current: tokenExpiredOfSeconds = {}, allowPasswdRetryTimes = {}, showSqlCommand = {}",
|
||||||
allowPasswdRetryTimes, showSqlCommand);
|
tokenExpiredOfSeconds,
|
||||||
|
allowPasswdRetryTimes,
|
||||||
|
showSqlCommand);
|
||||||
|
|
||||||
String addr = "localhost";
|
String addr = "localhost";
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -109,8 +109,12 @@ public class PlatformServiceConfig {
|
||||||
HttpClient httpClient = HttpClient.create().responseTimeout(Duration.ofSeconds(requestTimeout));
|
HttpClient httpClient = HttpClient.create().responseTimeout(Duration.ofSeconds(requestTimeout));
|
||||||
|
|
||||||
// 构建 WebClient
|
// 构建 WebClient
|
||||||
return builder.baseUrl(platformUrl).defaultHeader("Content-Type", "application/json").clientConnector(
|
return builder.baseUrl(platformUrl)
|
||||||
new ReactorClientHttpConnector(httpClient)).filter(logRequest()).filter(logResponse()).build();
|
.defaultHeader("Content-Type", "application/json")
|
||||||
|
.clientConnector(new ReactorClientHttpConnector(httpClient))
|
||||||
|
.filter(logRequest())
|
||||||
|
.filter(logResponse())
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -93,7 +93,8 @@ public class ProtocolConfigure {
|
||||||
private void initGlobalValue() {
|
private void initGlobalValue() {
|
||||||
log.info("Current: checkTimestamp = {}, timeoutOfSeconds = {}", checkTimestamp, timeoutOfSeconds);
|
log.info("Current: checkTimestamp = {}, timeoutOfSeconds = {}", checkTimestamp, timeoutOfSeconds);
|
||||||
|
|
||||||
setGlobalVars(Optional.ofNullable(checkTimestamp).orElse(false), Optional.ofNullable(timeoutOfSeconds).orElse(30),
|
setGlobalVars(Optional.ofNullable(checkTimestamp).orElse(false),
|
||||||
|
Optional.ofNullable(timeoutOfSeconds).orElse(30),
|
||||||
Optional.ofNullable(cryptoType).orElse(0));
|
Optional.ofNullable(cryptoType).orElse(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,14 +61,16 @@ public class CommonFrameworkApi {
|
||||||
OperationType = "SYSLOG_TYPE_READ",
|
OperationType = "SYSLOG_TYPE_READ",
|
||||||
OperationDesc = "SYSLOG_DESC_GET_VERSION")
|
OperationDesc = "SYSLOG_DESC_GET_VERSION")
|
||||||
public ProtocolResp<VersionResp> getVersion() {
|
public ProtocolResp<VersionResp> getVersion() {
|
||||||
return ProtocolResp.result(VersionResp.builder().version(VersionInfo.builder()
|
return ProtocolResp.result(VersionResp.builder()
|
||||||
|
.version(VersionInfo.builder()
|
||||||
.commitId(prgVer.getCommitId())
|
.commitId(prgVer.getCommitId())
|
||||||
.commitDescribe(prgVer.getCommitDescribe())
|
.commitDescribe(prgVer.getCommitDescribe())
|
||||||
.commitTime(prgVer.getCommitTime())
|
.commitTime(prgVer.getCommitTime())
|
||||||
.tagName(prgVer.getTagName())
|
.tagName(prgVer.getTagName())
|
||||||
.buildTime(prgVer.getBuildTime())
|
.buildTime(prgVer.getBuildTime())
|
||||||
.gitBranch(prgVer.getGitBranch())
|
.gitBranch(prgVer.getGitBranch())
|
||||||
.build()).build());
|
.build())
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,13 +87,15 @@ public class CommonFrameworkApi {
|
||||||
OperationType = "SYSLOG_TYPE_READ",
|
OperationType = "SYSLOG_TYPE_READ",
|
||||||
OperationDesc = "SYSLOG_DESC_GET_VERSION")
|
OperationDesc = "SYSLOG_DESC_GET_VERSION")
|
||||||
public ProtocolResp<VersionResp> getVersionV2() {
|
public ProtocolResp<VersionResp> getVersionV2() {
|
||||||
return ProtocolResp.result(VersionResp.builder().version(VersionInfo.builder()
|
return ProtocolResp.result(VersionResp.builder()
|
||||||
|
.version(VersionInfo.builder()
|
||||||
.commitId(prgVer.getCommitId())
|
.commitId(prgVer.getCommitId())
|
||||||
.commitDescribe(prgVer.getCommitDescribe())
|
.commitDescribe(prgVer.getCommitDescribe())
|
||||||
.commitTime(prgVer.getCommitTime())
|
.commitTime(prgVer.getCommitTime())
|
||||||
.tagName(prgVer.getTagName())
|
.tagName(prgVer.getTagName())
|
||||||
.buildTime(prgVer.getBuildTime())
|
.buildTime(prgVer.getBuildTime())
|
||||||
.gitBranch(prgVer.getGitBranch())
|
.gitBranch(prgVer.getGitBranch())
|
||||||
.build()).build());
|
.build())
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,8 +58,8 @@ public class RequestProtocolSecurity implements RequestBodyAdvice {
|
||||||
@NotNull Type type,
|
@NotNull Type type,
|
||||||
@NotNull Class<? extends HttpMessageConverter<?>> aClass) {
|
@NotNull Class<? extends HttpMessageConverter<?>> aClass) {
|
||||||
// 检查类级别或方法级别上是否存在 @DecryptionProtocol 注解
|
// 检查类级别或方法级别上是否存在 @DecryptionProtocol 注解
|
||||||
return methodParameter.getContainingClass().isAnnotationPresent(DecryptionProtocol.class)
|
return methodParameter.getContainingClass().isAnnotationPresent(DecryptionProtocol.class) || methodParameter.hasMethodAnnotation(
|
||||||
|| methodParameter.hasMethodAnnotation(DecryptionProtocol.class);
|
DecryptionProtocol.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -63,11 +63,10 @@ public class ResponseProtocolSecurity implements ResponseBodyAdvice<Object> {
|
||||||
* @since 2025-01-07
|
* @since 2025-01-07
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(@NotNull MethodParameter methodParameter,
|
public boolean supports(@NotNull MethodParameter methodParameter, @NotNull Class<? extends HttpMessageConverter<?>> aClass) {
|
||||||
@NotNull Class<? extends HttpMessageConverter<?>> aClass) {
|
|
||||||
// 检查类级别或方法级别上是否存在 @EncryptionProtocol 注解
|
// 检查类级别或方法级别上是否存在 @EncryptionProtocol 注解
|
||||||
return methodParameter.getContainingClass().isAnnotationPresent(EncryptionProtocol.class)
|
return methodParameter.getContainingClass().isAnnotationPresent(EncryptionProtocol.class) || methodParameter.hasMethodAnnotation(
|
||||||
|| methodParameter.hasMethodAnnotation(EncryptionProtocol.class);
|
EncryptionProtocol.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -75,8 +75,9 @@ public class RequestBodyFilter implements Filter {
|
||||||
* @throws ServletException 如果发生其他错误
|
* @throws ServletException 如果发生其他错误
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
|
public void doFilter(ServletRequest servletRequest,
|
||||||
throws IOException, ServletException {
|
ServletResponse servletResponse,
|
||||||
|
FilterChain filterChain) throws IOException, ServletException {
|
||||||
// 定义包装后的请求对象
|
// 定义包装后的请求对象
|
||||||
ServletRequest requestWrapper = null;
|
ServletRequest requestWrapper = null;
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ public class HelperUtils {
|
||||||
if (!stringNotEmptyOrNull(orgString) || orgString.length() <= maxLength) {
|
if (!stringNotEmptyOrNull(orgString) || orgString.length() <= maxLength) {
|
||||||
return orgString;
|
return orgString;
|
||||||
} else {
|
} else {
|
||||||
return orgString.substring(0, maxLength - 4) + "...";
|
return orgString.substring(0, maxLength - 3) + "...";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,9 +130,9 @@ public class JsonParameterizedType implements ParameterizedType {
|
||||||
if (this == other) {
|
if (this == other) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return Objects.equals(this.ownerType, other.getOwnerType())
|
return Objects.equals(this.ownerType, other.getOwnerType()) &&
|
||||||
&& Objects.equals(this.rawType, other.getRawType())
|
Objects.equals(this.rawType, other.getRawType()) &&
|
||||||
&& Arrays.equals(this.actualTypeArguments, other.getActualTypeArguments());
|
Arrays.equals(this.actualTypeArguments, other.getActualTypeArguments());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -144,9 +144,7 @@ public class JsonParameterizedType implements ParameterizedType {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Arrays.hashCode(this.actualTypeArguments)
|
return Arrays.hashCode(this.actualTypeArguments) ^ Objects.hashCode(this.ownerType) ^ Objects.hashCode(this.rawType);
|
||||||
^ Objects.hashCode(this.ownerType)
|
|
||||||
^ Objects.hashCode(this.rawType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.cmhi.magent.misc;
|
package com.cmhi.magent.misc;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
|
@ -101,8 +100,7 @@ public class SpringBootBeanUtils implements ApplicationContextAware {
|
||||||
* @throws BeansException 如果上下文注入失败
|
* @throws BeansException 如果上下文注入失败
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setApplicationContext(
|
public void setApplicationContext(@org.jetbrains.annotations.NotNull ApplicationContext applicationContext) throws BeansException {
|
||||||
@NotNull @org.jetbrains.annotations.NotNull ApplicationContext applicationContext) throws BeansException {
|
|
||||||
setAppContext(applicationContext);
|
setAppContext(applicationContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ import oshi.software.os.FileSystem;
|
||||||
import oshi.software.os.NetworkParams;
|
import oshi.software.os.NetworkParams;
|
||||||
import oshi.software.os.OSFileStore;
|
import oshi.software.os.OSFileStore;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -234,16 +233,8 @@ public interface IObjectConvert {
|
||||||
* @return 自定义的 {@link FileStoreInfo} 对象。
|
* @return 自定义的 {@link FileStoreInfo} 对象。
|
||||||
*/
|
*/
|
||||||
default FileStoreInfo toFileStoreInfo(FileSystem fs, List<HWDiskStore> d) {
|
default FileStoreInfo toFileStoreInfo(FileSystem fs, List<HWDiskStore> d) {
|
||||||
if (fs == null) {
|
|
||||||
return FileStoreInfo.builder().fileStore(new ArrayList<>()).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<OSFileStore> o = fs.getFileStores(true);
|
List<OSFileStore> o = fs.getFileStores(true);
|
||||||
|
|
||||||
if (o == null || o.isEmpty()) {
|
|
||||||
return FileStoreInfo.builder().fileStore(new ArrayList<>()).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileStoreInfo fileStoreInfo = FileStoreInfo.builder().build();
|
FileStoreInfo fileStoreInfo = FileStoreInfo.builder().build();
|
||||||
fileStoreInfo.setFileStore(toFileStoreDetailsList(o));
|
fileStoreInfo.setFileStore(toFileStoreDetailsList(o));
|
||||||
fileStoreInfo.setHwDisk(toHwDisk(d));
|
fileStoreInfo.setHwDisk(toHwDisk(d));
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package com.cmhi.magent.pojo.po;
|
package com.cmhi.magent.pojo.po;
|
||||||
|
|
||||||
import com.cmhi.magent.annotation.AutoExternString;
|
import com.cmhi.magent.annotation.AutoExternString;
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class IfInterfaceInfo {
|
||||||
*/
|
*/
|
||||||
@AutoExternString(format = UtilsFormatType.FORMAT_ENUM, enumClass = NetworkIF.IfOperStatus.class)
|
@AutoExternString(format = UtilsFormatType.FORMAT_ENUM, enumClass = NetworkIF.IfOperStatus.class)
|
||||||
@Schema(description = "网络接口的运行状态,枚举类型:UP, DOWN, UNKNOWN 等", example = "1")
|
@Schema(description = "网络接口的运行状态,枚举类型:UP, DOWN, UNKNOWN 等", example = "1")
|
||||||
private int ifOperStatus;
|
private Integer ifOperStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 网络接口的最大传输单元(MTU)。
|
* 网络接口的最大传输单元(MTU)。
|
||||||
|
|
|
@ -155,8 +155,7 @@ public class OperationLog {
|
||||||
* 记录 HTTP 请求的头部信息,通常以 JSON 字符串形式存储。
|
* 记录 HTTP 请求的头部信息,通常以 JSON 字符串形式存储。
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
@Schema(description = "HTTP 请求头信息(以 JSON 格式存储)。",
|
@Schema(description = "HTTP 请求头信息(以 JSON 格式存储)。", example = "{ 'Content-Type': 'application/json' }")
|
||||||
example = "{ 'Content-Type': 'application/json' }")
|
|
||||||
private String requestHeaders;
|
private String requestHeaders;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -68,8 +68,7 @@ public class PageResults<T> {
|
||||||
* 表示当前页返回的具体数据项,类型由泛型参数 {@code T} 决定。
|
* 表示当前页返回的具体数据项,类型由泛型参数 {@code T} 决定。
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
@Schema(description = "当前页的具体数据项列表。",
|
@Schema(description = "当前页的具体数据项列表。", example = "[{ 'id': 1, 'name': 'Item 1' }, { 'id': 2, 'name': 'Item 2' }]")
|
||||||
example = "[{ 'id': 1, 'name': 'Item 1' }, { 'id': 2, 'name': 'Item 2' }]")
|
|
||||||
private List<T> items;
|
private List<T> items;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -71,8 +71,7 @@ public class ProcessorInfo {
|
||||||
* 表示处理器的完整型号名称,例如 "Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz"。
|
* 表示处理器的完整型号名称,例如 "Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz"。
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
@Schema(description = "处理器的完整型号名称。",
|
@Schema(description = "处理器的完整型号名称。", example = "Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz")
|
||||||
example = "Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz")
|
|
||||||
private String cpuName;
|
private String cpuName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -79,7 +79,8 @@ public class BasePageResultResp<T> extends BaseRespStatus {
|
||||||
*/
|
*/
|
||||||
@Schema(description = "分页数据,包含分页元信息(如当前页码、总页数、总行数等)以及具体数据项。",
|
@Schema(description = "分页数据,包含分页元信息(如当前页码、总页数、总行数等)以及具体数据项。",
|
||||||
example = "{ \"pageNumber\": 1, \"pageSize\": 10, \"totalPage\": 5, \"totalRow\": 50, " +
|
example = "{ \"pageNumber\": 1, \"pageSize\": 10, \"totalPage\": 5, \"totalRow\": 50, " +
|
||||||
"\"items\": [ {\"id\": 1, \"name\": " + "\"Item 1\"}, {\"id\": 2, \"name\": " +
|
"\"items\": [ {\"id\": 1, \"name\": " +
|
||||||
|
"\"Item 1\"}, {\"id\": 2, \"name\": " +
|
||||||
"\"Item 2\"} ] }")
|
"\"Item 2\"} ] }")
|
||||||
private PageResults<T> items;
|
private PageResults<T> items;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,12 @@ public class OperationLogServiceImpl implements OperationLogService {
|
||||||
ErrorCode errorCode) {
|
ErrorCode errorCode) {
|
||||||
if (annotation != null) {
|
if (annotation != null) {
|
||||||
// 提取注解中的元数据并记录日志
|
// 提取注解中的元数据并记录日志
|
||||||
systemOperationLog(call, request, result, annotation.OperationModule(), annotation.OperationType(), annotation.OperationDesc(),
|
systemOperationLog(call,
|
||||||
|
request,
|
||||||
|
result,
|
||||||
|
annotation.OperationModule(),
|
||||||
|
annotation.OperationType(),
|
||||||
|
annotation.OperationDesc(),
|
||||||
errorCode);
|
errorCode);
|
||||||
} else {
|
} else {
|
||||||
// 如果注解为空,使用默认值记录日志
|
// 如果注解为空,使用默认值记录日志
|
||||||
|
|
|
@ -74,10 +74,7 @@ public class ValidHttpMethodImpl implements ConstraintValidator<ValidHttpMethod,
|
||||||
// 遍历 HTTP 方法列表并校验
|
// 遍历 HTTP 方法列表并校验
|
||||||
strings.forEach(k -> {
|
strings.forEach(k -> {
|
||||||
if (RequestMethod.resolve(k.toUpperCase()) == null) {
|
if (RequestMethod.resolve(k.toUpperCase()) == null) {
|
||||||
errMsg.append("[")
|
errMsg.append("[").append(k).append("]: ").append(MessageUtil.get("http.request_invalid", ApiContextUtils.getLanguage()));
|
||||||
.append(k)
|
|
||||||
.append("]: ")
|
|
||||||
.append(MessageUtil.get("http.request_invalid", ApiContextUtils.getLanguage()));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
package com.cmhi.magent.common;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NoneEnumTest 是 {@link NoneEnum} 的单元测试类。
|
||||||
|
* <p>
|
||||||
|
* 使用 JUnit 5 和 AssertJ 对 NoneEnum 的各个方法功能进行验证,确保枚举方法返回的值符合预期。
|
||||||
|
* 主要测试以下方法:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link NoneEnum#getStringValue()} - 验证获取字符串值功能。</li>
|
||||||
|
* <li>{@link NoneEnum#getValue()} - 验证获取整数值功能。</li>
|
||||||
|
* <li>{@link NoneEnum#getDescription()} - 验证获取描述功能。</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>依赖注入:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>使用 {@code @SpringBootTest} 确保 Spring Boot 环境正常加载。</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author huangxin@cmhi.chinamobile.com
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025-01-13
|
||||||
|
*/
|
||||||
|
@SpringBootTest
|
||||||
|
class EnumCoverTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试 {@link NoneEnum#getStringValue()} 方法。
|
||||||
|
* <p>
|
||||||
|
* 验证是否能正确返回枚举的字符串值。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>测试逻辑:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>调用 {@link NoneEnum#NONE_ENUM#getStringValue()}。</li>
|
||||||
|
* <li>断言返回的字符串值是否等于预期值 {@code ""}(空字符串)。</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testGetStringValue() {
|
||||||
|
// Setup
|
||||||
|
// Run the test
|
||||||
|
final String result = NoneEnum.NONE_ENUM.getStringValue();
|
||||||
|
|
||||||
|
// Verify the results
|
||||||
|
assertThat(result).isEqualTo("");
|
||||||
|
|
||||||
|
final String var = UtilsFormatType.FORMAT_NONE.getStringValue();
|
||||||
|
assertThat(var).isEqualTo("不进行格式化");
|
||||||
|
|
||||||
|
assertThat(UtilsFormatType.FORMAT_NONE.getValue()).isEqualTo(4);
|
||||||
|
assertThat(UtilsFormatType.FORMAT_NONE.getDescription().length()).isGreaterThan(0);
|
||||||
|
|
||||||
|
assertThat(ProtoCryptoType.CRYPTO_NONE.getValue()).isEqualTo(0);
|
||||||
|
assertThat(ProtoCryptoType.CRYPTO_NONE.getDescription().length()).isGreaterThan(0);
|
||||||
|
assertThat(ProtoCryptoType.CRYPTO_NONE.getStringValue().length()).isGreaterThan(0);
|
||||||
|
|
||||||
|
assertThat(CommonStatus.NORMAL.getValue()).isEqualTo(0);
|
||||||
|
assertThat(CommonStatus.NORMAL.getDescription().length()).isGreaterThan(0);
|
||||||
|
assertThat(CommonStatus.NORMAL.getStringValue().length()).isGreaterThan(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试 {@link NoneEnum#getValue()} 方法。
|
||||||
|
* <p>
|
||||||
|
* 验证是否能正确返回枚举的整数值。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>测试逻辑:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>调用 {@link NoneEnum#NONE_ENUM#getValue()}。</li>
|
||||||
|
* <li>断言返回的整数值是否等于预期值 {@code 0}。</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testGetValue() {
|
||||||
|
// Setup
|
||||||
|
// Run the test
|
||||||
|
final Integer result = NoneEnum.NONE_ENUM.getValue();
|
||||||
|
|
||||||
|
// Verify the results
|
||||||
|
assertThat(result).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试 {@link NoneEnum#getDescription()} 方法。
|
||||||
|
* <p>
|
||||||
|
* 验证是否能正确返回枚举的描述信息。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>测试逻辑:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>调用 {@link NoneEnum#NONE_ENUM#getDescription()}。</li>
|
||||||
|
* <li>断言返回的描述信息是否等于预期值 {@code ""}(空字符串)。</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testGetDescription() {
|
||||||
|
// Setup
|
||||||
|
// Run the test
|
||||||
|
final String result = NoneEnum.NONE_ENUM.getDescription();
|
||||||
|
|
||||||
|
// Verify the results
|
||||||
|
assertThat(result).isEqualTo("");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,260 @@
|
||||||
|
package com.cmhi.magent.misc;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HelperUtilsTest 是 HelperUtils 工具类的单元测试类。
|
||||||
|
* <p>
|
||||||
|
* 使用 JUnit 5 测试框架对 HelperUtils 提供的方法进行功能验证,确保工具方法在各种场景下表现正确。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>主要测试内容:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>JSON 序列化功能的测试</li>
|
||||||
|
* <li>字符串操作的测试</li>
|
||||||
|
* <li>字节数组与十六进制字符串转换的测试</li>
|
||||||
|
* <li>字符集编码转换的测试</li>
|
||||||
|
* <li>输入流与字符串的相互转换测试</li>
|
||||||
|
* <li>时间和时间戳处理的测试</li>
|
||||||
|
* <li>字符串非空判断与合并逻辑的测试</li>
|
||||||
|
* <li>对象验证功能的测试</li>
|
||||||
|
* </ul>
|
||||||
|
* @author huangxin@cmhi.chinamobile.com
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025-01-14
|
||||||
|
*/
|
||||||
|
@SpringBootTest
|
||||||
|
@Slf4j
|
||||||
|
public class HelperUtilsTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试 JSON 序列化功能。
|
||||||
|
* <p>
|
||||||
|
* 验证 {@link HelperUtils#getJson(Object)} 方法是否能正确序列化传入的对象为 JSON 字符串。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @throws Exception 如果 JSON 序列化失败
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@DisplayName("HelperUtils.getJson")
|
||||||
|
void testGetJson() throws Exception {
|
||||||
|
// 创建一个测试对象
|
||||||
|
Long jsonVal = 123L;
|
||||||
|
|
||||||
|
// 调用 getJson 方法
|
||||||
|
String json = HelperUtils.getJson(jsonVal);
|
||||||
|
|
||||||
|
// 断言生成的 JSON 字符串不为空
|
||||||
|
assertNotNull(json);
|
||||||
|
assertEquals(new ObjectMapper().writeValueAsString(jsonVal), json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试字符串截断功能。
|
||||||
|
* <p>
|
||||||
|
* 验证 {@link HelperUtils#truncateString(String, int)} 方法是否能正确截断字符串,并追加 "..." 后缀。
|
||||||
|
* 断言截断后的长度、内容与期望值是否一致。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@DisplayName("HelperUtils.truncateString")
|
||||||
|
void testTruncateString() {
|
||||||
|
// 原始字符串
|
||||||
|
String orgString = "This is a long string";
|
||||||
|
|
||||||
|
// 截断长度
|
||||||
|
int maxLength = 8;
|
||||||
|
|
||||||
|
// 调用 truncateString 方法
|
||||||
|
String truncatedString = HelperUtils.truncateString(orgString, maxLength);
|
||||||
|
|
||||||
|
log.info("[{}] --> [{}]", orgString, truncatedString);
|
||||||
|
// 断言截断后的字符串长度符合预期
|
||||||
|
assertEquals(maxLength, truncatedString.length());
|
||||||
|
assertTrue(truncatedString.endsWith("..."));
|
||||||
|
assertTrue(truncatedString.startsWith(orgString.substring(0, maxLength - 3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试字节数组转换为十六进制字符串功能。
|
||||||
|
* <p>
|
||||||
|
* 验证 {@link HelperUtils#bytesToHexString(byte[])} 方法是否能正确将字节数组转换为十六进制字符串。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@DisplayName("HelperUtils.bytesToHexString")
|
||||||
|
void testBytesToHexString() {
|
||||||
|
// 字节数组
|
||||||
|
byte[] bArray = {1, 2, 3, 4, 5};
|
||||||
|
|
||||||
|
// 调用 bytesToHexString 方法
|
||||||
|
String hexString = HelperUtils.bytesToHexString(bArray);
|
||||||
|
|
||||||
|
// 断言生成的十六进制字符串正确
|
||||||
|
assertEquals("0102030405", hexString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试字符串转换为 GB2312 编码的字节数组功能。
|
||||||
|
* <p>
|
||||||
|
* 验证 {@link HelperUtils#convertStringToGb2312(String)} 方法是否能正确转换字符串为 GB2312 字节数组。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @throws UnsupportedEncodingException 如果指定的编码不受支持
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@DisplayName("HelperUtils.convertStringToGb2312")
|
||||||
|
void testConvertStringToGb2312() throws UnsupportedEncodingException {
|
||||||
|
// 原始字符串
|
||||||
|
String str = "测试字符串";
|
||||||
|
|
||||||
|
// 调用 convertStringToGb2312 方法
|
||||||
|
byte[] gb2312Bytes = HelperUtils.convertStringToGb2312(str);
|
||||||
|
|
||||||
|
// 可以进一步验证转换后的字节数组是否符合预期
|
||||||
|
assertNotNull(gb2312Bytes);
|
||||||
|
assertTrue(gb2312Bytes.length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试输入流转换为字符串功能。
|
||||||
|
* <p>
|
||||||
|
* 验证 {@link HelperUtils#inputStream2String(InputStream)} 方法是否能将输入流正确转换为字符串。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @throws IOException 如果读取输入流失败
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@DisplayName("HelperUtils.inputStream2String")
|
||||||
|
void testInputStream2String() throws IOException {
|
||||||
|
// 创建一个输入流
|
||||||
|
InputStream inputStream = new ByteArrayInputStream("测试输入流".getBytes());
|
||||||
|
|
||||||
|
// 调用 inputStream2String 方法
|
||||||
|
String result = HelperUtils.inputStream2String(inputStream);
|
||||||
|
|
||||||
|
// 断言转换后的字符串正确
|
||||||
|
assertEquals("测试输入流", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试时间字符串转换为时间戳(毫秒)功能。
|
||||||
|
* <p>
|
||||||
|
* 验证 {@link HelperUtils#getTimestampMilliSecond(String)} 方法是否能正确计算时间戳。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@DisplayName("HelperUtils.getTimestampMilliSecond")
|
||||||
|
void testGetTimestampMilliSecond() {
|
||||||
|
// 时间字符串
|
||||||
|
String dateTime = "2023-09-15 10:10:10";
|
||||||
|
|
||||||
|
// 调用 getTimestampMilliSecond 方法
|
||||||
|
long timestamp = HelperUtils.getTimestampMilliSecond(dateTime);
|
||||||
|
|
||||||
|
// 可以根据具体时间进行断言
|
||||||
|
assertEquals(1694743810000L, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试获取当前日期和时间的功能。
|
||||||
|
* <p>
|
||||||
|
* 验证 {@link HelperUtils#getCurrentDatetime()} 方法是否能返回不为空的当前日期和时间字符串。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@DisplayName("HelperUtils.getCurrentDatetime")
|
||||||
|
void testGetCurrentDatetime() {
|
||||||
|
// 调用 getCurrentDatetime 方法
|
||||||
|
String currentDatetime = HelperUtils.getCurrentDatetime();
|
||||||
|
|
||||||
|
// 可以根据当前时间进行断言
|
||||||
|
assertNotNull(currentDatetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试字符串非空或非 null 检查功能。
|
||||||
|
* <p>
|
||||||
|
* 验证 {@link HelperUtils#stringNotEmptyOrNull(String)} 方法是否能正确判断字符串是否为空或 null。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@DisplayName("HelperUtils.stringNotEmptyOrNull")
|
||||||
|
void testStringNotEmptyOrNull() {
|
||||||
|
// 非空字符串
|
||||||
|
String str = "非空字符串";
|
||||||
|
|
||||||
|
// 调用 stringNotEmptyOrNull 方法
|
||||||
|
boolean result = HelperUtils.stringNotEmptyOrNull(str);
|
||||||
|
|
||||||
|
// 断言结果为 true
|
||||||
|
assertTrue(result);
|
||||||
|
|
||||||
|
// 空字符串
|
||||||
|
str = "";
|
||||||
|
|
||||||
|
result = HelperUtils.stringNotEmptyOrNull(str);
|
||||||
|
|
||||||
|
// 断言结果为 false
|
||||||
|
assertFalse(result);
|
||||||
|
|
||||||
|
// null 字符串
|
||||||
|
str = null;
|
||||||
|
// 断言结果为 false
|
||||||
|
assertFalse(HelperUtils.stringNotEmptyOrNull(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试合并数据库字符串值的功能。
|
||||||
|
* <p>
|
||||||
|
* 验证 {@link HelperUtils#meagreDbStringValue(String)} 方法是否能正确判断数据库字符串值:
|
||||||
|
* <ul>
|
||||||
|
* <li>对于非空字符串,返回原始值。</li>
|
||||||
|
* <li>对于空字符串或 null,返回 null。</li>
|
||||||
|
* </ul>
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@DisplayName("HelperUtils.meagreDbStringValue")
|
||||||
|
void testMeagreDbStringValue() {
|
||||||
|
// 非空字符串
|
||||||
|
String str = "非空字符串";
|
||||||
|
|
||||||
|
// 调用 meagreDbStringValue 方法
|
||||||
|
String result = HelperUtils.meagreDbStringValue(str);
|
||||||
|
|
||||||
|
// 断言结果为原始字符串
|
||||||
|
assertEquals(str, result);
|
||||||
|
|
||||||
|
// 空字符串
|
||||||
|
str = "";
|
||||||
|
|
||||||
|
result = HelperUtils.meagreDbStringValue(str);
|
||||||
|
|
||||||
|
// 断言结果为 null
|
||||||
|
assertNull(result);
|
||||||
|
|
||||||
|
// null 字符串
|
||||||
|
str = null;
|
||||||
|
|
||||||
|
result = HelperUtils.meagreDbStringValue(str);
|
||||||
|
|
||||||
|
// 断言结果为 null
|
||||||
|
assertNull(result);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,114 +0,0 @@
|
||||||
package com.cmhi.magent.service;
|
|
||||||
|
|
||||||
import com.cmhi.magent.misc.HelperUtils;
|
|
||||||
import com.cmhi.magent.pojo.mapper.IObjectConvert;
|
|
||||||
import com.cmhi.magent.pojo.po.HwInfo;
|
|
||||||
import com.cmhi.magent.pojo.po.MemoryDetails;
|
|
||||||
import com.cmhi.magent.pojo.po.ProcessorInfo;
|
|
||||||
import com.cmhi.magent.service.impl.SystemInfoServiceImpl;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import oshi.SystemInfo;
|
|
||||||
import oshi.hardware.GlobalMemory;
|
|
||||||
import oshi.hardware.HWDiskStore;
|
|
||||||
import oshi.hardware.NetworkIF;
|
|
||||||
import oshi.hardware.PhysicalMemory;
|
|
||||||
import oshi.software.os.FileSystem;
|
|
||||||
import oshi.software.os.NetworkParams;
|
|
||||||
import oshi.software.os.OSFileStore;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
class SystemInfoServiceTest {
|
|
||||||
|
|
||||||
private SystemInfoServiceImpl systemInfoService; // 实现类对象
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private ObjectMapper objectMapper;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
// 实例化实现类
|
|
||||||
systemInfoService = new SystemInfoServiceImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testGetOsName() {
|
|
||||||
// 调用接口方法
|
|
||||||
String osName = systemInfoService.getOsName();
|
|
||||||
|
|
||||||
// 检查返回值是否符合预期(这里只能验证非空,因为操作系统名称依赖具体环境)
|
|
||||||
assertNotNull(osName, "操作系统名称不能为空!");
|
|
||||||
System.out.println("操作系统名称: " + osName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testGetOsBootTimeStamp() {
|
|
||||||
// 调用接口方法
|
|
||||||
long bootTimeStamp = systemInfoService.getOsBootTimeStamp();
|
|
||||||
|
|
||||||
// 验证时间戳(一般会大于当前时间减去一个合理的范围)
|
|
||||||
assertTrue(bootTimeStamp > 0, "启动时间戳应该是正值!");
|
|
||||||
System.out.println("操作系统启动时间戳: " + bootTimeStamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testGetProcessInfo() {
|
|
||||||
// 调用接口方法获取处理器信息
|
|
||||||
ProcessorInfo processorInfo = systemInfoService.getProcessInfo();
|
|
||||||
|
|
||||||
// 检查返回的处理器信息是否合理
|
|
||||||
assertNotNull(processorInfo, "处理器信息不能为空!");
|
|
||||||
assertTrue(processorInfo.getPhysicalCores() > 0, "处理器核心数量应该大于0!");
|
|
||||||
assertTrue(processorInfo.getLogicalCpu() >= processorInfo.getPhysicalCores(), "线程数量应该不小于核心数量!");
|
|
||||||
assertTrue(processorInfo.getCpuVendorFreq() > 0, "CPU频率应该大于0!");
|
|
||||||
System.out.println(
|
|
||||||
"处理器信息: 核心数量 = " + processorInfo.getPhysicalCores() + ", 线程数量 = " + processorInfo.getLogicalCpu() + ", 主频 = " + processorInfo.getCpuVendorFreq() + " GHz");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testGetHardwareInfo() {
|
|
||||||
// // 调用接口方法获取硬件信息
|
|
||||||
// HwInfo hardwareInfo = systemInfoService.getHardwareInfo();
|
|
||||||
//
|
|
||||||
// // 检查返回的硬件信息是否合理
|
|
||||||
// assertNotNull(hardwareInfo, "硬件信息不能为空!");
|
|
||||||
// assertTrue(hardwareInfo.get() > 0, "内存大小应该大于0!");
|
|
||||||
// assertTrue(hardwareInfo.getDiskCapacity() > 0, "磁盘容量应该大于0!");
|
|
||||||
// System.out.println("硬件信息: 内存大小 = " + hardwareInfo.getMemorySize() +
|
|
||||||
// " GB, 磁盘容量 = " + hardwareInfo.getDiskCapacity() + " GB");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testGetMemoryInfo() throws JsonProcessingException {
|
|
||||||
SystemInfo si = new SystemInfo();
|
|
||||||
GlobalMemory memory = si.getHardware().getMemory();
|
|
||||||
List<PhysicalMemory> ph = memory.getPhysicalMemory();
|
|
||||||
List<HWDiskStore> d = si.getHardware().getDiskStores();
|
|
||||||
FileSystem fs = si.getOperatingSystem().getFileSystem();
|
|
||||||
List<OSFileStore> os = fs.getFileStores(true);
|
|
||||||
List<NetworkIF> nf = si.getHardware().getNetworkIFs(true);
|
|
||||||
NetworkParams np = si.getOperatingSystem().getNetworkParams();
|
|
||||||
|
|
||||||
MemoryDetails md = new MemoryDetails();
|
|
||||||
md.setFreeMemory(1000L);
|
|
||||||
md.setTotalMemory(3000L);
|
|
||||||
|
|
||||||
HwInfo hw = IObjectConvert.INSTANCE.toHwInfo(si);
|
|
||||||
System.out.println(HelperUtils.getJson(hw));
|
|
||||||
// System.out.println(HelperUtils.getJson(d));
|
|
||||||
// System.out.println(HelperUtils.getJson(fs));
|
|
||||||
|
|
||||||
//System.out.println(objectMapper.writeValueAsString(md));
|
|
||||||
// System.out.println(HelperUtils.getJson(memory));
|
|
||||||
// System.out.println(HelperUtils.getJson(ph));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
package com.cmhi.magent.service.impl;
|
||||||
|
|
||||||
|
import com.cmhi.magent.pojo.po.RegisterAgent;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import okhttp3.mockwebserver.MockResponse;
|
||||||
|
import okhttp3.mockwebserver.MockWebServer;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单元测试类 {@code PlatformApiServiceImplTest} 用于测试 {@link PlatformApiServiceImpl} 的功能。
|
||||||
|
* <p>
|
||||||
|
* 测试的主要目标是确保 {@link PlatformApiServiceImpl#registerAgent(RegisterAgent)} 方法能够正常工作,
|
||||||
|
* 并验证 {@link WebClient} 在调用外部 API 时的行为。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>测试中使用了 {@code MockWebServer} 来模拟 HTTP 请求和响应,避免依赖实际的外部服务。</p>
|
||||||
|
*
|
||||||
|
* <p>主要验证内容包括:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>是否正确构造了 HTTP 请求(如方法和路径)。</li>
|
||||||
|
* <li>是否正确处理了 HTTP 响应并返回预期结果。</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>依赖注入说明:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>通过 {@code @Resource} 注入被测试的 {@code PlatformApiServiceImpl}。</li>
|
||||||
|
* <li>通过 {@code @Autowired} 注入 {@code WebClient.Builder},用于生成测试时专用的 {@code WebClient}。</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author huangxin@cmhi.chinamobile.com
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025-01-14
|
||||||
|
*/
|
||||||
|
@SpringBootTest
|
||||||
|
class PlatformApiServiceImplTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 被测试的服务类 {@link PlatformApiServiceImpl}。
|
||||||
|
*/
|
||||||
|
@Resource
|
||||||
|
private PlatformApiServiceImpl platformApiService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于创建 {@link WebClient} 实例的 {@link WebClient.Builder},通过它构造指向 {@code MockWebServer} 的 WebClient。
|
||||||
|
*/
|
||||||
|
@Autowired
|
||||||
|
private WebClient.Builder webClientBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模拟 HTTP 请求和响应的 MockWebServer。
|
||||||
|
*/
|
||||||
|
private MockWebServer mockWebServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 MockWebServer,并通过反射注入 MockWebServer 对应的 WebClient 到 PlatformApiService 中。
|
||||||
|
*
|
||||||
|
* @throws Exception 如果 MockWebServer 或 WebClient 初始化失败。
|
||||||
|
*/
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() throws Exception {
|
||||||
|
// 初始化 MockWebServer
|
||||||
|
mockWebServer = new MockWebServer();
|
||||||
|
mockWebServer.start();
|
||||||
|
|
||||||
|
// 使用 MockWebServer 的 URL 配置 WebClient
|
||||||
|
WebClient webClient = webClientBuilder.baseUrl(mockWebServer.url("/").toString()).build();
|
||||||
|
|
||||||
|
// 使用反射注入 WebClient 到 PlatformApiService
|
||||||
|
injectWebClientIntoApiService(webClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止 MockWebServer。
|
||||||
|
*
|
||||||
|
* @throws Exception 如果 MockWebServer 停止失败。
|
||||||
|
*/
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() throws Exception {
|
||||||
|
// 停止 MockWebServer
|
||||||
|
mockWebServer.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用反射将测试用的 {@link WebClient} 实例注入到 {@link PlatformApiServiceImpl}。
|
||||||
|
*
|
||||||
|
* @param webClientToInject 用于注入的 {@link WebClient} 实例。
|
||||||
|
* @throws Exception 如果反射注入过程中出现错误。
|
||||||
|
*/
|
||||||
|
private void injectWebClientIntoApiService(WebClient webClientToInject) throws Exception {
|
||||||
|
var webClientField = PlatformApiServiceImpl.class.getDeclaredField("webClient");
|
||||||
|
webClientField.setAccessible(true);
|
||||||
|
webClientField.set(platformApiService, webClientToInject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试 {@link PlatformApiServiceImpl#registerAgent(RegisterAgent)} 方法。
|
||||||
|
*
|
||||||
|
* <p>验证以下内容:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>是否正确发送了 HTTP POST 请求到指定路径(如 {@code /register})。</li>
|
||||||
|
* <li>是否正确处理了 HTTP 响应并返回预期的结果。</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>测试流程:</p>
|
||||||
|
* <ol>
|
||||||
|
* <li>设置 MockWebServer 的响应内容为 {@code {"message": "Hello, World!"}}。</li>
|
||||||
|
* <li>使用测试数据(如 {@link RegisterAgent} 对象)调用 {@code registerAgent} 方法。</li>
|
||||||
|
* <li>验证返回值是否等于设置的响应内容。</li>
|
||||||
|
* <li>验证发送的请求是否符合预期(如方法为 POST,路径为 /register)。</li>
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* @throws InterruptedException 如果等待 MockWebServer 请求时被中断。
|
||||||
|
* @throws JsonProcessingException 如果 JSON 处理发生错误。
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testFetchData() throws InterruptedException, JsonProcessingException {
|
||||||
|
// 准备模拟的 HTTP 响应
|
||||||
|
String mockResponse = "{\"message\": \"Hello, World!\"}";
|
||||||
|
mockWebServer.enqueue(new MockResponse().setBody(mockResponse).addHeader("Content-Type", "application/json"));
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
final RegisterAgent agent = RegisterAgent.builder().deviceId("123542535").build();
|
||||||
|
|
||||||
|
// 调用被测试方法
|
||||||
|
final String result = platformApiService.registerAgent(agent);
|
||||||
|
|
||||||
|
// 验证结果
|
||||||
|
assertThat(result).isEqualTo(mockResponse);
|
||||||
|
|
||||||
|
// 验证请求
|
||||||
|
var recordedRequest = mockWebServer.takeRequest();
|
||||||
|
assertThat(recordedRequest.getMethod()).isEqualTo("POST");
|
||||||
|
assertThat(recordedRequest.getPath()).isEqualTo("/register");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,206 @@
|
||||||
|
package com.cmhi.magent.service.impl;
|
||||||
|
|
||||||
|
import com.cmhi.magent.misc.HelperUtils;
|
||||||
|
import com.cmhi.magent.pojo.mapper.IObjectConvert;
|
||||||
|
import com.cmhi.magent.pojo.po.HwInfo;
|
||||||
|
import com.cmhi.magent.pojo.po.MemoryDetails;
|
||||||
|
import com.cmhi.magent.pojo.po.ProcessorInfo;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import oshi.SystemInfo;
|
||||||
|
import oshi.hardware.GlobalMemory;
|
||||||
|
import oshi.hardware.HWDiskStore;
|
||||||
|
import oshi.hardware.NetworkIF;
|
||||||
|
import oshi.hardware.PhysicalMemory;
|
||||||
|
import oshi.software.os.FileSystem;
|
||||||
|
import oshi.software.os.NetworkParams;
|
||||||
|
import oshi.software.os.OSFileStore;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单元测试类 {@code SystemInfoServiceImplTest},用于测试 {@link SystemInfoServiceImpl} 的功能。
|
||||||
|
* <p>
|
||||||
|
* 本测试类通过各种测试用例验证 {@link SystemInfoServiceImpl} 提供的系统信息获取功能是否正常工作。
|
||||||
|
* 主要测试的功能包括:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>获取操作系统名称。</li>
|
||||||
|
* <li>获取操作系统启动时间戳。</li>
|
||||||
|
* <li>获取 CPU 处理器信息。</li>
|
||||||
|
* <li>获取硬件信息。</li>
|
||||||
|
* <li>获取内存信息。</li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* 测试内容涉及对操作系统、内存、磁盘、网络等信息的验证,通过对返回结果的合理性检查来确保相关接口的正确性。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>依赖注入说明:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>通过实例化的方式创建被测试的 {@link SystemInfoServiceImpl} 实例。</li>
|
||||||
|
* <li>通过 {@code @Resource} 注入 {@link ObjectMapper},用于 JSON 处理。</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author huangxin@cmhi.chinamobile.com
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025-01-07
|
||||||
|
*/
|
||||||
|
@SpringBootTest
|
||||||
|
class SystemInfoServiceImplTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 被测试的服务类 {@link SystemInfoServiceImpl}。
|
||||||
|
*/
|
||||||
|
private SystemInfoServiceImpl systemInfoService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于序列化和反序列化 JSON 的 {@link ObjectMapper} 实例。
|
||||||
|
*/
|
||||||
|
@Resource
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在每个测试方法运行之前初始化被测试对象。
|
||||||
|
* <p>
|
||||||
|
* 在此方法中实例化 {@link SystemInfoServiceImpl},确保每次测试都从干净的环境开始。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
// 实例化实现类
|
||||||
|
systemInfoService = new SystemInfoServiceImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试 {@link SystemInfoServiceImpl#getOsName()} 方法。
|
||||||
|
* <p>
|
||||||
|
* 该方法用于获取操作系统的名称。测试通过以下内容进行验证:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>返回值不能为空。</li>
|
||||||
|
* <li>打印操作系统名称到控制台以供手动检查。</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testGetOsName() {
|
||||||
|
// 调用接口方法
|
||||||
|
String osName = systemInfoService.getOsName();
|
||||||
|
|
||||||
|
// 检查返回值是否符合预期(这里只能验证非空,因为操作系统名称依赖具体环境)
|
||||||
|
assertNotNull(osName, "操作系统名称不能为空!");
|
||||||
|
System.out.println("操作系统名称: " + osName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试 {@link SystemInfoServiceImpl#getOsBootTimeStamp()} 方法。
|
||||||
|
* <p>
|
||||||
|
* 该方法用于获取操作系统的启动时间戳。测试通过以下内容进行验证:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>返回的时间戳为正值。</li>
|
||||||
|
* <li>打印启动时间戳到控制台以供手动检查。</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testGetOsBootTimeStamp() {
|
||||||
|
// 调用接口方法
|
||||||
|
long bootTimeStamp = systemInfoService.getOsBootTimeStamp();
|
||||||
|
|
||||||
|
// 验证时间戳(一般会大于当前时间减去一个合理的范围)
|
||||||
|
assertTrue(bootTimeStamp > 0, "启动时间戳应该是正值!");
|
||||||
|
System.out.println("操作系统启动时间戳: " + bootTimeStamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试 {@link SystemInfoServiceImpl#getProcessInfo()} 方法。
|
||||||
|
* <p>
|
||||||
|
* 该方法用于获取处理器的详细信息。测试通过以下内容进行验证:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>返回值不能为空。</li>
|
||||||
|
* <li>处理器核心数量大于 0。</li>
|
||||||
|
* <li>线程数量不小于核心数量。</li>
|
||||||
|
* <li>CPU 主频大于 0。</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testGetProcessInfo() {
|
||||||
|
// 调用接口方法获取处理器信息
|
||||||
|
ProcessorInfo processorInfo = systemInfoService.getProcessInfo();
|
||||||
|
|
||||||
|
// 检查返回的处理器信息是否合理
|
||||||
|
assertNotNull(processorInfo, "处理器信息不能为空!");
|
||||||
|
assertTrue(processorInfo.getPhysicalCores() > 0, "处理器核心数量应该大于0!");
|
||||||
|
assertTrue(processorInfo.getLogicalCpu() >= processorInfo.getPhysicalCores(), "线程数量应该不小于核心数量!");
|
||||||
|
assertTrue(processorInfo.getCpuVendorFreq() > 0, "CPU频率应该大于0!");
|
||||||
|
System.out.println(
|
||||||
|
"处理器信息: 核心数量 = " + processorInfo.getPhysicalCores() + ", 线程数量 = " + processorInfo.getLogicalCpu() + ", 主频 = " + processorInfo.getCpuVendorFreq() + " GHz");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试 {@link SystemInfoServiceImpl#getHardwareInfo()} 方法。
|
||||||
|
* <p>
|
||||||
|
* 该方法当前被注释掉,无法执行实际测试。
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* 如果启用此方法,测试应包括以下内容:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>返回的硬件信息不能为空。</li>
|
||||||
|
* <li>内存大小大于 0。</li>
|
||||||
|
* <li>磁盘容量大于 0。</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testGetHardwareInfo() {
|
||||||
|
// 方法被注释掉,当前无法运行测试
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试系统内存、磁盘和网络的详细信息。
|
||||||
|
* <p>
|
||||||
|
* 测试过程中通过 {@link SystemInfo} 对象获取各种硬件和操作系统信息,并转换为 {@link HwInfo} 对象。
|
||||||
|
* 测试内容包括:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>物理内存信息。</li>
|
||||||
|
* <li>磁盘存储信息。</li>
|
||||||
|
* <li>文件系统信息。</li>
|
||||||
|
* <li>网络接口信息。</li>
|
||||||
|
* <li>网络参数。</li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* 本方法主要用于调试和打印相关信息。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @throws JsonProcessingException 如果 JSON 序列化或反序列化失败。
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void testGetMemoryInfo() throws JsonProcessingException {
|
||||||
|
// 获取系统信息
|
||||||
|
SystemInfo si = new SystemInfo();
|
||||||
|
GlobalMemory memory = si.getHardware().getMemory();
|
||||||
|
List<PhysicalMemory> ph = memory.getPhysicalMemory();
|
||||||
|
List<HWDiskStore> d = si.getHardware().getDiskStores();
|
||||||
|
FileSystem fs = si.getOperatingSystem().getFileSystem();
|
||||||
|
List<OSFileStore> os = fs.getFileStores(true);
|
||||||
|
List<NetworkIF> nf = si.getHardware().getNetworkIFs(true);
|
||||||
|
NetworkParams np = si.getOperatingSystem().getNetworkParams();
|
||||||
|
|
||||||
|
// 创建 MemoryDetails 对象
|
||||||
|
MemoryDetails md = new MemoryDetails();
|
||||||
|
md.setFreeMemory(1000L);
|
||||||
|
md.setTotalMemory(3000L);
|
||||||
|
|
||||||
|
// 转换为 HwInfo 对象并打印 JSON 格式
|
||||||
|
HwInfo hw = IObjectConvert.INSTANCE.toHwInfo(si);
|
||||||
|
System.out.println(HelperUtils.getJson(hw));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue