這是一個隱形的坑。
先貼出項目中一個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")));
String userhomePath = System.getProperty("user.home");
System.out.println("===userhomePath===" +userhomePath);
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,環境配置項的問題最後在系統啓動初始化的時候全部加載打印到日誌文件中,方便查看是否我們真正所期望的值。