2010-08-06 126 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