Jersey Produce回复RSS Feed(找不到媒体类型= application / rss + xml的MessageBodyWriter)

时间:2017-02-08 12:35:07

标签: java spring-boot jersey

我正在为Jersey的RESTtFull web应用程序编写一个Blog响应列表。如何用泽西制作RSS feed?我试过

@GET
@Produces("application/rss+xml")
public Response list() {
    Map<Object, Object> apiResponse     = new HashMap<Object, Object>();
    Map<Object, Object> serviceResponse = new HashMap<Object, Object>();

    try {
        List<Blog> blogs = blogService.list();
        serviceResponse.put("total", blogs.size());
        serviceResponse.put("list", blogs); 
        apiResponse.put("apiresponse", serviceResponse);

        return Response.ok(apiResponse).build();

    } catch (Exception e) {
        logger.error("Error in getting blog list:", e);
        apiResponse.put("error", e.getMessage());
    }

    return Response.status(500).entity(apiResponse).build();
}

这是我服务层中的博客列表方法:

public List<Blog> list() throws Exception {

        List<Blog> blogs= new ArrayList<Blog>();
        Query query = new Query();

        blogs= SpringDataDBUtils.getMongoOperations().find(query, Blog.class);

        return blogs;
    }

但它不起作用。它产生错误:

MessageBodyWriter not found for media type=application/rss+xml, type=class java.util.HashMap

2 个答案:

答案 0 :(得分:0)

Jersey没有提及它可以处理HashMap到XML表示的转换。

  

XML媒体类型(text / xml,application / xml和application /...+ xml)

     
      
  • javax.xml.transform.Source
  •   
  • javax.xml.bind.JAXBElement
  •   
  • 应用程序提供的JAXB类(使用@XmlRootElement或@XmlType注释的类型)
  •   

即使您在散列映射中使用的其他对象被注释为转换为XML,它也不起作用。

我建议您创建一个专用的表示对象,例如BlogListResponse,其中注明了@XmlXXX注释,对于您尝试使用的Blog实体也是如此。< / p>

答案 1 :(得分:0)

提到by @Frederik Heremans时,问题出在(Hash)Map上。但即使你让地图工作,你仍然没有一个有效的RSS格式。你只需要随机的XML,RSS阅读器无法阅读。

如果您想要真正的RSS格式,请查看RSS Wikipedia page。在那里,您将看到不同的RSS版本和格式。之后,您应该找到一个专门处理RSS源的库。我个人建议Rome。我认为它是最受欢迎的Java库。 (请务必查看链接。有很多例子。)

罗马图书馆有一个单一的根界面SyndFeed,可以对RSS Feed进行建模(它支持多个RSS版本)。使用SyndFeed,您可以创建一个处理(反)序列化的JAX-RS Provider。这是一个完整的工作示例

import com.rometools.rome.feed.synd.SyndFeed;
import com.rometools.rome.io.FeedException;
import com.rometools.rome.io.SyndFeedInput;
import com.rometools.rome.io.SyndFeedOutput;

import javax.ws.rs.Consumes;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

/**
 * Example JAX-RS provider for Rome {@code SyndFeed}.
 */
@Provider
@Produces("application/rss+xml")
@Consumes("application/rss+xml")
public class SyndFeedProvider implements MessageBodyWriter<SyndFeed>, MessageBodyReader<SyndFeed> {

    @Override
    public boolean isWriteable(Class<?> type, Type genericType,
                               Annotation[] annotations,MediaType mediaType) {
        return SyndFeed.class.isAssignableFrom(type);
    }

    @Override
    public long getSize(SyndFeed syndFeed, Class<?> type, Type genericType,
                        Annotation[] annotations, MediaType mediaType) {
        return -1;
    }

    @Override
    public void writeTo(SyndFeed syndFeed, Class<?> type, Type genericType,
                        Annotation[] annotations, MediaType mediaType, MultivaluedMap<String,
                        Object> httpHeaders, OutputStream entityStream)
            throws IOException, WebApplicationException {

        SyndFeedOutput output = new SyndFeedOutput();
        OutputStreamWriter writer = new OutputStreamWriter(entityStream);
        try {
            output.output(syndFeed, writer);
        } catch (FeedException e) {
            throw new InternalServerErrorException(e);
        }
    }

    @Override
    public boolean isReadable(Class<?> type, Type genericType,
                              Annotation[] annotations, MediaType mediaType) {
        return SyndFeed.class.isAssignableFrom(type);
    }

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

        InputStreamReader reader = new InputStreamReader(entityStream);
        SyndFeedInput input = new SyndFeedInput();

        try {
            return input.build(reader);
        } catch (FeedException e) {
            throw new InternalServerErrorException(e);
        }
    }
}

您需要在Jersey应用程序中注册此提供程序,可以通过程序包扫描进行隐式注册,也可以使用ResourceConfig进行显式注册。

此提供程序处理SyndFeed的序列化和反序列化。因此,在您的资源中,您可以创建SyndFeed个实例,并将其作为响应实体返回。提供程序将处理序列化。示例提供程序还将从序列化形式的反序列化处理回到SyndFeed类,以防您想在客户端上使用它,可能用于测试。

您可以在this Gist

中找到完整的工作测试用例