listener代碼找不到properties文件的坑

這是一個隱形的坑。

 

   先貼出項目中一個listerner源代碼,仔細觀察:

 

public class SystemConfigInitListener implements ServletContextListener{

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        String prefix = sce.getServletContext().getRealPath("/");
        String file = sce.getServletContext().getInitParameter("systemConfigLocation");
        Properties props = new Properties();
        InputStream is = null;
        try {
            if (file.startsWith("classpath:")) {
                is = SystemConfigInitListener.class.getClassLoader().getResourceAsStream(file.substring(10));
            }
            else {
                String filePath = prefix + file;
                is = new FileInputStream(filePath);
            }
            props.load(is);
            for(Enumeration<Object> it = props.keys(); it.hasMoreElements();){
                String key = (String)it.nextElement();
                System.setProperty(key, props.getProperty(key));
                sce.getServletContext().setAttribute(key, props.getProperty(key));
            }
        }
        catch (Exception e) {
        }finally{
            if(is != null){
                try{
                    is.close();
                }catch(Exception e){}
            }
        }
        
        
        file = sce.getServletContext().getInitParameter("systemConfigLocationOverride");
        Properties props2 = new Properties();
        InputStream is2 = null;
        try {
            if (file.startsWith("file:")) {
                is2 = new FileInputStream(file.substring(5).replaceAll("\\$\\{user.home\\}", System.getProperty("user.home")));
            }
            else {
                String filePath = prefix + file;
                is2 = new FileInputStream(filePath);
            }

            props2.load(is2);
            for(Enumeration<Object> it = props2.keys(); it.hasMoreElements();){
                String key = (String)it.nextElement();
                System.setProperty(key, props2.getProperty(key));
                sce.getServletContext().setAttribute(key, props2.getProperty(key));
            }
        }
        catch (Exception e) {
        }finally{
            if(is != null){
                try{
                    is2.close();
                }catch(Exception e){}
            }
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // TODO Auto-generated method stub
        
    }

}

 

 

    這段代碼在線上,測試服務器上運行是沒有問題的,在蘋果電腦上運行也是沒有問題的,在windows電腦上運行表面上看起來也是沒有問題的,其實是又問題的,因爲異常被吃掉了,沒有打印出來,被你忽略掉了。

    

    web.xml中有這樣一個配置:

 

<context-param>
		<param-name>systemConfigLocationOverride</param-name>
		<param-value>file:${user.home}/config/sigma-release.properties</param-value>
</context-param>

 

 

  該配置的作用就是listerner代碼在服務啓動初始化的時候,將config目錄下的配置項替換爲真正的配置。

 

  

   服務器上的config目錄: /home/www/config 沒有問題

 

   假如你的config目錄是這個 C:\\Users\\用戶名\\config  恭喜你,你踩到坑了

   

 

   因爲listerner的下面這行代碼會報錯,但是錯誤信息又被吃掉,你沒有及時發現,導致在本地測試的時候,沒有達到你期望的效果。

 

  如果我們在異常中加上打印信息,例如e.printStackTrace();

  會報下面的錯誤信息的:



 

 

導致上面異常的真正原因是下面這行代碼:

 

is2 = new FileInputStream(file.substring(5).replaceAll("\\$\\{user.home\\}", System.getProperty("user.home")));

 

 

   這行代碼在linux平臺,蘋果電腦上運行是沒有問題的。
   但是如果你是windows,而你的config目錄又是C:\\Users\\用戶名\\config,可以通過下面這行代碼打印出來
  
String userhomePath = System.getProperty("user.home");
System.out.println("===userhomePath===" +userhomePath);
   
     我本地打印的是c:,我早就修改成了根目錄,所以不會有任何問題。而不是c:/xxx/xxx/xxx很深的目錄,(修改參考:http://cfyme.iteye.com/blog/2209012)
     解決方案1:將斜槓替換掉,replaceAll("\\\\", "/")));
例如:
                is2 = new FileInputStream(file.substring(5).replaceAll("\\$\\{user.home\\}", System.getProperty("user.home").replaceAll("\\\\", "/")));

 

   

    解決方案2:直接將user.home目錄設置成根目錄,設置方法參考:http://cfyme.iteye.com/blog/2209012

 

 

    總結:1,異常不要被吃掉,不然遇到一些問題難以發現。

               2,環境配置項的問題最後在系統啓動初始化的時候全部加載打印到日誌文件中,方便查看是否我們真正所期望的值。

 

 

 

 

發佈了249 篇原創文章 · 獲贊 3 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章