将未找到的(在特定目录中)转发到定义的 servlet 路径(对于使用 History.pushState 的 SPA)

问题描述 投票:0回答:1

背景

我有使用

history.pushState()
进行导航的 SPA 应用程序,因此我需要为许多 URL 提供相同的 HTML(可能由 JSP 或 servlet 生成)。不过,有些静态资源不能被这种机制“拦截/重写”。我还需要添加仅匹配 HTML 而不是其他静态资源或其他 servlet 的过滤器。最后,这个“转发”必须被范围指定到特定的路径(我的应用程序具有多个此类 SPA,每个 SPA 都有自己的范围和 HTML),而这一切都使用嵌入式 Jetty。

我在 Jetty 9、10 和 11 上都有工作代码,但 Jetty 12 引入了重大更改,使其无法执行。我正在寻找一种方法来使用 Jetty 12 复制相同的行为。

所以,假设这些文件:

/index.html
/subdir/
  +- app.js
  +- style.css
  `- index.html

和 servlet 映射到

/subdir/logout
/subdir/api/*

我需要所有这些请求返回

/subdir/index.html
(正确地通过具有requestforward调度类型的过滤器):

  • /subdir/
  • /subdir/index.html
  • /subdir/foo
  • /subdir/foo/bar
  • /subdir/bar

但是这些应该正确返回静态文件或调用映射的 servlet:

  • /subdir/app.js
  • /subdir/style.css
  • /subdir/api/foo
  • /subdir/logout

使用 Jetty 工作代码 9/10/11

在 Jetty 9/10/11 中,我曾经这样做过(注意:

context
ServletContextHandler
):

    // Sometimes I need a filter such as this one (injecting HTML/JS into the response)
    // or other filters that would redirect unauthenticated users to login (possibly SSO)
    context.addFilter(CsrfServletFilter.class, "*.html", EnumSet.of(REQUEST, ASYNC, FORWARD));
    // Sometimes the HTML is generated by a servlet (other times it would be an index.jsp file)
    context.addServlet(new ServletHolder(indexServlet), "/subdir/index.html");

    ServletHolder resources =
        new ServletHolder(
            "resources",
            new DefaultServlet(
                new ResourceService() {
                  @Override
                  protected void notFound(HttpServletRequest request, HttpServletResponse response)
                      throws IOException {
                    // For use with history.pushState: send back the index page for everything not found.
                    try {
                      response.setHeader("Content-Location", "/subdir/");
                      request.getRequestDispatcher("/subdir/").forward(request, response);
                    } catch (ServletException e) {
                      throw new RuntimeException(e);
                    }
                  }
                }));
    resources.setInitParameter("dirAllowed", "false");
    resources.setInitParameter("welcomeServlets", "exact");
    context.addServlet(resources, "/subdir/*");

Jetty 12 相当于吗?

Jetty 12 更改了大部分

DefaultServlet
API 和内部结构,使得上述内容不再可能。有什么替代方案吗?

java jetty embedded-jetty jetty-12 jetty-11
1个回答
0
投票

根据您所说的,您根本不需要任何复杂的

DefaultServlet
逻辑。

您的代码在 Jetty 9 / 10 / 11 中基本上是无操作并回调自身。 (事实上,在某些情况下,你甚至创建了无限循环)

你需要两件事。

  • 一个或多个正确定义的基础资源(对于多个基础资源,请使用复合/组合资源)。在
    ServletContextHandler
    中指定或作为 DefaultServlet 上的 init-param
  • 名为
    DefaultServlet
    的 servlet 上的 servlet 规范正常
    default

您可以选择在不同的基础资源上提供额外的

DefaultServlet
(通过 init-params)

jetty-examples
项目中找到了这样的示例。

码头 路径
12号码头
embedded/ee10-file-server
11号码头
embedded/file-server
10号码头
embedded/file-server
9号码头
embedded/file-server

查看

ServletFileServerMultipleLocations
示例。

如果您选择使用多基础资源方法,您可以简单地使用 Jetty 12 中的资源组合功能。

ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
ResourceFactory resourceFactory = ResourceFactory.of(context);

Resource defaultBase = resourceFactory.newClassLoaderResource("/webroot/");
Resource subdirBase = resourceFactory.newClassLoaderResource("/webroot/subdir/");
Resource multiBase = ResourceFactory.combine(defaultBase, subdirBase);

context.setBaseResource(multiBase);

ServletHolder holderDef = new ServletHolder("default", DefaultServlet.class);
holderDef.setInitParameter("dirAllowed", "true");
context.addServlet(holderDef, "/");
© www.soinside.com 2019 - 2024. All rights reserved.