diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java deleted file mode 100644 index eaa41fdb5..000000000 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.ruoyi.web.controller.monitor; - -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.framework.web.domain.Server; - -/** - * 服务器监控 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/monitor/server") -public class ServerController { - @PreAuthorize("@ss.hasPermi('monitor:server:list')") - @GetMapping() - public AjaxResult getInfo() throws Exception { - Server server = new Server(); - server.copyTo(); - return AjaxResult.success(server); - } -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java deleted file mode 100644 index fd19d98cf..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.ruoyi.framework.web.domain; - -import java.net.UnknownHostException; -import java.util.LinkedList; -import java.util.List; -import java.util.Properties; - -import com.ruoyi.common.utils.Arith; -import com.ruoyi.common.utils.ip.IpUtils; -import com.ruoyi.framework.web.domain.server.Cpu; -import com.ruoyi.framework.web.domain.server.Jvm; -import com.ruoyi.framework.web.domain.server.Mem; -import com.ruoyi.framework.web.domain.server.Sys; -import com.ruoyi.framework.web.domain.server.SysFile; -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; - -/** - * 服务器相关信息 - * - * @author ruoyi - */ -public class Server { - private static final int OSHI_WAIT_SECOND = 1000; - - /** - * CPU相关信息 - */ - private Cpu cpu = new Cpu(); - - /** - * 內存相关信息 - */ - private Mem mem = new Mem(); - - /** - * JVM相关信息 - */ - private Jvm jvm = new Jvm(); - - /** - * 服务器相关信息 - */ - private Sys sys = new Sys(); - - /** - * 磁盘相关信息 - */ - private List sysFiles = new LinkedList(); - - public void copyTo() throws Exception { - 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(IpUtils.getHostName()); - sys.setComputerIp(IpUtils.getHostIp()); - sys.setOsName(props.getProperty("os.name")); - sys.setOsArch(props.getProperty("os.arch")); - sys.setUserDir(props.getProperty("user.dir")); - } - - /** - * 设置Java虚拟机 - */ - private void setJvmInfo() throws UnknownHostException { - 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(); - List fsArray = fileSystem.getFileStores(); - for (OSFileStore fs : fsArray) { - long free = fs.getUsableSpace(); - long total = fs.getTotalSpace(); - long used = total - free; - SysFile sysFile = new SysFile(); - sysFile.setDirName(fs.getMount()); - sysFile.setSysTypeName(fs.getType()); - sysFile.setTypeName(fs.getName()); - sysFile.setTotal(convertFileSize(total)); - sysFile.setFree(convertFileSize(free)); - sysFile.setUsed(convertFileSize(used)); - sysFile.setUsage(Arith.mul(Arith.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/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java deleted file mode 100644 index 1591cac6c..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.ruoyi.framework.web.domain.server; - -import com.ruoyi.common.utils.Arith; - -/** - * CPU相关信息 - * - * @author ruoyi - */ -public class Cpu { - /** - * 核心数 - */ - private int cpuNum; - - /** - * CPU总的使用率 - */ - private double total; - - /** - * CPU系统使用率 - */ - private double sys; - - /** - * CPU用户使用率 - */ - private double used; - - /** - * CPU当前等待率 - */ - private double wait; - - /** - * CPU当前空闲率 - */ - private double free; - - public double getTotal() { - return Arith.round(Arith.mul(total, 100), 2); - } - - public double getSys() { - return Arith.round(Arith.mul(sys / total, 100), 2); - } - - public double getUsed() { - return Arith.round(Arith.mul(used / total, 100), 2); - } - - public double getWait() { - return Arith.round(Arith.mul(wait / total, 100), 2); - } - - public double getFree() { - return Arith.round(Arith.mul(free / total, 100), 2); - } - -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java deleted file mode 100644 index e0eb23b1f..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.ruoyi.framework.web.domain.server; - -import java.lang.management.ManagementFactory; - -import com.ruoyi.common.utils.Arith; -import com.ruoyi.common.utils.DateUtils; - -/** - * JVM相关信息 - * - * @author ruoyi - */ -public class Jvm { - /** - * 当前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 Arith.div(total, (1024 * 1024), 2); - } - - public double getMax() { - return Arith.div(max, (1024 * 1024), 2); - } - - public double getFree() { - return Arith.div(free, (1024 * 1024), 2); - } - - public void setFree(double free) { - this.free = free; - } - - public double getUsed() { - return Arith.div(total - free, (1024 * 1024), 2); - } - - public double getUsage() { - return Arith.mul(Arith.div(total - free, total, 4), 100); - } - - /** - * 获取JDK名称 - */ - public String getName() { - return ManagementFactory.getRuntimeMXBean().getVmName(); - } - - /** - * JDK启动时间 - */ - public String getStartTime() { - return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate()); - } - - /** - * JDK运行时间 - */ - public String getRunTime() { - return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate()); - } -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java deleted file mode 100644 index ac0f9b445..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.ruoyi.framework.web.domain.server; - -import com.ruoyi.common.utils.Arith; - -/** - * 內存相关信息 - * - * @author ruoyi - */ -public class Mem { - /** - * 内存总量 - */ - private double total; - - /** - * 已用内存 - */ - private double used; - - /** - * 剩余内存 - */ - private double free; - - public double getTotal() { - return Arith.div(total, (1024 * 1024 * 1024), 2); - } - - public double getUsed() { - return Arith.div(used, (1024 * 1024 * 1024), 2); - } - - public double getFree() { - return Arith.div(free, (1024 * 1024 * 1024), 2); - } - - public double getUsage() { - return Arith.mul(Arith.div(used, total, 4), 100); - } - -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java deleted file mode 100644 index eae6f07c5..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.ruoyi.framework.web.domain.server; - -/** - * 系统相关信息 - * - * @author ruoyi - */ -public class Sys { - /** - * 服务器名称 - */ - private String computerName; - - /** - * 服务器Ip - */ - private String computerIp; - - /** - * 项目路径 - */ - private String userDir; - - /** - * 操作系统 - */ - private String osName; - - /** - * 系统架构 - */ - private String osArch; - -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java deleted file mode 100644 index 8a8d89f1e..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.ruoyi.framework.web.domain.server; - -/** - * 系统文件相关信息 - * - * @author ruoyi - */ -public class SysFile { - /** - * 盘符路径 - */ - 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/iocoder/dashboard/common/pojo/CommonResult.java b/src/main/java/cn/iocoder/dashboard/common/pojo/CommonResult.java index 030d9df67..80b938dfb 100644 --- a/src/main/java/cn/iocoder/dashboard/common/pojo/CommonResult.java +++ b/src/main/java/cn/iocoder/dashboard/common/pojo/CommonResult.java @@ -5,6 +5,7 @@ import cn.iocoder.dashboard.common.exception.GlobalException; import cn.iocoder.dashboard.common.exception.ServiceException; import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants; import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import org.springframework.util.Assert; @@ -68,12 +69,14 @@ public final class CommonResult implements Serializable { return result; } - @JSONField(serialize = false) // 避免序列化 + @JSONField(serialize = false) // 避免 fastjson 序列化 + @JsonIgnore // 避免 jackson 序列化 public boolean isSuccess() { return GlobalErrorCodeConstants.SUCCESS.getCode().equals(code); } - @JSONField(serialize = false) // 避免序列化 + @JSONField(serialize = false) // 避免 fastjson 序列化 + @JsonIgnore // 避免 jackson 序列化 public boolean isError() { return !isSuccess(); } diff --git a/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java b/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java index 07f1468ae..2f15cfe8d 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java +++ b/src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java @@ -1,9 +1,15 @@ package cn.iocoder.dashboard.framework.web.config; +import cn.iocoder.dashboard.util.servlet.ServletUtils; +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.alibaba.fastjson.support.config.FastJsonConfig; +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; @@ -12,6 +18,10 @@ import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.nio.charset.Charset; +import java.util.Collections; +import java.util.List; /** * Web 配置类 @@ -27,26 +37,48 @@ public class WebConfiguration implements WebMvcConfigurer { public void configurePathMatch(PathMatchConfigurer configurer) { configurer.addPathPrefix(webProperties.getApiPrefix(), clazz -> clazz.isAnnotationPresent(RestController.class) - && clazz.getPackage().getName().contains("cn.iocoder.dashboard")); + && clazz.getPackage().getName().startsWith(webProperties.getControllerPackage())); } // ========== MessageConverter 相关 ========== -// @Override -// public void configureMessageConverters(List> converters) { -// // 创建 FastJsonHttpMessageConverter 对象 -// FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); -// // 自定义 FastJson 配置 -// FastJsonConfig fastJsonConfig = new FastJsonConfig(); -// fastJsonConfig.setCharset(Charset.defaultCharset()); // 设置字符集 -// fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect, // 剔除循环引用 -// SerializerFeature.WriteNonStringKeyAsString); // 解决 Integer 作为 Key 时,转换为 String 类型,避免浏览器报错 -// fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig); -// // 设置支持的 MediaType -// fastJsonHttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON)); -// // 添加到 converters 中 -// converters.add(0, fastJsonHttpMessageConverter); // 注意,添加到最开头,放在 MappingJackson2XmlHttpMessageConverter 前面 -// } + @Override + public void configureMessageConverters(List> converters) { + // 创建 FastJsonHttpMessageConverter 对象 + // 重写 canRead 和 canWrite 方法,判断只处理自己写的 API 为前缀的 URL。原因是,FastJSON 和一些三方框架集成存在问题,例如说: + // 1. 与 Spring Boot Admin 时,由于 Registration 基于 Builder 构造对象,导致它无法反序列化 + // 2. 与 Spring Boot Actuator 时,貌似也存在问题,具体还没去排查。 + // 但是,为什么不替换回 Jackson 呢? + // 原因是,一些 Number 数值比较小时,反序列化回来是 Integer 类型,实际是 Long 类型。此时,在序列化时,会报 Integer 无法转换成 Long 的异常 + FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter() { + + @Override + protected boolean canRead(MediaType mediaType) { + return isApiPrefix() && super.canRead(mediaType); + } + + @Override + protected boolean canWrite(MediaType mediaType) { + return isApiPrefix() && super.canWrite(mediaType); + } + + private boolean isApiPrefix() { + HttpServletRequest request = ServletUtils.getRequest(); + return request != null && request.getRequestURI().startsWith(webProperties.getApiPrefix()); + } + + }; + // 自定义 FastJson 配置 + FastJsonConfig fastJsonConfig = new FastJsonConfig(); + fastJsonConfig.setCharset(Charset.defaultCharset()); // 设置字符集 + fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect, // 剔除循环引用 + SerializerFeature.WriteNonStringKeyAsString); // 解决 Integer 作为 Key 时,转换为 String 类型,避免浏览器报错 + fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig); + // 设置支持的 MediaType + fastJsonHttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON)); + // 添加到 converters 中 + converters.add(0, fastJsonHttpMessageConverter); // 注意,添加到最开头,放在 MappingJackson2XmlHttpMessageConverter 前面 + } // ========== Filter 相关 ========== diff --git a/src/main/java/cn/iocoder/dashboard/framework/web/config/WebProperties.java b/src/main/java/cn/iocoder/dashboard/framework/web/config/WebProperties.java index bffac3fd3..93479bc96 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/web/config/WebProperties.java +++ b/src/main/java/cn/iocoder/dashboard/framework/web/config/WebProperties.java @@ -24,4 +24,14 @@ public class WebProperties { @NotNull(message = "API 前缀不能为空") private String apiPrefix; + /** + * Controller 所在包 + * + * 主要目的是,给该 Controller 设置指定的 {@link #apiPrefix} + * + * 因为我们有多个 modules 包里会包含 Controller,所以只需要写到 cn.iocoder.dashboard 这样的层级 + */ + @NotNull(message = "Controller 所在包不能为空") + private String controllerPackage; + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageItemRespVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageItemRespVO.java index dc6963c58..9fdcf033c 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageItemRespVO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserPageItemRespVO.java @@ -1,5 +1,6 @@ package cn.iocoder.dashboard.modules.system.controller.user.vo.user; +import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; @@ -17,6 +18,7 @@ public class SysUserPageItemRespVO extends SysUserRespVO { /** * 所在部门 */ + @JsonIgnore private Dept dept; @ApiModel("部门") diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 5a8d09e36..9a4e02e8c 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -36,6 +36,7 @@ spring: yudao: web: api-prefix: /api + controller-package: cn.iocoder.dashboard security: token-header: Authorization token-secret: abcdefghijklmnopqrstuvwxyz