【问题标题】:How to post generic type in jersey?如何在球衣中发布泛型类型?
【发布时间】:2016-10-21 05:36:30
【问题描述】:

-------------通用类型------

public class Pair<KT, VT> {
    private KT key;
    private VT value;

    public Pair() {
    }

    public Pair(KT key, VT value) {
        this.key = key;
        this.value = value;
    }
}

-------------Restful API------------

@Path("/test")
public class TestApi {
    @GET
    @Path("/query")
    @Produces(MediaType.APPLICATION_JSON)
    public Pair query(@DefaultValue("0") @QueryParam("key") int key) {
        return new Pair(key, "value:" + key);
    }

    @POST
    @Path("/post")
    @Consumes(MediaType.APPLICATION_JSON)
    public String create(Pair<Integer, String> pair){
        return "put success : " + pair.toString();
    }
}

-------------问题--------------

GET 的响应:http://localhost:8080/api/test/query 是:

{"key":{"type":"int","value":0},"value":{"type":"string","value":"value:0"}}

但是,当我使用“Content-Type: application/json”标头将相同的 json 发布到 POST : http://localhost:8080/api/test/post 时,会发生异常:

谁能告诉我如何发布一个泛型类型对象?

---------------pom.xml-------

    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-client</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-common</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.7.5</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.jaxrs</groupId>
            <artifactId>jackson-jaxrs-json-provider</artifactId>
            <version>2.7.4</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
            <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
            <version>${jersey.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-webapp</artifactId>
            <version>${jetty.version}</version>
        </dependency>
    </dependencies>
    <properties>
        <jersey.version>2.23.1</jersey.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jetty.version>9.0.6.v20130930</jetty.version>
    </properties>

【问题讨论】:

  • 你发帖怎么样?您是否提供“Content-Type: application/json”标头?
  • 是的!我已经设置了“Content-Type:application/json”标题。

标签: java json rest generics jersey-2.0


【解决方案1】:

这不应该是对 GET 请求的正确响应

{"key":{"type":"int","value":0},"value":{"type":"string","value":"value:0"}}

应该是

{"key":0,"value":"value:0"}

这只是使用MOXy 的众多风险之一,它是 Jersey 的默认 JSON 提供程序(在 Glassfish 中)。如果您改用Jackson,您应该会看到正确的行为。

要使用 Jackson,您可以通过将属性 ServerProperties.MOXY_JSON_FEATURE_DISABLE 设置为 true 来禁用 MOXy(这会阻止 Jackson 注册)。或者您可以添加 Jackson 依赖,然后向应用程序注册 JacksonFeature

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>${jersey2.version}</version>
</dependency>

进行更改后,它应该对 GET 和 POST 请求都正常工作。


更新

测试源。运行测试时,您还应该在日志中看到请求的正确输出,它只返回与发布的相同的对。

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.Response;
import javax.xml.bind.annotation.XmlRootElement;

import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

/**
 * Required dependencies for test
 * 
 *  <dependency>
 *      <groupId>org.glassfish.jersey.containers</groupId>
 *      <artifactId>jersey-container-grizzly2-http</artifactId>
 *      <version>2.23</version>
 *  </dependency>
 *  <dependency>
 *      <groupId>org.glassfish.jersey.media</groupId>
 *      <artifactId>jersey-media-json-jackson</artifactId>
 *      <version>2.23</version>
 *  </dependency>
 *
 * @author Paul Samsotha
 */
public class JacksonGenericTest extends JerseyTest {

    @XmlRootElement
    public static class Pair<K, V> {

        private K key;
        private V value;

        public Pair() {
        }

        public Pair(K key, V value) {
            this.key = key;
            this.value = value;
        }

        public K getKey() {
            return key;
        }

        public void setKey(K key) {
            this.key = key;
        }

        public V getValue() {
            return value;
        }

        public void setValue(V value) {
            this.value = value;
        }

        @Override
        public String toString() {
            return "Pair{" + "key=" + key + ", value=" + value + '}';
        }
    }

    @Path("test")
    @Consumes("application/json")
    @Produces("application/json")
    public static class TestResource {

        @POST
        public Pair create(Pair<Integer, String> pair) {
            return pair;
        }
    }

    @Override
    public ResourceConfig configure() {
        return new ResourceConfig(TestResource.class)
                // not required here since we don't have MOXy on the classpath,
                // but in Glassfish, you should make sure to register it
                // so it disables MOXy, since Glassfish has MOXy on the classpath.
                .register(JacksonFeature.class)
                .register(new LoggingFilter(Logger.getAnonymousLogger(), true));
    }
    
    private final String jsonData = "{\"key\":100,\"value\":\"value:100\"}";

    @Test
    public void postTest() {
        final Response response = target("test")
                .request()
                .post(Entity.json(jsonData));
        final Pair<Integer, String> pair = response.readEntity(
                new GenericType<Pair<Integer, String>>(){});
        assertThat(pair.getKey(), is(100));
        assertThat(pair.getValue(), is("value:100"));
    }
}

【讨论】:

  • 我尝试了 jersey-media-json-jackson 依赖,它只是不起作用,并返回 {},而不是 {"key":0,"value":"value:0" }. 看来我不应该返回除 List 类型之外的自定义泛型类型。
  • 我在发布这篇文章之前进行了实际测试,它对我来说效果很好。 GET 和 POST 都按预期工作
  • 嘿,peeskillet,我刚刚附加了我的 pom.xml,并使用 glassfish 作为 Web 服务器。希望得到您的帮助。
  • 如果你发布你的测试源会更好:-)
  • 是的!它奏效了,虽然我什至不知道为什么。我想我什么都没做,我把你的测试代码放到我的项目中测试,然后我的代码也可以工作了!谢谢!
猜你喜欢
  • 2014-05-04
  • 1970-01-01
  • 2014-02-01
  • 1970-01-01
  • 2021-04-09
  • 2013-04-17
  • 2020-02-05
  • 2021-09-21
  • 1970-01-01
相关资源
最近更新 更多