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

消息正文编写器/阅读器

慕容修伟
2023-03-14

我正试图让Jersey支持GSON,为此我了解到我需要实现一个自定义的MessageBodyWriter和MessageBodyReader。

现在我的问题是我找不到这两个接口的任何明确定义。

从文档中:

public interface MessageBodyWriter<T>

支持将Java类型转换为流的提供程序的契约。要添加MessageBodyWriter实现,请使用@Provider注释实现类。MessageBodyWriter实现可以使用Produces注释以限制它将被认为适合的媒体类型。

public interface MessageBodyReader<T>

支持将流转换为 Java 类型的提供程序的协定。MessageBodyReader 实现可以使用“消耗”进行批注,以限制它被认为适合的媒体类型。实现 MessageBodyReader 协定的提供程序必须在 JAX-RS 运行时中以编程方式注册,或者必须使用@Provider注释进行批注,以便 JAX-RS 运行时在提供程序扫描阶段自动发现。

谁能告诉我具体是什么意思?

为什么我需要在GSON支持的情况下实现它们?

谢谢。

共有1个答案

令狐经武
2023-03-14

就是指接口公开的方法集。如果我们实现接口,我们必须实现合同方法集,框架将使用这些方法来使用我们的实现

< code>MessageBodyWriter -支持将Java类型转换为流的提供者的合同-从我们的JAX-RS资源方法中,我们返回带有实体主体(Java对象)或Java对象的< code >响应。消息体编写器负责将这个Java对象转换成响应的输出流。例如(假设我们还不支持JAXB编组)

@Override
public void writeTo(Customer c, Class<Customer> type, 
                    Type genericType, Annotation[] annotations, 
                    MediaType mediaType, 
                    MultivaluedMap<String,Object> httpHeaders, 
                    OutputStream entityStream) {

    JAXBContext context = JAXBContext.newInstance(type);
    Marshaller marsaller = context.createMarshaller();
    marshaller.marshal(c, entityStream);
}

您可以看到我创建了< code > marshaler ,它将< code>Customer对象封送到(由框架提供的)< code>OutputStream

MessageBodyReader-支持将流转换为Java类型的提供者的合约-与编写器的交易相同,但这次过程相反。在将Java类型传递给我们的JAX-RS资源方法之前,需要对其进行转换。例如

@Override
public Customer readFrom(Class<T> type, Type genericType, 
                         Annotation[] annotations, MediaType mediaType,
                         MultivaluedMap<String,String> httpHeaders,
                         InputStream entityStream) throws IOException,
                         WebApplicationException {

    JAXBContext context = JAXBContext.newInstance(Customer.class);
    Unmarshaller unmarshaller = context.createUnmarshaller();

    return (Customer)unarshaller.unmarshal(entityStream);
}

要添加MessageBodyWriter实现,请使用@Provider,对实现类进行注释。MessageBodyWriter实现可以用products进行注释,以限制它被认为适合的媒体类型

JAX-RS有提供者的概念。你可以把它想象成组件的另一个词。当我们用@Provider注释我们的JAX-RS实现的类时,它就可以成为组件,由框架管理。

使用MessageBodyWriters/MessageBodyReaders,有一个特定的html" target="_blank">算法来确定每个请求/响应将使用哪个编写器/读取器。基本上,发生的情况是 JAX-RS 根据注释匹配@Produces计算列表或编写器。例如,如果我们的资源方法或资源类用@Produces(MediaType.APPLICATION_XML)注释,并且我们的提供者(编写器)也用此注释,则我们的编写器将被放入此列表中。然后,这些提供程序按某种算法进行排序。最后,在每个编写器上调用 isWriteable 方法,直到其中一个编写器返回 true。这就是将要使用的作家。例如

@Provider
@Produces(MediaType.APPLICATION_XML)
public class MyJAXBMessageBodyWriter 
                  implements MessaheBodyWriter<Customer> {
    @Override
    public boolean isWriteable(Class<Customer> type, Type genericType, 
                Annotation[] annotations, MediaType mediaType) {

        return type == Customer.class;
    }
}

@GET
@Produces(MediaType.APPLICATION_XML)
public Response getCustomer() {
    Customer customer = customerService.getCustomer();
    return Response.ok(customer).build();
}

这两个将被匹配,我们的编写器将用于转换我们的< code>Customer对象

< code>MessageBodyReader实现可以用< code>Consumes进行注释,以限制它适合的媒体类型。实现< code>MessageBodyReader协定的< code >提供程序必须以编程方式在JAX-RS运行时中注册,或者必须使用< code>@Provider批注进行批注,以便在提供程序扫描阶段由JAX-RS运行时自动发现。

@消费注释,与@Produces的编写者相同,只是颠倒了。相同的匹配算法。还有@Provider注释,相同的交易。例如

@Provider
@Consumes(MediaType.APPLICATION_XML)
public class MyJAXBMessageBodyReader 
                   implements MessageBodyReader<Customer> {
    @Override
    public boolean isReadable(Class<Customer> type, Type genericType, 
                              Annotation[] annotations, MediaType mediaType) {

        return type == Customer.class
    }
}

@POST
@Consumed(MediaType.APPLICATION_XML)
public Response createCustomer(Customer customer) {
    customerService.save(customer);
    return Response.created(newCustomerUri).build();
}

读取器将与我们的方法匹配,并将输入流转换为 Customer 对象,并将其传递给我们的方法。

至于最后一个词“扫描阶段”,这只是扫描我们的包寻找要管理的组件的JAX_RS实现。这发生在启动时,基于我们的配置(例如,应该扫描哪些包)

MessageBodyWriter还有另一种方法getSize。如果我们不知道大小,我们可以返回 -1,框架将为我们确定大小。

如果要以编程方式注册 MessageBodyReaderMessageBodyWriter,请在 Client 或 ClientBuilder(或任何可配置实例)上使用 register 方法。

 类似资料:
  • 我在泽西有以下资源: 我现在想编写一个MessageBodyReader/Writer,它使用不同的方法序列化/反序列化MyResponse对象,具体取决于用于创建响应的MyResource的属性(计划为不同的API版本创建两个MyResources实例,并以不同的方式序列化它们)。 现在的问题是如何访问处理泽西岛请求的MyResource实例?任何帮助都将不胜感激。 问候, 约亨

  • 问题内容: 我是REST服务的完整入门者,但是我需要从网站通过REST访问一些信息。该服务具有一些示例代码来显示我已使用的登录方式。示例代码使用Jettison作为JSON解析器,但是当我尝试运行以下代码片段时,出现异常: baseResourse是一个WebResource对象。该代码失败,但有以下异常: 该示例代码不建议我应该添加任何“邮件正文阅读器”来处理响应吗?还是我需要添加或做任何明显的

  • 问题内容: 我有一个基于Jersey的Rest WS,它输出JSON。我正在实现一个Jersey客户端,以调用WS并使用JSON响应。我的客户端代码如下 第二行正确地输出了JSON字符串响应,但是没有发生将JSON封送至POJO的第三行,并且我得到了以下异常stacktrace 我的请求中包含正确的MIME类型。我的POJO已用XMLRootElement注释。我想念什么。 谢谢 问题答案: 通过

  • 问题内容: 当我尝试返回List时,没有找到响应类ArrayList的消息正文编写器。 我有如下代码: 请帮我。提前致谢 问题答案: 要返回列表,最好将其包装到带注释的容器中,并将该列表作为字段添加到该容器中,并标记为。 像这样:

  • 我的球衣测试课有一个奇怪的问题。 当执行我的测试代码并在org.glassfish.jersey.message.internal.ReaderInterceptorExecutor的第203行放置断点时,我看到我的阅读器不在reader.workers.但是,正如您在下面看到的,我在ResourceConfig中注册了这个MessageBodyReader。 所有相关代码如下所示。 是的,返回为

  • 问题内容: 我正在使用Paho发送和接收mqtt消息。到目前为止,发送消息一直没有问题,我正在使用mosquitto接收消息。 现在,我想使用Java客户端读取消息,并且注意到关于接收消息的文档越来越少。 我实现了MqttCallback接口,但仍然无法弄清楚如何阅读已订阅的主题的消息。 到目前为止,这是我的源代码,我可以使用mosquitto_sub读取消息。 问题答案: 您将在代理有时间将消息