MessageBody Writer / Reader [英] MessageBody Writer / Reader

查看:142
本文介绍了MessageBody Writer / Reader的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让泽西支持 GSON ,为此我已阅读我需要实现自定义 MessageBodyWriter MessageBodyReader 的信息。



现在我的问题是我找不到这两个界面的明确定义。



doc:

  public interface MessageBodyWriter< T> 




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


  public interface MessageBodyReader< T> 




支持将流转换为$的提供者的合约b $ b Java类型。一个MessageBodyReader实现可以用
注释消费来限制它被认为是
的媒体类型。实现MessageBodyReader协定的提供者必须是
,或者以编程方式在JAX-RS运行时注册,或者必须是
以@Provider注释进行注释,以便在提供者扫描阶段由
自动发现JAX-RS运行时。

任何人都可以向我解释concretly的含义是什么?



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



谢谢。

解决方案

提供者的合同...



Just意味着接口的公开方法集合。如果我们实现了接口,我们必须实现一套契约方法,框架将使用该方法来使用我们的实现。

MessageBodyWriter - 支持将Java类型转换为流的提供者的合同 - 从我们的JAX-RS资源方法中,返回 Response 与一个实体主体(这是一个Java对象)或一个Java对象。消息正文编写者负责将此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>

你可以看到我创建了 Marshaller ,它将 Customer 对象封装到提供的(由框架) OutputStream



MessageBodyReader - 支持将流转换为Java类型的提供者的合约 - 相同作为作家来处理,但是这一次这个过程被逆转了。在将Java类型传递给我们的JAX-RS资源方法之前,需要对其进行转换。例如

  @Override 
public Customer readFrom(Class< T> type,type genericType,
Annotation []注释,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 ...

$


要添加 MessageBodyWriter 实现,请使用 @Provider 。一个 MessageBodyWriter 实现可能被注释为产生来限制它认为合适的媒体类型。


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



使用 MessageBodyWriters / MessageBodyReaders ,有一个特定的算法用于确定每个请求/响应将使用哪个写入器/读取器。基本上,JAX-RS基于 @Produces 注释匹配来计算一个或多个编写者。例如,如果我们的资源方法或资源类使用 @Produces(MediaType.APPLICATION_XML)进行注释,并且我们的提供者(作者)也用此注释,那么我们的作者将被放入这个清单。然后这些提供者按照某种算法进行排序。最后,每个作者调用 isWritable 方法,直到其中一个作者返回 true 。这是将要使用的作者。例如

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

返回类型== Customer 。类;
}
}

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

这两个匹配,我们的作者将被用来转换我们的 Customer object


$ b

MessageBodReader ...




MessageBodyReader 实现可以用 Consumes 注释来限制媒体将被视为合适的类型。 提供者执行 MessageBodyReader 合约必须以编程方式在JAX-RS运行时注册,或者必须用<$ c $注释c> @Provider
注释在提供程序扫描阶段由JAX-RS运行时自动发现。


@Consumes 注释,与作者 @Produces 相同的交易,恰好相反。相同的匹配算法。同样是 @Provider 注释。例如

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

返回类型== Customer .class


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

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



至于最后一句话scanning phase,这只是扫描我们的软件包以查找要管理的组件的JAX_RS实现。这种情况发生在启动时,根据我们的配置(例如,应该扫描哪些包)。

为了完整性,



MessageBodyWriter 有另一个方法 getSize 。如果我们不知道大小,我们可以返回 -1 ,并且框架将决定我们的大小。



...以及更完整的...



如果您想以编程方式注册 MessageBodyReader MessageBodyWriter ,在 Client 上使用 register $ c>或 ClientBuilder (或任何可配置实例)。


I'm trying to make Jersey supports GSON and for this I have read that I need to implement a Custom MessageBodyWriter and MessageBodyReader.

Now my problem is that I couldn't find any clear definition of these 2 interfaces.

From the doc :

public interface MessageBodyWriter<T>

Contract for a provider that supports the conversion of a Java type to a stream. To add a MessageBodyWriter implementation, annotate the implementation class with @Provider. A MessageBodyWriter implementation may be annotated with Produces to restrict the media types for which it will be considered suitable.

and

public interface MessageBodyReader<T>

Contract for a provider that supports the conversion of a stream to a Java type. A MessageBodyReader implementation may be annotated with Consumes to restrict the media types for which it will be considered suitable. Providers implementing MessageBodyReader contract must be either programmatically registered in a JAX-RS runtime or must be annotated with @Provider annotation to be automatically discovered by the JAX-RS runtime during a provider scanning phase.

Can anyone explain me what does concretly means ?

And why do I need to implement them in the case of GSON support for example ?

Thank you.

解决方案

Contract for a provider...

Just means the set of exposed method by the interfaces. If we implement the interface, we must implement the set of contract methods, for which the framework will use to make use of our implementations

MessageBodyWriter - Contract for a provider that supports the conversion of a Java type to a stream - From our JAX-RS resource methods, we return either a Response with an entity body (which is a Java Object) or a Java object. The message body writer is responsible for converting this Java object to the response's output stream. For example (just for play imagine we don't already have support for JAXB marshalling)

@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);
}

You can see that I create the Marshaller, which marshals the Customer object to the provided (by the framework) OutputStream

MessageBodyReader - Contract for a provider that supports the conversion of a stream to a Java type - Same deal as the writer, but this time the process is reversed. Before a Java type is passed to our JAX-RS resource methods, it needs to be converted. For example

@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...

To add a MessageBodyWriter implementation, annotate the implementation class with @Provider. A MessageBodyWriter implementation may be annotated with Produces to restrict the media types for which it will be considered suitable

JAX-RS has the concept of Providers. You can just think of it another word for Component. When we annotate our JAX-RS implemented classes with @Provider, it becomes eligable to be component, managed by the framework.

With MessageBodyWriters/MessageBodyReaders, there is a specific algorithm that goes into determining which writer/reader will be used for each request/response. Basically what happens is that JAX-RS calculates a list or writers, based on the @Produces annotations matches. For example if our resource method or resource class is annotated with @Produces(MediaType.APPLICATION_XML) and our provider (writer) is also annotated with this, our writer will be put into this list. Then these providers are sorted by some algorithm. Finally the isWritable method is called on each writer until true is returned by one of them. That is the writer that will be used. For example

@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();
}

These two will be matched, and our writer will be used to convert our Customer object

MessageBodReader...

A MessageBodyReader implementation may be annotated with Consumes to restrict the media types for which it will be considered suitable. Providers implementing MessageBodyReader contract must be either programmatically registered in a JAX-RS runtime or must be annotated with @Provider annotation to be automatically discovered by the JAX-RS runtime during a provider scanning phase.

The @Consumes annotation, same deal as the writer the @Produces, just reversed. Same matching algorithm. Also the @Provider annotation, same deal. For example

@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();
}

The reader will be matched to our method and convert the input stream into a Customer object and pass it to our method.

As far as the last words "scanning phase", this is just the JAX_RS implementation scanning our packages looking for components to manage. This happens at startup, based on our configurations (e.g. what packages should be scanned)

And just for completeness...

MessageBodyWriter has a another method getSize. We can just return -1 if we don't know the size, and the framework will determine the size for us.

…and for some more completeness…

In case you want to programmatically register a MessageBodyReader or MessageBodyWriter, use the register methods on your Client or ClientBuilder (or any Configurable instance).

这篇关于MessageBody Writer / Reader的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆