wake-up-neo.com

EL greift über die Ganzzahltaste auf einen Kartenwert zu

Ich habe eine Map mit Integer. Wie kann ich mit EL über seinen Schlüssel auf einen Wert zugreifen?

Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");

Ich dachte, das würde funktionieren, aber nicht (wo die Karte bereits in den Attributen der Anfrage enthalten ist):

<c:out value="${map[1]}"/>

Follow up: Ich habe das Problem aufgespürt. Anscheinend ${name[1]} führt eine Kartensuche mit der Nummer als Long durch. Das habe ich herausgefunden, als ich HashMap in TreeMap geändert habe und die Fehlermeldung erhalten habe:

Java.lang.ClassCastException: Java.lang.Integer cannot be cast to Java.lang.Long

Wenn ich meine Karte ändere, um zu sein:

Map<Long, String> map = new HashMap<Long, String>();
map.put(1L, "One");

dann ${name[1]} gibt "Eins" zurück. Was ist damit? Warum tut <c:out> Behandle eine Zahl als eine lange. Scheint mir nicht intuitiv zu sein (da int häufiger als long verwendet wird).

Meine neue Frage lautet also: Gibt es eine EL-Notation, um über einen Integer -Wert auf eine Karte zuzugreifen?

85
Steve Kuo

Erste Antwort (EL 2.1, Mai 2009)

Wie in this Java forum thread erwähnt:

Grundsätzlich fügt Autoboxing ein Integer-Objekt in die Map ein. dh:

map.put(new Integer(0), "myValue")

EL (Expressions Languages) wertet 0 als Long aus und sucht daher nach einem Long als Schlüssel in der Karte. dh es wertet aus:

map.get(new Long(0))

Da ein Long niemals gleich einem Integer Objekt ist, findet es den Eintrag in der Map nicht.
Das ist alles auf den Punkt gebracht.


Update seit Mai 2009 (EL 2.2)

Im Dezember 2009 wurde EL 2.2 mit JSP 2.2/Java EE 6 eingeführt, mit einem wenige Unterschiede zu EL 2.1 .
Es scheint (" EL Expression parsing integer as long "), dass:

Sie können die Methode intValue für das Objekt Long self in EL 2.2 aufrufen :

<c:out value="${map[(1).intValue()]}"/>

Das könnte hier eine gute Lösung sein (wird auch weiter unten in Tobias Liefke 's answer )


Ursprüngliche Antwort:

EL verwendet die folgenden Wrapper:

Terms                  Description               Type
null                   null value.               -
123                    int value.                Java.lang.Long
123.00                 real value.               Java.lang.Double
"string" ou 'string'   string.                   Java.lang.String
true or false          boolean.                  Java.lang.Boolean

JSP-Seite, die dies demonstriert:

 <%@ taglib prefix="c" uri="http://Java.Sun.com/jsp/jstl/core"%>

 <%@ page import="Java.util.*" %>

 <h2> Server Info</h2>
Server info = <%= application.getServerInfo() %> <br>
Servlet engine version = <%=  application.getMajorVersion() %>.<%= application.getMinorVersion() %><br>
Java version = <%= System.getProperty("Java.vm.version") %><br>
<%
  Map map = new LinkedHashMap();
  map.put("2", "String(2)");
  map.put(new Integer(2), "Integer(2)");
  map.put(new Long(2), "Long(2)");
  map.put(42, "AutoBoxedNumber");

  pageContext.setAttribute("myMap", map);  
  Integer lifeInteger = new Integer(42);
  Long lifeLong = new Long(42);  
%>
  <h3>Looking up map in JSTL - integer vs long </h3>

  This page demonstrates how JSTL maps interact with different types used for keys in a map.
  Specifically the issue relates to autoboxing by Java using map.put(1, "MyValue") and attempting to display it as ${myMap[1]}
  The map "myMap" consists of four entries with different keys: A String, an Integer, a Long and an entry put there by AutoBoxing Java 5 feature.       

  <table border="1">
    <tr><th>Key</th><th>value</th><th>Key Class</th></tr>
    <c:forEach var="entry" items="${myMap}" varStatus="status">
    <tr>      
      <td>${entry.key}</td>
      <td>${entry.value}</td>
      <td>${entry.key.class}</td>
    </tr>
    </c:forEach>
</table>

    <h4> Accessing the map</h4>    
    Evaluating: ${"${myMap['2']}"} = <c:out value="${myMap['2']}"/><br>
    Evaluating: ${"${myMap[2]}"}   = <c:out value="${myMap[2]}"/><br>    
    Evaluating: ${"${myMap[42]}"}   = <c:out value="${myMap[42]}"/><br>    

    <p>
    As you can see, the EL Expression for the literal number retrieves the value against the Java.lang.Long entry in the map.
    Attempting to access the entry created by autoboxing fails because a Long is never equal to an Integer
    <p>

    lifeInteger = <%= lifeInteger %><br/>
    lifeLong = <%= lifeLong %><br/>
    lifeInteger.equals(lifeLong) : <%= lifeInteger.equals(lifeLong) %> <br>
114
VonC

Ein weiterer hilfreicher Hinweis neben dem obigen Kommentar wäre, wenn in einer Variablen wie einem Anforderungsparameter ein Zeichenfolgenwert enthalten ist. In diesem Fall führt die Übergabe auch dazu, dass JSTL den Wert von "1" als Zeichenfolge eingibt und somit keine Übereinstimmung in einer Map-Hashmap gefunden wird.

Eine Möglichkeit, dies zu umgehen, besteht darin, so etwas zu tun.

<c:set var="longKey" value="${param.selectedIndex + 0}"/>

Dies wird nun als langes Objekt behandelt und hat dann die Möglichkeit, ein Objekt abzugleichen, wenn es in der Map Map oder was auch immer enthalten ist.

Fahren Sie dann wie gewohnt mit so etwas fort

${map[longKey]}
11
Dave

Sie können alle Funktionen von Long aus nutzen, wenn Sie die Nummer in "(" ")" eingeben. Auf diese Weise können Sie den Long in ein Int umwandeln:

<c:out value="${map[(1).intValue()]}"/>
8
Tobias Liefke

Basierend auf dem obigen Beitrag habe ich dies versucht und dies hat gut funktioniert. Ich wollte den Wert von Map B als Schlüssel für Map A verwenden:

<c:if test="${not empty activityCodeMap and not empty activityDescMap}">
<c:forEach var="valueMap" items="${auditMap}">
<tr>
<td class="activity_white"><c:out value="${activityCodeMap[valueMap.value.activityCode]}"/></td>
<td class="activity_white"><c:out value="${activityDescMap[valueMap.value.activityDescCode]}"/></td>
<td class="activity_white">${valueMap.value.dateTime}</td>
</tr>
</c:forEach>
</c:if>
3
Dhanashri

Wenn Sie zufällig eine Map mit Integer Tasten haben, die Sie nicht ändern können, können Sie eine benutzerdefinierte EL-Funktion schreiben, um eine Long in Integer. Auf diese Weise können Sie Folgendes tun:

<c:out value="${map[myLib:longToInteger(1)]}"/>
2
Jasper de Vries