20251220:授权码(TCP校验)& GB28181
This commit is contained in:
parent
c26f430924
commit
2c44850c38
@ -18,11 +18,11 @@
|
||||
<dependencies>
|
||||
|
||||
<!-- spring-boot-devtools -->
|
||||
<dependency>
|
||||
<!-- <dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<optional>true</optional> <!-- 表示依赖不会传递 -->
|
||||
</dependency>
|
||||
<optional>true</optional> <!– 表示依赖不会传递 –>
|
||||
</dependency>-->
|
||||
|
||||
<!-- swagger3-->
|
||||
<dependency>
|
||||
|
||||
@ -127,10 +127,10 @@ emqx:
|
||||
ApiSecret: emqx.api.123
|
||||
# sip 配置
|
||||
sip:
|
||||
enabled: false # 是否启用视频监控SIP,true为启用
|
||||
enabled: true # 是否启用视频监控SIP,true为启用
|
||||
## 本地调试时,绑定网卡局域网IP,设备在同一局域网,设备接入IP填写绑定IP
|
||||
## 部署服务端时,默认绑定容器IP,设备接入IP填写服务器公网IP
|
||||
ip: localhost
|
||||
ip: 192.168.110.78 # 本服务启动的 IP
|
||||
port: 5061 # SIP端口(保持默认)
|
||||
domain: 3402000000 # 由省级、市级、区级、基层编号组成
|
||||
id: 34020000002000000001 # 同上,另外增加编号,(可保持默认)
|
||||
|
||||
@ -129,7 +129,7 @@ sip:
|
||||
enabled: true # 是否启用视频监控SIP,true为启用
|
||||
## 本地调试时,绑定网卡局域网IP,设备在同一局域网,设备接入IP填写绑定IP
|
||||
## 部署服务端时,默认绑定容器IP,设备接入IP填写服务器公网IP
|
||||
ip: 177.7.0.13
|
||||
ip: 177.7.0.13 # 容器部署容器IP:177.7.0.13;云服务器部署写公网IP;本地部署127.0.0.1;总原则:能被摄像机访问的地址
|
||||
port: 5061 # SIP端口(保持默认)
|
||||
domain: 3402000000 # 由省级、市级、区级、基层编号组成
|
||||
id: 34020000002000000001 # 同上,另外增加编号,(可保持默认)
|
||||
|
||||
@ -66,9 +66,9 @@ spring:
|
||||
max-file-size: 10MB # 单个文件大小
|
||||
max-request-size: 20MB # 设置总上传的文件大小
|
||||
# 服务模块
|
||||
devtools:
|
||||
restart:
|
||||
enabled: true # 热部署开关
|
||||
# devtools:
|
||||
# restart:
|
||||
# enabled: true # 热部署开关
|
||||
task:
|
||||
execution:
|
||||
pool:
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
<configuration>
|
||||
<!-- 日志存放路径 -->
|
||||
<property name="log.path" scope="context" value="./logs"/>
|
||||
<!-- 日志输出格式 -->
|
||||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %class - [%method,%line] - %msg%n"/>
|
||||
<!-- 日志输出格式,添加TraceId -->
|
||||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %class - [%method,%line] - %msg%n"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
|
||||
@ -0,0 +1,108 @@
|
||||
package com.fastbee.common.utils;
|
||||
|
||||
import com.fastbee.common.utils.uuid.IdUtils;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* 日志追踪ID工具类
|
||||
* 统一生成TraceId的逻辑,使用IdWorker和ThreadLocalRandom
|
||||
*
|
||||
* @author fastbee
|
||||
*/
|
||||
public class TraceIdUtils {
|
||||
|
||||
/**
|
||||
* TraceId在MDC中的key
|
||||
*/
|
||||
public static final String TRACE_ID_KEY = "traceId";
|
||||
|
||||
/**
|
||||
* IdWorker实例(单例模式)
|
||||
*/
|
||||
private static volatile IdUtils idWorker;
|
||||
|
||||
/**
|
||||
* 获取IdWorker实例(懒加载单例)
|
||||
*
|
||||
* @return IdWorker实例
|
||||
*/
|
||||
private static IdUtils getIdWorker() {
|
||||
if (idWorker == null) {
|
||||
synchronized (TraceIdUtils.class) {
|
||||
if (idWorker == null) {
|
||||
// 使用机器ID,可以根据实际情况配置
|
||||
// 这里使用1作为默认workerId,可以通过配置文件读取
|
||||
// IdUtils构造函数:workerId, datacenterId,-1表示随机生成
|
||||
idWorker = new IdUtils(-1L, -1L);
|
||||
}
|
||||
}
|
||||
}
|
||||
return idWorker;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成TraceId
|
||||
* 格式:IdWorker.nextId() * 1000 + ThreadLocalRandom.nextInt(1000)
|
||||
* 参考:generateClueId() 的实现方式
|
||||
* 使用Math.abs确保TraceId为正数
|
||||
*
|
||||
* @return TraceId
|
||||
*/
|
||||
public static long generateTraceId() {
|
||||
long id = getIdWorker().nextId();
|
||||
// 使用绝对值确保TraceId为正数,避免负数显示
|
||||
long traceId = Math.abs(id) * 1000 + ThreadLocalRandom.current().nextInt(1000);
|
||||
MDC.put(TRACE_ID_KEY, String.valueOf(traceId));
|
||||
return traceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成TraceId并放入MDC
|
||||
* 返回字符串格式的TraceId
|
||||
*
|
||||
* @return TraceId字符串
|
||||
*/
|
||||
public static String generateTraceIdString() {
|
||||
long traceId = generateTraceId();
|
||||
return String.valueOf(traceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置TraceId到MDC
|
||||
*
|
||||
* @param traceId TraceId
|
||||
*/
|
||||
public static void setTraceId(String traceId) {
|
||||
if (traceId != null && !traceId.isEmpty()) {
|
||||
MDC.put(TRACE_ID_KEY, traceId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置TraceId到MDC(long类型)
|
||||
*
|
||||
* @param traceId TraceId
|
||||
*/
|
||||
public static void setTraceId(long traceId) {
|
||||
MDC.put(TRACE_ID_KEY, String.valueOf(traceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从MDC获取TraceId
|
||||
*
|
||||
* @return TraceId
|
||||
*/
|
||||
public static String getTraceId() {
|
||||
return MDC.get(TRACE_ID_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除MDC中的TraceId
|
||||
*/
|
||||
public static void clearTraceId() {
|
||||
MDC.remove(TRACE_ID_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package com.fastbee.framework.config;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.fastbee.framework.interceptor.LanguageInterceptor;
|
||||
import com.fastbee.framework.interceptor.TraceIdInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@ -31,6 +32,8 @@ public class ResourcesConfig implements WebMvcConfigurer
|
||||
private RepeatSubmitInterceptor repeatSubmitInterceptor;
|
||||
@Resource
|
||||
private LanguageInterceptor languageInterceptor;
|
||||
@Autowired
|
||||
private TraceIdInterceptor traceIdInterceptor;
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry)
|
||||
@ -51,6 +54,8 @@ public class ResourcesConfig implements WebMvcConfigurer
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry)
|
||||
{
|
||||
// TraceId拦截器放在最前面,确保所有请求都有TraceId
|
||||
registry.addInterceptor(traceIdInterceptor).addPathPatterns("/**").order(0);
|
||||
registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
|
||||
//这里配置国际化拦截器的白名单
|
||||
registry.addInterceptor(languageInterceptor).addPathPatterns("/**").excludePathPatterns("/v2/api-docs",
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
package com.fastbee.framework.interceptor;
|
||||
|
||||
import com.fastbee.common.utils.TraceIdUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 日志追踪ID拦截器
|
||||
* 用于生成和传递TraceId,方便同一个链路调用追查问题
|
||||
*
|
||||
* @author fastbee
|
||||
*/
|
||||
@Component
|
||||
public class TraceIdInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Override
|
||||
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();
|
||||
} else {
|
||||
// 如果请求头中有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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||
// 请求完成后清除MDC中的TraceId,避免内存泄漏
|
||||
TraceIdUtils.clearTraceId();
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,9 @@ 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.tdengine.service.ILogService;
|
||||
import com.fastbee.mqtt.manager.MqttRemoteManager;
|
||||
import com.fastbee.mqtt.model.PushMessageBo;
|
||||
@ -33,6 +36,7 @@ import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 设备调试错误日志AOP切面
|
||||
@ -63,6 +67,9 @@ public class DeviceDebugLogAspect {
|
||||
@Resource
|
||||
private IProductService productService;
|
||||
|
||||
@Resource
|
||||
private IProductAuthorizeService productAuthorizeService;
|
||||
|
||||
@Resource
|
||||
private MqttRemoteManager mqttRemoteManager;
|
||||
|
||||
@ -127,8 +134,7 @@ public class DeviceDebugLogAspect {
|
||||
String protocolCode = bo.getProtocolCode();
|
||||
Long productId = bo.getProductId();
|
||||
|
||||
saveErrorLog(serialNumber, sourceData, errorMsg, protocolCode, bo.getTopicName(),
|
||||
DeviceLogTypeEnum.DATA_PARSE_ERROR.getType(), "DEBUG_ERROR", productId);
|
||||
saveErrorLog(serialNumber, sourceData, errorMsg, DeviceLogTypeEnum.DATA_PARSE_ERROR.getType(), "DEBUG_ERROR", productId);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.error("记录数据解析错误日志失败: {}", ex.getMessage(), ex);
|
||||
@ -186,7 +192,7 @@ public class DeviceDebugLogAspect {
|
||||
String protocolCode = getProtocolCodeBySerialNumber(serialNumber);
|
||||
Long productId = getProductIdBySerialNumber(serialNumber);
|
||||
|
||||
saveErrorLog(serialNumber, sourceData, errorMsg, protocolCode, deviceMessage.getTopicName(),
|
||||
saveErrorLog(serialNumber, sourceData, errorMsg,
|
||||
DeviceLogTypeEnum.COMMAND_SEND_ERROR.getType(), "SEND_ERROR", productId);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
@ -242,7 +248,7 @@ public class DeviceDebugLogAspect {
|
||||
}
|
||||
|
||||
// 协议解析错误也归类为数据解析错误
|
||||
saveErrorLog(serialNumber, sourceData, errorMsg, protocolCode, deviceData.getTopicName(),
|
||||
saveErrorLog(serialNumber, sourceData, errorMsg,
|
||||
DeviceLogTypeEnum.DATA_PARSE_ERROR.getType(), "PARSE_ERROR", productId);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
@ -299,7 +305,7 @@ public class DeviceDebugLogAspect {
|
||||
* 保存错误日志到iot_device_log表,并推送到前端页面
|
||||
*/
|
||||
private void saveErrorLog(String serialNumber, String sourceData, String errorMsg,
|
||||
String protocolCode, String topicName, Integer logType, String identity, Long productId) {
|
||||
Integer logType, String identity, Long productId) {
|
||||
try {
|
||||
if (StringUtils.isEmpty(serialNumber)) {
|
||||
log.warn("设备编号为空,无法保存错误日志");
|
||||
@ -327,6 +333,27 @@ public class DeviceDebugLogAspect {
|
||||
productId = getProductIdBySerialNumber(serialNumber);
|
||||
}
|
||||
|
||||
// 授权码校验:如果产品开启了授权码,但设备未绑定授权码,不记录日志也不推送消息
|
||||
if (productId != null) {
|
||||
try {
|
||||
Product product = productService.selectProductByProductId(productId);
|
||||
if (product != null && product.getIsAuthorize() != null && product.getIsAuthorize() == 1) {
|
||||
// 产品开启了授权码,检查设备是否绑定了授权码
|
||||
ProductAuthorize queryParam = new ProductAuthorize();
|
||||
queryParam.setProductId(productId);
|
||||
queryParam.setSerialNumber(serialNumber);
|
||||
java.util.List<ProductAuthorize> authorizeList = productAuthorizeService.selectProductAuthorizeList(queryParam);
|
||||
if (authorizeList == null || authorizeList.isEmpty()) {
|
||||
log.debug("设备[{}]未绑定授权码,跳过错误日志记录和消息推送", serialNumber);
|
||||
return; // 不记录日志,也不推送消息
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.warn("授权码校验失败: {}, 设备编号: {}, 继续记录日志", ex.getMessage(), serialNumber);
|
||||
// 校验失败时继续记录日志,避免影响正常功能
|
||||
}
|
||||
}
|
||||
|
||||
DeviceLog deviceLog = new DeviceLog();
|
||||
deviceLog.setSerialNumber(serialNumber);
|
||||
deviceLog.setDeviceId(device.getDeviceId());
|
||||
@ -337,7 +364,7 @@ public class DeviceDebugLogAspect {
|
||||
// 存储错误信息(限制500字符)
|
||||
deviceLog.setRemark(StringUtils.substring(errorMsg, 0, 500));
|
||||
deviceLog.setIdentity(identity);
|
||||
deviceLog.setModelName(logType == DeviceLogTypeEnum.DATA_PARSE_ERROR.getType() ?
|
||||
deviceLog.setModelName(Objects.equals(logType, DeviceLogTypeEnum.DATA_PARSE_ERROR.getType()) ?
|
||||
"数据解析错误" : "指令发送错误");
|
||||
deviceLog.setCreateTime(DateUtils.getNowDate());
|
||||
deviceLog.setUserId(device.getTenantId());
|
||||
@ -374,7 +401,7 @@ public class DeviceDebugLogAspect {
|
||||
List<ThingsModelSimpleItem> errorItems = new ArrayList<>();
|
||||
ThingsModelSimpleItem errorItem = new ThingsModelSimpleItem();
|
||||
errorItem.setId("ERROR_" + identity);
|
||||
errorItem.setName(logType == DeviceLogTypeEnum.DATA_PARSE_ERROR.getType() ? "数据解析错误" : "指令发送错误");
|
||||
errorItem.setName(Objects.equals(logType, DeviceLogTypeEnum.DATA_PARSE_ERROR.getType()) ? "数据解析错误" : "指令发送错误");
|
||||
errorItem.setValue(errorMsg);
|
||||
errorItem.setRemark(errorMsg);
|
||||
errorItem.setTs(new Date());
|
||||
|
||||
@ -9,6 +9,7 @@ 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;
|
||||
@ -61,6 +62,11 @@ public abstract class DeviceAbstractQuartzJob implements Job
|
||||
protected void before(JobExecutionContext context, DeviceJob deviceJob)
|
||||
{
|
||||
threadLocal.set(new Date());
|
||||
|
||||
// 为设备定时任务生成TraceId,使用统一的生成逻辑
|
||||
TraceIdUtils.generateTraceId();
|
||||
|
||||
log.info("设备定时任务开始执行: {} - {}", deviceJob.getJobName(), deviceJob.getJobGroup());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,6 +116,11 @@ public abstract class DeviceAbstractQuartzJob implements Job
|
||||
|
||||
// 写入数据库当中
|
||||
SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog);
|
||||
|
||||
// 清除TraceId,避免内存泄漏
|
||||
TraceIdUtils.clearTraceId();
|
||||
|
||||
log.info("设备定时任务执行完成: {} - {}, 耗时: {}ms", deviceJob.getJobName(), deviceJob.getJobGroup(), runMs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -27,6 +27,9 @@ 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.mq.producer.MessageProducer;
|
||||
import com.fastbee.mqtt.manager.MqttRemoteManager;
|
||||
import com.fastbee.mqtt.model.PushMessageBo;
|
||||
@ -41,10 +44,7 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 处理类 处理设备主动上报和设备回调信息
|
||||
@ -60,6 +60,8 @@ public class DeviceReportMessageServiceImpl implements IDeviceReportMessageServi
|
||||
@Autowired
|
||||
private IProductService productService;
|
||||
@Autowired
|
||||
private IProductAuthorizeService productAuthorizeService;
|
||||
@Autowired
|
||||
private IProtocolManagerService protocolManagerService;
|
||||
@Autowired
|
||||
private IFirmwareTaskDetailService firmwareTaskDetailService;
|
||||
@ -120,6 +122,23 @@ 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);
|
||||
if (product != null && product.getIsAuthorize() != null && product.getIsAuthorize() == 1) {
|
||||
// 产品开启了授权码,检查设备是否绑定了授权码
|
||||
ProductAuthorize queryParam = new ProductAuthorize();
|
||||
queryParam.setProductId(productId);
|
||||
queryParam.setSerialNumber(serialNumber);
|
||||
List<ProductAuthorize> authorizeList = productAuthorizeService.selectProductAuthorizeList(queryParam);
|
||||
if (authorizeList == null || authorizeList.isEmpty()) {
|
||||
log.warn("TCP数据上报-授权码校验失败: 设备[{}]未绑定授权码,拒绝数据上报", serialNumber);
|
||||
return; // 拒绝数据上报
|
||||
}
|
||||
log.debug("TCP数据上报-授权码校验通过: 设备[{}]已绑定授权码", serialNumber);
|
||||
}
|
||||
|
||||
//同步设备状态
|
||||
this.synchDeviceStatus(serialNumber);
|
||||
DeviceReport deviceReport = new DeviceReport();
|
||||
|
||||
@ -4,6 +4,7 @@ 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.quartz.domain.SysJob;
|
||||
@ -61,6 +62,11 @@ public abstract class AbstractQuartzJob implements Job
|
||||
protected void before(JobExecutionContext context, SysJob sysJob)
|
||||
{
|
||||
threadLocal.set(new Date());
|
||||
|
||||
// 为定时任务生成TraceId,使用统一的生成逻辑
|
||||
TraceIdUtils.generateTraceId();
|
||||
|
||||
log.info("定时任务开始执行: {} - {}", sysJob.getJobName(), sysJob.getJobGroup());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -95,6 +101,11 @@ public abstract class AbstractQuartzJob implements Job
|
||||
|
||||
// 写入数据库当中
|
||||
SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog);
|
||||
|
||||
// 清除TraceId,避免内存泄漏
|
||||
TraceIdUtils.clearTraceId();
|
||||
|
||||
log.info("定时任务执行完成: {} - {}, 耗时: {}ms", sysJob.getJobName(), sysJob.getJobGroup(), runMs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,22 +1,29 @@
|
||||
spring:
|
||||
# REDIS数据库配置
|
||||
redis:
|
||||
# [可选] 超时时间
|
||||
timeout: 10000
|
||||
# 以下为单机配置
|
||||
# [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
|
||||
host: 127.0.0.1
|
||||
host: redis
|
||||
# [必须修改] 端口号
|
||||
port: 6379
|
||||
# [可选] 数据库 DB
|
||||
database: 8
|
||||
database: 0
|
||||
# [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
|
||||
password:
|
||||
# [可选] 超时时间
|
||||
timeout: 10000
|
||||
password: fastbee
|
||||
# 以下为集群配置
|
||||
# cluster:
|
||||
# nodes: 192.168.1.242:7001
|
||||
# password: 4767cb971b40a1300fa09b7f87b09d1c
|
||||
|
||||
# [可选] 监听的HTTP端口, 网页和接口调用都是这个端口
|
||||
# 您需要使用实际的证书名称替换domain_name.jks
|
||||
# 证书获取参考文档:https://help.aliyun.com/zh/ssl-certificate/user-guide/enable-https-on-spring-boot
|
||||
server:
|
||||
port: 18081
|
||||
servlet:
|
||||
context-path: / # 应用的访问路径
|
||||
# HTTPS配置, 默认不开启
|
||||
ssl:
|
||||
# 是否开启HTTPS访问 默认关闭
|
||||
@ -31,7 +38,9 @@ server:
|
||||
|
||||
# [根据业务需求配置]
|
||||
userSettings:
|
||||
# [可选 ] zlm配置的录像路径,
|
||||
# [必选 ] 服务ID
|
||||
id: 334533
|
||||
# [必选 ] zlm配置的录像路径
|
||||
record: /opt/media/bin/www/record
|
||||
# [可选 ] 录像保存时长(单位: 天)每天晚12点自动对过期文件执行清理
|
||||
recordDay: 7
|
||||
@ -44,6 +53,12 @@ userSettings:
|
||||
# [可选 ] 限制 ffmpeg 合并文件使用的线程数,间接限制cpu使用率, 默认2 限制到50%
|
||||
threads: 2
|
||||
|
||||
# MyBatis配置
|
||||
mybatis:
|
||||
typeAliasesPackage: com.fastbee.oss.domain # 搜索指定包别名
|
||||
mapperLocations: classpath*:mapper/**/*Mapper.xml # 配置mapper的扫描,找到所有的mapper.xml映射文件
|
||||
configLocation: classpath:mybatis/mybatis-config.xml # 加载全局的配置文件
|
||||
|
||||
swagger-ui:
|
||||
|
||||
# [可选] 日志配置, 一般不需要改
|
||||
|
||||
@ -41,15 +41,15 @@ userSettings:
|
||||
# [必选 ] 服务ID
|
||||
id: 334533
|
||||
# [必选 ] zlm配置的录像路径
|
||||
record: D:\soft\ZLMediaKit\www\record
|
||||
record: D:\fastbee\ZLMediaKit\www\record
|
||||
# [可选 ] 录像保存时长(单位: 天)每天晚12点自动对过期文件执行清理
|
||||
recordDay: 7
|
||||
# [可选 ] 录像下载合成临时文件保存时长, 不配置默认取值recordDay(单位: 天)每天晚12点自动对过期文件执行清理
|
||||
# recordTempDay: 7
|
||||
# [必选 ] ffmpeg路径
|
||||
ffmpeg: D:\soft\ZLMediaKit\bin\ffmpeg
|
||||
ffmpeg: D:\fastbee\ZLMediaKit\ffmpeg-8.0.1-essentials_build\bin\ffmpeg
|
||||
# [必选 ] ffprobe路径, 一般安装ffmpeg就会自带, 一般跟ffmpeg在同一目录,用于查询文件的信息
|
||||
ffprobe: D:\soft\ZLMediaKit\bin\ffprobe
|
||||
ffprobe: D:\fastbee\ZLMediaKit\ffmpeg-8.0.1-essentials_build\bin\ffprobe
|
||||
# [可选 ] 限制 ffmpeg 合并文件使用的线程数,间接限制cpu使用率, 默认2 限制到50%
|
||||
threads: 2
|
||||
|
||||
|
||||
@ -23,8 +23,7 @@ import java.util.List;
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Service
|
||||
public class SysConfigServiceImpl implements ISysConfigService
|
||||
{
|
||||
public class SysConfigServiceImpl implements ISysConfigService {
|
||||
@Autowired
|
||||
private SysConfigMapper configMapper;
|
||||
|
||||
@ -35,8 +34,7 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
* 项目启动时,初始化参数到缓存
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init()
|
||||
{
|
||||
public void init() {
|
||||
loadingConfigCache();
|
||||
}
|
||||
|
||||
@ -48,8 +46,7 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
*/
|
||||
@Override
|
||||
@DS("master")
|
||||
public SysConfig selectConfigById(Long configId)
|
||||
{
|
||||
public SysConfig selectConfigById(Long configId) {
|
||||
SysConfig config = new SysConfig();
|
||||
config.setConfigId(configId);
|
||||
return configMapper.selectConfig(config);
|
||||
@ -62,18 +59,15 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
* @return 参数键值
|
||||
*/
|
||||
@Override
|
||||
public String selectConfigByKey(String configKey)
|
||||
{
|
||||
public String selectConfigByKey(String configKey) {
|
||||
String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey)));
|
||||
if (StringUtils.isNotEmpty(configValue))
|
||||
{
|
||||
if (StringUtils.isNotEmpty(configValue)) {
|
||||
return configValue;
|
||||
}
|
||||
SysConfig config = new SysConfig();
|
||||
config.setConfigKey(configKey);
|
||||
SysConfig retConfig = configMapper.selectConfig(config);
|
||||
if (StringUtils.isNotNull(retConfig))
|
||||
{
|
||||
if (StringUtils.isNotNull(retConfig)) {
|
||||
redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
|
||||
return retConfig.getConfigValue();
|
||||
}
|
||||
@ -86,11 +80,9 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
* @return true开启,false关闭
|
||||
*/
|
||||
@Override
|
||||
public boolean selectCaptchaEnabled()
|
||||
{
|
||||
public boolean selectCaptchaEnabled() {
|
||||
String captchaEnabled = selectConfigByKey("sys.account.captchaEnabled");
|
||||
if (StringUtils.isEmpty(captchaEnabled))
|
||||
{
|
||||
if (StringUtils.isEmpty(captchaEnabled)) {
|
||||
return true;
|
||||
}
|
||||
return Convert.toBool(captchaEnabled);
|
||||
@ -103,8 +95,7 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
* @return 参数配置集合
|
||||
*/
|
||||
@Override
|
||||
public List<SysConfig> selectConfigList(SysConfig config)
|
||||
{
|
||||
public List<SysConfig> selectConfigList(SysConfig config) {
|
||||
return configMapper.selectConfigList(config);
|
||||
}
|
||||
|
||||
@ -115,11 +106,9 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertConfig(SysConfig config)
|
||||
{
|
||||
public int insertConfig(SysConfig config) {
|
||||
int row = configMapper.insertConfig(config);
|
||||
if (row > 0)
|
||||
{
|
||||
if (row > 0) {
|
||||
redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
|
||||
}
|
||||
return row;
|
||||
@ -132,17 +121,14 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateConfig(SysConfig config)
|
||||
{
|
||||
public int updateConfig(SysConfig config) {
|
||||
SysConfig temp = configMapper.selectConfigById(config.getConfigId());
|
||||
if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey()))
|
||||
{
|
||||
if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) {
|
||||
redisCache.deleteObject(getCacheKey(temp.getConfigKey()));
|
||||
}
|
||||
|
||||
int row = configMapper.updateConfig(config);
|
||||
if (row > 0)
|
||||
{
|
||||
if (row > 0) {
|
||||
redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
|
||||
}
|
||||
return row;
|
||||
@ -154,13 +140,10 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
* @param configIds 需要删除的参数ID
|
||||
*/
|
||||
@Override
|
||||
public void deleteConfigByIds(Long[] configIds)
|
||||
{
|
||||
for (Long configId : configIds)
|
||||
{
|
||||
public void deleteConfigByIds(Long[] configIds) {
|
||||
for (Long configId : configIds) {
|
||||
SysConfig config = selectConfigById(configId);
|
||||
if (StringUtils.equals(UserConstants.YES, config.getConfigType()))
|
||||
{
|
||||
if (StringUtils.equals(UserConstants.YES, config.getConfigType())) {
|
||||
throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
|
||||
}
|
||||
configMapper.deleteConfigById(configId);
|
||||
@ -172,11 +155,9 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
* 加载参数缓存数据
|
||||
*/
|
||||
@Override
|
||||
public void loadingConfigCache()
|
||||
{
|
||||
public void loadingConfigCache() {
|
||||
List<SysConfig> configsList = configMapper.selectConfigList(new SysConfig());
|
||||
for (SysConfig config : configsList)
|
||||
{
|
||||
for (SysConfig config : configsList) {
|
||||
redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
|
||||
}
|
||||
}
|
||||
@ -185,8 +166,7 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
* 清空参数缓存数据
|
||||
*/
|
||||
@Override
|
||||
public void clearConfigCache()
|
||||
{
|
||||
public void clearConfigCache() {
|
||||
Collection<String> keys = redisCache.keys(CacheConstants.SYS_CONFIG_KEY + "*");
|
||||
redisCache.deleteObject(keys);
|
||||
}
|
||||
@ -195,8 +175,7 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
* 重置参数缓存数据
|
||||
*/
|
||||
@Override
|
||||
public void resetConfigCache()
|
||||
{
|
||||
public void resetConfigCache() {
|
||||
clearConfigCache();
|
||||
loadingConfigCache();
|
||||
}
|
||||
@ -208,12 +187,10 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public String checkConfigKeyUnique(SysConfig config)
|
||||
{
|
||||
public String checkConfigKeyUnique(SysConfig config) {
|
||||
Long configId = StringUtils.isNull(config.getConfigId()) ? -1L : config.getConfigId();
|
||||
SysConfig info = configMapper.checkConfigKeyUnique(config.getConfigKey());
|
||||
if (StringUtils.isNotNull(info) && info.getConfigId().longValue() != configId.longValue())
|
||||
{
|
||||
if (StringUtils.isNotNull(info) && info.getConfigId().longValue() != configId.longValue()) {
|
||||
return UserConstants.NOT_UNIQUE;
|
||||
}
|
||||
return UserConstants.UNIQUE;
|
||||
@ -225,8 +202,7 @@ public class SysConfigServiceImpl implements ISysConfigService
|
||||
* @param configKey 参数键
|
||||
* @return 缓存键key
|
||||
*/
|
||||
private String getCacheKey(String configKey)
|
||||
{
|
||||
private String getCacheKey(String configKey) {
|
||||
return CacheConstants.SYS_CONFIG_KEY + configKey;
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,71 +226,6 @@
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="hover" style="margin: 10px 10px 20px 10px" class="phone-card">
|
||||
<el-row :gutter="40">
|
||||
<el-col :xs="24" :sm="24" :md="10" :lg="10" :xl="10" style="padding: 40px">
|
||||
<div style="padding: 30px; margin: 20px 0; font-size: 14px">
|
||||
<div style="font-size: 28px; font-weight: bold; margin-bottom: 20px">{{ $t('views.index.394840-0') }}</div>
|
||||
<div style="display: table; font-size: 14px; margin-bottom: 10px">
|
||||
<div style="display: table-cell; line-height: 22px">
|
||||
<b style="color: #67c23a; margin-right: 10px">{{ $t('views.index.394840-1') }}</b>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: table; margin-bottom: 10px">
|
||||
<div style="width: 70px; font-weight: bold; display: table-cell">{{ $t('views.index.394840-2') }}</div>
|
||||
<div style="display: table-cell; line-height: 22px">{{ $t('views.index.394840-3') }}</div>
|
||||
</div>
|
||||
<div style="display: table">
|
||||
<div style="width: 70px; font-weight: bold; display: table-cell">{{ $t('views.index.394840-4') }}</div>
|
||||
<div style="display: table-cell; line-height: 22px">
|
||||
{{ $t('views.index.394840-5') }}
|
||||
<br />
|
||||
<el-link target="_blank" href="https://fastbee.cn/doc/pages/sponsor">{{ $t('views.index.394840-6') }}</el-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 30px; font-size: 14px">
|
||||
<div style="float: left; width: 230px">
|
||||
<el-image style="width: 210px" :src="require('@/assets/images/code.jpg')"></el-image>
|
||||
</div>
|
||||
<div style="float: left">
|
||||
<div style="font-size: 18px; font-weight: bold; margin: 16px 0">{{ $t('views.index.394840-7') }}</div>
|
||||
<div style="font-size: 14px; font-weight: bold; margin: 16px 0; color: #f56c6c">{{ $t('views.index.394840-8') }}</div>
|
||||
<div style="display: table; margin-bottom: 10px">
|
||||
<div style="width: 70px; font-weight: bold; display: table-cell">{{ $t('views.index.394840-9') }}</div>
|
||||
<div style="display: table-cell">
|
||||
<el-link target="_blank" href="https://fastbee.cn/">www.fastbee.cn</el-link>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: table; margin-bottom: 10px">
|
||||
<div style="width: 70px; font-weight: bold; display: table-cell">{{ $t('views.index.394840-10') }}</div>
|
||||
<div style="display: table-cell">
|
||||
<el-link target="_blank" href="https://fastbee.cn/doc">www.fastbee.cn/doc</el-link>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: table; margin-bottom: 10px">
|
||||
<div style="width: 70px; font-weight: bold; display: table-cell">{{ $t('views.index.394840-11') }}</div>
|
||||
<div style="display: table-cell">
|
||||
<span>QQ 164770707</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: table; margin-bottom: 15px">
|
||||
<div style="width: 70px; font-weight: bold; display: table-cell">{{ $t('views.index.394840-12') }}</div>
|
||||
<div style="display: table-cell">
|
||||
<el-link target="_blank" href="https://gitee.com/kerwincui/wumei-smart" type="danger">{{ $t('views.index.394840-13') }}</el-link>
|
||||
<el-link target="_blank" href="https://github.com/kerwincui/fastbee" style="margin-left: 20px">{{ $t('views.index.394840-14') }}</el-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" style="padding: 40px">
|
||||
<div class="phone">
|
||||
<iframe src="https://fastbee.cn/h5" id="iframe" frameborder="0" scrolling="auto" height="100%" width="100%" class="phone-container"></iframe>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<!--通知公告详情 -->
|
||||
<el-dialog :title="notice.noticeTitle" :visible.sync="open" width="800px" append-to-body>
|
||||
@ -787,6 +722,9 @@ export default {
|
||||
this.$nextTick(() => {
|
||||
loadBMap().then(() => {
|
||||
this.getmap();
|
||||
}).catch((error) => {
|
||||
console.error('百度地图加载失败:', error);
|
||||
this.$message.error('百度地图加载失败,请检查API Key配置。错误信息:' + error.message);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
@ -47,7 +47,8 @@
|
||||
<el-form-item :class="{ 'is-null': true }">
|
||||
<div style="display: flex; text-align: center; justify-content: center">
|
||||
<el-link style="float: left; color: #a0a5a8; font-weight: normal" href="https://fastbee.cn/" :underline="false" target="_blank">{{ $t('register.974236-7') }}</el-link>
|
||||
<el-link style="float: left; color: #a0a5a8; font-weight: normal; margin-left: 20px" href="https://fastbee.cn/doc" :underline="false" target="_blank">{{ $t('register.974236-8') }}</el-link>
|
||||
<!-- 隐藏查看文档入口 -->
|
||||
<!-- <el-link style="float: left; color: #a0a5a8; font-weight: normal; margin-left: 20px" href="https://fastbee.cn/doc" :underline="false" target="_blank">{{ $t('register.974236-8') }}</el-link> -->
|
||||
<router-link style="float: left; color: #a0a5a8; font-weight: normal; margin-left: 20px" :to="{ path: '/login', query: this.$route.query }">{{ $t('register.974236-9') }}</router-link>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user