2011-06-10 16 views
5

के साथ एक मल्टीमैप Iterate मैं बैकअप डैशबोर्ड लिखने की कोशिश कर रहा हूं एकाधिक सर्वर बैकअप की स्थिति दिखा रहा है। विचार जेएसपी के साथ एक टेबल दिखाना है जिसमें पंक्तियों में कॉलम और सर्वर नामों में पिछले कुछ दिन की तारीखें हैं। इस गरीब आदमी की तालिका में मैंने हां/नहीं मूल्य लिखा था।जेएसपी

+------------+------------+------------+------------+ 
+ Host Name | 2011-06-10 | 2011-06-09 | 2011-06-08 | 
+------------+------------+------------+------------+ 
| web01  |  Y  |  Y  |  N  | 
+------------+------------+------------+------------+ 
| web02  |  Y  |  Y  |  Y  | 
+------------+------------+------------+------------+ 

प्रत्येक सर्वर, अपने स्वयं के बैकअप करता है और अमेज़न SimpleDb में स्थिति की बचत होती है और मैं एक जावा विधि लिखा निम्नलिखित हस्ताक्षर के साथ पिछले कुछ दिनों से इस जानकारी को पुन: प्राप्त करने:

/** 
* List MySQL backups of the last howManyDays days. It starts from today 
* included at index 0 and goes back in the past until we have a list of 
* howManyDays days, even if some day doesn't have any data. Return a list of 
* dates, each of which contains a list of backup jobs executed by servers in 
* that day. 
* 
* @param howManyDays 
*   how many days of backup to show 
* @return a Map where each key is the date in ISO format (2011-06-10) and each 
*   element is a backupJob which is represented by a Map where the key is 
*   the server name (ex. web01, web01) and the value is "Y" if all was 
*   fine, otherwise it contains the error message. 
*/ 
public Multimap<String, Map<String, String>> listMysqlBackups(int howManyDays); 

मल्टीमैप है Google Guava Multimap क्योंकि मेरे पास प्रति दिन एकाधिक बैकअप हैं। उदाहरण आउटपुट:

{2011-06-10=[{web06=Y}, {web05=Y}], 2011-06-08=[{web05=Y}, {web06=Y}], 
2011-06-09=[{web05=Y}, {web06=Y}], 2011-06-07=[{web05=Y}, {web06=Y}]} 

मैं कैसे JSP में इस जानकारी का उपभोग करने के पता नहीं है। मैं foreach के साथ करने की कोशिश की:

<c:forEach items="${backups}" var="backup" varStatus="backupId"> 
    ${backup.key} 
</c:forEach> 

और जवाब था:

javax.servlet.ServletException: javax.servlet.jsp.JspTagException: Don't know 
how to iterate over supplied "items" in <forEach> 

अब मैं अगर मैं एक बहुत जटिल वापसी मान के साथ और क्या मैं बजाय वापसी चाहिए पैर में खुद को शूटिंग कर रहा हूँ सोच रहा हूँ हैश मैप का एक सरल ऐरेलिस्ट जहां प्रत्येक हैश मैप में सभी आवश्यक जानकारी (दिनांक, होस्टनाम, संदेश) शामिल है। यदि आप सोचते हैं कि एक बेहतर दृष्टिकोण है तो मुझे डेटा निकालने वाली जावा विधि को फिर से लिखने में कोई समस्या नहीं है, लेकिन तत्व को प्राप्त करने के लिए अब प्रत्येक सेल को सभी ऐरेलिस्ट में लूप की आवश्यकता होगी (जो ठीक हो सकता है क्योंकि 7 सर्वर 6 दिन केवल 42 तत्व हैं)।

आप इस समस्या से कैसे संपर्क करेंगे?

उत्तर

8

JSTL forEach टैग Multimaps समर्थन नहीं करता। यह केवल मानक संग्रह/मानचित्र/सरणी से अधिक हो सकता है।

जब मुझे किसी जेएसपी में Multimap पर पुनरावृत्ति करने की आवश्यकता है, तो मैं इसका asMap() व्यू का उपयोग करता हूं। यह मुझे forEach का उपयोग करने देता है, क्योंकि यह जानता है कि Map इंटरफ़ेस पर फिर से कैसे सक्रिय किया जाए।

यह निम्न दिखाई देगा:

public Multimap<String, Map<String, String>> listMysqlBackups(int howManyDays) { 
    // ... 
} 

public Map<String, Collection<Map<String, String>>> getListMysqlBackupsAsMap() { 
    return listMysqlBackups(this.numberOfDays).asMap(); 
} 


<c:forEach var="backup" items="${bean.listMysqlBackupsAsMap}"> 
    <c:set var="dateISO" value="${backup.key}/> 
    <c:set var="backupJobs" value="${backup.value}/> <!-- a Collection<Map<String,String>> --> 
    <c:forEach var="backupJob" items="${backupJobs}"> 
     <!-- do something with each backup job (Map<String, String>) for the current date --> 
    </c:forEach> 
</c:forEach> 

आप JSP ईएल 2.1 का उपयोग कर सकते हैं, तो आप अतिरिक्त गेटर जरूरत नहीं है। Map व्यू प्राप्त करने के लिए आप बस जेएसपी के अंदर asMap() पर कॉल कर सकते हैं।


यह सब कहा जा रहा है, मुझे यकीन है कि एक Multimap के आपके उपयोग वास्तव में तुम यहाँ क्या चाहते हैं नहीं कर रहा हूँ। Multimap<String, Map<String, String>> के संग्रह पर प्रत्येक कुंजी को मानचित्र करता है। आपके मामले में, इसका मतलब है कि आपके पास:

2011-06-09 
    --> Collection 
     --> Map<String, String> 
     --> Map<String, String> 
     --> Map<String, String> 
2011-06-10 
    --> Collection 
     --> Map<String, String> 
     --> Map<String, String> 
     --> Map<String, String> 

मुझे यकीन है कि तुम यहाँ क्या चाहते हो नहीं हूँ। मुझे लगता है कि आप Map<String, Map<String, String>> चाहते हैं।

एक और समाधान गुवा के Table का उपयोग करना होगा।

+1

+1। – Ray

+0

यदि मैं चाबियों का उपयोग करता हूं जैसा मैंने कहा था + होस्टनाम (मुझे अंडरस्कोर की भी आवश्यकता नहीं है), तो मैं एक साधारण मानचित्र <स्ट्रिंग, स्ट्रिंग> के लिए नीचे जा सकता हूं और पहले से ही पर्याप्त है, और मुझे लूप की आवश्यकता नहीं है तत्व प्राप्त करने के लिए। तालिका भी दिलचस्प लगती है, लेकिन क्या इस पर काम करने के लिए जेएसपी करता है? अन्यथा यह जटिलता को जोड़ देगा, जबकि उद्देश्य जटिलता को कम कर देगा। – stivlo

+0

मैं उपयोगी और विस्तृत स्पष्टीकरण के लिए आपका उत्तर स्वीकार करता हूं, हालांकि मैंने नीचे दिए गए मेरे समाधान का उपयोग करने का निर्णय लिया क्योंकि केवल एक हैश मैप होने के बजाय तीन स्तरों को पार करने के बजाय सरल है। आपके सहयोग के लिए धन्यवाद। – stivlo

-1

मुझे लगता है कि आप पाश

जैसे के लिए एक तरह से नेस्टेड की कोशिश करनी चाहिए

<c:forEach items="${webs}" var="web" varStatus="webId"> 
    <c:forEach items="${web.backups}" var="backup" varStatus="backupId"> 
     ${backup.key} 
    </c:forEach> 
</c:forEach> 
+0

ठीक है हाँ, लेकिन समस्या यह है कि मैं मल्टीमैप पर बाहरी लूप को भी कोड नहीं कर सकता, क्योंकि जेएसपी के लिए यह पता नहीं है कि उपरोक्त त्रुटि संदेश में, इसे कैसे पुन: सक्रिय करना है। – stivlo

+0

क्या आप किसी अन्य मानचित्र को 'मल्टीमैप' –

+0

के बजाय 'हैश मैप' की कोशिश कर सकते हैं, निम्न संरचना के साथ नहीं, क्योंकि मेरे पास प्रत्येक कुंजी के लिए कई मान हैं, इसलिए या तो मैं डेटा संरचना बदलता हूं, उदाहरण के लिए, जैसा कि मैंने समझाया है, या मैं हैश मैप का उपयोग नहीं कर सकता या मैं कुंजी के मानों को ओवरराइट कर दूंगा। या मैं एक संयुक्त कुंजी दिनांक + अंडरस्कोर + होस्टनाम के साथ हैश मैप का उपयोग कर सकता हूं। – stivlo

1

मैंने जो कुछ किया है उसे सारांशित करने के लिए, और सबसे अच्छा समाधान होने का दावा किए बिना मैं अपने प्रश्न का उत्तर देता हूं। मुझे यह जानने में दिलचस्पी है कि Google टेबल संग्रह का उपयोग करना चीजों को सरल बना सकता है या नहीं।

सूची की वापसी प्रकार MysqlBackups को एक सरल हैश मैप में बदल दिया।

/** 
* List the MySQL backups of the last howManyDays days. It starts from today and 
* goes back in the past until we have a list of howManyDays days, even if some 
* day doesn't have any data. Return a Map with each index as the ISO date 
* underscore the server name. Key example: 2011-06-11_web01 
* 
* @param howManyDays 
*   how many days of backup to show 
* @return a Map where each key is the date in ISO format and each element is 
*   a backupJob which is represented by a Map where the key is the server 
*   name (ex. web01, web01) and the value is "Y" if all was fine, 
*   otherwise it contains the error message. 
*/ 
public Map<String, String> listMysqlBackups(int howManyDays) 

जोड़े गए नए तरीकों दिन सूची और सर्वर सूची वापस जाने के लिए।

public static List<String> listDatesFromToday(int howManyDays) { 
    List<String> dates = new ArrayList<String>(); 
    String currentDay = DateHelper.getCurrentDateAsIso(); 
    while (howManyDays > dates.size()) { 
     dates.add(currentDay); 
     currentDay = DateHelper.previousDay(currentDay); 
    } 
    return dates; 
} 

public static List<String> listHosts() { 
    return ImmutableList.of("web05", "web06"); 
} 

एक नेस्टेड पाश के साथ तालिका दिखाएं। मैप में जिस तरह से मैंने कुंजी बनाया है, मैं उन्हें मानचित्र में खोजे बिना सीधे चाबियाँ खोज सकता हूं।

<table class="dataTable"> 
    <tr> 
    <th></th> 
    <c:forEach items="${days}" var="day"> 
    <th>${day}${host}</th> 
    </c:forEach> 
    </tr> 
<c:forEach items="${hosts}" var="host"> 
    <tr> 
    <th>${host}</th> 
    <c:forEach items="${days}" var="day"> 
    <c:set var="key" value="${day}_${host}"/> 
    <td> ${backups[key]} </td> 
    </c:forEach> 
    </tr> 
</c:forEach> 
</table> 

मुझे लगता है कि इस समाधान आसान है, और मैं इसके साथ खुश हूँ, लेकिन अगर तुम लोगों को लगता है कि गूगल संग्रह टेबल सरल बना देता है, छोटे और क्लीनर कोड मुझे यह सुन कर खुशी होगी।