Jetty:默认的 servlet 上下文路径
Jetty: default servlet context path
我需要设置 Servlet(由于某些原因只有 servlet 而不是处理程序)以处理 war 之外的文件。在这里 我找到了以下解决方案:
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
。为什么?我怎样才能让它在这个特定的上下文中工作?由于同样的原因,我使用 jetty 9.2.15。
DefaultServlet
是为了看contextPath
之后的请求URI。
在您的示例代码中,当您将 servlet 的 url 模式从 /
更改为 /foo/*
时,在磁盘上查找的结果文件现在包含 /foo/
部分。
换句话说,/css/main.css
的请求 URI 导致它希望找到的文件(在磁盘上)为 ./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
中正常运行,您将在 "default url-pattern" 上添加 default
Servlet 名称,它恰好实现为 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"
现在,如果您也需要从不属于 webapp 的目录中的请求 URI /foo/*
提供静态内容,您也可以这样做.
这将要求您设置另一个不参与 ServletContext
.
的 DefaultServlet
此设置的示例是...
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
的初始参数被告知使用请求 URI 的 pathInfo,而不是像通常那样在 contextPath 上拆分。
For more information on what this whole pathInfo, request URI, contextPath, and url-patterns ending in /*
are all about, see the useful answer by @30thh
这个独立的 DefaultServlet
声明不参与 ServletContext
并且图书馆将无法通过 ServletContext
查看或访问来自 DefaultServlet
的内容方法。但是,所有传入的 HTTP 客户端请求都可以通过 url 模式轻松请求内容。
我需要设置 Servlet(由于某些原因只有 servlet 而不是处理程序)以处理 war 之外的文件。在这里 我找到了以下解决方案:
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
。为什么?我怎样才能让它在这个特定的上下文中工作?由于同样的原因,我使用 jetty 9.2.15。
DefaultServlet
是为了看contextPath
之后的请求URI。
在您的示例代码中,当您将 servlet 的 url 模式从 /
更改为 /foo/*
时,在磁盘上查找的结果文件现在包含 /foo/
部分。
换句话说,/css/main.css
的请求 URI 导致它希望找到的文件(在磁盘上)为 ./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
中正常运行,您将在 "default url-pattern" 上添加 default
Servlet 名称,它恰好实现为 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"
现在,如果您也需要从不属于 webapp 的目录中的请求 URI /foo/*
提供静态内容,您也可以这样做.
这将要求您设置另一个不参与 ServletContext
.
DefaultServlet
此设置的示例是...
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
的初始参数被告知使用请求 URI 的 pathInfo,而不是像通常那样在 contextPath 上拆分。
For more information on what this whole pathInfo, request URI, contextPath, and url-patterns ending in
/*
are all about, see the useful answer by @30thh
这个独立的 DefaultServlet
声明不参与 ServletContext
并且图书馆将无法通过 ServletContext
查看或访问来自 DefaultServlet
的内容方法。但是,所有传入的 HTTP 客户端请求都可以通过 url 模式轻松请求内容。