2012-02-06 170 views
13

我对Spring没有经验,现在我需要做的所有事情都是访问并获取对webapp文件夹中文件和文件夹的引用。这里是我的相关项目层次:在Spring中访问webapp文件夹中的文件/目录

-src 
--main 
---java (marked as source root) 
----my 
-----package 
------controller 
-------Home.java 
---webapp 
----images 
-----avatars 

我在Home.java代码:

@Controller 
@RequestMapping("/") 
public class Home 
{ 
    @RequestMapping(method = RequestMethod.GET) 
    public String index(Model model, 
         HttpServletRequest request) throws Exception 
    { 
     String test1 = request.getSession().getServletContext().getRealPath(""); 
     String test2 = request.getSession().getServletContext().getRealPath("/"); 
     String test3 = request.getRealPath(""); 
     String test4 = request.getRealPath("/"); 
     String test5 = request.getSession().getServletContext().getRealPath(request.getServletPath()); 

     return "index"; 
    } 
} 

所有5个请求返回null。难道我做错了什么?

的web.xml:

<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
     version="2.5"> 

    <display-name>Test</display-name> 

    <servlet> 
     <servlet-name>test</servlet-name> 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 

    <servlet-mapping> 
     <servlet-name>test</servlet-name> 
     <url-pattern>/</url-pattern> 
    </servlet-mapping> 

    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/applicationContext.xml</param-value> 
    </context-param> 

    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 

    <session-config> 
     <session-timeout>10</session-timeout> 
    </session-config> 
</web-app> 

我试图实现(在本例中未显示),用于编码负责图像的缩放控制器。为此,我需要访问src/main/webapp/_images文件夹。

谢谢!

更新:为了更好地理解,简化了示例。

Update2:感谢@gigadot的建议,我将应用程序部署为爆炸WAR,问题部分解决。有人能告诉我在部署WAR时爆炸的区别是什么?是否建议在生产服务器上执行某些操作?优点缺点?

我认为值得用一个例子来解释这种情况。假设我正在编写一个社交网络,我必须有可能上传我的个人资料图片。这张照片将被上传到src/main/webapp/_images/avatars/[myid].jpg文件夹。 是否建议将图片上传到webapp文件夹?还是有更好的解决方案? 我希望能够在访问URL /images/[width]x[height]/[userid].jpg时返回缩放的图像实例。

部署WAR的爆炸和实施ResourceLoaderAware(感谢@KevinSchmidt),我可以让它工作中使用此:

resourceLoader.getResource("file:" + request.getSession().getServletContext().getRealPath("/") + "_images/avatars/"); 

对我来说,它看起来很肮脏,是它在生产服务器是个好主意?有更好的解决方案吗?

+0

我在乎目录是否存在 – satoshi 2012-02-07 10:08:49

+0

任何人......?谢谢 – satoshi 2012-02-09 10:39:02

+0

你想如何处理这些文件,只需将它们返回给客户端,或处理其内容? – Ralph 2012-02-20 07:52:32

回答

15

您是如何部署应用程序的?

ServletContext().getRealPath("/")如果未部署为爆炸,则可能返回null。请阅读下面的链接了解更多信息。但是,配置它的方法可能与您的servlet容器不同。

http://ananthkannan.blogspot.com/2009/12/servletcontextgetrealpath-returns-null.html

更新

有人能告诉我这是在部署WAR作为 区别爆炸?

当您展开WAR文件时,servlet容器(例如, Tomcat会将war文件的内容提取到一个临时文件夹中,并运行该文件夹中的所有内容,因此{WEB_ROOT]/_images/avatars/[myid].jpg实际上存在于文件系统(硬盘)上。因此,你实际上可以得到真正的路径(正如它已经在方法的名字中所说的那样)。但是,如果您的servlet容器未提取war文件,则您要查找的文件夹位于war文件中,并且没有真正的路径,因此它将返回null

是不是推荐在生产服务器上执行某些操作? 优点/缺点?

你不应该动态内容存储你的源文件夹或文件夹的根目录(Web应用程序),因为servlet容器会暂时使用,并删除或更改到一个新的文件夹时,你重新部署Web应用程序下。您可能会丢失放入这些文件夹的动态数据。 Web根文件夹通常用于存储静态内容,这意味着您不想更改的内容 - 例如,您的Web组件的图形图像,如背景图像,css等。

存储用户数据的常用方法是以某种方式在用户空间中创建一个文件夹,并将您的动态数据放在那里。但是,您将无法为webroot之外的文件夹提供内容。您将需要编写自己的静态小服务程序以在请求时传输数据。这对初学者来说非常复杂。

实现自己的静态servlet来提供动态内容的最简单方法是扩展servlet容器的静态servlet。但是,您的代码将高度依赖您要部署到的servlet容器。

由于您要为调整图像大小提供一个REST界面,因此您可以创建一个控制器,从动态内容文件夹读取原始图像,进行大小调整,将其保存为临时文件或刷新HttpResponse

+0

谢谢,这解决了这个问题。你能告诉我在爆炸时部署WAR有何不同?是否建议在生产服务器上执行某些操作?优点缺点? – satoshi 2012-02-23 14:14:49

+0

(更新了相应的原始问题) – satoshi 2012-02-23 15:44:43

+0

@satoshi答案已更新。 – gigadot 2012-02-24 01:57:39

0

ClassPathResource可能有帮助。如果错误地访问类路径中资源的方式。

关于网络资源的位置,存储在src/main/resources中的将被部署在WEB-INF/classes文件夹中,所以这显然是不可行的。改为用户webapp。

更新:现在我明白你来自哪里。我没有看到地图上的任何错误,尽管非常奇特。机会是DispatcherServlet映射不包括images文件夹(即它不是/*)。

对于文件打开的问题,webapp目录在类加载器中不可见,只有WEB-INF文件夹例外。因此,您需要调用HttpServletRequest.getRealPath()方法才能获得图像的真实路径。

请注意,虽然不太可能成为您的情况,但强化的Java JVM(即带有安全策略的JVM)可能需要额外的授权才能让servlet从任意位置打开文件。

+0

谢谢你的回答。我现在将所有CSS/JS /图像文件和文件夹移至webapp文件夹。现在图像文件夹位于src/main/webapp/images,我如何从我的代码中引用它?它不在类路径中,对吗? – satoshi 2012-02-06 18:24:23

+0

你能透露更多关于你想要完成的事情吗? – 2012-02-06 18:43:35

+0

是的,我只是修改了原来的问题。谢谢 – satoshi 2012-02-06 18:53:55

0

看看在春季参考中使用<mvc:resources>,部分16.14.5 Configuring Serving of Resources。我使用这种方法为我的JavaScript/CSS /图像,它运作良好 - 我只需要添加一行到我的application-context.xml文件。该文件指出:

这提供了一种方便的方法,从比Web应用程序根等 地点,包括 类路径中的位置提供静态资源。

4

这是我的代码和它的作品 我不明白空。

我跑JDK 1.7_02 的Tomcat 7.0.25 春3.1.1

而且我没有得到空

@Controller 
    public class IndexController { 

     @RequestMapping("/index") 
     public String go(HttpServletRequest request, HttpServletResponse response) { 
      HttpSession session = request.getSession(); 
      ServletContext sc = session.getServletContext(); 
      String x = sc.getRealPath("/"); 
      System.out.println(x); 
      return "index"; 
     } 
    } 
+0

如果我有RestController,并且没有会话,该怎么办? – Sanandrea 2015-12-21 13:32:42

0

你可以试试这个:

@Controller 
@RequestMapping("/") 
public class Home implements ServletContextAware 
{ 
    private ServletContext servletContext; 
    public void setServletContext(ServletContext servletCtx){ 
     this.servletContext=servletCtx; 
    } 

    @RequestMapping(method=RequestMethod.GET) 
    public String index(Model model,HttpServletRequest) throws Exception{ 
     String rootPath = servletContext.getRealPath("/"); 
     //... 
    } 
} 
5

考虑到文件的位置,你应该看看春节ResourceLoader,像这样:

public class ArbitraryResourceLoader implements ResourceLoaderAware { 
    private ResourceLoader resourceLoader; 

    public void test() { 
     Resource resource = resourceLoader.getResource("file:webapp/images/avatars/avatar.jpg"); 
    } 

    @Override 
    public void setResourceLoader(ResourceLoader resourceLoader) { 
     this.resourceLoader = resourceLoader; 
    } 
} 

请注意,您的容器需要有权限访问该文件。

+0

谢谢,相应地更新了原来的问题 – satoshi 2012-02-23 15:59:11

相关问题