作者 钟来

添加日志功能

@@ -172,6 +172,19 @@ @@ -172,6 +172,19 @@
172 <artifactId>rocketmq-spring-boot-starter</artifactId> 172 <artifactId>rocketmq-spring-boot-starter</artifactId>
173 </dependency> 173 </dependency>
174 174
  175 + <!-- 日志 -->
  176 + <dependency>
  177 + <groupId>org.slf4j</groupId>
  178 + <artifactId>slf4j-api</artifactId>
  179 + </dependency>
  180 + <dependency>
  181 + <groupId>org.slf4j</groupId>
  182 + <artifactId>slf4j-log4j12</artifactId>
  183 + </dependency>
  184 + <dependency>
  185 + <groupId>log4j</groupId>
  186 + <artifactId>log4j</artifactId>
  187 + </dependency>
175 </dependencies> 188 </dependencies>
176 189
177 <build> 190 <build>
1 package com.zhonglai.luhui.mqtt.comm.service; 1 package com.zhonglai.luhui.mqtt.comm.service;
2 2
  3 +import com.alibaba.fastjson.JSON;
3 import com.ruoyi.system.domain.IotDevice; 4 import com.ruoyi.system.domain.IotDevice;
4 -import com.zhonglai.luhui.mqtt.comm.dto.DeviceSensorData;  
5 -import com.zhonglai.luhui.mqtt.comm.dto.LogDeviceOperation;  
6 import com.zhonglai.luhui.mqtt.comm.dto.ServerDto; 5 import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
7 import com.zhonglai.luhui.mqtt.comm.dto.business.BusinessDto; 6 import com.zhonglai.luhui.mqtt.comm.dto.business.BusinessDto;
8 import com.zhonglai.luhui.mqtt.comm.dto.business.BusinessDtoClassNew; 7 import com.zhonglai.luhui.mqtt.comm.dto.business.BusinessDtoClassNew;
@@ -10,8 +9,12 @@ import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreement; @@ -10,8 +9,12 @@ import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreement;
10 import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreementFactory; 9 import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreementFactory;
11 import com.zhonglai.luhui.mqtt.comm.factory.Topic; 10 import com.zhonglai.luhui.mqtt.comm.factory.Topic;
12 import com.zhonglai.luhui.mqtt.comm.util.ByteUtil; 11 import com.zhonglai.luhui.mqtt.comm.util.ByteUtil;
  12 +import com.zhonglai.luhui.mqtt.comm.util.DateUtils;
13 import com.zhonglai.luhui.mqtt.service.db.DeviceService; 13 import com.zhonglai.luhui.mqtt.service.db.DeviceService;
14 import lombok.SneakyThrows; 14 import lombok.SneakyThrows;
  15 +import org.apache.log4j.FileAppender;
  16 +import org.apache.log4j.PatternLayout;
  17 +import org.apache.log4j.RollingFileAppender;
15 import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; 18 import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
16 import org.eclipse.paho.client.mqttv3.MqttCallbackExtended; 19 import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
17 import org.eclipse.paho.client.mqttv3.MqttException; 20 import org.eclipse.paho.client.mqttv3.MqttException;
@@ -21,7 +24,7 @@ import org.slf4j.LoggerFactory; @@ -21,7 +24,7 @@ import org.slf4j.LoggerFactory;
21 import org.springframework.beans.factory.annotation.Autowired; 24 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.stereotype.Component; 25 import org.springframework.stereotype.Component;
23 26
24 -import java.util.List; 27 +import java.util.Date;
25 28
26 @Component 29 @Component
27 public class MqttCallback implements MqttCallbackExtended { 30 public class MqttCallback implements MqttCallbackExtended {
@@ -59,12 +62,29 @@ public class MqttCallback implements MqttCallbackExtended { @@ -59,12 +62,29 @@ public class MqttCallback implements MqttCallbackExtended {
59 public void messageArrived(String s, MqttMessage mqttMessage) { 62 public void messageArrived(String s, MqttMessage mqttMessage) {
60 //接收到消息 63 //接收到消息
61 log.info("接收到消息topc:{}, mqttMessage {},payload 十六进制 {}",s,mqttMessage, ByteUtil.hexStringToSpace(ByteUtil.toHexString(mqttMessage.getPayload()))); 64 log.info("接收到消息topc:{}, mqttMessage {},payload 十六进制 {}",s,mqttMessage, ByteUtil.hexStringToSpace(ByteUtil.toHexString(mqttMessage.getPayload())));
  65 +
  66 + StringBuffer buffer = new StringBuffer();
  67 + buffer.append("topic:");
  68 + buffer.append(s);
  69 + buffer.append("\r\n");
  70 + buffer.append("mqttMessage字符串:");
  71 + buffer.append(mqttMessage.toString());
  72 + buffer.append("\r\n");
  73 + buffer.append("mqttMessage十六进制:");
  74 + buffer.append(ByteUtil.hexStringToSpace(ByteUtil.toHexString(mqttMessage.getPayload())));
  75 + buffer.append("\r\n");
  76 + buffer.append("\r\n");
62 Topic topic = new Topic(s); 77 Topic topic = new Topic(s);
63 if(null == topic) 78 if(null == topic)
64 { 79 {
65 log.error("消息{},topic为空,不做解析"); 80 log.error("消息{},topic为空,不做解析");
  81 + getLoggerByName("error").error("消息《"+s+"》解析为空 》》》内容:\r\n"+buffer.toString());
66 return; 82 return;
67 } 83 }
  84 +
  85 + //日志记录
  86 + getLoggerByName(topic.getClientid()).info(buffer.toString());
  87 +
68 //准备数据 88 //准备数据
69 byte[] data = mqttMessage.getPayload(); 89 byte[] data = mqttMessage.getPayload();
70 IotDevice iotDevice = deviceService.getDeviceById(topic.getClientid()); 90 IotDevice iotDevice = deviceService.getDeviceById(topic.getClientid());
@@ -110,4 +130,37 @@ public class MqttCallback implements MqttCallbackExtended { @@ -110,4 +130,37 @@ public class MqttCallback implements MqttCallbackExtended {
110 } 130 }
111 } 131 }
112 132
  133 + public static org.apache.log4j.Logger getLoggerByName(String name) {
  134 + // 生成新的Logger
  135 + // 如果已經有了一個Logger實例返回現有的
  136 + org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(name);
  137 + // 清空Appender。特別是不想使用現存實例時一定要初期化
  138 + logger.removeAllAppenders();
  139 + // 設定Logger級別。
  140 +// logger.setLevel(Level.DEBUG);
  141 + // 設定是否繼承父Logger。
  142 + // 默認為true。繼承root輸出。
  143 + // 設定false後將不輸出root。
  144 + logger.setAdditivity(true);
  145 + // 生成新的Appender
  146 + FileAppender appender = new RollingFileAppender();
  147 + PatternLayout layout = new PatternLayout();
  148 + // log的输出形式
  149 + String conversionPattern = "%d{HH:mm:ss} [%p] -%m%n";
  150 + layout.setConversionPattern(conversionPattern);
  151 + appender.setLayout(layout);
  152 + // log输出路径
  153 + // 这里使用了环境变量[catalina.home],只有在tomcat环境下才可以取到
  154 +// String tomcatPath = java.lang.System.getProperty("catalina.home");
  155 + appender.setFile( "logs/" + name+"_"+ DateUtils.parseDateToStr("yyyyMMdd",new Date()) + ".log");
  156 + // log的文字码
  157 + appender.setEncoding("UTF-8");
  158 + // true:在已存在log文件后面追加 false:新log覆盖以前的log
  159 + appender.setAppend(true);
  160 + // 适用当前配置
  161 + appender.activateOptions();
  162 + // 将新的Appender加到Logger中
  163 + logger.addAppender(appender);
  164 + return logger;
  165 + }
113 } 166 }
1 package com.zhonglai.luhui.mqtt.controller; 1 package com.zhonglai.luhui.mqtt.controller;
2 2
3 -import com.alibaba.fastjson.JSON;  
4 -import com.alibaba.fastjson.JSONArray;  
5 -import com.alibaba.fastjson.JSONObject;  
6 import com.ruoyi.system.domain.IotDevice; 3 import com.ruoyi.system.domain.IotDevice;
7 import com.ruoyi.system.domain.IotTerminal; 4 import com.ruoyi.system.domain.IotTerminal;
8 import com.ruoyi.system.domain.IotThingsModel; 5 import com.ruoyi.system.domain.IotThingsModel;
9 -import com.zhonglai.luhui.mqtt.comm.dao.BaseDao;  
10 -import com.zhonglai.luhui.mqtt.comm.dto.thingsmodels.ThingsModelBase;  
11 -import com.zhonglai.luhui.mqtt.comm.dto.thingsmodels.ThingsModelDataTypeEnum;  
12 -import com.zhonglai.luhui.mqtt.comm.factory.Topic;  
13 -import com.zhonglai.luhui.mqtt.comm.service.ClienNoticeService;  
14 -import com.zhonglai.luhui.mqtt.comm.util.DateUtils;  
15 import com.zhonglai.luhui.mqtt.dto.Message; 6 import com.zhonglai.luhui.mqtt.dto.Message;
16 import com.zhonglai.luhui.mqtt.dto.MessageCode; 7 import com.zhonglai.luhui.mqtt.dto.MessageCode;
17 import com.zhonglai.luhui.mqtt.service.db.DeviceService; 8 import com.zhonglai.luhui.mqtt.service.db.DeviceService;
@@ -19,12 +10,10 @@ import com.zhonglai.luhui.mqtt.service.db.mode.TerminalDataThingsModeService; @@ -19,12 +10,10 @@ import com.zhonglai.luhui.mqtt.service.db.mode.TerminalDataThingsModeService;
19 import io.swagger.annotations.Api; 10 import io.swagger.annotations.Api;
20 import io.swagger.annotations.ApiOperation; 11 import io.swagger.annotations.ApiOperation;
21 import org.eclipse.paho.client.mqttv3.MqttException; 12 import org.eclipse.paho.client.mqttv3.MqttException;
22 -import org.eclipse.paho.client.mqttv3.MqttMessage;  
23 import org.springframework.beans.factory.annotation.Autowired; 13 import org.springframework.beans.factory.annotation.Autowired;
24 import org.springframework.transaction.annotation.Transactional; 14 import org.springframework.transaction.annotation.Transactional;
25 import org.springframework.web.bind.annotation.*; 15 import org.springframework.web.bind.annotation.*;
26 16
27 -import java.util.List;  
28 import java.util.Map; 17 import java.util.Map;
29 18
30 @Api(tags = "设备操作") 19 @Api(tags = "设备操作")
@@ -102,5 +91,4 @@ public class DeviceController { @@ -102,5 +91,4 @@ public class DeviceController {
102 public Message updateIotTerminal(@RequestBody IotTerminal iotTerminal) { 91 public Message updateIotTerminal(@RequestBody IotTerminal iotTerminal) {
103 return deviceService.updateIotTerminal(iotTerminal); 92 return deviceService.updateIotTerminal(iotTerminal);
104 } 93 }
105 -  
106 } 94 }
  1 +package com.zhonglai.luhui.mqtt.controller;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.util.IOUtils;
  5 +import com.zhonglai.luhui.mqtt.comm.util.DateUtils;
  6 +import com.zhonglai.luhui.mqtt.dto.Message;
  7 +import com.zhonglai.luhui.mqtt.dto.MessageCode;
  8 +import io.swagger.annotations.Api;
  9 +import io.swagger.annotations.ApiImplicitParam;
  10 +import io.swagger.annotations.ApiImplicitParams;
  11 +import io.swagger.annotations.ApiOperation;
  12 +import org.springframework.http.MediaType;
  13 +import org.springframework.stereotype.Controller;
  14 +import org.springframework.web.bind.annotation.PathVariable;
  15 +import org.springframework.web.bind.annotation.RequestMapping;
  16 +import org.springframework.web.bind.annotation.RequestMethod;
  17 +
  18 +import javax.servlet.ServletOutputStream;
  19 +import javax.servlet.http.HttpServletResponse;
  20 +import java.io.*;
  21 +import java.util.Date;
  22 +import java.util.zip.ZipEntry;
  23 +import java.util.zip.ZipFile;
  24 +
  25 +@Api(tags = "设备操作")
  26 +@Controller
  27 +@RequestMapping("/log")
  28 +public class LogController {
  29 + @ApiOperation("获取一天的日志")
  30 + @ApiImplicitParams({
  31 + @ApiImplicitParam(value = "时间(格式:20230114)",name = "time"),
  32 + @ApiImplicitParam(value = "设备imei",name = "imei"),
  33 + })
  34 + @RequestMapping(value = "getOneDateLog/{imei}/{time}",method = RequestMethod.GET)
  35 + public void getOneDateLog(HttpServletResponse response, @PathVariable String imei, @PathVariable String time) throws IOException {
  36 + response.setCharacterEncoding("UTF-8");
  37 + response.setHeader("Content-Type","text/html;charset=utf-8");
  38 + PrintWriter printWriter = response.getWriter();
  39 + String dateString = DateUtils.parseDateToStr("yyyyMMdd",new Date());
  40 + String fileName= imei+"_"+time+".log";
  41 + if(dateString.equals(time))
  42 + {
  43 + File logsFile = new File("logs/"+fileName);
  44 + if (!logsFile.exists())
  45 + {
  46 + printWriter.println(JSON.toJSONString(new Message(MessageCode.DEFAULT_FAIL_CODE,"文件"+logsFile.getPath()+"不存在")));
  47 + }
  48 + BufferedReader reader = null;
  49 + try {
  50 + reader = new BufferedReader(new FileReader(logsFile));
  51 + String line;
  52 + while((line = reader.readLine()) != null){
  53 + printWriter.println(line);
  54 + printWriter.println("<br/>");
  55 + }
  56 + } catch (IOException e) {
  57 + e.printStackTrace();
  58 + }finally {
  59 + IOUtils.close(printWriter);
  60 + IOUtils.close(reader);
  61 + }
  62 +
  63 + }
  64 + File logsFile = new File("zip/"+time+".zip");
  65 + BufferedReader reader = null;
  66 + try {
  67 + ZipFile zipFile = new ZipFile(logsFile);
  68 + reader = new BufferedReader(new InputStreamReader(zipFile.getInputStream(new ZipEntry(fileName))));
  69 + String line;
  70 + while((line = reader.readLine()) != null)
  71 + {
  72 + printWriter.println(line);
  73 + printWriter.println("<br/>");
  74 + }
  75 +
  76 + } catch (IOException e) {
  77 + printWriter.println(JSON.toJSONString(new Message(MessageCode.DEFAULT_FAIL_CODE,e.getMessage())));
  78 + }finally {
  79 + IOUtils.close(printWriter);
  80 + IOUtils.close(reader);
  81 + }
  82 + }
  83 +}
  1 +package com.zhonglai.luhui.mqtt.service;
  2 +
  3 +import com.zhonglai.luhui.mqtt.comm.util.DateUtils;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.scheduling.annotation.EnableScheduling;
  6 +import org.springframework.scheduling.annotation.Scheduled;
  7 +
  8 +import java.io.*;
  9 +import java.util.Calendar;
  10 +import java.util.Date;
  11 +import java.util.zip.ZipEntry;
  12 +import java.util.zip.ZipOutputStream;
  13 +
  14 +@Configuration //1.主要用于标记配置类,兼备Component的效果。
  15 +@EnableScheduling // 2.开启定时任务
  16 +public class LogTask {
  17 +
  18 + public static void main(String[] args) {
  19 + LogTask logTask = new LogTask();
  20 + logTask.pack();
  21 + }
  22 +
  23 + //每天凌晨1点钟,打包日志
  24 + @Scheduled(cron = "0 0 1 * * ?")
  25 + private void pack() {
  26 +
  27 + File logsFile = new File("logs/");
  28 + if(logsFile.exists() )
  29 + {
  30 + Calendar cal = Calendar.getInstance();
  31 + cal.setTime(new Date());
  32 + cal.add(Calendar.DATE,-1);
  33 + String dateString = DateUtils.parseDateToStr("yyyyMMdd",cal.getTime());
  34 +
  35 + String logfilename = "_"+ dateString +".log";
  36 +
  37 + String[] files = logsFile.list((dir, name) -> {
  38 + if(name.indexOf(logfilename)>=0)
  39 + {
  40 + return true;
  41 + }
  42 + return false;
  43 + });
  44 +
  45 + if(null != files && files.length != 0 )
  46 + {
  47 + String savePath = "zip/"+dateString+".zip";
  48 + File saveFile = new File(savePath);
  49 + if(!saveFile.getParentFile().exists())
  50 + {
  51 + saveFile.getParentFile().mkdirs();
  52 + }
  53 +
  54 + batchZip(saveFile,logsFile.getPath(),files);
  55 +
  56 + for(String fp:files)
  57 + {
  58 + new File(logsFile.getPath()+"/"+fp).delete();
  59 + }
  60 + }
  61 +
  62 + }
  63 + }
  64 +
  65 + //每天凌晨2点钟,删除30天之前的压缩包
  66 + @Scheduled(cron = "0 0 2 * * ?")
  67 + private void del()
  68 + {
  69 + File logsFile = new File("zip/");
  70 + Calendar cal = Calendar.getInstance();
  71 + cal.setTime(new Date());
  72 + cal.add(Calendar.DATE,-30);
  73 + String dateString = DateUtils.parseDateToStr("yyyyMMdd",cal.getTime());
  74 + String[] files = logsFile.list((dir, name) -> {
  75 +
  76 + if(name.compareTo(dateString)<=0)
  77 + {
  78 + return true;
  79 + }
  80 + return false;
  81 + });
  82 +
  83 + if(null != files && files.length != 0 )
  84 + {
  85 + for(String fp:files)
  86 + {
  87 + new File(logsFile.getPath()+"/"+fp).delete();
  88 + }
  89 + }
  90 + }
  91 + /**
  92 + * 批量压缩
  93 + * @param saveFile 压缩文件保存地址
  94 + * @param files 被压缩文件地址列表
  95 + */
  96 + private void batchZip(File saveFile,String path,String[] files)
  97 + {
  98 + ZipOutputStream zip = null;
  99 + try {
  100 + zip = new ZipOutputStream(new FileOutputStream(saveFile));
  101 + for(String filepath:files)
  102 + {
  103 + zip(zip,path+"/"+filepath);
  104 + }
  105 + zip.finish();
  106 + } catch (IOException e) {
  107 + e.printStackTrace();
  108 + }finally {
  109 + if(null != zip)
  110 + {
  111 + try {
  112 + zip.close();
  113 + } catch (IOException e) {
  114 + e.printStackTrace();
  115 + }
  116 + }
  117 + }
  118 + }
  119 +
  120 +
  121 + /**
  122 + * 压缩
  123 + * @param zip 压缩文件流
  124 + * @param filepath 被压缩文件地址
  125 + * @throws IOException
  126 + */
  127 + private void zip( ZipOutputStream zip,String filepath) throws IOException {
  128 + String[] fss = filepath.split("\\/");
  129 + zip.putNextEntry(new ZipEntry(fss[fss.length-1]));
  130 + //用字节方式读取源文件
  131 + InputStream is = null;
  132 + BufferedInputStream bis = null;
  133 + try {
  134 + is = new FileInputStream(filepath);
  135 + //创建一个缓存区
  136 + bis = new BufferedInputStream(is);
  137 + //字节数组,每次读取1024个字节
  138 + byte[] b = new byte[1024];
  139 + //循环读取,边读边写
  140 + while (bis.read(b) != -1) {
  141 + //写入压缩文件
  142 + zip.write(b);
  143 + }
  144 + } catch (IOException e) {
  145 + e.printStackTrace();
  146 + }finally {
  147 + //关闭流
  148 + if(null != bis)
  149 + {
  150 + bis.close();
  151 + }
  152 + if(null != is)
  153 + {
  154 + is.close();
  155 + }
  156 + }
  157 +
  158 + }
  159 +}
@@ -101,7 +101,7 @@ public class DeviceService { @@ -101,7 +101,7 @@ public class DeviceService {
101 for (String sk:saveJson.keySet()) 101 for (String sk:saveJson.keySet())
102 { 102 {
103 ThingsModelItemBase thingsModelItemBase = (ThingsModelItemBase) saveJson.get(sk); 103 ThingsModelItemBase thingsModelItemBase = (ThingsModelItemBase) saveJson.get(sk);
104 - if(null != thingsModelItemBase.getIs_save_log() && 1==thingsModelItemBase.getIs_save_log() && null != logDeviceOperationList) 104 + if(null != thingsModelItemBase.getMode_type() && (2==thingsModelItemBase.getMode_type() || 3==thingsModelItemBase.getMode_type()) && null != logDeviceOperationList)
105 { 105 {
106 if(null!=thingsModelItemBase.getSaveView() && null != oldjs && oldjs.containsKey(sk) && !thingsModelItemBase.getSaveView().equals(oldjs.getJSONObject(sk).getString("saveView"))) 106 if(null!=thingsModelItemBase.getSaveView() && null != oldjs && oldjs.containsKey(sk) && !thingsModelItemBase.getSaveView().equals(oldjs.getJSONObject(sk).getString("saveView")))
107 { 107 {
@@ -339,6 +339,23 @@ @@ -339,6 +339,23 @@
339 <version>2.1.1</version> 339 <version>2.1.1</version>
340 </dependency> 340 </dependency>
341 341
  342 + <!-- 日志 -->
  343 + <dependency>
  344 + <groupId>org.slf4j</groupId>
  345 + <artifactId>slf4j-api</artifactId>
  346 + <version>1.7.24</version>
  347 + </dependency>
  348 + <dependency>
  349 + <groupId>org.slf4j</groupId>
  350 + <artifactId>slf4j-log4j12</artifactId>
  351 + <version>1.7.24</version>
  352 + </dependency>
  353 + <dependency>
  354 + <groupId>log4j</groupId>
  355 + <artifactId>log4j</artifactId>
  356 + <version>1.2.17</version>
  357 + </dependency>
  358 +
342 </dependencies> 359 </dependencies>
343 360
344 361