getActiveSessions()
+ {
+ throw new UnsupportedOperationException("getActiveSessions method not supported");
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/session/SpringSessionValidationScheduler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/session/SpringSessionValidationScheduler.java
new file mode 100644
index 0000000..60174c0
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/web/session/SpringSessionValidationScheduler.java
@@ -0,0 +1,131 @@
+package com.ruoyi.framework.shiro.web.session;
+
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import org.apache.shiro.session.mgt.DefaultSessionManager;
+import org.apache.shiro.session.mgt.SessionValidationScheduler;
+import org.apache.shiro.session.mgt.ValidatingSessionManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.utils.Threads;
+
+/**
+ * 自定义任务调度器完成
+ *
+ * @author ruoyi
+ */
+@Component
+public class SpringSessionValidationScheduler implements SessionValidationScheduler
+{
+ private static final Logger log = LoggerFactory.getLogger(SpringSessionValidationScheduler.class);
+
+ public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
+
+ /**
+ * 定时器,用于处理超时的挂起请求,也用于连接断开时的重连。
+ */
+ @Autowired
+ @Qualifier("scheduledExecutorService")
+ private ScheduledExecutorService executorService;
+
+ private volatile boolean enabled = false;
+
+ /**
+ * 会话验证管理器
+ */
+ @Autowired
+ @Qualifier("sessionManager")
+ @Lazy
+ private ValidatingSessionManager sessionManager;
+
+ // 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟
+ @Value("${shiro.session.validationInterval}")
+ private long sessionValidationInterval;
+
+ @Override
+ public boolean isEnabled()
+ {
+ return this.enabled;
+ }
+
+ /**
+ * Specifies how frequently (in milliseconds) this Scheduler will call the
+ * {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions()
+ * ValidatingSessionManager#validateSessions()} method.
+ *
+ *
+ * Unless this method is called, the default value is {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}.
+ *
+ * @param sessionValidationInterval
+ */
+ public void setSessionValidationInterval(long sessionValidationInterval)
+ {
+ this.sessionValidationInterval = sessionValidationInterval;
+ }
+
+ /**
+ * Starts session validation by creating a spring PeriodicTrigger.
+ */
+ @Override
+ public void enableSessionValidation()
+ {
+
+ enabled = true;
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Scheduling session validation job using Spring Scheduler with "
+ + "session validation interval of [" + sessionValidationInterval + "]ms...");
+ }
+
+ try
+ {
+ executorService.scheduleAtFixedRate(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ if (enabled)
+ {
+ sessionManager.validateSessions();
+ }
+ }
+ }, 1000, sessionValidationInterval * 60 * 1000, TimeUnit.MILLISECONDS);
+
+ this.enabled = true;
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Session validation job successfully scheduled with Spring Scheduler.");
+ }
+
+ }
+ catch (Exception e)
+ {
+ if (log.isErrorEnabled())
+ {
+ log.error("Error starting the Spring Scheduler session validation job. Session validation may not occur.", e);
+ }
+ }
+ }
+
+ @Override
+ public void disableSessionValidation()
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("Stopping Spring Scheduler session validation job...");
+ }
+
+ if (this.enabled)
+ {
+ Threads.shutdownAndAwaitTermination(executorService);
+ }
+ this.enabled = false;
+ }
+}
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
new file mode 100644
index 0000000..6a549f8
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java
@@ -0,0 +1,241 @@
+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.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 Cpu getCpu()
+ {
+ return cpu;
+ }
+
+ public void setCpu(Cpu cpu)
+ {
+ this.cpu = cpu;
+ }
+
+ public Mem getMem()
+ {
+ return mem;
+ }
+
+ public void setMem(Mem mem)
+ {
+ this.mem = mem;
+ }
+
+ public Jvm getJvm()
+ {
+ return jvm;
+ }
+
+ public void setJvm(Jvm jvm)
+ {
+ this.jvm = jvm;
+ }
+
+ public Sys getSys()
+ {
+ return sys;
+ }
+
+ public void setSys(Sys sys)
+ {
+ this.sys = sys;
+ }
+
+ public List getSysFiles()
+ {
+ return sysFiles;
+ }
+
+ public void setSysFiles(List sysFiles)
+ {
+ this.sysFiles = sysFiles;
+ }
+
+ 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
new file mode 100644
index 0000000..a13a66c
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java
@@ -0,0 +1,101 @@
+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 int getCpuNum()
+ {
+ return cpuNum;
+ }
+
+ public void setCpuNum(int cpuNum)
+ {
+ this.cpuNum = cpuNum;
+ }
+
+ public double getTotal()
+ {
+ return Arith.round(Arith.mul(total, 100), 2);
+ }
+
+ public void setTotal(double total)
+ {
+ this.total = total;
+ }
+
+ public double getSys()
+ {
+ return Arith.round(Arith.mul(sys / total, 100), 2);
+ }
+
+ public void setSys(double sys)
+ {
+ this.sys = sys;
+ }
+
+ public double getUsed()
+ {
+ return Arith.round(Arith.mul(used / total, 100), 2);
+ }
+
+ public void setUsed(double used)
+ {
+ this.used = used;
+ }
+
+ public double getWait()
+ {
+ return Arith.round(Arith.mul(wait / total, 100), 2);
+ }
+
+ public void setWait(double wait)
+ {
+ this.wait = wait;
+ }
+
+ public double getFree()
+ {
+ return Arith.round(Arith.mul(free / total, 100), 2);
+ }
+
+ public void setFree(double free)
+ {
+ this.free = free;
+ }
+}
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
new file mode 100644
index 0000000..485d201
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java
@@ -0,0 +1,122 @@
+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 void setTotal(double total)
+ {
+ this.total = total;
+ }
+
+ public double getMax()
+ {
+ return Arith.div(max, (1024 * 1024), 2);
+ }
+
+ public void setMax(double max)
+ {
+ this.max = max;
+ }
+
+ 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();
+ }
+
+ public String getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion(String version)
+ {
+ this.version = version;
+ }
+
+ public String getHome()
+ {
+ return home;
+ }
+
+ public void setHome(String home)
+ {
+ this.home = home;
+ }
+
+ /**
+ * 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
new file mode 100644
index 0000000..13eec52
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java
@@ -0,0 +1,61 @@
+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 void setTotal(long total)
+ {
+ this.total = total;
+ }
+
+ public double getUsed()
+ {
+ return Arith.div(used, (1024 * 1024 * 1024), 2);
+ }
+
+ public void setUsed(long used)
+ {
+ this.used = used;
+ }
+
+ public double getFree()
+ {
+ return Arith.div(free, (1024 * 1024 * 1024), 2);
+ }
+
+ public void setFree(long free)
+ {
+ this.free = free;
+ }
+
+ 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
new file mode 100644
index 0000000..45d64d9
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java
@@ -0,0 +1,84 @@
+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;
+
+ public String getComputerName()
+ {
+ return computerName;
+ }
+
+ public void setComputerName(String computerName)
+ {
+ this.computerName = computerName;
+ }
+
+ public String getComputerIp()
+ {
+ return computerIp;
+ }
+
+ public void setComputerIp(String computerIp)
+ {
+ this.computerIp = computerIp;
+ }
+
+ public String getUserDir()
+ {
+ return userDir;
+ }
+
+ public void setUserDir(String userDir)
+ {
+ this.userDir = userDir;
+ }
+
+ public String getOsName()
+ {
+ return osName;
+ }
+
+ public void setOsName(String osName)
+ {
+ this.osName = osName;
+ }
+
+ public String getOsArch()
+ {
+ return osArch;
+ }
+
+ public void setOsArch(String osArch)
+ {
+ this.osArch = 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
new file mode 100644
index 0000000..1320cde
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java
@@ -0,0 +1,114 @@
+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;
+
+ public String getDirName()
+ {
+ return dirName;
+ }
+
+ public void setDirName(String dirName)
+ {
+ this.dirName = dirName;
+ }
+
+ public String getSysTypeName()
+ {
+ return sysTypeName;
+ }
+
+ public void setSysTypeName(String sysTypeName)
+ {
+ this.sysTypeName = sysTypeName;
+ }
+
+ public String getTypeName()
+ {
+ return typeName;
+ }
+
+ public void setTypeName(String typeName)
+ {
+ this.typeName = typeName;
+ }
+
+ public String getTotal()
+ {
+ return total;
+ }
+
+ public void setTotal(String total)
+ {
+ this.total = total;
+ }
+
+ public String getFree()
+ {
+ return free;
+ }
+
+ public void setFree(String free)
+ {
+ this.free = free;
+ }
+
+ public String getUsed()
+ {
+ return used;
+ }
+
+ public void setUsed(String used)
+ {
+ this.used = used;
+ }
+
+ public double getUsage()
+ {
+ return usage;
+ }
+
+ public void setUsage(double usage)
+ {
+ this.usage = usage;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
new file mode 100644
index 0000000..e315906
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
@@ -0,0 +1,116 @@
+package com.ruoyi.framework.web.exception;
+
+import javax.servlet.http.HttpServletRequest;
+import org.apache.shiro.authz.AuthorizationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.validation.BindException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.servlet.ModelAndView;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.exception.DemoModeException;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.security.PermissionUtils;
+
+/**
+ * 全局异常处理器
+ *
+ * @author ruoyi
+ */
+@RestControllerAdvice
+public class GlobalExceptionHandler
+{
+ private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+ /**
+ * 权限校验异常(ajax请求返回json,redirect请求跳转页面)
+ */
+ @ExceptionHandler(AuthorizationException.class)
+ public Object handleAuthorizationException(AuthorizationException e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage());
+ if (ServletUtils.isAjaxRequest(request))
+ {
+ return AjaxResult.error(PermissionUtils.getMsg(e.getMessage()));
+ }
+ else
+ {
+ return new ModelAndView("error/unauth");
+ }
+ }
+
+ /**
+ * 请求方式不支持
+ */
+ @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+ public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
+ HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
+ return AjaxResult.error(e.getMessage());
+ }
+
+ /**
+ * 拦截未知的运行时异常
+ */
+ @ExceptionHandler(RuntimeException.class)
+ public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("请求地址'{}',发生未知异常.", requestURI, e);
+ return AjaxResult.error(e.getMessage());
+ }
+
+ /**
+ * 系统异常
+ */
+ @ExceptionHandler(Exception.class)
+ public AjaxResult handleException(Exception e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("请求地址'{}',发生系统异常.", requestURI, e);
+ return AjaxResult.error(e.getMessage());
+ }
+
+ /**
+ * 业务异常
+ */
+ @ExceptionHandler(ServiceException.class)
+ public Object handleServiceException(ServiceException e, HttpServletRequest request)
+ {
+ log.error(e.getMessage(), e);
+ if (ServletUtils.isAjaxRequest(request))
+ {
+ return AjaxResult.error(e.getMessage());
+ }
+ else
+ {
+ return new ModelAndView("error/service", "errorMessage", e.getMessage());
+ }
+ }
+
+ /**
+ * 自定义验证异常
+ */
+ @ExceptionHandler(BindException.class)
+ public AjaxResult handleBindException(BindException e)
+ {
+ log.error(e.getMessage(), e);
+ String message = e.getAllErrors().get(0).getDefaultMessage();
+ return AjaxResult.error(message);
+ }
+
+ /**
+ * 演示模式异常
+ */
+ @ExceptionHandler(DemoModeException.class)
+ public AjaxResult handleDemoModeException(DemoModeException e)
+ {
+ return AjaxResult.error("演示模式,不允许操作");
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/CacheService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/CacheService.java
new file mode 100644
index 0000000..a8b037e
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/CacheService.java
@@ -0,0 +1,83 @@
+package com.ruoyi.framework.web.service;
+
+import java.util.Set;
+import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.CacheUtils;
+
+/**
+ * 缓存操作处理
+ *
+ * @author ruoyi
+ */
+@Service
+public class CacheService
+{
+ /**
+ * 获取所有缓存名称
+ *
+ * @return 缓存列表
+ */
+ public String[] getCacheNames()
+ {
+ String[] cacheNames = CacheUtils.getCacheNames();
+ return ArrayUtils.removeElement(cacheNames, Constants.SYS_AUTH_CACHE);
+ }
+
+ /**
+ * 根据缓存名称获取所有键名
+ *
+ * @param cacheName 缓存名称
+ * @return 键名列表
+ */
+ public Set getCacheKeys(String cacheName)
+ {
+ return CacheUtils.getCache(cacheName).keys();
+ }
+
+ /**
+ * 根据缓存名称和键名获取内容值
+ *
+ * @param cacheName 缓存名称
+ * @param cacheKey 键名
+ * @return 键值
+ */
+ public Object getCacheValue(String cacheName, String cacheKey)
+ {
+ return CacheUtils.get(cacheName, cacheKey);
+ }
+
+ /**
+ * 根据名称删除缓存信息
+ *
+ * @param cacheName 缓存名称
+ */
+ public void clearCacheName(String cacheName)
+ {
+ CacheUtils.removeAll(cacheName);
+ }
+
+ /**
+ * 根据名称和键名删除缓存信息
+ *
+ * @param cacheName 缓存名称
+ * @param cacheKey 键名
+ */
+ public void clearCacheKey(String cacheName, String cacheKey)
+ {
+ CacheUtils.remove(cacheName, cacheKey);
+ }
+
+ /**
+ * 清理所有缓存
+ */
+ public void clearAll()
+ {
+ String[] cacheNames = getCacheNames();
+ for (String cacheName : cacheNames)
+ {
+ CacheUtils.removeAll(cacheName);
+ }
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/ConfigService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/ConfigService.java
new file mode 100644
index 0000000..2859588
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/ConfigService.java
@@ -0,0 +1,28 @@
+package com.ruoyi.framework.web.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.system.service.ISysConfigService;
+
+/**
+ * RuoYi首创 html调用 thymeleaf 实现参数管理
+ *
+ * @author ruoyi
+ */
+@Service("config")
+public class ConfigService
+{
+ @Autowired
+ private ISysConfigService configService;
+
+ /**
+ * 根据键名查询参数配置信息
+ *
+ * @param configKey 参数键名
+ * @return 参数键值
+ */
+ public String getKey(String configKey)
+ {
+ return configService.selectConfigByKey(configKey);
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/DictService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/DictService.java
new file mode 100644
index 0000000..fd717c2
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/DictService.java
@@ -0,0 +1,65 @@
+package com.ruoyi.framework.web.service;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.system.service.ISysDeptService;
+import com.ruoyi.system.service.ISysDictDataService;
+import com.ruoyi.system.service.ISysDictTypeService;
+
+/**
+ * RuoYi首创 html调用 thymeleaf 实现字典读取
+ *
+ * @author ruoyi
+ */
+@Service("dict")
+public class DictService {
+ @Autowired
+ private ISysDictTypeService dictTypeService;
+
+ @Autowired
+ private ISysDictDataService dictDataService;
+
+ @Autowired
+ private ISysDeptService sysDeptService;
+
+ /**
+ * 根据字典类型查询字典数据信息
+ *
+ * @param dictType 字典类型
+ * @return 参数键值
+ */
+ public List getType(String dictType) {
+ return dictTypeService.selectDictDataByType(dictType);
+ }
+
+ /**
+ * 根据字典类型和字典键值查询字典数据信息
+ *
+ * @param dictType 字典类型
+ * @param dictValue 字典键值
+ * @return 字典标签
+ */
+ public String getLabel(String dictType, String dictValue) {
+ return dictDataService.selectDictLabel(dictType, dictValue);
+ }
+
+ public List getPlat() {
+ SysDept s = new SysDept();
+ s.setParentId(100l);
+ List list = sysDeptService.selectDeptList(s);
+ List r = new ArrayList();
+ for (SysDept d : list) {
+ SysDictData a = new SysDictData();
+ a.setDictLabel(d.getDeptName());
+ a.setDictValue(d.getDeptId().toString());
+ r.add(a);
+
+ }
+ return r;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java
new file mode 100644
index 0000000..6441807
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java
@@ -0,0 +1,262 @@
+package com.ruoyi.framework.web.service;
+
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.subject.Subject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * RuoYi首创 js调用 thymeleaf 实现按钮权限可见性
+ *
+ * @author ruoyi
+ */
+@Service("permission")
+public class PermissionService
+{
+ private static final Logger log = LoggerFactory.getLogger(PermissionService.class);
+
+ /** 没有权限,hidden用于前端隐藏按钮 */
+ public static final String NOACCESS = "hidden";
+
+ private static final String ROLE_DELIMETER = ",";
+
+ private static final String PERMISSION_DELIMETER = ",";
+
+ /**
+ * 验证用户是否具备某权限,无权限返回hidden用于前端隐藏(如需返回Boolean使用isPermitted)
+ *
+ * @param permission 权限字符串
+ * @return 用户是否具备某权限
+ */
+ public String hasPermi(String permission)
+ {
+ return isPermitted(permission) ? StringUtils.EMPTY : NOACCESS;
+ }
+
+ /**
+ * 验证用户是否不具备某权限,与 hasPermi逻辑相反。无权限返回hidden用于前端隐藏(如需返回Boolean使用isLacksPermitted)
+ *
+ * @param permission 权限字符串
+ * @return 用户是否不具备某权限
+ */
+ public String lacksPermi(String permission)
+ {
+ return isLacksPermitted(permission) ? StringUtils.EMPTY : NOACCESS;
+ }
+
+ /**
+ * 验证用户是否具有以下任意一个权限,无权限返回hidden用于隐藏(如需返回Boolean使用hasAnyPermissions)
+ *
+ * @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
+ * @return 用户是否具有以下任意一个权限
+ */
+ public String hasAnyPermi(String permissions)
+ {
+ return hasAnyPermissions(permissions, PERMISSION_DELIMETER) ? StringUtils.EMPTY : NOACCESS;
+ }
+
+ /**
+ * 验证用户是否具备某角色,无权限返回hidden用于隐藏(如需返回Boolean使用isRole)
+ *
+ * @param role 角色字符串
+ * @return 用户是否具备某角色
+ */
+ public String hasRole(String role)
+ {
+ return isRole(role) ? StringUtils.EMPTY : NOACCESS;
+ }
+
+ /**
+ * 验证用户是否不具备某角色,与hasRole逻辑相反。无权限返回hidden用于隐藏(如需返回Boolean使用isLacksRole)
+ *
+ * @param role 角色字符串
+ * @return 用户是否不具备某角色
+ */
+ public String lacksRole(String role)
+ {
+ return isLacksRole(role) ? StringUtils.EMPTY : NOACCESS;
+ }
+
+ /**
+ * 验证用户是否具有以下任意一个角色,无权限返回hidden用于隐藏(如需返回Boolean使用isAnyRoles)
+ *
+ * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
+ * @return 用户是否具有以下任意一个角色
+ */
+ public String hasAnyRoles(String roles)
+ {
+ return isAnyRoles(roles, ROLE_DELIMETER) ? StringUtils.EMPTY : NOACCESS;
+ }
+
+ /**
+ * 验证用户是否认证通过或已记住的用户。
+ *
+ * @return 用户是否认证通过或已记住的用户
+ */
+ public boolean isUser()
+ {
+ Subject subject = SecurityUtils.getSubject();
+ return subject != null && subject.getPrincipal() != null;
+ }
+
+ /**
+ * 判断用户是否拥有某个权限
+ *
+ * @param permission 权限字符串
+ * @return 用户是否具备某权限
+ */
+ public boolean isPermitted(String permission)
+ {
+ return SecurityUtils.getSubject().isPermitted(permission);
+ }
+
+ /**
+ * 判断用户是否不具备某权限,与 isPermitted逻辑相反。
+ *
+ * @param permission 权限名称
+ * @return 用户是否不具备某权限
+ */
+ public boolean isLacksPermitted(String permission)
+ {
+ return isPermitted(permission) != true;
+ }
+
+ /**
+ * 验证用户是否具有以下任意一个权限。
+ *
+ * @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
+ * @return 用户是否具有以下任意一个权限
+ */
+ public boolean hasAnyPermissions(String permissions)
+ {
+ return hasAnyPermissions(permissions, PERMISSION_DELIMETER);
+ }
+
+ /**
+ * 验证用户是否具有以下任意一个权限。
+ *
+ * @param permissions 以 delimeter 为分隔符的权限列表
+ * @param delimeter 权限列表分隔符
+ * @return 用户是否具有以下任意一个权限
+ */
+ public boolean hasAnyPermissions(String permissions, String delimeter)
+ {
+ Subject subject = SecurityUtils.getSubject();
+
+ if (subject != null)
+ {
+ if (delimeter == null || delimeter.length() == 0)
+ {
+ delimeter = PERMISSION_DELIMETER;
+ }
+
+ for (String permission : permissions.split(delimeter))
+ {
+ if (permission != null && subject.isPermitted(permission.trim()) == true)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * 判断用户是否拥有某个角色
+ *
+ * @param role 角色字符串
+ * @return 用户是否具备某角色
+ */
+ public boolean isRole(String role)
+ {
+ return SecurityUtils.getSubject().hasRole(role);
+ }
+
+ /**
+ * 验证用户是否不具备某角色,与 isRole逻辑相反。
+ *
+ * @param role 角色名称
+ * @return 用户是否不具备某角色
+ */
+ public boolean isLacksRole(String role)
+ {
+ return isRole(role) != true;
+ }
+
+ /**
+ * 验证用户是否具有以下任意一个角色。
+ *
+ * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
+ * @return 用户是否具有以下任意一个角色
+ */
+ public boolean isAnyRoles(String roles)
+ {
+ return isAnyRoles(roles, ROLE_DELIMETER);
+ }
+
+ /**
+ * 验证用户是否具有以下任意一个角色。
+ *
+ * @param roles 以 delimeter 为分隔符的角色列表
+ * @param delimeter 角色列表分隔符
+ * @return 用户是否具有以下任意一个角色
+ */
+ public boolean isAnyRoles(String roles, String delimeter)
+ {
+ Subject subject = SecurityUtils.getSubject();
+ if (subject != null)
+ {
+ if (delimeter == null || delimeter.length() == 0)
+ {
+ delimeter = ROLE_DELIMETER;
+ }
+
+ for (String role : roles.split(delimeter))
+ {
+ if (subject.hasRole(role.trim()) == true)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * 返回用户属性值
+ *
+ * @param property 属性名称
+ * @return 用户属性值
+ */
+ public Object getPrincipalProperty(String property)
+ {
+ Subject subject = SecurityUtils.getSubject();
+ if (subject != null)
+ {
+ Object principal = subject.getPrincipal();
+ try
+ {
+ BeanInfo bi = Introspector.getBeanInfo(principal.getClass());
+ for (PropertyDescriptor pd : bi.getPropertyDescriptors())
+ {
+ if (pd.getName().equals(property) == true)
+ {
+ return pd.getReadMethod().invoke(principal, (Object[]) null);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ log.error("Error reading property [{}] from principal of type [{}]", property, principal.getClass().getName());
+ }
+ }
+ return null;
+ }
+}