Jetty:默认的servlet上下文路径

时间:2016-08-18 06:48:05

标签: java servlets jetty embedded-jetty

我需要设置Servlet(因为某些原因,只有servlet而不是处理程序)来处理war之外的文件。在这里https://stackoverflow.com/a/28735121/5057736我找到了以下解决方案:

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。

1 个答案:

答案 0 :(得分:8)

DefaultServlet旨在查看contextPath之后的请求URI。

在您的示例代码中,当您将servlet的url-pattern从/更改为/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中使此设置更加清晰,您需要在&#34;默认网址格式&#34;上添加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/*的静态内容,那么您也可以这样做。 这将要求您设置另一个不参与DefaultServlet的{​​{1}}。

此设置的一个示例是......

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结尾的网址格式。

最后,第二个/*的init-parameter被告知使用Request URI的pathInfo而不像通常那样在contextPath上拆分。

  

有关以DefaultServlet结尾的整个pathInfo,request URI,contextPath和url-patterns的详细信息,请参阅useful answer by @30thh

此独立/*声明未参与DefaultServlet,图书馆将无法通过ServletContext方法查看或访问DefaultServlet内容。但是,所有传入的HTTP客户端请求都可以通过该url-pattern轻松地请求内容。