2017-02-22 74 views
1

我正在開發基於REST的web服務,使用彈簧來提供RSS提要。對RSS的更新非常少見(每週幾次),因此我想緩存RSS源,而不是每次有人請求時都建立它。這是我的代碼。我在啓動Web服務器後的第一個請求在SubscriptionEventHandler類中觸發getRssFeed()方法,然後進入SubscriptionRssFeedView並調用buildFeedMetadata,buildFeedItems方法等等,這是正確的。但是,當我做第二個請求,它會跳過getRssFeed()方法SubscriptionEventHandler但buildFeedMetadata,在SubscriptionRssFeedView buildFeedItems方法被調用這反過來又調用getIncidents()和從頭構建RSS。有沒有一種方法可以讓我避免這種情況並緩存RSS,直到我稱之爲@CacheEvictSpring 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你SubscriptionRssFeedView的render方法的反應總是會被調用。這個方法是觸發buildFeedMetadata,buildFeedEntries等等的調用的方法。該序列如下:

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

可以檢查父類的方法AbstractView.render和AbstractFeedView.renderMergedOutputModel如果您想更詳細地瞭解什麼觸發了對這些方法的調用

在你想避免重新計算RSS,你可以緩存SubscriptionRssFeedView.getIncidents()方法,而不是SubscriptionEventHandler.getRssFeed()

我建議增加一鍵緩存否則getIncidents所有調用將始終返回相同的值,這將是不希望的當你有多個飼料。

+0

我不覺得,因爲當我調試,在getRssFeed()方法被調用僅在第一次和期間的所有後續調用不執行該法的情況。所以我確定它從緩存中選擇訂閱RssFeedView對象。但不是服務於以前生成的輸出,而是再次重建所有內容。 – user864309

+0

對不起,我錯了關於非參數方法的默認關鍵策略。我已經更新了我的答案。 – artemisian