2012-02-06 73 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

相關問題