2010-08-06 128 views
1

我有一個Web應用程序,它由以前在Linux機器上運行的一些JSP組成。我需要在運行Tomcat 5.5.29的Windows XP SP3機器上運行它。現在大多數所有的東西都在工作,但這一項:應用程序有能力將配置文件寫入其Windows目錄(即C:\ Program Files \ Apache \ Tomcat \ webapps \ myapp)。但是當它嘗試這樣做時,應用程序無法打開FileOutputStream(返回null)。如果我放棄路徑說明符,並讓它打開文件,它會在Tomcat目錄中成功打開它。爲JSP/Tomcat/Windows設置目錄權限

第一行失敗,但第二個成功:

// outputFile2 = new PrintWriter(new FileOutputStream(basePathName + "programAll.txt", false)); 
    outputFile2 = new PrintWriter(new FileOutputStream("programAll.txt", false)); 

下面是創建的basePathName的代碼:

String basePathName = getBaseFilePath(); 
    ... 
    public String getBaseFilePath() 
      { 
      String curDir = System.getProperty("catalina.home"); 
      curDir = curDir + "/webapps/pubmed/"; 
      curDir = "file:///" + formatPathNameForOS(curDir); 
      return curDir; 
      } 

    public String formatPathNameForOS(String pathName) 
     { 
     if (codeIsOnWindows()) 
      { 
      pathName = pathName.replace('/','\\'); 
      } 
     else 
      { 
      pathName = pathName.replace('\\','/'); 
      } 
     return pathName; 
    } 

這裏的異常消息:

HTTP Status 500 - 

type Exception report 

message 

description The server encountered an internal error() that prevented it from fulfilling this request. 

exception 

org.apache.jasper.JasperException 
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:460) 
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:373) 
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:321) 
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:257) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 
root cause 

java.lang.NullPointerException 
    org.apache.jsp.updateMemberLists_jsp._jspService(updateMemberLists_jsp.java:1492) 
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:331) 
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:321) 
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:257) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 

以下是堆棧跟蹤:

Aug 6, 2010 1:20:39 PM org.apache.catalina.core.StandardWrapperValve invoke 
SEVERE: Servlet.service() for servlet jsp threw exception 
java.lang.NullPointerException 
    at org.apache.jsp.updateMemberLists_jsp._jspService(updateMemberLists_jsp.java:1492) 
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:331) 
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:321) 
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:257) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108) 
    at org.globus.tomcat.coyote.valves.HTTPSValve55.invoke(HTTPSValve55.java:45) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174) 
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:873) 
    at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665) 
    at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528) 
    at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81) 
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689) 
    at java.lang.Thread.run(Thread.java:595) 

我已經看過了updateMembersLists_jsp.java,並且這裏是空指針發生的部分:

//create a file to write to the output 
PrintWriter outputFile2 = null; 
try 
    { 
    outputFile2 = new PrintWriter(new FileOutputStream(basePathName + "programAll.txt", false)); 
// outputFile2 = new PrintWriter(new FileOutputStream("programAll.txt", false)); 
    } 
    catch (FileNotFoundException e) 
     { 
     out.write("<p><font color='red'>Error Saving</font></p>"); 
     } 
outputFile2.print(output); // THIS IS LINE 1492 -- NULL POINTER 
outputFile2.close(); 

另外:我們現在運行Tomcat關閉根目錄,而不是程序文件的。我檢查了basePathName並且它正在被正確計算。

現在我發現Tomcat的策略設置可能需要調整。我在catalina.policy中添加了以下幾行,希望它能夠設置正確的內容:

// The permissions granted to the pubmed webapp 
grant codeBase "file:${catalina.home}/webapps/pubmed/-" { 
     permission java.io.FilePermission "${catalina.home}/webapps/pubmed/-", "read, write"; 
     permission java.io.FilePermission "${catalina.home}/webapps/pubmed/*", "read, write"; 
}; 

這似乎沒有任何效果。 tomcat正在運行的Windows用戶對pubmed目錄具有讀/寫權限。除了這個webapp將文件寫入自己的目錄似乎有問題之外,我錯過了什麼?

肖恩

+0

什麼是basePathName? – naikus 2010-08-06 16:17:03

+0

好問題。這是 文件:/// C:\ Program Files \ Apache Software Foundation \ Tomcat 5.5 \ webapps \ pubmed \ – BridgetG 2010-08-06 16:21:38

+0

對不起另一個問題:你如何獲得它? – naikus 2010-08-06 16:38:22

回答

1

嘗試通過以下方式獲得的路徑:

String path = getServletContext().getRealPath("/"); 

這將您的路徑(到你的webapp)轉換爲實際路徑到磁盤上。

+0

看起來像這樣返回的路徑與我上面列出的絕對路徑相同。 – BridgetG 2010-08-06 17:01:57

+0

@SeanG你提到的路徑是一個URL(文件:/ url),getRealPath(「/」)不會返回類似URL的字符串。有兩個選項可以嘗試:1)將路徑更改爲正確的URL(帶正斜槓)並查看或2)使用從getRealPath()獲得的路徑。還像Balus提到的,任何日誌/堆棧痕跡都會有幫助 – naikus 2010-08-06 17:19:23

+0

它的工作!把getRealPath放在那裏就行了。當我第一次嘗試時,我認爲斜槓是錯誤的。謝謝 - – BridgetG 2010-08-06 21:05:41

1

您不應該在Java IO中使用相對路徑。該路徑將相對於當前工作目錄,這取決於您如何啓動Web服務器/ Web應用程序。例如,當Eclipse中啓動Tomcat時,它可能是Eclipse項目目錄。當Tomcat從CMD啓動時,它可能是CMD中當前打開的文件夾。當Tomcat作爲服務啓動時,它可能是Tomcat的/bin文件夾。要自己確定它,請執行以下操作:

System.out.println(new File("programAll.txt").getAbsolutePath()); 

而且您會發現它與您預期的完全不同。

您需要指定絕對路徑代替。您可以使用ServletContext#getRealPath()將web內容相對路徑轉換爲絕對磁盤文件系統路徑。

String relativeWebPath = "programAll.txt"; 
String absoluteDiskPath = getServletContext().getRealPath(relativeWebPath); 
output = new FileOutputStream(absoluteDiskPath); 
// ... 

getServletContext()方法在每個servlet中都可用。


這就是說,你有沒有考慮到的是,在web內容的所有修改過的文件都將灰飛煙滅/被覆蓋的,只要你重新部署/重新啓動Web應用/服務器?如果你想有更多的永久存儲空間,我強烈建議將存儲在以外的web內容(當然是絕對路徑,例如/var/webapp/files左右)。

+0

我按照描述添加了getServletContext代碼,並且它返回了我一直使用的相同路徑。所以,雖然我很欣賞現在相對路徑上的細微差別,但我不認爲這是我遇到的問題。我在上面的評論中列出的basePathName字符串是不是絕對的? – BridgetG 2010-08-06 17:00:32

+1

哦,我明白了。你能否更新你的問題以包含完整的異常信息和跟蹤?我認爲你說它返回null是不明確的。從字面上看,情況並非如此。 'new FileOutputStream(path)'部分只能返回一個完整的實例或拋出一個異常,而不是null。 – BalusC 2010-08-06 17:09:53

+0

@BalusC多數民衆贊成在權利,這就是我認爲,我認爲basePathname爲空 – naikus 2010-08-06 17:14:43