Pārlūkot izejas kodu

同步MINA最新代码

luoguangyi 2 gadi atpakaļ
vecāks
revīzija
b9ba304246

+ 6 - 5
pom.xml

@@ -72,11 +72,6 @@
         <!--		</dependency>-->
 
         <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-            <version>1.2.17</version>
-        </dependency>
-        <dependency>
             <groupId>dom4j</groupId>
             <artifactId>dom4j</artifactId>
             <version>1.6.1</version>
@@ -142,6 +137,12 @@
             <artifactId>bcprov-jdk15</artifactId>
             <version>140</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.11</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
     <build>
         <finalName>${project.artifactId}</finalName>

+ 88 - 0
src/main/java/com/persagy/communication/mina/queue/MsgQueue.java

@@ -0,0 +1,88 @@
+package com.persagy.communication.mina.queue;
+
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/***
+ * https://www.cnblogs.com/crazymakercircle/p/13934429.html
+ * 2.1BlockingQueue的核心方法
+ * 1.放入数据
+ * (1)offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false.(本方法不阻塞当前执行方法的线程);      
+ * (2)offer(E o, long timeout, TimeUnit unit):可以设定等待的时间,如果在指定的时间内,还不能往队列中加入BlockingQueue,则返回失败。
+ * (3)put(anObject):把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续.
+ *
+ * 2 获取数据
+ * (1)poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null;
+ * (2)poll(long timeout, TimeUnit unit):从BlockingQueue取出一个队首的对象,如果在指定时间内,队列一旦有数据可取,则立即返回队列中的数据。否则直到时间超时还没有数据可取,返回失败。
+ * (3)take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的数据被加入;
+ * (4)drainTo():一次性从BlockingQueue获取所有可用的数据对象(还可以指定获取数据的个数),通过该方法,可以提升获取数据效率;不需要多次分批加锁或释放锁。
+ *
+ * @author lgy
+ * @date 2022/4/15 18:00
+ */
+@Slf4j
+public class MsgQueue<T> {
+    //队列大小
+    private int queueMaxSize = Integer.MAX_VALUE;
+
+
+    private final BlockingQueue<T> blockingQueue = new LinkedBlockingQueue<>(queueMaxSize);
+
+    public MsgQueue() {
+    }
+
+    public MsgQueue(int queueMaxSize) {
+        this.queueMaxSize=queueMaxSize;
+    }
+    //生产入队
+    public void put(T msg){
+        try {
+            blockingQueue.put(msg);
+        } catch (Exception e) {
+            log.error(e.getMessage(),e);
+        }
+    }
+
+    //消费出队
+    public  T consume() throws InterruptedException {
+        return blockingQueue.take();
+    }
+    //消费出列,非阻塞方法
+    public int drainTo(Collection<? super T> c, int maxElements) throws InterruptedException {
+        return blockingQueue.drainTo(c, maxElements);
+    }
+    //消费出列,阻塞方法
+    public int drainToBlocking(Collection<? super T> c, int maxElements) throws InterruptedException {
+        int count = blockingQueue.drainTo(c, maxElements);
+        if(count >0){
+            return count;
+        }
+        c.add(blockingQueue.take());
+        return 1;
+    }
+    //消费出列,阻塞方法
+    public List<T> drainToBlocking(int maxElements) throws InterruptedException {
+        List<T> c = new ArrayList<>();
+        int count = blockingQueue.drainTo(c, maxElements);
+        if(count >0){
+            return c;
+        }
+        c.add(blockingQueue.take());
+        return c;
+    }
+    // 获取队列大小
+    public int size() {
+        return blockingQueue.size();
+    }
+
+    public BlockingQueue<T> getBlockingQueue() {
+        return blockingQueue;
+    }
+
+}

+ 1 - 1
src/main/java/com/persagy/communication/mina/tcp/client/TCPClientManager.java

@@ -344,7 +344,6 @@ public class TCPClientManager implements IClientManager {
                 }
                 int readBufferSize = connectorInner.getSessionConfig().getReadBufferSize();
                 connectorInner.getSessionConfig().setReadBufferSize(20480);
-                log.info("readBufferSize:{}", readBufferSize);
 
                 ConnectFuture connectFuture = connectorInner.connect(new InetSocketAddress(this.ip, this.port));
                 connectFuture.awaitUninterruptibly();
@@ -387,6 +386,7 @@ public class TCPClientManager implements IClientManager {
 
     @Override
     public void AppendToSend(Packet MyPackage) {
+
         if (this.session == null) {
             this.Start();
         }

+ 45 - 0
src/main/java/com/persagy/communication/mina/tcp/server/TCPServerManager.java

@@ -1,8 +1,11 @@
 package com.persagy.communication.mina.tcp.server;
 
+import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.core.util.StrUtil;
 import com.persagy.communication.entity.Packet;
 import com.persagy.communication.entity.PacketEntity;
 import com.persagy.communication.mina.codec.MinaCodecFactory;
+import com.persagy.communication.mina.queue.MsgQueue;
 import com.persagy.communication.util.IServerHandler;
 import com.persagy.communication.util.IServerManager;
 import com.persagy.communication.util.MySslContextFactory;
@@ -12,6 +15,7 @@ import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.mina.core.session.IoSession;
 import org.apache.mina.filter.codec.ProtocolCodecFactory;
 import org.apache.mina.filter.codec.ProtocolCodecFilter;
@@ -21,7 +25,9 @@ import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
 import java.net.InetSocketAddress;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @Slf4j
 @Data
@@ -31,6 +37,8 @@ import java.util.Map;
 public class TCPServerManager implements IServerManager {
     public final Map<String, Date> connectDateMap = new HashMap<String, Date>();
     public final PacketBuffer<PacketEntity> receList = new PacketBuffer<PacketEntity>();
+    public final MsgQueue<ImmutablePair<String,Packet>> sendQueue = new MsgQueue<>();
+
     //address-IoSession
     public final Map<String, IoSession> socketMap = new HashMap<String, IoSession>();
     String ip;
@@ -441,4 +449,41 @@ public class TCPServerManager implements IServerManager {
     public synchronized void hasRemark(int count) {
         remark_count = count;
     }
+
+
+    private void startSend() {
+        ThreadUtil.execAsync(()->{
+            while (true){
+                try {
+                    List<ImmutablePair<String, Packet>> immutablePairs = sendQueue.drainToBlocking(100);
+                    Map<String, List<ImmutablePair<String, Packet>>> listMap = immutablePairs.stream().collect(Collectors.groupingBy(ImmutablePair::getLeft));
+                    for (Map.Entry<String, List<ImmutablePair<String, Packet>>> entry : listMap.entrySet()) {
+                        String clientAddress = entry.getKey();
+                        List<String> packetStringList = entry.getValue().stream().map(item -> StrUtil.removeSuffix(item.getRight().packetString, "&")).collect(Collectors.toList());
+                        StringBuffer msgBuffer = new StringBuffer();
+                        for (int i = 0; i < packetStringList.size()-1; i++) {
+                            msgBuffer.append(packetStringList.get(i)).append("&");
+                            if(msgBuffer.length()>16000){
+                                sendPackage(clientAddress, new Packet(msgBuffer.toString()));
+                                msgBuffer = new StringBuffer();
+                            }
+                        }
+                        msgBuffer.append(packetStringList.get(packetStringList.size()-1));
+                        sendPackage(clientAddress, new Packet(msgBuffer.toString()));
+                    }
+                    if(immutablePairs.size()<5){
+                        ThreadUtil.safeSleep(5);
+                    }
+                } catch (Exception e) {
+                    log.error(e.getMessage(),e);
+                }
+            }
+        });
+    }
+    private void sendPackage(String clientAddress, Packet MyPackage) {
+        IoSession session = this.socketMap.get(clientAddress);
+        if (session != null) {
+            session.write(MyPackage);
+        }
+    }
 }

+ 51 - 5
src/main/java/com/persagy/communication/mina/udp/server/UDPServerManager.java

@@ -1,10 +1,12 @@
 package com.persagy.communication.mina.udp.server;
 
-import cn.hutool.core.util.NumberUtil;
+import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.core.util.StrUtil;
 import com.persagy.communication.entity.Packet;
 import com.persagy.communication.entity.PacketEntity;
 import com.persagy.communication.entity.UDPSendEntity;
 import com.persagy.communication.mina.codec.MinaCodecFactory;
+import com.persagy.communication.mina.queue.MsgQueue;
 import com.persagy.communication.util.IServerHandler;
 import com.persagy.communication.util.IServerManager;
 import com.persagy.communication.util.PacketBuffer;
@@ -12,6 +14,7 @@ import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.NoArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.mina.core.session.IoSession;
 import org.apache.mina.filter.codec.ProtocolCodecFactory;
 import org.apache.mina.filter.codec.ProtocolCodecFilter;
@@ -22,7 +25,9 @@ import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @Slf4j
 @Builder
@@ -30,6 +35,7 @@ import java.util.Map;
 @AllArgsConstructor
 public class UDPServerManager implements IServerManager {
     public final PacketBuffer<PacketEntity> receList = new PacketBuffer<PacketEntity>();
+    public final MsgQueue<ImmutablePair<String,Packet>> sendQueue = new MsgQueue<>();
     String ip;
     int port;
     String encoding;
@@ -153,10 +159,50 @@ public class UDPServerManager implements IServerManager {
         if (this.allowJustSend && !this.socketMap.containsKey(clientAddress)) {
             int index = clientAddress.indexOf(':');
             String remote_ip = clientAddress.substring(1, index);
-            int remote_port = NumberUtil.parseInt(clientAddress.substring(index + 1));
-            // newSession�ἤ��sessionCreated��sessionOpened
-            this.acceptor.newSession(new InetSocketAddress(remote_ip, remote_port),
-                    new InetSocketAddress(this.ip, this.port));
+            int remote_port = Integer.parseInt(clientAddress.substring(index + 1));
+            this.acceptor.newSession(new InetSocketAddress(remote_ip, remote_port),new InetSocketAddress(this.ip, this.port));
+        }
+        IoSession session = this.socketMap.get(clientAddress);
+        if (session != null) {
+            session.write(MyPackage);
+        }
+    }
+
+    private void startSend() {
+        ThreadUtil.execAsync(()->{
+            while (true){
+                try {
+                    List<ImmutablePair<String, Packet>> immutablePairs = sendQueue.drainToBlocking(100);
+                    Map<String, List<ImmutablePair<String, Packet>>> listMap = immutablePairs.stream().collect(Collectors.groupingBy(ImmutablePair::getLeft));
+                    for (Map.Entry<String, List<ImmutablePair<String, Packet>>> entry : listMap.entrySet()) {
+                        String clientAddress = entry.getKey();
+                        List<String> packetStringList = entry.getValue().stream().map(item -> StrUtil.removeSuffix(item.getRight().packetString, "&")).collect(Collectors.toList());
+                        StringBuffer msgBuffer = new StringBuffer();
+                        for (int i = 0; i < packetStringList.size()-1; i++) {
+                            msgBuffer.append(packetStringList.get(i)).append("&");
+                            if(msgBuffer.length()>16000){
+                                sendPackage(clientAddress, new Packet(msgBuffer.toString()));
+                                msgBuffer = new StringBuffer();
+                            }
+                        }
+                        msgBuffer.append(packetStringList.get(packetStringList.size()-1));
+                        sendPackage(clientAddress, new Packet(msgBuffer.toString()));
+                    }
+                    if(immutablePairs.size()<5){
+                        ThreadUtil.safeSleep(5);
+                    }
+                } catch (Exception e) {
+                    log.error(e.getMessage(),e);
+                }
+            }
+        });
+    }
+    private void sendPackage(String clientAddress, Packet MyPackage) {
+        if (this.allowJustSend && !this.socketMap.containsKey(clientAddress)) {
+            int index = clientAddress.indexOf(':');
+            String remote_ip = clientAddress.substring(1, index);
+            int remote_port = Integer.parseInt(clientAddress.substring(index + 1));
+            this.acceptor.newSession(new InetSocketAddress(remote_ip, remote_port),new InetSocketAddress(this.ip, this.port));
         }
         IoSession session = this.socketMap.get(clientAddress);
         if (session != null) {

+ 1 - 2
src/main/java/com/persagy/communication/netty/udp/server/NettyUDPServerManager.java

@@ -1,6 +1,5 @@
 package com.persagy.communication.netty.udp.server;
 
-import cn.hutool.core.util.NumberUtil;
 import com.persagy.communication.entity.Packet;
 import com.persagy.communication.entity.PacketEntity;
 import com.persagy.communication.entity.UDPSendEntity;
@@ -153,7 +152,7 @@ public class NettyUDPServerManager implements IServerManager {
             byte[] encoded = this.encoder.encode(packet);
             int index_ = clientAddress.indexOf(':');
             String ip = clientAddress.substring(1, index_);
-            int port = NumberUtil.parseInt(clientAddress.substring(index_ + 1));
+            int port = Integer.parseInt(clientAddress.substring(index_ + 1));
             InetSocketAddress remoteAddress = new InetSocketAddress(ip, port);
             channel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(encoded), remoteAddress));
 

+ 1 - 2
src/main/java/com/persagy/communication/nio/udp/server/NIOUDPServerManager.java

@@ -1,6 +1,5 @@
 package com.persagy.communication.nio.udp.server;
 
-import cn.hutool.core.util.NumberUtil;
 import com.persagy.communication.entity.Packet;
 import com.persagy.communication.entity.PacketEntity;
 import com.persagy.communication.entity.UDPSendEntity;
@@ -117,7 +116,7 @@ public class NIOUDPServerManager implements IServerManager {
             if (this.allowJustSend && !this.socketMap.containsKey(entity.address)) {
                 int index = entity.address.indexOf(':');
                 String remote_ip = entity.address.substring(1, index);
-                int remote_port = NumberUtil.parseInt(entity.address.substring(index + 1));
+                int remote_port = Integer.parseInt(entity.address.substring(index + 1));
                 this.socketMap.put(entity.address, new InetSocketAddress(remote_ip, remote_port));
             }
             UDPSendEntity result = new UDPSendEntity();

+ 10 - 11
src/main/java/com/persagy/communication/util/ASampleMain.java

@@ -1,6 +1,5 @@
 package com.persagy.communication.util;
 
-import cn.hutool.core.util.NumberUtil;
 import com.persagy.communication.entity.Packet;
 import com.persagy.communication.entity.PacketEntity;
 import com.persagy.communication.mina.udp.client.UDPClientManager;
@@ -24,34 +23,34 @@ public class ASampleMain {
         String server_or_client = args[index_args++];
         String ip = args[index_args++];
         String port_desc = args[index_args++];
-        int cycle_seconds = NumberUtil.parseInt(args[index_args++]);
+        int cycle_seconds = Integer.parseInt(args[index_args++]);
 
         int port_from;
         int port_to;
         int index_ = port_desc.indexOf("-");
         if (index_ == -1) {
-            port_from = NumberUtil.parseInt(port_desc);
-            port_to = NumberUtil.parseInt(port_desc);
+            port_from = Integer.parseInt(port_desc);
+            port_to = Integer.parseInt(port_desc);
         } else {
-            port_from = NumberUtil.parseInt(port_desc.substring(0, index_));
-            port_to = NumberUtil.parseInt(port_desc.substring(index_ + 1));
+            port_from = Integer.parseInt(port_desc.substring(0, index_));
+            port_to = Integer.parseInt(port_desc.substring(index_ + 1));
         }
         while (true) {
             if ("client".equalsIgnoreCase(server_or_client)) {
-                int count_each_port = NumberUtil.parseInt(args[index_args++]);
-                int sleep = NumberUtil.parseInt(args[index_args++]);
+                int count_each_port = Integer.parseInt(args[index_args++]);
+                int sleep = Integer.parseInt(args[index_args++]);
                 List<IClientManager> clientList;
                 if ("udp".equalsIgnoreCase(protocol)) {
                     String local_ip = args[index_args++];
-                    int local_port_start = NumberUtil.parseInt(args[index_args++]);
+                    int local_port_start = Integer.parseInt(args[index_args++]);
                     clientList = Init_UDPClient(ip, port_from, port_to, count_each_port, local_ip, local_port_start);
                 } else {
                     clientList = Init_TCPClient(ip, port_from, port_to, count_each_port);
                 }
                 Process_client(clientList, cycle_seconds, sleep);
             } else if ("ssl_client".equalsIgnoreCase(server_or_client)) {
-                int count_each_port = NumberUtil.parseInt(args[index_args++]);
-                int sleep = NumberUtil.parseInt(args[index_args++]);
+                int count_each_port = Integer.parseInt(args[index_args++]);
+                int sleep = Integer.parseInt(args[index_args++]);
                 List<IClientManager> clientList;
                 if ("tcp".equalsIgnoreCase(protocol)) {
                     clientList = Init_SSLTCPClient(ip, port_from, port_to, count_each_port);

+ 0 - 6
src/main/java/com/persagy/communication/util/PacketBuffer.java

@@ -11,9 +11,6 @@ public class PacketBuffer<T> {
     public PacketBuffer() {
     }
 
-    // put �����������������
-    // add ��������������쳣
-    // offer �����������������false
     public void offer(T packet, int size) {
         if (this.buffer.size() >= size) {
             return;
@@ -22,9 +19,6 @@ public class PacketBuffer<T> {
         this.buffer.offer(packet);
     }
 
-    // take ��������ѿգ�����
-    // remove ��������ѿգ��쳣
-    // poll ��������ѿգ�����null
     public T poll() {
         T MyPackage = null;
         try {

+ 3 - 3
src/main/resources/config.xml

@@ -5,8 +5,8 @@
 	<mqtt url="tcp://127.0.0.1:61613" clientId="simulator-collector-4403070003" username="admin" password="password" topic_prefix="project" />
 	
 	<PROTOCOL>TCP</PROTOCOL>
-	<ServerIP>127.0.0.1</ServerIP>
-	<ServerPort>8853</ServerPort>
+	<ServerIP>192.168.100.102</ServerIP>
+	<ServerPort>30054</ServerPort>
 	<Mode>mina</Mode>
 	<Max_size>10000</Max_size>
 	<SleepCount>1000</SleepCount>
@@ -18,7 +18,7 @@
 	<pointupload_period_second>300</pointupload_period_second>
 	<BatchSend>true</BatchSend>
 	<BatchCount>100</BatchCount>
-	<TimeStart_enable>false</TimeStart_enable>
+	<TimeStart_enable>true</TimeStart_enable>
 	<TimeStart>20211101000000</TimeStart>
 	<TimeBeiShu>360000</TimeBeiShu>
 	

+ 0 - 20
src/main/resources/log4j.properties

@@ -1,20 +0,0 @@
-log4j.rootLogger=INFO,ConsoleAppender,RollingLogFileAppender
-#print file   org.apache.log4j.DailyRollingFileAppender
-log4j.appender.RollingLogFileAppender=org.apache.log4j.RollingFileAppender
-log4j.appender.RollingLogFileAppender.Threshold=INFO
-log4j.appender.RollingLogFileAppender.ImmediateFlush=false
-log4j.appender.RollingLogFileAppender.File=../logs/simulator-collector/log.log
-log4j.appender.RollingLogFileAppender.Append=true
-log4j.appender.RollingLogFileAppender.MaxFileSize=20MB
-log4j.appender.RollingLogFileAppender.Encoding=UTF-8
-log4j.appender.RollingLogFileAppender.MaxBackupIndex=100
-log4j.appender.RollingLogFileAppender.layout=org.apache.log4j.PatternLayout
-log4j.appender.RollingLogFileAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}:%-5p %l - %m%n
-#print Console
-log4j.appender.ConsoleAppender=org.apache.log4j.ConsoleAppender
-log4j.appender.ConsoleAppender.Threshold=INFO
-log4j.appender.ConsoleAppender.ImmediateFlush=true
-log4j.appender.ConsoleAppender.Target=System.out
-log4j.appender.ConsoleAppender.layout=org.apache.log4j.PatternLayout
-log4j.appender.ConsoleAppender.Encoding=UTF-8
-log4j.appender.ConsoleAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} %m%n

+ 100 - 0
src/main/resources/logback-spring.xml

@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--scan:  当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
+scanPeriod:  设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
+debug:  当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
+configuration 子节点为 appender、logger、root       -->
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
+    <!--用于区分不同应用程序的记录-->
+    <contextName>simulator-collector</contextName>
+    <!--日志文件所在目录,如果是tomcat,如下写法日志文件会在则为${TOMCAT_HOME}/bin/logs/目录下-->
+    <property name="LOG_HOME" value="../logs/simulator-collector"/>
+    <!--
+    %p:输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
+    %r:输出自应用启动到输出该日志讯息所耗费的毫秒数
+    %t:输出产生该日志事件的线程名
+    %f:输出日志讯息所属的类别的类别名
+    %c:输出日志讯息所属的类的全名
+    %d:输出日志时间点的日期或时间,指定格式的方式: %d{yyyy-MM-dd HH:mm:ss}
+    %l:输出日志事件的发生位置,即输出日志讯息的语句在他所在类别的第几行。
+    %m:输出代码中指定的讯息,如log(message)中的message
+    %n:输出一个换行符号
+-->
+    <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
+    <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}  %-5level %logger{36}  %msg%n"/>
+
+    <!--控制台-->
+    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+        <!-- 字符串System.out(默认)或者System.err -->
+        <target>System.out</target>
+        <!-- ThresholdFilter:临界值过滤器,过滤掉 TRACE 和 DEBUG 级别的日志 -->
+<!--        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
+<!--            <level>WARN</level>-->
+<!--        </filter>-->
+        <!-- 对记录事件进行格式化 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${pattern}</pattern>
+            <!--解决乱码问题-->
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+    <!--滚动文件-->
+    <appender name="infoFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建 -->
+        <file>${LOG_HOME}/log.log</file>
+        <!-- ThresholdFilter:临界值过滤器,过滤掉 TRACE 和 DEBUG 级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--查看   gunzip -c xx.log.gz | less-->
+            <fileNamePattern>${LOG_HOME}/log.%d{yyyy-MM-dd}.log.%i.gz</fileNamePattern>
+            <totalSizeCap>600MB</totalSizeCap>
+            <maxHistory>50</maxHistory><!--保存最近30天的日志-->
+        </rollingPolicy>
+        <encoder>
+            <charset>UTF-8</charset>
+            <pattern>${pattern}</pattern>
+        </encoder>
+    </appender>
+    <!--滚动文件-->
+    <appender name="errorFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- ThresholdFilter:临界值过滤器,过滤掉 TRACE 和 DEBUG 级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>error</level>
+        </filter>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <fileNamePattern>${LOG_HOME}/error.%d{yyyy-MM-dd}.log.%i.gz</fileNamePattern>
+            <maxHistory>30</maxHistory><!--保存最近30天的日志-->
+            <totalSizeCap>2GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <encoder>
+            <charset>UTF-8</charset>
+            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%thread] %-5level %logger{36} : %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <!--将日志输出到logstack-->
+    <!--<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
+        <destination>47.93.173.81:7002</destination>
+        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
+            <charset>UTF-8</charset>
+        </encoder>
+        <keepAliveDuration>5 minutes</keepAliveDuration>
+    </appender>-->
+
+    <!--这里如果是info,spring、mybatis等框架则不会输出:TRACE < DEBUG < INFO <  WARN < ERROR-->
+    <!--root是所有logger的祖先,均继承root,如果某一个自定义的logger没有指定level,就会寻找
+    父logger看有没有指定级别,直到找到root。-->
+    <root level="INFO">
+        <appender-ref ref="stdout"/>
+        <appender-ref ref="infoFile"/>
+        <appender-ref ref="errorFile"/>
+    </root>
+</configuration>

BIN
src/main/resources/report.xlsx


src/main/resources/set.xlsx → src/main/resources/set1.xlsx