javabog.dk  |  << forrige  |  indhold  |  næste >>  |  programeksempler  |  om bogen

15 Java Server Faces


15.1 Kernefunktionalitet (<f: >) 289

15.2 HTML-funktionalitet (<h: >) 289

15.3 Visning af gæstebog fra JSF 290

15.4 Opdatering af gæstebog fra JSF 292

15.4.1 Avanceret: Validatorer 293

15.4.2 Avanceret: Fejlmeddelelser 293

15.4.3 Avanceret: Resursebundter 293

15.4.4 At gemme data i en javabønne 294

15.4.5 Avanceret: Startværdier for egenskaber 294

15.5 Aflæsning af JSF-bønnes egenskab 295

15.5.1 Adgang til de implicitte objekter fra JSF 295

15.6 JSF - anbefalet praksis 296

15.6.1 At gemme midlertidige data i en HashMap 296

15.7 Resumé 298

15.7.1 JSF og JDeveloper 298

15.7.2 Måder at aktivere JSF-komponenter 298

15.8 Kilder til JSF-komponenter 299

15.8.1 Oracle ADF Faces 299

15.8.2 Apache MyFaces 299

15.8.3 Andre kilder 300

15.9 EL - Expression Language 300

15.10 Om associative tabeller (HashMap) 300

Dette kapitel er frivillig læsning; det forudsættes ikke i resten af bogen.

Blablabla

xxx JSF er et HTML-lignende sprog, som man kan skrive koden, der udføres på serveren i, i stedet for Java. For ikke-Java-kyndige HTML-designere skulle JSTL være betydeligt simplere at bruge end Java, da syntaksen ligner den, de i forvejen kender fra HTML1.

JSF fungerer i praksis som to tag-biblioteker (eng.: taglibs). Det vis sige at JSP-sider der bruger JSF-komponenter skal have linjerne

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>

i starten af siden.

Et tag library (forkortet taglib) er, som navnet siger, et bibliotek af HTML-lignende koder. Ligesom JSP-koderne udføres taglib-koderne på serveren.

Læsning om JSF

15.1 Kernefunktionalitet (<f: >)

Kernefunktioner (de mest basale funktioner) i JSF ligger i core-taglibbet under navnet 'f'. Her er understøttelse for hændelser, datakonvertering, lokalisering, validatorer og andre ting.

Alle JSF-koder skal f.eks. være indeholdt i et 'view', der sørger for at registrere og konfigurere JSF-komponenterne:

<f:view>
  ... JSF-koder (og eventuelt andre JSP-koder)
</f:view>

De andre <f:>-koder angår alle kernefunktionalitet i JSF:

xxx oversigstabel ind

15.2 HTML-funktionalitet (<h: >)

JSF er beregnet til at kunne generere mange former for output (det mest almindelige er selvfølgelig HTML). Til dette bruges et JSF 'render kit', der er et tagbibliotek med komponenter beregnet til den pågældende form for output, f.eks. JSFs HTML-tagbibliotek <h:>:

xxx oversigstabel ind

15.3 Visning af gæstebog fra JSF

Herunder ses hvordan man kunne lave gæstebogen vi så i databasekapitlet i afsnit xxx med JSF.

Bind et objekt (en javabønne), til applikationen, med følgende i faces-config.xml:

  <managed-bean>
    <managed-bean-name>gaestebog</managed-bean-name>
    <managed-bean-class>jsf.Gaestebog</managed-bean-class>
    <managed-bean-scope>application</managed-bean-scope>
  </managed-bean>

I JDeveloper (og sikkert også andre værktøjer) kan det gøres ved at gå hen på fanen 'Overview' på faces-config.xml:

Denne klasse har logikken til at hente et ResultSet med data, med metoden getGaester():

package jsf;
import java.sql.*;

public class Gaestebog
{
  private Connection con;
  
  public Gaestebog()
  {
    try {
      // Initialisering gæstebogen
      Class.forName("com.mysql.jdbc.Driver");
      con = DriverManager.getConnection("jdbc:mysql:///test");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public ResultSet getGaester()
  {
    System.out.println("inde i getGaester()");
    try {
      // Hent ResultSet med gæstebogen
      Statement stmt = con.createStatement();
     ResultSet rs = stmt.executeQuery("SELECT navn, besked, dato FROM gaestebog");
      return rs;
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }
}

Nu kan vi lave en JSF-side med en <h:dataTable />, der viser gæsterne. Værktøjet spørger os om hvilken værdi der skal vises (det er #{gaestebog.gaester}, dvs metoden getGaester() på Gaestebog-objektet, der jo giver ResultSet-objektet) og om navnet på en variabel, der skal gennemløbe alle rækkerne.

Dernæst skal vi beskrive hvad der skal vises i hver kolonne. Da vi har kaldt vores gennemløbsvariabel for 'g' er det den vi skal bruge. Da kolonnerne i databasen hedder hhv 'navn', 'dato' og 'besked' skriver vi hhv #{g.navn}, #{g.dato} og #{g.besked} (egentlig bliver det oversat til getString("navn"), getString("dato") og getString("besked") på ResultSet'et):

Herefter ser siden nogenlunde sådan her ud:

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<f:view>
  <html>
    <head><title>Gæstebog JSF</title></head>
    <body>
      <h:form>
        <h1>Gæstebog-jsf</h1>
        <p>Velkommen til min lille gæstebog.</p>
        <p>
          <h:dataTable value="#{gaestebog.gaester}" var="g">
            <h:column>
              <f:facet name="header">
                <h:outputText value="navn"/>
              </f:facet>
              <h:outputText value="#{g.navn}"/>
            </h:column>
            <h:column>
              <f:facet name="header">
                <h:outputText value="datoen"/>
              </f:facet>
              <h:outputText value="#{g.dato}"/>
            </h:column>
            <h:column>
              <f:facet name="header">
                <h:outputText value="beskedden"/>
              </f:facet>
              <h:outputLink>
                <h:outputText value="#{g.besked}"/>
              </h:outputLink>
            </h:column>
            <h:column/>
          </h:dataTable>
        </p>

        <p>
          Du kan skrive dig ind 
          <h:commandLink action="indskriv">
            <h:outputText value="her"/>
          </h:commandLink>
        </p>
      </h:form>

<% 
  // Her ses hvordan man får fat i en JSF-bønne fra almindelig JSP-kode
  int antalGæster = 0;
  jsf.Gaestebog gæstebog = (jsf.Gaestebog) application.getAttribute("gaestebog");
  java.sql.ResultSet rs = gæstebog.getGaester();
  while (rs.next()) antalGæster++; // tæl antal rækker
  out.print("<p>Der er i alt "+antalGæster+" besøg.</p>");
%>
    </body>
  </html>
</f:view>

Nederst ses hvordan man kan få fat i JSFs objekter fra almindelig JSP-kode:

  jsf.Gaestebog gæstebog = (jsf.Gaestebog) application.getAttribute("gaestebog");

Sammenlign med faces-config.xml, der erklærede at bønnenavnet var 'gaestebog' med virkefelt application af type ' jsf.Gaestebog'.

15.4 Opdatering af gæstebog fra JSF

Lad os nu lave en JSF-side, der opdaterer gæstebogen:

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<f:view>
  <html><head><title>Gæstebog - indskriv</title></head>
    <body>
      <h:form>
        <h:commandLink action="tilbage">
          <h:outputText value="tilbage til gæstebog"/>
        </h:commandLink>
        
        <h1>Skriv dig ind i min gæstebog</h1>
        <p>
            Navn: <h:inputText value="#{gaest.navnet}" />
        </p>
        <p>
          Besked:<br></br>
        <h:inputTextarea value="#{gaest.besked}" cols="70" rows="5" />
        </p>
        <p>
          <h:commandButton value="Ok" action="#{gaestebog.indskriv}"/>
        </p>
      </h:form>
    </body>
  </html>
</f:view>

xxx skærmbillede ind

Her har vi sat de to JSF-komponenter <h:inputText/> og <h:inputTextarea/> til at binde til egenskaberne hhv 'navnet' og 'besked' på javabønnen 'gaest', der styres af JSF.

15.4.1 Avanceret: Validatorer

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

15.4.2 Avanceret: Fejlmeddelelser

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

15.4.3 Avanceret: Resursebundter

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

15.4.4 At gemme data i en javabønne

Vi skal nu skrive klassen, der har egenskaberne hhv 'navnet' og 'besked'. Den ligger i pakken 'jsf' og kaldes Gaest:

package jsf;

public class Gaest 
{
  String navnet;
  String besked;

  public String getNavnet()
  {
    return navnet;
  }

  public void setNavnet(String navnet)
  {
    this.navnet = navnet;
  }

  public String getBesked()
  {
    return besked;
  }

  public void setBesked(String besked)
  {
    this.besked = besked;
  }
}

Bemærk at de fleste udviklingsværktøjer kan generere get- og set-metoderne for os, sådan at vi slipper for at spilde tid med at indtaste dem selv. Det er dog stadig et kedeligt arbejde at generere og vedligeholde dem (senere, i afsnit 15.6.1At gemme midlertidige data i en HashMap) vil vi se et bud på hvordan man kan undgå at skrive alt for meget af denne slags 'hjernedød' kode).

Til sidst kan vi nu binde klassen 'jsf.Gaest' til navnet 'gaest' i faces-config.xml:

  <managed-bean>
    <managed-bean-name>gaest</managed-bean-name>
    <managed-bean-class>jsf.Gaest</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>

Hermed er javabønnen bundet og tilgængelig i JSP-siderne.

15.4.5 Avanceret: Startværdier for egenskaber

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

15.5 Aflæsning af JSF-bønnes egenskab

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

15.5.1 Adgang til de implicitte objekter fra JSF

Linjen

      FacesContext fc = FacesContext.getCurrentInstance();

er central. Den giver os adgang til hele JSF-systemet, der ligger som et lag oven på JSP.

I dette eksempel er vi dog kun interesserede i det underliggende JSP-system (JSF-systemets 'omgivelser' eller på engelsk 'external context'), nemlig request-objektet attributter (gaest-bønnen er har virkefelt 'request'). Dem kan vi få med

      Gaest g = (Gaest) fc.getExternalContext().getRequestMap().get("gaest");

Adgang til request-objektet fra JSF

Ville vi have fat i hele request-objektet skulle vi skrive

  FacesContext fc = FacesContext.getCurrentInstance();
  HttpServletRequest request;
  request = (HttpServletRequest) fc.getExternalContext().getRequest();

Fordi JSF i princippet kan fungere oven på andre systemer end Java Server Pages er returværdien af getRequest()-metoden af type blot 'Object' og vi må selv konvertere den til et HttpServletRequest-objekt.

Tilsvarende gælder for de andre implicitte objekter defineret implicit i JSP.

Adgang til session-objektet fra JSF

Man kan få adgang til session-objektet med:

  FacesContext fc = FacesContext.getCurrentInstance();
  HttpSession session = (HttpSession) fc.getExternalContext().getSession(false);

Kaldet til getSession(false) giver sessionobjektet hvis det allerede er oprettet, ellers null. Ønsker man at sessionobjektet skal oprettes hvis det ikke allerede findes skal man skrive:

  HttpSession session = (HttpSession) fc.getExternalContext().getSession(true);

Adgang til application-objektet fra JSF

Man får fat i application-objektet med

  FacesContext fc = FacesContext.getCurrentInstance();
  ServletContext application; 
  application = (ServletContext) fc.getExternalContext().getContext();

Bemærk at

  fc.getApplication()

ikke giver det normale application-objekt man er vant til! xxx

15.6 JSF - anbefalet praksis

Jeg anbefaler at man binder forretningsdata, data af lidt mere permanent karakter og data hvor noget lidt mere kompleks programlogik er involveret til javabønners egenskaber som beskrevet ovenfor.

15.6.1 At gemme midlertidige data i en HashMap

Til midlertidige formulardata, der bare nemt skal opbevares et sted indtil de skal behandles eller gemmes et andet sted (f.eks. i en database som Gaest-klassen ovenfor) synes jeg dog det bliver for tungt at oprette og vedligeholde alle disse javabønne. I disse tilfælde kan man bare bruge en HashMap (en nøgleindekseret tabel, se afsnit 15.10) til opbevaringen.

Herunder ses ovenstående eksempel uden brug af Gaest-klassen. I stedet bruges en HashMap (sammenlign med tidligere erklæring af bønnen 'gaest' i faces-config.xml):

  <managed-bean>
    <managed-bean-name>gaest</managed-bean-name>
    <managed-bean-class>java.util.HashMap</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>

Vi behøver ikke ændre på selve JSF-siden, da udtrykket

<h:inputText id="navn" value="#{gaest.navn}" />

automatisk bliver opfattet anderledes af JSF hvis gaest er en HashMap: I stedet for af forvente metoderne String getNavnet() og void setNavnet(String navnet) kaldes nu metoderne get("navnet") og set("navnet", navnet), dvs brugerens indtastning bliver gemt under nøglen "navnet" i hashtabellen.

Her ses den endelige kode for Gaestebog (ændringer i forhold til tidligere versioner er i fed):

package jsf;
import java.sql.*;
import java.util.HashMap;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

public class Gaestebog
{
  private Connection con;
  
  public Gaestebog()
  {
    try {
      // Initialisering gæstebogen
      Class.forName("com.mysql.jdbc.Driver");
      con = DriverManager.getConnection("jdbc:mysql:///test");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public ResultSet getGaester()
  {
    System.out.println("getGaester()");

    try {
      // Udskriv gæstebogen
      Statement stmt = con.createStatement();
     ResultSet rs = stmt.executeQuery("SELECT navn, besked, dato FROM gaestebog");
      return rs;
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  public String indskriv()
  {
    System.out.println("indskriv()");
    try {
      FacesContext fc = FacesContext.getCurrentInstance();
  
      System.out.println("fc="+fc);
      
      HashMap g = (HashMap) fc.getExternalContext().getRequestMap().get("gaest");
      System.out.println("formular="+g);
  
      String navn = (String) g.get("navn");
      String besked = (String) g.get("besked");
  
      PreparedStatement pstmt = con.prepareStatement(
        "INSERT INTO gaestebog (navn, besked, dato, ip) VALUES(?,?,?,?)");

      pstmt.setString(1, navn);
      pstmt.setString(2, besked);
      pstmt.setDate(3, new java.sql.Date(System.currentTimeMillis()));
      
      HttpServletRequest request;
      request = (HttpServletRequest) (fc.getExternalContext().getRequest());
     
      pstmt.setString(4, request.getRemoteAddr());
      pstmt.executeUpdate();  
      pstmt.close();
      con.close();
  
      return "tilbage";
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }
}

15.7 Resumé

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

15.7.1 JSF og JDeveloper

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

15.7.2 Måder at aktivere JSF-komponenter

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

15.8 Kilder til JSF-komponenter

Som bekendt er JSF opdelt i en generel del ('core'), der ikke er specielt rettet mod HTML og en HTML-specifik del, der indeholder de visuelle komponenter.

15.8.1 Oracle ADF Faces

Oracle ADF Faces (Application Development Framework) er er Oracles egne webkomponenter skrevet om til JSF. Det er en en imponerende samling af omkring 100 komponenter, selvfølgelig indbefattet en række der kan vise data fra en database.

Læs mere om ADF på http://www.oracle.com/technology/products/jdev/index.html under 'Oracle ADF --> Online tour'

15.8.2 Apache MyFaces

Apache MyFaces er en samling JSF-komponenter med Åben Kildekode (Open Source).

Se en række eksempler på MyFaces-komponenter her (klik på Examples og Components).Prøv f.eks. komponenterne File Upload, Calendar, HTML Editor og Tree.

Der er ca. 25 komponenter og validatorer. Kør selv den nyeste udgave af eksemplerne (de findes også i en simplere udgave, der er lettere at forstå) for at se alle komponenterne.

WAR-filen kan køres direkte i Tomcat (smid den i webapps/) eller fra JDeveloper (opret projekt fra WAR-fil). Du starter eksemplerne ved at køre 'index.jsp'.

Yderligere læsning

MyFaces' hjemmeside: http://myfaces.org/ (nyeste udgave er på http://myfaces.apache.org/).

MyFaces med JDeveloper

Som det fremgår af

http://www.oracle.com/technology/products/jdev/101/howtos/myfaces/index.html kan man desværre ikke installere MyFaces i JDevelopers komponentpalette i betaudgaven:

”In the JDeveloper 10.1.3 Developer Preview developers are restricted in that they cannot switch out the provided JSF implementation with another implementation such as MyFaces. In the production release of JDeveloper 10.1.3 developers will be able to switch out the by default provided RI and use a JSF implementations of their choice.”

Man kan dog sagtens køre og redigere MyFaces-komponenter.

15.8.3 Andre kilder

15.9 EL - Expression Language

Værdier fra variabler og regneudtryk skal i JSF puttes ind i et #{}-udtryk (i JSTL er det ${}), som er en måde at gøre brug af EL - Expression Language.

EL er et elegant sprog, der gør det muligt, at skrive ret lange Java-udtryk på kort form.

Således kan knudrede Java-udtryk, som f.eks.:

Velkommen <%= ((Bruger)session.getAttribute("bruger")).getNavn() %> !

med EL skrives som blot (xxx tjek):

Velkommen ${session.bruger.navn} !

Det skyldes, at EL har en meget fleksibel punktum-notation, der automatisk undersøger egenskaber på javabønner og gennemsøger attributter på implicitte objekter og andre nøgleindekserede objekter (hashtabeller).

15.10 Om associative tabeller (HashMap)

Xxx råtekst fra andre bøger - skal kortes ned

En hashtabel er en tabel, der afbilder nogle nøgler til værdier. Hashtabeller er nyttige som associative afbildninger - når man vil indeksere nogle objekter ud fra f.eks. navne.

Man opretter en hashtabel med:

  HashMap tabel = new HashMap();

Derefter kan man lægge en indgang i tabellen med put( nøgle, værdi ). F.eks.:

  tabel.put("abc", "def");

husker strengen "def" under nøglen "abc". Vil vi finde strengen frem igen, skal vi slå op under "abc":

  String værdi = (String) tabel.get("abc");

Da hashtabeller oftest anvendes til at lave afbildninger med, bruger man i dagligdags sprogbrug mere ordet 'hashtabel' end ordet 'afbildning'.

Før vi går videre, så bemærk lige, at lister går fra heltal til objekter, dvs. man finder listens elementer frem ud fra et helt tal (indekset). Blandt andet har en liste metoderne:

void add( int indeks , element )
Indsætter element i listen lige før plads nummer indeks. Første element er på plads nummer 0.

Elementtype get(int indeks)
returnerer en reference til objektet på plads nummer indeks.

Man kan sige, at elementerne i en liste indekseres (fremfindes) ud fra et tal.

Hashtabeller går fra objekter til objekter på den måde, at til hvert element knyttes et nøgle-objekt. Elementerne kan derefter findes frem ud fra nøglerne.

Man kan altså sige, at elementerne i en hashtabel indekseres (fremfindes) ud fra et objekt.

java.util.HashMap - nøgleindekseret tabel af objekter

Konstruktører

HashMap<Nøgletype, Elementtype> ()
opretter en tom tabel hvor nøglerne er af klassen Nøgletype og værdierne af klassen Elementtype. <Nøgletype, Elementtype> kan udelades.

Metoder

void put (Nøgletype nøgle, Elementtype værdi)
føjer objektet værdi til hashtabellen under objektet nøgle.

Elementtype get (Nøgletype nøgle)
slår op under nøgle og returnerer den værdi, der findes der (eller null hvis nøglen ikke kendes).

Elementtype remove(Nøgletype nøgle)
fjerner indgangen under nøgle og returnerer værdien (eller null hvis nøglen ikke kendes).

boolean isEmpty()
returnerer sand, hvis tabellen er tom (indeholder 0 indgange).

int size()
returnerer antallet af indgange.

boolean containsKey(Nøgletype nøgle)
returnerer sand, hvis nøgle findes blandt nøglerne i tabellen.

boolean containsValue(Elementtype værdi)
returnerer sand, hvis værdi findes blandt værdierne i tabellen.

Set<Nøgletype> keySet()
giver alle nøglerne. Kan bruges til at gennemløbe alle indgangene (se nedenfor).

String toString ()
giver tabellens indhold som en streng. Dette sker ved at konvertere hver af indgangenes nøgler og værdier til strenge.

Herunder opretter vi en tabel, der holder styr på fødselsdatoer for et antal personer med deres fornavne som nøgler, med put()-metoden: put("Jacob", dato). Derefter kan indgangene hentes tilbage igen med get()-metoden: get("Jacob") giver Jacobs fødselsdato.

Sidst gennemløbes alle indgangene. Vi bruger en for-løkke til at løbe gennem tabellens nøgler (med hashtabel.keySet()), hvorefter vi slår de tilsvarende værdier op2.

import java.util.*;
public class BenytHashMap
{
  public static void main(String[] arg)
  {
    // En tabel med strenge som nøgler og Date-objekter som værdier
    HashMap<String,Date> hashtabel = new HashMap<String,Date>();
    Date dato = new Date(71,0,1); // 1. januar 1971
    hashtabel.put("Jacob",dato);
    hashtabel.put("Troels",new Date(72,7,11)); // 11. august 1972
    hashtabel.put("Eva",new Date(73,2,5));
    hashtabel.put("Ulla",new Date(69,1,9));
    System.out.println( "tabel indeholder: "+hashtabel );

    // Lav nogle opslag i tabellen under forskellige navne
    dato = hashtabel.get("Troels");
    System.out.println( "Opslag under 'Troels' giver: "+dato);
    System.out.println( ".. og under Jacob: "+hashtabel.get("Jacob"));
    System.out.println( ".. Kurtbørge: "+hashtabel.get("Kurtbørge"));
    System.out.println( ".. Eva: "+hashtabel.get("Eva"));

    // Gennemløb af alle elementer
    for (String nøgle : hashtabel.keySet()) {
      dato = hashtabel.get(nøgle);
      System.out.println(nøgle + "'s fødselsår: "+dato.getYear());
    }
    //JDK1.4: for (Iterator i = hashtabel.keySet().iterator(); i.hasNext();) {
      //JDK1.4: String nøgle = (String) i.next();
  }
}

tabel indeholder: {Jacob=Fri Jan 01 00:00:00 CET 1971, Troels=Fri Aug 11 00:00:00 CET 1972, Eva=Mon Mar 05 00:00:00 CET 1973, Ulla=Sun Feb 09 00:00:00 CET 1969}
Opslag under 'Troels' giver: Fri Aug 11 00:00:00 CET 1972
.. og under Jacob: Fri Jan 01 00:00:00 CET 1971
.. Kurtbørge: null
.. Eva: Mon Mar 05 00:00:00 CET 1973
Jacob's fødselsår: 71
Troels's fødselsår: 72
Eva's fødselsår: 73
Ulla's fødselsår: 69

En hashtabel husker ikke rækkefølgen af indgangene. Derfor er rækkefølgen, som elementerne bliver udskrevet i, ikke den samme som den rækkefølge, de blev sat ind i.

Her er en lille esperanto-dansk-ordbog. Nøglerne er esperanto og værdierne er danske ord:

import java.util.*;
public class BenytHashMapOrdbog
{
  public static void main(String[] args)
  {
    HashMap<String,String> ord = new HashMap<String,String>();
    ord.put("granda", "stor");
    ord.put("longa", "lang");
    ord.put("bela", "smukt");
    ord.put("estas", "er");

    String esperantotekst = "longa, granda hundo estas.... bela!";

    for (String eoOrd : esperantotekst.split("\\b")) { // split efter ordgrænser
      String da = ord.get( eoOrd ); // slå esperantoord op og få det danske ord
      if (da == null) da=eoOrd;  // hvis intet fundet lader vi det stå uoversat
      System.out.print( da );
    }
  }
}

lang, stor hundo er.... smukt!

Har vi en tekst på esperanto, kan vi nu oversætte teksten ord for ord til dansk. Hvert ord slås op i hashtabellen og hvis det findes, erstattes det med det danske ord. Tegn og ord, som ikke kan findes i tabellen (såsom "hundo", der betyder "hund"), efterlades uforandret.

1JSP med JSTL kan minde om sproget Coldfusion fra Macromedia/Allaire

2Bruger du JDK 1.4 eller tidligere skal du fjerne <String,Date> fra new HashMap og bruge en iterator, som skitseret i kommentaren nederst. Iterator-objekter har to metoder: hasNext(), der fortæller, om der er flere elementer og next(), der går videre til næste element og returnerer det.

javabog.dk  |  << forrige  |  indhold  |  næste >>  |  programeksempler  |  om bogen
http://javabog.dk/ - Webprogrammering med Java Server Pages af Jacob Nordfalk.
Licens og kopiering under Åben Dokumentlicens (ÅDL) hvor intet andet er nævnt (72% af værket).

Ønsker du at se de sidste 28% af dette værk (275315 tegn) skal du købe bogen. Så får du pæne figurer og layout, stikordsregister og en trykt bog med i købet.