2017-02-22 100 views
1

Я разрабатываю веб-сервис на основе REST с использованием пружин для подачи RSS-канала. Обновления RSS очень редки (пару раз в неделю), и поэтому я хочу кэшировать RSS-канал, а не строить его каждый раз, когда кто-то просит об этом. Вот мой код. Мой первый запрос после запуска моего веб-сервера вызывает метод getRssFeed() в классе SubscriptionEventHandler, а затем переходит в SubscriptionRssFeedView и вызывает методы buildFeedMetadata, buildFeedItems и т. Д., Что является правильным. Но когда я делаю второй запрос, он пропускает метод getRssFeed() в SubscriptionEventHandler, но метод buildFeedMetadata, buildFeedItems в SubscriptionRssFeedView получает вызов, который в свою очередь вызывает getIncidents() и снова создает RSS с нуля. Есть ли способ, я могу избежать этого и кэшировать RSS, пока я не называть @CacheEvictКэширование Spring REST RSS AbstractRssFeedView

Вот мой 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; 
} 

} 

Мой SubscriptionService

@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(); 
} 
} 
+0

проверить мой обновленный комментарий – artemisian

ответ

0

При визуализации ответа вашего SubscriptionController render метод вашего SubscriptionRssFeedView всегда будет вызываться. Этот метод запускает вызовы buildFeedMetadata, buildFeedEntries и так далее. Последовательность выглядит следующим образом:

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

вы можете проверить родительские классы методы AbstractView.render и AbstractFeedView.renderMergedOutputModel если вы хотите увидеть более подробно, что вызывает вызов этих методов.

В вас хотят, чтобы избежать перерасчета RSS можно кэшировать SubscriptionRssFeedView.getIncidents() метод вместо SubscriptionEventHandler.getRssFeed()

Я предлагаю добавить ключ к кэшу в противном случае все вызовы getIncidents вернутся всегда то же самое значение, и это будет нежелательная когда у вас несколько каналов.

+0

Я не думаю, что это так, потому что, когда я отлаживаю, метод getRssFeed() вызывается только в первый раз, а во время всех последующих вызовов метод не выполняется. поэтому я уверен, что он выбирает объект subscriptionRssFeedView из кеша. Но вместо того, чтобы обслуживать ранее сгенерированный вывод, он снова восстанавливает все. – user864309

+0

Извините, я ошибся в стратегии ключевых слов по умолчанию для методов, отличных от arg. Я обновил свой ответ. – artemisian