سؤال

لدي قائمة من الفاصوليا، ولكل منها خاصية تمثل في حد ذاتها قائمة بعناوين البريد الإلكتروني.

<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 يصف.لماذا؟لأننا نستخدم مكتبة جافا سكريبت (mootools) لتحويل هذا <div> إلى تلميح أداة عائم، وتقوم المكتبة بتحويل ملف title في نص تلميح الأداة.

حتى إذا ${conf.subject} كان "الموضوع"، في النهاية أود title التابع <div> أن يكون "الموضوع:blah@blah.com، blah2@blah2.com، وما إلى ذلك."، والتي تحتوي على كافة عناوين البريد الإلكتروني الخاصة بالقائمة الفرعية.

كيف يمكنني القيام بذلك باستخدام JSP EL؟أحاول الابتعاد عن وضع كتل البرامج النصية في ملف jsp.

هل كانت مفيدة؟

المحلول 2

وبرزت وسيلة قذرة إلى حد ما للقيام بذلك:

<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> مرارا وتكرارا، الرجوع انها قيمة الخاصة، وإلحاق / سلسلة السلاسل.

نصائح أخرى

والطريقة "نظيفة" للقيام بذلك سيكون لاستخدام وظيفة. وبما أن وظيفة JSTL join لا تعمل على Collection، يمكنك إرسال بنفسك دون الكثير من المتاعب، وإعادة استخدامها في كل مكان بدلا من قص ولصق قطعة كبيرة من التعليمات البرمجية حلقة.

وتحتاج إلى تنفيذ وظيفة، وTLD للسماح تطبيق الويب الخاص بك يعرف أين يمكن العثور عليه. وضع هذه معا في JAR وأسقطه في WEB-INF / الدليل ليب الخاص بك.

إليك مخطط:

وكوم / س / 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 / س c.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>

وعلى الرغم من أن TLD هو قليلا مطول، مع العلم طريقك نحو واحد هو مهارة جيدة لأي مطور العمل مع JSP. ومنذ كنت قد اخترت معيار مثل JSP للعرض، هناك فرصة جيدة لديك الأدوات التي سوف تساعدك على الخروج.

وهذا النهج مزايا عديدة أكثر من بديل إضافة المزيد من الطرق للنموذج الأساسي. هذه الوظيفة يمكن كتابة مرة واحدة، وإعادة استخدامها في أي مشروع. وهو يعمل مع مغلقة المصدر، مكتبة طرف ثالث. المحددات المختلفة يمكن أن تكون معتمدة في سياقات مختلفة، دون تلويث API نموذج مع طريقة جديدة لكل منها.

والأهم من ذلك، <م> انها تؤيد الفصل بين الرأي والتنمية نموذج تحكم الأدوار. غالبا ما يتم إجراء المهام في هذين المجالين من قبل مختلف الناس في أوقات مختلفة. الحفاظ على اقتران فضفاض بين هذه الطبقات يقلل تكاليف التعقيد والصيانة. حتى عندما تغير تافهة مثل استخدام محدد مختلفة في العرض يتطلب مبرمج لتعديل مكتبة، لديك نظام مكلفة جدا ومرهقة.

والطبقة StringUtil هو نفسه ما إذا كان يتعرض لها بوصفها وظيفة EL أم لا. وفقط "إضافية" من الضروري هو TLD، وهو تافهة. أداة يمكن بسهولة تولد ذلك.

ويمكن استخدام هذا؟ يبدو أنه يريد مجموعة بدلا من القائمة ..

${fn:join(array, ";")}

HTTP: // جافا .sun.com / المنتجات / التخطيط الاستراتيجي المشترك / JSTL / 1.1 / مستندات / tlddocs / الجبهة الوطنية / join.fn.html

إذا قائمة فرعية الخاص بك هو ArrayList وأنت تفعل هذا:

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

وتحصل تقريبا على ما تحتاج إليه.

والفرق الوحيد هو أن العنوان سيكون: "الموضوع: [. blah@blah.com، blah2@blah2.com، الخ]".

وربما يمكن أن تكون جيدة بما يكفي بالنسبة لك.

وأعتقد أن هذا هو ما تريد:

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

في هذه الحالة، كان لي hashmap مع ID التبويب (مفتاح) وURL (القيمة). لم يتم تعيين متغير tabAttrs قبل ذلك. لذلك مجرد تعيين القيمة إلى القيمة الحالية tabAttrs ( '' لبدء)، بالإضافة إلى التعبير مفتاح / قيمة.

وضعت للتو سلسلة byside على فار من الخادم، مثل هذا:

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

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

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

وبعد فوات الأوان!

والطريقة التي يتم بها تنفيذ مكتبات العلامة يبدو أنه قد انتقلت إلى حد كبير منذ هذه الإجابة ونشرت أصلا حتى انتهى بي الأمر جعل بعض التغييرات الجذرية للحصول على الأشياء العمل. وكان بلدي النتيجة النهائية:

مكتبة العلامة الملف:

<?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="," />],

يمكنك استخدام EL 3.0 Stream API.على سبيل المثال، إذا كان لديك قائمة من السلاسل،

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

في حال كان لديك قائمة بالكائنات على سبيل المثال.الشخص (الاسم الأول، الاسم الأخير) وترغب في ربط خاصية واحدة فقط منهم (على سبيل المثال الاسم الأول) يمكنك استخدام الخريطة،

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

في حالتك، يمكنك استخدام شيء من هذا القبيل (قم بإزالة آخر "،" أيضًا)،

<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 ستريم API تم الانتهاء منه قبل جافا 8 ستريم API وهو مختلف عن ذلك.لا يمكنهم الوصول إلى كلا واجهات برمجة التطبيقات لأنه سيؤدي إلى كسر التوافق مع الإصدارات السابقة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top