我正在尝试让Jersey支持 GSON ,为此我已经读过我需要实现自定义 MessageBodyWriter 和 MessageBodyReader 。
现在我的问题是我找不到这两个接口的任何明确定义。
来自doc:
public interface MessageBodyWriter<T>
支持将Java类型转换为的提供程序的合同 一条小溪。要添加MessageBodyWriter实现,请注释 使用@Provider实现类。 MessageBodyWriter 可以使用Produces注释实现来限制媒体 它被认为适合的类型。
和
public interface MessageBodyReader<T>
支持将流转换为的提供商的合同 Java类型。 MessageBodyReader实现可以使用注释 消费以限制将被考虑的媒体类型 适当。必须是实现MessageBodyReader合同的提供者 要么以编程方式在JAX-RS运行时注册,要么必须注册 使用@Provider注释进行注释,以便自动发现 提供商扫描阶段的JAX-RS运行时。
任何人都能解释一下具体意味着什么吗?
为什么我需要在GSON支持的情况下实现它们呢?
谢谢。
答案 0 :(得分:1)
只是表示接口的公开方法集。如果我们实现接口,我们必须实现一组契约方法,框架将使用它们来实现我们的实现
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);
}
您可以看到我创建了Marshaller
,它将Customer
对象封送到提供的(框架)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
对Produces
实施进行注释,以限制适合其的媒体类型
JAX-RS具有 Providers 的概念。你可以想到 Component 的另一个词。当我们使用@Provider
注释我们的JAX-RS实现的类时,它变得可以成为组件,由框架管理。
使用MessageBodyWriters/MessageBodyReaders
,有一种特定的算法可用于确定每个请求/响应将使用哪个编写器/阅读器。基本上发生的是JAX-RS根据@Produces
注释匹配计算一个或多个列表。例如,如果我们的资源方法或资源类使用@Produces(MediaType.APPLICATION_XML)
进行注释,并且我们的提供者(编写者)也使用此注释,那么我们的编写器将被放入此列表中。然后这些提供者按一些算法排序。最后,在每个编写器上调用isWritable
方法,直到其中一个返回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();
}
这两个将匹配,我们的编写器将用于转换我们的Customer
对象
可以使用
MessageBodyReader
对Consumes
实施进行注释,以限制其认为合适的媒体类型。实现Providers
合同的MessageBodyReader
必须以编程方式在JAX-RS运行时中注册,或者必须使用@Provider
注释进行注释,以便在提供程序扫描阶段由JAX-RS运行时自动发现。
@Consumes
注释,与作家@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
,框架将决定我们的大小。
如果您想以编程方式注册MessageBodyReader
或MessageBodyWriter
,请使用register
或Client
上的ClientBuilder
方法(或任何Configurable
实例)。