m2pool项目提交

Signed-off-by: jxy_duyi <2826961034@qq.com>
This commit is contained in:
jxy_duyi
2025-04-10 18:44:21 +08:00
parent faaeb24007
commit c4f34073c4
508 changed files with 50991 additions and 0 deletions

View File

@@ -0,0 +1,213 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>m2pool-modules</artifactId>
<groupId>com.m2pool</groupId>
<version>3.5.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>m2pool-chat</artifactId>
<!-- <packaging>war</packaging>-->
<!-- <dependencies>-->
<!-- <dependency>-->
<!-- <groupId>junit</groupId>-->
<!-- <artifactId>junit</artifactId>-->
<!-- <version>4.13.1</version>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- </dependencies>-->
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- Mysql Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<scope>provided</scope>
</dependency>
<!-- &lt;!&ndash; Mybatis-Plus &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.baomidou</groupId>-->
<!-- <artifactId>mybatis-plus-boot-starter</artifactId>-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <artifactId>jsqlparser</artifactId>-->
<!-- <groupId>com.github.jsqlparser</groupId>-->
<!-- </exclusion>-->
<!--&lt;!&ndash; <exclusion>&ndash;&gt;-->
<!--&lt;!&ndash; <artifactId>mybatis</artifactId>&ndash;&gt;-->
<!--&lt;!&ndash; <groupId>org.mybatis</groupId>&ndash;&gt;-->
<!--&lt;!&ndash; </exclusion>&ndash;&gt;-->
<!-- </exclusions>-->
<!-- </dependency>-->
<!-- M2Pool Common DataSource -->
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-datasource</artifactId>
</dependency>
<!-- M2Pool Common security -->
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-security</artifactId>
</dependency>
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-log</artifactId>
</dependency>
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-swagger</artifactId>
</dependency>
<!-- WebSocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.3.5</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
<scope>compile</scope>
</dependency>
<!--google两步认证相关-->
<dependency>
<groupId>de.taimos</groupId>
<artifactId>totp</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
<profiles>
<profile>
<!-- 本地环境 -->
<id>dev</id>
<properties>
<spring.profile>dev</spring.profile>
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
</properties>
<activation>
<!-- 是否默认激活 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<!-- 测试环境 -->
<id>test</id>
<properties>
<spring.profile>test</spring.profile>
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
<profile>
<!-- 生产环境 -->
<id>prod</id>
<properties>
<spring.profile>prod</spring.profile>
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
</profiles>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,34 @@
package com.m2pool.chat;
import com.m2pool.common.security.annotation.EnableCustomConfig;
import com.m2pool.common.security.annotation.EnableM2PoolFeignClients;
import com.m2pool.common.swagger.annotation.EnableCustomSwagger2;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @Description 在线客服服务入口类
* @Date 2025/2/25 10:42
* @Author dy
*/
@EnableCustomConfig
@EnableCustomSwagger2
@EnableM2PoolFeignClients
@SpringBootApplication
@MapperScan({"com.m2pool.chat.mapper"})
public class M2ChatApplication {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(M2ChatApplication.class,args);
System.out.println("m2pool矿池 开放api微服务启动成功");
}
}

View File

@@ -0,0 +1,21 @@
package com.m2pool.chat.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import javax.websocket.server.ServerEndpointConfig;
/**
* @Description TODO
* @Date 2025/2/25 14:43
* @Author 杜懿
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}

View File

@@ -0,0 +1,45 @@
package com.m2pool.chat.controller;
import com.m2pool.chat.entity.ChatMessage;
import com.m2pool.chat.entity.ChatMsg;
import com.m2pool.chat.service.ChatService;
import com.m2pool.chat.service.WebSocketServer;
import com.m2pool.chat.vo.ChatHistoryVo;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.core.web.controller.BaseController;
import com.m2pool.system.api.entity.SysUser;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
/**
* @Description TODO
* @Date 2025/2/24 15:05
* @Author 杜懿
*/
@RestController
@RequestMapping("/chat")
public class ChatController extends BaseController {
@Resource
private ChatService chatService;
//@Resource
// //private WebSocketServer webSocketServer;
@GetMapping("/history")
public AjaxResult getChatHistory(@RequestBody ChatHistoryVo vo) {
if(StringUtils.isNull(vo)){
return AjaxResult.error("请求参数为空");
}
String identifier = StringUtils.isNotBlank(vo.getEmail()) ? vo.getEmail() : vo.getBrowserId();
return chatService.getHistory(identifier);
}
}

View File

@@ -0,0 +1,22 @@
package com.m2pool.chat.entity;
import lombok.Data;
import java.util.Date;
/**
* @Description TODO
* @Date 2025/3/7 15:53
* @Author 杜懿
*/
@Data
public class ChatMessage {
private Long id;
private String senderType; // USER 0/CUSTOMER_SERVICE 1
private String senderId; // 邮箱或客服ID
private String receiverId;
private String content;
private String userIdentifier; // 邮箱或浏览器指纹
private String browserFingerprint;
private Date createdTime;
}

View File

@@ -0,0 +1,60 @@
package com.m2pool.chat.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import java.util.Date;
/**
* @Description TODO
* @Date 2025/2/28 18:11
* @Author 杜懿
*/
@Data
public class ChatMsg {
@Id
private String id;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy_MM_dd_HH_mm_ss")
private Date createTime=new Date();
/**
* 通信keysendId_receiveId
*/
private String msgKey;
/**
* 通信消息
*/
private String chatMsg;
/**
* 发送id
*/
private String sendId;
/**
* 接收id
*/
private String receiveId;
/**
* 查看状态 0未看 1已看
*/
private String readState;
/**
*1为我 0 为他
*/
@Transient
private Integer flag;
@Transient
private String name;
}

View File

@@ -0,0 +1,20 @@
package com.m2pool.chat.mapper;
import com.m2pool.chat.entity.ChatMessage;
import com.m2pool.common.datasource.annotation.Master;
import org.apache.ibatis.annotations.Param;
import javax.validation.constraints.Pattern;
import java.util.List;
/**
* @Description 角色数据层
* @Date 2024/6/12 17:37
* @Author dy
*/
@Master
public interface ChatMapper {
public boolean insert(@Param("vo") ChatMessage vo);
}

View File

@@ -0,0 +1,30 @@
package com.m2pool.chat.service;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.system.api.entity.SysUser;
import org.springframework.cache.CacheManager;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description TODO
* @Date 2025/2/28 18:06
* @Author 杜懿
*/
public interface ChatService {
//public AjaxResult userList(UserItem userItem, SysUser data);
public AjaxResult getHistory(String identifier);
}

View File

@@ -0,0 +1,169 @@
package com.m2pool.chat.service;
import com.alibaba.fastjson.JSONObject;
import com.m2pool.chat.entity.ChatMsg;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Description TODO
* @Date 2025/2/28 18:02
* @Author 杜懿
*/
@ServerEndpoint(value = "/ws/asset")
@Component
public class WebSocketServer {
private static ChatService chatService;
@Autowired
public void setChatService(ChatService chatService) {
WebSocketServer.chatService = chatService;
}
@PostConstruct
public void init() {
System.out.println("websocket 加载");
}
private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
private static final AtomicInteger OnlineCount = new AtomicInteger(0);
// concurrent包的线程安全Set用来存放每个客户端对应的Session对象。
private static CopyOnWriteArraySet<Session> SessionSet = new CopyOnWriteArraySet<Session>();
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session) {
SessionSet.add(session);
int cnt = OnlineCount.incrementAndGet();
log.info("有连接加入,当前连接数为:{}", cnt);
SendMessage(session, "连接成功");
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
SessionSet.remove(session);
int cnt = OnlineCount.decrementAndGet();
log.info("有连接关闭,当前连接数为:{}", cnt);
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("来自客户端的消息:{}",message);
try{
JSONObject jsonObject = JSONObject.parseObject(message);
String linkType = jsonObject.getString("linkType");
String sendId = jsonObject.getString("sendId");
if (linkType.equals("bind")){
//CacheManager.set("bind_"+sendId,session);
SendMessage(session, "连接成功");
}else if (linkType.equals("msg")){
//聊天
ChatMsg msg = new ChatMsg();
//发消息
String chatMsg = jsonObject.getString("chatMsg");
String receiveId = jsonObject.getString("receiveId");
msg.setChatMsg(chatMsg);
msg.setSendId(sendId);
msg.setMsgKey(sendId+"_"+receiveId);
msg.setReceiveId(receiveId);
msg.setReadState("0");
//chatService.sendOne(msg);
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 出现错误
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误:{}Session ID {}",error.getMessage(),session.getId());
error.printStackTrace();
}
/**
* 发送消息实践表明每次浏览器刷新session会发生变化。
* @param session
* @param message
*/
public static void SendMessage(Session session, String message) {
try {
//session.getBasicRemote().sendText(String.format("%s (From ServerSession ID=%s)",message,session.getId()));
log.info("sessionID="+session.getId());
session.getBasicRemote().sendText(message);
} catch (IOException e) {
log.error("发送消息出错:{}", e.getMessage());
e.printStackTrace();
}
}
/**
* 指定Session发送消息
* @param sessionId
* @param message
* @throws IOException
*/
public static void SendMessageById(String message,String sessionId) throws IOException {
Session session = null;
for (Session s : SessionSet) {
if(s.getId().equals(sessionId)){
session = s;
break;
}
}
if(session!=null){
SendMessage(session, message);
}
else{
log.warn("没有找到你指定ID的会话{}",sessionId);
}
}
/**
* @description: 指定发送
* @author: lvyq
* @date: 2021/9/24 11:30
* @version 1.0
*/
public static void SendMessageByRecId(String message,String receiveId) throws IOException {
//Session session= CacheManager.get("bind_"+receiveId);
Session session= null;
String sessionId = "";
if (session!=null){
sessionId=session.getId();
}
for (Session s : SessionSet) {
if(s.getId().equals(sessionId)){
session = s;
break;
}
}
if(session!=null){
SendMessage(session, message);
}
else{
System.out.println("没有找到你指定ID的会话"+sessionId);
}
}
}

View File

@@ -0,0 +1,37 @@
package com.m2pool.chat.service.impl;
import com.m2pool.chat.entity.ChatMessage;
import com.m2pool.chat.mapper.ChatMapper;
import com.m2pool.chat.service.ChatService;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.security.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
/**
* @Description TODO
* @Date 2025/2/28 18:08
* @Author 杜懿
*/
@Service
public class ChatServiceImpl implements ChatService {
@Autowired
private ChatMapper chatMapper;
@Async("messageExecutor")
public void saveMessageAsync(ChatMessage message) {
// 批量插入优化
chatMapper.insert(message);
}
@Override
public AjaxResult getHistory(String identifier) {
return null;
}
}

View File

@@ -0,0 +1,14 @@
package com.m2pool.chat.vo;
import lombok.Data;
/**
* @Description TODO
* @Date 2025/3/7 15:55
* @Author 杜懿
*/
@Data
public class ChatHistoryVo {
private String email;
private String browserId;
}

View File

@@ -0,0 +1,156 @@
server:
port: 9209
compression:
enabled: true
mime-types: application/json
spring:
#邮箱基本配置
mail:
# 配置在limit_time内用户可以发送limit次验证码
limit: 2 这个是我额外的配置,结合邮箱服务用的
limitTime: 10 这个是我额外的配置
#配置smtp服务主机地址
# sina smtp.sina.cn
# aliyun smtp.aliyun.com
# 163 smtp.163.com 端口号465或994
host: mail.privateemail.com
#发送者邮箱
username: support@m2pool.cc
#配置密码,注意不是真正的密码,而是刚刚申请到的授权码
# password:
# password: m2pool2024@!
# password: axvm-zfgx-cgcg-qhhu
password: m2pool2024@!
#端口号
port: 587
#默认的邮件编码为UTF-8
default-encoding: UTF-8
#其他参数
properties:
mail:
#配置SSL 加密工厂
smtp:
ssl:
#本地测试先放开ssl
enable: false
required: false
#开启debug模式这样邮件发送过程的日志会在控制台打印出来方便排查错误
debug: false
socketFactory:
class: javax.net.ssl.SSLSocketFactory
application:
# 应用名称
name: m2pool-chat
profiles:
# 环境配置
active: prod
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8808
namespace: m2_prod
group: m2_prod_group
# server-addr: 127.0.0.1:8808
config:
# 配置中心地址
server-addr: 127.0.0.1:8808
# server-addr: 127.0.0.1:8808
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: m2_prod
group: m2_prod_group
servlet:
multipart:
max-file-size: 2MB
max-request-size: 8MB
myenv:
domain: https://www.m2pool.com
path: /var/www/html/web
img: /img
#测试环境
#server:
# port: 9509
# compression:
# enabled: true
# mime-types: application/json
#
#spring:
# #邮箱基本配置
# mail:
# # 配置在limit_time内用户可以发送limit次验证码
# limit: 2 这个是我额外的配置,结合邮箱服务用的
# limitTime: 10 这个是我额外的配置
# #配置smtp服务主机地址
# # sina smtp.sina.cn
# # aliyun smtp.aliyun.com
# # 163 smtp.163.com 端口号465或994
# host: mail.privateemail.com
# #发送者邮箱
# username: support@m2pool.cc
# #配置密码,注意不是真正的密码,而是刚刚申请到的授权码
# # password:
# # password: m2pool2024@!
# # password: axvm-zfgx-cgcg-qhhu
# password: m2pool2024@!
# #端口号
# port: 587
# #默认的邮件编码为UTF-8
# default-encoding: UTF-8
# #其他参数
# properties:
# mail:
# #配置SSL 加密工厂
# smtp:
# ssl:
# #本地测试先放开ssl
# enable: false
# required: false
# #开启debug模式这样邮件发送过程的日志会在控制台打印出来方便排查错误
# debug: false
# socketFactory:
# class: javax.net.ssl.SSLSocketFactory
#
# application:
# # 应用名称
# name: m2pool-chat
# profiles:
# # 环境配置
# active: test
# cloud:
# nacos:
# discovery:
# # 服务注册地址
# server-addr: 127.0.0.1:8808
# namespace: m2_test
# group: m2_test_group
# # server-addr: 127.0.0.1:8808
# config:
# # 配置中心地址
# server-addr: 127.0.0.1:8808
# # server-addr: 127.0.0.1:8808
# # 配置文件格式
# file-extension: yml
# # 共享配置
# shared-configs:
# - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# namespace: m2_test
# group: m2_test_group
# servlet:
# multipart:
# max-file-size: 2MB
# max-request-size: 8MB
#
#myenv:
# domain: https://test.m2pool.com
# path: /var/www/html/web_test
# img: /imgpp
#

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/m2pool-chat" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 30天 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 30天 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.m2pool" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>