DefaultServlet
旨在查看
contextPath
后的请求URI。
在您的示例代码中,当您将servlet的url-pattern从
/
更改为
/foo/*
时,正在查找的结果文件现在包括
/foo/
部分。
换句话说,请求URI
/css/main.css
会将期望在磁盘上找到的文件(位于)
./src/webapp/foo/css/main.css
您的示例有一些缺陷。对于您的
ServletContextHandler
,没有一个空的资源基础是不明智的,因为
ServletContext
本身
需要访问该配置值。
您可以通过删除...来解决问题。
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
中使该设置正常,您需要在“默认url-pattern”上添加
default
Servlet名称,它恰好实现为
DefaultServlet
。
像这样:
String defName = "default";
ServletHolder holderDef = new ServletHolder(defName, DefaultServlet.class);
holderDef.setInitParameter("dirAllowed","true");
ctx.addServlet(holderDef,"/");
现在,如果您还需要从请求URI
/foo/*
中提供静态内容,而这些内容不属于Web应用程序的目录,则也可以实现。
这将需要您设置另一个
DefaultServlet
,该Servlet不参与
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);
Path homePath = new File(System.getProperty("user.home")).toPath().toRealPath();
Path pwdPath = new File(System.getProperty("user.dir")).toPath().toRealPath();
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
context.setBaseResource(new PathResource(pwdPath));
server.setHandler(context);
ServletHolder holderHome = new ServletHolder("static-home", DefaultServlet.class);
holderHome.setInitParameter("resourceBase",homePath.toUri().toASCIIString());
holderHome.setInitParameter("dirAllowed","true");
holderHome.setInitParameter("pathInfoOnly","true");
context.addServlet(holderHome,"/foo/*");
String defName = "default";
ServletHolder holderDef = new ServletHolder(defName, DefaultServlet.class);
holderDef.setInitParameter("dirAllowed","true");
context.addServlet(holderDef,"/");
server.start();
server.join();
}
}
这里使用了第二个DefaultServlet
,该DefaultServlet
仅使用唯一的资源基础,并映射到以/*
结尾的url-pattern。
最后,告诉这个第二个DefaultServlet
的init参数使用请求URI的pathInfo而不是像通常那样在contextPath上拆分。
有关整个pathInfo、请求URI、contextPath和以/*
结尾的url-pattern的更多信息,请参见@30thh的有用答案
这个独立的DefaultServlet
声明不参与ServletContext
,库将无法通过ServletContext
方法看到或访问该DefaultServlet
的内容。然而,所有传入的HTTP客户端请求都可以通过该url-pattern轻松请求内容。