天天看點

springboot - 利用@PostConstruct對自定義Bean進行初始化

開發部落格系統的時候有一個需求,就是希望系統啟動時,自動将指定檔案夾中的md檔案寫入到資料庫,這樣我每更新一篇文章隻需将文章拷貝入那個檔案夾即可。(當然也可以開發界面上傳的方式,但我不想搞得那麼複雜,怎麼友善怎麼來)。資料庫表長這樣:

springboot - 利用@PostConstruct對自定義Bean進行初始化

存儲文章的檔案夾長這樣:

springboot - 利用@PostConstruct對自定義Bean進行初始化

這裡用@PostConstruct這個注解很好實作,注意系統啟動時,初始化的順序為:構造方法 -> @Autowired -> @PostConstruct

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)  //指定執行順序
public class InitHandler {

    @Value("${file.upload.abpath}") //從配置檔案中取出指定檔案夾
    private String abpath;

    @Autowired
    private ArticleService articleService;   //引入ArticleService接口操作資料庫

    private Logger logger = LoggerFactory.getLogger(this.getClass());  //定義logger寫日志

    public InitHandler(){
        this.logger.info("開始資料初始化");
    }

    @PostConstruct
    public void init() throws Exception {
        this.logger.info("資料庫 初始化開始");

        //1.讀取abpath中所有的檔案

        //需要過濾的檔案夾,存放image
        String imgAbPath=abpath+"assets/";
        //需要過濾的檔案夾,測試
        String testPath=abpath+"test/";

        ArrayList<String> ar=new ArrayList<>();
        ar.add(imgAbPath);
        ar.add(testPath);

        //擷取所有檔案路徑清單
        ArrayList<String> fs = FileUtil.getDirsOrFiles(abpath, ar);
        List<Article> articles = articleService.queryAll();

        //擷取資料庫中所有md檔案title,用一個List接收
        List<String> list=new ArrayList<>();
        articles.forEach(article -> {
            list.add(article.getTitle());
        });

        for(String s :fs){
            File f=new File(s);

            //擷取絕對路徑
            this.logger.info("originalName: "+f.getAbsolutePath());
            String arabpath =f.getAbsolutePath();

            //擷取名子
            String name=f.getName().split("\\.")[0];

            //過濾掉資料庫中已有md檔案,這種方法快,不用重複查資料庫,提高效率
            if(list.contains(name)){
                continue;
            }

            //将資料寫入資料庫
            Article art=new Article();
            art.setCategoryId(1L);
            art.setName(f.getName());
            art.setTitle(name);

            art.setCreateTime(new Timestamp(System.currentTimeMillis()));
            articleService.addArticle(art);
            this.logger.info(f.getName()+"已寫入資料庫");
        }
    }
}
           

這裡用到的getDirsOrFiles(String strPath,ArrayList filterDirs)定義如下:

/**
     *
     * @param strPath    檔案夾的絕對路徑
     * @param filterDirs   檔案夾中需要過濾掉的檔案夾List
     * @return             遞歸查詢到的文體絕對路徑清單
     * @throws Exception
     */
    public static  ArrayList<String> getDirsOrFiles(String strPath,ArrayList<String> filterDirs) throws Exception {
        ArrayList<String> mfiles = new ArrayList<String>();
        try {
            File f = new File(strPath);
            if (f.isDirectory()) {
                File[] fList = f.listFiles();
                for (int j = 0; j < fList.length; j++) {
                    if (fList[j].isDirectory()) {

                        //如果含有filterDirs中包含的檔案夾則過濾掉
                        for(String s:filterDirs){
                            if (fList[j].equals(filterDirs)){
                                continue;
                            }
                        }

//                        System.out.println("Directory is: "	+ fList[j].getPath());
                        getDirsOrFiles(fList[j].getPath(),filterDirs); // 對目前目錄下仍是目錄的路徑進行周遊
                    }
                }
                for (int j = 0; j < fList.length; j++) {
                    if (fList[j].isFile()) {
                        String name = fList[j].getPath().toString();
//                        System.out.println("Filename is: " + name);
                        mfiles.add(fList[j].getPath());
                    }
                }
            }
            return mfiles;
        } catch (Exception e) {
            System.err.println("Error: " + e);
            return null;
        }

    }
           

這個函數的作用是遞歸擷取某檔案夾下所有檔案,同時可以指定在遞歸過程中過濾掉指定的檔案夾,比如指定檔案夾中的assets檔案夾是放圖檔的,我不需要擷取裡面的png或jpg檔案,于是可以将其過濾掉。

啟動系統可以看到日志如下 :

springboot - 利用@PostConstruct對自定義Bean進行初始化

說明系統啟動時成功執行初始化資料庫的操作。