SpringBoot监控服务器内存信息简介

/**
* 定时任务监控服务器内存信息
*/
@Component
public class OsMonitorScheduleTask implements Runnable {@Resourceprivate OsMonitorMapper osMonitorMapper;@Resourceprivate SystemUserMapper systemUserMapper;private final FeedbackData feedbackData;private static final Logger log = LoggerFactory.getLogger(ValidCheckTask.class);@Autowiredpublic OsMonitorScheduleTask(FeedbackData feedbackData) {this.feedbackData = feedbackData;}@Overridepublic void run() {try {doBusiness();} catch (Exception e) {log.error("It has an error when get monitor info. message:{}", e.getMessage());}}/*** 具体业务处理*/private void doBusiness() {// 重新加载配置ConfigProperties.loadConfig(FileUtils.getWebRootPath());int WARNING_THRESHOLD = Integer.parseInt(ConfigProperties.getKey(ConfigList.BASIC, "ALARM_THRESHOLD"));int sentType = Integer.parseInt(ConfigProperties.getKey(ConfigList.BASIC, "ALARM_SEND_TYPE"));OsMonitorInfoBean monitorInfo = OsMonitorUtils.GetMonitorInfo();monitorInfo.setThreshold(WARNING_THRESHOLD);monitorInfo.setRecordTime(new java.util.Date());double cpuRatio = Double.parseDouble(monitorInfo.getCpuRatio());if (cpuRatio < WARNING_THRESHOLD) {monitorInfo.setWarning(0);osMonitorMapper.osMonitorLogInsert(monitorInfo);return;}
monitorInfo.setWarning(1);OsMonitorInfoBean lastAlarm = osMonitorMapper.getLatestAlarmedMonitorInfo();long alarmInterval = Long.parseLong(ConfigProperties.getKey(ConfigList.BASIC, "ALARM_INTERVAL_MINUTE"));if (lastAlarm != null && ((new java.util.Date().getTime() - lastAlarm.getRecordTime().getTime()) <= (alarmInterval - 2) * 60 * 1000)) {monitorInfo.setAlarmType(0);osMonitorMapper.osMonitorLogInsert(monitorInfo);return; // 存在上一次报警但不超过 alarmInterval 分钟, 不报警}List<SystemUserBean> adminUsers = systemUserMapper.getSystemUserByName("superUser");// 短信通知管理员if (sentType == 0) {monitorInfo.setAlarmType(0);osMonitorMapper.osMonitorLogInsert(monitorInfo);log.error("突破报警阈值,但不发送报警信息");} else if (sentType == 1) {  // 发短信monitorInfo.setAlarmType(1);monitorInfo.setAlarmAddr(adminUsers.get(0).getPhone());osMonitorMapper.osMonitorLogInsert(monitorInfo);SendSmsMessage(WARNING_THRESHOLD, cpuRatio, adminUsers);} else if (sentType == 2) {  // 发邮箱monitorInfo.setAlarmType(2);monitorInfo.setAlarmAddr(adminUsers.get(0).getEmail());osMonitorMapper.osMonitorLogInsert(monitorInfo);SendMailMessage(WARNING_THRESHOLD, cpuRatio, adminUsers);} else if (sentType == 3) {  // 短信、邮箱同时发monitorInfo.setAlarmType(3);monitorInfo.setAlarmAddr(adminUsers.get(0).getPhone() + ";" + adminUsers.get(0).getEmail());osMonitorMapper.osMonitorLogInsert(monitorInfo);SendSmsMessage(WARNING_THRESHOLD, cpuRatio, adminUsers);SendMailMessage(WARNING_THRESHOLD, cpuRatio, adminUsers);}}// 发送短信private void SendSmsMessage(int WARNING_THRESHOLD, double cpuRatio, List<SystemUserBean> adminUsers) {if (adminUsers == null || adminUsers.size() == 0|| adminUsers.get(0).getPhone() == null|| adminUsers.get(0).getPhone().equals("")) {return;}FeedBack.addFeedbackMessage(message);}// 发送邮箱private void SendMailMessage(int WARNING_THRESHOLD, double cpuRatio, List<SystemUserBean> adminUsers) {if (adminUsers == null || adminUsers.size() == 0|| adminUsers.get(0).getEmail() == null|| adminUsers.get(0).getEmail().equals("")) {return;}FeedBackMessageBean message = new FeedBackMessageBean();String mailContact = adminUsers.get(0).getEmail();message.setContact(mailContact);message.setMsgtype(FeedbackDataType.MAIL_TYPE);message.setSubject("后台CPU报警");message.setContent(String.format("后台CPU使用率已达 %.2f%%,超过阈值 %2d%%,请关注。", cpuRatio, WARNING_THRESHOLD));feedbackData.addFeedbackMessage(message);}
}

FeedBack

@Component
public class FeedbackData {private static ConcurrentLinkedQueue<FeedBackMessageBean> queue = new ConcurrentLinkedQueue<FeedBackMessageBean>();private final RBlockingQueue<FeedBackMessageBean> rQueue;@Autowiredpublic FeedbackData(RBlockingQueueService rBlockingQueueService) {rQueue = rBlockingQueueService.getBlockingQueue("FeedBackMessage");}/*** 添加信息到队列等待发送** @param messageBean FeedBackMessageBean*/public void addFeedbackMessage(FeedBackMessageBean messageBean) {if (messageBean != null) {//queue.add(messageBean);rQueue.add(messageBean);}}/*** 获取队列任务信息** @return FeedBackMessageBean*/public FeedBackMessageBean getFeedbackMessage() {if (!rQueue.isEmpty()) {return rQueue.poll();}return null}
}

SendFeedBack

public class SendFeedbackTask implements Runnable {private static final Logger logger = LoggerFactory.getLogger(SendFeedbackTask.class);private final FeedbackData feedbackData;/*** 线程是否存活*/private boolean alive = false;/*** 消息处理线程*/private Thread t = null;@Autowiredpublic SendFeedbackTask(FeedbackData feedbackData) {this.feedbackData = feedbackData;}/*** 关闭线程*/public void stop() {alive = false;}/*** 启动线程*/public void start() {alive = true;t = new Thread(this);t.setName(this.getClass().getSimpleName());t.start();}@Overridepublic void run() {do {try {if (!doBusiness()) {try {Thread.sleep(100);} catch (Exception e) {logger.error("It has an error when thread sleep.");}}} catch (Exception e) {try {Thread.sleep(100);} catch (Exception ee) {logger.error("It has an error when thread sleep.");}logger.debug("It has an error when receive message. {}", e.getLocalizedMessage());}} while (alive);}
private boolean doBusiness() {FeedBackMessageBean message = feedbackData.getFeedbackMessage();if (message != null) {if (message.getMsgtype() == FeedbackDataType.SMS_TYPE) {SmsServerBean smsBean = (SmsServerBean) ConfigData.getConfigData(FieldConstants.SMS_SERVER_TYPE);if (smsBean == null || StringUtils.isEmpty(smsBean.getAccessKeyID())|| StringUtils.isEmpty(smsBean.getAccessKeySecret())|| StringUtils.isEmpty(smsBean.getSignName())|| StringUtils.isEmpty(smsBean.getFeedBackTemplateCode())|| StringUtils.isEmpty(smsBean.getAuthTemplateCode())) {logger.error("It has an error when get the sms template.");return false;}if (!StringUtils.isEmpty(message.getContent()) && !StringUtils.isEmpty(message.getContact())) {if (message.getSmstype() == FeedbackDataType.SMS_QUESTION_TYPE) {String content = "{'question':'" + message.getContent() + "'}";SMSUtils.sendSMSByAliyun(smsBean, message.getContact(), smsBean.getFeedBackTemplateCode(),content);}if (message.getSmstype() == FeedbackDataType.SMS_AUTH_TYPE) {String content = "{'reason':'" + message.getContent() + "'}";SMSUtils.sendSMSByAliyun(smsBean, message.getContact(), smsBean.getAuthTemplateCode(), content);}if (!StringUtils.isEmpty(message.getContent()) && !StringUtils.isEmpty(message.getContact())) {if (message.getSmstype() == FeedbackDataType.SMS_ALARM_TYPE) {String content = "{'param':'" + message.getContent() + "'}";SMSUtils.sendSMSByAliyun(smsBean, message.getContact(), smsBean.getAlarmTemplateCode(), content);}}return true;}}if (message.getMsgtype() == FeedbackDataType.MAIL_TYPE) {MailServerBean mailServerBean = (MailServerBean) ConfigData.getConfigData(FieldConstants.MAIL_SERVER_TYPE);if (mailServerBean == null || StringUtils.isEmpty(mailServerBean.getHost())|| StringUtils.isEmpty(mailServerBean.getPort())|| StringUtils.isEmpty(mailServerBean.getMail())|| StringUtils.isEmpty(mailServerBean.getPassword())) {logger.error("It has an error when get the mail template.");return false;}
MailMessage mailInfo = new MailMessage();mailInfo.setMailServerHost(mailServerBean.getHost());mailInfo.setMailServerPort(mailServerBean.getPort());mailInfo.setValidate(true);mailInfo.setUserName(mailServerBean.getMail());mailInfo.setPassword(mailServerBean.getPassword());mailInfo.setFromAddress(mailServerBean.getFromaddress());String mailBody = message.getContent();boolean useHtmlTemplate = message.getUseHtmlTemplate();if (!useHtmlTemplate) {  // 没有使用模板时需要替换mailBody = mailBody.replaceAll(" ", "&nbsp;");mailBody = mailBody.replaceAll("\n", "<br/>");}mailInfo.setToAddress(message.getContact());mailInfo.setSubject(message.getSubject());mailInfo.setContent(mailBody);if (MailSender.sendHtmlMail(mailInfo)) {logger.info("success to send mail. receiver={}", message.getContact());} else {logger.info("failed to send mail. receiver={}", message.getContact());}}}return false;}
}

邮件内容主题

    // 发送邮件的服务器的IP和端口private String mailServerHost;private String mailServerPort = "25";// 邮件发送者的地址private String fromAddress;// 邮件接收者的地址private String toAddress;// 登陆邮件发送服务器的用户名和密码private String userName;private String password;// 是否需要身份验证private boolean validate = false;// 邮件主题private String subject;// 邮件的文本内容private String content;// 邮件附件的文件名private String[] attachFileNames;// 重传次数 最多3次private Integer reSentTimes = 0;/*** 获得邮件会话属性*/public Properties getProperties() {Properties p = new Properties();MailSSLSocketFactory sf = null;try {sf = new MailSSLSocketFactory();} catch (GeneralSecurityException e1) {e1.printStackTrace();log.error("getProperties get an exception:" + e1.getLocalizedMessage());return p;}sf.setTrustAllHosts(true);p.put("mail.smtp.host", this.mailServerHost);p.put("mail.smtp.port", this.mailServerPort);if ("ON".equalsIgnoreCase(ConfigProperties.getKey(ConfigList.BASIC, "SMTP_TLS"))) {p.put("mail.smtp.starttls.enable", "true");} else {p.put("mail.smtp.starttls.enable", "false");}p.put("mail.smtp.connectiontimeout", "30000");p.put("mail.smtp.timeout", "30000");p.put("mail.smtp.auth", validate ? "true" : "false");p.put("mail.pop3.socketFactory", sf);p.put("mail.pop3.socketFactory.fallback", "false");p.put("mail.pop3.port", "995");p.put("mail.pop3.socketFactory.port", "995");p.put("mail.pop3.disabletop", "true");p.put("mail.pop3.ssl.enable", "true");p.put("mail.pop3.useStartTLS", "true");return p;}

系统内存信息

    /*** 操作系统名*/private String osName;/*** cpu使用率.*/private String cpuRatio;/*** 系统总内存*/private String osTotalMemory;/*** 系统剩余内存.*/private String osFreeMemory;/*** 最大可获取内存.*/private String maxReachableMemory;/*** 已分配的内存的剩余量*/private String allocatedFreeMemory;/*** 已分配的内存的使用量*/private String allocatedUsedMemory;/*** 最大可使用内存*/private String maxUsableMemory;/*** 线程总数*/private Integer appThread;/*** 记录时间*/private Date recordTime;/*** 报警阈值*/private Integer threshold;/*** 是否报警*/private Integer warning;/*** 报警类型 0:不报警,1:短信,2:邮箱,3:短信+邮箱*/private Integer alarmType;/*** 报警地址(短信/邮箱)*/private String alarmAddr;

获取系统信息

/**
*
* 获取系统信息
*/
public class getSystemInfoUtils{/*** 获取 OS Name*/private static String GetOsName() {return System.getProperty("os.name");}/*** 获取 JVM 参数*/private static void GetJvmMemoryInfo(OsMonitorInfoBean infoBean) {double mb = 1024 * 1024 * 1.0;// jvmdouble totalMemory = Runtime.getRuntime().totalMemory() / mb;double freeMemory = Runtime.getRuntime().freeMemory() / mb;double maxMemory = Runtime.getRuntime().maxMemory() / mb;DecimalFormat df = new DecimalFormat("#.##M");// MonitorInfoinfoBean.setMaxReachableMemory(df.format(maxMemory - totalMemory));infoBean.setAllocatedFreeMemory(df.format(freeMemory));infoBean.setAllocatedUsedMemory(df.format(totalMemory - freeMemory));infoBean.setMaxUsableMemory(df.format(maxMemory));}/*** 得到类所在磁盘*/public static String getClassLocaledDisk() {Class<OsMonitorUtils> thisClass = OsMonitorUtils.class;try {String strClassName = thisClass.getName();String strPackageName = "";if (thisClass.getPackage() != null) {strPackageName = thisClass.getPackage().getName();}String strClassFileName = "";if (!"".equals(strPackageName)) {strClassFileName = strClassName.substring(strPackageName.length() + 1);} else {strClassFileName = strClassName;}URL url = null;url = thisClass.getResource(strClassFileName + ".class");String strURL = url.toString();strURL = strURL.substring(strURL.indexOf('/') + 1);//返回当前类的路径,并且处理路径中的空格,因为在路径中出现的空格如果不处理的话,//在访问时就会从空格处断开,那么也就取不到完整的信息了,这个问题在web开发中尤其要注意return strURL.substring(0, strURL.indexOf('/'));} catch (Exception ex) {ex.printStackTrace();throw ex;}}/*** 获取App运行中的线程数*/private static int GetAppProcessingNum() {try {//获取所有运行中的线程Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();return map.size();} catch (Exception e) {e.printStackTrace();}return -1;}public static final SystemInfo si = new SystemInfo();public static final CentralProcessor cpu = si.getHardware().getProcessor();public static final Object oshiLock = new Object();static {cpu.getSystemCpuLoadTicks();   // 预加载一下,第一次调用很慢}/*** 获取 Oshi CPU 综合使用率*/public static String GetOshiCpuRadio(CentralProcessor processor) {long[] oldTicks = processor.getSystemCpuLoadTicks();// 睡眠1stry {TimeUnit.MILLISECONDS.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}double totalCpu = processor.getSystemCpuLoadBetweenTicks(oldTicks);DecimalFormat df = new DecimalFormat("#.##");return df.format(totalCpu * 100D);}// ***************使用第三方框架OSHI获取系统信息************ ///*** 获取 Oshi 内存*/public static GlobalMemory GetOshiMemory(SystemInfo si) {return si.getHardware().getMemory();}/*** 获取 Oshi 总内存*/public static String GetOshiTotalMemory(GlobalMemory memory) {Double total = (double) memory.getTotal() / 1024 / 1024;DecimalFormat df = new DecimalFormat("#.##M");return df.format(total);}/*** 获取 Oshi 可用内存*/public static String GetOshiFreeMemory(GlobalMemory memory) {Double free = (double) memory.getAvailable() / 1024 / 1024;DecimalFormat df = new DecimalFormat("#.##M");return df.format(free);}/*** 获取 Oshi 内存占比*/public static String GetOshiMemoryPerc(SystemInfo si) {GlobalMemory memory = si.getHardware().getMemory();double total = (double) memory.getTotal();double used = total - (double) memory.getAvailable();double perc = used / total;DecimalFormat df = new DecimalFormat("#0");return df.format(perc * 100D);}/*** 获取 Oshi 磁盘使用占比*/public static String GetOshiDiskPerc(SystemInfo si) {FileSystem fileSystem = si.getOperatingSystem().getFileSystem();List<OSFileStore> fileStores = fileSystem.getFileStores();double usable = 0;double total = 0;double perc = 0;int diskCount = 0;for (OSFileStore store : fileStores) {logger.info("fileStore name: {}", store.getName());usable += (double) store.getUsableSpace();total += (double) store.getTotalSpace();perc += (total - usable) / total * 100D;diskCount++;}DecimalFormat df = new DecimalFormat("#0");if (diskCount != 0) {return df.format(perc / diskCount);} else {return df.format(0);}}获取监控信息 //////// 获取监控信息public static OsMonitorInfoBean GetMonitorInfo() {// return GetSigarMonitorInfo();return GetOshiMonitorInfo();}public static OsMonitorInfoBean GetOshiMonitorInfo() {synchronized (oshiLock) {OsMonitorInfoBean infoBean = new OsMonitorInfoBean();infoBean.setOsName(GetOsName());infoBean.setCpuRatio(GetOshiCpuRadio(cpu));GlobalMemory memory = GetOshiMemory(si);infoBean.setOsTotalMemory(GetOshiTotalMemory(memory));infoBean.setOsFreeMemory(GetOshiFreeMemory(memory));GetJvmMemoryInfo(infoBean);infoBean.setAppThread(GetAppProcessingNum());return infoBean;}}/*** CPU的用户使用量、系统使用剩余量、总的剩余量、总的使用占用量等(单位:100%)*/public static String getCpuPerc() {return getOshiCpuPerc();}/*** 内存资源信息*/public static String getPhysicalMemory() {return getOshiMemoryPerc();}/*** 资源信息(主要是硬盘) 平均占比* 取硬盘已有的分区及其详细信息* 通过 sigar.getFileSystemList()来获得FileSystem列表对象,然后对其进行编历*/public static String getFileSystemInfo() {return getOshiFileSystemInfo();}private static final SystemInfo si = OsMonitorUtils.si;private static final CentralProcessor cpu = OsMonitorUtils.cpu;private static final Object oshiLock = OsMonitorUtils.oshiLock;/*** CPU使用占比*/public static String getOshiCpuPerc() {synchronized (oshiLock) {return OsMonitorUtils.GetOshiCpuRadio(cpu);}}/*** 内存使用占比*/public static String getOshiMemoryPerc() {synchronized (oshiLock) {return OsMonitorUtils.GetOshiMemoryPerc(si);}}/*** 磁盘使用占比*/public static String getOshiFileSystemInfo() {synchronized (oshiLock) {return OsMonitorUtils.GetOshiDiskPerc(si);}}// 获取操作平台信息public static String getOsPrefix() {String arch = System.getProperty("os.arch").toLowerCase();final String name = System.getProperty("os.name");String osPrefix;switch (Platform.getOSType()) {case Platform.WINDOWS: {if ("i386".equals(arch))arch = "x86";osPrefix = "win32-" + arch;}break;case Platform.LINUX: {if ("x86".equals(arch)) {arch = "i386";} else if ("x86_64".equals(arch)) {arch = "amd64";}osPrefix = "linux-" + arch;}break;case Platform.MAC: {//mac系统的os.arch都是ppc(老版本的mac是powerpc,已经基本不用)看不出系统位数,使用下面的参数表示arch = System.getProperty("sun.arch.data.model");osPrefix = "mac-" + arch;}break;default: {osPrefix = name.toLowerCase();if ("x86".equals(arch)) {arch = "i386";}if ("x86_64".equals(arch)) {arch = "amd64";}int space = osPrefix.indexOf(" ");if (space != -1) {osPrefix = osPrefix.substring(0, space);}osPrefix += "-" + arch;}break;}return osPrefix;}public static String getOsName() {String osName = "";String osPrefix = getOsPrefix();if (osPrefix.toLowerCase().startsWith("win32-x86")|| osPrefix.toLowerCase().startsWith("win32-amd64")) {osName = "win";} else if (osPrefix.toLowerCase().startsWith("linux-i386")|| osPrefix.toLowerCase().startsWith("linux-amd64")) {osName = "linux";} else if (osPrefix.toLowerCase().startsWith("mac-64")|| osPrefix.toLowerCase().startsWith("mac-32")) {osName = "mac";}return osName;}}

SpringBoot自带的Health Indicator

使用

引入依赖

     <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId></dependency>

配置

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

info.app.author=DigitalSonic
info.app.encoding=@project.build.sourceEncoding@

定义自己的Indicator实现HealthIndicator接口

@Component
public class MyIndicator implements HealthIndicator {@Autowiredprivate CoffeeService coffeeService;@Overridepublic Health health() {// 用于判断的指标long count = coffeeService.getCoffeeCount();Health health;if (count > 0) {health = Health.up().withDetail("count", count).withDetail("message", "We have enough coffee.").build();} else {health = Health.down().withDetail("count", 0).withDetail("message", "We are out of coffee.").build();}return health;}
}

SpringBoot监控服务器信息以及SpringBoot自带Health Indicator相关推荐

  1. springboot监控服务器信息,面试官:聊一聊SpringBoot服务监控机制

    目录 前言 任何一个服务如果没有监控,那就是两眼一抹黑,无法知道当前服务的运行情况,也就无法对可能出现的异常状况进行很好的处理,所以对任意一个服务来说,监控都是必不可少的. 就目前而言,大部分微服务应 ...

  2. java监测服务器信息(cpu,内存,运行时间等),springboot监控服务器信息

    目录 1.添加工程依赖 2. 依赖工具类 3. 使用 PS:工具类代码 model Cpu.java Jvm.java Mem.java Sys.java SysFile.java utils Ari ...

  3. springBoot JPA 数据库字段(实体类)带下划线在扩展findBy方法时出错的解决办法

    springBoot JPA 数据库字段(实体类)带下划线在扩展findBy方法时出错的解决办法 参考文章: (1)springBoot JPA 数据库字段(实体类)带下划线在扩展findBy方法时出 ...

  4. 微信公众号网页OAuth2.0授权登录并获取用户信息(SpringBoot实现)

    微信公众号网页OAuth2.0授权登录并获取用户信息(SpringBoot实现) 文章目录 微信公众号网页OAuth2.0授权登录并获取用户信息(SpringBoot实现) 准备工作 开发思路 具体代 ...

  5. ava Springboot养老院信息管理系统源码

    Java Springboot养老院信息管理系统源码 开发语言 : JAVA 数据库 : MySQL 开发工具 : IDEA 源码类型 : WebForm 开源地址:http://www.taoydm ...

  6. 基于SpringBoot旅游信息管理系统

    <基于SpringBoot旅游信息管理系统>该项目采用技术: 后台使用了springboot+ssm框架 前端使用html+css+layui,界面美观大方 mysql数据库+tomcat ...

  7. springboot+人事信息管理系统 毕业设计-附源码221507

    Springboot人事信息管理系统 摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以 ...

  8. Springboot 启动信息:Generating unique operation named

    文章目录 Springboot 启动信息:Generating unique operation named 1.springboot 项目启动时,显示Generating unique operat ...

  9. 企业微信通过群聊机器人用springboot发送信息

    前言 学习了一下,如何通过企业微信的群聊机器人发送信息,没想到比想象中的简单,那么这次就来讲讲如何进行通过群聊机器人发送信息吧 步骤 第一步,在自己的企业进行创建一个群聊 然后,在自己的群聊里,添加机 ...

最新文章

  1. [异常笔记] spring boot 启动-2018040201
  2. 【收藏】推荐系列:2008年第08期 总10期
  3. 【移动端最强架构】LCNet吊打现有主流轻量型网络(附代码实现)
  4. amazeui学习笔记--css(常用组件4)--关闭按钮Close
  5. Paddle下的Tensor运算以及简单回归问题
  6. scrapy之内蒙古自治区环境保护厅
  7. pytorch学习——构建多元线性回归的网络结构
  8. php出现Cannot modify header information问题的解决方法
  9. HDU 6162 2017 多校训练:Ch's gift(树链剖分)
  10. cad被管理员阻止_CAD注册机无法以管理员身份输入的解决方案
  11. 假期无聊 就来试试用Python做一个智能识别 包教会哦 多图预警:配置Pyqt5超详细解说(designer.exe和pyuic.exe)以及项目:Python实现百度智能识别,识别各种实物
  12. ppt制作弹跳的小球动画效果_如何利用ppt制作小球弹跳动画?
  13. [bzoj5510]唱跳rap和篮球
  14. powershell环境下的“ping”命令
  15. Python实现任意多边形的最大内切圆算法
  16. 用Java自动发邮件
  17. java中的NIO,BIO,AIO
  18. [Windows] 获取设备唯一标识
  19. html text decoration,更好利用text-decoration属性
  20. Word在试图打开文件时遇到错误。 请尝试下列方法: * 检查文档或驱动器的文件权限。 * 确保有足够的内存和磁盘空间。 * 用文件恢复转换器打开文件。

热门文章

  1. 从事网络安全,可以考取哪些证书?
  2. 安卓平板做pc显示器_现在是购买PC显示器的好时机吗?
  3. windows或者Ubuntu环境下用python实现瞳孔定位
  4. 数据增强:随机HSV增强
  5. 基于结构的药物设计:从分子对接到分子动力学
  6. 2023最新AI创作系统/ChatGPT商业运营版网站程序源码+支持GPT4+支持ai绘画(MJ)+实时语音识别输入+免费更新版本
  7. ntp服务器无响应,NTP服务
  8. 日期类Date控制台应用程序设计C#
  9. 每天一点数据库之-----Day 7 字段相关与联合结果集
  10. Git清除贡献者信息和历史提交记录