【问题标题】:How to serve static content and resource at same base url with Grizzly如何使用 Grizzly 在相同的基本 url 提供静态内容和资源
【发布时间】:2016-05-12 20:06:52
【问题描述】:

我正在使用 Grizzly 为我的 REST 服务提供服务,该服务可以有多个“模块”。我希望能够为服务和静态内容使用相同的基本 URL,这样我就可以访问所有这些 url:

我尝试设置的代码如下所示:

private HttpServer createServer(String host, int port, ResourceConfig config)
{               
    HttpServer server = GrizzlyHttpServerFactory.createHttpServer(URI.create("http://" + host + ":" + port + "/"), config, false);

    HttpHandler httpHandler = new CLStaticHttpHandler(HttpServer.class.getClassLoader(), "docs/");
    server.getServerConfiguration().addHttpHandler(httpHandler, "/");

    return server;
}

使用此代码,我只能看到 html 页面,当我尝试获取资源时,我会收到“路径标识的资源不存在”响应。 当我注释掉添加 HttpHandler 的代码时,我就可以访问我的资源(但当然没有文档)。 我需要做什么才能同时访问我的资源和静态内容?

【问题讨论】:

    标签: java rest jersey jax-rs grizzly


    【解决方案1】:

    我最终自己编写了一个服务来处理静态资源。我决定从文件系统中提供我的文件,但这种方法也适用于从 jar 中提供它们 - 您只需将文件作为资源获取,而不是直接创建文件。

    @Path("/")
    public class StaticService
    {
    
        @GET
        @Path("/{docPath:.*}.{ext}")
        public Response getHtml(@PathParam("docPath") String docPath, @PathParam("ext") String ext, @HeaderParam("accept") String accept)
        {
            File file = new File(cleanDocPath(docPath) + "." + ext);
            return Response.ok(file).build();
        }
    
        @GET
        @Path("{docPath:.*}")
        public Response getFolder(@PathParam("docPath") String docPath)
        {
            File file = null;
            if ("".equals(docPath) || "/".equals(docPath))
            {
                file = new File("index.html");
            }
            else
            {
                file = new File(cleanDocPath(docPath) + "/index.html"); 
            }
            return Response.ok(file).build();
        }
    
        private String cleanDocPath(String docPath)
        {
            if (docPath.startsWith("/"))
            {
                return docPath.substring(1);
            }
            else
            {
                return docPath;
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      您可以做的一件事是将 Grizzly 作为 servlet 容器运行。这样你就可以run Jersey as servlet filteradd a default servlet 来处理静态内容。例如

      public class Main {
          public static HttpServer createServer() {
              WebappContext context = new WebappContext("GrizzlyContext", "");
              createJerseyFilter(context);
              createDefaultServlet(context);
              HttpServer server = GrizzlyHttpServerFactory
                      .createHttpServer(URI.create("http://localhost:8080/"));
              context.deploy(server);
              return server;
          }
      
          private static void createJerseyFilter(WebappContext context) {
              ResourceConfig rc = new ResourceConfig().packages("com.grizzly.test");
              // This causes Jersey to forward 404s to default servlet
              // which will catch all the static content requests.
              rc.property(ServletProperties.FILTER_FORWARD_ON_404, true);
              FilterRegistration reg = context.addFilter("JerseyApp", new ServletContainer(rc));
              reg.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), "/*");
          }
      
          private static void createDefaultServlet(WebappContext context) {
              ArraySet<File> baseDir = new ArraySet<>(File.class);
              baseDir.add(new File("."));
              ServletRegistration defaultServletReg 
                      = context.addServlet("DefaultServlet", new DefaultServlet(baseDir) {});
              defaultServletReg.addMapping("/*");
          }
      
          public static void main(String[] args) throws IOException {
              HttpServer server = createServer();      
              System.in.read();
              server.stop();
          }
      }
      

      您需要添加 Jersey Grizzly servlet 依赖项

      <dependency>
          <groupId>org.glassfish.jersey.containers</groupId>
          <artifactId>jersey-container-grizzly2-servlet</artifactId>
          <version>${jersey2.version}</version>
      </dependency>
      

      这种方法的唯一问题是,默认 servlet 旨在从文件系统提供文件,而不是从类路径中提供文件,就像您当前尝试做的那样。您可以在createDefaultServlet 方法中看到我只是将基目录设置为当前工作目录。所以这就是你所有文件都需要的地方。您可以将其更改为"docs",这样您的所有文件都将位于docs 文件夹中,该文件夹位于当前工作目录中。

      如果您想从类路径中读取文件,您可能需要实现自己的 servlet。您可以查看source code for DefaultServlet 并尝试修改它以从类路径中提供服务。您还可以查看 Dropwizard's AssetServlet,它已经提供了类路径中的内容。

      或者你可以直接说算了,直接从文件系统中提供服务 :-)

      【讨论】:

      • 我实际上并没有尝试过这个,因为我最终想出了另一个解决方法。如果我遇到任何问题,我会尝试一下。感谢您的回答!
      猜你喜欢
      • 2013-06-02
      • 2014-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-14
      相关资源
      最近更新 更多