MessageBody Writer / Reader

后端 未结 1 1234
清酒与你
清酒与你 2021-01-16 06:14

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

相关标签:
1条回答
  • 2021-01-16 06:31

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

    0 讨论(0)
提交回复
热议问题