MokaByte
Numero 28 - marzo 1999
|
|||
|
Ms Access e Ms IIS |
||
Martino Pezzoli |
|
||
Introduzione
Le versioni dei
prodotti SUN utilizzate per lo sviluppo sono JDK 1.1.6 , JDBC 1.2 , JDSK
1.2 , tutte scaricabili gratuitamente dal sito http://www.java.sun.com/products/
<html>
<script language="JavaScript">
// controlla la corretezza dei dati inseriti e chiama il Servlet function testForm() { if (document.forms[0].snumber.value=="") { document.forms[0].snumber.value="0"; } if (document.forms[0].snumber.value>"0" && document.forms[0].snumber.value<"9999") { }
else document.forms[0].snumber.value="0";
if (document.forms[0].code.value=="") { alert("Insert a valid Table code.") } if (document.forms[0].code.value!="") { document.forms[0].action="http://localhost:8000/servlet/SqlServlet" } }
</script>
<form method=POST onSubmit="return
testForm()">
<CENTER> <BR><BR>Table <input type=text name=code size=15 maxlength=15>
<BR><BR>Serial Number <input type=text name=snumber size=5 maxlength=5>
<BR><BR><BR><input type=submit value="Submit"> <input type=reset value=Reset> </CENTER></form> </body> </html> Bisogna innanzi
tutto inserire la voce relativa alla "fontedati" ODBC andando in pannello
di controllo, ODBC (Open DataBase Connectivity).
Ora cominciamo con la parte Servlet, questi come sappiamo sono "programmi" (classi invocate da JVM) che girano su Web Server in attesa di richieste da parte di qualche client. In altre parole il programma (che vedremo) deve essere lanciato sul Server e interagirà con esso spedendogli in modalità GET o POST i dati di FORM HTML. Per poter eseguire delle classi Servlet occorre avere un supporto che quasi tutti gli web server hanno. Purtroppo l' IIS di Microsoft non l' ha, in questo caso si può utilizzare un prodotto di terze parti, come quello che io ho utilizzato JRun della LiveSoftware http://www.livesoftware.com , del quale è possibile scaricare una versione trial. Esiste anche un tool freeware compreso in JSDK di SUN è il ServletRunner.exe posto nella cartella "bin". Questo simula un web server per poter provare e fare il debug dei propri servlets e si deve lanciare localmente. Più informazioni si possono trovare tra i documenti html compresi nell' installazione del Kit. Per chi non volesse
o non potesse usare le Servlets basterà sostituire la parte relativa
ad esse con il metodo main(). Piuttosto di generare la pagina HTML fare
un system.out.println(….) su consolle e lanciare il bytecode generato con
il tool compreso in JDK nel seguente modo "java nome.class" per poter visualizzare
il risultato della query SQL (Structured Query Language). Questo dimostra
quanto la soluzione servlet sia efficiente ed applicabile utilizzando classi
sviluppate non appositamente per le servlet ; ancora l' implementazione
di un servlet utilizzando classi già esistenti e funzionanti (cioè
testate) può risultare abbastanza banale.
Qui sotto è
inserito la parte di codice relativo alla gestione Servlet. Al metodo SqlDB,
che eseguirà il passo successivo della richiesta, gli vengono passate
le informazioni sulla comunicazione (req), il destinatario (toClient) e
l' elenco dei parametri passati (values). La connessione viene aperta una
sola volta al DB nel metodo init() e chiusa nel metodo destroy(); inoltre
viene gestita la concorrenza sull' accesso al DB in modo che un solo client
alla volta utilizzi il "canale" di connessione, in questo modo l' accesso
risulta più veloce, sicuro e controllato.
import javax.servlet.*; // necessari per ottenere la disponibilità delle classi Servlet import javax.servlet.http.*; public class SqlServlet extends
HttpServlet {
PrintWriter toClient; // destinazione del client in output Enumeration values; // elenco dei parametri passati in output
DrvMsAccess Sqlac; // istanzia fittizia per aprire il DBase
SQL
/* * Inizializza il Servlet Overriding del metodo init(), * viene chiamato solo all' apertura della Servlet */ public void init(ServletConfig config) throws ServletException { super.init(config); Sqlac = new DrvMsAccess("NomeFonteDati");
}
/* * Funzione che intercetta le richieste e risponde alla FORM html * Overriding del metodo doPost() */ public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // negozia il MIME per pagine HTML "content type" //header of the response res.setContentType("text/html"); // recupera il "nome" come PrinterWriter del //client che ha eseguito la richiesta. toClient = res.getWriter(); // parametri passati dalla form
values = req.getParameterNames();
// evade la richiesta del client, esegue la logica utente SqlDB aaa = new SqlDB(req, toClient, values);
aaa.run();
} // end doPost()
/* * Funzione rchiesta dalla FORM html * Overriding del metodo doGet() */ public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // negozia il MIME per pagine HTML "content type" //header of the response
res.setContentType("text/html");
// recupera il "nome" del client che ha eseguito la richiesta.. toClient = res.getWriter();
values = req.getParameterNames();
// evade la richiesta del client sqlDB aaa = new SqlDB(req, toClient, values);
aaa.run();
} // end doGet()
/* * Overriding -distrugge il servlet */ public void destroy() { Sqlac.CloseCon(); // chiusura connessione DB SQL } // end destroy() } // end Class SqlServlet Ora vediamo come estrarre i dati richiesti dal client con la FORM, formattarli in una pagina HTML e rispedirli al richiedente. La cosa è molto semplice bisogna prima estrarre i valori delle variabili per la ricerca (contenuti nella struttura di enumerazione values), lanciare la query SQL istanziando la classe DrvMsAccess e da ultimo formattare una semplice pagina HTML. Quando eseguiremo la close del PrinterWriter i dati, così preparati, verranno spediti al richiedente senza che noi dobbiamo preoccuparcene. * * classe per SERVIZIO accesso al DBase SQL tramite ODBC */
class SqlDB {
// Sincronizzazione dell' Handler Thread //per la concorrenza sulla risorsa "con" // static perchè è unica a fronte di più istanze della stessa classe
static Object critsect = new Object(); // oggetto generico
String query = new String(); // codice distinta in input con valore di default String Code = new String("?"); // matricola in input con valore di default
Integer SNumber = new Integer(0);
PrintWriter toClient; // destinazione del client Enumeration values; // elenco dei parametri passati
HttpServletRequest req; // definisce la richiesta client
/* * Costruttore classe estrazione dati richiesti */
public SqlDB(HttpServletRequest req, PrintWriter toClient, Enumeration
values) {
this.req=req; this.values=values; this.toClient=toClient;
} // end SqlDB()
/* * Overloading del metodo run() se la classe extend Thread */ public void run() { // estrae i parametri di input da passare nella query SQL ExtractInput(); // estrae parametri passati ed esegue la chiamata di accesso DB PrepareQuery(); // Sincronizzazione dell' accesso alla risorsa "con" // per evitare risultati e/o errori indesiderati synchronized (critsect) { // istanzia la classe driver per ODBC MsAccess DrvMsAccess Sqlac = new DrvMsAccess("NomeFonteDati"); Sqlac.ExecStmt(query); WriteHtml(Sqlac); // compone l' HTML da restituire al client richiedente Sqlac.CloseStmt(); // reset statement query SQL
} // fine sincronizzazione
} // end run()
/* * Estrazione da outstream parametri * passati dalla form (doPost) o dalla richiesta (doGet) */
public void ExtractInput() {
// estrae i parametri passati dalla form dall' outstream while(values.hasMoreElements()) { String name = (String)values.nextElement(); //String value = req.getParameterValues(name)[0]; if (name.compareTo("code") == 0) { // codice distinta Code = req.getParameterValues(name)[0]; } if (name.compareTo("snumber") == 0) { // matricola SNumber = new Integer(req.getParameterValues(name)[0]); } }
} // end ExtractInput()
/* * Estrazione da outstream parametri passati dalla form (doPost) o * dalla richiesta (doGet) */
public void PrepareQuery() {
query = "SELECT DISTINTE.Pos, DISTINTE.codPezzo, PEZZI.descITA, " + "PEZZI.UM, DISTINTE.Qta, DISTINTE.DA, DISTINTE.A " + "FROM PEZZI INNER JOIN DISTINTE ON PEZZI.codPezzo = DISTINTE.codPezzo " + "WHERE (DISTINTE.codTavola='" + Code.toUpperCase() + "'"; if (SNumber.intValue() != 0) { query = query + ") AND (DISTINTE.DA<=" + SNumber.intValue() + ") AND (DISTINTE.A>=" + SNumber.intValue(); }
query = query + ")";
} // end ExtractData()
/* * Scrittura pagina HTML da inviare al Client */
void WriteHtml(DrvMsAccess Sqlac) {
// Respond to client with a thank you toClient.println("<html>");
toClient.println("<title>Dati MsAccess</title>");
toClient.println("<CENTER><TABLE BORDER=1>"); toClient.println("<TR><TD><H3>"+ Code.toUpperCase()+" S/N "+SNumber.intValue()+ "</H3></TD></TR>"); toClient.println("</TABLE><HR WIDTH=80%><BR>"); toClient.println("<TABLE BORDER=1>"); try { int numberOfColumns = Sqlac.rsmd.getColumnCount(); while (Sqlac.rs.next()) { toClient.print("<TR>"); for (int i = 1; i <= numberOfColumns; i++) toClient.print("<TD><H5>" + Sqlac.rs.getString(i)+"</H5></TD>"); toClient.println("</TR>"); } } catch(SQLException ex) { System.err.print("SQLException: "); System.err.println(ex.getMessage());
}
toClient.println("</TABLE></CENTER>");
toClient.println("</html>");
// Close the writer; the response is done.
toClient.close();
} // end WriteHtml()
} // end Class SqlDB Come ultima parte
di codice vediamo la classe DrvMsAccess che permette di reperire i dati
da un data base tramite connessione ODBC; il costruttore della classe richiede
la "fonte dati ODBC" per aprire la connessione, poi chiamando il metodo
CreateStmt("stringa QUERY SQL" ) verrano estratti i dati. Come si può
notare nel codice precedente una volta istanziata la classe bisogna richiamare
il metodo CloseStmt() per chiudere lo statement SQL in modo da non lasciarlo
appeso e ritrovarsi con un SQL Exception.
import java.io.*; import java.util.*; import java.sql.*;
public class DrvMsAccess {
// static perchè è unica (globale) a fronte di più istanze della classe static String fonte; // fontedati ODBC in input static Connection
con; // driver di connessione JDBC
String query; // query SQL in input Statement stmt; // prepare statement SQL ODBC ResultSet rs; // risultato della chiamata SQL in output (Dati) ResultSetMetaData
rsmd; // caratteristiche dei dati in output
/*
* Costruttore di classe appertura connessione */ public DrvMsAccess(String
fonte) {
try { // se la connection è close open connessione if ((con == null) || (con.isClosed())) { // fonte dati ODBC this.fonte=fonte; // definisco tipo e fonte dati String url = "jdbc:odbc:" + fonte; Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") Con = DriverManager.getConnection(url);
}
} catch (SQLException ex) { System.out.println ("\n*** SQLException catturata ***\n"); while (ex != null) { System.out.println ("SQLState: " + ex.getSQLState ()); System.out.println ("Message: " + ex.getMessage ()); System.out.println ("Code: " + ex.getErrorCode ()); ex = ex.getNextException (); System.out.println (""); }
} // errori SQL
catch (Exception e) { e.printStackTrace();
} // errori generici
}
// end DrvMsAccess()
/* * Esegue la query SQL - è richiesto la stringa della query e della fonte dati */ public void ExecStmt(String query) {
this.query=query;
try { stmt = con.createStatement(); // prepare dello statement rs = stmt.executeQuery(query); // esegue statment e restituisce i dati
rsmd = rs.getMetaData();
} catch(SQLException ex) { System.out.println ("\n*** SQLException catturata ***\n"); while (ex != null) { System.out.println ("SQLState: " + ex.getSQLState ()); System.out.println ("Message: " + ex.getMessage ()); System.out.println ("Code: " + ex.getErrorCode ()); ex = ex.getNextException (); System.out.println (""); }
}
} // end ExecStmt()
/* * Chiusura statement SQL */ public void CloseStmt() { try { rs.close();
stmt.close();
} catch(SQLException ex) { System.out.println ("\n*** SQLException catturata ***\n"); while (ex != null) { System.out.println ("SQLState: " + ex.getSQLState ()); System.out.println ("Message: " + ex.getMessage ()); System.out.println ("Code: " + ex.getErrorCode ()); ex = ex.getNextException (); System.out.println (""); } }
} // end CloseStmt()
/*
* Chiusura connessione JDBC-ODBC */ public void CloseCon() { try { con.close(); } catch(SQLException ex) { System.out.println ("\n*** SQLException catturata ***\n"); while (ex != null) { System.out.println ("SQLState: " + ex.getSQLState ()); System.out.println ("Message: " + ex.getMessage ()); System.out.println ("Code: " + ex.getErrorCode ()); ex = ex.getNextException (); System.out.println (""); } }
} // end CloseCon()
} // end Class Bibliografia
[1] "Java La
Grande Guida", Patrick Naughton, Herbert Schildt, ed. McGrawHill .
"JDBC - La pratica" di Giovanni Puliti _ Mokabyte 16, Feb97. "JDBC API" di Giovanni Puliti _ Mokabyte 9,10,11, Giu-Set 97 "Le Servlet Api" di Fabrizio Giudici _ Mokabyte 11, Set97 "Servlet & Database" di Domenico Di Girolamo _ Mokabyte 16, Feb97. "Servlet, JDBC e JavaServer" di Giovanni Puliti _ Mokabyte 20, Giu98. e-mail JDCTechTips@sun.com oppure http://developer.javasoft.com/developer |
|
|
||
MokaByte ricerca
nuovi collaboratori.
|
||
|