【问题标题】:Jersey: How to Add Jackson to Servlet HolderJersey:如何将 Jackson 添加到 Servlet Holder
【发布时间】:2015-02-26 03:10:42
【问题描述】:

我正在使用 Jersey 创建一个嵌入式 Jetty webapp。我不知道如何在这里为自动 JSON serde 添加 Jackson:

    ServletHolder jerseyServlet = context.addServlet(
       org.glassfish.jersey.servlet.ServletContainer.class, "/*");
    jerseyServlet.setInitOrder(0);

    jerseyServlet.setInitParameter(
        ServerProperties.PROVIDER_CLASSNAMES,
        StringUtils.join(
            Arrays.asList(
                HealthCheck.class.getCanonicalName(),
                Rest.class.getCanonicalName()),
            ";"));

    // Create JAX-RS application.
    final Application application = new ResourceConfig()
        .packages("com.example.application")
        .register(JacksonFeature.class);

    // what do I do now to tie this to the ServletHolder?

如何向 ServletHolder 注册此 ResourceConfig,以便在使用注解 @Produces(MediaType.APPLICATION_JSON) 的地方使用 Jackson?这是嵌入式 Jetty 应用程序的完整主类

package com.example.application.web;

import com.example.application.api.HealthCheck;
import com.example.application.api.Rest;
import com.example.application.api.Frontend;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;

import javax.ws.rs.core.Application;
import java.util.Arrays;

public class JettyStarter {

public static void main(String[] args) throws Exception {

    ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setContextPath("/");
    Server jettyServer = new Server(9090);
    jettyServer.setHandler(context);
    ServletHolder jerseyServlet = context.addServlet(
     org.glassfish.jersey.servlet.ServletContainer.class, "/*");
    jerseyServlet.setInitOrder(0);

    jerseyServlet.setInitParameter(
        ServerProperties.PROVIDER_CLASSNAMES,
        StringUtils.join(
            Arrays.asList(
                HealthCheck.class.getCanonicalName(),
                Rest.class.getCanonicalName()),
            ";"));

    // Create JAX-RS application.
    final Application application = new ResourceConfig()
        .packages("com.example.application")
        .register(JacksonFeature.class);


    try {
        jettyServer.start();
        jettyServer.join();
    } catch (Exception e) {
        System.out.println("Could not start server");
        e.printStackTrace();
    } finally {
        jettyServer.destroy();
    }
}
}

【问题讨论】:

    标签: java jersey jackson jetty embedded-jetty


    【解决方案1】:

    一种方法是将ResourceConfig 包装在ServletContainer 的显式construction 中,如here 所示。

    用你的例子测试

    public class RestServer {
    
        public static void main(String[] args) throws Exception {
    
            // Create JAX-RS application.
            final ResourceConfig application = new ResourceConfig()
                    .packages("jersey.jetty.embedded")
                    .register(JacksonFeature.class);
    
            ServletContextHandler context 
                     = new ServletContextHandler(ServletContextHandler.SESSIONS);
            context.setContextPath("/");
            Server jettyServer = new Server(9090);
            jettyServer.setHandler(context);
            ServletHolder jerseyServlet = new ServletHolder(new
                    org.glassfish.jersey.servlet.ServletContainer(application));
            jerseyServlet.setInitOrder(0);
    
            context.addServlet(jerseyServlet, "/*");
    
            // ... removed property (init-param) to compile. 
    
            try {
                jettyServer.start();
                jettyServer.join();
            } catch (Exception e) {
                System.out.println("Could not start server");
                e.printStackTrace();
            } finally {
                jettyServer.destroy();
            }
        }
    }
    

    你也可以...

    无需更改原始帖子中的任何其他内容,只需设置 init 参数以扫描 Jackson 提供程序包

    jerseyServlet.setInitParameter(ServerProperties.PROVIDER_PACKAGES,
            "com.fasterxml.jackson.jaxrs.json;"
          + "jersey.jetty.embedded"  // my package(s)
    );
    

    请注意,您尝试使用 ResourceConfig 似乎有点多余,因为您已经在 init 参数中配置了类。您也可以不显式添加每个类,像我一样扫描整个包。

    你也可以...

    只需使用您需要的 Jackson 提供程序类。您可以查看 jar,您将看到的不仅仅是编组/解组提供程序 (Jackson[JAXB]JsonProvider),例如 ExceptionMappers。您可能不喜欢这些映射器,并自行配置。在这种情况下,就像我说的那样,只需包括您需要的提供者。例如

    jerseyServlet.setInitParameter(ServerProperties.PROVIDER_CLASSNAMES,
          "com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider");
    
    jerseyServlet.setInitParameter(ServerProperties.PROVIDER_PACKAGES, 
          "jersey.jetty.embedded"  // my package(s)
    );
    

    经过进一步测试...

    不确定 Jersey 的版本,但我使用的是 Jersey 2.15(带有jersey-media-json-jackson:2.15),并且没有任何进一步的配置,只需扫描我的资源类的 my 包,Jackson 功能已经启用。这是自动发现功能的一部分。我相信这是在 2.8 或 2.9 中为 Jackson 功能启用的。因此,如果您使用的是以后的版本,我认为您不需要显式配置任何内容,至少从我测试的内容来看:-)


    更新

    以上所有示例均已使用以下 Maven pom.xml 进行了测试

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                    http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.underdog.jersey</groupId>
        <artifactId>jersey-jetty-embedded</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.7</maven.compiler.source>
            <maven.compiler.target>1.7</maven.compiler.target>
            <jersey.version>2.15</jersey.version>
            <jetty.version>9.2.6.v20141205</jetty.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jersey.containers</groupId>
                <artifactId>jersey-container-servlet</artifactId>
            </dependency>
            <dependency>
                <groupId>org.glassfish.jersey.media</groupId>
                <artifactId>jersey-media-json-jackson</artifactId>
            </dependency>
            <dependency>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-server</artifactId>
                <version>${jetty.version}</version>
            </dependency>
            <dependency>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-servlet</artifactId>
                <version>${jetty.version}</version>
            </dependency>
            <dependency>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-servlets</artifactId>
                <version>${jetty.version}</version>
            </dependency>
        </dependencies>
    
            <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.glassfish.jersey</groupId>
                    <artifactId>jersey-bom</artifactId>
                    <version>${jersey.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    </project>
    

    和资源类

    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
    import javax.ws.rs.core.Response;
    
    @Path("/json")
    public class JsonResource {
    
        @GET
        @Produces(MediaType.APPLICATION_JSON)
        public Response getJson() {
            Resource resource = new Resource();
            resource.hello = "world";
            return Response.ok(resource).build();
        }
    
        public static class Resource {
            public String hello;
        }
    }
    

    使用路径

    http://localhost:9090/json

    【讨论】:

    • 嗨,哇,感谢您提供如此广泛而详细的答案以及许多替代方案。我从第一种方法开始,使用 Jersey 2.10(我的服务器不会从 >= 2.11 的版本开始)我正在尝试第一种方法,但是在更改之后,我在所有 jaxrs 路由上都得到 404。这是我的 Java 的样子:pastebin.com/4t4rZz9X 我把你在上面评论的 sn-p 留下了 // ... removed property (init-param) to compile. 我在那个 pastebin 中做错了什么吗?
    • 我刚刚使用了htttp://localhost:9090/hello,其中"hello" 是资源类上的@Path。此外,ResourceConfig 上的 packages 会扫描整个包和子包以查找带注释的类。就我个人而言,我从来没有真正使用过单独添加类,所以我不知道它是否与包扫描有任何冲突。尝试做其中之一。我不知道为什么 2.11+ 不起作用。我需要查看堆栈跟踪。 “没有开始”并没有说太多。同时发布您的 pom.xml 也会有所帮助。
    • 我会把我的 pom 依赖贴出来给你看看
    • 谢谢。这是我的pom。抱歉描述模糊,没有堆栈或任何东西,泽西岛从未初始化。 pastebin.com/FpA2Vn2x
    • 1) 用我的依赖项试试。 2)尝试注释掉初始化参数。如果您已经使用ResourceConfg.packages 扫描包,这是多余的
    猜你喜欢
    • 1970-01-01
    • 2018-11-09
    • 2013-05-21
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    • 2020-10-01
    • 2017-08-06
    • 1970-01-01
    相关资源
    最近更新 更多