springboot-OSHI

OSHI 是什么

OSHI 是一个免费的基于 JNA(本机)的 Java 操作系统和硬件信息库。它不需要安装任何额外的本地库,旨在提供跨平台实现来检索系统信息,例如操作系统版本、进程、内存和 CPU 使用率、磁盘和分区、设备、传感器等。
OSHI is a free JNA-based (native) Operating System and Hardware Information library for Java. It does not require the installation of any additional native libraries and aims to provide a cross-platform implementation to retrieve system information, such as OS version, processes, memory and CPU usage, disks and partitions, devices, sensors, etc.

支持的平台

Windows • Linux • macOS • Unix (AIX, FreeBSD, OpenBSD, Solaris)

在Spring boot中使用OSHI

1、oshi依赖

		<dependency>
			<groupId>com.github.oshi</groupId>
			<artifactId>oshi-core</artifactId>
			<version>3.5.0</version>
		</dependency>

2、测试代码

package com.wxz.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.wxz.ServerMain;

import oshi.SystemInfo;
import oshi.hardware.*;
import oshi.hardware.CentralProcessor.TickType;
import oshi.software.os.*;
import oshi.software.os.OperatingSystem.ProcessSort;
import oshi.util.FormatUtil;
import oshi.util.Util;

import java.util.Arrays;
import java.util.List;

/**
 * The Class SystemInfoTest.
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ServerMain.class)
public class SystemInfoTest {

	@Test
	public void test() {
        // Options: ERROR > WARN > INFO > DEBUG > TRACE
        Logger LOG = LoggerFactory.getLogger(SystemInfoTest.class);

        LOG.info("Initializing System...");
        SystemInfo si = new SystemInfo();

        HardwareAbstractionLayer hal = si.getHardware();
        OperatingSystem os = si.getOperatingSystem();

        System.out.println(os);

        LOG.info("Checking computer system...");
        printComputerSystem(hal.getComputerSystem());

        LOG.info("Checking Processor...");
        printProcessor(hal.getProcessor());

        LOG.info("Checking Memory...");
        printMemory(hal.getMemory());

        LOG.info("Checking CPU...");
        printCpu(hal.getProcessor());

        LOG.info("Checking Processes...");
        printProcesses(os, hal.getMemory());

        LOG.info("Checking Sensors...");
        printSensors(hal.getSensors());

        LOG.info("Checking Power sources...");
        printPowerSources(hal.getPowerSources());

        LOG.info("Checking Disks...");
        printDisks(hal.getDiskStores());

        LOG.info("Checking File System...");
        printFileSystem(os.getFileSystem());

        LOG.info("Checking Network interfaces...");
        printNetworkInterfaces(hal.getNetworkIFs());

        LOG.info("Checking Network parameterss...");
        printNetworkParameters(os.getNetworkParams());

        // hardware: displays
        LOG.info("Checking Displays...");
        printDisplays(hal.getDisplays());

        // hardware: USB devices
        LOG.info("Checking USB Devices...");
        printUsbDevices(hal.getUsbDevices(true));
    }

    private static void printComputerSystem(final ComputerSystem computerSystem) {

        System.out.println("manufacturer: " + computerSystem.getManufacturer());
        System.out.println("model: " + computerSystem.getModel());
        System.out.println("serialnumber: " + computerSystem.getSerialNumber());
        final Firmware firmware = computerSystem.getFirmware();
        System.out.println("firmware:");
        System.out.println("  manufacturer: " + firmware.getManufacturer());
        System.out.println("  name: " + firmware.getName());
        System.out.println("  description: " + firmware.getDescription());
        System.out.println("  version: " + firmware.getVersion());
        System.out.println("  release date: " + (firmware.getReleaseDate() == null ? "unknown"
                : firmware.getReleaseDate() == null ? "unknown" : FormatUtil.formatDate(firmware.getReleaseDate())));
        final Baseboard baseboard = computerSystem.getBaseboard();
        System.out.println("baseboard:");
        System.out.println("  manufacturer: " + baseboard.getManufacturer());
        System.out.println("  model: " + baseboard.getModel());
        System.out.println("  version: " + baseboard.getVersion());
        System.out.println("  serialnumber: " + baseboard.getSerialNumber());
    }

    private static void printProcessor(CentralProcessor processor) {
        System.out.println(processor);
        System.out.println(" " + processor.getPhysicalPackageCount() + " physical CPU package(s)");
        System.out.println(" " + processor.getPhysicalProcessorCount() + " physical CPU core(s)");
        System.out.println(" " + processor.getLogicalProcessorCount() + " logical CPU(s)");

        System.out.println("Identifier: " + processor.getIdentifier());
        System.out.println("ProcessorID: " + processor.getProcessorID());
    }

    private static void printMemory(GlobalMemory memory) {
        System.out.println("Memory: " + FormatUtil.formatBytes(memory.getAvailable()) + "/"
                + FormatUtil.formatBytes(memory.getTotal()));
        System.out.println("Swap used: " + FormatUtil.formatBytes(memory.getSwapUsed()) + "/"
                + FormatUtil.formatBytes(memory.getSwapTotal()));
    }

    private static void printCpu(CentralProcessor processor) {
        System.out.println("Uptime: " + FormatUtil.formatElapsedSecs(processor.getSystemUptime()));
        System.out.println(
                "Context Switches/Interrupts: " + processor.getContextSwitches() + " / " + processor.getInterrupts());

        long[] prevTicks = processor.getSystemCpuLoadTicks();
        System.out.println("CPU, IOWait, and IRQ ticks @ 0 sec:" + Arrays.toString(prevTicks));
        // Wait a second...
        Util.sleep(1000);
        long[] ticks = processor.getSystemCpuLoadTicks();
        System.out.println("CPU, IOWait, and IRQ ticks @ 1 sec:" + Arrays.toString(ticks));
        long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
        long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
        long sys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
        long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
        long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
        long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
        long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
        long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
        long totalCpu = user + nice + sys + idle + iowait + irq + softirq + steal;

        System.out.format(
                "User: %.1f%% Nice: %.1f%% System: %.1f%% Idle: %.1f%% IOwait: %.1f%% IRQ: %.1f%% SoftIRQ: %.1f%% Steal: %.1f%%%n",
                100d * user / totalCpu, 100d * nice / totalCpu, 100d * sys / totalCpu, 100d * idle / totalCpu,
                100d * iowait / totalCpu, 100d * irq / totalCpu, 100d * softirq / totalCpu, 100d * steal / totalCpu);
        System.out.format("CPU load: %.1f%% (counting ticks)%n", processor.getSystemCpuLoadBetweenTicks() * 100);
        System.out.format("CPU load: %.1f%% (OS MXBean)%n", processor.getSystemCpuLoad() * 100);
        double[] loadAverage = processor.getSystemLoadAverage(3);
        System.out.println("CPU load averages:" + (loadAverage[0] < 0 ? " N/A" : String.format(" %.2f", loadAverage[0]))
                + (loadAverage[1] < 0 ? " N/A" : String.format(" %.2f", loadAverage[1]))
                + (loadAverage[2] < 0 ? " N/A" : String.format(" %.2f", loadAverage[2])));
        // per core CPU
        StringBuilder procCpu = new StringBuilder("CPU load per processor:");
        double[] load = processor.getProcessorCpuLoadBetweenTicks();
        for (double avg : load) {
            procCpu.append(String.format(" %.1f%%", avg * 100));
        }
        System.out.println(procCpu.toString());
    }

    private static void printProcesses(OperatingSystem os, GlobalMemory memory) {
        System.out.println("Processes: " + os.getProcessCount() + ", Threads: " + os.getThreadCount());
        // Sort by highest CPU
        List<OSProcess> procs = Arrays.asList(os.getProcesses(5, ProcessSort.CPU));

        System.out.println("   PID  %CPU %MEM       VSZ       RSS Name");
        for (int i = 0; i < procs.size() && i < 5; i++) {
            OSProcess p = procs.get(i);
            System.out.format(" %5d %5.1f %4.1f %9s %9s %s%n", p.getProcessID(),
                    100d * (p.getKernelTime() + p.getUserTime()) / p.getUpTime(),
                    100d * p.getResidentSetSize() / memory.getTotal(), FormatUtil.formatBytes(p.getVirtualSize()),
                    FormatUtil.formatBytes(p.getResidentSetSize()), p.getName());
        }
    }

    private static void printSensors(Sensors sensors) {
        System.out.println("Sensors:");
        System.out.format(" CPU Temperature: %.1f°C%n", sensors.getCpuTemperature());
        System.out.println(" Fan Speeds: " + Arrays.toString(sensors.getFanSpeeds()));
        System.out.format(" CPU Voltage: %.1fV%n", sensors.getCpuVoltage());
    }

    private static void printPowerSources(PowerSource[] powerSources) {
        StringBuilder sb = new StringBuilder("Power: ");
        if (powerSources.length == 0) {
            sb.append("Unknown");
        } else {
            double timeRemaining = powerSources[0].getTimeRemaining();
            if (timeRemaining < -1d) {
                sb.append("Charging");
            } else if (timeRemaining < 0d) {
                sb.append("Calculating time remaining");
            } else {
                sb.append(String.format("%d:%02d remaining", (int) (timeRemaining / 3600),
                        (int) (timeRemaining / 60) % 60));
            }
        }
        for (PowerSource pSource : powerSources) {
            sb.append(String.format("%n %s @ %.1f%%", pSource.getName(), pSource.getRemainingCapacity() * 100d));
        }
        System.out.println(sb.toString());
    }

    private static void printDisks(HWDiskStore[] diskStores) {
        System.out.println("Disks:");
        for (HWDiskStore disk : diskStores) {
            boolean readwrite = disk.getReads() > 0 || disk.getWrites() > 0;
            System.out.format(" %s: (model: %s - S/N: %s) size: %s, reads: %s (%s), writes: %s (%s), xfer: %s ms%n",
                    disk.getName(), disk.getModel(), disk.getSerial(),
                    disk.getSize() > 0 ? FormatUtil.formatBytesDecimal(disk.getSize()) : "?",
                    readwrite ? disk.getReads() : "?", readwrite ? FormatUtil.formatBytes(disk.getReadBytes()) : "?",
                    readwrite ? disk.getWrites() : "?", readwrite ? FormatUtil.formatBytes(disk.getWriteBytes()) : "?",
                    readwrite ? disk.getTransferTime() : "?");
            HWPartition[] partitions = disk.getPartitions();
            if (partitions == null) {
                // TODO Remove when all OS's implemented
                continue;
            }
            for (HWPartition part : partitions) {
                System.out.format(" |-- %s: %s (%s) Maj:Min=%d:%d, size: %s%s%n", part.getIdentification(),
                        part.getName(), part.getType(), part.getMajor(), part.getMinor(),
                        FormatUtil.formatBytesDecimal(part.getSize()),
                        part.getMountPoint().isEmpty() ? "" : " @ " + part.getMountPoint());
            }
        }
    }

    private static void printFileSystem(FileSystem fileSystem) {
        System.out.println("File System:");

        System.out.format(" File Descriptors: %d/%d%n", fileSystem.getOpenFileDescriptors(),
                fileSystem.getMaxFileDescriptors());

        OSFileStore[] fsArray = fileSystem.getFileStores();
        for (OSFileStore fs : fsArray) {
            long usable = fs.getUsableSpace();
            long total = fs.getTotalSpace();
            System.out.format(
                    " %s (%s) [%s] %s of %s free (%.1f%%) is %s "
                            + (fs.getLogicalVolume() != null && fs.getLogicalVolume().length() > 0 ? "[%s]" : "%s")
                            + " and is mounted at %s%n",
                    fs.getName(), fs.getDescription().isEmpty() ? "file system" : fs.getDescription(), fs.getType(),
                    FormatUtil.formatBytes(usable), FormatUtil.formatBytes(fs.getTotalSpace()), 100d * usable / total,
                    fs.getVolume(), fs.getLogicalVolume(), fs.getMount());
        }
    }

    private static void printNetworkInterfaces(NetworkIF[] networkIFs) {
        System.out.println("Network interfaces:");
        for (NetworkIF net : networkIFs) {
            System.out.format(" Name: %s (%s)%n", net.getName(), net.getDisplayName());
            System.out.format("   MAC Address: %s %n", net.getMacaddr());
            System.out.format("   MTU: %s, Speed: %s %n", net.getMTU(), FormatUtil.formatValue(net.getSpeed(), "bps"));
            System.out.format("   IPv4: %s %n", Arrays.toString(net.getIPv4addr()));
            System.out.format("   IPv6: %s %n", Arrays.toString(net.getIPv6addr()));
            boolean hasData = net.getBytesRecv() > 0 || net.getBytesSent() > 0 || net.getPacketsRecv() > 0
                    || net.getPacketsSent() > 0;
            System.out.format("   Traffic: received %s/%s%s; transmitted %s/%s%s %n",
                    hasData ? net.getPacketsRecv() + " packets" : "?",
                    hasData ? FormatUtil.formatBytes(net.getBytesRecv()) : "?",
                    hasData ? " (" + net.getInErrors() + " err)" : "",
                    hasData ? net.getPacketsSent() + " packets" : "?",
                    hasData ? FormatUtil.formatBytes(net.getBytesSent()) : "?",
                    hasData ? " (" + net.getOutErrors() + " err)" : "");
        }
    }

    private static void printNetworkParameters(NetworkParams networkParams) {
        System.out.println("Network parameters:");
        System.out.format(" Host name: %s%n", networkParams.getHostName());
        System.out.format(" Domain name: %s%n", networkParams.getDomainName());
        System.out.format(" DNS servers: %s%n", Arrays.toString(networkParams.getDnsServers()));
        System.out.format(" IPv4 Gateway: %s%n", networkParams.getIpv4DefaultGateway());
        System.out.format(" IPv6 Gateway: %s%n", networkParams.getIpv6DefaultGateway());
    }

    private static void printDisplays(Display[] displays) {
        System.out.println("Displays:");
        int i = 0;
        for (Display display : displays) {
            System.out.println(" Display " + i + ":");
            System.out.println(display.toString());
            i++;
        }
    }

    private static void printUsbDevices(UsbDevice[] usbDevices) {
        System.out.println("USB Devices:");
        for (UsbDevice usbDevice : usbDevices) {
            System.out.println(usbDevice.toString());
        }
    }
}

3、测试结果

2021-09-03 11:23:41,933 INFO SystemInfoTest:59 - Started SystemInfoTest in 5.556 seconds (JVM running for 6.849)
2021-09-03 11:23:42,289 INFO SystemInfoTest:41 - Initializing System…
Microsoft Windows 10 build 17763
2021-09-03 11:23:42,589 INFO SystemInfoTest:49 - Checking computer system…
manufacturer: System manufacturer
model: System Product Name
serialnumber: System Serial Number
firmware:
manufacturer: American Megatrends Inc.
name: BIOS Date: 06/20/18 19:09:08 Ver: 05.0000D
description: BIOS Date: 06/20/18 19:09:08 Ver: 05.0000D
version: ALASKA - 1072009
release date: 06/20/2018
baseboard:
manufacturer: ASUSTeK COMPUTER INC.
model: unknown
version: Rev X.0x
serialnumber: 180732055100087
2021-09-03 11:23:42,674 INFO SystemInfoTest:52 - Checking Processor…
Intel® Core™ i5-8500 CPU @ 3.00GHz
1 physical CPU package(s)
6 physical CPU core(s)
6 logical CPU(s)
Identifier: Intel64 Family 6 Model 158 Stepping 10
ProcessorID: BFEBFBFF000906EA
2021-09-03 11:23:46,992 INFO SystemInfoTest:55 - Checking Memory…
Memory: 9.7 GiB/15.8 GiB
Swap used: 0 bytes/16 GiB
2021-09-03 11:23:47,046 INFO SystemInfoTest:58 - Checking CPU…
Uptime: 0 days, 02:54:33
Context Switches/Interrupts: 99067944 / 79338270
CPU, IOWait, and IRQ ticks @ 0 sec:[1695625, 0, 901650, 60230843, 0, 5197, 8497, 0]
CPU, IOWait, and IRQ ticks @ 1 sec:[1695671, 0, 901665, 60236875, 0, 5197, 8497, 0]
User: 0.8% Nice: 0.0% System: 0.2% Idle: 99.0% IOwait: 0.0% IRQ: 0.0% SoftIRQ: 0.0% Steal: 0.0%
CPU load: 4.3% (counting ticks)
CPU load: 6.2% (OS MXBean)
CPU load averages: N/A N/A N/A
CPU load per processor: 6.5% 1.3% 6.5% 0.0% 7.7% 9.1%
2021-09-03 11:23:48,163 INFO SystemInfoTest:61 - Checking Processes…
Processes: 169, Threads: 2033
PID %CPU %MEM VSZ RSS Name
0 100.0 0.0 8 KiB 8 KiB System Idle Process
13172 95.9 2.5 9.7 GiB 408.4 MiB javaw.exe
10148 5.6 0.2 2.0 TiB 25.3 MiB WmiPrvSE.exe
9928 4.2 0.0 2.0 TiB 6.6 MiB WmiPrvSE.exe
2616 3.5 6.8 39.6 GiB 1.1 GiB eclipse.exe
2021-09-03 11:23:53,388 INFO SystemInfoTest:64 - Checking Sensors…
Sensors:
2021-09-03 11:23:53,396 ERROR WmiUtil:409 - Could not connect to namespace root\OpenHardwareMonitor. Error code = 0x8004100e
CPU Temperature: 28.0°C
2021-09-03 11:23:53,487 ERROR WmiUtil:409 - Could not connect to namespace root\OpenHardwareMonitor. Error code = 0x8004100e
Fan Speeds: [0]
2021-09-03 11:23:53,507 ERROR WmiUtil:409 - Could not connect to namespace root\OpenHardwareMonitor. Error code = 0x8004100e
CPU Voltage: 0.0V
2021-09-03 11:23:53,536 INFO SystemInfoTest:67 - Checking Power sources…
Power: Calculating time remaining
Unknown @ 0.0%
2021-09-03 11:23:53,540 INFO SystemInfoTest:70 - Checking Disks…
Disks:
\.\PHYSICALDRIVE0: (model: ST1000DM010-2EP102 (标准磁盘驱动器) - S/N: W9AD5TQQ) size: 1.0 TB, reads: 138306 (3.9 GiB), writes: 131328 (1.7 GiB), xfer: 4511539 ms
|-- 磁盘 #0,分区 #0: Installable File System (可安装的文件系统) Maj:Min=0:0, size: 85.9 GB @ C:
|-- 磁盘 #0,分区 #1: Extended w/Extended Int 13 (Extended w/Extended Int 13) Maj:Min=0:1, size: 914.3 GB @ F:
2021-09-03 11:23:53,635 INFO SystemInfoTest:73 - Checking File System…
File System:
File Descriptors: 0/0
本地固定磁盘 (C:) (Fixed drive) [NTFS] 38.7 GiB of 80.0 GiB free (48.3%) is \?\Volume{f0875368-0000-0000-0000-100000000000}\ and is mounted at C:
本地固定磁盘 (D:) (Fixed drive) [NTFS] 208.8 GiB of 284.0 GiB free (73.5%) is \?\Volume{f0875368-0000-0000-0000-300014000000}\ and is mounted at D:
本地固定磁盘 (E:) (Fixed drive) [NTFS] 88.6 GiB of 284.0 GiB free (31.2%) is \?\Volume{f0875368-0000-0000-0000-50005b000000}\ and is mounted at E:
本地固定磁盘 (F:) (Fixed drive) [NTFS] 279.2 GiB of 283.5 GiB free (98.5%) is \?\Volume{f0875368-0000-0000-0000-7000a2000000}\ and is mounted at F:
2021-09-03 11:23:53,713 INFO SystemInfoTest:76 - Checking Network interfaces…
Network interfaces:
Name: eth0 (VMware Virtual Ethernet Adapter for VMnet1)
MAC Address: 00:50:56:c0:00:01
MTU: 1500, Speed: 100 Mbps
IPv4: [192.168.195.1]
IPv6: [fe80:0:0:0:1123:3391:feda:6086]
Traffic: received 24 packets/24 bytes (0 err); transmitted 21 packets/2.5 KiB (0 err)
Name: eth1 (VMware Virtual Ethernet Adapter for VMnet8)
MAC Address: 00:50:56:c0:00:08
MTU: 1500, Speed: 100 Mbps
IPv4: [192.168.128.1]
IPv6: [fe80:0:0:0:6d5d:5cd7:87cf:d746]
Traffic: received 24 packets/24 bytes (0 err); transmitted 21 packets/7.2 KiB (0 err)
Name: wlan1 (Microsoft Wi-Fi Direct Virtual Adapter #9)
MAC Address: 08:10:78:3f:f6:ae
MTU: 1500, Speed: 0 bps
IPv4: []
IPv6: [fe80:0:0:0:4892:432f:272f:35a6]
Traffic: received ?/?; transmitted ?/?
Name: eth5 (Realtek PCIe GBE Family Controller)
MAC Address: 0c:9d:92:bb:c4:60
MTU: 1500, Speed: 1 Gbps
IPv4: [192.168.137.112]
IPv6: [fe80:0:0:0:ccd6:7f6e:8e13:21d1]
Traffic: received 2 packets/1.9 MiB (0 err); transmitted 2 packets/529.4 KiB (0 err)
Name: wlan3 (Realtek RTL8188EU Wireless LAN 802.11n USB 2.0 Network Adapter #5)
MAC Address: 08:10:78:3f:f6:ae
MTU: 1500, Speed: 72.2 Mbps
IPv4: [192.168.1.32]
IPv6: [fe80:0:0:0:942e:200f:ee7d:4462]
Traffic: received 163630 packets/143.2 MiB (0 err); transmitted 113177 packets/20.7 MiB (0 err)
Name: wlan4 (Microsoft Wi-Fi Direct Virtual Adapter #8)
MAC Address: 0a:10:78:3f:f6:ae
MTU: 1500, Speed: 0 bps
IPv4: []
IPv6: [fe80:0:0:0:5c54:9c54:8d28:1039]
Traffic: received ?/?; transmitted ?/?
2021-09-03 11:23:54,973 INFO SystemInfoTest:79 - Checking Network parameterss…
Network parameters:
Host name: PC-wx_z
Domain name: PC-wx_z
DNS servers: [192.168.1.1]
IPv4 Gateway: 192.168.1.1
IPv6 Gateway:
2021-09-03 11:23:55,137 INFO SystemInfoTest:83 - Checking Displays…
Displays:
Display 0:
Manuf. ID=DEL, Product ID=d0a2, Digital, Serial=0SAI, ManufDate=7/2018, EDID v1.4
53 x 30 cm (20.9 x 11.8 in)
Preferred Timing: Clock 148MHz, Active Pixels 1920x1080
Serial Number: XN09C87J0SAI
Monitor Name: DELL SE2416HM
Range Limits: Field Rate 56-76 Hz vertical, 30-83 Hz horizontal, Max clock: 170 MHz
2021-09-03 11:23:55,144 INFO SystemInfoTest:87 - Checking USB Devices…
USB Devices:
Intel® USB 3.1 可扩展主机控制器 - 1.10 (Microsoft) (通用 USB xHCI 主机控制器)
|-- USB 根集线器(USB 3.0) ((标准 USB 集线器))
|-- Realtek RTL8188EU Wireless LAN 802.11n USB 2.0 Network Adapter #5 (Realtek Semiconductor Corp.)
|-- Microsoft Wi-Fi Direct Virtual Adapter #8 (Microsoft)
|-- Microsoft Wi-Fi Direct Virtual Adapter #9 (Microsoft)
|-- USB Composite Device ((标准 USB 主控制器))
|-- USB 输入设备 ((标准系统设备))
|-- HID Keyboard Device ((标准键盘))
|-- USB 输入设备 ((标准系统设备))
|-- HID Keyboard Device ((标准键盘))
|-- HID Keyboard Device ((标准键盘))
|-- 符合 HID 标准的用户控制设备 (Microsoft)
|-- USB 输入设备 ((标准系统设备))
|-- HID-compliant mouse (Microsoft)
|-- USB-SERIAL CH340 (COM12) (wch.cn)
2021-09-03 11:23:55,427 INFO GenericWebApplicationContext:993 - Closing org.springframework.web.context.support.GenericWebApplicationContext@662f5666: startup date [Fri Sep 03 11:23:36 CST 2021]; root of context hierarchy
2021-09-03 11:23:55,434 INFO DruidDataSource:1825 - {dataSource-1} closed

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值