2016-08-18 142 views
0

我需要設置Servlet(由於某些原因,只有servlet不處理)才能處理war之外的文件。這裏https://stackoverflow.com/a/28735121/5057736我發現了以下解決方案:Jetty:默認的servlet上下文路徑

Server server = new Server(8080); 

ServletContextHandler ctx = new ServletContextHandler(); 
ctx.setContextPath("/"); 

DefaultServlet defaultServlet = new DefaultServlet(); 
ServletHolder holderPwd = new ServletHolder("default", defaultServlet); 
holderPwd.setInitParameter("resourceBase", "./src/webapp/"); 

ctx.addServlet(holderPwd, "/*");//LINE N 
ctx.addServlet(InfoServiceSocketServlet.class, "/info"); 

server.setHandler(ctx); 

此解決方案的作品,這是我需要的。但是,只要將LINE N更改爲ctx.addServlet(holderPwd, "/foo/*");,它就會停止工作。我試過「/ foo /」,「/ foo」但結果是一樣的 - 我得到not found。爲什麼?我怎樣才能使它在這個特定的環境下工作?由於相同的原因,我使用碼頭9.2.15。

回答

6

DefaultServlet旨在查看contextPath之後的請求URI。

在您的示例代碼中,當您將servlet的url-pattern從/更改爲/foo/*時,在磁盤上查找的結果文件現在包含/foo/部分。

換句話說,的/css/main.css結果的文件(在磁盤上)在請求URI它希望找到作爲./src/webapp/foo/css/main.css

你的例子有一些缺陷。由於ServletContext本身需要訪問該配置值,因此您的ServletContextHandler沒有明確的空白資源庫。

你會解決,通過消除...

holderPwd.setInitParameter("resourceBase", "./src/webapp/"); 

,並使用ServletContextHandler.setBaseResource(Resource),而不是...

ctx.setResourceBase(Resource.newResource(new File("./src/webapp"))); 

這將允許以下ServletContext方法(使用無數的servlet庫)工作以及

  • String getRealPath(String path)
  • URL getResource(String path)
  • InputStream getResourceAsStream(String path)
  • Set<String> getResources(String path)

最後,使這一設置在ServletContextHandler神志清醒,你將添加default Servlet的名稱,在 「默認的url-pattern」,這恰好是實施爲DefaultServlet

像這樣:

// Lastly, the default servlet for root content 
// It is important that this is added last. 
String defName = "default"; // the important "default" name 
ServletHolder holderDef = new ServletHolder(defName, DefaultServlet.class); 
holderDef.setInitParameter("dirAllowed","true"); 
ctx.addServlet(holderDef,"/"); // the servlet spec "default url-pattern" 

現在,如果你有必要從請求的URI /foo/*提供靜態內容從一個目錄不屬於Web應用程序,你可以做到這一點。 這將需要您設置另一個DefaultServlet,不參與ServletContext

此設置的一個示例是...

package jetty; 

import org.eclipse.jetty.server.Server; 
import org.eclipse.jetty.server.ServerConnector; 
import org.eclipse.jetty.servlet.DefaultServlet; 
import org.eclipse.jetty.servlet.ServletContextHandler; 
import org.eclipse.jetty.servlet.ServletHolder; 
import org.eclipse.jetty.util.resource.PathResource; 

import java.io.File; 
import java.nio.file.Path; 

public class ManyDefaultServlet 
{ 
    public static void main(String[] args) throws Exception { 
     Server server = new Server(); 
     ServerConnector connector = new ServerConnector(server); 
     connector.setPort(8080); 
     server.addConnector(connector); 

     // The filesystem paths we will map 
     Path homePath = new File(System.getProperty("user.home")).toPath().toRealPath(); 
     Path pwdPath = new File(System.getProperty("user.dir")).toPath().toRealPath(); 

     // Setup the basic application "context" for this application at "/" 
     // This is also known as the handler tree (in jetty speak) 
     ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); 
     context.setContextPath("/"); 
     context.setBaseResource(new PathResource(pwdPath)); 
     server.setHandler(context); 

     // Fist, add special pathspec of "/home/" content mapped to the homePath 
     ServletHolder holderHome = new ServletHolder("static-home", DefaultServlet.class); 
     holderHome.setInitParameter("resourceBase",homePath.toUri().toASCIIString()); 
     holderHome.setInitParameter("dirAllowed","true"); 
     // Use request pathInfo, don't calculate from contextPath 
     holderHome.setInitParameter("pathInfoOnly","true"); 
     context.addServlet(holderHome,"/foo/*"); // must end in "/*" for pathInfo to work 

     // Lastly, the default servlet for root content 
     // It is important that this is last. 
     String defName = "default"; // the important "default" name 
     ServletHolder holderDef = new ServletHolder(defName, DefaultServlet.class); 
     holderDef.setInitParameter("dirAllowed","true"); 
     context.addServlet(holderDef,"/"); // the servlet spec "default url-pattern" 

     server.start(); 
     server.join(); 
    } 
} 

此使用第二DefaultServlet,採用了獨特的資源基礎爲只有DefaultServlet,並映射到在/*結尾的URL圖案。

最後,第二個DefaultServlet的init參數被告知使用請求URI的pathInfo,而不像通常那樣在contextPath上分割。

關於什麼這整個PATHINFO更多信息,請求URI,contextPath中,並在/*結束URL的模式是一回事,看到useful answer by @30thh

這個獨立DefaultServlet聲明不參加ServletContext和庫將無法通過ServletContext方法查看或訪問該DefaultServlet中的內容。但是,所有傳入的HTTP客戶端請求都可以通過該url模式輕鬆請求內容。

+0

不幸的是,我不能一勞永逸。感謝您的詳細解釋。 –