Domanda

Ho un Elenco di bean, ognuno dei quali ha una proprietà che è esso stesso un Elenco di indirizzi e-mail.

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

Questo rende uno <div> per bean nell'elenco.

Per l'elenco secondario, ciò che mi piacerebbe poter fare è concatenare ciascuna delle voci nell'elenco per formare una singola stringa, da visualizzare come parte dell'attributo title dell '${conf.subject} . Perché? Perché stiamo usando una libreria javascript (mootools) per trasformare questo <=> in un suggerimento mobile e la libreria trasforma <=> nel testo del suggerimento.

Quindi, se <=> era " Oggetto " ;, in definitiva vorrei che <=> del <=> fosse " Oggetto: blah@blah.com , blah2@blah2.com, ecc. " ;, contenente tutti gli indirizzi e-mail dell'elenco secondario.

Come posso fare questo usando JSP EL? Sto cercando di stare lontano dal mettere blocchi di scriptlet nel file jsp.

È stato utile?

Soluzione 2

Ho scoperto un modo un po 'sporco per farlo:

<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>

Uso semplicemente <c:set> ripetutamente, facendo riferimento al suo valore, per aggiungere / concatenare le stringhe.

Altri suggerimenti

Il " clean " modo per farlo sarebbe usare una funzione. Poiché la funzione JSTL join non funziona su un Collection, puoi scriverne una tua senza troppi problemi e riutilizzarla ovunque invece di tagliare e incollare un grosso blocco di codice loop.

È necessaria l'implementazione della funzione e un TLD per far sapere alla tua applicazione web dove trovarla. Mettili insieme in un JAR e rilascialo nella tua directory WEB-INF / lib.

Ecco uno schema:

com / x / taglib / core / 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 / x-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>

Mentre il TLD è un po 'prolisso, conoscerne uno è una buona abilità per qualsiasi sviluppatore che lavora con JSP. E, dal momento che hai scelto uno standard come JSP per la presentazione, ci sono buone probabilità di avere strumenti che ti aiuteranno.

Questo approccio presenta molti vantaggi rispetto all'alternativa di aggiungere più metodi al modello sottostante. Questa funzione può essere scritta una volta e riutilizzata in qualsiasi progetto. Funziona con una libreria di terze parti chiusa. Delimitatori diversi possono essere supportati in contesti diversi, senza inquinare un'API di modello con un nuovo metodo per ciascuno.

Soprattutto, supporta una separazione dei ruoli di sviluppo della vista e del controller del modello. Le attività in queste due aree sono spesso eseguite da persone diverse in momenti diversi. Mantenere un accoppiamento libero tra questi strati riduce al minimo la complessità e i costi di manutenzione. Quando anche un cambiamento banale come l'uso di un delimitatore diverso nella presentazione richiede che un programmatore modifichi una libreria, hai un sistema molto costoso e ingombrante.

La classe StringUtil è la stessa, indipendentemente dal fatto che sia esposta come una funzione EL. L'unica & Quot; extra & Quot; necessario è il TLD, che è banale; uno strumento potrebbe facilmente generarlo.

Potresti usare questo? Sembra che voglia un array anziché un elenco ..

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

http: // java .sun.com / prodotti / JSP / JSTL / 1.1 / docs / tlddocs / FN / join.fn.html

Se la tua lista secondaria è una ArrayList e fai questo:

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

ottieni quasi ciò di cui hai bisogno.

L'unica differenza è che il titolo sarà: " Oggetto: [blah@blah.com, blah2@blah2.com, ecc.] " ;.

Forse può essere abbastanza buono per te.

Penso che questo sia quello che vuoi:

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

In questo caso, avevo una hashmap con ID scheda (chiave) e URL (valore). La variabile tabAttrs non è stata impostata prima di questo. Quindi imposta semplicemente il valore sul valore corrente di tabAttrs ('' per iniziare) più l'espressione chiave / valore.

Metti la stringa accanto al var dal server, in questo modo:

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

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

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

Troppo tardi !!!

Il modo in cui sono implementate le librerie di tag sembra essersi spostato considerevolmente da quando questa risposta è stata originariamente pubblicata, quindi ho finito per apportare alcune drastiche modifiche per far funzionare le cose. Il mio risultato finale è stato:

File libreria tag:

<?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;
    }
}

Per usarlo:

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

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

È possibile utilizzare l'API Stream EL 3.0. Ad esempio se hai un elenco di stringhe,

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

Nel caso in cui tu abbia un elenco di oggetti per es. Person (firstName, lastName) e desideri concederne solo una proprietà (ex firstName) puoi utilizzare map,

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

Nel tuo caso potresti usare qualcosa del genere (rimuovi anche l'ultimo ','),

<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>

Stai attento! Il API EL 3.0 Stream è stato finalizzato prima che API Java 8 Stream ed è diverso da quello. Non sono in grado di sradicare entrambe le API perché interromperà la compatibilità con le versioni precedenti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top