diff --git a/pom.xml b/pom.xml
index 5074634..571150a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -183,6 +183,11 @@
avatar-generator
1.1.0
+
+ com.github.oshi
+ oshi-core
+ 6.4.0
+
diff --git a/src/main/kotlin/top/fatweb/api/controller/system/MailController.kt b/src/main/kotlin/top/fatweb/api/controller/system/MailController.kt
deleted file mode 100644
index 01bc336..0000000
--- a/src/main/kotlin/top/fatweb/api/controller/system/MailController.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package top.fatweb.api.controller.system
-
-import io.swagger.v3.oas.annotations.tags.Tag
-import org.springframework.web.bind.annotation.RequestMapping
-import org.springframework.web.bind.annotation.RestController
-
-@Tag(name = "邮件接口", description = "邮件发送接口")
-@RequestMapping("/system/mail")
-@RestController
-class MailController {
-
-}
\ No newline at end of file
diff --git a/src/main/kotlin/top/fatweb/api/controller/system/StatisticsController.kt b/src/main/kotlin/top/fatweb/api/controller/system/StatisticsController.kt
new file mode 100644
index 0000000..045ebda
--- /dev/null
+++ b/src/main/kotlin/top/fatweb/api/controller/system/StatisticsController.kt
@@ -0,0 +1,26 @@
+package top.fatweb.api.controller.system
+
+import io.swagger.v3.oas.annotations.Operation
+import io.swagger.v3.oas.annotations.tags.Tag
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+import top.fatweb.api.entity.common.ResponseResult
+import top.fatweb.api.service.system.IStatisticsService
+import top.fatweb.api.vo.system.HardwareInfoVo
+import top.fatweb.api.vo.system.SoftwareInfoVo
+
+@Tag(name = "统计接口", description = "系统信息统计相关接口")
+@RequestMapping("/system/statistics")
+@RestController
+class StatisticsController(
+ private val statisticsService: IStatisticsService
+) {
+ @Operation(summary = "获取软件信息")
+ @GetMapping("/software")
+ fun software(): ResponseResult = ResponseResult.success(data = statisticsService.software())
+
+ @Operation(summary = "获取硬件信息")
+ @GetMapping("/hardware")
+ fun hardware(): ResponseResult = ResponseResult.success(data = statisticsService.hardware())
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/fatweb/api/properties/ServerProperties.kt b/src/main/kotlin/top/fatweb/api/properties/ServerProperties.kt
index 5176cfb..e9b3c1b 100644
--- a/src/main/kotlin/top/fatweb/api/properties/ServerProperties.kt
+++ b/src/main/kotlin/top/fatweb/api/properties/ServerProperties.kt
@@ -4,6 +4,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.stereotype.Component
import java.time.LocalDateTime
import java.time.ZoneId
+import java.time.ZoneOffset
import java.time.ZonedDateTime
/**
@@ -38,6 +39,14 @@ object ServerProperties {
* @since 1.0.0
*/
lateinit var buildTime: String
+
+ /**
+ * Startup time
+ *
+ * @author FatttSnake, fatttsnake@gmail.com
+ * @since 1.0.0
+ */
+ val startupTime: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC)
fun buildZoneDateTime(zoneId: ZoneId = ZoneId.systemDefault()): ZonedDateTime =
LocalDateTime.parse(buildTime).atZone(ZoneId.of("UTC")).withZoneSameInstant(zoneId)
diff --git a/src/main/kotlin/top/fatweb/api/service/system/IStatisticsService.kt b/src/main/kotlin/top/fatweb/api/service/system/IStatisticsService.kt
new file mode 100644
index 0000000..c6134dd
--- /dev/null
+++ b/src/main/kotlin/top/fatweb/api/service/system/IStatisticsService.kt
@@ -0,0 +1,10 @@
+package top.fatweb.api.service.system
+
+import top.fatweb.api.vo.system.HardwareInfoVo
+import top.fatweb.api.vo.system.SoftwareInfoVo
+
+interface IStatisticsService {
+ fun software(): SoftwareInfoVo
+
+ fun hardware(): HardwareInfoVo
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/fatweb/api/service/system/impl/StatisticsServiceImpl.kt b/src/main/kotlin/top/fatweb/api/service/system/impl/StatisticsServiceImpl.kt
new file mode 100644
index 0000000..b0bb625
--- /dev/null
+++ b/src/main/kotlin/top/fatweb/api/service/system/impl/StatisticsServiceImpl.kt
@@ -0,0 +1,44 @@
+package top.fatweb.api.service.system.impl
+
+import org.springframework.stereotype.Service
+import oshi.SystemInfo
+import top.fatweb.api.properties.ServerProperties
+import top.fatweb.api.service.system.IStatisticsService
+import top.fatweb.api.vo.system.HardwareInfoVo
+import top.fatweb.api.vo.system.SoftwareInfoVo
+import java.time.LocalDateTime
+import java.time.ZoneOffset
+import java.util.Properties
+
+@Service
+class StatisticsServiceImpl : IStatisticsService {
+ private val systemProperties: Properties = System.getProperties()
+ private val systemInfo: SystemInfo = SystemInfo()
+
+ override fun software(): SoftwareInfoVo = SoftwareInfoVo(
+ os = systemInfo.operatingSystem.toString(),
+ bitness = systemInfo.operatingSystem.bitness,
+ javaVersion = systemProperties.getProperty("java.version"),
+ javaVersionDate = systemProperties.getProperty("java.version.date"),
+ javaVendor = systemProperties.getProperty("java.vendor"),
+ javaRuntime = systemProperties.getProperty("java.runtime.name"),
+ javaRuntimeVersion = systemProperties.getProperty("java.runtime.version"),
+ jvm = systemProperties.getProperty("java.vm.name"),
+ jvmVersion = systemProperties.getProperty("java.vm.version"),
+ jvmInfo = systemProperties.getProperty("java.vm.info"),
+ jvmVendor = systemProperties.getProperty("java.vm.vendor"),
+ javaClassVersion = systemProperties.getProperty("java.class.version"),
+ osBootTime = LocalDateTime.ofEpochSecond(systemInfo.operatingSystem.systemBootTime, 0, ZoneOffset.UTC),
+ serverStartupTime = ServerProperties.startupTime
+ )
+
+ override fun hardware(): HardwareInfoVo = HardwareInfoVo(
+ cpu = systemInfo.hardware.processor.processorIdentifier.name,
+ arch = systemProperties.getProperty("os.arch"),
+ is64Bit = systemInfo.hardware.processor.processorIdentifier.isCpu64bit,
+ cpuPhysicalPackageCount = systemInfo.hardware.processor.physicalPackageCount,
+ cpuPhysicalProcessorCount = systemInfo.hardware.processor.physicalProcessorCount,
+ cpuLogicalProcessorCount = systemInfo.hardware.processor.logicalProcessorCount,
+ microarchitecture = systemInfo.hardware.processor.processorIdentifier.microarchitecture
+ )
+}
\ No newline at end of file
diff --git a/src/main/kotlin/top/fatweb/api/vo/system/HardwareInfoVo.kt b/src/main/kotlin/top/fatweb/api/vo/system/HardwareInfoVo.kt
new file mode 100644
index 0000000..cafef9e
--- /dev/null
+++ b/src/main/kotlin/top/fatweb/api/vo/system/HardwareInfoVo.kt
@@ -0,0 +1,11 @@
+package top.fatweb.api.vo.system
+
+data class HardwareInfoVo(
+ val cpu: String,
+ val arch: String,
+ val is64Bit: Boolean,
+ val cpuPhysicalPackageCount: Int,
+ val cpuPhysicalProcessorCount: Int,
+ val cpuLogicalProcessorCount: Int,
+ val microarchitecture: String
+)
\ No newline at end of file
diff --git a/src/main/kotlin/top/fatweb/api/vo/system/SoftwareInfoVo.kt b/src/main/kotlin/top/fatweb/api/vo/system/SoftwareInfoVo.kt
new file mode 100644
index 0000000..cfebdd8
--- /dev/null
+++ b/src/main/kotlin/top/fatweb/api/vo/system/SoftwareInfoVo.kt
@@ -0,0 +1,20 @@
+package top.fatweb.api.vo.system
+
+import java.time.LocalDateTime
+
+data class SoftwareInfoVo(
+ val os: String,
+ val bitness: Int,
+ val javaVersion: String,
+ val javaVersionDate: String,
+ val javaVendor: String,
+ val javaRuntime: String,
+ val javaRuntimeVersion: String,
+ val jvm: String,
+ val jvmVersion: String,
+ val jvmInfo: String,
+ val jvmVendor: String,
+ val javaClassVersion: String,
+ val osBootTime: LocalDateTime,
+ val serverStartupTime: LocalDateTime
+)