SubscriptionRssFeedView

SubscriptionRssFeedView

我正在使用Spring开发基于REST的Web服务来提供RSS提要。 RSS的更新非常罕见(一周两次),因此我想缓存RSS feed,而不是每次有人请求时都构建它。这是我的代码。启动Web服务器后,我的第一个请求命中了SubscriptionEventHandler类中的getRssFeed()方法,然后进入SubscriptionRssFeedView并调用buildFeedMetadata,buildFeedItems方法等正确的方法。但是,当我发出第二个请求时,它将跳过SubscriptionEventHandler中的getRssFeed()方法,但buildFeedMetadata会被调用,而SubscriptionRssFeedView中的buildFeedItems方法会被调用,而后者又会调用getIncidents()并从头开始再次构建RSS。有没有一种方法可以避免这种情况并缓存RSS,直到我调用@CacheEvict

这是我的SubscriptionRssFeedView

@Component("subscriptionRssView")
public class SubscriptionRssFeedView extends AbstractRssFeedView
{

    private String base_Url=”http://mycompany.com/”;

    private final String feed_title = "My RSS Title ";
    private final String feed_desc = "RSS feed desc";
    private final String feed_type = "rss_2.0";

    @Override
    protected void buildFeedMetadata(Map<String, Object> model, Channel feed, HttpServletRequest request)
    {

        feed.setTitle(feed_title);
        feed.setDescription(feed_desc);
        feed.setLink(base_Url);
        feed.setFeedType(feed_type);

        super.buildFeedMetadata(model, feed, request);
    }


    @Override
    protected List<Item> buildFeedItems(Map<String, Object> model, HttpServletRequest request,
                                        HttpServletResponse response) throws Exception
    {
        List<Message> messageList = new ArrayList(Arrays.asList(getIncidents()));

        List<Item> itemList = new ArrayList<Item>(messageList.size());

        for (Message message : messageList)
        {
            itemList.add(createItem(message));
        }

        return itemList;
    }


    private Message[] getIncidents()
    {
        RestTemplate restTemplate = new RestTemplate();
        Message[] message = restTemplate.getForObject("http://xxxxx.com/api/message", Message[].class);

        return message;
    }


    private Item createItem(Message message)
    {
        Item item = new Item();
        item.setLink(getFeedItemURL(message));
        item.setTitle(prepareFeedItemTitle(message));
        item.setDescription(createDescription(message));
        item.setPubDate(getLocalizedDateTimeasDate(message.getT()));
        return item;
    }
}


我的SubscriptionEventHandler

@Component("SubscriptionService")
public class SubscriptionEventHandler implements SubscriptionService
{

@Autowired
private SubscriptionRssFeedView subscriptionRssFeedView;


@Override
@Cacheable("rssFeedCache")
public SubscriptionRssFeedView getRssFeed()
{
    return subscriptionRssFeedView;
}

}


我的订阅服务

@Service
public interface SubscriptionService
{
    SubscriptionRssFeedView getRssFeed();
}


我的SubscriptionController

@Controller
@RequestMapping("/subscription")
public class SubscriptionController
{

@Autowired
private SubscriptionService subscriptionService;


@RequestMapping(value = "/rss", method = RequestMethod.GET)
public SubscriptionRssFeedView getRSS() throws Exception
{
    return subscriptionService.getRssFeed();
}
}

最佳答案

呈现SubscriptionController的响应时,将始终调用SubscriptionRssFeedView的render方法。此方法是触发对buildFeedMetadata,buildFeedEntries等的调用的方法。顺序如下:

AbstractView.render => AbstractFeedView.renderMergedOutputModel => SubscriptionRssFeedView.buildFeedMetadata和SubscriptionRssFeedView.buildFeedEntries

如果您想详细了解触发这些方法调用的详细信息,可以检查父类方法AbstractView.render和AbstractFeedView.renderMergedOutputModel。

为了避免重新计算RSS,可以缓存SubscriptionRssFeedView.getIncidents()方法而不是SubscriptionEventHandler.getRssFeed()

我建议向您的缓存中添加一个键,否则对getIncidents的所有调用将始终返回相同的值,并且当您具有多个提要时,这将是不希望的。

关于java - Spring REST缓存RSS AbstractRssFeedView,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42403763/

10-11 19:49