如何使用Grizzly在同一个基本URL上提供静态内容和资源

时间:2016-05-12 20:06:53

标签: java rest jersey jax-rs grizzly

我正在使用Grizzly来提供我的REST服务,该服务可能有多个"模块"。我希望能够为服务和静态内容使用相同的基本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的代码时,我能够访问我的资源(但当然没有文档)。 访问我的资源和静态内容需要做什么?

2 个答案:

答案 0 :(得分:3)

我最终写了一个服务来自己处理静态资源。我决定从文件系统提供我的文件,但这种方法也适用于从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;
        }
    }
}

答案 1 :(得分:2)

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Formater
{
    public class Startup
    {
        public async Task <object> Invoke (object input)
        {
            return ".NET";
        }
    }
}

您需要添加Jersey Grizzly 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();
    }
}

这种方法的唯一问题是默认servlet用于提供文件系统中的文件,而不是像目前尝试的那样从类路径提供文件。您可以在<dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-grizzly2-servlet</artifactId> <version>${jersey2.version}</version> </dependency> 方法中看到我只是将基目录设置为当前工作目录。这就是你需要的所有文件。您可以将其更改为createDefaultServlet,以便所有文件都位于"docs"文件夹中,该文件夹位于当前工作目录中。

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

或者你可以说忘了它,只是从文件系统提供服务: - )