在Spring中访问webapp文件夹中的文件/目录

时间:2012-02-06 18:07:34

标签: java spring spring-mvc

我在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/");

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

6 个答案:

答案 0 :(得分:16)

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

如果未将{p> ServletContext().getRealPath("/")部署为已展开,则

{WEB_ROOT]/_images/avatars/[myid].jpg可能会返回null。请阅读以下链接以获取更多信息。但是,配置它的方法可能与servlet容器不同。

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

<强>更新

  

有人能告诉我部署WAR的区别是什么   分解?

将war文件部署为爆炸时,servlet容器,例如, Tomcat会将war文件的内容提取到一个临时文件夹中并运行该文件夹中的所有内容,以便null实际存在于文件系统(硬盘)上。因此,您实际上可以获得真实路径(正如它已经在方法的名称中所述)。但是,如果您的servlet容器未提取war文件,则您要查找的文件夹位于war文件中,并且没有真正的路径,因此它将返回HttpResponse

  

是否不建议在生产服务器上执行此操作?   优点/缺点?

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

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

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

由于您要提供用于调整图像大小的REST界面,因此您可以创建一个控制器,该控制器从动态内容文件夹中读取原始图像,执行调整大小,将其另存为临时文件或刷新{的内容{1}}。

答案 1 :(得分:5)

考虑到文件的位置,您应该查看Spring 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;
    }
}

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

答案 2 :(得分: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";
        }
    }

答案 3 :(得分:0)

ClassPathResource可能会有所帮助。如果完全错误的话,你可以在类路径中访问资源。

对于Web资源的位置而言,存储在src / main / resources中的那些资源将部署在WEB-INF / classes文件夹中,因此显然不行。用户webapp。

更新:现在我看到你来自哪里。我没有看到映射有什么问题,虽然极具异国情调。有可能DispatcherServlet映射不包含images文件夹(即它不是/*)。

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

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

答案 4 :(得分:0)

在Spring Reference,16.14.5 Configuring Serving of Resources部分中查看使用<mvc:resources>。我将此方法用于我的JavaScript / CSS /图像并且效果很好 - 我只需要在我的application-context.xml文件中添加一行。文档说明:

  

这提供了一种从中提供静态资源的便捷方式   Web应用程序根目录以外的位置,包括位置   classpath。

答案 5 :(得分: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("/");
       //...
    }
}