Jak przeglądać HashMap w JSP?

146

Jak mogę przejść przez pętlę HashMapw JSP?

<%
    HashMap<String, String> countries = MainUtils.getCountries(l);
%>

<select name="country">
    <% 
        // Here I need to loop through countries.
    %>
</select>
blub
źródło
17
Nawiasem mówiąc, z HashMapnatury jest nieuporządkowany. Czy na pewno nie potrzebujesz TreeMap(sortowanie automagiczne według klucza) lub LinkedHashMap(utrzymuje kolejność reklamową)?
BalusC

Odpowiedzi:

308

Tak samo, jak w normalnym kodzie Java.

for (Map.Entry<String, String> entry : countries.entrySet()) {
    String key = entry.getKey();
    String value = entry.getValue();
    // ...
}

Jednakże , scriptlets (surowy kod Java w plikach JSP, tych <% %>miejscach) są uważane za biedny praktyka . Zalecam zainstalowanie JSTL (po prostu upuść plik JAR /WEB-INF/libi zadeklaruj potrzebne taglibs na górze JSP). Posiada <c:forEach>tag, który może iterować między innymi po Maps. Każda iteracja da ci Map.Entryzwrot, który z kolei ma getKey()i getValue()metody.

Oto podstawowy przykład:

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

<c:forEach items="${map}" var="entry">
    Key = ${entry.key}, value = ${entry.value}<br>
</c:forEach>

W ten sposób Twój konkretny problem można rozwiązać w następujący sposób:

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

<select name="country">
    <c:forEach items="${countries}" var="country">
        <option value="${country.key}">${country.value}</option>
    </c:forEach>
</select>

Potrzebujesz a Servletlub a, ServletContextListeneraby umieścić ${countries}w żądanym zakresie. Jeśli ta lista ma być oparte na żądanie, a następnie użyć Servlet„s doGet():

protected void doGet(HttpServletRequest request, HttpServletResponse response) {
    Map<String, String> countries = MainUtils.getCountries();
    request.setAttribute("countries", countries);
    request.getRequestDispatcher("/WEB-INF/page.jsp").forward(request, response);
}

Lub jeśli ta lista ma być stałą dla całej aplikacji, użyj ServletContextListeners contextInitialized(), aby została załadowana tylko raz i przechowywana w pamięci:

public void contextInitialized(ServletContextEvent event) {
    Map<String, String> countries = MainUtils.getCountries();
    event.getServletContext().setAttribute("countries", countries);
}

W obu przypadkach countriesbędzie dostępny w EL do godz${countries} .

Mam nadzieję że to pomoże.

Zobacz też:

BalusC
źródło
2
@Khue: tak, możesz również umieścić atrybuty w sesji. Nie rozumiem tylko, dlaczego chcesz powielać dane całej aplikacji w wielu sesjach.
BalusC
Myślę w przypadku informacji opartych na sesji. Dzięki za bardzo miłe wyjaśnienie.
Khue Vu
Jestem pewien, że odpowiedź jest oczywista, ale - dlaczego skryptlety są uważane za kiepską praktykę? W przypadku braku JSTL z powodu utrzymywania starszej aplikacji jest to moja jedyna opcja.
Zibbobz
@Zibbobz: tekst „słaba praktyka” to link. Kliknij na to.
BalusC
1

W zależności od tego, co chcesz osiągnąć w pętli, zamiast tego wykonaj iterację jednej z nich:

  • countries.keySet()
  • countries.entrySet()
  • countries.values()
Jim Garrison
źródło
tak, dzięki temu otrzymuję zestaw wszystkich kluczy, ale jak mogę zintegrować go z wybranym polem dla html?
blub
6
to nie jest odpowiedzią na pytanie, które jest specyficzne dla JSP
Taoufik Mohdit
0

Poniższy kod działa u mnie

najpierw zdefiniowałem partnerTypesMapjak poniżej po stronie serwera,

Map<String, String> partnerTypes = new HashMap<>();

po dodaniu do niego wartości dodałem obiekt do model,

model.addAttribute("partnerTypesMap", partnerTypes);

Podczas renderowania strony używam poniżej, foreachaby wydrukować je jeden po drugim.

<c:forEach items="${partnerTypesMap}" var="partnerTypesMap">
      <form:option value="${partnerTypesMap['value']}">${partnerTypesMap['key']}</form:option>
</c:forEach>
tk_
źródło