java - 项目启动时自动将jar包名称、路径、进程号信息写入指定的文件里

1.需要配置启动时记录项目进程号到指定公共文件里

参考我的随笔 java - sprootboot 配置启动时记录进程号 - 岑惜 - 博客园 (cnblogs.com)

2. 指定公共文件路径

 

 

 3.对springboot 生命周期做监听

 

 

 在 生命周期 ApplicationReadyEvent 里处理

完整代码

复制代码
import cn.cenxi.common.basic.StringUtils;
import cn.cenxi.common.file.FileFormat;
import com.google.common.base.Joiner;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStartedEvent;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * springboot 生命周期
 */
@Component
@Slf4j
public class ApplicationEventListener implements ApplicationListener<ApplicationEvent> {

    //   记录当前jar进程号文件的路径
    @Value("${spring.pid.file}")
    private String filePath;

    //    公共的jar包进程数据文件路径
    @Value("${configFile.AllProPidrec}")
    private String AllProPidrecPath;

    //    jar包名称
    @Value("${spring.application.name}")
    private String applicationName;

    @SneakyThrows
    @Override
    public void onApplicationEvent(ApplicationEvent event) {

        if (event instanceof ApplicationReadyEvent) {
            if (StringUtils.isEmpty(filePath) || StringUtils.isEmpty(AllProPidrecPath)) return;
            File file = new File(filePath);
            if (!file.exists()) {
                log.error("pidRec.txt文件不存在:路径在:" + filePath);
            }
            //进程号
            String pid = FileFormat.getTxtForUtf8(file, filePath);
            //启动jar文件路径
            ApplicationHome h = new ApplicationHome(getClass());
            File jarF = h.getSource();
            String jarPath = jarF.getParentFile().toString();
//            log.error(jarPath);
            //写入指定位置
            File allProPidrec = new File(AllProPidrecPath);
            String allProPidrecTxt = "";
            if (allProPidrec.exists()) {
                allProPidrecTxt = FileFormat.getTxtForUtf8(allProPidrec, AllProPidrecPath);
            } else {
                allProPidrec.createNewFile();
            }
            List<String> list = Arrays.asList(allProPidrecTxt.split("\n"));
            List<String> resList = new ArrayList<>();
            for (String str : list) {
                if (StringUtils.isEmpty(str)) {
                    continue;
                }
                String[] arr = str.split("&");
                if (!StringUtils.equals(arr[0] + "&" + arr[1], applicationName + "&" + jarPath)) {
                    resList.add(str);
                }
            }
            resList.add(applicationName + "&" + jarPath + "&" + pid );
            String txt = Joiner.on("\n").join(resList);
            //写入文件中[覆盖写入]
            FileFormat.setTxt(txt, allProPidrec, AllProPidrecPath, false);
        }
    }
}
View Code
复制代码

 

相应的文件解析工具

复制代码
import cn.cenxi.common.basic.StringUtils;
import cn.cenxi.common.exception.ExcBox;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.hslf.extractor.PowerPointExtractor;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.jodconverter.DocumentConverter;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;

import javax.annotation.Resource;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.NumberFormat;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Slf4j
public class FileFormat {


    /**
     * 多次读取文件数据--解决utf-8中文乱码问题
     */

    public static String getTxtForUtf8(File file, String url) {
        try {
            if (null == file) {
                file = new File(url);
            }
            if (!file.exists()) return null;
            //字节输入流
            //意思是文件内容向JVM输入
            FileInputStream fis = new FileInputStream(file);
            StringBuilder txt = new StringBuilder();
            //==============================================
            //开启管道
            FileChannel fc = fis.getChannel();
            //如果设置太小的,会乱码【解决方式不靠谱】
            //如果是utf-8,最大长度是4字节  ,GBK 为2 byte
            //因此这里设置最小是4
            ByteBuffer buffer = ByteBuffer.allocate(6);
            //管道将文件对象的内容读出并放入缓冲区里面,字符上限为上面缓冲区设置的最大值
            //read()方法返回的是个抽象的整数,意为字符的长度/个数,当为空时返回-1
            int mread;
            //此时管道读取数据放入缓冲,缓冲的定位position 不再是0 ,需要将limit设为position,而position需要恢复到0 ,
            //形成 【 limit == 当前的position值【也等于mread】,position == 0 , cap 不变】
            while ((mread = fc.read(buffer)) != -1) {
                byte b;
                //计算出此时中文utf-8的编码长度后放入这里
                int idx;
                //out可以bai改成任何不与保留关键字相同的字符,其中du标签out代表了这个for循环结构zhi体。理论上,标签可以标记任何结构体
                //break out ;代表语句执行跳出整个for循环结构
                out:
                for (idx = buffer.position() - 1; idx >= 0; idx--) {
                    b = buffer.get(idx);
                    if ((b & 0xff) >> 7 == 0) {  // 0xxxxxxx
                        break;
                    }
                    if ((b & 0xff & 0xc0) == 0xc0) {   // 11xxxxxx,110xxxxx、1110xxxx、11110xxx
                        idx -= 1;
                        break;
                    }
                    if ((b & 0xff & 0x80) == 0x80) {
                        for (int i = 1; i < 4; i++) {
                            b = buffer.get(idx - i);
                            if ((b & 0xff & 0xc0) == 0xc0) {
                                if ((b & 0xff) >> (5 + 1 - i) == 0xf >> (3 - i)) {
                                    //break out ;代表语句执行跳出整个for循环结构
                                    break out;
                                } else {
                                    idx = idx - 1 - i;
                                    //break out ;代表语句执行跳出整个for循环结构
                                    break out;
                                }
                            }
                        }
                    }
                }
                //缓冲区定位参数移位
                buffer.flip();
                //获取限制数,备份
                int limit = buffer.limit();
                //设限制数为上面计算出的utf-8字符的长度
                buffer.limit(idx + 1);  // 阻止读取跨界数据
                //文本信息
                txt.append(StandardCharsets.UTF_8.decode(buffer));
                // 恢复limit
                buffer.limit(limit);
                //compact()方法将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。
                // limit属性依然像clear()方法一样,设置成capacity。现在Buffer准备好写数据了,但是不会覆盖未读的数据。
                //也就是说把已经写入缓冲区但是还没有读的数据左移到开头,然后将position设为该数据默认
                //然后继续做写操作,不会覆盖这些数据
                buffer.compact();
            }
            //清除缓冲区
            buffer.clear();
            //关闭管道
            fc.close();
            //关闭字节输入流
            fis.close();
            return txt.toString();
        } catch (IOException e) {
            ExcBox.getExcMsg(e);
            return null;
        }
    }

    /**
     * 把字符串写入文件[使用  buffer.put]
     */
    public static void setTxt(String txt, File file, String url, boolean isAppen) {
        try {
            FileOutputStream fos = null;
            if (null != file) {
                fos = new FileOutputStream(file, isAppen);
            }
            if (StringUtils.isNotEmpty(url)) {
                fos = new FileOutputStream(url, isAppen);
            }
            //==============================================
            //true表示追加,如果文件存在 向里面继续添加内容,不加默认是覆盖
//            FileOutputStream fos=new FileOutputStream(file,true);
            //获取通道,该通道允许写操作【根据字节流是输入还是输出决定是读通道还是写通道】
            FileChannel fc = fos.getChannel();
            //allocate是使用JVM的的内存的,适合小文件;allocateDirect则是使用系统的内存的,适合大文件
            //设置字节缓的大小
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            //控制台写入字符串
//            Scanner sca = new Scanner(System.in);
//            String str = sca.next();
            //将字符串转成字节后,放入字节缓冲
            buffer.put(txt.getBytes(StandardCharsets.UTF_8));
            // 此行语句一定要有,每次执行了这一句才可以做io操作
            buffer.flip();
            //通道对字节缓冲区里的内容写入文件对象里面
            fc.write(buffer);
            //清空缓冲块
            buffer.clear();
            //关闭管道
            fc.close();
            //关闭字节输出流
            fos.close();
        } catch (IOException e) {
            ExcBox.getExcMsg(e);
        }
    }
}
View Code
复制代码

 

posted @   岑惜  阅读(497)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示