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模式輕鬆請求內容。
不幸的是,我不能一勞永逸。感謝您的詳細解釋。 –