在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/");
对我来说,它看起来很脏,对生产服务器来说是个好主意吗?有更好的解决方案吗?
问题答案:
您究竟如何部署应用程序?
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
。