Pu Zhibing
5 天以前 1ee76c252f2dbba62e0ec34cccf9eaac51de9083
修改bug
4个文件已删除
17个文件已修改
1277 ■■■■■ 已修改文件
ruoyi-modules/ruoyi-system/pom.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/CarController.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/OrderController.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/WarnController.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ICarService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CarServiceImpl.java 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DriverServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/WarnServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/JavaCVStreamUtil.java 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/TaskUtil.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/websocket/MyWebSocketHandler.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/websocket/SessionMap.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/websocket/WebSocketConfig.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/resources/logback.xml 293 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/resources/mapping/system/WarnMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-dataInterchange/src/main/java/com/ruoyi/dataInterchange/model/UPWarnMsgAdptInfo.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-dataInterchange/src/main/java/com/ruoyi/dataInterchange/netty/client/ChannelMap.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-dataInterchange/src/main/java/com/ruoyi/dataInterchange/netty/client/NettyClientHandler.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-dataInterchange/src/main/java/com/ruoyi/dataInterchange/util/haikang/Artemis.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-dataInterchange/src/main/java/com/ruoyi/dataInterchange/util/mqtt/MqttReceiverMessageHandler.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-dataInterchange/src/main/resources/logback.xml 293 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/pom.xml
@@ -131,21 +131,6 @@
            <artifactId>hutool-all</artifactId>
            <version>5.0.3</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv-platform</artifactId>
            <version>1.5.11</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>ffmpeg</artifactId>
            <version>7.1-1.5.11</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
    </dependencies>
    
    <build>
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/CarController.java
@@ -1,6 +1,5 @@
package com.ruoyi.system.controller;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
@@ -22,7 +21,6 @@
import com.ruoyi.system.service.ICarTypeService;
import com.ruoyi.system.service.IDriverService;
import com.ruoyi.system.service.IEnterpriseService;
import com.ruoyi.system.util.JavaCVStreamUtil;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
@@ -34,15 +32,10 @@
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
@@ -174,7 +167,6 @@
            return R.fail("失败");
        }
        String folderPath = hlsOutputPath + "hls\\" + car.getVehicleNumber();
        JavaCVStreamUtil.close(id, folderPath);
        return R.ok();
    }
    
@@ -310,48 +302,6 @@
            car.setCompanyCode(enterprise.getCode());
        }
        return R.ok(list);
    }
    public void live_hls(String input, Car car){
        String path = hlsOutputPath + "hls\\" + car.getVehicleNumber() + "\\live.m3u8";
        String folderPath = hlsOutputPath + "hls\\" + car.getVehicleNumber();
        FileUtil.mkParentDirs(path);
        File file = new File(path);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        //执行拉流和推流
        ExecutorService executorService = new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                JavaCVStreamUtil.push_hls(input, path, car.getId(), folderPath);
            }
        });
        carService.taskPlayDetection(car.getId());
    }
    public void live_flv(String input, Integer id){
        String url = "rtmp://" + flvIp + ":" + flvRtmpPort + "/flv/" + id;
        //执行拉流和推流
        ExecutorService executorService = new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                JavaCVStreamUtil.push_flv(input, url, id);
            }
        });
        carService.taskPlayDetection(id);
    }
    
    
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/OrderController.java
@@ -2,7 +2,6 @@
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.io.FileUtil;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.web.page.PageInfo;
import com.ruoyi.dataInterchange.api.feignClient.PlaybackMsgClient;
@@ -19,7 +18,6 @@
import com.ruoyi.system.service.IDriverService;
import com.ruoyi.system.service.IEnterpriseService;
import com.ruoyi.system.service.IOrderService;
import com.ruoyi.system.util.JavaCVStreamUtil;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
@@ -35,16 +33,12 @@
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
@@ -214,44 +208,4 @@
    }
    
    
    public void live_hls(String input, Car car){
        String path = hlsOutputPath + "hls\\" + car.getVehicleNumber() + "\\live.m3u8";
        String folderPath = hlsOutputPath + "hls\\" + car.getVehicleNumber();
        FileUtil.mkParentDirs(path);
        File file = new File(path);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        //执行拉流和推流
        ExecutorService executorService = new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                JavaCVStreamUtil.push_hls(input, path, car.getId(), folderPath);
            }
        });
        carService.taskPlayDetection(car.getId());
    }
    public void live_flv(String input, Integer id){
        String url = "rtmp://" + flvIp + ":" + flvRtmpPort + "/flv/" + id;
        //执行拉流和推流
        ExecutorService executorService = new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                JavaCVStreamUtil.push_flv(input, url, id);
            }
        });
        carService.taskPlayDetection(id);
    }
}
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/WarnController.java
@@ -110,17 +110,19 @@
        CarWarnInfoResp carWarnInfoResp = new CarWarnInfoResp();
        carWarnInfoResp.setVehicleNumber(vehicleNumber);
        GnssDataVo gnssDataVo = upExgMsgRealLocationClient.getVehicleSpeed(vehicleNumber).getData();
        carWarnInfoResp.setSpeed(new BigDecimal(gnssDataVo.getVec1()));
        Map<String, String> geocode = null;
        try {
            String longitude = new BigDecimal(gnssDataVo.getLon()).divide(new BigDecimal(1000000)).toString();
            String latitude = new BigDecimal(gnssDataVo.getLat()).divide(new BigDecimal(1000000)).toString();
            geocode = GDMapGeocodingUtil.geocode(longitude, latitude);
        } catch (Exception e) {
            throw new RuntimeException(e);
        if(null != gnssDataVo){
            carWarnInfoResp.setSpeed(new BigDecimal(gnssDataVo.getVec1()));
            Map<String, String> geocode = null;
            try {
                String longitude = new BigDecimal(gnssDataVo.getLon()).divide(new BigDecimal(1000000)).toString();
                String latitude = new BigDecimal(gnssDataVo.getLat()).divide(new BigDecimal(1000000)).toString();
                geocode = GDMapGeocodingUtil.geocode(longitude, latitude);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            String address = geocode.get("address");
            carWarnInfoResp.setNowAddress(address);
        }
        String address = geocode.get("address");
        carWarnInfoResp.setNowAddress(address);
        List<WarnResp> warnList = new ArrayList<>();
        for (Warn warn : list) {
            WarnResp warnResp = new WarnResp();
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ICarService.java
@@ -38,12 +38,6 @@
    void taskUpdateCarStatus();
    
    
    /**
     * 检测视频播放,清除没有播放的视频流
     * @return
     */
    void taskPlayDetection(Integer deviceNumber);
    
    /**
     * 定时任务获取出租车视频设备号
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CarServiceImpl.java
@@ -26,7 +26,6 @@
import com.ruoyi.system.service.ICarTypeService;
import com.ruoyi.system.service.IDriverService;
import com.ruoyi.system.service.IEnterpriseService;
import com.ruoyi.system.util.JavaCVStreamUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@@ -38,8 +37,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
@@ -84,8 +81,13 @@
        }
        List<Enterprise> list1 = enterpriseService.list();
        List<Driver> driverList = driverService.list(new LambdaQueryWrapper<Driver>().eq(Driver::getStatus, 1));
        List<Car> list2 = this.list();
        List<Car> carList = new ArrayList<>();
        for (UPExgMsgRegisterVo vo : list) {
            Optional<Car> first = list2.stream().filter(s -> s.getVehicleNumber().equals(vo.getVehicleNo())).findFirst();
            if(first.isPresent()){
                continue;
            }
            car = new Car();
            car.setVehicleNumber(vo.getVehicleNo());
            car.setLicensePlateColor(VehicleColorEnum.getName(vo.getVehicleColor()));
@@ -187,26 +189,7 @@
    }
    
    
    /**
     * 检测视频播放,清除没有播放的视频流
     */
    @Override
    public void taskPlayDetection(Integer deviceNumber) {
        Car car = this.getById(deviceNumber);
        try {
            ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
            executorService.scheduleWithFixedDelay(new Runnable() {
                @Override
                public void run() {
                    if(!redisTemplate.hasKey("live:" + car.getId())){
                        String folderPath = hlsOutputPath + "hls\\" + car.getVehicleNumber();
                        JavaCVStreamUtil.close(car.getId(), folderPath);
                    }
                }}, 1, 1, TimeUnit.MINUTES);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    
    
    
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/DriverServiceImpl.java
@@ -19,6 +19,7 @@
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
 * @author zhibing.pu
@@ -52,8 +53,13 @@
            return;
        }
        List<Enterprise> list1 = enterpriseService.list();
        List<Driver> list2 = driverService.list();
        List<Driver> driverList = new ArrayList<>();
        for (UPExgMsgReportDriverInfoVo vo : list) {
            Optional<Driver> first = list2.stream().filter(s -> s.getDrivingLicenseNumber().equals(vo.getDriverId())).findFirst();
            if(first.isPresent()){
                continue;
            }
            driver = new Driver();
            driver.setName(vo.getDriverName());
            driver.setDrivingLicenseNumber(vo.getDriverId());
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/WarnServiceImpl.java
@@ -75,6 +75,10 @@
        List<Car> carList = carService.list();
        List<Warn> warns = new ArrayList<>();
        for (UPWarnMsgAdptInfoVo vo : list) {
            long count = this.count(new LambdaQueryWrapper<Warn>().eq(Warn::getObjectId, vo.getInfoId()));
            if(0 != count){
                continue;
            }
            String warnTypeName = WarnType.getWarnTypeName(vo.getWarnType());
            warn = new Warn();
            Optional<Car> carOptional = carList.stream().filter(s -> s.getVehicleNumber().equals(vo.getVehicleNo())).findFirst();
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/JavaCVStreamUtil.java
File was deleted
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/TaskUtil.java
@@ -32,7 +32,7 @@
    /**
     * 定时任务获取新车辆数据
     */
    @Scheduled(fixedRate = 1000 * 60)
    @Scheduled(fixedRate = 1000 * 180)
    public void taskSaveNewCar() {
        carService.taskSaveNewCar();
        carService.taskSaveDriverId();
@@ -42,7 +42,7 @@
    /**
     * 定时任务获取新驾驶员数据
     */
    @Scheduled(fixedRate = 1000 * 60)
    @Scheduled(fixedRate = 1000 * 180)
    public void taskSaveNewDriver() {
        driverService.taskSaveNewDriver();
    }
@@ -51,7 +51,7 @@
    /**
     * 定时任务获取新报警数据
     */
    @Scheduled(fixedRate = 1000 * 60)
    @Scheduled(fixedRate = 1000 * 300)
    public void taskSaveNewWarn() {
        warnService.taskSaveNewWarn();
        warnService.taskSaveCarIdAndDriverId();
@@ -61,7 +61,7 @@
    /**
     * 定时任务修改预警信息处理结果
     */
    @Scheduled(fixedRate = 1000 * 600)
    @Scheduled(fixedRate = 1000 * 300)
    public void taskUpdateWarnStatus() {
        warnService.taskUpdateWarnStatus();
    }
@@ -70,7 +70,7 @@
    /**
     * 定时任务获取新订单数据
     */
    @Scheduled(fixedRate = 1000 * 60)
    @Scheduled(fixedRate = 1000 * 300)
    public void taskSaveNewOrder() {
        orderService.taskSaveNewOrder();
        orderService.taskSaveCarIdAndDriverId();
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/websocket/MyWebSocketHandler.java
File was deleted
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/websocket/SessionMap.java
File was deleted
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/util/websocket/WebSocketConfig.java
File was deleted
ruoyi-modules/ruoyi-system/src/main/resources/logback.xml
@@ -1,77 +1,222 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- 日志存放路径 -->
    <property name="log.path" value="/mnt/java/log/system" />
   <!-- 日志输出格式 -->
    <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>
            <charset>UTF-8</charset>
        </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>
            <!-- 日志最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
            <charset>UTF-8</charset>
        </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>
            <!-- 日志最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 过滤的级别 -->
            <level>ERROR</level>
            <!-- 匹配时的操作:接收(记录) -->
            <onMatch>ACCEPT</onMatch>
            <!-- 不匹配时的操作:拒绝(不记录) -->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 系统模块日志级别控制  -->
    <logger name="com.ruoyi" level="info" />
    <!-- Spring日志级别控制  -->
    <logger name="org.springframework" level="warn" />
    <root level="info">
        <appender-ref ref="console" />
    </root>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,比如: 如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration  scan="true" scanPeriod="10 seconds">
    <contextName>logback</contextName>
    
    <!--系统操作日志-->
    <root level="info">
        <appender-ref ref="file_info" />
        <appender-ref ref="file_error" />
    </root>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="/mnt/java/log/system"/>
    <!--0. 日志格式和颜色渲染 -->
    <!-- 彩色日志依赖的渲染类 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
    <!-- 彩色日志格式 -->
    <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <!--1. 输出到控制台-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!--2. 输出到文档-->
    <!-- 2.1 level为 DEBUG 日志,时间滚动输出  -->
    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/debug.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志归档 -->
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录debug级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>debug</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.2 level为 INFO 日志,时间滚动输出  -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/info.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.3 level为 WARN 日志,时间滚动输出  -->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/warn.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录warn级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.4 level为 ERROR 日志,时间滚动输出  -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/error.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.5 所有 除了DEBUG级别的其它高于DEBUG的 日志,记录到一个文件  -->
    <appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/all.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/all-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档记录除了DEBUG级别的其它高于DEBUG的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
    </appender>
    <!--
        <logger>用来设置某一个包或者具体的某一个类的日志打印级别、
        以及指定<appender>。<logger>仅有一个name属性,
        一个可选的level和一个可选的addtivity属性。
        name:用来指定受此logger约束的某一个包或者具体的某一个类。
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
              还有一个特殊值INHERITED或者同义词NULL,代表强制执行上级的级别。
              如果未设置此属性,那么当前logger将会继承上级的级别。
        addtivity:是否向上级logger传递打印信息。默认是true。
        <logger name="org.springframework.web" level="info"/>
        <logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
    -->
    <!--
        root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
        不能设置为INHERITED或者同义词NULL。默认是DEBUG
        可以包含零个或多个元素,标识这个appender将会添加到这个logger。
    -->
    <!-- 4  最终的策略:
                 基本策略(root级) + 根据profile在启动时, logger标签中定制化package日志级别(优先级高于上面的root级)-->
    <springProfile name="dev">
        <root level="info">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
        <logger name="com.stylefeng.guns.modular.system.dao" level="debug"/>
    </springProfile>
    <springProfile name="test">
        <root level="info">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
    </springProfile>
    <springProfile name="prod">
        <root level="info">
            <!-- 生产环境最好不配置console写文件 -->
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
    </springProfile>
</configuration>
ruoyi-modules/ruoyi-system/src/main/resources/mapping/system/WarnMapper.xml
@@ -83,10 +83,10 @@
                and d.`name` like CONCAT('%', #{item.enterpriseName}, '%')
            </if>
            <if test="null != item.startTime and '' != item.startTime">
                and a.start_time >= #{item.startTime}
                and a.start_time >= CONCAT(#{item.startTime}, ' 00:00:00')
            </if>
            <if test="null != item.endTime and '' != item.endTime">
                and a.end_time &lt;= #{item.endTime}
                and a.end_time &lt;= CONCAT(#{item.endTime}, ' 23:59:59')
            </if>
            <if test="null != item.treatmentState and '' != item.treatmentState">
                and a.treatment_state = #{item.treatmentState}
ruoyi-service/ruoyi-dataInterchange/src/main/java/com/ruoyi/dataInterchange/model/UPWarnMsgAdptInfo.java
@@ -65,7 +65,7 @@
    /**
     * 报警时间
     */
    @Field(type = FieldType.Integer)
    @Field(type = FieldType.Long)
    private long warnTime;
    /**
     * 信息ID
ruoyi-service/ruoyi-dataInterchange/src/main/java/com/ruoyi/dataInterchange/netty/client/ChannelMap.java
@@ -9,7 +9,6 @@
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
 * @author zhibing.pu
@@ -36,7 +35,13 @@
     * @param channel
     */
    public static void addClientChannel(int key, Channel channel) {
        if(null == CLIENT_ID_MAP){
            CLIENT_ID_MAP = new HashMap<>();
        }
        CLIENT_ID_MAP.put(key, channel.id());
        if(null == CLIENT_GROUP){
            CLIENT_GROUP = new DefaultChannelGroup("Jtt809Client", GlobalEventExecutor.INSTANCE);
        }
        CLIENT_GROUP.add(channel);
    }
    
@@ -48,9 +53,15 @@
     * @return
     */
    public static Channel getClientChannel(int key) {
        if(null == CLIENT_ID_MAP){
            CLIENT_ID_MAP = new HashMap<>();
        }
        ChannelId channelId = CLIENT_ID_MAP.get(key);
        if (null == channelId) {
            return null;
        }
        if(null == CLIENT_GROUP){
            CLIENT_GROUP = new DefaultChannelGroup("Jtt809Client", GlobalEventExecutor.INSTANCE);
        }
        Channel channel = CLIENT_GROUP.find(channelId);
        return channel;
@@ -64,7 +75,13 @@
     * @param channel
     */
    public static void addServerChannel(int key, Channel channel) {
        if(null == SERVER_ID_MAP){
            SERVER_ID_MAP = new HashMap<>();
        }
        SERVER_ID_MAP.put(key, channel.id());
        if(null == SERVER_GROUP){
            SERVER_GROUP = new DefaultChannelGroup("Jtt809Server", GlobalEventExecutor.INSTANCE);
        }
        SERVER_GROUP.add(channel);
    }
    
@@ -92,6 +109,9 @@
     * @param req
     */
    public static void addIpAndPort(int key, UPConnect req) {
        if(null == IP_PORT){
            IP_PORT = new HashMap<>();
        }
        IP_PORT.put(key, req);
    }
    
@@ -102,6 +122,9 @@
     * @param key
     */
    public static UPConnect getIpAndPort(int key) {
        if(null == IP_PORT){
            IP_PORT = new HashMap<>();
        }
        return IP_PORT.get(key);
    }
    
@@ -112,6 +135,9 @@
     * @return
     */
    public static Integer getTimes(int key) {
        if(null == TIMES){
            TIMES = new HashMap<>();
        }
        return TIMES.get(key);
    }
    
@@ -122,6 +148,9 @@
     * @return
     */
    public static int saveTimes(int key, int t) {
        if(null == TIMES){
            TIMES = new HashMap<>();
        }
        return TIMES.put(key, t);
    }
}
ruoyi-service/ruoyi-dataInterchange/src/main/java/com/ruoyi/dataInterchange/netty/client/NettyClientHandler.java
@@ -69,13 +69,13 @@
     * 当客户端主动断开服务端的链接后,这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据
     */
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客户端与服务端通道-关闭:" + ctx.channel().localAddress() + "channelInactive");
        log.error("客户端与服务端通道-关闭:" + ctx.channel().localAddress() + "channelInactive");
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
        System.out.println("异常退出:" + cause.getMessage());
        log.error("异常退出:" + cause.getMessage());
    }
    
    public void write(ChannelHandlerContext ctx, String mess) throws Exception {
ruoyi-service/ruoyi-dataInterchange/src/main/java/com/ruoyi/dataInterchange/util/haikang/Artemis.java
@@ -2,7 +2,6 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSONArray;
import com.hikvision.artemis.sdk.ArtemisHttpUtil;
import com.hikvision.artemis.sdk.config.ArtemisConfig;
import com.ruoyi.dataInterchange.util.haikang.model.*;
@@ -72,67 +71,6 @@
        return result;
    }
    
    public static void main(String[] args) {
        try {
            FindVehicleByLicensePlateRequest findVehicleByLicensePlateRequest = new FindVehicleByLicensePlateRequest();
            findVehicleByLicensePlateRequest.setVehicleLicensePlate("川J52303");
            String vehicleByLicensePlate = Artemis.findVehicleByLicensePlate(findVehicleByLicensePlateRequest);
            com.alibaba.fastjson2.JSONObject jsonObject = com.alibaba.fastjson2.JSONObject.parseObject(vehicleByLicensePlate);
            String code = jsonObject.getString("code");
            if(!"0".equals(code)){
                return ;
            }
            com.alibaba.fastjson2.JSONObject data = jsonObject.getJSONObject("data");
            //车辆编号
            String indexCode = data.getString("indexCode");
            //主设备编号
            String primaryDeviceIndexCode = data.getString("primaryDeviceIndexCode");
            //根据车辆编号和设备编号获取监控点信息列表
            FindCameraPageRequest findCameraPageRequest = new FindCameraPageRequest();
            findCameraPageRequest.setPageNo(1);
            findCameraPageRequest.setPageSize(1000);
            ExactCondition1 exactCondition = new ExactCondition1();
            exactCondition.setDeviceIndexCodes(new ArrayList<String>(){{
                add(primaryDeviceIndexCode);
            }});
            exactCondition.setVehicleIndexCodes(new ArrayList<String>(){{
                add(indexCode);
            }});
            findCameraPageRequest.setExactCondition(exactCondition);
            String cameraPage = Artemis.findCameraPage(findCameraPageRequest);
            jsonObject = com.alibaba.fastjson2.JSONObject.parseObject(cameraPage);
            code = jsonObject.getString("code");
            if(!"0".equals(code)){
                return;
            }
            data = jsonObject.getJSONObject("data");
            JSONArray list = data.getJSONArray("list");
            //监控点编号
            String indexCode1 = "";
            for (int i = 0; i < list.size(); i++) {
                com.alibaba.fastjson2.JSONObject jsonObject1 = list.getJSONObject(i);
                String cameraName = jsonObject1.getString("cameraName");
                if("驾驶位".equals(cameraName)){
                    indexCode1 = jsonObject1.getString("indexCode");
                }
            }
            //根据监控点编号获取监控预览url
            PreviewURLsRequest previewURLsRequest = new PreviewURLsRequest();
            previewURLsRequest.setCameraIndexCode(indexCode1);
            String s = Artemis.previewURLs(previewURLsRequest);
            jsonObject = com.alibaba.fastjson2.JSONObject.parseObject(s);
            code = jsonObject.getString("code");
            if(!"0".equals(code)){
                return ;
            }
            data = jsonObject.getJSONObject("data");
            String url = data.getString("url");
            System.out.println(url);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    //根据车牌号码获取车辆信息(含设备)
    public static String findVehicleByLicensePlate(FindVehicleByLicensePlateRequest findVehicleByLicensePlateRequest)throws Exception{
ruoyi-service/ruoyi-dataInterchange/src/main/java/com/ruoyi/dataInterchange/util/mqtt/MqttReceiverMessageHandler.java
@@ -25,7 +25,7 @@
    @Override
    public void handleMessage(Message<?> message) throws MessagingException {
        MessageHeaders headers = message.getHeaders();
        log.error("线程名称:{},收到消息,主题:{},消息:{}", Thread.currentThread().getName(), headers.get("mqtt_receivedTopic").toString(), message.getPayload());
        log.info("线程名称:{},收到消息,主题:{},消息:{}", Thread.currentThread().getName(), headers.get("mqtt_receivedTopic").toString(), message.getPayload());
        // log.info("收到消息主题:{}", headers.get("mqtt_receivedTopic").toString());
        // log.info("收到消息:{}", message.getPayload());
        String s = message.getPayload().toString();
ruoyi-service/ruoyi-dataInterchange/src/main/resources/logback.xml
@@ -1,77 +1,222 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- 日志存放路径 -->
    <property name="log.path" value="/mnt/java/log/dataInterchange" />
   <!-- 日志输出格式 -->
    <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>
            <charset>UTF-8</charset>
        </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>
            <!-- 日志最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
            <charset>UTF-8</charset>
        </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>
            <!-- 日志最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 过滤的级别 -->
            <level>ERROR</level>
            <!-- 匹配时的操作:接收(记录) -->
            <onMatch>ACCEPT</onMatch>
            <!-- 不匹配时的操作:拒绝(不记录) -->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 系统模块日志级别控制  -->
    <logger name="com.ruoyi" level="info" />
    <!-- Spring日志级别控制  -->
    <logger name="org.springframework" level="warn" />
    <root level="info">
        <appender-ref ref="console" />
    </root>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,比如: 如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration  scan="true" scanPeriod="10 seconds">
    <contextName>logback</contextName>
    
    <!--系统操作日志-->
    <root level="info">
        <appender-ref ref="file_info" />
        <appender-ref ref="file_error" />
    </root>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="/mnt/java/log/dataInterchange"/>
    <!--0. 日志格式和颜色渲染 -->
    <!-- 彩色日志依赖的渲染类 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
    <!-- 彩色日志格式 -->
    <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <!--1. 输出到控制台-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!--2. 输出到文档-->
    <!-- 2.1 level为 DEBUG 日志,时间滚动输出  -->
    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/debug.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志归档 -->
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录debug级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>debug</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.2 level为 INFO 日志,时间滚动输出  -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/info.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.3 level为 WARN 日志,时间滚动输出  -->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/warn.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录warn级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.4 level为 ERROR 日志,时间滚动输出  -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/error.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!-- 2.5 所有 除了DEBUG级别的其它高于DEBUG的 日志,记录到一个文件  -->
    <appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文档的路径及文档名 -->
        <file>${log.path}/all.log</file>
        <!--日志文档输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}/all-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文档保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <!-- 此日志文档记录除了DEBUG级别的其它高于DEBUG的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
    </appender>
    <!--
        <logger>用来设置某一个包或者具体的某一个类的日志打印级别、
        以及指定<appender>。<logger>仅有一个name属性,
        一个可选的level和一个可选的addtivity属性。
        name:用来指定受此logger约束的某一个包或者具体的某一个类。
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
              还有一个特殊值INHERITED或者同义词NULL,代表强制执行上级的级别。
              如果未设置此属性,那么当前logger将会继承上级的级别。
        addtivity:是否向上级logger传递打印信息。默认是true。
        <logger name="org.springframework.web" level="info"/>
        <logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
    -->
    <!--
        root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
        不能设置为INHERITED或者同义词NULL。默认是DEBUG
        可以包含零个或多个元素,标识这个appender将会添加到这个logger。
    -->
    <!-- 4  最终的策略:
                 基本策略(root级) + 根据profile在启动时, logger标签中定制化package日志级别(优先级高于上面的root级)-->
    <springProfile name="dev">
        <root level="info">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
        <logger name="com.stylefeng.guns.modular.system.dao" level="debug"/>
    </springProfile>
    <springProfile name="test">
        <root level="info">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
    </springProfile>
    <springProfile name="prod">
        <root level="info">
            <!-- 生产环境最好不配置console写文件 -->
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="ALL_FILE" />
        </root>
    </springProfile>
</configuration>