泽西岛不遵守@Produces的响应媒体类型规则

时间:2014-06-30 20:20:30

标签: java jax-rs jersey-2.0

当一个方法可以生成几个中的一个时,我可能会误解Jersey规范中的响应的媒体类型。根据{{​​3}},我认为当@Produces(..)注释中列出的两种媒体类型与传入的Accept标题匹配时,Jersey会遵守与注释中的这些类型相关联的任何权重,或者会选择首先,如果权重没有决定胜利者。

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

我尝试过的事情:

  1. 从模型中删除@XmlRootElement注释。决赛 两个案件然后通过,但第二个案件分歧,因为 没有合适的作家。
  2. 从资源中返回Object 方法。结果是案件的通过/未通过状态没有变化。
  3. @Produces(..)注释中删除权重 资源类(JSON媒体类型仍然列在第一位)。结果 案件的通过/未通过状态没有变化。
  4. 此示例是使用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();
            }
    
        }
    
    }
    

1 个答案:

答案 0 :(得分:2)

我误读了规范。在@Produces(..)注释中,质量参数名称为qs而非q。正确指定质量参数后,所有情况都会通过。

然而,当移除质量参数时,最终情况不会通过。根据同样的泽西岛文件,应该选择第一个列出但不是。

相关问题