Jetty:默认 servlet 上下文路径 [英] Jetty: default servlet context path

查看:33
本文介绍了Jetty:默认 servlet 上下文路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to set Servlet (only servlet not handler because of some reasons) to work with files outside war. Here https://stackoverflow.com/a/28735121/5057736 I found the following solution:

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.

This solutions works and this is what I need. However, it stops working as soon as I change LINE N to ctx.addServlet(holderPwd, "/foo/*");. I tried "/foo/","/foo" but result is the same - I get not found. Why? How can I make it work with this certain context? I use jetty 9.2.15 because of the same reasons.

推荐答案

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

The DefaultServlet is designed to look at the request URI after the contextPath.

在示例代码中,当您将 servlet 的 url-pattern 从 / 更改为 /foo/* 时,在磁盘上查找的结果文件现在包含/foo/ 部分.

In your example code when you changed the url-pattern of your servlet from / to /foo/* the resulting file being looked for on disk is now includes the /foo/ portion.

换句话说,/css/main.css 的请求 URI 会导致它期望找到的文件(在磁盘上)为 ./src/webapp/foo/css/main.css

In other words, a request URI of /css/main.css results in the file (on disk) it expects to find as ./src/webapp/foo/css/main.css

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

Your example has a few flaws. It's not a wise have an empty resource base for your ServletContextHandler, as the ServletContext itself needs access to that configuration value.

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

You would fix that by removing ...

holderPwd.setInitParameter("resourceBase", "./src/webapp/");

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

ctx.setResourceBase(Resource.newResource(new File("./src/webapp")));

这将允许以下 ServletContext 方法(被无数 servlet 库使用)也能正常工作

This will allow the following ServletContext methods (used by countless servlet libraries) to work as well

  • String getRealPath(String path)
  • URL getResource(String path)
  • InputStream getResourceAsStream(String path)
  • 设置<字符串>getResources(String path)

最后,为了使 ServletContextHandler 中的设置合理,您将在默认 url-pattern"上添加 default Servlet 名称,这恰好是实现为 DefaultServlet.

Finally, to make this setup sane in the ServletContextHandler, you'll add the default Servlet name, on the "default url-pattern", which happens to be implemented as the 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/* 的静态内容,您可以这样做也.这将需要您设置另一个不参与 ServletContextDefaultServlet.

Now, if you also have a need to serve static content from request URI /foo/* out of a directory not belonging to the webapp, you can do that too. That will require you to setup another DefaultServlet that does not participate in the ServletContext.

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

An example of this setup is ...

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 的唯一资源库,并映射到以 /*.

This uses a second DefaultServlet, using a unique resource base for that DefaultServlet only, and mapped to a url-pattern that ends in /*.

最后,第二个 DefaultServlet 的 init 参数被告知使用请求 URI 的路径信息,而不是像通常那样在 contextPath 上拆分.

Finally, the init-parameter for this second DefaultServlet is told to use the pathInfo of the Request URI and not split on the contextPath like it normally does.

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

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 并且库将无法查看或访问来自该 DefaultServlet 的内容通过 ServletContext 方法.但是,所有传入的 HTTP 客户端请求都可以通过该 url-pattern 轻松请求内容.

This stand alone DefaultServlet declaration does not participate in the ServletContext and libraries will not be able to see or access the content from that DefaultServlet via the ServletContext methods. However all incoming HTTP client requests can request the content easily via that url-pattern.

这篇关于Jetty:默认 servlet 上下文路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆