【问题标题】:Jersey not obeying response media type rules from @Produces泽西岛不遵守@Produces 的响应媒体类型规则
【发布时间】:2014-06-30 20:20:30
【问题描述】:

当一种方法可以产生几种方法中的一种时,我可能会误解 Jersey 对响应媒体类型的规范。根据https://jersey.java.net/documentation/latest/jaxrs-resources.html#d0e1785,我认为当@Produces(..) 注释中列出的两种媒体类型与传入的Accept 标头匹配时,Jersey 将尊重与注释中这些类型相关的任何权重,或者如果权重不匹配,则会选择第一个决出胜负。

下面的代码演示了这不是实践中的行为。在最后两种情况下,当请求不明确时,我希望得到 JSON 响应,但我得到的是 XML。我对文档的理解不正确吗?或者这可能是泽西岛的缺陷?

我尝试过的事情:

  1. 从模型中删除@XmlRootElement 注释。决赛 然后两种情况通过,但第二种情况不同,因为 没有合适的作家。
  2. 从资源返回Object 方法。结果是案例的通过/失败状态没有变化。
  3. @Produces(..) 注释中删除权重 资源类(仍然首先列出 JSON 媒体类型)。结果 案例的通过/失败状态没有变化。

此示例是在 Ubuntu 14.04 上使用 Jersey 2.10 和 Java 1.8_05 构建的。

package demo;

import java.net.URI;
import java.util.Arrays;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.annotation.XmlRootElement;

import org.glassfish.jersey.jdkhttp.JdkHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;

import com.sun.net.httpserver.HttpServer;

public class DemonstrateAmbiguousMediaType {

    private static final String BASE_URI = "http://localhost:8092/";

    public static void main(final String[] args) {

        final HttpServer server = startServer();

        try {

            /*
             * These cases work fine.
             */
            check("application/json", "application/json");
            check("application/xml", "application/xml");

            /*
             * These cases should pass according to Jersey
             * documentation for @Produces
             * https://jersey.java.net/documentation/latest/jaxrs-resources.html#d0e1785
             * but they do not.
             */
            check("application/json", "application/*");
            check("application/json", "*/*");

        } finally {
            server.stop(0);
        }

    }

    private static void check(final String expected, final String... acceptTypes) {

        final MediaType atype = fetchAs(acceptTypes).getMediaType();
        final String actual = atype.getType() + "/" + atype.getSubtype();

        System.out.println(Arrays.asList(acceptTypes) + ":"
            + (expected.equals(actual) ? "pass" : "fail"));

    }

    private static Response fetchAs(final String[] acceptable) {

        return ClientBuilder.newClient()
                            .target(BASE_URI)
                            .path("model")
                            .request()
                            .accept(acceptable)
                            .get();

    }

    private static HttpServer startServer() {
        final ResourceConfig config = new ResourceConfig(Resource.class);
        final HttpServer rval = JdkHttpServerFactory.createHttpServer(
                URI.create(BASE_URI), config, false);
        rval.setExecutor(Executors.newCachedThreadPool(new ThreadFactory() {

            @Override
            public Thread newThread(Runnable r) {
                final Thread rval = new Thread(r);
                rval.setDaemon(true);
                return rval;
            }
        }));
        rval.start();
        return rval;
    }

    @XmlRootElement
    public static class Model {

        public int a = 10;
        public String b = "Bbb";

    }

    @Path("/model")
    @Produces({ "application/json; q=0.9", "application/xml; q=0.5" })
    public static class Resource {

        @GET
        public Model getModel() {
            return new Model();
        }

    }

}

【问题讨论】:

标签: java jax-rs jersey-2.0


【解决方案1】:

我误读了规范。在@Produces(..) 注解中,质量参数名称是qs 而不是q。当质量参数指定正确时,上述所有情况均通过。

但是,当质量参数被移除时,最终案例不会通过。根据同一份 Jersey 文档,应该选择列出的第一个,但不是。

【讨论】:

    猜你喜欢
    • 2015-07-12
    • 1970-01-01
    • 2014-06-29
    • 2015-01-21
    • 1970-01-01
    • 2014-06-10
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多