实时读取日志并推送(记录读取位置)

package com.sfa.hcc.logread;

import com.alibaba.fastjson.JSON;
import com.sfa.hcc.utils.DateUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

@Component
public class SecurityReadLogManagerImpl implements SecurityReadLogManager {

    private final Logger logger = LoggerFactory.getLogger(SecurityReadLogManagerImpl.class);

    private static Properties properties = new Properties();
    private static Properties properties1 = new Properties();

    //@Autowired
    //private SysConfUtil sysConfUtil;

    static {
        File file = new File(System.getProperty("user.dir") + File.separator + "config.properties");
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(file);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            properties.load(fileInputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @PostConstruct
    public void contextInitialized() {
        while (1 == 1) {
            try {
                readAndSendSecurityLog();
                //获取配置的读取频率
                String readFrequency = properties.getProperty("read_frequency");
                //如果没有配置默认为1秒
                if (StringUtils.isBlank(readFrequency)) {
                    Thread.sleep(1000);
                } else {
                    //配置的是秒,这里是毫秒,转换一下
                    Thread.sleep(Long.valueOf(readFrequency) * 1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void readAndSendSecurityLog() {
        String fileUrl = properties.getProperty("file.url");//读取的日志文件路径
        try {
            File localFile = new File(System.getProperty("user.dir") + File.separator + "lastTimeFileSize.properties");
            try (FileInputStream fileInputStream = new FileInputStream(localFile)) {
                properties1.load(fileInputStream);
            }
            RandomAccessFile accessFile1 = new RandomAccessFile(localFile, "rw");
            String s1 = "";
            //定义当前要读取的文件名
            String path = "";
            //如果记录下标的文件没有内容就从当天的.0文件开始读取,有内容就取上次读取的文件以及记录的下标开始读取
            if ((s1 = accessFile1.readLine()) != null) {
                String s2 = new String(s1.getBytes("ISO-8859-1"));
                String[] strings = s2.split("=");
                path = strings[0];
            } else {
                path = DateUtil.parse(new Date(), DateUtil.DEFAULT_FORMAT) + ".0" + ".txt";
            }
            //拼接读取的文件完整路径
            String readPath = fileUrl + File.separator + path;
            RandomAccessFile accessFile = new RandomAccessFile(readPath, "r");
            List<String> readMsg = null;
            //读取日志文件
            readMsg = readTxt(path, accessFile, accessFile1);
            if (CollectionUtils.isEmpty(readMsg)) {
                //如果读取的文件里没有新内容,就去看看有没有新文件
                searchNewTxt(fileUrl, accessFile1, path);
            }
            //关流
            accessFile.close();
            accessFile1.close();
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    private void searchNewTxt(String fileUrl, RandomAccessFile accessFile1, String path) throws IOException {
        String[] split = path.split("\\.");
        //將2022-05-23.0.txt中的.0改成.1看看有没有
        String integer = String.valueOf(Integer.valueOf(split[1]) + 1);
        String newPath = split[0] + "." + integer + "." + split[2];
        //获取读取日志日期记录的下一天
        String lastDate = split[0];
        try {
            int countDay = DateUtil.getDay(lastDate, DateUtil.parse(new Date(), DateUtil.DEFAULT_FORMAT));
            File file = new File(fileUrl + File.separator);
            for (File listFile : file.listFiles()) {
                //统计当前文件下,当前日期的日志文件个数
                String trim = listFile.getName().trim();
                String[] split1 = trim.split("\\\\");
                String filePath = split1[split1.length - 1];
                if (filePath.equals(newPath)) {
                    //将文件内容清除,防止写入文本内容小于原内容,导致无法完全覆盖
                    accessFile1.setLength(0);
                    //每次都从文件开头开始写入
                    accessFile1.seek(0);
                    //将光标位置写进lastTimeFileSize.properties文件
                    accessFile1.write((newPath + "=0").getBytes());
                    break;
                } else {
                    //将记录下标读取的最后文件的日期提取出来
                    Date date = DateUtil.parse(lastDate, DateUtil.DEFAULT_FORMAT);
                    for (int i = 1; i <= countDay; i++) {
                        //从记录的日期下一天开始寻找
                        String nextDate = DateUtil.parse(DateUtil.getBeforOrNextDay(date, i), DateUtil.DEFAULT_FORMAT);
                        String newPath1 = nextDate + ".0.txt";
                        if (filePath.equals(newPath1)) {
                            // 将文件内容清除,防止写入文本内容小于原内容,导致无法完全覆盖
                            accessFile1.setLength(0);
                            //每次都从文件开头开始写入
                            accessFile1.seek(0);
                            //将光标位置写进lastTimeFileSize.properties文件
                            accessFile1.write((newPath1 + "=0").getBytes());
                            break;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private List<String> readTxt(String newPath, RandomAccessFile accessFile, RandomAccessFile accessFile1) throws IOException {
        List<String> messages = new ArrayList<>();
        int count = 0;
        long lastTime = System.currentTimeMillis();
        //通过配置的文件名作key查询有没有记录下标,如果记录的下标位置后面有新内容就继续读取
        String property = properties1.getProperty(newPath);
        //以日志文件名为key获取当前读取的光标位置
        //如果为空,从0开始读取
        if (StringUtils.isBlank(property)) {
            property = "0";
        }
        //查询上次读取的点标位置
        Long lastTimeFileSize = Long.valueOf(property);
        //从记录的指标最后读取位置开始读取文件
        accessFile.seek(lastTimeFileSize);
        String s = "";
        long nowTime = 0L;
        do {
            s = accessFile.readLine();
            nowTime = System.currentTimeMillis();
            if (s == null) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                String s1 = new String(s.getBytes("ISO-8859-1"), "UTF-8");
                messages.add(s1);
                count++;
                //每次读取后记录当前读取的位置
                lastTimeFileSize = s1.length() + lastTimeFileSize + 2; //加2 是\r\n的字节数
                //每读取了500条数据,就推送信息给安检服务
                if (count % 500 == 0) {
                    sendMsg(newPath, accessFile1, messages, lastTimeFileSize);
                    return messages;
                }
            }
            //如果1分钟后没有500条记录,就跳出循环
        } while ((nowTime - lastTime) / 1000 / 60 <= 1);
        //如果跳出了循环,则推送一次
        if (CollectionUtils.isNotEmpty(messages)){
            sendMsg(newPath, accessFile1, messages, lastTimeFileSize);
        }
        return messages;
    }

    private boolean sendMsg(String newPath, RandomAccessFile accessFile1, List<String> messages, Long lastTimeFileSize) throws IOException {
        String airport3Code = properties.getProperty("airport3_code");//航站
        String channelNum = properties.getProperty("channel_num");//通道编号
        //将要推送的信息封装
        SecurityReadLog securityReadLog = new SecurityReadLog();
        securityReadLog.setAirport3Code(airport3Code);
        securityReadLog.setChannelNum(channelNum);
        securityReadLog.setSecurityLogList(messages);
        //转换为json格式
        String body = JSON.toJSONString(securityReadLog);

        //请求接口
        String pushReadLog_url = properties.getProperty("pushReadLog_url", "http://10.88.5.141:8000/check/securityReadLog/saveReceiveLog");
        HttpResponse responResult = doPost(pushReadLog_url, body);
        if (responResult != null && responResult.getStatusLine().getStatusCode() == 200) {
            //将文件内容清除,防止写入文本内容小于原内容,导致无法完全覆盖
            accessFile1.setLength(0);
            //每次都从文件开头开始写入
            accessFile1.seek(0);
            //将光标位置写进lastTimeFileSize.properties文件
            accessFile1.write((newPath + "=" + lastTimeFileSize).getBytes());
            return true;
        } else {
            logger.error("推送信息失败");
        }
        return false;
    }


    /**
     * Post请求一个地址
     *
     * @param url         请求地址
     * @param requestBody 请求的body
     * @return
     */
    public HttpResponse doPost(String url, String requestBody) {
        //获得Http客户端(相当于一个浏览器)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        //创建post请求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-type", "application/json;charset=utf-8");
        //设置参数(post请求是将参数放在请求体里面传过去的)
        httpPost.setEntity(new StringEntity(requestBody, "utf-8"));
        //设置超时
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(5000).setConnectionRequestTimeout(1000)
                .setSocketTimeout(5000).build();
        httpPost.setConfig(requestConfig);
        //推送并获取响应
        HttpResponse httpResponse = null;
        try {
            httpResponse = httpClient.execute(httpPost);
            return httpResponse;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return httpResponse;
    }

}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值