PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : JSP: konkurrierende Aufrufe sequentiell bedienen


MeLLe
2005-11-21, 14:59:26
Liebe Gemeinde,

folgende Konstruktion sei gegeben:

a) eine JSP-Seite, die - durch URL-Parameter gefüttert - eine Datenbank durchwühlt und die Daten dann als Bild an den Browser zurückgibt

b) eine weitere JSP-Seite, die HTML-Code an den Browser gibt und die mehrere Bilder enthält, die von a) generiert werden, und die via <img src="xyz.jsp?param1=value1"> eingebunden sind.

Seite b) ist (im Browser-Quellcode) sauber, d.h. die Bilder werden wunderbar via <img...>-Tag eingebunden und enthalten im src-Teil jeweils durch die Parameter verschiedene Quellen.
Leider gibt mir mein Browser manchmal mehrfach das gleiche Bild nacheinander aus, wohl aus dem Grund, weil die Objekte statisch im Webserver vorhanden bleiben und bei schnellem Aufruf der Seite a) die "falschen" Daten benutzt werden, statt dass in einem eigenen Context auf "neue" Daten zugegriffen wird.

Wie kann ich nun JSP dazu bringen, bei jedem Aufruf einen neuen Context zu benutzen, bzw. wie kann ich JSP dazu bringen, bei mehrfachem Aufruf einer Seite auf die Beendigung und Bedienung des vorhergehenden Requests zu warten?

Danke!

Demirug
2005-11-21, 15:43:32
Ich verstehe da ein kleines Detail nicht. Wird durch die Parameter in der URL nicht fest ein bestimmtes Bild eindeutig in der Datenbank referenziert?

mithrandir
2005-11-21, 15:52:08
Kannst ja ruhig auch mal Code posten.

Abnaxos
2005-11-21, 16:25:02
folgende Konstruktion sei gegeben:

a) eine JSP-Seite, die - durch URL-Parameter gefüttert - eine Datenbank durchwühlt und die Daten dann als Bild an den Browser zurückgibt


Aua! Das ist keine Aufgabe für eine JSP. Generell sollte man immer zuerst ein Servlet verwenden, das die Programmlogik ausführt und dann erst für die Ausgabe des Ergebnisses den Request an eine JSP weiterleiten. Binäre Daten wie Bilder sind sowieso nichts für JSPs.

Zusätzlich empfiehlt es sich, sämtliche Requests von einem einzigen Servlet "routen" zu lassen. Das mag bei einer Mini-Applikation allerdings Overkill sein.

Seite b) ist (im Browser-Quellcode) sauber, d.h. die Bilder werden wunderbar via <img...>-Tag eingebunden und enthalten im src-Teil jeweils durch die Parameter verschiedene Quellen.
Leider gibt mir mein Browser manchmal mehrfach das gleiche Bild nacheinander aus, wohl aus dem Grund, weil die Objekte statisch im Webserver vorhanden bleiben und bei schnellem Aufruf der Seite a) die "falschen" Daten benutzt werden, statt dass in einem eigenen Context auf "neue" Daten zugegriffen wird.

Ich bin mir jetzt nicht sicher, was du mit "statisch im Webserver vorhanden" meinst. Ich vermute mal, die JSP a liest das Bild aus der DB, schreibt es in ein Verzeichnis, von wo es der Web-Server an den Client weitergibt. Das ist natürlich zum Scheitern verurteilt, da hier, wie du vermutest, der Cache des Web-Servers greift.

Gib die Bilder direkt via Servlet an den Browser zurück:

// imageInput sei der Stream, aus dem die Image-Daten
// eingelesen werden, z.B. aus einem ResultSet

// Achtung: Sicherstellen, dass ein BufferedInputStream
// vorgeschaltet ist, sonst wird das fürchterlich ineffizient!

response.setContentType("image/jpeg");
// "image/jpeg" durch den korrekten Content-Type ersetzen
OutputStream output = response.getOutputStream();
int b;
while ( (b=imageInput.read()) != -1 ) {
output.write((byte)b);
}

// Fehlerbehandlung und Aufräumen (Streams etc. schliessen) nicht vergessen

Ich hoffe, ich habe dich jetzt nicht komplett falsch verstanden ... ;)

MeLLe
2005-11-21, 18:44:59
Zuallererst mal danke für die rege Beteiligung.
Ich glaube ich habe mich etwas missverständlich ausgedrückt, denn so richtig passt keine Antwort auf mein Problem ;)

Aber das ist wohl mein Fehler, deswegen nochmal etwas detaillierter:

JSP-Seite A (show_stats.jsp) schaut schematisch so aus:
...

OracleCachedRowSet rsStat = JdbcConnect.getOracleCachedRowSet("SELECT
DISTINCT moduser FROM stat_verladung WHERE ...");

while (rsStat.next())
{
%>
<IMG SRC="get_graph.jsp?moduser=<%=rsStat.getString(1)%>"><BR>
<%
}

...

Seite B (get_graph.jsp) dazu dann so ähnlich:
...

String moduser = request.getParameter("moduser");
OracleCachedRowSet rsStat = JdbcConnect.getOracleCachedRowSet("SELECT * FROM stat_verladung WHERE moduser='" + moduser + "' ...");

BufferedImage imgTemp = new BufferedImage(800, 320, BufferedImage.TYPE_RGB);
Graphics g = imgTemp.CreateGraphics();

while (rsStat.next())
{
g.setColor(Color.red);
g.drawRect(...rsStat.getXXX()...);
g.setColor(Color.blue);
g.drawText(...rsStat.getXXX()...);
}

response.setContentType("image/png");
OutputStream outStream= response.getOutputStream();
ImageIO.write(imgTemp, "png", outStream);
outStream.close();

...


Sol heissen, ich schiebe keine Bilddaten aus der DB an den Browser, sondern erzeuge mir auf Basis des übergebenen Parameters als Kriterium einer DB-Query einen kleinen Graph aus den in der DB abgelegten Daten, den ich dann als Image an den Browser zurückgebe.

Soweit so klar? ;)

Achso, JdbcConnect ist ne kleine Hilfsklasse, die den DB-Zugriff kapselt. Ist hier aber nicht von Belang, nur der Vollständigkeit halber sei's erwähnt.

Abnaxos
2005-11-21, 19:29:52
Aha. OK. Das sollte so, wie du es beschrieben hast, funktionieren, ich wüsste nicht, warum nicht. Daran, dass du vor allem für das Bild keine JSPs sondern Servlets verwenden solltest, ändert sich dadurch jedoch nichts (merke: Scriptlets sind pöhse und habe in einer JSP nichts zu suchen, schon gar keine DB-Abfragen). :)

Mit welchem Browser tritt das Problem auf? Lässt es sich auch mit anderen Browsern reproduzieren? Ich frage deshalb, weil dein Browser möglicherweise die Bilder fälschlicherweise cached, weil sie dieselbe URI haben.

In dem Fall könnte wiederum ein Servlet helfen, indem man die Parameter in die URI verlegt, also sowas: get_graph/<moduser> statt get_graph.jsp?moduser=<moduser>. Damit hätte das Bild für jeden "moduser" eine eigene URI und kein Browser dieser Welt käme auf die Idee, das zu cachen. Das ist allerdings ein Schuss ins Blaue ... ;)

Damit, dass da mehrere Requests gleichzeitig ankommen werden, hat dein Problem jedenfalls nichts zu tun, nicht aufgrund des Codes, den du gepostet hat.

MeLLe
2005-11-22, 13:02:40
Habe mein Problem geklärt ... lag an mir ... oder einer (mir unbekannten) Eigenart von JSP.

Der Kopf der JSP-Seiten hatte ich so gestaltet:

<%@ page import="java.io.*" %>
<%@ page import="java.sql.*" %>
<%@ page import="java.util.*" %>

<%!
// Deklarationen
...

String moddate = null;
String moduser = null;
String stattype = null;
%>

<html>

<html>
<head>
<META HTTP-EQUIV="Expires" CONTENT="0">
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="cache-control" CONTENT="no-cache">
<title>verladung</title>
</head>
<body style="font-family:verdana;text-align:center;">

<%
// Rest der Logik der JSP-Seite folgt ...

try
{
...
}
....
%>
</body>
</html>

Dadurch, dass die Variablen, die die Parameter aufnehmen sollten, im oberen Konstrukt untergebracht waren, hat er die sich quasi-static "gemerkt". In dieser Art

<%@ page import="java.io.*" %>
<%@ page import="java.sql.*" %>
<%@ page import="java.util.*" %>

<html>

<html>
<head>
<META HTTP-EQUIV="Expires" CONTENT="0">
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="cache-control" CONTENT="no-cache">
<title>verladung</title>
</head>
<body style="font-family:verdana;text-align:center;">

<%
// Deklarationen
...

String moddate = null;
String moduser = null;
String stattype = null;


// Rest der Logik der JSP-Seite folgt ...

try
{
...
}
....
%>
</body>
</html>

klappt die Sache wunderbar! Danke euch allen, trotzdem :)

Köppchen
2005-11-22, 22:40:49
Statisch sind deine Variablen dadurch nicht. Das ! sorgt dafür das die Variablen zur Instanz des Servlet gehören (aus einer JSP wir halt immer ein Servlet).
Die Servlet Engine darf aber mit einem Servlet mehrere Requests gleichzeitig ausführen. Das führt in folge zu dem was du beschrieben hast.

Du solltest übrigens noch was an deinem SQL Konstrukt tun.
Besser wäre es ein Prepared Statement zu verwenden und die Parameter an das prepared Statement zu übergeben. So wie du das SQL Statement beschrieben hast riskierst du SQL Injections. Schau dir mal den Artikel bei Wikipedia dazu an: http://de.wikipedia.org/wiki/SQL-Injection


Gruß Markus

MeLLe
2005-11-23, 22:32:40
Das war ich doch mit "quasi-static" gar net so schlecht in der Formulierung ;)

Danke für die erleuchtende Erklärung, jetzt machts gut Sinn und die Entwicklung schreitet gut voran - ich kann mich nun ganz den DB-Selects und -Procedures hingeben, jetzt wo das JSP-Framework steht.
Danke auch für den Tipp in Sachen SQL-Injections - aber da bin ich hoffentlich auf der sicheren Seite. Zumindest kann ich mir kein Szenario für mein SQL-Konstrukt ausmalen, wo eine Injection erfolgreich sein würde. Und das wichtigste - unser Intranet, wofür das ganze entwickelt wird, wird nur intern und nur von gewissenhaften, einfach gestrickten "normalo-PC-Usern" genutzt, denen "SQL" nur als wirre Buchstabenfolge erscheint ;)