diff --git a/pom.xml b/pom.xml index 3203cdc7..94f0eea8 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,7 @@ 1.8 8.0.21 latest + 3.9.1 @@ -35,7 +36,6 @@ beetl 3.3.1.RELEASE - cn.stylefeng.roses auth-spring-boot-starter @@ -129,7 +129,22 @@ org.springframework.boot spring-boot-configuration-processor + + org.projectlombok + lombok + + + + com.github.oshi + oshi-core + ${oshi.version} + + + com.alibaba + druid-spring-boot-starter + 1.1.10 + diff --git a/src/main/java/cn/stylefeng/guns/config/web/DruidConfiguration.java b/src/main/java/cn/stylefeng/guns/config/web/DruidConfiguration.java new file mode 100644 index 00000000..8c0df532 --- /dev/null +++ b/src/main/java/cn/stylefeng/guns/config/web/DruidConfiguration.java @@ -0,0 +1,67 @@ +package cn.stylefeng.guns.config.web; + +import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; +import com.alibaba.druid.util.Utils; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import java.io.IOException; + +/*** + * 功能描述:
Druid配置 + * 创建时间: 2021/1/5 15:14 + * @author chenli + */ +@Configuration +public class DruidConfiguration { + + /*** + * 功能描述:
去除监控页面广告 + * 创建时间: 2021/1/4 20:57 + * @author chenli + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + @Bean +// @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true") + public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) { + // 获取web监控页面的参数 + DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); + // 提取common.js的配置路径 + String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"; + String commonJsPattern = pattern.replaceAll("\\*", "js/common.js"); + final String filePath = "support/http/resources/js/common.js"; + Filter filter = new Filter() { + @Override + public void init(javax.servlet.FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + chain.doFilter(request, response); + String text = Utils.readFromResource(filePath); + // 正则替换banner, 除去底部的广告信息 + text = text.replaceAll("
", ""); + text = text.replaceAll("powered.*?shrek.wang", ""); + text = text.replaceAll("", ""); + text = text.replaceAll("", ""); + response.getWriter().write(text); + } + + @Override + public void destroy() { + } + }; + FilterRegistrationBean registrationBean = new FilterRegistrationBean(); + registrationBean.setFilter(filter); + registrationBean.addUrlPatterns(commonJsPattern); + return registrationBean; + } + +} diff --git a/src/main/java/cn/stylefeng/guns/modular/system/controller/MonitorController.java b/src/main/java/cn/stylefeng/guns/modular/system/controller/MonitorController.java new file mode 100644 index 00000000..bee38cd2 --- /dev/null +++ b/src/main/java/cn/stylefeng/guns/modular/system/controller/MonitorController.java @@ -0,0 +1,50 @@ +package cn.stylefeng.guns.modular.system.controller; + +import cn.stylefeng.guns.modular.system.warpper.SystemHardwareWarpper; +import cn.stylefeng.roses.kernel.resource.api.annotation.ApiResource; +import cn.stylefeng.roses.kernel.resource.api.annotation.GetResource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; + +/** + * @author chenli + * @date 2020/12/30 16:40 + */ +@Controller +@Slf4j +@ApiResource(name = "项目监控") +public class MonitorController { + + private String PREFIX = "/modular/frame"; + + @Value("${server.port}") + private String port; + + /** + * 系统硬件信息页面 + * + * @author fengshuonan + * @Date 2018/12/24 22:43 + */ + @GetResource(name = "服务器监控", path = "/monitor/systemInfo", requiredPermission = false) + public String systemInfo(Model model) { + SystemHardwareWarpper systemHardwareWarpper = new SystemHardwareWarpper(); + systemHardwareWarpper.copyTo(); + model.addAttribute("server",systemHardwareWarpper); + return PREFIX+"/systemInfo.html"; + } + + /*** + * 功能描述:
durid sql监控页面 + * 创建时间: 2021/1/4 16:32 + * @author chenli + */ + @GetResource(name = "SQL监控", path = "/monitor/druid", requiredPermission = false,requiredLogin = false) + public String duridInfo(Model model){ + model.addAttribute("port",port); + return PREFIX+"/druid.html"; + } + +} diff --git a/src/main/java/cn/stylefeng/guns/modular/system/model/CpuInfo.java b/src/main/java/cn/stylefeng/guns/modular/system/model/CpuInfo.java new file mode 100755 index 00000000..5b04af4b --- /dev/null +++ b/src/main/java/cn/stylefeng/guns/modular/system/model/CpuInfo.java @@ -0,0 +1,69 @@ +package cn.stylefeng.guns.modular.system.model; + +import cn.hutool.core.util.NumberUtil; +import lombok.Setter; + +/** + * CPU相关信息 + * + * @author fengshuonan + * @Date 2019-07-13 13:42 + */ +@Setter +public class CpuInfo { + + /** + * 核心数 + */ + private int cpuNum; + + /** + * CPU总的使用率 + */ + private double total; + + /** + * CPU系统使用率 + */ + private double sys; + + /** + * CPU用户使用率 + */ + private double used; + + /** + * CPU当前等待率 + */ + private double wait; + + /** + * CPU当前空闲率 + */ + private double free; + + public int getCpuNum() { + return cpuNum; + } + + public double getTotal() { + return NumberUtil.round(NumberUtil.mul(total, 100), 2).doubleValue(); + } + + public double getSys() { + return NumberUtil.round(NumberUtil.mul(sys / total, 100), 2).doubleValue(); + } + + public double getUsed() { + return NumberUtil.round(NumberUtil.mul(used / total, 100), 2).doubleValue(); + } + + public double getWait() { + return NumberUtil.round(NumberUtil.mul(wait / total, 100), 2).doubleValue(); + } + + public double getFree() { + return NumberUtil.round(NumberUtil.mul(free / total, 100), 2).doubleValue(); + } + +} diff --git a/src/main/java/cn/stylefeng/guns/modular/system/model/JvmInfo.java b/src/main/java/cn/stylefeng/guns/modular/system/model/JvmInfo.java new file mode 100755 index 00000000..9494da7e --- /dev/null +++ b/src/main/java/cn/stylefeng/guns/modular/system/model/JvmInfo.java @@ -0,0 +1,109 @@ +package cn.stylefeng.guns.modular.system.model; + +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.NumberUtil; +import lombok.Setter; + +import java.lang.management.ManagementFactory; +import java.util.Date; + +/** + * JVM相关信息 + * + * @author fengshuonan + * @Date 2019-07-13 13:42 + */ +@Setter +public class JvmInfo { + /** + * 当前JVM占用的内存总数(M) + */ + private double total; + + /** + * JVM最大可用内存总数(M) + */ + private double max; + + /** + * JVM空闲内存(M) + */ + private double free; + + /** + * JDK版本 + */ + private String version; + + /** + * JDK路径 + */ + private String home; + + public double getTotal() { + return NumberUtil.div(total, (1024 * 1024), 2); + } + + public double getMax() { + return NumberUtil.div(max, (1024 * 1024), 2); + } + + public double getFree() { + return NumberUtil.div(free, (1024 * 1024), 2); + } + + public double getUsed() { + return NumberUtil.div(total - free, (1024 * 1024), 2); + } + + public String getVersion() { + return version; + } + + public String getHome() { + return home; + } + + public double getUsage() { + return NumberUtil.mul(NumberUtil.div(total - free, total, 4), 100); + } + + /** + * 获取JDK名称 + */ + public String getName() { + return ManagementFactory.getRuntimeMXBean().getVmName(); + } + + /** + * JDK启动时间 + */ + public String getStartTime() { + long time = ManagementFactory.getRuntimeMXBean().getStartTime(); + Date date = new Date(time); + return DateUtil.formatDateTime(date); + } + + /** + * JDK运行时间 + */ + public String getRunTime() { + + long time = ManagementFactory.getRuntimeMXBean().getStartTime(); + Date date = new Date(time); + + //运行多少分钟 + long runMS = DateUtil.between(date, new Date(), DateUnit.MS); + + long nd = 1000 * 24 * 60 * 60; + long nh = 1000 * 60 * 60; + long nm = 1000 * 60; + + long day = runMS / nd; + long hour = runMS % nd / nh; + long min = runMS % nd % nh / nm; + + return day + "天" + hour + "小时" + min + "分钟"; + } +} diff --git a/src/main/java/cn/stylefeng/guns/modular/system/model/MemInfo.java b/src/main/java/cn/stylefeng/guns/modular/system/model/MemInfo.java new file mode 100755 index 00000000..05808e87 --- /dev/null +++ b/src/main/java/cn/stylefeng/guns/modular/system/model/MemInfo.java @@ -0,0 +1,45 @@ +package cn.stylefeng.guns.modular.system.model; + +import cn.hutool.core.util.NumberUtil; +import lombok.Setter; + +/** + * 內存相关信息 + * + * @author fengshuonan + * @Date 2019-07-13 13:42 + */ +@Setter +public class MemInfo { + /** + * 内存总量 + */ + private double total; + + /** + * 已用内存 + */ + private double used; + + /** + * 剩余内存 + */ + private double free; + + public double getTotal() { + return NumberUtil.div(total, (1024 * 1024 * 1024), 2); + } + + public double getUsed() { + return NumberUtil.div(used, (1024 * 1024 * 1024), 2); + } + + + public double getFree() { + return NumberUtil.div(free, (1024 * 1024 * 1024), 2); + } + + public double getUsage() { + return NumberUtil.mul(NumberUtil.div(used, total, 4), 100); + } +} diff --git a/src/main/java/cn/stylefeng/guns/modular/system/model/SysFileInfo.java b/src/main/java/cn/stylefeng/guns/modular/system/model/SysFileInfo.java new file mode 100755 index 00000000..7566a903 --- /dev/null +++ b/src/main/java/cn/stylefeng/guns/modular/system/model/SysFileInfo.java @@ -0,0 +1,49 @@ +package cn.stylefeng.guns.modular.system.model; + +import lombok.Data; + +/** + * 系统文件相关信息 + * + * @author fengshuonan + * @Date 2019-07-13 13:42 + */ +@Data +public class SysFileInfo { + + /** + * 盘符路径 + */ + private String dirName; + + /** + * 盘符类型 + */ + private String sysTypeName; + + /** + * 文件类型 + */ + private String typeName; + + /** + * 总大小 + */ + private String total; + + /** + * 剩余大小 + */ + private String free; + + /** + * 已经使用量 + */ + private String used; + + /** + * 资源的使用率 + */ + private double usage; + +} diff --git a/src/main/java/cn/stylefeng/guns/modular/system/model/SysInfo.java b/src/main/java/cn/stylefeng/guns/modular/system/model/SysInfo.java new file mode 100755 index 00000000..f70674ab --- /dev/null +++ b/src/main/java/cn/stylefeng/guns/modular/system/model/SysInfo.java @@ -0,0 +1,39 @@ +package cn.stylefeng.guns.modular.system.model; + +import lombok.Data; + +/** + * 系统相关信息 + * + * @author fengshuonan + * @Date 2019-07-13 13:42 + */ +@Data +public class SysInfo { + + /** + * 服务器名称 + */ + private String computerName; + + /** + * 服务器Ip + */ + private String computerIp; + + /** + * 项目路径 + */ + private String userDir; + + /** + * 操作系统 + */ + private String osName; + + /** + * 系统架构 + */ + private String osArch; + +} diff --git a/src/main/java/cn/stylefeng/guns/modular/system/warpper/SystemHardwareWarpper.java b/src/main/java/cn/stylefeng/guns/modular/system/warpper/SystemHardwareWarpper.java new file mode 100755 index 00000000..a0497a42 --- /dev/null +++ b/src/main/java/cn/stylefeng/guns/modular/system/warpper/SystemHardwareWarpper.java @@ -0,0 +1,181 @@ +package cn.stylefeng.guns.modular.system.warpper; + +import cn.hutool.core.net.NetUtil; +import cn.hutool.core.util.NumberUtil; +import cn.stylefeng.guns.modular.system.model.*; +import cn.stylefeng.guns.core.util.IpInfoUtils; +import lombok.Data; +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +import oshi.hardware.CentralProcessor.TickType; +import oshi.hardware.GlobalMemory; +import oshi.hardware.HardwareAbstractionLayer; +import oshi.software.os.FileSystem; +import oshi.software.os.OSFileStore; +import oshi.software.os.OperatingSystem; +import oshi.util.Util; + +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; + +/** + * 服务器相关信息 + * + * @author fengshuonan + * @Date 2019-07-13 13:42 + */ +@Data +public class SystemHardwareWarpper { + + private static final int OSHI_WAIT_SECOND = 1000; + + /** + * CPU相关信息 + */ + private CpuInfo cpu = new CpuInfo(); + + /** + * 內存相关信息 + */ + private MemInfo mem = new MemInfo(); + + /** + * JVM相关信息 + */ + private JvmInfo jvm = new JvmInfo(); + + /** + * 服务器相关信息 + */ + private SysInfo sys = new SysInfo(); + + /** + * 磁盘相关信息 + */ + private List sysFiles = new LinkedList<>(); + + public void copyTo() { + SystemInfo si = new SystemInfo(); + HardwareAbstractionLayer hal = si.getHardware(); + + setCpuInfo(hal.getProcessor()); + + setMemInfo(hal.getMemory()); + + setSysInfo(); + + setJvmInfo(); + + setSysFiles(si.getOperatingSystem()); + } + + /** + * 设置CPU信息 + */ + private void setCpuInfo(CentralProcessor processor) { + // CPU信息 + long[] prevTicks = processor.getSystemCpuLoadTicks(); + Util.sleep(OSHI_WAIT_SECOND); + long[] ticks = processor.getSystemCpuLoadTicks(); + long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.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 cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()]; + long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()]; + long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()]; + long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()]; + long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal; + cpu.setCpuNum(processor.getLogicalProcessorCount()); + cpu.setTotal(totalCpu); + cpu.setSys(cSys); + cpu.setUsed(user); + cpu.setWait(iowait); + cpu.setFree(idle); + } + + /** + * 设置内存信息 + */ + private void setMemInfo(GlobalMemory memory) { + mem.setTotal(memory.getTotal()); + mem.setUsed(memory.getTotal() - memory.getAvailable()); + mem.setFree(memory.getAvailable()); + } + + /** + * 设置服务器信息 + */ + private void setSysInfo() { + Properties props = System.getProperties(); + sys.setComputerName(IpInfoUtils.getHostName()); + sys.setComputerIp(NetUtil.getLocalhostStr()); + sys.setOsName(props.getProperty("os.name")); + sys.setOsArch(props.getProperty("os.arch")); + sys.setUserDir(props.getProperty("user.dir")); + } + + /** + * 设置Java虚拟机 + */ + private void setJvmInfo() { + Properties props = System.getProperties(); + jvm.setTotal(Runtime.getRuntime().totalMemory()); + jvm.setMax(Runtime.getRuntime().maxMemory()); + jvm.setFree(Runtime.getRuntime().freeMemory()); + jvm.setVersion(props.getProperty("java.version")); + jvm.setHome(props.getProperty("java.home")); + } + + /** + * 设置磁盘信息 + */ + private void setSysFiles(OperatingSystem os) { + FileSystem fileSystem = os.getFileSystem(); + OSFileStore[] fsArray = fileSystem.getFileStores(); + for (OSFileStore fs : fsArray) { + long free = fs.getUsableSpace(); + long total = fs.getTotalSpace(); + long used = total - free; + SysFileInfo sysFile = new SysFileInfo(); + sysFile.setDirName(fs.getMount()); + sysFile.setSysTypeName(fs.getType()); + sysFile.setTypeName(fs.getName()); + sysFile.setTotal(convertFileSize(total)); + sysFile.setFree(convertFileSize(free)); + sysFile.setUsed(convertFileSize(used)); + + if (total == 0) { + sysFile.setUsage(0); + } else { + sysFile.setUsage(NumberUtil.mul(NumberUtil.div(used, total, 4), 100)); + } + + sysFiles.add(sysFile); + } + } + + /** + * 字节转换 + * + * @param size 字节大小 + * @return 转换后值 + */ + public String convertFileSize(long size) { + long kb = 1024; + long mb = kb * 1024; + long gb = mb * 1024; + if (size >= gb) { + return String.format("%.1f GB", (float) size / gb); + } else if (size >= mb) { + float f = (float) size / mb; + return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f); + } else if (size >= kb) { + float f = (float) size / kb; + return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f); + } else { + return String.format("%d B", size); + } + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index daf3f3ea..c0946d9e 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -4,8 +4,41 @@ spring: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://114.215.203.183:3306/guns?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT username: guest - password: p8HMTBEapAPPmXB8 + password: p8HMTBEapAPPmXB8! # 连接池大小根据实际情况调整 max-active: 100 - max-pool-prepared-statement-per-connection-size: 100 \ No newline at end of file + max-pool-prepared-statement-per-connection-size: 100 + druid: + initialSize: 50 + minIdle: 50 + maxActive: 200 + maxWait: 60000 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + maxEvictableIdleTimeMillis: 900000 + validationQuery: SELECT 1 FROM DUAL + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: false + webStatFilter: + enabled: true + statViewServlet: + enabled: true + # 设置白名单,不填则允许所有访问 + allow: + url-pattern: /druid/* + # 控制台管理用户名和密码 + login-username: + login-password: + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true \ No newline at end of file diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index dfce303e..384b045c 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -1,11 +1,44 @@ # Mysql数据库 spring: datasource: + type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/guns?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT - username: root - password: 123456 - + url: jdbc:mysql://192.168.1.114:3306/guns?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT + username: guest + password: p8HMTBEapAPPmXB8! # 连接池大小根据实际情况调整 max-active: 100 - max-pool-prepared-statement-per-connection-size: 100 \ No newline at end of file + max-pool-prepared-statement-per-connection-size: 100 + druid: + initialSize: 50 + minIdle: 50 + maxActive: 200 + maxWait: 60000 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + maxEvictableIdleTimeMillis: 900000 + validationQuery: SELECT 1 FROM DUAL + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: false + webStatFilter: + enabled: true + statViewServlet: + enabled: true + # 设置白名单,不填则允许所有访问 + allow: + url-pattern: /druid/* + # 控制台管理用户名和密码 + login-username: + login-password: + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index af165c22..82b8e245 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -20,7 +20,8 @@ spring: locale: zh_CN serialization: indent_output: false - + main: + allow-bean-definition-overriding: true scanner: open: true sys-log: diff --git a/src/main/webapp/pages/login.html b/src/main/webapp/pages/login.html index 2875f42a..b3bb34da 100644 --- a/src/main/webapp/pages/login.html +++ b/src/main/webapp/pages/login.html @@ -177,7 +177,7 @@
- +
@if(constants.getCaptchaOpen()){