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

sat*_*shi 15 java spring spring-mvc

我在Spring方面缺乏经验,现在我需要做的就是访问并获取webapp文件夹中的文件和文件夹的引用.这是我的相关项目层次结构:

-src
--main
---java (marked as source root)
----my
-----package
------controller
-------Home.java
---webapp
----images
-----avatars
Run Code Online (Sandbox Code Playgroud)

我在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";
    }
}
Run Code Online (Sandbox Code Playgroud)

所有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>
Run Code Online (Sandbox Code Playgroud)

我想要实现的(在这个例子中没有显示)是编码负责图像缩放的控制器.出于这个原因,我需要访问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/");
Run Code Online (Sandbox Code Playgroud)

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

gig*_*dot 16

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

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.

是不是建议在生产服务器上做什么?优点缺点?

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

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

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

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


Kev*_*idt 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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