2008-11-17 17 views
15

मेरे पास सेम की एक सूची है, जिनमें से प्रत्येक में एक संपत्ति है जो स्वयं ईमेल पते की एक सूची है।जेएसपी ईएल में तारों को जोड़ना?

<c:forEach items="${upcomingSchedule}" var="conf"> 
    <div class='scheduled' title="${conf.subject}" id="scheduled<c:out value="${conf.id}"/>"> 
    ... 
    </div> 
</c:forEach> 

यह सूची में प्रति <div> प्रति बीन प्रस्तुत करता है।

उपन्यासकार के लिए, मैं क्या करना चाहता हूं, एक स्ट्रिंग बनाने के लिए सूची में से प्रत्येक प्रविष्टि को समेकित करना है, <div> की title विशेषता के हिस्से के रूप में प्रदर्शित किया जाना है। क्यूं कर? चूंकि हम इस <div> को एक फ़्लोटिंग टूल टिप में बदलने के लिए जावास्क्रिप्ट लाइब्रेरी (mootools) का उपयोग कर रहे हैं, और लाइब्रेरी title टूलटिप के पाठ में बदल जाती है।

तो, अगर ${conf.subject} "विषय" था, अंत में मैं <div> की title चाहते होने के लिए चाहते हैं "विषय: [email protected], [email protected], आदि", जिसमें सभी ईमेल पते उप-सूची का।

मैं जेएसपी ईएल का उपयोग करके यह कैसे कर सकता हूं? मैं jsp फ़ाइल में स्क्रिप्टलेट ब्लॉक डालने से दूर रहने की कोशिश कर रहा हूं।

+0

[जेएसपी ईएल स्ट्रिंग कॉन्सटेनेशन] का संभावित डुप्लिकेट (http://stackoverflow.com/questions/3189642/jsp-el-string-concatenation) –

उत्तर

8

पता लगा यह करने के लिए कुछ हद तक एक गंदा रास्ता:

<c:forEach items="${upcomingSchedule}" var="conf"> 
    <c:set var="title" value="${conf.subject}: "/> 
    <c:forEach items="${conf.invitees}" var="invitee"> 
     <c:set var="title" value="${title} ${invitee}, "/> 
    </c:forEach> 
    <div class='scheduled' title="${title}" id="scheduled<c:out value="${conf.id}"/>"> 
    ... 
    </div> 
</c:forEach> 

मैं सिर्फ बार-बार <c:set> उपयोग करते हैं, अपने आप मूल्य को संदर्भित, संलग्न करने के लिए/तार जोड़।

+0

मुझे लगता है कि यह सबसे अच्छा है जो आप अपना स्वयं का फ़ंक्शन लिखने के बिना कर सकते हैं (जो एफएन की लाइनों के साथ बहुत मुश्किल नहीं है) – erickson

1

अपने sublist एक ArrayList है और आप ऐसा करते हैं तो:

<div class='scheduled' title="${conf.subject}: ${conf.invitees}" id="scheduled${conf.id}"> 

आप प्राप्त आप लगभग क्या जरूरत है।

एकमात्र अंतर यह है कि शीर्षक होगा: "विषय: [[email protected], [email protected], आदि]"।

शायद आपके लिए पर्याप्त हो सकता है।

+0

में शामिल हों अगर अंतर्निहित सूची एक ऐरेलिस्ट है तो मैं काम करता हूं, लेकिन मैं यह मौका नहीं लेना चाहता कि यह कुछ अन्य स्ट्रिंग कार्यान्वयन के बिना कुछ अन्य सूची कार्यान्वयन था() implemenation। –

16

ऐसा करने के लिए "साफ" तरीका एक फ़ंक्शन का उपयोग करना होगा। चूंकि जेएसटीएल join फ़ंक्शन Collection पर काम नहीं करेगा, आप बिना किसी परेशानी के अपने आप लिख सकते हैं, और लूप कोड के बड़े हिस्से को काटने और चिपकाने के बजाय इसे पूरे स्थान पर पुन: उपयोग कर सकते हैं।

आपको फ़ंक्शन कार्यान्वयन और एक टीएलडी की आवश्यकता है ताकि आपके वेब एप्लिकेशन को यह पता चल सके कि उसे कहां मिलना है। इन्हें एक साथ जार में रखें और इसे अपने वेब-आईएनएफ/lib निर्देशिका में छोड़ दें।

कॉम/एक्स/taglib/कोर/StringUtil.java

package com.x.taglib.core; 

public class StringUtil { 

    public static String join(Iterable<?> elements, CharSequence separator) { 
    StringBuilder buf = new StringBuilder(); 
    if (elements != null) { 
     if (separator == null) 
     separator = " "; 
     for (Object o : elements) { 
     if (buf.length() > 0) 
      buf.append(separator); 
     buf.append(o); 
     } 
    } 
    return buf.toString(); 
    } 

} 

META-INF/xc.tld:

यहाँ एक रूपरेखा है

<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> 
    <tlib-version>1.0</tlib-version> 
    <short-name>x-c</short-name> 
    <uri>http://dev.x.com/taglib/core/1.0</uri> 
    <function> 
    <description>Join elements of an Iterable into a string.</description> 
    <display-name>Join</display-name> 
    <name>join</name> 
    <function-class>com.x.taglib.core.StringUtil</function-class> 
    <function-signature>java.lang.String join(java.lang.Iterable, java.lang.CharSequence)</function-signature> 
    </function> 
</taglib> 

जबकि टीएलडी एक है थोड़ा वर्बोज़, जेएसपी के साथ काम कर रहे किसी भी डेवलपर के लिए एक के आसपास अपना रास्ता जानना एक अच्छा कौशल है।और, चूंकि आपने प्रस्तुति के लिए जेएसपी जैसे मानक को चुना है, इसलिए आपके पास ऐसे टूल हैं जो आपके पास मदद करेंगे।

इस दृष्टिकोण के अंतर्निहित मॉडल में और विधियों को जोड़ने के विकल्प के कई फायदे हैं। यह फ़ंक्शन एक बार लिखा जा सकता है, और किसी भी प्रोजेक्ट में पुन: उपयोग किया जा सकता है। यह एक बंद स्रोत, तीसरे पक्ष पुस्तकालय के साथ काम करता है। विभिन्न डिलीमीटरों को प्रत्येक संदर्भ के लिए एक नई विधि के साथ एक मॉडल एपीआई प्रदूषित किए बिना विभिन्न संदर्भों में समर्थित किया जा सकता है।

सबसे महत्वपूर्ण बात यह है कि यह दृश्य और मॉडल-नियंत्रक विकास भूमिकाओं को अलग करने का समर्थन करता है। इन दो क्षेत्रों में कार्य अक्सर अलग-अलग लोगों द्वारा अलग-अलग लोगों द्वारा किया जाता है। इन परतों के बीच ढीले युग्मन को बनाए रखना जटिलता और रखरखाव लागत को कम करता है। जब प्रस्तुति में एक अलग डिलीमीटर का उपयोग करने में भी एक छोटा बदलाव होता है, तो प्रोग्रामर को लाइब्रेरी को संशोधित करने की आवश्यकता होती है, आपके पास एक बहुत महंगा और बोझिल सिस्टम होता है।

StringUtil कक्षा वही है चाहे वह ईएल फ़ंक्शन के रूप में उजागर हो या नहीं। केवल "अतिरिक्त" आवश्यक टीएलडी है, जो तुच्छ है; एक उपकरण आसानी से इसे उत्पन्न कर सकता है।

+0

बैकिंग बीन में एक और विधि की तुलना में कस्टम jstl funtion लिखना बेहतर क्यों लगता है? यह एक उत्तेजक सवाल नहीं है। इस तरह के मामले में मैं बीन में इस विधि को एक विधि लिखूंगा, कुछ ऐसा प्राप्त करें जैसे InviteesAsString()। इसके साथ क्या गलत है? – alexmeia

+0

मैंने अपने जवाब में एक प्रतिक्रिया जोड़ा। मैं आपको एक ही प्रश्न पूछूंगा: आपको लगता है कि बैकिंग बीन को बदलने के लिए बेहतर क्यों है? – erickson

+0

मैंने सोचा कि यह बेहतर था क्योंकि यह दृश्य और मॉडल-नियंत्रक विकास भूमिकाओं को अलग करने का समर्थन करता है, और दृश्य में जितना संभव हो उतना कम तर्क छोड़ देता है। लेकिन, आपके उत्तर में जोड़ने के साथ, मैं समझता हूं कि आपकी विधि भी इस अलगाव का समर्थन करती है, और इसके अलावा अन्य लाभ भी हैं। एड के लिए धन्यवाद। – alexmeia

0

मुझे लगता है कि यह तुम क्या चाहते है:

<c:forEach var="tab" items="${tabs}"> 
<c:set var="tabAttrs" value='${tabAttrs} ${tab.key}="${tab.value}"'/> 
</c:forEach> 

इस मामले में, मैं टैब आईडी (key) और यूआरएल (मान) के साथ एक hashmap था। टैबएटर्स वैरिएबल इससे पहले सेट नहीं है। इसलिए यह केवल टैब एटर्स ('' शुरू करने के लिए) के साथ-साथ कुंजी/मान अभिव्यक्ति के वर्तमान मान को मान सेट करता है। बहुत देर हो गई

<c:forEach items="${upcomingSchedule}" var="conf"> 
    <div class='scheduled' title="${conf.subject}" 

     id="scheduled${conf.id}"> 

    ... 
    </div> 
</c:forEach> 

!!!:

+0

ओपी ने पहले से ही अपने प्रश्न का उत्तर दिया :) बड़े हरे रंग के चेकमार्क के साथ संदेश की जांच करें। – BalusC

0

बस सर्वर से वर byside स्ट्रिंग डाल दिया, इस तरह

0

टैग लाइब्रेरी लागू किए जाने का तरीका काफी हद तक बढ़ गया है क्योंकि यह उत्तर मूल रूप से पोस्ट किया गया था इसलिए मैंने काम करने के लिए कुछ कठोर परिवर्तन किए। मेरे अंतिम परिणाम था:

टैग लाइब्रेरी फ़ाइल:

<?xml version="1.0" encoding="UTF-8"?> 
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"> 
    <tlib-version>1.0</tlib-version> 
    <short-name>string_util</short-name> 
    <uri>/WEB-INF/tlds/string_util</uri> 
    <info>String Utilities</info> 
    <tag> 
    <name>join</name> 
    <info>Join the contents of any iterable using a separator</info> 
    <tag-class>XXX.taglib.JoinObjects</tag-class> 
    <body-content>tagdependent</body-content> 
    <attribute> 
     <name>iterable</name> 
     <required>true</required> 
     <rtexprvalue>true</rtexprvalue> 
     <type>java.lang.Iterable</type> 
    </attribute> 
    <attribute> 
     <name>separator</name> 
     <required>false</required> 
     <rtexprvalue>false</rtexprvalue> 
     <type>java.lang.String</type> 
    </attribute> 
    </tag> 

    <tag> 
    <name>joinints</name> 
    <info>Join the contents of an integer array using a separator</info> 
    <tag-class>XXX.taglib.JoinInts</tag-class> 
    <body-content>tagdependent</body-content> 
    <attribute> 
     <name>integers</name> 
     <required>true</required> 
     <rtexprvalue>true</rtexprvalue> 
     <type>java.lang.Integer[]</type> 
    </attribute> 
    <attribute> 
     <name>separator</name> 
     <required>false</required> 
     <rtexprvalue>false</rtexprvalue> 
     <type>java.lang.String</type> 
    </attribute> 
    </tag> 
</taglib> 

JoinInts.java

public class JoinInts extends TagSupport { 

    int[] integers; 
    String separator = ","; 

    @Override 
    public int doStartTag() throws JspException { 
     if (integers != null) { 
      StringBuilder buf = new StringBuilder(); 
      if (separator == null) { 
       separator = " "; 
      } 
      for (int i: integers) { 
       if (buf.length() > 0) { 
        buf.append(separator); 
       } 
       buf.append(i); 
      } 
      try { 
       pageContext.getOut().print(buf); 
      } catch (IOException ex) { 
       Logger.getLogger(JoinInts.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
     return SKIP_BODY; 
    } 

    @Override 
    public int doEndTag() throws JspException { 
     return EVAL_PAGE; 
    } 

    public int[] getIntegers() { 
     return integers; 
    } 

    public void setIntegers(int[] integers) { 
     this.integers = integers; 
    } 

    public String getSeparator() { 
     return separator; 
    } 

    public void setSeparator(String separator) { 
     this.separator = separator; 
    } 
} 

इसका इस्तेमाल करने के लिए:

<%@ taglib prefix="su" uri="/WEB-INF/tlds/string_util.tld" %> 

[new Date(${row.key}), <su:joinints integers="${row.value}" separator="," />], 
0

आप ईएल 3.0 स्ट्रीम एपीआई का उपयोग कर सकते हैं। उदाहरण के लिए यदि आपके पास तारों की एक सूची है,

<div>${stringList.stream().reduce(",", (n,p)->p.concat(n))}</div> 

यदि आपके पास पूर्व के लिए ऑब्जेक्ट्स की एक सूची है। व्यक्ति (firstName, lastName) और आप आप ऐसा ही कुछ इस्तेमाल कर सकते हैं (पूर्व firstName) उनमें से केवल एक संपत्ति आप नक्शे उपयोग कर सकते हैं,

<div>${personList.stream().map(p->p.getFirstName()).reduce(",", (n,p)->p.concat(n))}</div> 

concat करने के लिए अपने मामले में इच्छा (पिछले हटाने ',' भी) ,

<c:forEach items="${upcomingSchedule}" var="conf"> 
    <c:set var="separator" value=","/> 
    <c:set var="titleFront" value="${conf.subject}: "/> 
    <c:set var="titleEnd" value="${conf.invitees.stream().reduce(separator, (n,p)->p.concat(n))}"/> 
    <div class='scheduled' title="${titleFront} ${titleEnd.isEmpty() ? "" : titleEnd.substring(0, titleEnd.length()-1)}" id="scheduled<c:out value="${conf.id}"/>"> 
    ... 
    </div> 
</c:forEach> 

सावधान रहें!EL 3.0 Stream API को Java 8 Stream एपीआई से पहले अंतिम रूप दिया गया था और यह उससे अलग है। वे दोनों एपीआईएस को सनक नहीं कर सकते क्योंकि यह पिछड़े संगतता को तोड़ देगा।

संबंधित मुद्दे