I dette kapitel finder du rettelser og tilføjelser til den trykte bog (rettelserne er ført ind på http://javabog.dk). Du kan udskrive kapitlet og gemme bagest i din bog.
I afsnit 3.3, Appendiks: Typer af formularfelter, ret (tak til Klaus Elmquist Nielsen):
<input type="hidden"> |
Skjult felt. Vises for brugeren, men alligevel har en værdi, se afsnit 3.6.2, Skjulte felter i formularer. |
Til:
<input type="hidden"> |
Skjult felt. Vises ikke for brugeren, men har alligevel en værdi, se afsnit 3.6.2, Skjulte felter i formularer. |
I log_ind.jsp i afsnit 9.5.3, Login-siden, ret:
<font color="red"> <% if (login.isLoggetInd()) {
Til:
<font color="red"> <% login.tjekLogin(); if (login.isLoggetInd()) {
I VekslerBean.java i afsnit 12.2.2, Eksempel: Veksler, ret:
System.out.println("dollarTilEuro("+dollar+euro+") kaldt!");
Til:
System.out.println("dollarTilEuro("+dollar+") kaldt!");
En række steder i kapitel 11 og kapitel 12 skal linjen
public double euroTilDollar(int euro)
i Veksler-klassen rettes til
public double euroTilDollar(double euro)
side 227, afsnit 11.7, punkt 1 i listen:
XML kræver at alle attributter skal være i "..", hvoraf
<motor hk=100 />
skal være
<motor hk="100" />
Afsnit 3.7.6 Sende mere data til klienten løbende og de tre efterfølgende afsnit.
Afsnit 5.8.6 Metadata og afsnit 5.8.7 Eksempel: Webgrænseflade til database.
Kapitel 15 om Java Server Faces.
Nogen gange kan en anmodning tage lang tid at fuldføre. Det kan f.eks. være en krævende operation eller et indviklet databaseopslag.
I sådanne tilfælde vil brugeren opleve at siden tager utrolig lang tid at indlæse. Da er det hensigtsmæssigt at sende noget af svaret på anmodningen, f.eks. titel og overskrift på siden, gerne nogle instruktioner eller forbehold for hvordan det efterfølgende resultat (når det kommer) skal læses.
I andre tilfælde kommer der løbende data som klienten skal se efterhånden som de dukker op.
Man tvinger serveren tømme sine interne buffere og sende al data til klienten ved at kalde
out.flush();
Derved sendes HTTP-hovedet1 og det, der indtil videre er skrevet til out-objektet.
Her er eksemplet Syvtabellen fra afsnit 2.2.1 skrevet sådan at der går et sekund mellem hver linje:
<html>
<head><title>Syvtabellen langsomt</title></head>
<body>
<p>Her er syv-tabellen:<br>
<%
for (int i=1; i<=10; i++)
{
out.flush(); // tøm interne buffere, sådan at data sendes til klienten
Thread.sleep(1000); // vent et sekund
%>
Syv gange <%= i %> er: <%= 7*i %>.<br>
<%
}
%>
</p>
</body>
</html>
Det følgende eksempel følger med i Tomcats logfil (logs/catalina.out) og opdaterer hvert sekund siden med de nyeste oplysninger fra logfilen.
<html> <head><title>Serverlog</title></head> <body> <h1>Webserverens logfil</h1> Det følgende er det nyeste fra webserverens logfil.<br> Hvert sekund opdateres siden hvis der kommer mere i loggen, i de næste 10 minutter. <pre> <% String filnavn = "logs/catalina.out"; // sti til Tomcats logfil long glFilLgd = 0; // hvor mange byte filen fylder byte[] buf = null; // en databuffer java.io.RandomAccessFile fil = null; // ... og selve filen for (int i=0; i<600; i++) // gennemløb 60 sekunder * 10 minutter try { Thread.sleep(1000); // vent et sekund fil = new java.io.RandomAccessFile(filnavn,"r"); // åbn filen if (glFilLgd < fil.length()) // har længden ændret sig? { if (glFilLgd==0) glFilLgd = fil.length()-1500; // læs sidste 1500 tegn int bufLgd = (int) (fil.length() - glFilLgd); if (buf==null || bufLgd > buf.length) buf = new byte[bufLgd]; fil.seek(glFilLgd); fil.read(buf,0,bufLgd); String tekst = new String(buf,0,bufLgd); out.println("---- lgd="+fil.length()+" tid="+new java.util.Date()+" ----"); out.write(tekst); out.flush(); // tøm interne buffere, sådan at data sendes til klienten glFilLgd = fil.length(); } } finally { fil.close(); } %> </pre> Slut. <br> Vil du se mere af logfilen må du genindlæse siden. </body> </html>
Bemærk at det kan være en sikkerhedsrisiko at kunne følge med serverloggen (her kan ubetænksomme programmører f.eks. komme til at logge brugernavne og adgangskoder som andre helst ikke skal have adgang til).
Under udviklingen af en webapplikation, der bruger en database, kan det være rart med en webbaseret grænseflade til databasen som man kan skrive SQL-kommandoer ned i eller lave forespørgsler med.
<%@ page language="java" import="java.sql.*" %> <html> <head><title>Webgrænseflade til database</title></head> <body> <h1>SQL-grænseflade til databasen</h1> Herunder kan du skrive SQL-kommandoer. Adskil kommandoer med ; <form method="post"> <textarea name="sql" rows="8" cols="70">SELECT * FROM kunder </textarea> <input type="submit" name="udf" value="Udfør SQL!"> </form> <% // Se om der kommer nogle SQL-kommander der skal behandles String sql = request.getParameter("sql"); Connection con = null; Statement stmt = null; if (sql != null) { Class.forName("com.mysql.jdbc.Driver"); con = DriverManager.getConnection("jdbc:mysql:///test"); stmt = con.createStatement(); String[] kommandoer = sql.split(";"); // opdel i kommandoer efter skilletegn ; for (int k=0; k<kommandoer.length; k++) try { String kom = kommandoer[k].trim(); if (kom.length()==0) continue; // videre til næste linje out.println("<hr>Udfører '"+kom+"':<br>"); if (kom.toUpperCase().startsWith("SELECT")) { ResultSet rs = stmt.executeQuery(kom); ResultSetMetaData rsmd = rs.getMetaData(); int antalKolonner = rsmd.getColumnCount(); out.println("<table border='2'><tr>"); for (int i=1; i<=antalKolonner; i++) out.println("<th>"+rsmd.getColumnName(i)+"</th>"); out.println("</tr>"); // udskriv cellerne i hver række while (rs.next()) { out.println("<tr>"); for (int i=1; i<=antalKolonner; i++) out.println("<td>"+rs.getString(i)+"</td>"); out.println("</tr>"); } out.println("</table>"); rs.close(); } else { int ret = stmt.executeUpdate(kom); out.println("Returkode: "+ret); } } catch (Exception e) { out.println("Der skete en fejl: "+e); e.printStackTrace(); } stmt.close(); con.close(); } %> </body> </html>
Tillægskapitel til ”Webprogrammering med JSP”
Jacob Nordfalk
1Og derved kan man så ikke mere foretage omdirigeringer, j.v.f. afsnit 3.7 og afsnit 4.3.