调整
This commit is contained in:
parent
8b72d7db64
commit
25321e3a7d
7
pom.xml
7
pom.xml
@ -301,9 +301,14 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<!-- <scope>test</scope>-->
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 开发工具 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- lombok -->
|
||||
<dependency>
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -19,10 +18,8 @@ import java.util.concurrent.TimeUnit;
|
||||
* @author lin
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DynamicTask {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DynamicTask.class);
|
||||
|
||||
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
|
||||
|
||||
private final Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();
|
||||
@ -48,9 +45,9 @@ public class DynamicTask {
|
||||
ScheduledFuture<?> future = futureMap.get(key);
|
||||
if (future != null) {
|
||||
if (future.isCancelled()) {
|
||||
logger.debug("任务【{}】已存在但是关闭状态!!!", key);
|
||||
log.debug("任务【{}】已存在但是关闭状态!!!", key);
|
||||
} else {
|
||||
logger.debug("任务【{}】已存在且已启动!!!", key);
|
||||
log.debug("任务【{}】已存在且已启动!!!", key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -59,9 +56,9 @@ public class DynamicTask {
|
||||
if (future != null){
|
||||
futureMap.put(key, future);
|
||||
runnableMap.put(key, task);
|
||||
logger.debug("任务【{}】启动成功!!!", key);
|
||||
log.debug("任务【{}】启动成功!!!", key);
|
||||
}else {
|
||||
logger.debug("任务【{}】启动失败!!!", key);
|
||||
log.debug("任务【{}】启动失败!!!", key);
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,12 +75,12 @@ public class DynamicTask {
|
||||
// 获取执行的时刻
|
||||
Instant startInstant = Instant.now().plusMillis(TimeUnit.MILLISECONDS.toMillis(delay));
|
||||
|
||||
ScheduledFuture future = futureMap.get(key);
|
||||
ScheduledFuture<?> future = futureMap.get(key);
|
||||
if (future != null) {
|
||||
if (future.isCancelled()) {
|
||||
logger.debug("任务【{}】已存在但是关闭状态!!!", key);
|
||||
log.debug("任务【{}】已存在但是关闭状态!!!", key);
|
||||
} else {
|
||||
logger.debug("任务【{}】已存在且已启动!!!", key);
|
||||
log.debug("任务【{}】已存在且已启动!!!", key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -92,9 +89,9 @@ public class DynamicTask {
|
||||
if (future != null){
|
||||
futureMap.put(key, future);
|
||||
runnableMap.put(key, task);
|
||||
logger.debug("任务【{}】启动成功!!!", key);
|
||||
log.debug("任务【{}】启动成功!!!", key);
|
||||
}else {
|
||||
logger.debug("任务【{}】启动失败!!!", key);
|
||||
log.debug("任务【{}】启动失败!!!", key);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,8 +26,8 @@
|
||||
package com.genersoft.iot.vmp.gb28181.auth;
|
||||
|
||||
import gov.nist.core.InternalErrorHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import javax.sip.address.URI;
|
||||
import javax.sip.header.AuthorizationHeader;
|
||||
@ -46,19 +46,14 @@ import java.util.Random;
|
||||
* @author M. Ranganathan
|
||||
* @author Marc Bednarek
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
public class DigestServerAuthenticationHelper {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(DigestServerAuthenticationHelper.class);
|
||||
|
||||
private MessageDigest messageDigest;
|
||||
private final MessageDigest messageDigest;
|
||||
|
||||
public static final String DEFAULT_ALGORITHM = "MD5";
|
||||
public static final String DEFAULT_SCHEME = "Digest";
|
||||
|
||||
|
||||
|
||||
|
||||
/** to hex converter */
|
||||
private static final char[] toHex = { '0', '1', '2', '3', '4', '5', '6',
|
||||
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
@ -93,8 +88,8 @@ public class DigestServerAuthenticationHelper {
|
||||
long pad = rand.nextLong();
|
||||
String nonceString = Long.valueOf(time).toString()
|
||||
+ Long.valueOf(pad).toString();
|
||||
byte mdbytes[] = messageDigest.digest(nonceString.getBytes());
|
||||
return toHexString(mdbytes);
|
||||
byte[] mdBytes = messageDigest.digest(nonceString.getBytes());
|
||||
return toHexString(mdBytes);
|
||||
}
|
||||
|
||||
public Response generateChallenge(HeaderFactory headerFactory, Response response, String realm) {
|
||||
@ -138,12 +133,9 @@ public class DigestServerAuthenticationHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
String A2 = request.getMethod().toUpperCase() + ":" + uri.toString();
|
||||
String A2 = request.getMethod().toUpperCase() + ":" + uri;
|
||||
String HA1 = hashedPassword;
|
||||
|
||||
|
||||
byte[] mdbytes = messageDigest.digest(A2.getBytes());
|
||||
String HA2 = toHexString(mdbytes);
|
||||
|
||||
@ -177,7 +169,7 @@ public class DigestServerAuthenticationHelper {
|
||||
String realm = authHeader.getRealm().trim();
|
||||
String username = authHeader.getUsername().trim();
|
||||
|
||||
if ( username == null || realm == null ) {
|
||||
if(ObjectUtils.anyNull(username,realm)){
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -196,26 +188,22 @@ public class DigestServerAuthenticationHelper {
|
||||
// nonce计数器,是一个16进制的数值,表示同一nonce下客户端发送出请求的数量
|
||||
int nc = authHeader.getNonceCount();
|
||||
String ncStr = String.format("%08x", nc).toUpperCase();
|
||||
// String ncStr = new DecimalFormat("00000000").format(nc);
|
||||
// String ncStr = new DecimalFormat("00000000").format(Integer.parseInt(nc + "", 16));
|
||||
String A1 = String.join(":",username , realm , pass);
|
||||
String A2 = String.join(":",request.getMethod().toUpperCase() , uri.toString());
|
||||
|
||||
String A1 = username + ":" + realm + ":" + pass;
|
||||
|
||||
String A2 = request.getMethod().toUpperCase() + ":" + uri.toString();
|
||||
|
||||
byte mdbytes[] = messageDigest.digest(A1.getBytes());
|
||||
byte[] mdbytes = messageDigest.digest(A1.getBytes());
|
||||
String HA1 = toHexString(mdbytes);
|
||||
logger.debug("A1: " + A1);
|
||||
logger.debug("A2: " + A2);
|
||||
log.debug("A1: " + A1);
|
||||
log.debug("A2: " + A2);
|
||||
mdbytes = messageDigest.digest(A2.getBytes());
|
||||
String HA2 = toHexString(mdbytes);
|
||||
logger.debug("HA1: " + HA1);
|
||||
logger.debug("HA2: " + HA2);
|
||||
log.debug("HA1: " + HA1);
|
||||
log.debug("HA2: " + HA2);
|
||||
// String cnonce = authHeader.getCNonce();
|
||||
logger.debug("nonce: " + nonce);
|
||||
logger.debug("nc: " + ncStr);
|
||||
logger.debug("cnonce: " + cnonce);
|
||||
logger.debug("qop: " + qop);
|
||||
log.debug("nonce: " + nonce);
|
||||
log.debug("nc: " + ncStr);
|
||||
log.debug("cnonce: " + cnonce);
|
||||
log.debug("qop: " + qop);
|
||||
String KD = HA1 + ":" + nonce;
|
||||
|
||||
if (qop != null && qop.equalsIgnoreCase("auth") ) {
|
||||
@ -228,12 +216,12 @@ public class DigestServerAuthenticationHelper {
|
||||
KD += ":" + qop;
|
||||
}
|
||||
KD += ":" + HA2;
|
||||
logger.debug("KD: " + KD);
|
||||
log.debug("KD: " + KD);
|
||||
mdbytes = messageDigest.digest(KD.getBytes());
|
||||
String mdString = toHexString(mdbytes);
|
||||
logger.debug("mdString: " + mdString);
|
||||
log.debug("mdString: " + mdString);
|
||||
String response = authHeader.getResponse();
|
||||
logger.debug("response: " + response);
|
||||
log.debug("response: " + response);
|
||||
return mdString.equals(response);
|
||||
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ import gov.nist.javax.sip.address.SipUri;
|
||||
import gov.nist.javax.sip.header.SIPDateHeader;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -43,32 +43,26 @@ import java.util.Locale;
|
||||
/**
|
||||
* SIP命令类型: REGISTER请求
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class RegisterRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {
|
||||
public static final String METHOD = "REGISTER";
|
||||
|
||||
private final SipConfig sipConfig;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(RegisterRequestProcessor.class);
|
||||
private final SIPProcessorObserver sipProcessorObserver;
|
||||
|
||||
public final String method = "REGISTER";
|
||||
private final IDeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private SipConfig sipConfig;
|
||||
private final SIPSender sipSender;
|
||||
|
||||
@Autowired
|
||||
private SIPProcessorObserver sipProcessorObserver;
|
||||
|
||||
@Autowired
|
||||
private IDeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private SIPSender sipSender;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
private final UserSetting userSetting;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// 添加消息处理的订阅
|
||||
sipProcessorObserver.addRequestProcessor(method, this);
|
||||
sipProcessorObserver.addRequestProcessor(METHOD, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,8 +76,8 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
|
||||
RequestEventExt evtExt = (RequestEventExt) evt;
|
||||
|
||||
SIPRequest request = (SIPRequest)evt.getRequest();
|
||||
Response response = null;
|
||||
boolean passwordCorrect = false;
|
||||
Response response;
|
||||
boolean passwordCorrect;
|
||||
// 注册标志
|
||||
boolean registerFlag;
|
||||
FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
|
||||
@ -96,11 +90,11 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
|
||||
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request,
|
||||
userSetting.getSipUseSourceIpAsRemoteAddress());
|
||||
String requestAddress = remoteAddressInfo.getIp() + ":" + remoteAddressInfo.getPort();
|
||||
logger.info("[注册请求] 设备:{}, 开始处理: {}", deviceId, requestAddress);
|
||||
log.info("[注册请求] 设备:{}, 开始处理: {}", deviceId, requestAddress);
|
||||
if (device != null &&
|
||||
device.getSipTransactionInfo() != null &&
|
||||
request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) {
|
||||
logger.info("[注册请求] 设备:{}, 注册续订: {}",device.getDeviceId(), device.getDeviceId());
|
||||
log.info("[注册请求] 设备:{}, 注册续订: {}",device.getDeviceId(), device.getDeviceId());
|
||||
device.setExpires(request.getExpires().getExpires());
|
||||
device.setIp(remoteAddressInfo.getIp());
|
||||
device.setPort(remoteAddressInfo.getPort());
|
||||
@ -120,7 +114,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
|
||||
String password = (device != null && !ObjectUtils.isEmpty(device.getPassword()))? device.getPassword() : sipConfig.getPassword();
|
||||
AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
|
||||
if (authHead == null && !ObjectUtils.isEmpty(password)) {
|
||||
logger.info("[注册请求] 设备:{}, 回复401: {}",deviceId, requestAddress);
|
||||
log.info("[注册请求] 设备:{}, 回复401: {}",deviceId, requestAddress);
|
||||
response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request);
|
||||
new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain());
|
||||
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
||||
@ -135,7 +129,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
|
||||
// 注册失败
|
||||
response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
|
||||
response.setReasonPhrase("wrong password");
|
||||
logger.info("[注册请求] 设备:{}, 密码/SIP服务器ID错误, 回复403: {}", deviceId, requestAddress);
|
||||
log.info("[注册请求] 设备:{}, 密码/SIP服务器ID错误, 回复403: {}", deviceId, requestAddress);
|
||||
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
|
||||
return;
|
||||
}
|
||||
@ -199,16 +193,16 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
|
||||
// 注册成功
|
||||
// 保存到redis
|
||||
if (registerFlag) {
|
||||
logger.info("[注册成功] deviceId: {}->{}", deviceId, requestAddress);
|
||||
log.info("[注册成功] deviceId: {}->{}", deviceId, requestAddress);
|
||||
device.setRegisterTime(DateUtil.getNow());
|
||||
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
|
||||
deviceService.online(device, sipTransactionInfo);
|
||||
} else {
|
||||
logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
|
||||
log.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
|
||||
deviceService.offline(deviceId, "主动注销");
|
||||
}
|
||||
} catch (SipException | NoSuchAlgorithmException | ParseException e) {
|
||||
logger.error("未处理的异常 ", e);
|
||||
log.error("未处理的异常 ", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
|
||||
Request reqAck = headerProvider.createAckRequest(response.getLocalAddress().getHostAddress(), requestUri, response);
|
||||
|
||||
logger.info("[回复ack] {}-> {}:{} ", sdp.getOrigin().getUsername(), event.getRemoteIpAddress(), event.getRemotePort());
|
||||
logger.debug("{}",reqAck);
|
||||
sipSender.transmitRequest( response.getLocalAddress().getHostAddress(), reqAck);
|
||||
}
|
||||
} catch (InvalidArgumentException | ParseException | SipException | SdpParseException e) {
|
||||
|
@ -424,10 +424,8 @@ public class PlatformController {
|
||||
@PostMapping("/catalog/add")
|
||||
@ResponseBody
|
||||
public void addCatalog(@RequestBody PlatformCatalog platformCatalog) {
|
||||
logger.debug("添加目录,{}", JSON.toJSONString(platformCatalog));
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("添加目录,{}", JSON.toJSONString(platformCatalog));
|
||||
}
|
||||
PlatformCatalog platformCatalogInStore = storager.getCatalog(platformCatalog.getPlatformId(), platformCatalog.getId());
|
||||
|
||||
if (platformCatalogInStore != null) {
|
||||
|
@ -5,9 +5,8 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@ -22,15 +21,13 @@ import java.text.ParseException;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = "/api/v1/control")
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class ApiControlController {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ApiControlController.class);
|
||||
private final SIPCommander cmder;
|
||||
|
||||
@Autowired
|
||||
private SIPCommander cmder;
|
||||
|
||||
@Autowired
|
||||
private IVideoManagerStorage storager;
|
||||
private final IVideoManagerStorage storager;
|
||||
|
||||
/**
|
||||
* 设备控制 - 云台控制
|
||||
@ -47,8 +44,8 @@ public class ApiControlController {
|
||||
@RequestParam(required = false)String code,
|
||||
@RequestParam(required = false)Integer speed){
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("模拟接口> 设备云台控制 API调用,deviceId:{} ,channelId:{} ,command:{} ,speed:{} ",
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("模拟接口> 设备云台控制 API调用,deviceId:{} ,channelId:{} ,command:{} ,speed:{} ",
|
||||
serial, code, command, speed);
|
||||
}
|
||||
if (channel == null) {channel = 0;}
|
||||
@ -99,7 +96,7 @@ public class ApiControlController {
|
||||
try {
|
||||
cmder.frontEndCmd(device, code, cmdCode, speed, speed, speed);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 云台控制: {}", e.getMessage());
|
||||
log.error("[命令发送失败] 云台控制: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
@ -121,8 +118,8 @@ public class ApiControlController {
|
||||
@RequestParam(required = false)String name,
|
||||
@RequestParam(required = false)Integer preset){
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("模拟接口> 预置位控制 API调用,deviceId:{} ,channelId:{} ,command:{} ,name:{} ,preset:{} ",
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("模拟接口> 预置位控制 API调用,deviceId:{} ,channelId:{} ,command:{} ,name:{} ,preset:{} ",
|
||||
serial, code, command, name, preset);
|
||||
}
|
||||
|
||||
@ -148,7 +145,7 @@ public class ApiControlController {
|
||||
try {
|
||||
cmder.frontEndCmd(device, code, cmdCode, 0, preset, 0);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 预置位控制: {}", e.getMessage());
|
||||
log.error("[命令发送失败] 预置位控制: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -28,27 +29,19 @@ import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* API兼容:设备信息
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = "/api/v1/device")
|
||||
@RequiredArgsConstructor
|
||||
public class ApiDeviceController {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ApiDeviceController.class);
|
||||
private final IVideoManagerStorage storager;
|
||||
private final SIPCommander cmder;
|
||||
|
||||
@Autowired
|
||||
private IVideoManagerStorage storager;
|
||||
private final IDeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private SIPCommander cmder;
|
||||
@Autowired
|
||||
private IDeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private DeferredResultHolder resultHolder;
|
||||
private final DeferredResultHolder resultHolder;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -90,7 +90,7 @@
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
<logger name="com.genersoft.iot.vmp" level="info" additivity="true">
|
||||
<logger name="com.genersoft.iot.vmp" level="debug" additivity="true">
|
||||
<appender-ref ref="RollingFileError"/>
|
||||
<appender-ref ref="RollingFile"/>
|
||||
</logger>
|
||||
|
Loading…
Reference in New Issue
Block a user