MessageBody Writer / Reader
我试图让Jersey支持GSON ,为此我已经读过我需要实现自定义MessageBodyWriter和MessageBodyReader 。
现在我的问题是我找不到这两个接口的任何明确定义。
从文档:
public interface MessageBodyWriter
支持将Java类型转换为流的提供程序的合同。 要添加MessageBodyWriter实现,请使用@Provider注释实现类。 MessageBodyWriter实现可以使用Produces注释,以限制它被认为适合的媒体类型。
和
public interface MessageBodyReader
支持将流转换为Java类型的提供程序的合同。 MessageBodyReader实现可以使用Consumes注释,以限制它被认为适合的媒体类型。 实现MessageBodyReader契约的提供者必须以编程方式在JAX-RS运行时中注册,或者必须使用@Provider注释进行注释,以便在提供者扫描阶段由JAX-RS运行时自动发现。
任何人都能解释一下具体意味着什么吗?
为什么我需要在GSON支持的情况下实现它们?
谢谢。
提供商的合同……
只是表示接口的公开方法集。 如果我们实现接口,我们必须实现一组契约方法,框架将使用它们来实现我们的实现
MessageBodyWriter
– 支持将Java类型转换为流的提供者的合同 – 从我们的JAX-RS资源方法,我们返回带有实体主体(它是Java对象)的Response
或Java对象。 消息体编写器负责将此Java对象转换为响应的输出流。 例如(只是为了游戏想象我们还没有支持JAXB编组)
@Override public void writeTo(Customer c, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) { JAXBContext context = JAXBContext.newInstance(type); Marshaller marsaller = context.createMarshaller(); marshaller.marshal(c, entityStream); }
你可以看到我创建了Marshaller
,它将Customer
对象封送到提供的(通过框架) OutputStream
MessageBodyReader
– 支持将流转换为Java类型的提供者的合同 – 与编写者相同的交易,但这次过程是相反的。 在将Java类型传递给JAX-RS资源方法之前,需要对其进行转换。 例如
@Override public Customer readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap 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
实现可以使用Produces
注释,以限制它被认为适合的媒体类型
JAX-RS具有Providers的概念。 你可以把它想象成Component的另一个词。 当我们用@Provider
注释我们的JAX-RS实现的类时,它变得可以成为组件,由框架管理。
使用MessageBodyWriters/MessageBodyReaders
,有一个特定的算法可用于确定每个请求/响应将使用哪个编写器/读取器。 基本上发生的是JAX-RS基于@Produces
注释匹配来计算列表或编写器。 例如,如果我们的资源方法或资源类使用@Produces(MediaType.APPLICATION_XML)
注释,并且我们的提供者(编写者)也使用此注释,那么我们的编写器将被放入此列表中。 然后这些提供者按一些算法排序。 最后,在每个writer上调用isWritable
方法,直到其中一个返回true
。 那是将要使用的作家。 例如
@Provider @Produces(MediaType.APPLICATION_XML) public class MyJAXBMessageBodyWriter implements MessaheBodyWriter { @Override public boolean isWriteable(Class 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(); }
这两个将匹配,我们的编写器将用于转换我们的Customer
对象
MessageBodReader …
MessageBodyReader
实现可以使用Consumes
注释,以限制它被认为适合的媒体类型。 实现MessageBodyReader
契约的Providers
必须以编程方式在JAX-RS运行时中注册,或者必须使用@Provider
注释进行注释,@Provider
在提供者扫描阶段由JAX-RS运行时自动发现。
@Consumes
注释,与@Produces
的作者相同的交易,刚刚逆转。 相同的匹配算法。 还有@Provider
注释,同样的交易。 例如
@Provider @Consumes(MediaType.APPLICATION_XML) public class MyJAXBMessageBodyReader implements MessageBodyReader { @Override public boolean isReadable(Class 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
,框架将确定我们的大小。
……而且更完整……
如果要以编程方式注册MessageBodyReader
或MessageBodyWriter
,请使用Client
或ClientBuilder
(或任何可Configurable
实例)上的register
方法。