Jetty:默认的servlet上下文路径

Pav*_*l_K 3 java servlets jetty embedded-jetty

我需要设置Servlet(由于某些原因,只有servlet而不是处理程序)来处理war之外的文件.在这里/sf/answers/2011458501/我找到了以下解决方案:

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);
Run Code Online (Sandbox Code Playgroud)

这个解决方案有效,这就是我需要的.但是,一旦我将LINE N更改为,它就会停止工作ctx.addServlet(holderPwd, "/foo/*");.我试过"/ foo /","/ foo",但结果是一样的 - 我明白了not found.为什么?如何使其适应这种特定的背景?由于同样的原因,我使用jetty 9.2.15.

Joa*_*elt 8

该DefaultServlet设计看后请求URI contextPath.

在当你从改变你的servlet的URL模式的示例代码/来/foo/*生成的文件正在寻找在磁盘上是现在包括/foo/部分.

换句话说,/css/main.css它希望找到的文件(在磁盘上)中的结果的请求URI./src/webapp/foo/css/main.css

你的例子有一些缺陷.拥有一个空的资源库并不是明智之举ServletContextHandler,因为它ServletContext本身需要访问该配置值.

您可以通过删除来解决这个问题

holderPwd.setInitParameter("resourceBase", "./src/webapp/");
Run Code Online (Sandbox Code Playgroud)

并使用ServletContextHandler.setBaseResource(Resource)代替......

ctx.setResourceBase(Resource.newResource(new File("./src/webapp")));
Run Code Online (Sandbox Code Playgroud)

这将允许以下ServletContext方法(由无数的servlet库使用)也可以工作

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

最后,为了使这个设置理智ServletContextHandler,你将default在"默认url-pattern"上添加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"
Run Code Online (Sandbox Code Playgroud)

现在,如果您还需要/foo/*从不属于webapp的目录中提供来自请求URI的静态内容,您也可以这样做.这将要求您设置另一个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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这使用了第二个DefaultServlet,仅使用唯一的资源库DefaultServlet,并映射到以其结尾的url模式/*.

最后,DefaultServlet告诉第二个init-parameter 使用Request URI的pathInfo,而不是像通常那样在contextPath上拆分.

有关整个pathInfo,请求URI,contextPath和url-patterns结尾的/*内容的更多信息,请参阅@ 30thh的有用答案

此独立DefaultServlet声明不参与,ServletContext并且库将无法DefaultServlet通过ServletContext方法查看或访问该内容.但是,所有传入的HTTP客户端请求都可以通过该url-pattern轻松地请求内容.