当前位置: 首页 > 知识库问答 >
问题:

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

邹高懿
2023-03-14

我可能误解了泽西岛规范,即响应的媒体类型,当一种方法可以产生几种方法之一时。根据 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();
        }

    }

}

共有1个答案

姜鸿
2023-03-14

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

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

 类似资料:
  • 我正在尝试遵循Jersey文档,以便在发生错误时启用非200响应(https://Jersey.java.net/documentation/latest/representations.html#D0E3586) 我的代码看起来像: 不幸的是,这会产生以下错误: [2015-02-01T16:13:02.157+0000][glassfish 4.1][严重][][org.glassfish.j

  • 我现在正在尝试泽西,按照这个链接在netbean中设置了一个网络服务。我有我的实体类和REST类。它可以从javafx2客户端添加、编辑、删除、请求对象(在本例中是用户对象)。 然而,现在我尝试向我的网络服务添加一个新方法来进行一些简单的身份验证。首先,我在Users.java文件中添加了一个新的命名查询(Users.login): 之后,我将以下代码添加到我的UsersFacadeREST.ja

  • 我正在尝试使用Jersey作为框架实现一个小的REST API,原则上代码工作正常,但是当我尝试对哈希表进行“GET”时,我得到以下错误: 这是有问题的一行: 这就是我实现服务的方式: pom公司。xml(maven依赖项) 服务器端配置: 在客户端中注册杰克逊时出错: 新类别: 术语类: 有人能帮我退回地图吗?

  • 我使用的是一个restful web服务,CRUD操作可以在其中工作,除了在一个页面上列出每个用户。getUser()方法仅用于登录webapp。我已经看了这个问题,但我没有使用命名查询。 我得到的错误:: 严重:产生媒体类型冲突。资源方法public…UserResource.getUser()和…UserResource.list()抛出org.codehaus.jackson.JsonGen

  • 问题内容: 在管道级别,我指定代理和节点(带有标签和自定义工作区)。管道启动时,它将在指定的节点上运行,但是当命中“ build job”时,将选择第一个可用节点。我尝试使用NodeLabel插件,但是那也不起作用。 这是我的: 问题答案: 当您使用Jenkinsfile中的指令时,它告诉Jenkins您想要构建一个完全独立的作业。正是 其他工作 需要指定将要构建的代理。如果这是基于Jenkins

  • 我想返回一个临时重定向,使用AsyncACK。 下面的“工作”(因为没有错误),但似乎不是异步的(它一次处理一个请求)。 这应该工作吗?如果我明确需要像https://jersey.github.io/documentation/latest/async.html#d0e9895一样启动一个新线程,返回响应是什么样子的?