20251224:格式化代码
This commit is contained in:
parent
7e612e03eb
commit
d89e3b63dc
@ -8,14 +8,13 @@ import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 数据权限过滤注解
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface DataScope
|
||||
{
|
||||
public @interface DataScope {
|
||||
/**
|
||||
* 部门表的别名
|
||||
*/
|
||||
|
||||
@ -8,43 +8,35 @@ import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* 获取IP方法
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class IpUtils
|
||||
{
|
||||
public class IpUtils {
|
||||
/**
|
||||
* 获取客户端IP
|
||||
*
|
||||
*
|
||||
* @param request 请求对象
|
||||
* @return IP地址
|
||||
*/
|
||||
public static String getIpAddr(HttpServletRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
public static String getIpAddr(HttpServletRequest request) {
|
||||
if (request == null) {
|
||||
return "unknown";
|
||||
}
|
||||
String ip = request.getHeader("x-forwarded-for");
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
|
||||
{
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
|
||||
{
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("X-Forwarded-For");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
|
||||
{
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
|
||||
{
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("X-Real-IP");
|
||||
}
|
||||
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
|
||||
{
|
||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
|
||||
@ -53,26 +45,23 @@ public class IpUtils
|
||||
|
||||
/**
|
||||
* 检查是否为内部IP地址
|
||||
*
|
||||
*
|
||||
* @param ip IP地址
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean internalIp(String ip)
|
||||
{
|
||||
public static boolean internalIp(String ip) {
|
||||
byte[] addr = textToNumericFormatV4(ip);
|
||||
return internalIp(addr) || "127.0.0.1".equals(ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为内部IP地址
|
||||
*
|
||||
*
|
||||
* @param addr byte地址
|
||||
* @return 结果
|
||||
*/
|
||||
private static boolean internalIp(byte[] addr)
|
||||
{
|
||||
if (StringUtils.isNull(addr) || addr.length < 2)
|
||||
{
|
||||
private static boolean internalIp(byte[] addr) {
|
||||
if (StringUtils.isNull(addr) || addr.length < 2) {
|
||||
return true;
|
||||
}
|
||||
final byte b0 = addr[0];
|
||||
@ -86,20 +75,16 @@ public class IpUtils
|
||||
// 192.168.x.x/16
|
||||
final byte SECTION_5 = (byte) 0xC0;
|
||||
final byte SECTION_6 = (byte) 0xA8;
|
||||
switch (b0)
|
||||
{
|
||||
switch (b0) {
|
||||
case SECTION_1:
|
||||
return true;
|
||||
case SECTION_2:
|
||||
if (b1 >= SECTION_3 && b1 <= SECTION_4)
|
||||
{
|
||||
if (b1 >= SECTION_3 && b1 <= SECTION_4) {
|
||||
return true;
|
||||
}
|
||||
case SECTION_5:
|
||||
switch (b1)
|
||||
{
|
||||
case SECTION_6:
|
||||
return true;
|
||||
if (b1 == SECTION_6) {
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
@ -108,29 +93,24 @@ public class IpUtils
|
||||
|
||||
/**
|
||||
* 将IPv4地址转换成字节
|
||||
*
|
||||
*
|
||||
* @param text IPv4地址
|
||||
* @return byte 字节
|
||||
*/
|
||||
public static byte[] textToNumericFormatV4(String text)
|
||||
{
|
||||
if (text.length() == 0)
|
||||
{
|
||||
public static byte[] textToNumericFormatV4(String text) {
|
||||
if (text.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] bytes = new byte[4];
|
||||
String[] elements = text.split("\\.", -1);
|
||||
try
|
||||
{
|
||||
try {
|
||||
long l;
|
||||
int i;
|
||||
switch (elements.length)
|
||||
{
|
||||
switch (elements.length) {
|
||||
case 1:
|
||||
l = Long.parseLong(elements[0]);
|
||||
if ((l < 0L) || (l > 4294967295L))
|
||||
{
|
||||
if ((l < 0L) || (l > 4294967295L)) {
|
||||
return null;
|
||||
}
|
||||
bytes[0] = (byte) (int) (l >> 24 & 0xFF);
|
||||
@ -140,14 +120,12 @@ public class IpUtils
|
||||
break;
|
||||
case 2:
|
||||
l = Integer.parseInt(elements[0]);
|
||||
if ((l < 0L) || (l > 255L))
|
||||
{
|
||||
if ((l < 0L) || (l > 255L)) {
|
||||
return null;
|
||||
}
|
||||
bytes[0] = (byte) (int) (l & 0xFF);
|
||||
l = Integer.parseInt(elements[1]);
|
||||
if ((l < 0L) || (l > 16777215L))
|
||||
{
|
||||
if ((l < 0L) || (l > 16777215L)) {
|
||||
return null;
|
||||
}
|
||||
bytes[1] = (byte) (int) (l >> 16 & 0xFF);
|
||||
@ -155,29 +133,24 @@ public class IpUtils
|
||||
bytes[3] = (byte) (int) (l & 0xFF);
|
||||
break;
|
||||
case 3:
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
for (i = 0; i < 2; ++i) {
|
||||
l = Integer.parseInt(elements[i]);
|
||||
if ((l < 0L) || (l > 255L))
|
||||
{
|
||||
if ((l < 0L) || (l > 255L)) {
|
||||
return null;
|
||||
}
|
||||
bytes[i] = (byte) (int) (l & 0xFF);
|
||||
}
|
||||
l = Integer.parseInt(elements[2]);
|
||||
if ((l < 0L) || (l > 65535L))
|
||||
{
|
||||
if ((l < 0L) || (l > 65535L)) {
|
||||
return null;
|
||||
}
|
||||
bytes[2] = (byte) (int) (l >> 8 & 0xFF);
|
||||
bytes[3] = (byte) (int) (l & 0xFF);
|
||||
break;
|
||||
case 4:
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
for (i = 0; i < 4; ++i) {
|
||||
l = Integer.parseInt(elements[i]);
|
||||
if ((l < 0L) || (l > 255L))
|
||||
{
|
||||
if ((l < 0L) || (l > 255L)) {
|
||||
return null;
|
||||
}
|
||||
bytes[i] = (byte) (int) (l & 0xFF);
|
||||
@ -186,9 +159,7 @@ public class IpUtils
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
return bytes;
|
||||
@ -196,34 +167,26 @@ public class IpUtils
|
||||
|
||||
/**
|
||||
* 获取IP地址
|
||||
*
|
||||
*
|
||||
* @return 本地IP地址
|
||||
*/
|
||||
public static String getHostIp()
|
||||
{
|
||||
try
|
||||
{
|
||||
public static String getHostIp() {
|
||||
try {
|
||||
return InetAddress.getLocalHost().getHostAddress();
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
} catch (UnknownHostException e) {
|
||||
}
|
||||
return "127.0.0.1";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主机名
|
||||
*
|
||||
*
|
||||
* @return 本地主机名
|
||||
*/
|
||||
public static String getHostName()
|
||||
{
|
||||
try
|
||||
{
|
||||
public static String getHostName() {
|
||||
try {
|
||||
return InetAddress.getLocalHost().getHostName();
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
} catch (UnknownHostException e) {
|
||||
}
|
||||
return "未知";
|
||||
}
|
||||
@ -234,16 +197,12 @@ public class IpUtils
|
||||
* @param ip 获得的IP地址
|
||||
* @return 第一个非unknown IP地址
|
||||
*/
|
||||
public static String getMultistageReverseProxyIp(String ip)
|
||||
{
|
||||
public static String getMultistageReverseProxyIp(String ip) {
|
||||
// 多级反向代理检测
|
||||
if (ip != null && ip.indexOf(",") > 0)
|
||||
{
|
||||
if (ip != null && ip.indexOf(",") > 0) {
|
||||
final String[] ips = ip.trim().split(",");
|
||||
for (String subIp : ips)
|
||||
{
|
||||
if (false == isUnknown(subIp))
|
||||
{
|
||||
for (String subIp : ips) {
|
||||
if (false == isUnknown(subIp)) {
|
||||
ip = subIp;
|
||||
break;
|
||||
}
|
||||
@ -258,8 +217,7 @@ public class IpUtils
|
||||
* @param checkString 被检测的字符串
|
||||
* @return 是否未知
|
||||
*/
|
||||
public static boolean isUnknown(String checkString)
|
||||
{
|
||||
public static boolean isUnknown(String checkString) {
|
||||
return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>fastbee</artifactId>
|
||||
@ -18,7 +18,7 @@
|
||||
<dependencies>
|
||||
|
||||
<!-- SpringBoot Web容器 -->
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
@ -1,16 +1,5 @@
|
||||
package com.fastbee.framework.aspect;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
//@Aspect
|
||||
//@Component
|
||||
public class WebLogAspect {
|
||||
@ -48,7 +37,7 @@ public class WebLogAspect {
|
||||
// @After("webLog()")
|
||||
// public void doAfter() throws Throwable {
|
||||
// logger.info("=========================================== End ===========================================");
|
||||
// 每个请求之间空一行
|
||||
// 每个请求之间空一行
|
||||
// logger.info("");
|
||||
// }
|
||||
// /**
|
||||
|
||||
@ -1,11 +1,5 @@
|
||||
package com.fastbee.framework.aspectj;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.fastbee.common.annotation.DataScope;
|
||||
import com.fastbee.common.core.domain.BaseEntity;
|
||||
import com.fastbee.common.core.domain.entity.SysRole;
|
||||
@ -15,6 +9,13 @@ import com.fastbee.common.core.text.Convert;
|
||||
import com.fastbee.common.utils.SecurityUtils;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.framework.security.context.PermissionContextHolder;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据过滤处理
|
||||
@ -23,8 +24,7 @@ import com.fastbee.framework.security.context.PermissionContextHolder;
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class DataScopeAspect
|
||||
{
|
||||
public class DataScopeAspect {
|
||||
/**
|
||||
* 全部数据权限
|
||||
*/
|
||||
@ -55,23 +55,74 @@ public class DataScopeAspect
|
||||
*/
|
||||
public static final String DATA_SCOPE = "dataScope";
|
||||
|
||||
/**
|
||||
* 数据范围过滤
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
* @param user 用户
|
||||
* @param deptAlias 部门别名
|
||||
* @param userAlias 用户别名
|
||||
* @param permission 权限字符
|
||||
*/
|
||||
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission) {
|
||||
StringBuilder sqlString = new StringBuilder();
|
||||
List<String> conditions = new ArrayList<String>();
|
||||
|
||||
for (SysRole role : user.getRoles()) {
|
||||
String dataScope = role.getDataScope();
|
||||
if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope)) {
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
|
||||
&& !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) {
|
||||
continue;
|
||||
}
|
||||
if (DATA_SCOPE_ALL.equals(dataScope)) {
|
||||
sqlString = new StringBuilder();
|
||||
break;
|
||||
} else if (DATA_SCOPE_CUSTOM.equals(dataScope)) {
|
||||
sqlString.append(StringUtils.format(
|
||||
" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
|
||||
role.getRoleId()));
|
||||
} else if (DATA_SCOPE_DEPT.equals(dataScope)) {
|
||||
sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
|
||||
} else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
|
||||
sqlString.append(StringUtils.format(
|
||||
" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
|
||||
deptAlias, user.getDeptId(), user.getDeptId()));
|
||||
} else if (DATA_SCOPE_SELF.equals(dataScope)) {
|
||||
if (StringUtils.isNotBlank(userAlias)) {
|
||||
sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
|
||||
} else {
|
||||
// 数据权限为仅本人且没有userAlias别名不查询任何数据
|
||||
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
|
||||
}
|
||||
}
|
||||
conditions.add(dataScope);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(sqlString.toString())) {
|
||||
Object params = joinPoint.getArgs()[0];
|
||||
if (StringUtils.isNotNull(params) && params instanceof BaseEntity) {
|
||||
BaseEntity baseEntity = (BaseEntity) params;
|
||||
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Before("@annotation(controllerDataScope)")
|
||||
public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable
|
||||
{
|
||||
public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable {
|
||||
clearDataScope(point);
|
||||
handleDataScope(point, controllerDataScope);
|
||||
}
|
||||
|
||||
protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope)
|
||||
{
|
||||
protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) {
|
||||
// 获取当前的用户
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (StringUtils.isNotNull(loginUser))
|
||||
{
|
||||
if (StringUtils.isNotNull(loginUser)) {
|
||||
SysUser currentUser = loginUser.getUser();
|
||||
// 如果是超级管理员,则不过滤数据
|
||||
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
|
||||
{
|
||||
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) {
|
||||
String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
|
||||
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
|
||||
controllerDataScope.userAlias(), permission);
|
||||
@ -79,87 +130,12 @@ public class DataScopeAspect
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据范围过滤
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
* @param user 用户
|
||||
* @param deptAlias 部门别名
|
||||
* @param userAlias 用户别名
|
||||
* @param permission 权限字符
|
||||
*/
|
||||
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission)
|
||||
{
|
||||
StringBuilder sqlString = new StringBuilder();
|
||||
List<String> conditions = new ArrayList<String>();
|
||||
|
||||
for (SysRole role : user.getRoles())
|
||||
{
|
||||
String dataScope = role.getDataScope();
|
||||
if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
|
||||
&& !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (DATA_SCOPE_ALL.equals(dataScope))
|
||||
{
|
||||
sqlString = new StringBuilder();
|
||||
break;
|
||||
}
|
||||
else if (DATA_SCOPE_CUSTOM.equals(dataScope))
|
||||
{
|
||||
sqlString.append(StringUtils.format(
|
||||
" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
|
||||
role.getRoleId()));
|
||||
}
|
||||
else if (DATA_SCOPE_DEPT.equals(dataScope))
|
||||
{
|
||||
sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
|
||||
}
|
||||
else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
|
||||
{
|
||||
sqlString.append(StringUtils.format(
|
||||
" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
|
||||
deptAlias, user.getDeptId(), user.getDeptId()));
|
||||
}
|
||||
else if (DATA_SCOPE_SELF.equals(dataScope))
|
||||
{
|
||||
if (StringUtils.isNotBlank(userAlias))
|
||||
{
|
||||
sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 数据权限为仅本人且没有userAlias别名不查询任何数据
|
||||
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
|
||||
}
|
||||
}
|
||||
conditions.add(dataScope);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(sqlString.toString()))
|
||||
{
|
||||
Object params = joinPoint.getArgs()[0];
|
||||
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
|
||||
{
|
||||
BaseEntity baseEntity = (BaseEntity) params;
|
||||
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接权限sql前先清空params.dataScope参数防止注入
|
||||
*/
|
||||
private void clearDataScope(final JoinPoint joinPoint)
|
||||
{
|
||||
private void clearDataScope(final JoinPoint joinPoint) {
|
||||
Object params = joinPoint.getArgs()[0];
|
||||
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
|
||||
{
|
||||
if (StringUtils.isNotNull(params) && params instanceof BaseEntity) {
|
||||
BaseEntity baseEntity = (BaseEntity) params;
|
||||
baseEntity.getParams().put(DATA_SCOPE, "");
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package com.fastbee.framework.aspectj;
|
||||
|
||||
import java.util.Objects;
|
||||
import com.fastbee.common.annotation.DataSource;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.framework.datasource.DynamicDataSourceContextHolder;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
@ -11,45 +13,37 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.fastbee.common.annotation.DataSource;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.framework.datasource.DynamicDataSourceContextHolder;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 多数据源处理
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Aspect
|
||||
@Order(1)
|
||||
@Component
|
||||
public class DataSourceAspect
|
||||
{
|
||||
public class DataSourceAspect {
|
||||
protected Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Pointcut("@annotation(com.fastbee.common.annotation.DataSource)"
|
||||
+ "|| @within(com.fastbee.common.annotation.DataSource)")
|
||||
public void dsPointCut()
|
||||
{
|
||||
public void dsPointCut() {
|
||||
|
||||
}
|
||||
|
||||
@Around("dsPointCut()")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable
|
||||
{
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
DataSource dataSource = getDataSource(point);
|
||||
|
||||
if (StringUtils.isNotNull(dataSource))
|
||||
{
|
||||
if (StringUtils.isNotNull(dataSource)) {
|
||||
DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
return point.proceed();
|
||||
}
|
||||
finally
|
||||
{
|
||||
} finally {
|
||||
// 销毁数据源 在执行方法之后
|
||||
DynamicDataSourceContextHolder.clearDataSourceType();
|
||||
}
|
||||
@ -58,12 +52,10 @@ public class DataSourceAspect
|
||||
/**
|
||||
* 获取需要切换的数据源
|
||||
*/
|
||||
public DataSource getDataSource(ProceedingJoinPoint point)
|
||||
{
|
||||
public DataSource getDataSource(ProceedingJoinPoint point) {
|
||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||
DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
|
||||
if (Objects.nonNull(dataSource))
|
||||
{
|
||||
if (Objects.nonNull(dataSource)) {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +1,5 @@
|
||||
package com.fastbee.framework.aspectj;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.AfterThrowing;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.fastbee.common.annotation.Log;
|
||||
import com.fastbee.common.core.domain.model.LoginUser;
|
||||
@ -26,48 +13,58 @@ import com.fastbee.common.utils.ip.IpUtils;
|
||||
import com.fastbee.framework.manager.AsyncManager;
|
||||
import com.fastbee.framework.manager.factory.AsyncFactory;
|
||||
import com.fastbee.system.domain.SysOperLog;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.AfterThrowing;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 操作日志记录处理
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class LogAspect
|
||||
{
|
||||
public class LogAspect {
|
||||
/**
|
||||
* 排除敏感属性字段
|
||||
*/
|
||||
public static final String[] EXCLUDE_PROPERTIES = {"password", "oldPassword", "newPassword", "confirmPassword"};
|
||||
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
|
||||
|
||||
/** 排除敏感属性字段 */
|
||||
public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
|
||||
|
||||
/**
|
||||
* 处理完请求后执行
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
*/
|
||||
@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
|
||||
public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult)
|
||||
{
|
||||
public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
|
||||
handleLog(joinPoint, controllerLog, null, jsonResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截异常操作
|
||||
*
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
* @param e 异常
|
||||
* @param e 异常
|
||||
*/
|
||||
@AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
|
||||
public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e)
|
||||
{
|
||||
public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {
|
||||
handleLog(joinPoint, controllerLog, e, null);
|
||||
}
|
||||
|
||||
protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) {
|
||||
try {
|
||||
// 获取当前的用户
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
|
||||
@ -78,13 +75,11 @@ public class LogAspect
|
||||
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
|
||||
operLog.setOperIp(ip);
|
||||
operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
|
||||
if (loginUser != null)
|
||||
{
|
||||
if (loginUser != null) {
|
||||
operLog.setOperName(loginUser.getUsername());
|
||||
}
|
||||
|
||||
if (e != null)
|
||||
{
|
||||
if (e != null) {
|
||||
operLog.setStatus(BusinessStatus.FAIL.ordinal());
|
||||
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
|
||||
}
|
||||
@ -98,9 +93,7 @@ public class LogAspect
|
||||
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
|
||||
// 保存数据库
|
||||
AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
} catch (Exception exp) {
|
||||
// 记录本地异常日志
|
||||
log.error("异常信息:{}", exp.getMessage());
|
||||
exp.printStackTrace();
|
||||
@ -109,13 +102,12 @@ public class LogAspect
|
||||
|
||||
/**
|
||||
* 获取注解中对方法的描述信息 用于Controller层注解
|
||||
*
|
||||
* @param log 日志
|
||||
*
|
||||
* @param log 日志
|
||||
* @param operLog 操作日志
|
||||
* @throws Exception
|
||||
*/
|
||||
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception
|
||||
{
|
||||
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception {
|
||||
// 设置action动作
|
||||
operLog.setBusinessType(log.businessType().ordinal());
|
||||
// 设置标题
|
||||
@ -123,34 +115,28 @@ public class LogAspect
|
||||
// 设置操作人类别
|
||||
operLog.setOperatorType(log.operatorType().ordinal());
|
||||
// 是否需要保存request,参数和值
|
||||
if (log.isSaveRequestData())
|
||||
{
|
||||
if (log.isSaveRequestData()) {
|
||||
// 获取参数的信息,传入到数据库中。
|
||||
setRequestValue(joinPoint, operLog);
|
||||
}
|
||||
// 是否需要保存response,参数和值
|
||||
if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult))
|
||||
{
|
||||
if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) {
|
||||
operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求的参数,放到log中
|
||||
*
|
||||
*
|
||||
* @param operLog 操作日志
|
||||
* @throws Exception 异常
|
||||
*/
|
||||
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception
|
||||
{
|
||||
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception {
|
||||
String requestMethod = operLog.getRequestMethod();
|
||||
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod))
|
||||
{
|
||||
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
|
||||
String params = argsArrayToString(joinPoint.getArgs());
|
||||
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
|
||||
operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter()), 0, 2000));
|
||||
}
|
||||
@ -159,22 +145,15 @@ public class LogAspect
|
||||
/**
|
||||
* 参数拼装
|
||||
*/
|
||||
private String argsArrayToString(Object[] paramsArray)
|
||||
{
|
||||
private String argsArrayToString(Object[] paramsArray) {
|
||||
String params = "";
|
||||
if (paramsArray != null && paramsArray.length > 0)
|
||||
{
|
||||
for (Object o : paramsArray)
|
||||
{
|
||||
if (StringUtils.isNotNull(o) && !isFilterObject(o))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (paramsArray != null && paramsArray.length > 0) {
|
||||
for (Object o : paramsArray) {
|
||||
if (StringUtils.isNotNull(o) && !isFilterObject(o)) {
|
||||
try {
|
||||
String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter());
|
||||
params += jsonObj.toString() + " ";
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,38 +164,29 @@ public class LogAspect
|
||||
/**
|
||||
* 忽略敏感属性
|
||||
*/
|
||||
public PropertyPreExcludeFilter excludePropertyPreFilter()
|
||||
{
|
||||
public PropertyPreExcludeFilter excludePropertyPreFilter() {
|
||||
return new PropertyPreExcludeFilter().addExcludes(EXCLUDE_PROPERTIES);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否需要过滤的对象。
|
||||
*
|
||||
*
|
||||
* @param o 对象信息。
|
||||
* @return 如果是需要过滤的对象,则返回true;否则返回false。
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public boolean isFilterObject(final Object o)
|
||||
{
|
||||
public boolean isFilterObject(final Object o) {
|
||||
Class<?> clazz = o.getClass();
|
||||
if (clazz.isArray())
|
||||
{
|
||||
if (clazz.isArray()) {
|
||||
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
|
||||
}
|
||||
else if (Collection.class.isAssignableFrom(clazz))
|
||||
{
|
||||
} else if (Collection.class.isAssignableFrom(clazz)) {
|
||||
Collection collection = (Collection) o;
|
||||
for (Object value : collection)
|
||||
{
|
||||
for (Object value : collection) {
|
||||
return value instanceof MultipartFile;
|
||||
}
|
||||
}
|
||||
else if (Map.class.isAssignableFrom(clazz))
|
||||
{
|
||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||
Map map = (Map) o;
|
||||
for (Object value : map.entrySet())
|
||||
{
|
||||
for (Object value : map.entrySet()) {
|
||||
Map.Entry entry = (Map.Entry) value;
|
||||
return entry.getValue() instanceof MultipartFile;
|
||||
}
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
package com.fastbee.framework.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import com.fastbee.common.annotation.RateLimiter;
|
||||
import com.fastbee.common.enums.LimitType;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.ServletUtils;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.common.utils.ip.IpUtils;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
@ -13,12 +16,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.script.RedisScript;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.fastbee.common.annotation.RateLimiter;
|
||||
import com.fastbee.common.enums.LimitType;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.ServletUtils;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.common.utils.ip.IpUtils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 限流处理
|
||||
@ -27,8 +28,7 @@ import com.fastbee.common.utils.ip.IpUtils;
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class RateLimiterAspect
|
||||
{
|
||||
public class RateLimiterAspect {
|
||||
private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
|
||||
|
||||
private RedisTemplate<Object, Object> redisTemplate;
|
||||
@ -36,49 +36,38 @@ public class RateLimiterAspect
|
||||
private RedisScript<Long> limitScript;
|
||||
|
||||
@Autowired
|
||||
public void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate)
|
||||
{
|
||||
public void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setLimitScript(RedisScript<Long> limitScript)
|
||||
{
|
||||
public void setLimitScript(RedisScript<Long> limitScript) {
|
||||
this.limitScript = limitScript;
|
||||
}
|
||||
|
||||
@Before("@annotation(rateLimiter)")
|
||||
public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable
|
||||
{
|
||||
public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable {
|
||||
int time = rateLimiter.time();
|
||||
int count = rateLimiter.count();
|
||||
|
||||
String combineKey = getCombineKey(rateLimiter, point);
|
||||
List<Object> keys = Collections.singletonList(combineKey);
|
||||
try
|
||||
{
|
||||
try {
|
||||
Long number = redisTemplate.execute(limitScript, keys, count, time);
|
||||
if (StringUtils.isNull(number) || number.intValue() > count)
|
||||
{
|
||||
if (StringUtils.isNull(number) || number.intValue() > count) {
|
||||
throw new ServiceException("访问过于频繁,请稍候再试");
|
||||
}
|
||||
log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), combineKey);
|
||||
}
|
||||
catch (ServiceException e)
|
||||
{
|
||||
} catch (ServiceException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("服务器限流异常,请稍候再试");
|
||||
}
|
||||
}
|
||||
|
||||
public String getCombineKey(RateLimiter rateLimiter, JoinPoint point)
|
||||
{
|
||||
public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) {
|
||||
StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
|
||||
if (rateLimiter.limitType() == LimitType.IP)
|
||||
{
|
||||
if (rateLimiter.limitType() == LimitType.IP) {
|
||||
stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-");
|
||||
}
|
||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import java.util.TimeZone;
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* 程序注解配置
|
||||
*
|
||||
@ -14,14 +15,12 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
@Configuration
|
||||
// 表示通过aop框架暴露该代理对象,AopContext能够访问
|
||||
@EnableAspectJAutoProxy(exposeProxy = true)
|
||||
public class ApplicationConfig
|
||||
{
|
||||
public class ApplicationConfig {
|
||||
/**
|
||||
* 时区配置
|
||||
*/
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization()
|
||||
{
|
||||
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
|
||||
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import java.util.Properties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.google.code.kaptcha.impl.DefaultKaptcha;
|
||||
import com.google.code.kaptcha.util.Config;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import static com.google.code.kaptcha.Constants.*;
|
||||
|
||||
/**
|
||||
* 验证码配置
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class CaptchaConfig
|
||||
{
|
||||
public class CaptchaConfig {
|
||||
@Bean(name = "captchaProducer")
|
||||
public DefaultKaptcha getKaptchaBean()
|
||||
{
|
||||
public DefaultKaptcha getKaptchaBean() {
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
Properties properties = new Properties();
|
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
@ -44,8 +44,7 @@ public class CaptchaConfig
|
||||
}
|
||||
|
||||
@Bean(name = "captchaProducerMath")
|
||||
public DefaultKaptcha getKaptchaBeanMath()
|
||||
{
|
||||
public DefaultKaptcha getKaptchaBeanMath() {
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
Properties properties = new Properties();
|
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
|
||||
@ -31,8 +31,8 @@ public class DataSourceConfig {
|
||||
private final DataSource shardingSphereDataSource;
|
||||
|
||||
public DataSourceConfig(DynamicDataSourceProperties properties,
|
||||
DefaultDataSourceCreator dataSourceCreator,
|
||||
@Qualifier("shardingSphereDataSource") DataSource shardingSphereDataSource) {
|
||||
DefaultDataSourceCreator dataSourceCreator,
|
||||
@Qualifier("shardingSphereDataSource") DataSource shardingSphereDataSource) {
|
||||
this.properties = properties;
|
||||
this.dataSourceCreator = dataSourceCreator;
|
||||
this.shardingSphereDataSource = shardingSphereDataSource;
|
||||
|
||||
@ -15,11 +15,10 @@ public class DruidConfig {
|
||||
/**
|
||||
* 去除监控页面底部的广告
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true")
|
||||
public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
|
||||
{
|
||||
public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) {
|
||||
// 获取web监控页面的参数
|
||||
DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
|
||||
// 提取common.js的配置路径
|
||||
@ -27,16 +26,14 @@ public class DruidConfig {
|
||||
String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
|
||||
final String filePath = "support/http/resources/js/common.js";
|
||||
// 创建filter进行过滤
|
||||
Filter filter = new Filter()
|
||||
{
|
||||
Filter filter = new Filter() {
|
||||
@Override
|
||||
public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
|
||||
{
|
||||
public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
throws IOException, ServletException {
|
||||
chain.doFilter(request, response);
|
||||
// 重置缓冲区,响应头不会被重置
|
||||
response.resetBuffer();
|
||||
@ -47,9 +44,9 @@ public class DruidConfig {
|
||||
text = text.replaceAll("powered.*?shrek.wang</a>", "");
|
||||
response.getWriter().write(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
public void destroy() {
|
||||
}
|
||||
};
|
||||
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
|
||||
|
||||
@ -1,44 +1,39 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.SerializationException;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONReader;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.SerializationException;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Redis使用FastJson序列化
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
|
||||
{
|
||||
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
|
||||
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
private Class<T> clazz;
|
||||
|
||||
public FastJson2JsonRedisSerializer(Class<T> clazz)
|
||||
{
|
||||
public FastJson2JsonRedisSerializer(Class<T> clazz) {
|
||||
super();
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(T t) throws SerializationException
|
||||
{
|
||||
if (t == null)
|
||||
{
|
||||
public byte[] serialize(T t) throws SerializationException {
|
||||
if (t == null) {
|
||||
return new byte[0];
|
||||
}
|
||||
return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T deserialize(byte[] bytes) throws SerializationException
|
||||
{
|
||||
if (bytes == null || bytes.length <= 0)
|
||||
{
|
||||
public T deserialize(byte[] bytes) throws SerializationException {
|
||||
if (bytes == null || bytes.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
String str = new String(bytes, DEFAULT_CHARSET);
|
||||
|
||||
@ -1,16 +1,17 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.servlet.DispatcherType;
|
||||
import com.fastbee.common.filter.RepeatableFilter;
|
||||
import com.fastbee.common.filter.XssFilter;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.fastbee.common.filter.RepeatableFilter;
|
||||
import com.fastbee.common.filter.XssFilter;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Filter配置
|
||||
@ -18,19 +19,17 @@ import com.fastbee.common.utils.StringUtils;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class FilterConfig
|
||||
{
|
||||
public class FilterConfig {
|
||||
@Value("${xss.excludes}")
|
||||
private String excludes;
|
||||
|
||||
@Value("${xss.urlPatterns}")
|
||||
private String urlPatterns;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
|
||||
public FilterRegistrationBean xssFilterRegistration()
|
||||
{
|
||||
public FilterRegistrationBean xssFilterRegistration() {
|
||||
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
registration.setDispatcherTypes(DispatcherType.REQUEST);
|
||||
registration.setFilter(new XssFilter());
|
||||
@ -43,10 +42,9 @@ public class FilterConfig
|
||||
return registration;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@Bean
|
||||
public FilterRegistrationBean someFilterRegistration()
|
||||
{
|
||||
public FilterRegistrationBean someFilterRegistration() {
|
||||
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
registration.setFilter(new RepeatableFilter());
|
||||
registration.addUrlPatterns("/*");
|
||||
|
||||
@ -1,61 +1,49 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import java.util.Random;
|
||||
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* 验证码文本生成器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class KaptchaTextCreator extends DefaultTextCreator
|
||||
{
|
||||
public class KaptchaTextCreator extends DefaultTextCreator {
|
||||
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
|
||||
|
||||
@Override
|
||||
public String getText()
|
||||
{
|
||||
public String getText() {
|
||||
Integer result = 0;
|
||||
Random random = new Random();
|
||||
int x = random.nextInt(10);
|
||||
int y = random.nextInt(10);
|
||||
StringBuilder suChinese = new StringBuilder();
|
||||
int randomoperands = random.nextInt(3);
|
||||
if (randomoperands == 0)
|
||||
{
|
||||
if (randomoperands == 0) {
|
||||
result = x * y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("*");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
else if (randomoperands == 1)
|
||||
{
|
||||
if ((x != 0) && y % x == 0)
|
||||
{
|
||||
} else if (randomoperands == 1) {
|
||||
if ((x != 0) && y % x == 0) {
|
||||
result = y / x;
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
suChinese.append("/");
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
result = x + y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("+");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x >= y)
|
||||
{
|
||||
} else {
|
||||
if (x >= y) {
|
||||
result = x - y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("-");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
result = y - x;
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
suChinese.append("-");
|
||||
|
||||
@ -8,8 +8,9 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
@Configuration
|
||||
public class OtaThreadPoolConfig
|
||||
{
|
||||
public class OtaThreadPoolConfig {
|
||||
// 配置线程池的前缀
|
||||
private static final String threadNamePrefix = "ota-";
|
||||
// 核心线程池大小
|
||||
private int corePoolSize = 10;
|
||||
// 最大可创建的线程数
|
||||
@ -18,12 +19,9 @@ public class OtaThreadPoolConfig
|
||||
private int queueCapacity = 10000;
|
||||
// 线程池维护线程所允许的空闲时间
|
||||
private int keepAliveSeconds = 30;
|
||||
// 配置线程池的前缀
|
||||
private static final String threadNamePrefix = "ota-";
|
||||
|
||||
@Bean(name = FastBeeConstant.TASK.OTA_THREAD_POOL)
|
||||
public ThreadPoolTaskExecutor threadPoolTaskExecutor()
|
||||
{
|
||||
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setMaxPoolSize(maxPoolSize);
|
||||
executor.setCorePoolSize(corePoolSize);
|
||||
|
||||
@ -14,12 +14,10 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class RedisConfig extends CachingConfigurerSupport
|
||||
{
|
||||
public class RedisConfig extends CachingConfigurerSupport {
|
||||
@Bean
|
||||
@SuppressWarnings(value = { "unchecked", "rawtypes" })
|
||||
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
|
||||
{
|
||||
@SuppressWarnings(value = {"unchecked", "rawtypes"})
|
||||
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<Object, Object> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
|
||||
@ -38,8 +36,7 @@ public class RedisConfig extends CachingConfigurerSupport
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DefaultRedisScript<Long> limitScript()
|
||||
{
|
||||
public DefaultRedisScript<Long> limitScript() {
|
||||
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
|
||||
redisScript.setScriptText(limitScriptText());
|
||||
redisScript.setResultType(Long.class);
|
||||
@ -49,8 +46,7 @@ public class RedisConfig extends CachingConfigurerSupport
|
||||
/**
|
||||
* 限流脚本
|
||||
*/
|
||||
private String limitScriptText()
|
||||
{
|
||||
private String limitScriptText() {
|
||||
return "local key = KEYS[1]\n" +
|
||||
"local count = tonumber(ARGV[1])\n" +
|
||||
"local time = tonumber(ARGV[2])\n" +
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.fastbee.framework.config.properties.RedissonProperties;
|
||||
import com.fastbee.framework.handler.KeyPrefixHandler;
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@ -9,7 +11,6 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.fastbee.framework.config.properties.RedissonProperties;
|
||||
import org.redisson.client.codec.StringCodec;
|
||||
import org.redisson.codec.CompositeCodec;
|
||||
import org.redisson.codec.TypedJsonJacksonCodec;
|
||||
@ -18,8 +19,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.fastbee.framework.handler.KeyPrefixHandler;
|
||||
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
@ -53,39 +52,39 @@ public class RedissonConfig {
|
||||
// 组合序列化 key 使用 String 内容使用通用 json 格式
|
||||
CompositeCodec codec = new CompositeCodec(StringCodec.INSTANCE, jsonCodec, jsonCodec);
|
||||
config.setThreads(redissonProperties.getThreads())
|
||||
.setNettyThreads(redissonProperties.getNettyThreads())
|
||||
// 缓存 Lua 脚本 减少网络传输(redisson 大部分的功能都是基于 Lua 脚本实现)
|
||||
.setUseScriptCache(true)
|
||||
.setCodec(codec);
|
||||
.setNettyThreads(redissonProperties.getNettyThreads())
|
||||
// 缓存 Lua 脚本 减少网络传输(redisson 大部分的功能都是基于 Lua 脚本实现)
|
||||
.setUseScriptCache(true)
|
||||
.setCodec(codec);
|
||||
RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
|
||||
if (ObjectUtil.isNotNull(singleServerConfig)) {
|
||||
// 使用单机模式
|
||||
config.useSingleServer()
|
||||
//设置redis key前缀
|
||||
.setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix()))
|
||||
.setTimeout(singleServerConfig.getTimeout())
|
||||
.setClientName(singleServerConfig.getClientName())
|
||||
.setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
|
||||
.setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
|
||||
.setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
|
||||
.setConnectionPoolSize(singleServerConfig.getConnectionPoolSize());
|
||||
//设置redis key前缀
|
||||
.setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix()))
|
||||
.setTimeout(singleServerConfig.getTimeout())
|
||||
.setClientName(singleServerConfig.getClientName())
|
||||
.setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
|
||||
.setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
|
||||
.setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
|
||||
.setConnectionPoolSize(singleServerConfig.getConnectionPoolSize());
|
||||
}
|
||||
// 集群配置方式 参考下方注释
|
||||
RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig();
|
||||
if (ObjectUtil.isNotNull(clusterServersConfig)) {
|
||||
config.useClusterServers()
|
||||
//设置redis key前缀
|
||||
.setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix()))
|
||||
.setTimeout(clusterServersConfig.getTimeout())
|
||||
.setClientName(clusterServersConfig.getClientName())
|
||||
.setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
|
||||
.setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
|
||||
.setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
|
||||
.setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
|
||||
.setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
|
||||
.setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
|
||||
.setReadMode(clusterServersConfig.getReadMode())
|
||||
.setSubscriptionMode(clusterServersConfig.getSubscriptionMode());
|
||||
//设置redis key前缀
|
||||
.setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix()))
|
||||
.setTimeout(clusterServersConfig.getTimeout())
|
||||
.setClientName(clusterServersConfig.getClientName())
|
||||
.setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
|
||||
.setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
|
||||
.setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
|
||||
.setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
|
||||
.setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
|
||||
.setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
|
||||
.setReadMode(clusterServersConfig.getReadMode())
|
||||
.setSubscriptionMode(clusterServersConfig.getSubscriptionMode());
|
||||
}
|
||||
log.info("初始化 redis 配置");
|
||||
};
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.fastbee.common.config.RuoYiConfig;
|
||||
import com.fastbee.common.constant.Constants;
|
||||
import com.fastbee.framework.interceptor.LanguageInterceptor;
|
||||
import com.fastbee.framework.interceptor.RepeatSubmitInterceptor;
|
||||
import com.fastbee.framework.interceptor.TraceIdInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -14,20 +15,17 @@ import org.springframework.web.filter.CorsFilter;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import com.fastbee.common.config.RuoYiConfig;
|
||||
import com.fastbee.common.constant.Constants;
|
||||
import com.fastbee.framework.interceptor.RepeatSubmitInterceptor;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 通用配置
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class ResourcesConfig implements WebMvcConfigurer
|
||||
{
|
||||
public class ResourcesConfig implements WebMvcConfigurer {
|
||||
@Autowired
|
||||
private RepeatSubmitInterceptor repeatSubmitInterceptor;
|
||||
@Resource
|
||||
@ -36,8 +34,7 @@ public class ResourcesConfig implements WebMvcConfigurer
|
||||
private TraceIdInterceptor traceIdInterceptor;
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry)
|
||||
{
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
/** 本地文件上传路径 */
|
||||
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
|
||||
.addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
|
||||
@ -45,15 +42,15 @@ public class ResourcesConfig implements WebMvcConfigurer
|
||||
/** swagger配置 */
|
||||
registry.addResourceHandler("/swagger-ui/**")
|
||||
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
|
||||
.setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());;
|
||||
.setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义拦截规则
|
||||
*/
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry)
|
||||
{
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// TraceId拦截器放在最前面,确保所有请求都有TraceId
|
||||
registry.addInterceptor(traceIdInterceptor).addPathPatterns("/**").order(0);
|
||||
registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
|
||||
@ -66,8 +63,7 @@ public class ResourcesConfig implements WebMvcConfigurer
|
||||
* 跨域配置
|
||||
*/
|
||||
@Bean
|
||||
public CorsFilter corsFilter()
|
||||
{
|
||||
public CorsFilter corsFilter() {
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.setAllowCredentials(true);
|
||||
// 设置访问源地址
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import com.fastbee.framework.config.properties.PermitAllUrlProperties;
|
||||
import com.fastbee.framework.security.filter.JwtAuthenticationTokenFilter;
|
||||
import com.fastbee.framework.security.handle.AuthenticationEntryPointImpl;
|
||||
import com.fastbee.framework.security.handle.LogoutSuccessHandlerImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@ -15,10 +19,6 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import com.fastbee.framework.config.properties.PermitAllUrlProperties;
|
||||
import com.fastbee.framework.security.filter.JwtAuthenticationTokenFilter;
|
||||
import com.fastbee.framework.security.handle.AuthenticationEntryPointImpl;
|
||||
import com.fastbee.framework.security.handle.LogoutSuccessHandlerImpl;
|
||||
|
||||
/**
|
||||
* spring security配置
|
||||
@ -27,8 +27,7 @@ import com.fastbee.framework.security.handle.LogoutSuccessHandlerImpl;
|
||||
*/
|
||||
//@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
{
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
/**
|
||||
* 自定义用户认证逻辑
|
||||
*/
|
||||
@ -73,8 +72,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
*/
|
||||
@Bean
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception
|
||||
{
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@ -94,8 +92,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
* authenticated | 用户登录后可访问
|
||||
*/
|
||||
@Override
|
||||
protected void configure(HttpSecurity httpSecurity) throws Exception
|
||||
{
|
||||
protected void configure(HttpSecurity httpSecurity) throws Exception {
|
||||
// 注解标记允许匿名访问的url
|
||||
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();
|
||||
permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());
|
||||
@ -113,17 +110,17 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
// 过滤请求
|
||||
.authorizeRequests()
|
||||
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
|
||||
.antMatchers("/login", "/register", "/captchaImage","/iot/tool/register","/iot/tool/ntp",
|
||||
"/iot/tool/mqtt/auth","/iot/tool/mqtt/authv5","/iot/tool/mqtt/webhook","/iot/tool/mqtt/webhookv5","/auth/**/**",
|
||||
.antMatchers("/login", "/register", "/captchaImage", "/iot/tool/register", "/iot/tool/ntp",
|
||||
"/iot/tool/mqtt/auth", "/iot/tool/mqtt/authv5", "/iot/tool/mqtt/webhook", "/iot/tool/mqtt/webhookv5", "/auth/**/**",
|
||||
"/wechat/mobileLogin", "/wechat/miniLogin", "/wechat/wxBind/callback").permitAll()
|
||||
.antMatchers("/zlmhook/**").permitAll()
|
||||
//.antMatchers("/sip/player/getBigScreenUrl/**").permitAll()
|
||||
.antMatchers("/ruleengine/rulemanager/**").permitAll()
|
||||
.antMatchers("/goview/sys/login","/goview/project/getData").permitAll()
|
||||
.antMatchers("/notify/smsLoginCaptcha","/auth/sms/login", "/notify/weComVerifyUrl"
|
||||
,"/wechat/publicAccount/callback","/notify/smsRegisterCaptcha").permitAll()
|
||||
.antMatchers("/goview/sys/login", "/goview/project/getData").permitAll()
|
||||
.antMatchers("/notify/smsLoginCaptcha", "/auth/sms/login", "/notify/weComVerifyUrl"
|
||||
, "/wechat/publicAccount/callback", "/notify/smsRegisterCaptcha").permitAll()
|
||||
.antMatchers("/app/language/list").permitAll()
|
||||
.antMatchers("/iot/news/bannerList","/iot/news/topList", "/iot/news/getDetail").permitAll()
|
||||
.antMatchers("/iot/news/bannerList", "/iot/news/topList", "/iot/news/getDetail").permitAll()
|
||||
// 静态资源,可匿名访问
|
||||
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
|
||||
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
|
||||
@ -161,8 +158,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
* 强散列哈希加密实现
|
||||
*/
|
||||
@Bean
|
||||
public BCryptPasswordEncoder bCryptPasswordEncoder()
|
||||
{
|
||||
public BCryptPasswordEncoder bCryptPasswordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@ -170,8 +166,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
|
||||
* 身份认证接口
|
||||
*/
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception
|
||||
{
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,32 +1,30 @@
|
||||
package com.fastbee.framework.config;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.fastbee.common.utils.ServletUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 服务相关配置
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class ServerConfig
|
||||
{
|
||||
/**
|
||||
* 获取完整的请求路径,包括:域名,端口,上下文访问路径
|
||||
*
|
||||
* @return 服务地址
|
||||
*/
|
||||
public String getUrl()
|
||||
{
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
return getDomain(request);
|
||||
}
|
||||
|
||||
public static String getDomain(HttpServletRequest request)
|
||||
{
|
||||
public class ServerConfig {
|
||||
public static String getDomain(HttpServletRequest request) {
|
||||
StringBuffer url = request.getRequestURL();
|
||||
String contextPath = request.getServletContext().getContextPath();
|
||||
return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取完整的请求路径,包括:域名,端口,上下文访问路径
|
||||
*
|
||||
* @return 服务地址
|
||||
*/
|
||||
public String getUrl() {
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
return getDomain(request);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,16 +20,18 @@ import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 解决Mybatis Plus Order By SQL注入问题
|
||||
*
|
||||
* @author admin
|
||||
*/
|
||||
@Slf4j
|
||||
public class SqlFilterArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
private final static String[] KEYWORDS = { "master", "truncate", "insert", "select", "delete", "update", "declare",
|
||||
"alter", "drop", "sleep" };
|
||||
private final static String[] KEYWORDS = {"master", "truncate", "insert", "select", "delete", "update", "declare",
|
||||
"alter", "drop", "sleep"};
|
||||
|
||||
/**
|
||||
* 判断Controller是否包含page 参数
|
||||
*
|
||||
* @param parameter 参数
|
||||
* @return 是否过滤
|
||||
*/
|
||||
@ -39,9 +41,9 @@ public class SqlFilterArgumentResolver implements HandlerMethodArgumentResolver
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parameter 入参集合
|
||||
* @param mavContainer model 和 view
|
||||
* @param webRequest web相关
|
||||
* @param parameter 入参集合
|
||||
* @param mavContainer model 和 view
|
||||
* @param webRequest web相关
|
||||
* @param binderFactory 入参解析
|
||||
* @return 检查后新的page对象
|
||||
* <p>
|
||||
@ -77,6 +79,7 @@ public class SqlFilterArgumentResolver implements HandlerMethodArgumentResolver
|
||||
|
||||
/**
|
||||
* 判断用户输入里面有没有关键字
|
||||
*
|
||||
* @return Predicate
|
||||
*/
|
||||
private Predicate<String> sqlInjectPredicate() {
|
||||
|
||||
@ -5,6 +5,7 @@ import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
@ -15,8 +16,7 @@ import java.util.concurrent.ThreadPoolExecutor;
|
||||
* @author ruoyi
|
||||
**/
|
||||
@Configuration
|
||||
public class ThreadPoolConfig
|
||||
{
|
||||
public class ThreadPoolConfig {
|
||||
// 核心线程池大小
|
||||
private int corePoolSize = 50;
|
||||
|
||||
@ -30,8 +30,7 @@ public class ThreadPoolConfig
|
||||
private int keepAliveSeconds = 300;
|
||||
|
||||
@Bean(name = "threadPoolTaskExecutor")
|
||||
public ThreadPoolTaskExecutor threadPoolTaskExecutor()
|
||||
{
|
||||
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setMaxPoolSize(maxPoolSize);
|
||||
executor.setCorePoolSize(corePoolSize);
|
||||
@ -46,15 +45,12 @@ public class ThreadPoolConfig
|
||||
* 执行周期性或定时任务
|
||||
*/
|
||||
@Bean(name = "scheduledExecutorService")
|
||||
protected ScheduledExecutorService scheduledExecutorService()
|
||||
{
|
||||
protected ScheduledExecutorService scheduledExecutorService() {
|
||||
return new ScheduledThreadPoolExecutor(corePoolSize,
|
||||
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
|
||||
new ThreadPoolExecutor.CallerRunsPolicy())
|
||||
{
|
||||
new ThreadPoolExecutor.CallerRunsPolicy()) {
|
||||
@Override
|
||||
protected void afterExecute(Runnable r, Throwable t)
|
||||
{
|
||||
protected void afterExecute(Runnable r, Throwable t) {
|
||||
super.afterExecute(r, t);
|
||||
Threads.printException(r, t);
|
||||
}
|
||||
|
||||
@ -8,8 +8,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class DruidProperties
|
||||
{
|
||||
public class DruidProperties {
|
||||
// @Value("${spring.datasource.druid.initialSize}")
|
||||
// private int initialSize;
|
||||
//
|
||||
|
||||
@ -1,10 +1,6 @@
|
||||
package com.fastbee.framework.config.properties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
import com.fastbee.common.annotation.Anonymous;
|
||||
import org.apache.commons.lang3.RegExUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
@ -15,27 +11,27 @@ import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import com.fastbee.common.annotation.Anonymous;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 设置Anonymous注解允许匿名访问的url
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware
|
||||
{
|
||||
public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware {
|
||||
private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
|
||||
|
||||
public String ASTERISK = "*";
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private List<String> urls = new ArrayList<>();
|
||||
|
||||
public String ASTERISK = "*";
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet()
|
||||
{
|
||||
public void afterPropertiesSet() {
|
||||
RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
|
||||
Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
|
||||
|
||||
@ -55,18 +51,15 @@ public class PermitAllUrlProperties implements InitializingBean, ApplicationCont
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException
|
||||
{
|
||||
public void setApplicationContext(ApplicationContext context) throws BeansException {
|
||||
this.applicationContext = context;
|
||||
}
|
||||
|
||||
public List<String> getUrls()
|
||||
{
|
||||
public List<String> getUrls() {
|
||||
return urls;
|
||||
}
|
||||
|
||||
public void setUrls(List<String> urls)
|
||||
{
|
||||
public void setUrls(List<String> urls) {
|
||||
this.urls = urls;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Redisson 配置属性
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "redisson")
|
||||
|
||||
@ -21,15 +21,18 @@ import java.util.stream.Collectors;
|
||||
/**
|
||||
* <p> @Title ShardingAlgorithmTool
|
||||
* <p> @Description 按月分片算法工具
|
||||
*
|
||||
*/
|
||||
@Slf4j
|
||||
public class ShardingAlgorithmTool {
|
||||
|
||||
/** 表分片符号,例:siot_device_log_202201 中,分片符号为 "_" */
|
||||
/**
|
||||
* 表分片符号,例:siot_device_log_202201 中,分片符号为 "_"
|
||||
*/
|
||||
private static final String TABLE_SPLIT_SYMBOL = "_";
|
||||
|
||||
/** 数据库配置 */
|
||||
/**
|
||||
* 数据库配置
|
||||
*/
|
||||
private static final Environment ENV = SpringUtil.getApplicationContext().getEnvironment();
|
||||
private static final String DATASOURCE_URL = ENV.getProperty("spring.shardingsphere.datasource.ds0.url");
|
||||
private static final String DATASOURCE_USERNAME = ENV.getProperty("spring.shardingsphere.datasource.ds0.username");
|
||||
@ -38,7 +41,8 @@ public class ShardingAlgorithmTool {
|
||||
|
||||
/**
|
||||
* 检查分表获取的表名是否存在,不存在则自动建表
|
||||
* @param logicTable 逻辑表
|
||||
*
|
||||
* @param logicTable 逻辑表
|
||||
* @param resultTableNames 真实表名,例:iot_device_log_202201
|
||||
* @return 存在于数据库中的真实表名集合
|
||||
*/
|
||||
@ -48,7 +52,8 @@ public class ShardingAlgorithmTool {
|
||||
|
||||
/**
|
||||
* 检查分表获取的表名是否存在,不存在则自动建表
|
||||
* @param logicTable 逻辑表
|
||||
*
|
||||
* @param logicTable 逻辑表
|
||||
* @param resultTableName 真实表名,例:iot_device_log_202201
|
||||
* @return 确认存在于数据库中的真实表名
|
||||
*/
|
||||
@ -72,6 +77,7 @@ public class ShardingAlgorithmTool {
|
||||
|
||||
/**
|
||||
* 重载指定分表缓存
|
||||
*
|
||||
* @param logicTable 逻辑表
|
||||
*/
|
||||
public static void tableNameCacheReload(ShardingTableCacheEnum logicTable) {
|
||||
@ -89,8 +95,9 @@ public class ShardingAlgorithmTool {
|
||||
|
||||
/**
|
||||
* 获取所有表名
|
||||
* @return 表名集合
|
||||
*
|
||||
* @param logicTable 逻辑表
|
||||
* @return 表名集合
|
||||
*/
|
||||
public static List<String> getAllTableNameBySchema(ShardingTableCacheEnum logicTable) {
|
||||
List<String> tableNames = new ArrayList<>();
|
||||
@ -102,10 +109,10 @@ public class ShardingAlgorithmTool {
|
||||
Statement st = conn.createStatement()) {
|
||||
String logicTableName = logicTable.logicTableName();
|
||||
try (ResultSet rs = st.executeQuery("show TABLES like '" + logicTableName + TABLE_SPLIT_SYMBOL + "%'")) {
|
||||
log.info("查询数据库所有表:{}","show TABLES like '" + logicTableName + TABLE_SPLIT_SYMBOL + "%'");
|
||||
log.info("查询数据库所有表:{}", "show TABLES like '" + logicTableName + TABLE_SPLIT_SYMBOL + "%'");
|
||||
while (rs.next()) {
|
||||
String tableName = rs.getString(1);
|
||||
log.info("分表格式:{}",String.format("^(%s\\d{6})$", logicTableName + TABLE_SPLIT_SYMBOL));
|
||||
log.info("分表格式:{}", String.format("^(%s\\d{6})$", logicTableName + TABLE_SPLIT_SYMBOL));
|
||||
// 匹配分表格式 例:^(t\_contract_\d{6})$
|
||||
if (org.apache.commons.lang3.StringUtils.isNotBlank(tableName) && tableName.matches(String.format("^(%s\\d{6})$", logicTableName + TABLE_SPLIT_SYMBOL))) {
|
||||
tableNames.add(rs.getString(1));
|
||||
@ -125,7 +132,7 @@ public class ShardingAlgorithmTool {
|
||||
* @param logicTableName 逻辑表名
|
||||
* @param tableNamesCache 真实表名集合
|
||||
*/
|
||||
public static void actualDataNodesRefresh(String logicTableName, List<String> tableNamesCache) {
|
||||
public static void actualDataNodesRefresh(String logicTableName, List<String> tableNamesCache) {
|
||||
try {
|
||||
if (CollectionUtils.isEmpty(tableNamesCache)) {
|
||||
return;
|
||||
@ -138,7 +145,7 @@ public class ShardingAlgorithmTool {
|
||||
String newActualDataNodes = tableNamesCache.stream().map(o -> String.format("%s.%s", dbName, o)).collect(Collectors.joining(","));
|
||||
ShardingSphereDataSource shardingSphereDataSource = SpringUtil.getBean(ShardingSphereDataSource.class);
|
||||
updateShardRuleActualDataNodes(shardingSphereDataSource, logicTableName, newActualDataNodes);
|
||||
}catch (Exception e){
|
||||
} catch (Exception e) {
|
||||
log.error("初始化 动态表单失败,原因:{}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
@ -209,13 +216,14 @@ public class ShardingAlgorithmTool {
|
||||
|
||||
/**
|
||||
* 创建分表
|
||||
* @param logicTable 逻辑表
|
||||
*
|
||||
* @param logicTable 逻辑表
|
||||
* @param resultTableName 真实表名,例:sys_user_behavior_202201
|
||||
* @return 创建结果(true创建成功,false未创建)
|
||||
*/
|
||||
private static boolean createShardingTable(ShardingTableCacheEnum logicTable, String resultTableName) {
|
||||
// 根据日期判断,当前月份之后分表不提前创建
|
||||
String month = resultTableName.replace(logicTable.logicTableName() + TABLE_SPLIT_SYMBOL,"");
|
||||
String month = resultTableName.replace(logicTable.logicTableName() + TABLE_SPLIT_SYMBOL, "");
|
||||
YearMonth shardingMonth = YearMonth.parse(month, DateTimeFormatter.ofPattern("yyyyMM"));
|
||||
if (shardingMonth.isAfter(YearMonth.now())) {
|
||||
return false;
|
||||
@ -236,6 +244,7 @@ public class ShardingAlgorithmTool {
|
||||
|
||||
/**
|
||||
* 执行SQL
|
||||
*
|
||||
* @param sqlList SQL集合
|
||||
*/
|
||||
private static void executeSql(List<String> sqlList) {
|
||||
|
||||
@ -7,7 +7,6 @@ import org.springframework.stereotype.Component;
|
||||
/**
|
||||
* <p> @Title ShardingTablesLoadRunner
|
||||
* <p> @Description 项目启动后,读取已有分表,进行缓存
|
||||
*
|
||||
*/
|
||||
@Order(value = 1) // 数字越小,越先执行
|
||||
@Component
|
||||
|
||||
@ -20,7 +20,6 @@ import java.util.function.Function;
|
||||
/**
|
||||
* <p> @Title TimeShardingAlgorithm
|
||||
* <p> @Description 分片算法,按月分片
|
||||
*
|
||||
*/
|
||||
@Slf4j
|
||||
public class TimeShardingAlgorithm implements StandardShardingAlgorithm<Date> {
|
||||
@ -51,7 +50,8 @@ public class TimeShardingAlgorithm implements StandardShardingAlgorithm<Date> {
|
||||
|
||||
/**
|
||||
* 精准分片
|
||||
* @param tableNames 对应分片库中所有分片表的集合
|
||||
*
|
||||
* @param tableNames 对应分片库中所有分片表的集合
|
||||
* @param preciseShardingValue 分片键值,其中 logicTableName 为逻辑表,columnName 分片键,value 为从 SQL 中解析出来的分片键的值
|
||||
* @return 表名
|
||||
*/
|
||||
@ -69,7 +69,7 @@ public class TimeShardingAlgorithm implements StandardShardingAlgorithm<Date> {
|
||||
LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||
String resultTableName = logicTableName + "_" + TABLE_SHARD_TIME_FORMATTER.format(localDateTime);
|
||||
// 检查分表获取的表名是否存在,不存在则自动建表
|
||||
if (!tableNames.contains(resultTableName)){
|
||||
if (!tableNames.contains(resultTableName)) {
|
||||
tableNames.add(resultTableName);
|
||||
}
|
||||
return ShardingAlgorithmTool.getShardingTableAndCreate(logicTable, resultTableName);
|
||||
@ -77,13 +77,14 @@ public class TimeShardingAlgorithm implements StandardShardingAlgorithm<Date> {
|
||||
|
||||
/**
|
||||
* 范围分片
|
||||
* @param tableNames 对应分片库中所有分片表的集合
|
||||
*
|
||||
* @param tableNames 对应分片库中所有分片表的集合
|
||||
* @param rangeShardingValue 分片范围
|
||||
* @return 表名集合
|
||||
*/
|
||||
@Override
|
||||
public Collection<String> doSharding(Collection<String> tableNames, RangeShardingValue<Date> rangeShardingValue) {
|
||||
log.info("开始分表查询开始:{}",System.currentTimeMillis());
|
||||
log.info("开始分表查询开始:{}", System.currentTimeMillis());
|
||||
String logicTableName = rangeShardingValue.getLogicTableName();
|
||||
ShardingTableCacheEnum logicTable = ShardingTableCacheEnum.of(logicTableName);
|
||||
createAllTable(logicTable, tableNames);
|
||||
@ -113,7 +114,7 @@ public class TimeShardingAlgorithm implements StandardShardingAlgorithm<Date> {
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1); // 给日期加一天
|
||||
minDate = calendar.getTime();
|
||||
}
|
||||
log.info("开始分表查询结束:{}",System.currentTimeMillis());
|
||||
log.info("开始分表查询结束:{}", System.currentTimeMillis());
|
||||
return ShardingAlgorithmTool.getShardingTablesAndCreate(logicTable, resultTableNames);
|
||||
} catch (Exception e) {
|
||||
return ShardingAlgorithmTool.getShardingTablesAndCreate(logicTable, logicTable.resultTableNamesCache());
|
||||
@ -137,6 +138,7 @@ public class TimeShardingAlgorithm implements StandardShardingAlgorithm<Date> {
|
||||
|
||||
/**
|
||||
* 获取 最小分片值
|
||||
*
|
||||
* @param tableNames 表名集合
|
||||
* @return 最小分片值
|
||||
*/
|
||||
@ -156,6 +158,7 @@ public class TimeShardingAlgorithm implements StandardShardingAlgorithm<Date> {
|
||||
|
||||
/**
|
||||
* 获取 最大分片值
|
||||
*
|
||||
* @param tableNames 表名集合
|
||||
* @return 最大分片值
|
||||
*/
|
||||
@ -175,6 +178,7 @@ public class TimeShardingAlgorithm implements StandardShardingAlgorithm<Date> {
|
||||
|
||||
/**
|
||||
* 根据分片规则获取的表,创建所有的表
|
||||
*
|
||||
* @param logicTable
|
||||
* @param tableNames
|
||||
*/
|
||||
@ -184,7 +188,7 @@ public class TimeShardingAlgorithm implements StandardShardingAlgorithm<Date> {
|
||||
return;
|
||||
}
|
||||
//根据分片规则创建表
|
||||
ShardingAlgorithmTool.getShardingTablesAndCreate(logicTable,tableNames);
|
||||
ShardingAlgorithmTool.getShardingTablesAndCreate(logicTable, tableNames);
|
||||
//刷新缓存
|
||||
ShardingAlgorithmTool.tableNameCacheReload(logicTable);
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.fastbee.framework.config.sharding.enums;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.fastbee.framework.config.sharding.ShardingAlgorithmTool.actualDataNodesRefresh;
|
||||
@ -9,7 +10,6 @@ import static com.fastbee.framework.config.sharding.ShardingAlgorithmTool.actual
|
||||
/**
|
||||
* <p> @Title ShardingTableCacheEnum
|
||||
* <p> @Description 分片表缓存枚举
|
||||
*
|
||||
*/
|
||||
public enum ShardingTableCacheEnum {
|
||||
|
||||
@ -18,6 +18,12 @@ public enum ShardingTableCacheEnum {
|
||||
*/
|
||||
DEVICE_LOG("iot_device_log", new HashSet<>());
|
||||
|
||||
private static Map<String, ShardingTableCacheEnum> valueMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
Arrays.stream(ShardingTableCacheEnum.values()).forEach(o -> valueMap.put(o.logicTableName, o));
|
||||
}
|
||||
|
||||
/**
|
||||
* 逻辑表名
|
||||
*/
|
||||
@ -27,12 +33,6 @@ public enum ShardingTableCacheEnum {
|
||||
*/
|
||||
private final Set<String> resultTableNamesCache;
|
||||
|
||||
private static Map<String, ShardingTableCacheEnum> valueMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
Arrays.stream(ShardingTableCacheEnum.values()).forEach(o -> valueMap.put(o.logicTableName, o));
|
||||
}
|
||||
|
||||
ShardingTableCacheEnum(String logicTableName, Set<String> resultTableNamesCache) {
|
||||
this.logicTableName = logicTableName;
|
||||
this.resultTableNamesCache = resultTableNamesCache;
|
||||
@ -42,6 +42,10 @@ public enum ShardingTableCacheEnum {
|
||||
return valueMap.get(value);
|
||||
}
|
||||
|
||||
public static Set<String> logicTableNames() {
|
||||
return valueMap.keySet();
|
||||
}
|
||||
|
||||
public String logicTableName() {
|
||||
return logicTableName;
|
||||
}
|
||||
@ -69,10 +73,6 @@ public enum ShardingTableCacheEnum {
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> logicTableNames() {
|
||||
return valueMap.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ShardingTableCacheEnum{" +
|
||||
|
||||
@ -12,18 +12,15 @@ import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Slf4j
|
||||
public class DynamicDataSource extends AbstractRoutingDataSource
|
||||
{
|
||||
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources)
|
||||
{
|
||||
public class DynamicDataSource extends AbstractRoutingDataSource {
|
||||
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
|
||||
super.setDefaultTargetDataSource(defaultTargetDataSource);
|
||||
super.setTargetDataSources(targetDataSources);
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object determineCurrentLookupKey()
|
||||
{
|
||||
protected Object determineCurrentLookupKey() {
|
||||
//log.debug("数据源:" + DynamicDataSourceContextHolder.getDataSourceType());
|
||||
return DynamicDataSourceContextHolder.getDataSourceType();
|
||||
}
|
||||
|
||||
@ -5,41 +5,37 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 数据源切换处理
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class DynamicDataSourceContextHolder
|
||||
{
|
||||
public class DynamicDataSourceContextHolder {
|
||||
public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
|
||||
|
||||
/**
|
||||
* 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
|
||||
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
|
||||
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
|
||||
*/
|
||||
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* 获得数据源的变量
|
||||
*/
|
||||
public static String getDataSourceType() {
|
||||
return CONTEXT_HOLDER.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置数据源的变量
|
||||
*/
|
||||
public static void setDataSourceType(String dsType)
|
||||
{
|
||||
public static void setDataSourceType(String dsType) {
|
||||
log.info("切换到{}数据源", dsType);
|
||||
CONTEXT_HOLDER.set(dsType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得数据源的变量
|
||||
*/
|
||||
public static String getDataSourceType()
|
||||
{
|
||||
return CONTEXT_HOLDER.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空数据源变量
|
||||
*/
|
||||
public static void clearDataSourceType()
|
||||
{
|
||||
public static void clearDataSourceType() {
|
||||
CONTEXT_HOLDER.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,14 +27,14 @@ public class LanguageInterceptor implements HandlerInterceptor {
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
String language = request.getHeader(LANGUAGE);
|
||||
if (StringUtils.isEmpty(language) || language.equals("undefined")
|
||||
|| language.equals("")|| language.equals("null")){
|
||||
|| language.equals("") || language.equals("null")) {
|
||||
//针对有些接口没有增加语言字段,先去token获取
|
||||
language = SecurityUtils.getLanguage();
|
||||
}else if (!language.contains("-")){
|
||||
language = Language.matches(language);
|
||||
} else if (!language.contains("-")) {
|
||||
language = Language.matches(language);
|
||||
}
|
||||
// 前端传递的language必须是zh-CN格式的,中间的-必须要完整,不能只传递zh或en
|
||||
Locale locale = new Locale(language.split("-")[0],language.split("-")[1]);
|
||||
Locale locale = new Locale(language.split("-")[0], language.split("-")[1]);
|
||||
// 这样赋值以后,MessageUtils.message方法就不用修改了
|
||||
LocaleContextHolder.setLocale(locale);
|
||||
return true;
|
||||
|
||||
@ -3,6 +3,7 @@ package com.fastbee.framework.interceptor;
|
||||
import java.lang.reflect.Method;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
@ -17,29 +18,22 @@ import com.fastbee.common.utils.ServletUtils;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public abstract class RepeatSubmitInterceptor implements HandlerInterceptor
|
||||
{
|
||||
public abstract class RepeatSubmitInterceptor implements HandlerInterceptor {
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
|
||||
{
|
||||
if (handler instanceof HandlerMethod)
|
||||
{
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
Method method = handlerMethod.getMethod();
|
||||
RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
|
||||
if (annotation != null)
|
||||
{
|
||||
if (this.isRepeatSubmit(request, annotation))
|
||||
{
|
||||
if (annotation != null) {
|
||||
if (this.isRepeatSubmit(request, annotation)) {
|
||||
AjaxResult ajaxResult = AjaxResult.error(annotation.message());
|
||||
ServletUtils.renderString(response, JSON.toJSONString(ajaxResult));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,10 +20,10 @@ public class TraceIdInterceptor implements HandlerInterceptor {
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
// 获取请求URI
|
||||
String requestURI = request.getRequestURI();
|
||||
|
||||
|
||||
// 尝试从请求头中获取TraceId(支持分布式追踪)
|
||||
String traceId = request.getHeader("X-Trace-Id");
|
||||
|
||||
|
||||
// 如果请求头中没有TraceId,则生成一个新的
|
||||
if (traceId == null || traceId.isEmpty()) {
|
||||
traceId = TraceIdUtils.generateTraceIdString();
|
||||
@ -31,14 +31,14 @@ public class TraceIdInterceptor implements HandlerInterceptor {
|
||||
// 如果请求头中有TraceId,设置到MDC
|
||||
TraceIdUtils.setTraceId(traceId);
|
||||
}
|
||||
|
||||
|
||||
// 将TraceId放入响应头,方便前端获取
|
||||
response.setHeader("X-Trace-Id", traceId);
|
||||
|
||||
|
||||
// 打印请求路径日志
|
||||
org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TraceIdInterceptor.class);
|
||||
log.info("拦截请求路径: {}", requestURI);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -19,12 +20,11 @@ import com.fastbee.framework.interceptor.RepeatSubmitInterceptor;
|
||||
/**
|
||||
* 判断请求url和数据是否和上一次相同,
|
||||
* 如果和上次相同,则是重复提交表单。 有效时间为10秒内。
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
|
||||
{
|
||||
public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
|
||||
public final String REPEAT_PARAMS = "repeatParams";
|
||||
|
||||
public final String REPEAT_TIME = "repeatTime";
|
||||
@ -38,18 +38,15 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation)
|
||||
{
|
||||
public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) {
|
||||
String nowParams = "";
|
||||
if (request instanceof RepeatedlyRequestWrapper)
|
||||
{
|
||||
if (request instanceof RepeatedlyRequestWrapper) {
|
||||
RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
|
||||
nowParams = HttpHelper.getBodyString(repeatedlyRequest);
|
||||
}
|
||||
|
||||
// body参数为空,获取Parameter的数据
|
||||
if (StringUtils.isEmpty(nowParams))
|
||||
{
|
||||
if (StringUtils.isEmpty(nowParams)) {
|
||||
nowParams = JSON.toJSONString(request.getParameterMap());
|
||||
}
|
||||
Map<String, Object> nowDataMap = new HashMap<String, Object>();
|
||||
@ -66,14 +63,11 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
|
||||
String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey;
|
||||
|
||||
Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
|
||||
if (sessionObj != null)
|
||||
{
|
||||
if (sessionObj != null) {
|
||||
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
|
||||
if (sessionMap.containsKey(url))
|
||||
{
|
||||
if (sessionMap.containsKey(url)) {
|
||||
Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
|
||||
if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval()))
|
||||
{
|
||||
if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -87,8 +81,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
|
||||
/**
|
||||
* 判断参数是否相同
|
||||
*/
|
||||
private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap)
|
||||
{
|
||||
private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap) {
|
||||
String nowParams = (String) nowMap.get(REPEAT_PARAMS);
|
||||
String preParams = (String) preMap.get(REPEAT_PARAMS);
|
||||
return nowParams.equals(preParams);
|
||||
@ -97,12 +90,10 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
|
||||
/**
|
||||
* 判断两次间隔时间
|
||||
*/
|
||||
private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval)
|
||||
{
|
||||
private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval) {
|
||||
long time1 = (Long) nowMap.get(REPEAT_TIME);
|
||||
long time2 = (Long) preMap.get(REPEAT_TIME);
|
||||
if ((time1 - time2) < interval)
|
||||
{
|
||||
if ((time1 - time2) < interval) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
package com.fastbee.framework.manager;
|
||||
|
||||
import com.fastbee.common.utils.Threads;
|
||||
import com.fastbee.common.utils.spring.SpringUtils;
|
||||
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import com.fastbee.common.utils.Threads;
|
||||
import com.fastbee.common.utils.spring.SpringUtils;
|
||||
|
||||
/**
|
||||
* 异步任务管理器
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class AsyncManager
|
||||
{
|
||||
public class AsyncManager {
|
||||
private static AsyncManager me = new AsyncManager();
|
||||
/**
|
||||
* 操作延迟10毫秒
|
||||
*/
|
||||
private final int OPERATE_DELAY_TIME = 10;
|
||||
|
||||
/**
|
||||
* 异步操作任务调度线程池
|
||||
*/
|
||||
@ -26,30 +26,26 @@ public class AsyncManager
|
||||
/**
|
||||
* 单例模式
|
||||
*/
|
||||
private AsyncManager(){}
|
||||
private AsyncManager() {
|
||||
}
|
||||
|
||||
private static AsyncManager me = new AsyncManager();
|
||||
|
||||
public static AsyncManager me()
|
||||
{
|
||||
public static AsyncManager me() {
|
||||
return me;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行任务
|
||||
*
|
||||
*
|
||||
* @param task 任务
|
||||
*/
|
||||
public void execute(TimerTask task)
|
||||
{
|
||||
public void execute(TimerTask task) {
|
||||
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止任务线程池
|
||||
*/
|
||||
public void shutdown()
|
||||
{
|
||||
public void shutdown() {
|
||||
Threads.shutdownAndAwaitTermination(executor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,16 +2,16 @@ package com.fastbee.framework.manager;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import com.fastbee.common.utils.spring.SpringUtils;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Cache 装饰器模式(用于扩展 Caffeine 一级缓存)
|
||||
*
|
||||
*/
|
||||
public class CaffeineCacheDecorator implements Cache {
|
||||
|
||||
private static final com.github.benmanes.caffeine.cache.Cache<Object, Object>
|
||||
CAFFEINE = SpringUtils.getBean("caffeine");
|
||||
CAFFEINE = SpringUtils.getBean("caffeine");
|
||||
|
||||
private final Cache cache;
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ package com.fastbee.framework.manager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
/**
|
||||
@ -11,28 +12,22 @@ import javax.annotation.PreDestroy;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class ShutdownManager
|
||||
{
|
||||
public class ShutdownManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger("sys-user");
|
||||
|
||||
@PreDestroy
|
||||
public void destroy()
|
||||
{
|
||||
public void destroy() {
|
||||
shutdownAsyncManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止异步执行任务
|
||||
*/
|
||||
private void shutdownAsyncManager()
|
||||
{
|
||||
try
|
||||
{
|
||||
private void shutdownAsyncManager() {
|
||||
try {
|
||||
logger.info("====关闭后台任务任务线程池====");
|
||||
AsyncManager.me().shutdown();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,22 +23,16 @@ import java.util.concurrent.ConcurrentMap;
|
||||
* <p>
|
||||
* 修改 RedissonSpringCacheManager 源码
|
||||
* 重写 cacheName 处理方法 支持多参数
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class SpringCacheManager implements CacheManager {
|
||||
|
||||
private boolean dynamic = true;
|
||||
|
||||
private boolean allowNullValues = true;
|
||||
|
||||
private boolean transactionAware = true;
|
||||
|
||||
private Long ttl;
|
||||
|
||||
Map<String, CacheConfig> configMap = new ConcurrentHashMap<>();
|
||||
ConcurrentMap<String, Cache> instanceMap = new ConcurrentHashMap<>();
|
||||
private boolean dynamic = true;
|
||||
private boolean allowNullValues = true;
|
||||
private boolean transactionAware = true;
|
||||
private Long ttl;
|
||||
|
||||
/**
|
||||
* Creates CacheManager supplied by Redisson instance
|
||||
@ -74,25 +68,6 @@ public class SpringCacheManager implements CacheManager {
|
||||
this.transactionAware = transactionAware;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines 'fixed' cache names.
|
||||
* A new cache instance will not be created in dynamic for non-defined names.
|
||||
* <p>
|
||||
* `null` parameter setups dynamic mode
|
||||
*
|
||||
* @param names of caches
|
||||
*/
|
||||
public void setCacheNames(Collection<String> names) {
|
||||
if (names != null) {
|
||||
for (String name : names) {
|
||||
getCache(name);
|
||||
}
|
||||
dynamic = false;
|
||||
} else {
|
||||
dynamic = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cache config mapped by cache name
|
||||
*
|
||||
@ -182,5 +157,24 @@ public class SpringCacheManager implements CacheManager {
|
||||
return Collections.unmodifiableSet(configMap.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines 'fixed' cache names.
|
||||
* A new cache instance will not be created in dynamic for non-defined names.
|
||||
* <p>
|
||||
* `null` parameter setups dynamic mode
|
||||
*
|
||||
* @param names of caches
|
||||
*/
|
||||
public void setCacheNames(Collection<String> names) {
|
||||
if (names != null) {
|
||||
for (String name : names) {
|
||||
getCache(name);
|
||||
}
|
||||
dynamic = false;
|
||||
} else {
|
||||
dynamic = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
package com.fastbee.framework.manager.factory;
|
||||
|
||||
import java.util.TimerTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.fastbee.common.constant.Constants;
|
||||
import com.fastbee.common.utils.LogUtils;
|
||||
import com.fastbee.common.utils.ServletUtils;
|
||||
@ -15,35 +12,35 @@ import com.fastbee.system.domain.SysOperLog;
|
||||
import com.fastbee.system.service.ISysLogininforService;
|
||||
import com.fastbee.system.service.ISysOperLogService;
|
||||
import eu.bitwalker.useragentutils.UserAgent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* 异步工厂(产生任务用)
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class AsyncFactory
|
||||
{
|
||||
public class AsyncFactory {
|
||||
private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
|
||||
|
||||
/**
|
||||
* 记录登录信息
|
||||
*
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param status 状态
|
||||
* @param message 消息
|
||||
* @param args 列表
|
||||
* @param status 状态
|
||||
* @param message 消息
|
||||
* @param args 列表
|
||||
* @return 任务task
|
||||
*/
|
||||
public static TimerTask recordLogininfor(final String username, final String status, final String message,
|
||||
final Object... args)
|
||||
{
|
||||
final Object... args) {
|
||||
final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||
final String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
|
||||
return new TimerTask()
|
||||
{
|
||||
return new TimerTask() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
public void run() {
|
||||
String address = AddressUtils.getRealAddressByIP(ip);
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append(LogUtils.getBlock(ip));
|
||||
@ -66,12 +63,9 @@ public class AsyncFactory
|
||||
logininfor.setOs(os);
|
||||
logininfor.setMsg(message);
|
||||
// 日志状态
|
||||
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
|
||||
{
|
||||
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
|
||||
logininfor.setStatus(Constants.SUCCESS);
|
||||
}
|
||||
else if (Constants.LOGIN_FAIL.equals(status))
|
||||
{
|
||||
} else if (Constants.LOGIN_FAIL.equals(status)) {
|
||||
logininfor.setStatus(Constants.FAIL);
|
||||
}
|
||||
// 插入数据
|
||||
@ -82,17 +76,14 @@ public class AsyncFactory
|
||||
|
||||
/**
|
||||
* 操作日志记录
|
||||
*
|
||||
*
|
||||
* @param operLog 操作日志信息
|
||||
* @return 任务task
|
||||
*/
|
||||
public static TimerTask recordOper(final SysOperLog operLog)
|
||||
{
|
||||
return new TimerTask()
|
||||
{
|
||||
public static TimerTask recordOper(final SysOperLog operLog) {
|
||||
return new TimerTask() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
public void run() {
|
||||
// 远程查询操作地点
|
||||
operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
|
||||
SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
|
||||
|
||||
@ -9,7 +9,7 @@ import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 拓展 MyBatis Plus QueryWrapper 类,主要增加如下功能:
|
||||
*
|
||||
* <p>
|
||||
* 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。
|
||||
*
|
||||
* @param <T> 数据类型
|
||||
@ -93,13 +93,13 @@ public class QueryWrapperX<T> extends QueryWrapper<T> {
|
||||
}
|
||||
|
||||
public QueryWrapperX<T> betweenIfPresent(String column, Object[] values) {
|
||||
if (values!= null && values.length != 0 && values[0] != null && values[1] != null) {
|
||||
if (values != null && values.length != 0 && values[0] != null && values[1] != null) {
|
||||
return (QueryWrapperX<T>) super.between(column, values[0], values[1]);
|
||||
}
|
||||
if (values!= null && values.length != 0 && values[0] != null) {
|
||||
if (values != null && values.length != 0 && values[0] != null) {
|
||||
return (QueryWrapperX<T>) ge(column, values[0]);
|
||||
}
|
||||
if (values!= null && values.length != 0 && values[1] != null) {
|
||||
if (values != null && values.length != 0 && values[1] != null) {
|
||||
return (QueryWrapperX<T>) le(column, values[1]);
|
||||
}
|
||||
return this;
|
||||
|
||||
@ -24,6 +24,7 @@ public class MybatisPlusConfig implements WebMvcConfigurer {
|
||||
|
||||
/**
|
||||
* SQL 过滤器避免SQL 注入
|
||||
*
|
||||
* @param argumentResolvers
|
||||
*/
|
||||
@Override
|
||||
@ -49,8 +50,10 @@ public class MybatisPlusConfig implements WebMvcConfigurer {
|
||||
public IdentifierGenerator idGenerator() {
|
||||
return new DefaultIdentifierGenerator(NetUtil.getLocalhost());
|
||||
}
|
||||
|
||||
/**
|
||||
* 审计字段自动填充
|
||||
*
|
||||
* @return {@link MybatisPlusMetaObjectHandler}
|
||||
*/
|
||||
@Bean
|
||||
|
||||
@ -19,6 +19,32 @@ import java.util.Date;
|
||||
@Slf4j
|
||||
public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
/**
|
||||
* 填充值,先判断是否有手动设置,优先手动设置的值,例如:job必须手动设置
|
||||
*
|
||||
* @param fieldName 属性名
|
||||
* @param fieldVal 属性值
|
||||
* @param metaObject MetaObject
|
||||
* @param isCover 是否覆盖原有值,避免更新操作手动入参
|
||||
*/
|
||||
private static void fillValIfNullByName(String fieldName, Object fieldVal, MetaObject metaObject, boolean isCover) {
|
||||
// 1. 没有 get 方法
|
||||
if (!metaObject.hasSetter(fieldName)) {
|
||||
return;
|
||||
}
|
||||
// 2. 如果用户有手动设置的值
|
||||
Object userSetValue = metaObject.getValue(fieldName);
|
||||
String setValueStr = StrUtil.str(userSetValue, Charset.defaultCharset());
|
||||
if (StrUtil.isNotBlank(setValueStr) && !isCover) {
|
||||
return;
|
||||
}
|
||||
// 3. field 类型相同时设置
|
||||
Class<?> getterType = metaObject.getGetterType(fieldName);
|
||||
if (ClassUtils.isAssignableValue(getterType, fieldVal)) {
|
||||
metaObject.setValue(fieldName, fieldVal);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
log.debug("mybatisPlus插入填充--------------");
|
||||
@ -38,33 +64,9 @@ public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
|
||||
fillValIfNullByName("updateBy", getUserName(), metaObject, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充值,先判断是否有手动设置,优先手动设置的值,例如:job必须手动设置
|
||||
* @param fieldName 属性名
|
||||
* @param fieldVal 属性值
|
||||
* @param metaObject MetaObject
|
||||
* @param isCover 是否覆盖原有值,避免更新操作手动入参
|
||||
*/
|
||||
private static void fillValIfNullByName(String fieldName, Object fieldVal, MetaObject metaObject, boolean isCover) {
|
||||
// 1. 没有 get 方法
|
||||
if (!metaObject.hasSetter(fieldName)) {
|
||||
return;
|
||||
}
|
||||
// 2. 如果用户有手动设置的值
|
||||
Object userSetValue = metaObject.getValue(fieldName);
|
||||
String setValueStr = StrUtil.str(userSetValue, Charset.defaultCharset());
|
||||
if (StrUtil.isNotBlank(setValueStr) && !isCover) {
|
||||
return;
|
||||
}
|
||||
// 3. field 类型相同时设置
|
||||
Class<?> getterType = metaObject.getGetterType(fieldName);
|
||||
if (ClassUtils.isAssignableValue(getterType, fieldVal)) {
|
||||
metaObject.setValue(fieldName, fieldVal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 spring security 当前的用户名
|
||||
*
|
||||
* @return 当前用户名
|
||||
*/
|
||||
private String getUserName() {
|
||||
|
||||
@ -34,7 +34,7 @@ public class MyBatisUtils {
|
||||
// 排序字段
|
||||
if (!CollectionUtil.isEmpty(sortingFields)) {
|
||||
page.addOrder(sortingFields.stream().map(sortingField -> SortingField.ORDER_ASC.equals(sortingField.getOrder()) ?
|
||||
OrderItem.asc(sortingField.getField()) : OrderItem.desc(sortingField.getField()))
|
||||
OrderItem.asc(sortingField.getField()) : OrderItem.desc(sortingField.getField()))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
return page;
|
||||
@ -45,8 +45,8 @@ public class MyBatisUtils {
|
||||
* 由于 MybatisPlusInterceptor 不支持添加拦截器,所以只能全量设置
|
||||
*
|
||||
* @param interceptor 链
|
||||
* @param inner 拦截器
|
||||
* @param index 位置
|
||||
* @param inner 拦截器
|
||||
* @param index 位置
|
||||
*/
|
||||
public static void addInterceptor(MybatisPlusInterceptor interceptor, InnerInterceptor inner, int index) {
|
||||
List<InnerInterceptor> inners = new ArrayList<>(interceptor.getInterceptors());
|
||||
@ -56,7 +56,7 @@ public class MyBatisUtils {
|
||||
|
||||
/**
|
||||
* 获得 Table 对应的表名
|
||||
*
|
||||
* <p>
|
||||
* 兼容 MySQL 转义表名 `t_xxx`
|
||||
*
|
||||
* @param table 表
|
||||
@ -73,9 +73,9 @@ public class MyBatisUtils {
|
||||
/**
|
||||
* 构建 Column 对象
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @param tableName 表名
|
||||
* @param tableAlias 别名
|
||||
* @param column 字段名
|
||||
* @param column 字段名
|
||||
* @return Column 对象
|
||||
*/
|
||||
public static Column buildColumn(String tableName, Alias tableAlias, String column) {
|
||||
|
||||
@ -4,25 +4,21 @@ import org.springframework.security.core.Authentication;
|
||||
|
||||
/**
|
||||
* 身份验证信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class AuthenticationContextHolder
|
||||
{
|
||||
public class AuthenticationContextHolder {
|
||||
private static final ThreadLocal<Authentication> contextHolder = new ThreadLocal<>();
|
||||
|
||||
public static Authentication getContext()
|
||||
{
|
||||
public static Authentication getContext() {
|
||||
return contextHolder.get();
|
||||
}
|
||||
|
||||
public static void setContext(Authentication context)
|
||||
{
|
||||
public static void setContext(Authentication context) {
|
||||
contextHolder.set(context);
|
||||
}
|
||||
|
||||
public static void clearContext()
|
||||
{
|
||||
public static void clearContext() {
|
||||
contextHolder.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,22 +6,19 @@ import com.fastbee.common.core.text.Convert;
|
||||
|
||||
/**
|
||||
* 权限信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class PermissionContextHolder
|
||||
{
|
||||
public class PermissionContextHolder {
|
||||
private static final String PERMISSION_CONTEXT_ATTRIBUTES = "PERMISSION_CONTEXT";
|
||||
|
||||
public static void setContext(String permission)
|
||||
{
|
||||
RequestContextHolder.currentRequestAttributes().setAttribute(PERMISSION_CONTEXT_ATTRIBUTES, permission,
|
||||
RequestAttributes.SCOPE_REQUEST);
|
||||
}
|
||||
|
||||
public static String getContext()
|
||||
{
|
||||
public static String getContext() {
|
||||
return Convert.toStr(RequestContextHolder.currentRequestAttributes().getAttribute(PERMISSION_CONTEXT_ATTRIBUTES,
|
||||
RequestAttributes.SCOPE_REQUEST));
|
||||
}
|
||||
|
||||
public static void setContext(String permission) {
|
||||
RequestContextHolder.currentRequestAttributes().setAttribute(PERMISSION_CONTEXT_ATTRIBUTES, permission,
|
||||
RequestAttributes.SCOPE_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@ -18,22 +19,19 @@ import com.fastbee.framework.web.service.TokenService;
|
||||
|
||||
/**
|
||||
* token过滤器 验证token有效性
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
|
||||
{
|
||||
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
throws ServletException, IOException {
|
||||
LoginUser loginUser = tokenService.getLoginUser(request);
|
||||
if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
|
||||
{
|
||||
if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())) {
|
||||
tokenService.verifyToken(loginUser);
|
||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
|
||||
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
|
||||
@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -15,30 +16,27 @@ import com.fastbee.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 认证失败处理类 返回未授权
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable
|
||||
{
|
||||
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable {
|
||||
private static final long serialVersionUID = -8970718410437077606L;
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
|
||||
throws IOException
|
||||
{
|
||||
// if (isAjaxRequest(request)){
|
||||
int code = HttpStatus.UNAUTHORIZED;
|
||||
String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI());
|
||||
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg)));
|
||||
// }else {
|
||||
// response.sendRedirect("/oauth/login");
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
public static boolean isAjaxRequest(HttpServletRequest request) {
|
||||
String ajaxFlag = request.getHeader("X-Requested-With");
|
||||
return ajaxFlag != null && "XMLHttpRequest".equals(ajaxFlag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
|
||||
throws IOException {
|
||||
// if (isAjaxRequest(request)){
|
||||
int code = HttpStatus.UNAUTHORIZED;
|
||||
String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI());
|
||||
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg)));
|
||||
// }else {
|
||||
// response.sendRedirect("/oauth/login");
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@ -20,27 +21,24 @@ import com.fastbee.framework.web.service.TokenService;
|
||||
|
||||
/**
|
||||
* 自定义退出处理类 返回成功
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler
|
||||
{
|
||||
public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
/**
|
||||
* 退出处理
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
throws IOException, ServletException {
|
||||
LoginUser loginUser = tokenService.getLoginUser(request);
|
||||
if (StringUtils.isNotNull(loginUser))
|
||||
{
|
||||
if (StringUtils.isNotNull(loginUser)) {
|
||||
String userName = loginUser.getUsername();
|
||||
// 删除用户缓存记录
|
||||
tokenService.delLoginUser(loginUser.getToken());
|
||||
|
||||
@ -1,16 +1,8 @@
|
||||
package com.fastbee.framework.web.domain;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import com.fastbee.common.utils.Arith;
|
||||
import com.fastbee.common.utils.ip.IpUtils;
|
||||
import com.fastbee.framework.web.domain.server.Cpu;
|
||||
import com.fastbee.framework.web.domain.server.Jvm;
|
||||
import com.fastbee.framework.web.domain.server.Mem;
|
||||
import com.fastbee.framework.web.domain.server.Sys;
|
||||
import com.fastbee.framework.web.domain.server.SysFile;
|
||||
import com.fastbee.framework.web.domain.server.*;
|
||||
import oshi.SystemInfo;
|
||||
import oshi.hardware.CentralProcessor;
|
||||
import oshi.hardware.CentralProcessor.TickType;
|
||||
@ -21,15 +13,19 @@ import oshi.software.os.OSFileStore;
|
||||
import oshi.software.os.OperatingSystem;
|
||||
import oshi.util.Util;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* 服务器相关信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Server
|
||||
{
|
||||
public class Server {
|
||||
private static final int OSHI_WAIT_SECOND = 1000;
|
||||
|
||||
|
||||
/**
|
||||
* CPU相关信息
|
||||
*/
|
||||
@ -55,58 +51,69 @@ public class Server
|
||||
*/
|
||||
private List<SysFile> sysFiles = new LinkedList<SysFile>();
|
||||
|
||||
public Cpu getCpu()
|
||||
{
|
||||
public Cpu getCpu() {
|
||||
return cpu;
|
||||
}
|
||||
|
||||
public void setCpu(Cpu cpu)
|
||||
{
|
||||
public void setCpu(Cpu cpu) {
|
||||
this.cpu = cpu;
|
||||
}
|
||||
|
||||
public Mem getMem()
|
||||
{
|
||||
public Mem getMem() {
|
||||
return mem;
|
||||
}
|
||||
|
||||
public void setMem(Mem mem)
|
||||
{
|
||||
public void setMem(Mem mem) {
|
||||
this.mem = mem;
|
||||
}
|
||||
|
||||
public Jvm getJvm()
|
||||
{
|
||||
public Jvm getJvm() {
|
||||
return jvm;
|
||||
}
|
||||
|
||||
public void setJvm(Jvm jvm)
|
||||
{
|
||||
public void setJvm(Jvm jvm) {
|
||||
this.jvm = jvm;
|
||||
}
|
||||
|
||||
public Sys getSys()
|
||||
{
|
||||
public Sys getSys() {
|
||||
return sys;
|
||||
}
|
||||
|
||||
public void setSys(Sys sys)
|
||||
{
|
||||
public void setSys(Sys sys) {
|
||||
this.sys = sys;
|
||||
}
|
||||
|
||||
public List<SysFile> getSysFiles()
|
||||
{
|
||||
public List<SysFile> getSysFiles() {
|
||||
return sysFiles;
|
||||
}
|
||||
|
||||
public void setSysFiles(List<SysFile> sysFiles)
|
||||
{
|
||||
public void setSysFiles(List<SysFile> sysFiles) {
|
||||
this.sysFiles = sysFiles;
|
||||
}
|
||||
|
||||
public void copyTo() throws Exception
|
||||
{
|
||||
/**
|
||||
* 设置磁盘信息
|
||||
*/
|
||||
private void setSysFiles(OperatingSystem os) {
|
||||
FileSystem fileSystem = os.getFileSystem();
|
||||
List<OSFileStore> 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);
|
||||
}
|
||||
}
|
||||
|
||||
public void copyTo() throws Exception {
|
||||
SystemInfo si = new SystemInfo();
|
||||
HardwareAbstractionLayer hal = si.getHardware();
|
||||
|
||||
@ -124,8 +131,7 @@ public class Server
|
||||
/**
|
||||
* 设置CPU信息
|
||||
*/
|
||||
private void setCpuInfo(CentralProcessor processor)
|
||||
{
|
||||
private void setCpuInfo(CentralProcessor processor) {
|
||||
// CPU信息
|
||||
long[] prevTicks = processor.getSystemCpuLoadTicks();
|
||||
Util.sleep(OSHI_WAIT_SECOND);
|
||||
@ -150,8 +156,7 @@ public class Server
|
||||
/**
|
||||
* 设置内存信息
|
||||
*/
|
||||
private void setMemInfo(GlobalMemory memory)
|
||||
{
|
||||
private void setMemInfo(GlobalMemory memory) {
|
||||
mem.setTotal(memory.getTotal());
|
||||
mem.setUsed(memory.getTotal() - memory.getAvailable());
|
||||
mem.setFree(memory.getAvailable());
|
||||
@ -160,8 +165,7 @@ public class Server
|
||||
/**
|
||||
* 设置服务器信息
|
||||
*/
|
||||
private void setSysInfo()
|
||||
{
|
||||
private void setSysInfo() {
|
||||
Properties props = System.getProperties();
|
||||
sys.setComputerName(IpUtils.getHostName());
|
||||
sys.setComputerIp(IpUtils.getHostIp());
|
||||
@ -173,8 +177,7 @@ public class Server
|
||||
/**
|
||||
* 设置Java虚拟机
|
||||
*/
|
||||
private void setJvmInfo() throws UnknownHostException
|
||||
{
|
||||
private void setJvmInfo() throws UnknownHostException {
|
||||
Properties props = System.getProperties();
|
||||
jvm.setTotal(Runtime.getRuntime().totalMemory());
|
||||
jvm.setMax(Runtime.getRuntime().maxMemory());
|
||||
@ -183,57 +186,25 @@ public class Server
|
||||
jvm.setHome(props.getProperty("java.home"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置磁盘信息
|
||||
*/
|
||||
private void setSysFiles(OperatingSystem os)
|
||||
{
|
||||
FileSystem fileSystem = os.getFileSystem();
|
||||
List<OSFileStore> 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)
|
||||
{
|
||||
public String convertFileSize(long size) {
|
||||
long kb = 1024;
|
||||
long mb = kb * 1024;
|
||||
long gb = mb * 1024;
|
||||
if (size >= gb)
|
||||
{
|
||||
if (size >= gb) {
|
||||
return String.format("%.1f GB", (float) size / gb);
|
||||
}
|
||||
else if (size >= mb)
|
||||
{
|
||||
} else if (size >= mb) {
|
||||
float f = (float) size / mb;
|
||||
return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
|
||||
}
|
||||
else if (size >= kb)
|
||||
{
|
||||
} else if (size >= kb) {
|
||||
float f = (float) size / kb;
|
||||
return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return String.format("%d B", size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,11 +4,10 @@ import com.fastbee.common.utils.Arith;
|
||||
|
||||
/**
|
||||
* CPU相关信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Cpu
|
||||
{
|
||||
public class Cpu {
|
||||
/**
|
||||
* 核心数
|
||||
*/
|
||||
@ -39,63 +38,51 @@ public class Cpu
|
||||
*/
|
||||
private double free;
|
||||
|
||||
public int getCpuNum()
|
||||
{
|
||||
public int getCpuNum() {
|
||||
return cpuNum;
|
||||
}
|
||||
|
||||
public void setCpuNum(int cpuNum)
|
||||
{
|
||||
public void setCpuNum(int cpuNum) {
|
||||
this.cpuNum = cpuNum;
|
||||
}
|
||||
|
||||
public double getTotal()
|
||||
{
|
||||
public double getTotal() {
|
||||
return Arith.round(Arith.mul(total, 100), 2);
|
||||
}
|
||||
|
||||
public void setTotal(double total)
|
||||
{
|
||||
public void setTotal(double total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public double getSys()
|
||||
{
|
||||
public double getSys() {
|
||||
return Arith.round(Arith.mul(sys / total, 100), 2);
|
||||
}
|
||||
|
||||
public void setSys(double sys)
|
||||
{
|
||||
public void setSys(double sys) {
|
||||
this.sys = sys;
|
||||
}
|
||||
|
||||
public double getUsed()
|
||||
{
|
||||
public double getUsed() {
|
||||
return Arith.round(Arith.mul(used / total, 100), 2);
|
||||
}
|
||||
|
||||
public void setUsed(double used)
|
||||
{
|
||||
public void setUsed(double used) {
|
||||
this.used = used;
|
||||
}
|
||||
|
||||
public double getWait()
|
||||
{
|
||||
public double getWait() {
|
||||
return Arith.round(Arith.mul(wait / total, 100), 2);
|
||||
}
|
||||
|
||||
public void setWait(double wait)
|
||||
{
|
||||
public void setWait(double wait) {
|
||||
this.wait = wait;
|
||||
}
|
||||
|
||||
public double getFree()
|
||||
{
|
||||
public double getFree() {
|
||||
return Arith.round(Arith.mul(free / total, 100), 2);
|
||||
}
|
||||
|
||||
public void setFree(double free)
|
||||
{
|
||||
public void setFree(double free) {
|
||||
this.free = free;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
package com.fastbee.framework.web.domain.server;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import com.fastbee.common.utils.Arith;
|
||||
import com.fastbee.common.utils.DateUtils;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
/**
|
||||
* JVM相关信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Jvm
|
||||
{
|
||||
public class Jvm {
|
||||
/**
|
||||
* 当前JVM占用的内存总数(M)
|
||||
*/
|
||||
@ -36,95 +36,79 @@ public class Jvm
|
||||
*/
|
||||
private String home;
|
||||
|
||||
public double getTotal()
|
||||
{
|
||||
public double getTotal() {
|
||||
return Arith.div(total, (1024 * 1024), 2);
|
||||
}
|
||||
|
||||
public void setTotal(double total)
|
||||
{
|
||||
public void setTotal(double total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public double getMax()
|
||||
{
|
||||
public double getMax() {
|
||||
return Arith.div(max, (1024 * 1024), 2);
|
||||
}
|
||||
|
||||
public void setMax(double max)
|
||||
{
|
||||
public void setMax(double max) {
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public double getFree()
|
||||
{
|
||||
public double getFree() {
|
||||
return Arith.div(free, (1024 * 1024), 2);
|
||||
}
|
||||
|
||||
public void setFree(double free)
|
||||
{
|
||||
public void setFree(double free) {
|
||||
this.free = free;
|
||||
}
|
||||
|
||||
public double getUsed()
|
||||
{
|
||||
public double getUsed() {
|
||||
return Arith.div(total - free, (1024 * 1024), 2);
|
||||
}
|
||||
|
||||
public double getUsage()
|
||||
{
|
||||
public double getUsage() {
|
||||
return Arith.mul(Arith.div(total - free, total, 4), 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取JDK名称
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
public String getName() {
|
||||
return ManagementFactory.getRuntimeMXBean().getVmName();
|
||||
}
|
||||
|
||||
public String getVersion()
|
||||
{
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version)
|
||||
{
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getHome()
|
||||
{
|
||||
public String getHome() {
|
||||
return home;
|
||||
}
|
||||
|
||||
public void setHome(String home)
|
||||
{
|
||||
public void setHome(String home) {
|
||||
this.home = home;
|
||||
}
|
||||
|
||||
/**
|
||||
* JDK启动时间
|
||||
*/
|
||||
public String getStartTime()
|
||||
{
|
||||
public String getStartTime() {
|
||||
return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate());
|
||||
}
|
||||
|
||||
/**
|
||||
* JDK运行时间
|
||||
*/
|
||||
public String getRunTime()
|
||||
{
|
||||
public String getRunTime() {
|
||||
return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate());
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行参数
|
||||
*/
|
||||
public String getInputArgs()
|
||||
{
|
||||
public String getInputArgs() {
|
||||
return ManagementFactory.getRuntimeMXBean().getInputArguments().toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,11 +4,10 @@ import com.fastbee.common.utils.Arith;
|
||||
|
||||
/**
|
||||
* 內存相关信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Mem
|
||||
{
|
||||
public class Mem {
|
||||
/**
|
||||
* 内存总量
|
||||
*/
|
||||
@ -24,38 +23,31 @@ public class Mem
|
||||
*/
|
||||
private double free;
|
||||
|
||||
public double getTotal()
|
||||
{
|
||||
public double getTotal() {
|
||||
return Arith.div(total, (1024 * 1024 * 1024), 2);
|
||||
}
|
||||
|
||||
public void setTotal(long total)
|
||||
{
|
||||
public void setTotal(long total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public double getUsed()
|
||||
{
|
||||
public double getUsed() {
|
||||
return Arith.div(used, (1024 * 1024 * 1024), 2);
|
||||
}
|
||||
|
||||
public void setUsed(long used)
|
||||
{
|
||||
public void setUsed(long used) {
|
||||
this.used = used;
|
||||
}
|
||||
|
||||
public double getFree()
|
||||
{
|
||||
public double getFree() {
|
||||
return Arith.div(free, (1024 * 1024 * 1024), 2);
|
||||
}
|
||||
|
||||
public void setFree(long free)
|
||||
{
|
||||
public void setFree(long free) {
|
||||
this.free = free;
|
||||
}
|
||||
|
||||
public double getUsage()
|
||||
{
|
||||
public double getUsage() {
|
||||
return Arith.mul(Arith.div(used, total, 4), 100);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,11 +2,10 @@ package com.fastbee.framework.web.domain.server;
|
||||
|
||||
/**
|
||||
* 系统相关信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Sys
|
||||
{
|
||||
public class Sys {
|
||||
/**
|
||||
* 服务器名称
|
||||
*/
|
||||
@ -32,53 +31,43 @@ public class Sys
|
||||
*/
|
||||
private String osArch;
|
||||
|
||||
public String getComputerName()
|
||||
{
|
||||
public String getComputerName() {
|
||||
return computerName;
|
||||
}
|
||||
|
||||
public void setComputerName(String computerName)
|
||||
{
|
||||
public void setComputerName(String computerName) {
|
||||
this.computerName = computerName;
|
||||
}
|
||||
|
||||
public String getComputerIp()
|
||||
{
|
||||
public String getComputerIp() {
|
||||
return computerIp;
|
||||
}
|
||||
|
||||
public void setComputerIp(String computerIp)
|
||||
{
|
||||
public void setComputerIp(String computerIp) {
|
||||
this.computerIp = computerIp;
|
||||
}
|
||||
|
||||
public String getUserDir()
|
||||
{
|
||||
public String getUserDir() {
|
||||
return userDir;
|
||||
}
|
||||
|
||||
public void setUserDir(String userDir)
|
||||
{
|
||||
public void setUserDir(String userDir) {
|
||||
this.userDir = userDir;
|
||||
}
|
||||
|
||||
public String getOsName()
|
||||
{
|
||||
public String getOsName() {
|
||||
return osName;
|
||||
}
|
||||
|
||||
public void setOsName(String osName)
|
||||
{
|
||||
public void setOsName(String osName) {
|
||||
this.osName = osName;
|
||||
}
|
||||
|
||||
public String getOsArch()
|
||||
{
|
||||
public String getOsArch() {
|
||||
return osArch;
|
||||
}
|
||||
|
||||
public void setOsArch(String osArch)
|
||||
{
|
||||
public void setOsArch(String osArch) {
|
||||
this.osArch = osArch;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,11 +2,10 @@ package com.fastbee.framework.web.domain.server;
|
||||
|
||||
/**
|
||||
* 系统文件相关信息
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class SysFile
|
||||
{
|
||||
public class SysFile {
|
||||
/**
|
||||
* 盘符路径
|
||||
*/
|
||||
@ -42,73 +41,59 @@ public class SysFile
|
||||
*/
|
||||
private double usage;
|
||||
|
||||
public String getDirName()
|
||||
{
|
||||
public String getDirName() {
|
||||
return dirName;
|
||||
}
|
||||
|
||||
public void setDirName(String dirName)
|
||||
{
|
||||
public void setDirName(String dirName) {
|
||||
this.dirName = dirName;
|
||||
}
|
||||
|
||||
public String getSysTypeName()
|
||||
{
|
||||
public String getSysTypeName() {
|
||||
return sysTypeName;
|
||||
}
|
||||
|
||||
public void setSysTypeName(String sysTypeName)
|
||||
{
|
||||
public void setSysTypeName(String sysTypeName) {
|
||||
this.sysTypeName = sysTypeName;
|
||||
}
|
||||
|
||||
public String getTypeName()
|
||||
{
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
public void setTypeName(String typeName)
|
||||
{
|
||||
public void setTypeName(String typeName) {
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
public String getTotal()
|
||||
{
|
||||
public String getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(String total)
|
||||
{
|
||||
public void setTotal(String total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public String getFree()
|
||||
{
|
||||
public String getFree() {
|
||||
return free;
|
||||
}
|
||||
|
||||
public void setFree(String free)
|
||||
{
|
||||
public void setFree(String free) {
|
||||
this.free = free;
|
||||
}
|
||||
|
||||
public String getUsed()
|
||||
{
|
||||
public String getUsed() {
|
||||
return used;
|
||||
}
|
||||
|
||||
public void setUsed(String used)
|
||||
{
|
||||
public void setUsed(String used) {
|
||||
this.used = used;
|
||||
}
|
||||
|
||||
public double getUsage()
|
||||
{
|
||||
public double getUsage() {
|
||||
return usage;
|
||||
}
|
||||
|
||||
public void setUsage(double usage)
|
||||
{
|
||||
public void setUsage(double usage) {
|
||||
this.usage = usage;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
package com.fastbee.framework.web.exception;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import com.fastbee.common.constant.HttpStatus;
|
||||
import com.fastbee.common.core.domain.AjaxResult;
|
||||
import com.fastbee.common.exception.DemoModeException;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
@ -9,28 +13,23 @@ import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import com.fastbee.common.constant.HttpStatus;
|
||||
import com.fastbee.common.core.domain.AjaxResult;
|
||||
import com.fastbee.common.exception.DemoModeException;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler
|
||||
{
|
||||
public class GlobalExceptionHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||
|
||||
/**
|
||||
* 权限校验异常
|
||||
*/
|
||||
@ExceptionHandler(AccessDeniedException.class)
|
||||
public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request)
|
||||
{
|
||||
public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request) {
|
||||
String requestURI = request.getRequestURI();
|
||||
log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage());
|
||||
return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权");
|
||||
@ -41,8 +40,7 @@ public class GlobalExceptionHandler
|
||||
*/
|
||||
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
|
||||
public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
|
||||
HttpServletRequest request)
|
||||
{
|
||||
HttpServletRequest request) {
|
||||
String requestURI = request.getRequestURI();
|
||||
log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
|
||||
return AjaxResult.error(e.getMessage());
|
||||
@ -52,8 +50,7 @@ public class GlobalExceptionHandler
|
||||
* 业务异常
|
||||
*/
|
||||
@ExceptionHandler(ServiceException.class)
|
||||
public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request)
|
||||
{
|
||||
public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request) {
|
||||
log.error(e.getMessage(), e);
|
||||
Integer code = e.getCode();
|
||||
return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
|
||||
@ -63,8 +60,7 @@ public class GlobalExceptionHandler
|
||||
* 拦截未知的运行时异常
|
||||
*/
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request)
|
||||
{
|
||||
public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request) {
|
||||
String requestURI = request.getRequestURI();
|
||||
log.error("请求地址'{}',发生未知异常.", requestURI, e);
|
||||
return AjaxResult.error(e.getMessage());
|
||||
@ -74,8 +70,7 @@ public class GlobalExceptionHandler
|
||||
* 系统异常
|
||||
*/
|
||||
@ExceptionHandler(Exception.class)
|
||||
public AjaxResult handleException(Exception e, HttpServletRequest request)
|
||||
{
|
||||
public AjaxResult handleException(Exception e, HttpServletRequest request) {
|
||||
String requestURI = request.getRequestURI();
|
||||
log.error("请求地址'{}',发生系统异常.", requestURI, e);
|
||||
return AjaxResult.error(e.getMessage());
|
||||
@ -85,8 +80,7 @@ public class GlobalExceptionHandler
|
||||
* 自定义验证异常
|
||||
*/
|
||||
@ExceptionHandler(BindException.class)
|
||||
public AjaxResult handleBindException(BindException e)
|
||||
{
|
||||
public AjaxResult handleBindException(BindException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
String message = e.getAllErrors().get(0).getDefaultMessage();
|
||||
return AjaxResult.error(message);
|
||||
@ -96,8 +90,7 @@ public class GlobalExceptionHandler
|
||||
* 自定义验证异常
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
|
||||
{
|
||||
public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
String message = e.getBindingResult().getFieldError().getDefaultMessage();
|
||||
return AjaxResult.error(message);
|
||||
@ -107,8 +100,7 @@ public class GlobalExceptionHandler
|
||||
* 演示模式异常
|
||||
*/
|
||||
@ExceptionHandler(DemoModeException.class)
|
||||
public AjaxResult handleDemoModeException(DemoModeException e)
|
||||
{
|
||||
public AjaxResult handleDemoModeException(DemoModeException e) {
|
||||
return AjaxResult.error("演示模式,不允许操作");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,26 +1,30 @@
|
||||
package com.fastbee.framework.web.service;
|
||||
|
||||
import java.util.Set;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import com.fastbee.common.core.domain.entity.SysRole;
|
||||
import com.fastbee.common.core.domain.model.LoginUser;
|
||||
import com.fastbee.common.utils.SecurityUtils;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.framework.security.context.PermissionContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* RuoYi首创 自定义权限实现,ss取自SpringSecurity首字母
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Service("ss")
|
||||
public class PermissionService
|
||||
{
|
||||
/** 所有权限标识 */
|
||||
public class PermissionService {
|
||||
/**
|
||||
* 所有权限标识
|
||||
*/
|
||||
private static final String ALL_PERMISSION = "*:*:*";
|
||||
|
||||
/** 管理员角色权限标识 */
|
||||
/**
|
||||
* 管理员角色权限标识
|
||||
*/
|
||||
private static final String SUPER_ADMIN = "admin";
|
||||
|
||||
private static final String ROLE_DELIMETER = ",";
|
||||
@ -29,19 +33,16 @@ public class PermissionService
|
||||
|
||||
/**
|
||||
* 验证用户是否具备某权限
|
||||
*
|
||||
*
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否具备某权限
|
||||
*/
|
||||
public boolean hasPermi(String permission)
|
||||
{
|
||||
if (StringUtils.isEmpty(permission))
|
||||
{
|
||||
public boolean hasPermi(String permission) {
|
||||
if (StringUtils.isEmpty(permission)) {
|
||||
return false;
|
||||
}
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
|
||||
{
|
||||
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) {
|
||||
return false;
|
||||
}
|
||||
PermissionContextHolder.setContext(permission);
|
||||
@ -54,8 +55,7 @@ public class PermissionService
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否不具备某权限
|
||||
*/
|
||||
public boolean lacksPermi(String permission)
|
||||
{
|
||||
public boolean lacksPermi(String permission) {
|
||||
return hasPermi(permission) != true;
|
||||
}
|
||||
|
||||
@ -65,23 +65,18 @@ public class PermissionService
|
||||
* @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
|
||||
* @return 用户是否具有以下任意一个权限
|
||||
*/
|
||||
public boolean hasAnyPermi(String permissions)
|
||||
{
|
||||
if (StringUtils.isEmpty(permissions))
|
||||
{
|
||||
public boolean hasAnyPermi(String permissions) {
|
||||
if (StringUtils.isEmpty(permissions)) {
|
||||
return false;
|
||||
}
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
|
||||
{
|
||||
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) {
|
||||
return false;
|
||||
}
|
||||
PermissionContextHolder.setContext(permissions);
|
||||
Set<String> authorities = loginUser.getPermissions();
|
||||
for (String permission : permissions.split(PERMISSION_DELIMETER))
|
||||
{
|
||||
if (permission != null && hasPermissions(authorities, permission))
|
||||
{
|
||||
for (String permission : permissions.split(PERMISSION_DELIMETER)) {
|
||||
if (permission != null && hasPermissions(authorities, permission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -90,26 +85,21 @@ public class PermissionService
|
||||
|
||||
/**
|
||||
* 判断用户是否拥有某个角色
|
||||
*
|
||||
*
|
||||
* @param role 角色字符串
|
||||
* @return 用户是否具备某角色
|
||||
*/
|
||||
public boolean hasRole(String role)
|
||||
{
|
||||
if (StringUtils.isEmpty(role))
|
||||
{
|
||||
public boolean hasRole(String role) {
|
||||
if (StringUtils.isEmpty(role)) {
|
||||
return false;
|
||||
}
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
|
||||
{
|
||||
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) {
|
||||
return false;
|
||||
}
|
||||
for (SysRole sysRole : loginUser.getUser().getRoles())
|
||||
{
|
||||
for (SysRole sysRole : loginUser.getUser().getRoles()) {
|
||||
String roleKey = sysRole.getRoleKey();
|
||||
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
|
||||
{
|
||||
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -122,8 +112,7 @@ public class PermissionService
|
||||
* @param role 角色名称
|
||||
* @return 用户是否不具备某角色
|
||||
*/
|
||||
public boolean lacksRole(String role)
|
||||
{
|
||||
public boolean lacksRole(String role) {
|
||||
return hasRole(role) != true;
|
||||
}
|
||||
|
||||
@ -133,21 +122,16 @@ public class PermissionService
|
||||
* @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
|
||||
* @return 用户是否具有以下任意一个角色
|
||||
*/
|
||||
public boolean hasAnyRoles(String roles)
|
||||
{
|
||||
if (StringUtils.isEmpty(roles))
|
||||
{
|
||||
public boolean hasAnyRoles(String roles) {
|
||||
if (StringUtils.isEmpty(roles)) {
|
||||
return false;
|
||||
}
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
|
||||
{
|
||||
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) {
|
||||
return false;
|
||||
}
|
||||
for (String role : roles.split(ROLE_DELIMETER))
|
||||
{
|
||||
if (hasRole(role))
|
||||
{
|
||||
for (String role : roles.split(ROLE_DELIMETER)) {
|
||||
if (hasRole(role)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -156,13 +140,12 @@ public class PermissionService
|
||||
|
||||
/**
|
||||
* 判断是否包含权限
|
||||
*
|
||||
*
|
||||
* @param permissions 权限列表
|
||||
* @param permission 权限字符串
|
||||
* @param permission 权限字符串
|
||||
* @return 用户是否具备某权限
|
||||
*/
|
||||
private boolean hasPermissions(Set<String> permissions, String permission)
|
||||
{
|
||||
private boolean hasPermissions(Set<String> permissions, String permission) {
|
||||
return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,5 @@
|
||||
package com.fastbee.framework.web.service;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.fastbee.common.constant.CacheConstants;
|
||||
import com.fastbee.common.constant.Constants;
|
||||
import com.fastbee.common.core.domain.entity.SysUser;
|
||||
@ -16,6 +11,12 @@ import com.fastbee.common.utils.SecurityUtils;
|
||||
import com.fastbee.framework.manager.AsyncManager;
|
||||
import com.fastbee.framework.manager.factory.AsyncFactory;
|
||||
import com.fastbee.framework.security.context.AuthenticationContextHolder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 登录密码方法
|
||||
@ -23,8 +24,7 @@ import com.fastbee.framework.security.context.AuthenticationContextHolder;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class SysPasswordService
|
||||
{
|
||||
public class SysPasswordService {
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@ -40,86 +40,71 @@ public class SysPasswordService
|
||||
* @param username 用户名
|
||||
* @return 缓存键key
|
||||
*/
|
||||
private String getCacheKey(String username)
|
||||
{
|
||||
private String getCacheKey(String username) {
|
||||
return CacheConstants.PWD_ERR_CNT_KEY + username;
|
||||
}
|
||||
|
||||
public void validate(SysUser user)
|
||||
{
|
||||
public void validate(SysUser user) {
|
||||
Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
|
||||
String username = usernamePasswordAuthenticationToken.getName();
|
||||
String password = usernamePasswordAuthenticationToken.getCredentials().toString();
|
||||
|
||||
Integer retryCount = redisCache.getCacheObject(getCacheKey(username));
|
||||
|
||||
if (retryCount == null)
|
||||
{
|
||||
if (retryCount == null) {
|
||||
retryCount = 0;
|
||||
}
|
||||
|
||||
if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
|
||||
{
|
||||
if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
|
||||
MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount, lockTime)));
|
||||
throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime);
|
||||
}
|
||||
|
||||
if (!matches(user, password))
|
||||
{
|
||||
if (!matches(user, password)) {
|
||||
retryCount = retryCount + 1;
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
|
||||
MessageUtils.message("user.password.retry.limit.count", retryCount)));
|
||||
redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
clearLoginRecordCache(username);
|
||||
}
|
||||
}
|
||||
|
||||
public void socialValidate(SysUser user, String encodePwd)
|
||||
{
|
||||
public void socialValidate(SysUser user, String encodePwd) {
|
||||
String username = user.getUserName();
|
||||
String password = user.getPassword();
|
||||
|
||||
Integer retryCount = redisCache.getCacheObject(getCacheKey(username));
|
||||
|
||||
if (retryCount == null)
|
||||
{
|
||||
if (retryCount == null) {
|
||||
retryCount = 0;
|
||||
}
|
||||
|
||||
if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
|
||||
{
|
||||
if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
|
||||
MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount, lockTime)));
|
||||
throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime);
|
||||
}
|
||||
|
||||
if(!password.equals(encodePwd)){
|
||||
if (!password.equals(encodePwd)) {
|
||||
retryCount = retryCount + 1;
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
|
||||
MessageUtils.message("user.password.retry.limit.count", retryCount)));
|
||||
redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
clearLoginRecordCache(username);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean matches(SysUser user, String rawPassword)
|
||||
{
|
||||
public boolean matches(SysUser user, String rawPassword) {
|
||||
return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
|
||||
}
|
||||
|
||||
public void clearLoginRecordCache(String loginName)
|
||||
{
|
||||
if (redisCache.hasKey(getCacheKey(loginName)))
|
||||
{
|
||||
public void clearLoginRecordCache(String loginName) {
|
||||
if (redisCache.hasKey(getCacheKey(loginName))) {
|
||||
redisCache.deleteObject(getCacheKey(loginName));
|
||||
}
|
||||
}
|
||||
@ -130,28 +115,23 @@ public class SysPasswordService
|
||||
|
||||
Integer retryCount = redisCache.getCacheObject(getCacheKey(username));
|
||||
|
||||
if (retryCount == null)
|
||||
{
|
||||
if (retryCount == null) {
|
||||
retryCount = 0;
|
||||
}
|
||||
|
||||
if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
|
||||
{
|
||||
if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
|
||||
MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount, lockTime)));
|
||||
throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime);
|
||||
}
|
||||
|
||||
if (!matches(user, encodePwd))
|
||||
{
|
||||
if (!matches(user, encodePwd)) {
|
||||
retryCount = retryCount + 1;
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
|
||||
MessageUtils.message("user.password.retry.limit.count", retryCount)));
|
||||
redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
clearLoginRecordCache(username);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
package com.fastbee.framework.web.service;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.fastbee.common.core.domain.entity.SysRole;
|
||||
import com.fastbee.common.core.domain.entity.SysUser;
|
||||
import com.fastbee.system.service.ISysMenuService;
|
||||
import com.fastbee.system.service.ISysRoleService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 用户权限处理
|
||||
@ -16,8 +17,7 @@ import com.fastbee.system.service.ISysRoleService;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class SysPermissionService
|
||||
{
|
||||
public class SysPermissionService {
|
||||
@Autowired
|
||||
private ISysRoleService roleService;
|
||||
|
||||
@ -30,16 +30,12 @@ public class SysPermissionService
|
||||
* @param user 用户信息
|
||||
* @return 角色权限信息
|
||||
*/
|
||||
public Set<String> getRolePermission(SysUser user)
|
||||
{
|
||||
public Set<String> getRolePermission(SysUser user) {
|
||||
Set<String> roles = new HashSet<String>();
|
||||
// 管理员拥有所有权限
|
||||
if (user.isAdmin())
|
||||
{
|
||||
if (user.isAdmin()) {
|
||||
roles.add("admin");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId()));
|
||||
}
|
||||
return roles;
|
||||
@ -51,26 +47,21 @@ public class SysPermissionService
|
||||
* @param user 用户信息
|
||||
* @return 菜单权限信息
|
||||
*/
|
||||
public Set<String> getMenuPermission(SysUser user)
|
||||
{
|
||||
public Set<String> getMenuPermission(SysUser user) {
|
||||
Set<String> perms = new HashSet<String>();
|
||||
// 管理员拥有所有权限
|
||||
if (user.isAdmin()) {
|
||||
perms.add("*:*:*");
|
||||
} else {
|
||||
List<SysRole> roles = user.getRoles();
|
||||
if (!roles.isEmpty() && roles.size() > 1)
|
||||
{
|
||||
if (!roles.isEmpty() && roles.size() > 1) {
|
||||
// 多角色设置permissions属性,以便数据权限匹配权限
|
||||
for (SysRole role : roles)
|
||||
{
|
||||
for (SysRole role : roles) {
|
||||
Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
|
||||
role.setPermissions(rolePerms);
|
||||
perms.addAll(rolePerms);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
package com.fastbee.framework.web.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.fastbee.common.constant.CacheConstants;
|
||||
import com.fastbee.common.constant.Constants;
|
||||
import com.fastbee.common.constant.UserConstants;
|
||||
@ -17,15 +15,16 @@ import com.fastbee.framework.manager.AsyncManager;
|
||||
import com.fastbee.framework.manager.factory.AsyncFactory;
|
||||
import com.fastbee.system.service.ISysConfigService;
|
||||
import com.fastbee.system.service.ISysUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 注册校验方法
|
||||
*
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class SysRegisterService
|
||||
{
|
||||
public class SysRegisterService {
|
||||
@Autowired
|
||||
private ISysUserService userService;
|
||||
|
||||
@ -38,52 +37,36 @@ public class SysRegisterService
|
||||
/**
|
||||
* 注册
|
||||
*/
|
||||
public String register(RegisterBody registerBody)
|
||||
{
|
||||
public String register(RegisterBody registerBody) {
|
||||
String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword();
|
||||
SysUser sysUser = new SysUser();
|
||||
sysUser.setUserName(username);
|
||||
|
||||
// 验证码开关
|
||||
boolean captchaEnabled = configService.selectCaptchaEnabled();
|
||||
if (captchaEnabled)
|
||||
{
|
||||
if (captchaEnabled) {
|
||||
validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(username))
|
||||
{
|
||||
if (StringUtils.isEmpty(username)) {
|
||||
msg = "用户名不能为空";
|
||||
}
|
||||
else if (StringUtils.isEmpty(password))
|
||||
{
|
||||
} else if (StringUtils.isEmpty(password)) {
|
||||
msg = "用户密码不能为空";
|
||||
}
|
||||
else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|
||||
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
|
||||
{
|
||||
} else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|
||||
|| username.length() > UserConstants.USERNAME_MAX_LENGTH) {
|
||||
msg = "账户长度必须在2到20个字符之间";
|
||||
}
|
||||
else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|
||||
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
|
||||
{
|
||||
} else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|
||||
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
|
||||
msg = "密码长度必须在5到20个字符之间";
|
||||
}
|
||||
else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(sysUser)))
|
||||
{
|
||||
} else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(sysUser))) {
|
||||
msg = "保存用户'" + username + "'失败,注册账号已存在";
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
sysUser.setNickName(username);
|
||||
sysUser.setPassword(SecurityUtils.encryptPassword(password));
|
||||
boolean regFlag = userService.registerUser(sysUser);
|
||||
if (!regFlag)
|
||||
{
|
||||
if (!regFlag) {
|
||||
msg = "注册失败,请联系系统管理人员";
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success")));
|
||||
}
|
||||
}
|
||||
@ -92,23 +75,20 @@ public class SysRegisterService
|
||||
|
||||
/**
|
||||
* 校验验证码
|
||||
*
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param code 验证码
|
||||
* @param uuid 唯一标识
|
||||
* @param code 验证码
|
||||
* @param uuid 唯一标识
|
||||
* @return 结果
|
||||
*/
|
||||
public void validateCaptcha(String username, String code, String uuid)
|
||||
{
|
||||
public void validateCaptcha(String username, String code, String uuid) {
|
||||
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
|
||||
String captcha = redisCache.getCacheObject(verifyKey);
|
||||
redisCache.deleteObject(verifyKey);
|
||||
if (captcha == null)
|
||||
{
|
||||
if (captcha == null) {
|
||||
throw new CaptchaExpireException();
|
||||
}
|
||||
if (!code.equalsIgnoreCase(captcha))
|
||||
{
|
||||
if (!code.equalsIgnoreCase(captcha)) {
|
||||
throw new CaptchaException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,24 +35,18 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
@Component
|
||||
public class TokenService {
|
||||
protected static final long MILLIS_SECOND = 1000;
|
||||
protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
|
||||
private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
|
||||
// 令牌自定义标识
|
||||
@Value("${token.header}")
|
||||
private String header;
|
||||
|
||||
// 令牌秘钥
|
||||
@Value("${token.secret}")
|
||||
private String secret;
|
||||
|
||||
// 令牌有效期(默认30分钟)
|
||||
@Value("${token.expireTime}")
|
||||
private int expireTime;
|
||||
|
||||
protected static final long MILLIS_SECOND = 1000;
|
||||
|
||||
protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
|
||||
|
||||
private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
package com.fastbee.framework.web.service;
|
||||
|
||||
import com.fastbee.common.core.domain.entity.SysUser;
|
||||
import com.fastbee.common.core.domain.model.LoginUser;
|
||||
import com.fastbee.common.enums.UserStatus;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.system.service.ISysUserService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -7,12 +13,6 @@ import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.fastbee.common.core.domain.entity.SysUser;
|
||||
import com.fastbee.common.core.domain.model.LoginUser;
|
||||
import com.fastbee.common.enums.UserStatus;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.system.service.ISysUserService;
|
||||
|
||||
/**
|
||||
* 用户验证处理
|
||||
@ -20,13 +20,12 @@ import com.fastbee.system.service.ISysUserService;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Service
|
||||
public class UserDetailsServiceImpl implements UserDetailsService
|
||||
{
|
||||
public class UserDetailsServiceImpl implements UserDetailsService {
|
||||
private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
|
||||
|
||||
@Autowired
|
||||
private ISysUserService userService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private SysPasswordService passwordService;
|
||||
|
||||
@ -34,21 +33,15 @@ public class UserDetailsServiceImpl implements UserDetailsService
|
||||
private SysPermissionService permissionService;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
|
||||
{
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
SysUser user = userService.selectUserByUserName(username);
|
||||
if (StringUtils.isNull(user))
|
||||
{
|
||||
if (StringUtils.isNull(user)) {
|
||||
log.info("登录用户:{} 不存在.", username);
|
||||
throw new ServiceException("登录用户:" + username + " 不存在");
|
||||
}
|
||||
else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
|
||||
{
|
||||
} else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
|
||||
log.info("登录用户:{} 已被删除.", username);
|
||||
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
|
||||
}
|
||||
else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
|
||||
{
|
||||
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
|
||||
log.info("登录用户:{} 已被停用.", username);
|
||||
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
|
||||
}
|
||||
@ -58,8 +51,7 @@ public class UserDetailsServiceImpl implements UserDetailsService
|
||||
return createLoginUser(user);
|
||||
}
|
||||
|
||||
public UserDetails createLoginUser(SysUser user)
|
||||
{
|
||||
public UserDetails createLoginUser(SysUser user) {
|
||||
return new LoginUser(user.getUserId(), user.getDeptId(), user.getLanguage(), user, permissionService.getMenuPermission(user));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,34 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>fastbee</artifactId>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<version>3.8.5</version>
|
||||
</parent>
|
||||
<artifactId>fastbee-iot-data</artifactId>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>fastbee</artifactId>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<version>3.8.5</version>
|
||||
</parent>
|
||||
<artifactId>fastbee-iot-data</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<artifactId>mqtt-broker</artifactId>
|
||||
</dependency>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<artifactId>mqtt-broker</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<artifactId>fastbee-mq</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<artifactId>fastbee-mq</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<artifactId>fastbee-quartz</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<artifactId>fastbee-quartz</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<artifactId>fastbee-mqtt-client</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fastbee</groupId>
|
||||
<artifactId>fastbee-mqtt-client</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@ -65,7 +65,7 @@ public class StartBoot implements ApplicationRunner {
|
||||
log.info("=>设备监听队列启动成功");
|
||||
}).start();
|
||||
} catch (Exception e) {
|
||||
log.error("=>客户端启动失败:{}", e.getMessage(),e);
|
||||
log.error("=>客户端启动失败:{}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,11 +14,11 @@ import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.common.utils.gateway.mq.TopicsUtils;
|
||||
import com.fastbee.iot.domain.Device;
|
||||
import com.fastbee.iot.domain.DeviceLog;
|
||||
import com.fastbee.iot.service.IDeviceService;
|
||||
import com.fastbee.iot.service.IProductService;
|
||||
import com.fastbee.iot.service.IProductAuthorizeService;
|
||||
import com.fastbee.iot.domain.ProductAuthorize;
|
||||
import com.fastbee.iot.domain.Product;
|
||||
import com.fastbee.iot.domain.ProductAuthorize;
|
||||
import com.fastbee.iot.service.IDeviceService;
|
||||
import com.fastbee.iot.service.IProductAuthorizeService;
|
||||
import com.fastbee.iot.service.IProductService;
|
||||
import com.fastbee.iot.tdengine.service.ILogService;
|
||||
import com.fastbee.mqtt.manager.MqttRemoteManager;
|
||||
import com.fastbee.mqtt.model.PushMessageBo;
|
||||
@ -41,7 +41,7 @@ import java.util.Objects;
|
||||
/**
|
||||
* 设备调试错误日志AOP切面
|
||||
* 用于拦截数据解析和指令发送的异常,自动记录错误日志并推送到前端页面
|
||||
*
|
||||
* <p>
|
||||
* 功能:
|
||||
* 1. 拦截设备数据解析异常(parseReportMsg)
|
||||
* 2. 拦截指令发送异常(messagePost)
|
||||
@ -58,13 +58,21 @@ import java.util.Objects;
|
||||
@Slf4j
|
||||
public class DeviceDebugLogAspect {
|
||||
|
||||
/** 日志值最大长度 */
|
||||
/**
|
||||
* 日志值最大长度
|
||||
*/
|
||||
private static final int MAX_LOG_VALUE_LENGTH = 64;
|
||||
/** 备注最大长度 */
|
||||
/**
|
||||
* 备注最大长度
|
||||
*/
|
||||
private static final int MAX_REMARK_LENGTH = 200;
|
||||
/** 错误信息显示最大长度 */
|
||||
/**
|
||||
* 错误信息显示最大长度
|
||||
*/
|
||||
private static final int MAX_ERROR_MSG_DISPLAY_LENGTH = 50;
|
||||
/** 其他模式 */
|
||||
/**
|
||||
* 其他模式
|
||||
*/
|
||||
private static final int MODE_OTHER = 3;
|
||||
|
||||
@Resource
|
||||
@ -121,7 +129,7 @@ public class DeviceDebugLogAspect {
|
||||
String sourceData = extractSourceDataFromReportBo(bo);
|
||||
String errorMsg = getErrorMessage(e);
|
||||
Long productId = bo.getProductId();
|
||||
return new ErrorLogContext(serialNumber, sourceData, errorMsg,
|
||||
return new ErrorLogContext(serialNumber, sourceData, errorMsg,
|
||||
DeviceLogTypeEnum.DATA_PARSE_ERROR.getType(), "DEBUG_ERROR", productId);
|
||||
}
|
||||
return null;
|
||||
@ -223,7 +231,7 @@ public class DeviceDebugLogAspect {
|
||||
/**
|
||||
* 统一异常处理入口
|
||||
*/
|
||||
private void handleException(JoinPoint joinPoint, Throwable e,
|
||||
private void handleException(JoinPoint joinPoint, Throwable e,
|
||||
java.util.function.Function<Object[], ErrorLogContext> contextExtractor,
|
||||
String errorLogPrefix) {
|
||||
try {
|
||||
@ -371,7 +379,7 @@ public class DeviceDebugLogAspect {
|
||||
DeviceLog deviceLog = buildDeviceLog(device, context);
|
||||
logService.saveDeviceLog(deviceLog);
|
||||
log.info("已保存错误日志到数据库 - 设备: {}, 错误类型: {}, 错误信息: {}",
|
||||
serialNumber, context.getIdentity(),
|
||||
serialNumber, context.getIdentity(),
|
||||
StringUtils.substring(context.getErrorMsg(), 0, MAX_ERROR_MSG_DISPLAY_LENGTH));
|
||||
|
||||
// 推送错误信息到前端页面
|
||||
@ -430,7 +438,7 @@ public class DeviceDebugLogAspect {
|
||||
// 构建错误消息的物模型数据
|
||||
ThingsModelSimpleItem errorItem = new ThingsModelSimpleItem();
|
||||
errorItem.setId("ERROR_" + context.getIdentity());
|
||||
errorItem.setName(Objects.equals(context.getLogType(), DeviceLogTypeEnum.DATA_PARSE_ERROR.getType())
|
||||
errorItem.setName(Objects.equals(context.getLogType(), DeviceLogTypeEnum.DATA_PARSE_ERROR.getType())
|
||||
? "数据解析错误" : "指令发送错误");
|
||||
errorItem.setValue(context.getErrorMsg());
|
||||
errorItem.setRemark(context.getErrorMsg());
|
||||
@ -441,7 +449,7 @@ public class DeviceDebugLogAspect {
|
||||
// 构建推送消息
|
||||
PushMessageBo messageBo = new PushMessageBo();
|
||||
messageBo.setTopic(topicsUtils.buildTopic(productId, serialNumber.toUpperCase(), TopicType.WS_SERVICE_INVOKE));
|
||||
|
||||
|
||||
String sourceAscii = hexToAscii(context.getSourceData());
|
||||
JSONObject pushObj = new JSONObject();
|
||||
pushObj.put("message", errorItems);
|
||||
@ -449,49 +457,21 @@ public class DeviceDebugLogAspect {
|
||||
pushObj.put("sourcesAscii", sourceAscii);
|
||||
pushObj.put("errorType", context.getIdentity());
|
||||
pushObj.put("isError", true);
|
||||
|
||||
|
||||
messageBo.setMessage(JSON.toJSONString(pushObj));
|
||||
|
||||
|
||||
// 推送消息到MQTT
|
||||
mqttRemoteManager.pushCommon(messageBo);
|
||||
log.info("已推送错误信息到前端 - 设备: {}, 产品ID: {}, 错误类型: {}",
|
||||
log.info("已推送错误信息到前端 - 设备: {}, 产品ID: {}, 错误类型: {}",
|
||||
serialNumber, productId, context.getIdentity());
|
||||
} catch (Exception ex) {
|
||||
log.error("推送错误信息到前端失败: {}", ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误日志上下文对象
|
||||
*/
|
||||
private static class ErrorLogContext {
|
||||
private final String serialNumber;
|
||||
private final String sourceData;
|
||||
private final String errorMsg;
|
||||
private final Integer logType;
|
||||
private final String identity;
|
||||
private final Long productId;
|
||||
|
||||
public ErrorLogContext(String serialNumber, String sourceData, String errorMsg,
|
||||
Integer logType, String identity, Long productId) {
|
||||
this.serialNumber = serialNumber;
|
||||
this.sourceData = sourceData;
|
||||
this.errorMsg = errorMsg;
|
||||
this.logType = logType;
|
||||
this.identity = identity;
|
||||
this.productId = productId;
|
||||
}
|
||||
|
||||
public String getSerialNumber() { return serialNumber; }
|
||||
public String getSourceData() { return sourceData; }
|
||||
public String getErrorMsg() { return errorMsg; }
|
||||
public Integer getLogType() { return logType; }
|
||||
public String getIdentity() { return identity; }
|
||||
public Long getProductId() { return productId; }
|
||||
}
|
||||
|
||||
/**
|
||||
* 将ASCII字符串转换为HEX字符串
|
||||
*
|
||||
* @param asciiStr ASCII字符串
|
||||
* @return HEX字符串(大写,每两个字符一组,用空格分隔)
|
||||
*/
|
||||
@ -515,7 +495,7 @@ public class DeviceDebugLogAspect {
|
||||
}
|
||||
return hex.toString();
|
||||
} catch (Exception e) {
|
||||
log.warn("ASCII转HEX失败: {}, ASCII字符串: {}", e.getMessage(),
|
||||
log.warn("ASCII转HEX失败: {}, ASCII字符串: {}", e.getMessage(),
|
||||
StringUtils.isNotEmpty(asciiStr) ? StringUtils.substring(asciiStr, 0, 50) : "");
|
||||
return "";
|
||||
}
|
||||
@ -523,6 +503,7 @@ public class DeviceDebugLogAspect {
|
||||
|
||||
/**
|
||||
* 将16进制字符串转换为ASCII字符串
|
||||
*
|
||||
* @param hexStr 16进制字符串(可能包含空格)
|
||||
* @return ASCII字符串,保留换行符和回车符,其他不可打印字符显示为点号
|
||||
*/
|
||||
@ -565,9 +546,55 @@ public class DeviceDebugLogAspect {
|
||||
}
|
||||
return ascii.toString();
|
||||
} catch (Exception e) {
|
||||
log.warn("HEX转ASCII失败: {}, HEX字符串: {}", e.getMessage(),
|
||||
log.warn("HEX转ASCII失败: {}, HEX字符串: {}", e.getMessage(),
|
||||
StringUtils.isNotEmpty(hexStr) ? StringUtils.substring(hexStr, 0, 50) : "");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误日志上下文对象
|
||||
*/
|
||||
private static class ErrorLogContext {
|
||||
private final String serialNumber;
|
||||
private final String sourceData;
|
||||
private final String errorMsg;
|
||||
private final Integer logType;
|
||||
private final String identity;
|
||||
private final Long productId;
|
||||
|
||||
public ErrorLogContext(String serialNumber, String sourceData, String errorMsg,
|
||||
Integer logType, String identity, Long productId) {
|
||||
this.serialNumber = serialNumber;
|
||||
this.sourceData = sourceData;
|
||||
this.errorMsg = errorMsg;
|
||||
this.logType = logType;
|
||||
this.identity = identity;
|
||||
this.productId = productId;
|
||||
}
|
||||
|
||||
public String getSerialNumber() {
|
||||
return serialNumber;
|
||||
}
|
||||
|
||||
public String getSourceData() {
|
||||
return sourceData;
|
||||
}
|
||||
|
||||
public String getErrorMsg() {
|
||||
return errorMsg;
|
||||
}
|
||||
|
||||
public Integer getLogType() {
|
||||
return logType;
|
||||
}
|
||||
|
||||
public String getIdentity() {
|
||||
return identity;
|
||||
}
|
||||
|
||||
public Long getProductId() {
|
||||
return productId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -21,12 +21,12 @@ public class DeviceOtherMsgConsumer {
|
||||
private DeviceOtherMsgHandler otherMsgHandler;
|
||||
|
||||
@Async(FastBeeConstant.TASK.DEVICE_OTHER_TASK)
|
||||
public void consume(DeviceReportBo bo){
|
||||
public void consume(DeviceReportBo bo) {
|
||||
try {
|
||||
//处理emq订阅的非 property/post 属性上报的消息 ,因为其他消息量小,放在一起处理
|
||||
//处理emq订阅的非 property/post 属性上报的消息 ,因为其他消息量小,放在一起处理
|
||||
otherMsgHandler.messageHandler(bo);
|
||||
}catch (Exception e){
|
||||
log.error("=>设备其他消息处理出错",e);
|
||||
} catch (Exception e) {
|
||||
log.error("=>设备其他消息处理出错", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -55,6 +55,8 @@ import java.util.stream.Collectors;
|
||||
public class DevicePropFetchConsumer {
|
||||
|
||||
|
||||
//锁集合
|
||||
private final ConcurrentHashMap<String, Lock> taskLocks = new ConcurrentHashMap<>();
|
||||
@Autowired
|
||||
private PubMqttClient pubMqttClient;
|
||||
@Autowired
|
||||
@ -71,11 +73,8 @@ public class DevicePropFetchConsumer {
|
||||
private ISessionStore sessionStore;
|
||||
@Resource
|
||||
private IModbusParamsService modbusParamsService;
|
||||
|
||||
@Value("${server.broker.enabled}")
|
||||
private Boolean enabled;
|
||||
//锁集合
|
||||
private final ConcurrentHashMap<String, Lock> taskLocks = new ConcurrentHashMap<>();
|
||||
|
||||
@Async(FastBeeConstant.TASK.DEVICE_FETCH_PROP_TASK)
|
||||
public void consume(ModbusPollJob job) {
|
||||
@ -83,7 +82,7 @@ public class DevicePropFetchConsumer {
|
||||
DeviceJob deviceJob = job.getDeviceJob();
|
||||
// type 1:手动下发 2:定时任务执行
|
||||
ModbusPollMsg task = type == 1 ? job.getPollMsg() : getCommandList(deviceJob);
|
||||
if (CollectionUtils.isEmpty(task.getCommandList()))return;
|
||||
if (CollectionUtils.isEmpty(task.getCommandList())) return;
|
||||
String serialNumber = task.getSerialNumber();
|
||||
//获取一个线程锁
|
||||
Lock lock = taskLocks.computeIfAbsent(serialNumber, k -> new ReentrantLock());
|
||||
@ -132,21 +131,21 @@ public class DevicePropFetchConsumer {
|
||||
modbusJob.setJobId(jobId);
|
||||
modbusJob.setStatus("0");
|
||||
List<ModbusJob> modbusJobList = modbusJobService.selectModbusJobList(modbusJob);
|
||||
if (CollectionUtils.isEmpty(modbusJobList))return modbusPollMsg;
|
||||
if (CollectionUtils.isEmpty(modbusJobList)) return modbusPollMsg;
|
||||
//处理子设备情况
|
||||
handleSubDeviceStatus(modbusJobList);
|
||||
List<String> commandList = modbusJobList.stream().map(ModbusJob::getCommand).collect(Collectors.toList());
|
||||
|
||||
|
||||
// 检查是否有设备上电触发任务(cycleType=3)
|
||||
boolean hasPowerOnTrigger = modbusJobList.stream()
|
||||
.anyMatch(job -> job.getCycleType() != null && job.getCycleType() == 3);
|
||||
|
||||
|
||||
// modbus-tcp 重新处理事务标识符
|
||||
String subSerialNumber = modbusJobList.get(0).getSubSerialNumber();
|
||||
String tcpKey = RedisKeyBuilder.buildModbusTcpCacheKey(subSerialNumber);
|
||||
String tcpObject = redisCache.getStrCacheObject(tcpKey);
|
||||
List<String> tcpCommandList = new ArrayList<>();
|
||||
|
||||
|
||||
// 如果是设备上电触发任务(cycleType=3),跳过事务ID处理,直接使用原始指令
|
||||
if (hasPowerOnTrigger) {
|
||||
log.info("检测到设备上电触发任务(cycleType=3),跳过事务ID处理,使用原始指令");
|
||||
@ -179,8 +178,8 @@ public class DevicePropFetchConsumer {
|
||||
DeviceStatusVO deviceStatusVO = deviceService.selectDeviceStatusAndTransportStatus(modbusPollMsg.getSerialNumber());
|
||||
modbusPollMsg.setTransport(deviceStatusVO.getTransport());
|
||||
Session session = sessionStore.getSession(modbusPollMsg.getSerialNumber());
|
||||
if (enabled && Objects.isNull(session)){
|
||||
log.info("设备:[{}],不在线",modbusPollMsg.getSerialNumber());
|
||||
if (enabled && Objects.isNull(session)) {
|
||||
log.info("设备:[{}],不在线", modbusPollMsg.getSerialNumber());
|
||||
return modbusPollMsg;
|
||||
}
|
||||
log.info("执行modbus轮询指令:[{}]", JSON.toJSONString(commandList));
|
||||
@ -190,30 +189,30 @@ public class DevicePropFetchConsumer {
|
||||
/**
|
||||
* 处理子设备根据设备数据定时更新状态
|
||||
*/
|
||||
public void handleSubDeviceStatus(List<ModbusJob> modbusJobList){
|
||||
public void handleSubDeviceStatus(List<ModbusJob> modbusJobList) {
|
||||
for (ModbusJob modbusJob : modbusJobList) {
|
||||
String subSerialNumber = modbusJob.getSubSerialNumber();
|
||||
Session session = sessionStore.getSession(subSerialNumber);
|
||||
if (Objects.isNull(session))continue;
|
||||
if (Objects.isNull(session)) continue;
|
||||
//如果是网关子设备,则检测子设备是否在特定时间内有数据上报
|
||||
if (modbusJob.getDeviceType() == DeviceType.SUB_GATEWAY.getCode()){
|
||||
if (modbusJob.getDeviceType() == DeviceType.SUB_GATEWAY.getCode()) {
|
||||
long deterTime = 300L; //这里默认使用5分钟,如果轮询时间大于5分钟,请在配置参数设置更长时间
|
||||
ModbusParams params = modbusParamsService.getModbusParamsByDeviceId(modbusJob.getSubDeviceId());
|
||||
if (!Objects.isNull(params)){
|
||||
if (!Objects.isNull(params)) {
|
||||
deterTime = Long.parseLong(params.getDeterTimer());
|
||||
}
|
||||
|
||||
long lastAccessTime = session.getLastAccessTime();
|
||||
//如果现在的时间 - 最后访问时间 > 判断时间则更新为离线
|
||||
long time = (System.currentTimeMillis() - lastAccessTime - 20) / 1000;
|
||||
if (time > deterTime){
|
||||
if (time > deterTime) {
|
||||
//处理设备离线
|
||||
DeviceStatusBo statusBo = DeviceStatusBo.builder().status(DeviceStatus.OFFLINE)
|
||||
.serialNumber(subSerialNumber)
|
||||
.timestamp(DateUtils.getNowDate()).build();
|
||||
MessageProducer.sendStatusMsg(statusBo);
|
||||
sessionStore.cleanSession(subSerialNumber);
|
||||
log.info("设备[{}],超过:[{}],未上报数据,更新为离线",subSerialNumber,deterTime);
|
||||
log.info("设备[{}],超过:[{}],未上报数据,更新为离线", subSerialNumber, deterTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ public class DeviceStatusConsumer {
|
||||
try {
|
||||
List<DeviceStatusBo> list = new ArrayList<>();
|
||||
List<SubDeviceBo> subDeviceList = subGatewayService.getSubDeviceListByGw(bo.getSerialNumber());
|
||||
if (!CollectionUtils.isEmpty(subDeviceList) && bo.getStatus()== DeviceStatus.OFFLINE){
|
||||
if (!CollectionUtils.isEmpty(subDeviceList) && bo.getStatus() == DeviceStatus.OFFLINE) {
|
||||
for (SubDeviceBo subDeviceBo : subDeviceList) {
|
||||
DeviceStatusBo deviceStatusBo = new DeviceStatusBo();
|
||||
BeanUtils.copyProperties(bo, deviceStatusBo);
|
||||
|
||||
@ -20,12 +20,12 @@ public class DeviceTestConsumer {
|
||||
private IDeviceTestService testHandler;
|
||||
|
||||
@Async(FastBeeConstant.TASK.DEVICE_TEST_TASK)
|
||||
public void consume(DeviceTestReportBo bo){
|
||||
public void consume(DeviceTestReportBo bo) {
|
||||
try {
|
||||
//处理emq订阅的非 property/post 属性上报的消息 ,因为其他消息量小,放在一起处理
|
||||
testHandler.messageHandler(bo);
|
||||
}catch (Exception e){
|
||||
log.error("=>设备其他消息处理出错",e);
|
||||
} catch (Exception e) {
|
||||
log.error("=>设备其他消息处理出错", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,6 +64,6 @@ public class subscribeCallback implements IMqttMessageListener {
|
||||
.serverType(ServerType.MQTT)
|
||||
.build();
|
||||
/*将mqtt的消息发送至MQ队列处理消息 ,减轻mqtt客户端消息压力*/
|
||||
emqxMessageSerice.sendEmqxMessage(name,reportBo);
|
||||
emqxMessageSerice.sendEmqxMessage(name, reportBo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,12 +4,12 @@ import com.fastbee.common.constant.Constants;
|
||||
import com.fastbee.common.constant.ScheduleConstants;
|
||||
import com.fastbee.common.utils.ExceptionUtil;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.common.utils.TraceIdUtils;
|
||||
import com.fastbee.common.utils.bean.BeanUtils;
|
||||
import com.fastbee.common.utils.spring.SpringUtils;
|
||||
import com.fastbee.iot.domain.DeviceJob;
|
||||
import com.fastbee.quartz.domain.SysJobLog;
|
||||
import com.fastbee.quartz.service.ISysJobLogService;
|
||||
import com.fastbee.common.utils.TraceIdUtils;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
@ -23,8 +23,7 @@ import java.util.Date;
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public abstract class DeviceAbstractQuartzJob implements Job
|
||||
{
|
||||
public abstract class DeviceAbstractQuartzJob implements Job {
|
||||
private static final Logger log = LoggerFactory.getLogger(DeviceAbstractQuartzJob.class);
|
||||
|
||||
/**
|
||||
@ -33,21 +32,16 @@ public abstract class DeviceAbstractQuartzJob implements Job
|
||||
private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();
|
||||
|
||||
@Override
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException
|
||||
{
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException {
|
||||
DeviceJob deviceJob = new DeviceJob();
|
||||
BeanUtils.copyBeanProp(deviceJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));
|
||||
try
|
||||
{
|
||||
try {
|
||||
before(context, deviceJob);
|
||||
if (deviceJob != null)
|
||||
{
|
||||
if (deviceJob != null) {
|
||||
doExecute(context, deviceJob);
|
||||
}
|
||||
after(context, deviceJob, null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
} catch (Exception e) {
|
||||
log.error("任务执行异常 - :", e);
|
||||
after(context, deviceJob, e);
|
||||
}
|
||||
@ -56,44 +50,42 @@ public abstract class DeviceAbstractQuartzJob implements Job
|
||||
/**
|
||||
* 执行前
|
||||
*
|
||||
* @param context 工作执行上下文对象
|
||||
* @param context 工作执行上下文对象
|
||||
* @param deviceJob 系统计划任务
|
||||
*/
|
||||
protected void before(JobExecutionContext context, DeviceJob deviceJob)
|
||||
{
|
||||
protected void before(JobExecutionContext context, DeviceJob deviceJob) {
|
||||
threadLocal.set(new Date());
|
||||
|
||||
|
||||
// 为设备定时任务生成TraceId,使用统一的生成逻辑
|
||||
TraceIdUtils.generateTraceId();
|
||||
|
||||
|
||||
log.info("设备定时任务开始执行: {} - {}", deviceJob.getJobName(), deviceJob.getJobGroup());
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行后
|
||||
*
|
||||
* @param context 工作执行上下文对象
|
||||
* @param context 工作执行上下文对象
|
||||
* @param deviceJob 系统计划任务
|
||||
*/
|
||||
protected void after(JobExecutionContext context, DeviceJob deviceJob, Exception e)
|
||||
{
|
||||
protected void after(JobExecutionContext context, DeviceJob deviceJob, Exception e) {
|
||||
Date startTime = threadLocal.get();
|
||||
threadLocal.remove();
|
||||
|
||||
final SysJobLog sysJobLog = new SysJobLog();
|
||||
sysJobLog.setJobName(deviceJob.getJobName());
|
||||
sysJobLog.setJobGroup(deviceJob.getJobGroup());
|
||||
|
||||
|
||||
// 设置 invokeTarget,确保不为空(数据库字段是 NOT NULL)
|
||||
String invokeTarget = deviceJob.getDeviceName();
|
||||
if (StringUtils.isEmpty(invokeTarget)) {
|
||||
// 如果设备名称为空,使用设备编号或任务名称作为默认值
|
||||
invokeTarget = StringUtils.isNotEmpty(deviceJob.getSerialNumber())
|
||||
? deviceJob.getSerialNumber()
|
||||
: deviceJob.getJobName();
|
||||
invokeTarget = StringUtils.isNotEmpty(deviceJob.getSerialNumber())
|
||||
? deviceJob.getSerialNumber()
|
||||
: deviceJob.getJobName();
|
||||
}
|
||||
sysJobLog.setInvokeTarget(invokeTarget);
|
||||
|
||||
|
||||
// 确保 startTime 不为 null
|
||||
if (startTime == null) {
|
||||
startTime = new Date();
|
||||
@ -103,30 +95,27 @@ public abstract class DeviceAbstractQuartzJob implements Job
|
||||
sysJobLog.setStopTime(stopTime);
|
||||
long runMs = stopTime.getTime() - startTime.getTime();
|
||||
sysJobLog.setJobMessage(sysJobLog.getJobName() + " 总共耗时:" + runMs + "毫秒");
|
||||
if (e != null)
|
||||
{
|
||||
if (e != null) {
|
||||
sysJobLog.setStatus(Constants.FAIL);
|
||||
String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000);
|
||||
sysJobLog.setExceptionInfo(errorMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
sysJobLog.setStatus(Constants.SUCCESS);
|
||||
}
|
||||
|
||||
// 写入数据库当中
|
||||
SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog);
|
||||
|
||||
|
||||
// 清除TraceId,避免内存泄漏
|
||||
TraceIdUtils.clearTraceId();
|
||||
|
||||
|
||||
log.info("设备定时任务执行完成: {} - {}, 耗时: {}ms", deviceJob.getJobName(), deviceJob.getJobGroup(), runMs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行方法,由子类重载
|
||||
*
|
||||
* @param context 工作执行上下文对象
|
||||
* @param context 工作执行上下文对象
|
||||
* @param deviceJob 系统计划任务
|
||||
* @throws Exception 执行过程中的异常
|
||||
*/
|
||||
|
||||
@ -8,14 +8,11 @@ import org.quartz.JobExecutionContext;
|
||||
* 定时任务处理(禁止并发执行)
|
||||
*
|
||||
* @author ruoyi
|
||||
*
|
||||
*/
|
||||
@DisallowConcurrentExecution
|
||||
public class DeviceDisallowConcurrentExecution extends DeviceAbstractQuartzJob
|
||||
{
|
||||
public class DeviceDisallowConcurrentExecution extends DeviceAbstractQuartzJob {
|
||||
@Override
|
||||
protected void doExecute(JobExecutionContext context, DeviceJob deviceJob) throws Exception
|
||||
{
|
||||
protected void doExecute(JobExecutionContext context, DeviceJob deviceJob) throws Exception {
|
||||
DeviceJobInvoke.invokeMethod(deviceJob);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,13 +7,10 @@ import org.quartz.JobExecutionContext;
|
||||
* 定时任务处理(允许并发执行)
|
||||
*
|
||||
* @author ruoyi
|
||||
*
|
||||
*/
|
||||
public class DeviceJobExecution extends DeviceAbstractQuartzJob
|
||||
{
|
||||
public class DeviceJobExecution extends DeviceAbstractQuartzJob {
|
||||
@Override
|
||||
protected void doExecute(JobExecutionContext context, DeviceJob deviceJob) throws Exception
|
||||
{
|
||||
protected void doExecute(JobExecutionContext context, DeviceJob deviceJob) throws Exception {
|
||||
DeviceJobInvoke.invokeMethod(deviceJob);
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,6 +36,7 @@ public class DeviceJobInvoke {
|
||||
private static FlowLogExecutor flowExecutor = SpringUtils.getBean(FlowLogExecutor.class);
|
||||
|
||||
private static IDataHandler dataHandler = SpringUtils.getBean(IDataHandler.class);
|
||||
|
||||
/**
|
||||
* 执行方法
|
||||
*
|
||||
|
||||
@ -10,18 +10,15 @@ import org.quartz.*;
|
||||
* 定时任务工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*
|
||||
*/
|
||||
public class DeviceScheduleUtils
|
||||
{
|
||||
public class DeviceScheduleUtils {
|
||||
/**
|
||||
* 得到quartz任务类
|
||||
*
|
||||
* @param deviceJob 执行计划
|
||||
* @return 具体执行任务类
|
||||
*/
|
||||
private static Class<? extends Job> getQuartzJobClass(DeviceJob deviceJob)
|
||||
{
|
||||
private static Class<? extends Job> getQuartzJobClass(DeviceJob deviceJob) {
|
||||
boolean isConcurrent = "0".equals(deviceJob.getConcurrent());
|
||||
return isConcurrent ? DeviceJobExecution.class : DeviceDisallowConcurrentExecution.class;
|
||||
}
|
||||
@ -29,24 +26,21 @@ public class DeviceScheduleUtils
|
||||
/**
|
||||
* 构建任务触发对象
|
||||
*/
|
||||
public static TriggerKey getTriggerKey(Long jobId, String jobGroup)
|
||||
{
|
||||
public static TriggerKey getTriggerKey(Long jobId, String jobGroup) {
|
||||
return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建任务键对象
|
||||
*/
|
||||
public static JobKey getJobKey(Long jobId, String jobGroup)
|
||||
{
|
||||
public static JobKey getJobKey(Long jobId, String jobGroup) {
|
||||
return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建定时任务
|
||||
*/
|
||||
public static void createScheduleJob(Scheduler scheduler, DeviceJob job) throws SchedulerException, TaskException
|
||||
{
|
||||
public static void createScheduleJob(Scheduler scheduler, DeviceJob job) throws SchedulerException, TaskException {
|
||||
Class<? extends Job> jobClass = getQuartzJobClass(job);
|
||||
// 1.创建任务
|
||||
Long jobId = job.getJobId();
|
||||
@ -65,8 +59,7 @@ public class DeviceScheduleUtils
|
||||
jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
|
||||
|
||||
// 判断是否存在
|
||||
if (scheduler.checkExists(getJobKey(jobId, jobGroup)))
|
||||
{
|
||||
if (scheduler.checkExists(getJobKey(jobId, jobGroup))) {
|
||||
// 防止创建时存在数据问题 先移除,然后在执行创建操作
|
||||
scheduler.deleteJob(getJobKey(jobId, jobGroup));
|
||||
}
|
||||
@ -75,8 +68,7 @@ public class DeviceScheduleUtils
|
||||
scheduler.scheduleJob(jobDetail, trigger);
|
||||
|
||||
// 暂停任务
|
||||
if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
|
||||
{
|
||||
if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) {
|
||||
scheduler.pauseJob(DeviceScheduleUtils.getJobKey(jobId, jobGroup));
|
||||
}
|
||||
}
|
||||
@ -85,10 +77,8 @@ public class DeviceScheduleUtils
|
||||
* 设置定时任务策略
|
||||
*/
|
||||
public static CronScheduleBuilder handleCronScheduleMisfirePolicy(DeviceJob job, CronScheduleBuilder cb)
|
||||
throws TaskException
|
||||
{
|
||||
switch (job.getMisfirePolicy())
|
||||
{
|
||||
throws TaskException {
|
||||
switch (job.getMisfirePolicy()) {
|
||||
case ScheduleConstants.MISFIRE_DEFAULT:
|
||||
return cb;
|
||||
case ScheduleConstants.MISFIRE_IGNORE_MISFIRES:
|
||||
|
||||
@ -17,6 +17,7 @@ import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 定时同步设备状态 -- netty版本mqtt使用
|
||||
*
|
||||
* @author gsb
|
||||
* @date 2024/4/11 10:33
|
||||
*/
|
||||
@ -32,8 +33,8 @@ public class SyncDeviceStatusJob {
|
||||
|
||||
/**
|
||||
* 定期同步设备状态
|
||||
* 1.将异常在线设备变更为离线状态
|
||||
* 2.将离线设备但实际在线设备变更为在线
|
||||
* 1.将异常在线设备变更为离线状态
|
||||
* 2.将离线设备但实际在线设备变更为在线
|
||||
*/
|
||||
public void syncDeviceStatus() {
|
||||
if (enabled) {
|
||||
|
||||
@ -22,12 +22,12 @@ public class DeviceOtherListen {
|
||||
private DeviceOtherMsgConsumer otherMsgConsumer;
|
||||
|
||||
@Async(FastBeeConstant.TASK.DEVICE_OTHER_TASK)
|
||||
public void listen(){
|
||||
while (true){
|
||||
public void listen() {
|
||||
while (true) {
|
||||
try {
|
||||
DeviceReportBo reportBo = DeviceOtherQueue.take();
|
||||
otherMsgConsumer.consume(reportBo);
|
||||
}catch (Exception e){
|
||||
} catch (Exception e) {
|
||||
log.error("=>emq数据转发异常");
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 设备状态监听
|
||||
*
|
||||
* @author bill
|
||||
*/
|
||||
@Slf4j
|
||||
|
||||
@ -21,13 +21,13 @@ public class DeviceTestListen {
|
||||
private DeviceTestConsumer deviceTestConsumer;
|
||||
|
||||
@Async(FastBeeConstant.TASK.DEVICE_TEST_TASK)
|
||||
public void listen(){
|
||||
while (true){
|
||||
public void listen() {
|
||||
while (true) {
|
||||
try {
|
||||
DeviceTestReportBo take = DeviceTestQueue.take();
|
||||
|
||||
deviceTestConsumer.consume(take);
|
||||
}catch (Exception e){
|
||||
} catch (Exception e) {
|
||||
log.error("=>emq数据转发异常");
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ import java.util.Date;
|
||||
|
||||
/**
|
||||
* OTA升级监听
|
||||
*
|
||||
* @author bill
|
||||
*/
|
||||
@Slf4j
|
||||
@ -41,18 +42,18 @@ public class UpGradeListener implements ApplicationRunner {
|
||||
|
||||
|
||||
@Async(FastBeeConstant.TASK.DELAY_UPGRADE_TASK)
|
||||
public void listen(){
|
||||
while (true){
|
||||
public void listen() {
|
||||
while (true) {
|
||||
try {
|
||||
OtaUpgradeDelayTask task = DelayUpgradeQueue.task();
|
||||
if (StringUtils.isNotNull(task)){
|
||||
if (StringUtils.isNotNull(task)) {
|
||||
Date startTime = task.getStartTime();
|
||||
otaUpgradeService.upgrade(task);
|
||||
log.info("=>开始OTA升级时间{}",startTime);
|
||||
log.info("=>开始OTA升级时间{}", startTime);
|
||||
}
|
||||
continue;
|
||||
}catch (Exception e){
|
||||
log.error("=>OTA升级监听异常",e);
|
||||
} catch (Exception e) {
|
||||
log.error("=>OTA升级监听异常", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -68,14 +69,14 @@ public class UpGradeListener implements ApplicationRunner {
|
||||
/**
|
||||
* 切换菜单中Emqx控制台和netty管理
|
||||
*/
|
||||
public void updateMenu(){
|
||||
public void updateMenu() {
|
||||
SysMenu sysMenu = new SysMenu();
|
||||
if (enabled){
|
||||
if (enabled) {
|
||||
sysMenu.setMenuId(2104L);
|
||||
sysMenu.setVisible("1");
|
||||
menuService.updateMenu(sysMenu);
|
||||
sysMenu.setMenuId(3031L);
|
||||
}else {
|
||||
} else {
|
||||
sysMenu.setMenuId(3031L);
|
||||
sysMenu.setVisible("1");
|
||||
menuService.updateMenu(sysMenu);
|
||||
|
||||
@ -45,52 +45,37 @@ import static java.util.regex.Pattern.compile;
|
||||
@Slf4j
|
||||
public class SceneContext {
|
||||
private static Logger scene_logger = LoggerFactory.getLogger("scene");
|
||||
private static IFunctionInvoke functionInvoke = SpringUtils.getBean(IFunctionInvoke.class);
|
||||
private static IDeviceService deviceService = SpringUtils.getBean(IDeviceService.class);
|
||||
private static IAlertService alertService = SpringUtils.getBean(IAlertService.class);
|
||||
private static NotifySendService notifySendService = SpringUtils.getBean(NotifySendService.class);
|
||||
private static RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
|
||||
private static IAlertLogService alertLogService = SpringUtils.getBean(IAlertLogService.class);
|
||||
private static IDeviceUserService deviceUserService = SpringUtils.getBean(IDeviceUserService.class);
|
||||
private static ISceneService sceneService = SpringUtils.getBean(ISceneService.class);
|
||||
private static IRuleEngine ruleService = SpringUtils.getBean(IRuleEngine.class);
|
||||
private static IDeviceAlertUserService deviceAlertUserService = SpringUtils.getBean(IDeviceAlertUserService.class);
|
||||
/**
|
||||
* 上报信息的设备编号
|
||||
*/
|
||||
private String deviceNum;
|
||||
|
||||
/**
|
||||
* 上报信息的设备所属产品ID
|
||||
*/
|
||||
private Long productId;
|
||||
|
||||
/**
|
||||
* 上报信息的设备信息类型 1=属性, 2=功能,3=事件,4=设备升级,5=设备上线,6=设备下线
|
||||
*/
|
||||
private int type;
|
||||
|
||||
/**
|
||||
* 上报的物模型集合
|
||||
*/
|
||||
private List<ThingsModelSimpleItem> thingsModelSimpleItems;
|
||||
|
||||
/**
|
||||
* 触发成功的物模型集合,保留给告警记录
|
||||
*/
|
||||
private List<SceneThingsModelItem> sceneThingsModelItems;
|
||||
|
||||
|
||||
private static IFunctionInvoke functionInvoke = SpringUtils.getBean(IFunctionInvoke.class);
|
||||
|
||||
private static IDeviceService deviceService = SpringUtils.getBean(IDeviceService.class);
|
||||
|
||||
private static IAlertService alertService = SpringUtils.getBean(IAlertService.class);
|
||||
|
||||
private static NotifySendService notifySendService = SpringUtils.getBean(NotifySendService.class);
|
||||
|
||||
private static RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
|
||||
|
||||
private static IAlertLogService alertLogService = SpringUtils.getBean(IAlertLogService.class);
|
||||
|
||||
private static IDeviceUserService deviceUserService = SpringUtils.getBean(IDeviceUserService.class);
|
||||
|
||||
private static ISceneService sceneService = SpringUtils.getBean(ISceneService.class);
|
||||
|
||||
private static IRuleEngine ruleService = SpringUtils.getBean(IRuleEngine.class);
|
||||
|
||||
private static IDeviceAlertUserService deviceAlertUserService = SpringUtils.getBean(IDeviceAlertUserService.class);
|
||||
|
||||
public SceneContext(String deviceNum, Long productId, int type, List<ThingsModelSimpleItem> thingsModelSimpleItems) {
|
||||
this.deviceNum = deviceNum;
|
||||
this.productId = productId;
|
||||
|
||||
@ -5,6 +5,7 @@ import com.fastbee.common.core.mq.message.ReportDataBo;
|
||||
|
||||
/**
|
||||
* 客户端上报数据处理方法集合
|
||||
*
|
||||
* @author bill
|
||||
*/
|
||||
public interface IDataHandler {
|
||||
@ -26,12 +27,14 @@ public interface IDataHandler {
|
||||
|
||||
/**
|
||||
* 上报设备信息
|
||||
*
|
||||
* @param bo 上报数据模型
|
||||
*/
|
||||
public void reportDevice(ReportDataBo bo);
|
||||
|
||||
/**
|
||||
* 计算场景变量的值
|
||||
*
|
||||
* @param id 主键id
|
||||
* @return java.lang.String
|
||||
*/
|
||||
@ -39,6 +42,7 @@ public interface IDataHandler {
|
||||
|
||||
/**
|
||||
* 场景变量指令下发
|
||||
*
|
||||
* @param reqDto 下发类
|
||||
* @return void
|
||||
*/
|
||||
|
||||
@ -21,6 +21,7 @@ public interface IDeviceMessageService {
|
||||
|
||||
/**
|
||||
* 变量读取
|
||||
*
|
||||
* @param readVO
|
||||
*/
|
||||
public void readVariableValue(VariableReadVO readVO);
|
||||
|
||||
@ -6,6 +6,7 @@ import com.fastbee.protocol.base.protocol.IProtocol;
|
||||
|
||||
/**
|
||||
* 处理设备上报数据解析
|
||||
*
|
||||
* @author gsb
|
||||
* @date 2022/10/10 13:48
|
||||
*/
|
||||
@ -13,18 +14,21 @@ public interface IDeviceReportMessageService {
|
||||
|
||||
/**
|
||||
* 处理设备主动上报数据
|
||||
*
|
||||
* @param bo
|
||||
*/
|
||||
public void parseReportMsg(DeviceReportBo bo);
|
||||
|
||||
/**
|
||||
* 处理设备普通消息回调
|
||||
*
|
||||
* @param bo
|
||||
*/
|
||||
public void parseReplyMsg(DeviceReportBo bo);
|
||||
|
||||
/**
|
||||
* 处理设备OTA升级
|
||||
*
|
||||
* @param bo
|
||||
*/
|
||||
public void parseOTAUpdateReply(DeviceReportBo bo);
|
||||
@ -32,6 +36,7 @@ public interface IDeviceReportMessageService {
|
||||
|
||||
/**
|
||||
* 构建消息
|
||||
*
|
||||
* @param bo
|
||||
*/
|
||||
public DeviceStatusVO buildReport(DeviceReportBo bo);
|
||||
|
||||
@ -15,8 +15,7 @@ import java.util.List;
|
||||
* @author kerwincui
|
||||
* @date 2024-08-18
|
||||
*/
|
||||
public interface IFirmwareTaskDetailService extends IService<FirmwareTaskDetail>
|
||||
{
|
||||
public interface IFirmwareTaskDetailService extends IService<FirmwareTaskDetail> {
|
||||
|
||||
/**
|
||||
* 查询固件升级任务详细对象列表
|
||||
@ -29,6 +28,7 @@ public interface IFirmwareTaskDetailService extends IService<FirmwareTaskDetail>
|
||||
|
||||
/**
|
||||
* 查询固件升级任务详细
|
||||
*
|
||||
* @param taskId
|
||||
* @param serialNumber
|
||||
* @return
|
||||
@ -36,9 +36,9 @@ public interface IFirmwareTaskDetailService extends IService<FirmwareTaskDetail>
|
||||
public FirmwareTaskDetail selectFirmwareTaskDetailByTaskIdAndSerialNumber(Long taskId, String serialNumber);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 更新升级状态
|
||||
*
|
||||
* @param taskId
|
||||
* @param serialNumber
|
||||
* @param otaUpgrade
|
||||
|
||||
@ -13,8 +13,7 @@ import java.util.List;
|
||||
* @author kerwincui
|
||||
* @date 2024-08-18
|
||||
*/
|
||||
public interface IFirmwareTaskService extends IService<FirmwareTask>
|
||||
{
|
||||
public interface IFirmwareTaskService extends IService<FirmwareTask> {
|
||||
|
||||
/**
|
||||
* 查询固件升级任务对象列表
|
||||
@ -35,6 +34,7 @@ public interface IFirmwareTaskService extends IService<FirmwareTask>
|
||||
|
||||
/**
|
||||
* OTA升级
|
||||
*
|
||||
* @param task
|
||||
*/
|
||||
void upgrade(OtaUpgradeDelayTask task);
|
||||
|
||||
@ -5,6 +5,7 @@ import com.fastbee.common.core.mq.InvokeReqDto;
|
||||
|
||||
/**
|
||||
* 设备指令下发接口
|
||||
*
|
||||
* @author gsb
|
||||
* @date 2022/12/5 11:03
|
||||
*/
|
||||
@ -12,6 +13,7 @@ public interface IFunctionInvoke {
|
||||
|
||||
/**
|
||||
* 服务调用,等待设备响应
|
||||
*
|
||||
* @param reqDto 服务下发对象
|
||||
* @return 数据结果
|
||||
*/
|
||||
@ -19,6 +21,7 @@ public interface IFunctionInvoke {
|
||||
|
||||
/**
|
||||
* 服务调用,设备不响应
|
||||
*
|
||||
* @param reqDto 服务下发对象
|
||||
* @return 消息id messageId
|
||||
*/
|
||||
|
||||
@ -2,6 +2,7 @@ package com.fastbee.iot.data.service;
|
||||
|
||||
/**
|
||||
* 设备消息推送mq
|
||||
*
|
||||
* @author bill
|
||||
*/
|
||||
public interface IMessagePublishService {
|
||||
@ -9,9 +10,10 @@ public interface IMessagePublishService {
|
||||
|
||||
/**
|
||||
* 发布消息到mq
|
||||
*
|
||||
* @param message 设备消息
|
||||
* @param channel 推送channel
|
||||
*/
|
||||
public void publish(Object message,String channel);
|
||||
public void publish(Object message, String channel);
|
||||
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ public interface IMqttMessagePublish {
|
||||
* 推送设备状态
|
||||
*
|
||||
* @param device 设备
|
||||
* @param status 状态
|
||||
* @param status 状态
|
||||
*/
|
||||
public void pushDeviceStatus(Device device, DeviceStatus status);
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ public interface IOtaTaskUpgradeService {
|
||||
|
||||
/**
|
||||
* 固件升级异步方法
|
||||
*
|
||||
* @param taskId
|
||||
* @param serialNumber
|
||||
* @param firmware
|
||||
|
||||
@ -4,12 +4,14 @@ import com.fastbee.common.core.mq.ota.OtaUpgradeDelayTask;
|
||||
|
||||
/**
|
||||
* OTA升级
|
||||
*
|
||||
* @author bill
|
||||
*/
|
||||
public interface IOtaUpgradeService {
|
||||
|
||||
/**
|
||||
* OTA延迟升级任务发送
|
||||
*
|
||||
* @param task
|
||||
*/
|
||||
public void upgrade(OtaUpgradeDelayTask task);
|
||||
|
||||
@ -6,6 +6,7 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
/**
|
||||
* 规则引擎处理数据方法集合
|
||||
*
|
||||
* @author bill
|
||||
*/
|
||||
public interface IRuleEngine {
|
||||
@ -15,6 +16,8 @@ public interface IRuleEngine {
|
||||
* @param bo 上报数据模型
|
||||
*/
|
||||
public void ruleMatch(ReportDataBo bo);
|
||||
|
||||
public void addCheckTask(String key, ScheduledExecutorService task);
|
||||
|
||||
public void removeCheckTask(String key);
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ import java.util.*;
|
||||
|
||||
/**
|
||||
* 上报数据处理方法集合
|
||||
*
|
||||
* @author bill
|
||||
*/
|
||||
@Service
|
||||
@ -99,7 +100,7 @@ public class DataHandlerImpl implements IDataHandler {
|
||||
input.setSources(bo.getSources());
|
||||
List<ThingsModelSimpleItem> result = deviceService.reportDeviceThingsModelValue(input, bo.getType(), bo.isShadow());
|
||||
// 只有设备上报进入规则引擎流程
|
||||
if (bo.isRuleEngine() && !bo.getSerialNumber().startsWith("server-")){
|
||||
if (bo.isRuleEngine() && !bo.getSerialNumber().startsWith("server-")) {
|
||||
ruleEngine.ruleMatch(bo);
|
||||
}
|
||||
//发送至前端
|
||||
@ -107,11 +108,11 @@ public class DataHandlerImpl implements IDataHandler {
|
||||
messageBo.setTopic(topicsUtils.buildTopic(bo.getProductId(), bo.getSerialNumber(), TopicType.WS_SERVICE_INVOKE));
|
||||
JSONObject pushObj = new JSONObject();
|
||||
pushObj.put("message", result);
|
||||
pushObj.put("sources",bo.getSources());
|
||||
pushObj.put("sources", bo.getSources());
|
||||
messageBo.setMessage(JSON.toJSONString(pushObj));
|
||||
remoteManager.pushCommon(messageBo);
|
||||
if (!Objects.isNull(bo.getGwDeviceBo())){
|
||||
messageBo.setTopic(topicsUtils.buildTopic(bo.getGwDeviceBo().getProductId(),bo.getGwDeviceBo().getSerialNumber(),TopicType.WS_SERVICE_INVOKE));
|
||||
if (!Objects.isNull(bo.getGwDeviceBo())) {
|
||||
messageBo.setTopic(topicsUtils.buildTopic(bo.getGwDeviceBo().getProductId(), bo.getGwDeviceBo().getSerialNumber(), TopicType.WS_SERVICE_INVOKE));
|
||||
remoteManager.pushCommon(messageBo);
|
||||
}
|
||||
// 上报属性给小度音箱,接入小度音箱后可放开
|
||||
@ -122,7 +123,7 @@ public class DataHandlerImpl implements IDataHandler {
|
||||
// log.error("=>上报属性信息给小度音箱异常", e);
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
log.error("接收属性数据,解析数据时异常 message={}", e.getMessage(),e);
|
||||
log.error("接收属性数据,解析数据时异常 message={}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,7 +161,7 @@ public class DataHandlerImpl implements IDataHandler {
|
||||
//eventLogService.insertEventLog(event);
|
||||
}
|
||||
eventLogService.saveBatch(results);
|
||||
if (bo.isRuleEngine()){
|
||||
if (bo.isRuleEngine()) {
|
||||
ruleEngine.ruleMatch(bo);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@ -255,10 +256,11 @@ public class DataHandlerImpl implements IDataHandler {
|
||||
|
||||
/**
|
||||
* 保存场景变量值
|
||||
*
|
||||
* @param sceneModelTag 变量类
|
||||
* @return void
|
||||
* @param: value 值
|
||||
* @param: now 执行时间
|
||||
* @return void
|
||||
*/
|
||||
private void saveSceneModelTagValue(SceneModelTag sceneModelTag, String value, LocalDateTime now) {
|
||||
// 保存运算型变量值,存缓存
|
||||
|
||||
@ -68,9 +68,9 @@ public class DeviceJob {
|
||||
//更新iot设备状态
|
||||
Device dev = deviceService.selectDeviceBySerialNumber(item.getDeviceSipId());
|
||||
if (dev != null && dev.getStatus() == DeviceStatus.ONLINE.getType()) {
|
||||
log.warn("定时任务:=>设备:{} 已经下线,设备超过{}秒没上线!",item.getDeviceSipId(),timeout);
|
||||
log.warn("定时任务:=>设备:{} 已经下线,设备超过{}秒没上线!", item.getDeviceSipId(), timeout);
|
||||
dev.setStatus(DeviceStatus.OFFLINE.getType());
|
||||
deviceService.updateDeviceStatusAndLocation(dev,"");
|
||||
deviceService.updateDeviceStatusAndLocation(dev, "");
|
||||
DeviceStatusBo bo = DeviceStatusBo.builder()
|
||||
.serialNumber(dev.getSerialNumber())
|
||||
.status(DeviceStatus.OFFLINE)
|
||||
|
||||
@ -29,8 +29,7 @@ import java.util.List;
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
{
|
||||
public class DeviceJobServiceImpl implements IDeviceJobService {
|
||||
@Autowired
|
||||
private Scheduler scheduler;
|
||||
|
||||
@ -45,13 +44,11 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
* 项目启动时,初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据)
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init() throws SchedulerException, TaskException
|
||||
{
|
||||
public void init() throws SchedulerException, TaskException {
|
||||
scheduler.clear();
|
||||
// 设备定时任务
|
||||
List<DeviceJob> jobList = jobMapper.selectJobAll();
|
||||
for (DeviceJob deviceJob : jobList)
|
||||
{
|
||||
for (DeviceJob deviceJob : jobList) {
|
||||
// 跳过设备上电触发任务,它们不需要加入调度器
|
||||
if (!isPowerOnTriggerTask(deviceJob) && StringUtils.isNotEmpty(deviceJob.getCronExpression())) {
|
||||
DeviceScheduleUtils.createScheduleJob(scheduler, deviceJob);
|
||||
@ -60,8 +57,7 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
|
||||
// 系统定时任务
|
||||
List<SysJob> sysJobList = sysJobMapper.selectJobAll();
|
||||
for (SysJob job : sysJobList)
|
||||
{
|
||||
for (SysJob job : sysJobList) {
|
||||
com.fastbee.quartz.util.ScheduleUtils.createScheduleJob(scheduler, job);
|
||||
}
|
||||
}
|
||||
@ -73,8 +69,7 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<DeviceJob> selectJobList(DeviceJob job)
|
||||
{
|
||||
public List<DeviceJob> selectJobList(DeviceJob job) {
|
||||
return jobMapper.selectJobList(job);
|
||||
}
|
||||
|
||||
@ -85,8 +80,7 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
* @return 调度任务对象信息
|
||||
*/
|
||||
@Override
|
||||
public DeviceJob selectJobById(Long jobId)
|
||||
{
|
||||
public DeviceJob selectJobById(Long jobId) {
|
||||
return jobMapper.selectJobById(jobId);
|
||||
}
|
||||
|
||||
@ -97,14 +91,12 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int pauseJob(DeviceJob job) throws SchedulerException
|
||||
{
|
||||
public int pauseJob(DeviceJob job) throws SchedulerException {
|
||||
Long jobId = job.getJobId();
|
||||
String jobGroup = job.getJobGroup();
|
||||
job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
|
||||
int rows = jobMapper.updateJob(job);
|
||||
if (rows > 0)
|
||||
{
|
||||
if (rows > 0) {
|
||||
scheduler.pauseJob(DeviceScheduleUtils.getJobKey(jobId, jobGroup));
|
||||
}
|
||||
return rows;
|
||||
@ -117,14 +109,12 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int resumeJob(DeviceJob job) throws SchedulerException
|
||||
{
|
||||
public int resumeJob(DeviceJob job) throws SchedulerException {
|
||||
Long jobId = job.getJobId();
|
||||
String jobGroup = job.getJobGroup();
|
||||
job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
|
||||
int rows = jobMapper.updateJob(job);
|
||||
if (rows > 0)
|
||||
{
|
||||
if (rows > 0) {
|
||||
scheduler.resumeJob(DeviceScheduleUtils.getJobKey(jobId, jobGroup));
|
||||
}
|
||||
return rows;
|
||||
@ -137,13 +127,11 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int deleteJob(DeviceJob job) throws SchedulerException
|
||||
{
|
||||
public int deleteJob(DeviceJob job) throws SchedulerException {
|
||||
Long jobId = job.getJobId();
|
||||
String jobGroup = job.getJobGroup();
|
||||
int rows = jobMapper.deleteJobById(jobId);
|
||||
if (rows > 0)
|
||||
{
|
||||
if (rows > 0) {
|
||||
scheduler.deleteJob(DeviceScheduleUtils.getJobKey(jobId, jobGroup));
|
||||
}
|
||||
return rows;
|
||||
@ -157,10 +145,8 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteJobByIds(Long[] jobIds) throws SchedulerException
|
||||
{
|
||||
for (Long jobId : jobIds)
|
||||
{
|
||||
public void deleteJobByIds(Long[] jobIds) throws SchedulerException {
|
||||
for (Long jobId : jobIds) {
|
||||
DeviceJob job = jobMapper.selectJobById(jobId);
|
||||
deleteJob(job);
|
||||
}
|
||||
@ -174,14 +160,13 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteJobByDeviceIds(Long[] deviceIds) throws SchedulerException
|
||||
{
|
||||
public void deleteJobByDeviceIds(Long[] deviceIds) throws SchedulerException {
|
||||
// 查出所有job
|
||||
List<DeviceJob> deviceJobs=jobMapper.selectShortJobListByDeviceIds(deviceIds);
|
||||
List<DeviceJob> deviceJobs = jobMapper.selectShortJobListByDeviceIds(deviceIds);
|
||||
// 批量删除job
|
||||
int rows=jobMapper.deleteJobByDeviceIds(deviceIds);
|
||||
int rows = jobMapper.deleteJobByDeviceIds(deviceIds);
|
||||
// 批量删除调度器
|
||||
for(DeviceJob job:deviceJobs){
|
||||
for (DeviceJob job : deviceJobs) {
|
||||
scheduler.deleteJob(DeviceScheduleUtils.getJobKey(job.getJobId(), job.getJobGroup()));
|
||||
}
|
||||
}
|
||||
@ -194,14 +179,13 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteJobByAlertIds(Long[] alertIds) throws SchedulerException
|
||||
{
|
||||
public void deleteJobByAlertIds(Long[] alertIds) throws SchedulerException {
|
||||
// 查出所有job
|
||||
List<DeviceJob> deviceJobs=jobMapper.selectShortJobListByAlertIds(alertIds);
|
||||
List<DeviceJob> deviceJobs = jobMapper.selectShortJobListByAlertIds(alertIds);
|
||||
// 批量删除job
|
||||
int rows=jobMapper.deleteJobByAlertIds(alertIds);
|
||||
int rows = jobMapper.deleteJobByAlertIds(alertIds);
|
||||
// 批量删除调度器
|
||||
for(DeviceJob job:deviceJobs){
|
||||
for (DeviceJob job : deviceJobs) {
|
||||
scheduler.deleteJob(DeviceScheduleUtils.getJobKey(job.getJobId(), job.getJobGroup()));
|
||||
}
|
||||
}
|
||||
@ -214,14 +198,13 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteJobBySceneIds(Long[] sceneIds) throws SchedulerException
|
||||
{
|
||||
public void deleteJobBySceneIds(Long[] sceneIds) throws SchedulerException {
|
||||
// 查出所有job
|
||||
List<DeviceJob> deviceJobs=jobMapper.selectShortJobListBySceneIds(sceneIds);
|
||||
List<DeviceJob> deviceJobs = jobMapper.selectShortJobListBySceneIds(sceneIds);
|
||||
// 批量删除job
|
||||
int rows=jobMapper.deleteJobBySceneIds(sceneIds);
|
||||
int rows = jobMapper.deleteJobBySceneIds(sceneIds);
|
||||
// 批量删除调度器
|
||||
for(DeviceJob job:deviceJobs){
|
||||
for (DeviceJob job : deviceJobs) {
|
||||
scheduler.deleteJob(DeviceScheduleUtils.getJobKey(job.getJobId(), job.getJobGroup()));
|
||||
}
|
||||
}
|
||||
@ -233,16 +216,12 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int changeStatus(DeviceJob job) throws SchedulerException
|
||||
{
|
||||
public int changeStatus(DeviceJob job) throws SchedulerException {
|
||||
int rows = 0;
|
||||
String status = job.getStatus();
|
||||
if (ScheduleConstants.Status.NORMAL.getValue().equals(status))
|
||||
{
|
||||
if (ScheduleConstants.Status.NORMAL.getValue().equals(status)) {
|
||||
rows = resumeJob(job);
|
||||
}
|
||||
else if (ScheduleConstants.Status.PAUSE.getValue().equals(status))
|
||||
{
|
||||
} else if (ScheduleConstants.Status.PAUSE.getValue().equals(status)) {
|
||||
rows = pauseJob(job);
|
||||
}
|
||||
return rows;
|
||||
@ -255,8 +234,7 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void run(DeviceJob job) throws SchedulerException
|
||||
{
|
||||
public void run(DeviceJob job) throws SchedulerException {
|
||||
Long jobId = job.getJobId();
|
||||
String jobGroup = job.getJobGroup();
|
||||
DeviceJob properties = selectJobById(job.getJobId());
|
||||
@ -273,8 +251,7 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int insertJob(DeviceJob deviceJob) throws SchedulerException, TaskException
|
||||
{
|
||||
public int insertJob(DeviceJob deviceJob) throws SchedulerException, TaskException {
|
||||
int rows = jobMapper.insertJob(deviceJob);
|
||||
if (rows > 0) {
|
||||
// 检查是否是设备上电触发任务(通过检查remark或cron表达式)
|
||||
@ -289,6 +266,7 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
|
||||
/**
|
||||
* 检查是否是设备上电触发任务
|
||||
*
|
||||
* @param deviceJob 设备任务
|
||||
* @return true表示是设备上电触发任务
|
||||
*/
|
||||
@ -315,12 +293,10 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int updateJob(DeviceJob deviceJob) throws SchedulerException, TaskException
|
||||
{
|
||||
public int updateJob(DeviceJob deviceJob) throws SchedulerException, TaskException {
|
||||
DeviceJob properties = selectJobById(deviceJob.getJobId());
|
||||
int rows = jobMapper.updateJob(deviceJob);
|
||||
if (rows > 0)
|
||||
{
|
||||
if (rows > 0) {
|
||||
updateSchedulerJob(deviceJob, properties.getJobGroup());
|
||||
}
|
||||
return rows;
|
||||
@ -330,15 +306,13 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
* 更新任务
|
||||
*
|
||||
* @param deviceJob 任务对象
|
||||
* @param jobGroup 任务组名
|
||||
* @param jobGroup 任务组名
|
||||
*/
|
||||
public void updateSchedulerJob(DeviceJob deviceJob, String jobGroup) throws SchedulerException, TaskException
|
||||
{
|
||||
public void updateSchedulerJob(DeviceJob deviceJob, String jobGroup) throws SchedulerException, TaskException {
|
||||
Long jobId = deviceJob.getJobId();
|
||||
// 判断是否存在
|
||||
JobKey jobKey = DeviceScheduleUtils.getJobKey(jobId, jobGroup);
|
||||
if (scheduler.checkExists(jobKey))
|
||||
{
|
||||
if (scheduler.checkExists(jobKey)) {
|
||||
// 防止创建时存在数据问题 先移除,然后在执行创建操作
|
||||
scheduler.deleteJob(jobKey);
|
||||
}
|
||||
@ -356,8 +330,7 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public boolean checkCronExpressionIsValid(String cronExpression)
|
||||
{
|
||||
public boolean checkCronExpressionIsValid(String cronExpression) {
|
||||
return CronUtils.isValid(cronExpression);
|
||||
}
|
||||
|
||||
@ -374,7 +347,7 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
// 批量删除job
|
||||
int rows = jobMapper.deleteJobByJobTypeAndDatasourceIds(datasourceIds, jobType);
|
||||
// 批量删除调度器
|
||||
for(DeviceJob job:deviceJobs){
|
||||
for (DeviceJob job : deviceJobs) {
|
||||
scheduler.deleteJob(DeviceScheduleUtils.getJobKey(job.getJobId(), job.getJobGroup()));
|
||||
}
|
||||
}
|
||||
@ -387,6 +360,7 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
|
||||
/**
|
||||
* 根据条件批量删除定时任务
|
||||
*
|
||||
* @param deviceId
|
||||
* @param jobType
|
||||
*/
|
||||
@ -401,7 +375,7 @@ public class DeviceJobServiceImpl implements IDeviceJobService
|
||||
// 批量删除job
|
||||
jobMapper.deleteJobByJobTypeAndDeviceId(deviceId, jobType);
|
||||
// 批量删除调度器
|
||||
for(DeviceJob job:deviceJobs){
|
||||
for (DeviceJob job : deviceJobs) {
|
||||
scheduler.deleteJob(DeviceScheduleUtils.getJobKey(job.getJobId(), job.getJobGroup()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,12 +87,12 @@ public class DeviceMessageServiceImpl implements IDeviceMessageService {
|
||||
DeviceAndProtocol deviceAndProtocol = deviceService.selectProtocolBySerialNumber(serialNumber);
|
||||
String transport = deviceAndProtocol.getTransport();
|
||||
TopicType type = TopicType.getType(topicName);
|
||||
topicName = topicsUtils.buildTopic(deviceAndProtocol.getProductId(), serialNumber,type);
|
||||
switch (type){
|
||||
topicName = topicsUtils.buildTopic(deviceAndProtocol.getProductId(), serialNumber, type);
|
||||
switch (type) {
|
||||
case FUNCTION_GET:
|
||||
if (transport.equals(ServerType.MQTT.getCode())){
|
||||
if (transport.equals(ServerType.MQTT.getCode())) {
|
||||
mqttClient.publish(0, false, topicName, deviceMessage.getMessage().toString());
|
||||
}else if (transport.equals(ServerType.TCP.getCode())){
|
||||
} else if (transport.equals(ServerType.TCP.getCode())) {
|
||||
//处理TCP下发
|
||||
ModbusPollMsg modbusPollMsg = new ModbusPollMsg();
|
||||
modbusPollMsg.setSerialNumber(serialNumber);
|
||||
@ -102,8 +102,8 @@ public class DeviceMessageServiceImpl implements IDeviceMessageService {
|
||||
modbusPollMsg.setCommandList(commandList);
|
||||
DeviceStatusVO deviceStatusVO = deviceService.selectDeviceStatusAndTransportStatus(modbusPollMsg.getSerialNumber());
|
||||
modbusPollMsg.setTransport(deviceStatusVO.getTransport());
|
||||
if (deviceStatusVO.getStatus() != DeviceStatus.ONLINE.getType()){
|
||||
log.info("设备:[{}],不在线",modbusPollMsg.getSerialNumber());
|
||||
if (deviceStatusVO.getStatus() != DeviceStatus.ONLINE.getType()) {
|
||||
log.info("设备:[{}],不在线", modbusPollMsg.getSerialNumber());
|
||||
return;
|
||||
}
|
||||
ModbusPollJob modbusPollJob = new ModbusPollJob();
|
||||
@ -149,13 +149,13 @@ public class DeviceMessageServiceImpl implements IDeviceMessageService {
|
||||
out = modbusTcpEncoder.encode(modbusTcp);
|
||||
} else {
|
||||
//兼容15、16功能码
|
||||
if (modbusRtu.getCode() == ModbusCode.Write10.getCode()){
|
||||
if (modbusRtu.getCode() == ModbusCode.Write10.getCode()) {
|
||||
//计算:字节数=2*N;N为寄存器个数
|
||||
modbusRtu.setBitCount(2 * modbusRtu.getCount());
|
||||
}else if (modbusRtu.getCode() == ModbusCode.Write0F.getCode()){
|
||||
} else if (modbusRtu.getCode() == ModbusCode.Write0F.getCode()) {
|
||||
//计算:字节数=N/8 余数为0是 N需要再+1。N是线圈个数
|
||||
int i = modbusRtu.getCount() / 8;
|
||||
if (modbusRtu.getCount() % 8!= 0){
|
||||
if (modbusRtu.getCount() % 8 != 0) {
|
||||
i++;
|
||||
}
|
||||
modbusRtu.setBitCount(i);
|
||||
@ -192,31 +192,33 @@ public class DeviceMessageServiceImpl implements IDeviceMessageService {
|
||||
|
||||
/**
|
||||
* 变量读取
|
||||
*
|
||||
* @param readVO
|
||||
*/
|
||||
@Override
|
||||
public void readVariableValue(VariableReadVO readVO){
|
||||
public void readVariableValue(VariableReadVO readVO) {
|
||||
String serialNumber = readVO.getSerialNumber();
|
||||
assert !Objects.isNull(serialNumber) : "设备编号为空";
|
||||
DeviceAndProtocol deviceAndProtocol = deviceService.selectProtocolBySerialNumber(serialNumber);
|
||||
if (!(deviceAndProtocol.getProtocolCode().equals(FastBeeConstant.PROTOCOL.ModbusRtu) ||
|
||||
deviceAndProtocol.getProtocolCode().equals(FastBeeConstant.PROTOCOL.ModbusTcp))) throw new ServiceException("非modbus协议请先配置主动采集协议");
|
||||
deviceAndProtocol.getProtocolCode().equals(FastBeeConstant.PROTOCOL.ModbusTcp)))
|
||||
throw new ServiceException("非modbus协议请先配置主动采集协议");
|
||||
Long productId = deviceAndProtocol.getProductId();
|
||||
//如果是子设备,则获取网关子设备的产品id和设备编号
|
||||
Integer deviceType = deviceAndProtocol.getDeviceType();
|
||||
if (deviceType == DeviceType.SUB_GATEWAY.getCode()){
|
||||
if (deviceType == DeviceType.SUB_GATEWAY.getCode()) {
|
||||
serialNumber = deviceAndProtocol.getGwSerialNumber();
|
||||
productId = deviceAndProtocol.getGwProductId();
|
||||
}
|
||||
Integer type = readVO.getType();
|
||||
type = Objects.isNull(type) ? 1 : type;
|
||||
if (type == 1){
|
||||
if (type == 1) {
|
||||
//单个变量获取
|
||||
String identifier = readVO.getIdentifier();
|
||||
ThingsModelValueItem thingModels = itslCache.getSingleThingModels(deviceAndProtocol.getProductId(), identifier);
|
||||
ModbusConfig config = thingModels.getConfig();
|
||||
if (Objects.isNull(config)) throw new ServiceException("未配置modbus点位");
|
||||
thingModels.getConfig().setModbusCode(ModbusUtils.getReadModbusCode(config.getType(),config.getIsReadonly()));
|
||||
thingModels.getConfig().setModbusCode(ModbusUtils.getReadModbusCode(config.getType(), config.getIsReadonly()));
|
||||
MQSendMessageBo messageBo = new MQSendMessageBo();
|
||||
messageBo.setThingsModel(JSON.toJSONString(thingModels));
|
||||
messageBo.setSerialNumber(readVO.getSerialNumber());
|
||||
@ -235,15 +237,15 @@ public class DeviceMessageServiceImpl implements IDeviceMessageService {
|
||||
modbusPollMsg.setCommandList(commandList);
|
||||
DeviceStatusVO deviceStatusVO = deviceService.selectDeviceStatusAndTransportStatus(modbusPollMsg.getSerialNumber());
|
||||
modbusPollMsg.setTransport(deviceStatusVO.getTransport());
|
||||
if (deviceStatusVO.getStatus() != DeviceStatus.ONLINE.getType()){
|
||||
log.info("设备:[{}],不在线",modbusPollMsg.getSerialNumber());
|
||||
if (deviceStatusVO.getStatus() != DeviceStatus.ONLINE.getType()) {
|
||||
log.info("设备:[{}],不在线", modbusPollMsg.getSerialNumber());
|
||||
return;
|
||||
}
|
||||
ModbusPollJob job = new ModbusPollJob();
|
||||
job.setPollMsg(modbusPollMsg);
|
||||
job.setType(1);
|
||||
MessageProducer.sendPropFetch(job);
|
||||
}else {
|
||||
} else {
|
||||
//读取当前设备的所有变量,这里读取所有的,判断传递的设备是网关设备、网关子设备、直连设备
|
||||
DeviceType code = DeviceType.transfer(deviceType);
|
||||
List<ModbusJob> modbusJobList = modbusJobService.selectDevicesJobByDeviceType(code, readVO.getSerialNumber());
|
||||
|
||||
@ -22,14 +22,14 @@ import com.fastbee.iot.data.service.IDataHandler;
|
||||
import com.fastbee.iot.data.service.IDeviceReportMessageService;
|
||||
import com.fastbee.iot.data.service.IFirmwareTaskDetailService;
|
||||
import com.fastbee.iot.domain.FunctionLog;
|
||||
import com.fastbee.iot.domain.Product;
|
||||
import com.fastbee.iot.domain.ProductAuthorize;
|
||||
import com.fastbee.iot.enums.DeviceType;
|
||||
import com.fastbee.iot.model.DeviceStatusVO;
|
||||
import com.fastbee.iot.service.IDeviceService;
|
||||
import com.fastbee.iot.service.IFunctionLogService;
|
||||
import com.fastbee.iot.service.IProductService;
|
||||
import com.fastbee.iot.service.IProductAuthorizeService;
|
||||
import com.fastbee.iot.domain.ProductAuthorize;
|
||||
import com.fastbee.iot.domain.Product;
|
||||
import com.fastbee.iot.service.IProductService;
|
||||
import com.fastbee.mq.producer.MessageProducer;
|
||||
import com.fastbee.mqtt.manager.MqttRemoteManager;
|
||||
import com.fastbee.mqtt.model.PushMessageBo;
|
||||
@ -108,7 +108,7 @@ public class DeviceReportMessageServiceImpl implements IDeviceReportMessageServi
|
||||
handlerDeviceReply(reportMessage);
|
||||
}
|
||||
serialNumber = reportMessage.getSerialNumber() == null ? serialNumber : reportMessage.getSerialNumber();
|
||||
productId = reportMessage.getProductId()== null ? productId : reportMessage.getProductId();
|
||||
productId = reportMessage.getProductId() == null ? productId : reportMessage.getProductId();
|
||||
reportMessage.setSerialNumber(serialNumber);
|
||||
reportMessage.setProductId(productId);
|
||||
reportMessage.setPlatformDate(bo.getPlatformDate());
|
||||
@ -122,7 +122,7 @@ public class DeviceReportMessageServiceImpl implements IDeviceReportMessageServi
|
||||
log.debug("*MQ收到TCP推送消息[{}]", JSON.toJSON(bo.getThingsModelSimpleItem()));
|
||||
DeviceStatusVO deviceStatusVO1 = deviceService.selectDeviceStatusAndTransportStatus(serialNumber);
|
||||
Optional.ofNullable(deviceStatusVO1).orElseThrow(() -> new ServiceException("设备不存在"));
|
||||
|
||||
|
||||
// TCP协议授权码校验
|
||||
productId = deviceStatusVO1.getProductId();
|
||||
Product product = productService.selectProductByProductId(productId);
|
||||
@ -138,7 +138,7 @@ public class DeviceReportMessageServiceImpl implements IDeviceReportMessageServi
|
||||
}
|
||||
log.debug("TCP数据上报-授权码校验通过: 设备[{}]已绑定授权码", serialNumber);
|
||||
}
|
||||
|
||||
|
||||
//同步设备状态
|
||||
this.synchDeviceStatus(serialNumber);
|
||||
DeviceReport deviceReport = new DeviceReport();
|
||||
@ -157,7 +157,6 @@ public class DeviceReportMessageServiceImpl implements IDeviceReportMessageServi
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 处理设备回调数据
|
||||
*/
|
||||
@ -199,9 +198,9 @@ public class DeviceReportMessageServiceImpl implements IDeviceReportMessageServi
|
||||
return;
|
||||
}
|
||||
int size = 256;
|
||||
if ((int)data[0] == 1) {
|
||||
if ((int) data[0] == 1) {
|
||||
size = 512;
|
||||
} else if ((int)data[0] == 2) {
|
||||
} else if ((int) data[0] == 2) {
|
||||
size = 1024;
|
||||
}
|
||||
otaTaskCache.setOtaCacheValue(bo.getSerialNumber(), "packageSize", String.valueOf(size), 5);
|
||||
@ -299,6 +298,7 @@ public class DeviceReportMessageServiceImpl implements IDeviceReportMessageServi
|
||||
/**
|
||||
* 处理设备回调信息,此处按照topic区分 prop上报和设备回调reply,
|
||||
* 如果模组可订阅的topic有限,不能区分prop上报和reply,自行根据上报数据来区分
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public void handlerDeviceReply(DeviceReport message) {
|
||||
@ -310,13 +310,13 @@ public class DeviceReportMessageServiceImpl implements IDeviceReportMessageServi
|
||||
//从redis中获取messageId 流水号,获取下发记录
|
||||
for (String fun : functionList) {
|
||||
String[] split = fun.split(":");
|
||||
if (split[0].equals(sources)){
|
||||
if (split[0].equals(sources)) {
|
||||
messageId = split[1];
|
||||
}
|
||||
redisCache.zRem(cacheKey,fun);
|
||||
redisCache.zRem(cacheKey, fun);
|
||||
}
|
||||
FunctionLog functionLog = new FunctionLog();
|
||||
switch (message.getProtocolCode()){
|
||||
switch (message.getProtocolCode()) {
|
||||
case FastBeeConstant.PROTOCOL.ModbusRtu:
|
||||
case FastBeeConstant.PROTOCOL.ModbusToJsonHP:
|
||||
case FastBeeConstant.PROTOCOL.ModbusRtuPak:
|
||||
@ -340,13 +340,14 @@ public class DeviceReportMessageServiceImpl implements IDeviceReportMessageServi
|
||||
|
||||
/**
|
||||
* 同步设备状态
|
||||
*
|
||||
* @param
|
||||
*/
|
||||
private void synchDeviceStatus(String serialNumber){
|
||||
private void synchDeviceStatus(String serialNumber) {
|
||||
//如果有数据上报,但是数据库设备状态为离线,则进行同步
|
||||
DeviceStatusVO deviceStatusVO = deviceService.selectDeviceStatusAndTransportStatus(serialNumber);
|
||||
if (deviceStatusVO.getStatus() == DeviceStatus.OFFLINE.getType()
|
||||
|| deviceStatusVO.getStatus() == DeviceStatus.UNACTIVATED.getType()){
|
||||
|| deviceStatusVO.getStatus() == DeviceStatus.UNACTIVATED.getType()) {
|
||||
DeviceStatusBo statusBo = new DeviceStatusBo();
|
||||
statusBo.setStatus(DeviceStatus.ONLINE);
|
||||
statusBo.setSerialNumber(deviceStatusVO.getSerialNumber());
|
||||
@ -362,11 +363,11 @@ public class DeviceReportMessageServiceImpl implements IDeviceReportMessageServi
|
||||
session.setConnected(true);
|
||||
sessionStore.storeSession(deviceStatusVO.getSerialNumber(), session);
|
||||
}
|
||||
}else if (deviceStatusVO.getStatus() == DeviceStatus.ONLINE.getType() ){
|
||||
if (deviceStatusVO.getDeviceType() == DeviceType.SUB_GATEWAY.getCode()){
|
||||
} else if (deviceStatusVO.getStatus() == DeviceStatus.ONLINE.getType()) {
|
||||
if (deviceStatusVO.getDeviceType() == DeviceType.SUB_GATEWAY.getCode()) {
|
||||
//如果是在线,则更新session在线时间
|
||||
Session session = sessionStore.getSession(deviceStatusVO.getSerialNumber());
|
||||
if (session!= null) {
|
||||
if (session != null) {
|
||||
session.setLastAccessTime(DateUtils.getTimestamp());
|
||||
sessionStore.storeSession(deviceStatusVO.getSerialNumber(), session);
|
||||
}
|
||||
|
||||
@ -34,10 +34,11 @@ public class DeviceTestHandler implements IDeviceTestService {
|
||||
|
||||
/**
|
||||
* 处理数据调试信息
|
||||
*
|
||||
* @param testReportBo
|
||||
*/
|
||||
@Override
|
||||
public void messageHandler(DeviceTestReportBo testReportBo){
|
||||
public void messageHandler(DeviceTestReportBo testReportBo) {
|
||||
boolean isReply = testReportBo.getIsReply();
|
||||
Long productId = testReportBo.getProductId();
|
||||
String serialNumber = testReportBo.getSerialNumber();
|
||||
@ -49,7 +50,7 @@ public class DeviceTestHandler implements IDeviceTestService {
|
||||
} else {
|
||||
deviceMessage.setTopicName(TopicType.PROPERTY_POST.getTopicSuffix());
|
||||
}
|
||||
if (Objects.isNull(productId)){
|
||||
if (Objects.isNull(productId)) {
|
||||
DeviceAndProtocol protocol = deviceService.selectProtocolBySerialNumber(serialNumber);
|
||||
productId = protocol.getProductId();
|
||||
}
|
||||
@ -58,7 +59,7 @@ public class DeviceTestHandler implements IDeviceTestService {
|
||||
messageBo.setTopic(topicsUtils.buildTopic(productId, serialNumber.toUpperCase(), TopicType.WS_SERVICE_INVOKE));
|
||||
JSONObject pushObj = new JSONObject();
|
||||
pushObj.put("message", testReportBo.getThingsModelSimpleItem());
|
||||
pushObj.put("sources",testReportBo.getSources());
|
||||
pushObj.put("sources", testReportBo.getSources());
|
||||
messageBo.setMessage(JSON.toJSONString(pushObj));
|
||||
mqttRemoteManager.pushCommon(messageBo);
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ import java.util.Objects;
|
||||
* @date 2024-08-18
|
||||
*/
|
||||
@Service
|
||||
public class FirmwareTaskDetailServiceImpl extends ServiceImpl<FirmwareTaskDetailMapper,FirmwareTaskDetail> implements IFirmwareTaskDetailService {
|
||||
public class FirmwareTaskDetailServiceImpl extends ServiceImpl<FirmwareTaskDetailMapper, FirmwareTaskDetail> implements IFirmwareTaskDetailService {
|
||||
|
||||
@Resource
|
||||
private FirmwareTaskDetailMapper firmwareTaskDetailMapper;
|
||||
@ -66,19 +66,21 @@ public class FirmwareTaskDetailServiceImpl extends ServiceImpl<FirmwareTaskDetai
|
||||
|
||||
/**
|
||||
* 查询固件升级任务详细
|
||||
*
|
||||
* @param taskId
|
||||
* @param serialNumber
|
||||
* @return
|
||||
*/
|
||||
public FirmwareTaskDetail selectFirmwareTaskDetailByTaskIdAndSerialNumber(Long taskId, String serialNumber){
|
||||
public FirmwareTaskDetail selectFirmwareTaskDetailByTaskIdAndSerialNumber(Long taskId, String serialNumber) {
|
||||
LambdaQueryWrapper<FirmwareTaskDetail> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(FirmwareTaskDetail::getId,taskId);
|
||||
wrapper.eq(FirmwareTaskDetail::getSerialNumber,serialNumber);
|
||||
wrapper.eq(FirmwareTaskDetail::getId, taskId);
|
||||
wrapper.eq(FirmwareTaskDetail::getSerialNumber, serialNumber);
|
||||
return baseMapper.selectOne(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新升级状态
|
||||
*
|
||||
* @param taskId
|
||||
* @param serialNumber
|
||||
* @param otaUpgrade
|
||||
@ -97,6 +99,7 @@ public class FirmwareTaskDetailServiceImpl extends ServiceImpl<FirmwareTaskDetai
|
||||
|
||||
/**
|
||||
* 根据固件id查询下属设备列表
|
||||
*
|
||||
* @param firmwareTaskDetailInput
|
||||
* @return
|
||||
*/
|
||||
@ -108,8 +111,7 @@ public class FirmwareTaskDetailServiceImpl extends ServiceImpl<FirmwareTaskDetai
|
||||
String statusCache = otaTaskCache.getOtaCacheValue(output.getSerialNumber(), "status");
|
||||
if (output.getUpgradeStatus() == 1 && StringUtils.isNotEmpty(statusCache)) {
|
||||
output.setProgress(Integer.parseInt(statusCache));
|
||||
}
|
||||
else if (output.getUpgradeStatus() == 2 || output.getUpgradeStatus() == 3) {
|
||||
} else if (output.getUpgradeStatus() == 2 || output.getUpgradeStatus() == 3) {
|
||||
output.setProgress(100);
|
||||
} else {
|
||||
output.setProgress(0);
|
||||
@ -120,6 +122,7 @@ public class FirmwareTaskDetailServiceImpl extends ServiceImpl<FirmwareTaskDetai
|
||||
|
||||
/**
|
||||
* 固件升级设备统计
|
||||
*
|
||||
* @param firmwareTaskDetailInput
|
||||
* @return
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user