ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ INTERNET ΜΕ ΤΗΝ ΤΕΧΝΟΛΟΓΙΑ ΤΩΝ JAVA SERVLETS

transportdingdongSoftware and s/w Development

Jul 14, 2012 (4 years and 9 months ago)

708 views


ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ INTERNET ΜΕ ΤΗΝ
ΤΕΧΝΟΛΟΓΙΑ ΤΩΝ
JAVA SERVLETS



Κακαρόντζας Γιώργος





ΤΕΙ Λάρισας
Τµήµα Τεχνολογίας Πληροφορικής & Τηλ/νιών
Οκτώβριος 2003


Προγραµµατισµός Internet µε τα Java Servlets Περιεχόµενα
ΕΙΣΑΓΩΓΗ
..................................................................................................................1
Τ
Ι ΕΙΝΑΙ ΤΑ
J
AVA
S
ERVLETS
........................................................................................1
Π
ΛΕΟΝΕΚΤΗΜΑΤΑ ΤΩΝ SERVLETS
..............................................................................2
Ε
ΓΚΑΤΑΣΤΑΣΕΙΣ ΠΡΟΓΡΑΜΜΑΤΩΝ
..............................................................................3

ΗΜΙΟΥΡΓΙΑ ΝΕΑΣ ΕΦΑΡΜΟΓΗΣ
..................................................................................5

ΗΜΙΟΥΡΓΙΑ ΤΟΥ
WEB-INF
.......................................................................................8
H
ELLO
W
ORLD
..........................................................................................................10
W
EB ΕΦΑΡΜΟΓΕΣ ΜΕ ΤΗΝ ΜΟΡΦΗ
WAR
ΑΡΧΕΙΟΥ
....................................................13
∆ΟΜΗ ΕΝΟΣ ΒΑΣΙΚΟΥ SERVLET
.....................................................................15
Έ
ΝΑ ΠΑΡΑ∆ΕΙΓΜΑ ΑΙΤΗΣΗΣ ΚΑΙ ΑΠΟΚΡΙΣΗΣ
.............................................................17
ΚΥΚΛΟΣ ΖΩΗΣ ΤΩΝ JAVA SERVLETS
............................................................21

ΗΜΙΟΥΡΓΙΑ ΕΝΟΣ ΣΤΙΓΜΙΟΤΥΠΟΥ ΕΝΟΣ SERVLET
(
SERVLET INSTANCE
)
..................21
Η
ΜΕΘΟ∆ΟΣ INIT
.......................................................................................................23
Η
ΜΕΘΟ∆ΟΣ DESTROY
...............................................................................................24
Έ
ΝΑ ΠΑΡΑ∆ΕΙΓΜΑ ΤΩΝ INIT ΚΑΙ DESTROY
.................................................................24
ΠΑΡΑΜΕΤΡΙΚΑ SERVLETS
.................................................................................29
Π
ΕΡΑΣΜΑ ΠΑΡΑΜΕΤΡΩΝ ΑΡΧΙΚΟΙΗΣΗΣ ΣΕ ΕΝΑ SERVLET
...........................................29
Α
ΝΑΚΤΗΣΗ ΤΙΜΗΣ ΠΑΡΑΜΕΤΡΟΥ ΑΠΟ ΤΟ SERVLET
...................................................30
Π
ΑΡΑ∆ΕΙΓΜΑ ΜΕ ΠΑΡΑΜΕΤΡΟΥΣ ΑΡΧΙΚΟΠΟΙΗΣΗΣ
....................................................31
Ά
ΛΛΕΣ ΣΧΕΤΙΚΕΣ ΜΕΘΟ∆ΟΙ ΜΕ ΤΙΣ ΠΑΡΑΜΕΤΡΟΥΣ ΑΡΧΙΚΟΠΟΙΗΣΗΣ ΕΝΟΣ SERVLET
.37
ΠΑΡΑΚΟΛΟΥΘΗΣΗ ΤΗΣ ΣΥΝΟ∆ΟΥ ΤΟΥ ΧΡΗΣΤΗ
.....................................38
Α
ΝΑΚΤΗΣΗ ΤΗΣ ΣΥΝΟ∆ΟΥ ΤΟΥ ΧΡΗΣΤΗ
....................................................................38
Μ
ΕΘΟ∆ΟΙ ΤΟΥ ΑΝΤΙΚΕΙΜΕΝΟΥ
H
TTP
S
ESSION
...........................................................39
Τ
ΡΟΠΟΙ ΥΛΟΠΟΙΗΣΗΣ ΣΥΝΟ∆ΩΝ
................................................................................40
Έ
ΝΑ ΠΑΡΑ∆ΕΙΓΜΑ ΠΑΡΑΚΟΛΟΥΘΗΣΗΣ ΣΥΝΟ∆ΟΥ
.....................................................42
Login.htm
.............................................................................................................42
LoginHandler.java
...............................................................................................44
ProtectedResource.java
.......................................................................................45
ΣΧΕΣΙΑΚΕΣ Β∆, SQL ΚΑΙ JDBC
..........................................................................47
Λ
ΙΓΑ ΛΟΓΙΑ ΓΙΑ ΤΙΣ
Σ
ΧΕΣΙΑΚΕΣ
Β
ΑΣΕΙΣ

Ε∆ΟΜΕΝΩΝ
...............................................48

Προγραµµατισµός Internet µε τα Java Servlets Περιεχόµενα

ΙΑΧΕΙΡΙΣΗ
Β∆
ΜΕ ΤΗΝ
SQL
....................................................................................50
M
Y
SQL
....................................................................................................................51
MM.M
Y
SQL JDBC D
RIVER
....................................................................................52
ΠΡΟΣΒΑΣΗ ΣΕ Β∆ ΜΕ SERVLETS
.....................................................................54

ΗΜΙΟΥΡΓΙΑ
Β∆
ΠΑΡΑ∆ΕΙΓΜΑΤΟΣ
............................................................................54

ΗΜΙΟΥΡΓΙΑ
Σ
ΥΝ∆ΕΣΗΣ
............................................................................................57
Π
ΑΡΑ∆ΕΙΓΜΑ ΣΥΝ∆ΕΣΗΣ
...........................................................................................58
Ε
ΚΤΕΛΕΣΗ ΕΝΤΟΛΩΝ ΤΗΣ
SQL
.................................................................................61
Εντολές της SQL: Η διασύνδεση java.sql.Statement
............................................61
Αποτελέσµατα της SQL: Η διασύνδεση java.sql.ResultSet
...................................62
Ένα παράδειγµα ενηµέρωσης και ανάκτησης δεδοµένων
.....................................64
Π
ΑΡΑ∆ΕΙΓΜΑ ΕΚΤΕΛΕΣΗΣ ΟΠΟΙΑΣ∆ΗΠΟΤΕ ΕΡΩΤΗΣΗΣ
...............................................69
ΠΡΟΣΒΑΣΗ ΣΕ Β∆ ΜΕ SERVLETS: ΠΡΟΧΩΡΗΜΕΝΑ ΣΤΟΙΧΕΙΑ
.............75
P
REPARED
S
TATEMENTS
............................................................................................75
Παράδειγµα µε PreparedStatement
......................................................................76
Σ
ΥΝΑΛΛΑΓΕΣ
(T
RANSACTIONS
)
................................................................................79
Τι είναι µία συναλλαγή
..........................................................................................79
Υποστήριξη συναλλαγών στο JDBC
......................................................................80
Παράδειγµα σύνδεσης σε κατάσταση συναλλαγής
.................................................81

ΕΞΑΜΕΝΕΣ ΣΥΝ∆ΕΣΕΩΝ
..........................................................................................84
Η τάξη ConnectionPool
.......................................................................................85
∆ηµιουργία και κλείσιµο των συνδέσεων της δεξαµενής
.......................................90
Παράδειγµα χρήσης της δεξαµενής συνδέσεων
.....................................................95

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Εισαγωγή
Σε αυτό το µάθηµα θα κάνουµε µία εισαγωγή στα Java Servlets. Πιο συγκεκριµένα θα
δούµε τα εξής:

Θα µάθουµε τι είναι τα Java Servlets και ποια είναι η θέση τους στις web
τεχνολογίες που συζητάµε.

Θα δούµε επίσης τι χρειαζόµαστε για να αναπτύξουµε web εφαρµογές µε τα
Java Servlets (όπως θα δείτε οτιδήποτε χρειάζεται είναι διαθέσιµο από το
∆ιαδίκτυο χωρίς κόστος).

Θα συζητήσουµε επίσης για τον tomcat που είναι ένας web server µε
δυνατότητες εκτέλεσης servlets και Java Server Pages (µία τεχνολογία που θα
συζητήσουµε σε επόµενο κεφάλαιο).

Θα δούµε ποια είναι η δοµή µιας web εφαρµογής βασισµένης στα Java
Servlets (και στις Java Server Pages).

Θα αναπτύξουµε µία µικρή εφαρµογή βασισµένη σε Java Servlets και θα την
εκτελέσουµε στον Tomcat.

Τέλος, θα δούµε πως µπορούµε να διαθέσουµε µία web εφαρµογή της Java µε
µία µορφή που ονοµάζεται war (web archive)
Τι είναι τα Java Servlets
Τα Java Servlets είναι µία web τεχνολογία βασισµένη στη Java µε την οποία
µπορούµε να αναπτύξουµε server-side εφαρµογές για το Internet. Ένα servlet είναι
µία µικρή τάξη της Java που περιέχεται σε ένα container. Το container διαχειρίζεται
το servlet. Το container µπορεί να είναι ταυτόχρονα και web server ή να είναι ένα
add-on component για ένα web server χωρίς δυνατότητες εκτέλεσης servlet. Για
παράδειγµα ο Tomcat που θα συζητήσουµε στη συνέχεια, είναι container και
ταυτόχρονα web server. Παρόλα αυτά, υπάρχει η δυνατότητα να χρησιµοποιηθεί ο
Tomcat µαζί µε τον Apache ή τον IIS οι οποίοι δεν µπορούν να εκτελέσουν servlets.
-
1 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Πλεονεκτήματα των servlets
Με τα servlets µπορούµε να αναπτύξουµε πολύ ισχυρές web εφαρµογές που έχουν τα
εξής πλεονεκτήµατα:

Βασίζονται και αναπτύσσονται στην Java και όχι σε µία script γλώσσα. Έτσι
οι προγραµµατιστές των servlets έχουν πρόσβαση στο Java API και τις
µεγάλες δυνατότητες που δίνει. Άλλες τεχνολογίες, όπως το PHP, βασίζονται
σε script γλώσσες που έχουν αναπτυχθεί ειδικά γι' αυτό το σκοπό. Με την
δυνατότητα να χρησιµοποιήσουµε Java επωφελούµαστε εφόσον γνωρίζουµε
ήδη τη Java.

Είναι πολύ εύκολο να προσθέσουµε state σε εφαρµογές διαδικτύου. Το HTTP
είναι ένα stateless πρωτόκολλο. Αυτό σηµαίνει πως σε κάθε get που κάνει ο
χρήστης ενός browser για µία ιστοσελίδα, για τον web server είναι σαν να
ξεκινά από την αρχή. Με τα servlets υπάρχει η έννοια της συνεδρίας (session)
µε την οποία µπορούµε να κρατήσουµε πληροφορίες που σχετίζονται µε την
συνεδρία του χρήστη µε το σύστηµα που µπορούν να διατηρούνται ανάµεσα
από διαδοχικά get. Αυτό είναι απαραίτητο σε πολλές εφαρµογές. Κλασικό
παράδειγµα είναι το shopping cart σε µία εφαρµογή πώλησης προϊόντων µέσω
Internet, στο οποίο ο χρήστης τοποθετεί προϊόντα καθώς πηγαίνει από σελίδα
σε σελίδα. Όπως είναι αυτονόητο, το shopping cart θα πρέπει να συγκρατεί τα
περιεχόµενά του ανάµεσα από διαδοχικές αιτήσεις για νέες σελίδες.

Μπορούµε να έχουµε πρόσβαση σε βάσεις δεδοµένων µέσω του JDBC API
της Java, πράγµα που είναι απαραίτητο για όλες σχεδόν τις διαδικτυακές
εφαρµογές των επιχειρήσεων.

Έχουµε ανεξαρτησία από Λειτουργικό Σύστηµα, µια και τα Servlets
εκτελούνται από την Java Virtual Machine. Μία εξίσου ισχυρή τεχνολογία µε
τα Servlets/JSP που είναι το ASP.NET της Microsoft δεν διαθέτει αυτή τη
δυνατότητα. Προς το παρόν ο µόνος web server που µπορεί να εκτελεί
ASP.NET εφαρµογές είναι ο Internet Information Server της ίδιας εταιρείας
που τρέχει σε Win2000 Professional, Win2000 Server και σε WinXP
Professional. Άλλωστε το ίδιο .NET που είναι το Framework κοµµάτι του
-
2 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
οποίου αποτελεί το ASP.NET µπορεί και εγκαθίσταται µόνο στα
προαναφερθέντα Λειτουργικά συστήµατα της Microsoft.

Έχουµε καλύτερη επίδοση (performance) από άλλες τεχνολογίες, όπως για
παράδειγµα το CGI (Common Gateway Interface), διότι το µοντέλο
διεργασιών που χρησιµοποιείται για τα servlets είναι αισθητά καλύτερο έναντι
αυτών των τεχνολογιών. Το αν τα Servlets/JSP και ευρύτερα η πλατφόρµα
J2EE έχουν καλύτερη επίδοση από το ASP.NET και το .ΝΕΤ framework ή το
αντίθετο, όπως και το ποια είναι καλύτερη πλατφόρµα γενικότερα, είναι ένα
θέµα ανοιχτής διαµάχης αυτό το διάστηµα µε ανακοινώσεις στο Internet από
όλες τις ενδιαφερόµενες πλευρές. Για όσους ενδιαφέρονται µπορούν να
ρίξουν µία µατιά στα ακόλουθα:
o
http://www.gotdotnet.com/team/compare/oraclerespond.aspx
o
http://otn.oracle.com/tech/java/oc4j/pdf/9ias_net_bench.pdf
o
http://www.oracle.com/ip/develop/ids/index.html?tough_ms.html
o
http://www.onjava.com/pub/a/onjava/2001/11/28/catfight.html?page=1
Εγκαταστάσεις προγραμμάτων
Για να εκτελέσετε στον υπολογιστή σας εφαρµογές βασισµένες σε servlets χρειάζεστε
ένα κατάλληλο web container που να είναι σε θέση να εκτελέσει servlets. Για τους
σκοπούς αυτών των µαθηµάτων θα χρησιµοποιήσουµε τον Tomcat 4.0, που είναι
ταυτόχρονα και web server. Ο Tomcat 4.0 υλοποιεί τις προδιαγραφές των Java
Servlets 2.3 και Java Server Pages 1.2.
Το λογισµικό που απαιτείται για να µεταφράσετε και να εγκαταστήσετε servlets είναι
το εξής:
1. Το Java Development Kit έκδοση 1.2 και πάνω: Αυτό µπορείτε να το
κατεβάσετε για το σύστηµά σας από την διεύθυνση: http://java.sun.com/
2. Επίσης µπορείτε να κατεβάσετε και να εγκαταστήσετε στον υπολογιστή σας
ένα freeware περιβάλλον για να γράφετε προγράµµατα java από την
διεύθυνση:
http://www.jcreator.com
-
3 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
3. Θα πρέπει στη συνέχεια να κατεβάσετε και να εγκαταστήσετε τον Tomcat
(εδώ θα χρησιµοποιήσουµε την έκδοση 4.0) από την διεύθυνση:
http://jakarta.apache.org/builds/jakarta-tomcat-4.0/nightly/
Για τα windows κατεβάστε το jakarta-tomcat-4.0-YYYYMMDD.zip. Αφού
κατεβάσετε αυτό το zip αρχείο, αποσυµπιέστε το σε κάποιο κατάλογο (εξ
ορισµού ο κατάλογος αυτός θα ονοµάζεται jakarta-tomcat-4.0). Σηµειώστε
πως για τα Windows NT/2000/XP υπάρχει η δυνατότητα να εγκαταστήσετε
τον Tomcat ως Windows service και να ξεκινά αυτόµατα κάθε φορά που
ξεκινάτε τον υπολογιστή σας.
4. Αφού εγκαταστήσετε τον Tomcat στον υπολογιστή σας και τον ξεκινήσετε
(είτε απευθείας είτε από το service για τα Windows) µπορείτε να ελέγξετε αν
λειτουργεί δίνοντας στον browser την διεύθυνση:
http://localhost:8080/
Όπως µπορείτε να δείτε ο Tomcat εξ ορισµού "ακούει" στο port 8080. Αν όλα
πήγαν καλά θα πρέπει να δείτε την πρώτη σελίδα του Tomcat.

-
4 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Δημιουργία νέας εφαρμογής
Μία web εφαρµογή βασισµένες σε τεχνολογίες Java θα πρέπει να έχει µία
συγκεκριµένη µορφή. Η βασική µορφή έχει την ακόλουθη δενδρική δοµή καταλόγων:

Ο βασικός κατάλογος (στο παράδειγµά µας ο "examples") ο οποίος περιέχει τα αρχεία
.html και .jsp της εφαρµογής (για jsp αρχεία θα µιλήσουµε σε επόµενα µαθήµατα).
Επίσης είναι δυνατόν να περιέχει και πρόσθετους καταλόγους ως συνήθως (για
παράδειγµα ο κατάλογος "images" στην εικόνα θα περιέχει τις εικόνες του website).
Ο ενδιαφέρων κατάλογος από την άποψη της web εφαρµογής Java είναι ο κατάλογος
WEB-INF. Μέσα σε αυτόν περιέχεται ένα αρχείο το web.xml το οποίο περιέχει
πληροφορίες ρύθµισης για την λειτουργία της εφαρµογής (τις βασικότερες από τις
οποίες θα δούµε στη συνέχεια). Αυτός ο κατάλογος περιέχει επίσης και τον κατάλογο
classes. Μέσα σε αυτόν τον κατάλογο τοποθετούµε τα .class αρχεία των servlets της
εφαρµογής. Τα αρχεία αυτά µπορεί να είναι έξω από πακέτα οπότε και θα περιέχονται
απευθείας στον κατάλογο classes ή να ανήκουν σε πακέτα οπότε θα περιέχονται
κατάλογοι για τα πακέτα µέσα στον κατάλογο classes και τα .class αρχεία των
servlets θα περιέχονται µέσα σε αυτούς τους καταλόγους των πακέτων (ως συνήθως
µε τα πακέτα της Java).
Για να δηµιουργήσουµε µία νέα web εφαρµογή µε τον Tomcat θα πρέπει να δώσουµε
κάποιες πληροφορίες στον Tomcat σχετικά µε το όνοµα που θα ζητάµε την εφαρµογή
και σχετικά µε το που βρίσκεται αυτή η εφαρµογή στον δίσκο. Αυτά και πολλά άλλα
καθορίζονται από ένα XML αρχείο στον κατάλογο conf που βρίσκεται µέσα στον
κατάλογο εγκατάστασης του Tomcat. Το αρχείο αυτό λέγεται server.xml. Όλες τις
παραµέτρους ρύθµισης για τον server που µπορείτε να καθορίσετε στο server.xml
µπορείτε να τις δείτε δίνοντας στον browser την διεύθυνση:
http://localhost:8080/tomcat-docs/config/index.html. Εδώ θα δούµε µόνο πως
µπορούµε να δηµιουργήσουµε µία νέα εφαρµογή ή ένα νέο context. Το context είναι
ένα εµφωλευµένο στοιχείο µέσα στο στοιχείο <host>.
-
5 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Συστήνω πριν να κάνετε οποιαδήποτε αλλαγή στο server.xml να αποθηκεύσετε το
αρχικό server.xml µε κάποιο άλλο όνοµα έτσι ώστε αν κάτι δεν πάει καλά µε τις
αλλαγές σας να µπορέσετε να επαναφέρετε τον server στην αρχική του κατάσταση.
Βρίσκουµε λοιπόν στο αρχείο server.xml την γραµµή:
<!-- Define the default virtual host -->
<Host name="localhost" debug="0" appBase="webapps" unpackWARs="true">

Αυτήν η γραµµή περιέχει το στοιχείο Host το οποίο έχει τις υποχρεωτικές
παραµέτρους name (στην περίπτωσή µας localhost γιατί δεν έχουµε DNS για τον
Tomcat) και η appbase που είναι ο κατάλογος στον οποίο περιέχονται οι web
εφαρµογές του Tomcat (όπως η εφαρµογή examples που είδαµε προηγουµένως).
Αυτός ο κατάλογος είναι ο webapps µέσα στον κατάλογο εγκατάστασης του Tomcat.
Οι εφαρµογές µας µπορούν να βρίσκονται και σε άλλους καταλόγους αν δώσουµε
απόλυτη τιµή στην παράµετρο docbase του στοιχείου context (βλ. επόµενα). Στην
εικόνα που ακολουθεί φαίνονται οι εφαρµογές που εγκαθίστανται εξ ορισµού όταν
εγκαθιστούµε τον Tomcat 4:



Όπως βλέπετε η εφαρµογή examples που συζητήσαµε προηγουµένως βρίσκεται µέσα
στον κατάλογο webapps. Αν διαβάσετε προσεκτικά το αρχείο server.xml µετά την
γραµµή <host> θα δείτε διάφορα στοιχεία <context> τα οποία είναι εµφωλευµένα και
αφορούν τις εγκατεστηµένες web εφαρµογές.
Εµείς για να δηµιουργήσουµε µία νέα εφαρµογή θα προσθέσουµε ένα νέο context στο
αρχείο server.xml. Αναζητείστε το </host> και πριν από αυτό τοποθετείστε την
ακόλουθη γραµµή:
-
6 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
<Context path="/webprog" docBase="webprog" reloadable="true" />
Όπως βλέπετε το στοιχείο Context που δηλώνουµε δηλώνει ως path το /webprog.
Επίσης δηλώνει ως docbase την σχετική διαδροµή webprog. Τέλος αποδίδει στην
παράµετρο reloadable την τιµή true. Το στοιχείο Context θα το κλείναµε φυσιολογικά
δίνοντας το </context>. Στην XML το ίδιο επιτυγχάνεται αν αφήσουµε ένα κενό και
στην συνέχεια βάλουµε />.
Οι σηµασία των παραµέτρων που δώσαµε είναι η ακόλουθη:
name: Είναι το URI της εφαρµογής, δηλαδή είναι αυτό που γράφει ο χρήστης µετά το
http://localhost:8080. Στο παράδειγµά µας δηλαδή οι χρήστες θα πρέπει να γράφουν
http://localhost:8080/webprog/
docbase: Είναι το directory στο οποίο περιέχονται τα αρχεία της εφαρµογής. Αν εδώ
δώσουµε σχετική διαδροµή τότε εννοείται πως ο κατάλογος αυτός βρίσκεται κάτω
από τον κατάλογο webapps που προσδιορίστηκε στο στοιχείο <host>. Μπορούµε να
δώσουµε και απόλυτη διαδροµή οπότε ο κατάλογος είναι αυτός που προδιορίζουµε
στην απόλυτη διαδροµή.
reloadable: Αυτή η παράµετρος είναι πολύ χρήσιµη όταν αναπτύσσουµε µία
εφαρµογή. Αν είναι true τότε ο Tomcat ελέγχει κάθε φορά που ζητάµε ένα servlet από
τον κατάλογο WEB-INF/classes της εφαρµογής, για το αν άλλαξε από την τελευταία
φορά που δηµιούργησε ένα στιγµιότυπο αυτού του servlet και αν άλλαξε το
δηµιουργεί ένα νέο στιγµιότυπο. Όπως θα δούµε για ένα servlet φυσιολογικά
δηµιουργείται µόνο ένα στιγµιότυπο το οποίο εξυπηρετεί όλες τις αιτήσεις γι' αυτό το
servlet. Με την παράµετρο reloadable µπορούµε λοιπόν να αλλάξουµε ένα servlet και
να το εγκαταστήσουµε και πάλι στο WEB-INF/classes και να το δούµε µε τις αλλαγές
που κάναµε χωρίς να χρειαστεί να σταµατήσουµε και να ξεκινήσουµε τον Tomcat
ξανά (που είναι και το default). Η τεκµηρίωση του Tomcat αναφέρει πως επειδή η
επιβάρυνση για τον έλεγχο αυτό είναι σηµαντική όταν εγκαθιστούµε την εφαρµογή
προς χρήση δεν θα πρέπει να είναι true. Πάντως για µας που µαθαίνουµε τα servlets
είναι χρήσιµη.
Πριν να δοκιµάσουµε το νέο context θα πρέπει να σταµατήσουµε και να ξεκινήσουµε
και πάλι τον Tomcat για να ενηµερωθεί για τις αλλαγές στο server.xml.
Για να δοκιµάσουµε το νέο context αποθηκεύστε το αρχείο server.xml, και στην
συνέχεια µέσα στον κατάλογο webapps δηµιουργείστε ένα κατάλογο µε το όνοµα
webprog. Μέσα στον κατάλογο webprog γράψτε το ακόλουθο αρχείο hello.htm:

-
7 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-
1253">
<title>Hello</title>
</head>
<body>
<p>Hello από τον Tomcat</p>
</body>
</html>
Στην συνέχεια αφού αποθηκεύσετε το αρχείο δώστε από τον browser την διεύθυνση:
http://localhost:8080/webprog/hello.htm. Θα πρέπει να δείτε την ακόλουθη εικόνα:


Δημιουργία του WEB-INF
Όπως είδαµε στο root του νέου context που δηµιουργήσαµε βάλαµε µία html σελίδα
και αυτήν ανακτήθηκε από τον Tomcat. Τώρα θα πρέπει να δηµιουργήσουµε τον
κατάλογο WEB-INF µέσα στον Tomcat και εκεί να δηµιουργήσουµε το αρχείο
web.xml µε τις ρυθµίσεις της νέας εφαρµογής καθώς και τον κατάλογο classes στον
οποίο θα τοποθετήσουµε τα servlets της νέας εφαρµογής (τα µεταφρασµένα servlets
δηλαδή τα αρχεία µε επέκταση .class).
Το αρχείο web.xml είναι ο Web Application Deployment Descriptor της εφαρµογής
και περιέχει πληροφορίες για την εφαρµογή όπως οι ακόλουθες:
Μία γενική περιγραφή της
Παράµετροι του context
-
8 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Παράµετροι του servlet
Τα ονόµατα των servlets και τις αντιστοιχίες αυτών των ονοµάτων µε URIs
Παράµετροι ασφάλειας κλπ.
Για περισσότερες πληρφορίες για το αρχείο web.xml µπορείτε να δείτε το
http://localhost:8080/tomcat-docs/appdev/deployment.html το οποίο παρέχει και ένα
βασικό web.xml αρχείο το οποίο µπορείτε να τροποποιήσετε για τις ανάγκες των
δικών σας εφαρµογών. Επίσης µία αναλυτική περιγραφή µπορείτε να βρείτε στο 13ο
κεφάλαιο του Servlet 2.3 spec. στο Servlet 2.3 Specification διαθέσιµο στην
διεύθυνση http://java.sun.com/products/servlet/download.html.
Για τις ανάγκες της δικής µας εφαρµογής προς το παρόν δηµιουργήστε τον κατάλογο
WEB-INF και µέσα σε αυτόν τον κατάλογο δηµιουργείστε ένα αρχείο web.xml και
πληκτρολογήστε σε αυτό το αρχείο τα εξής:

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
Σε αυτό το αρχείο ορίζουµε (προς το παρόν) ένα servlet το οποίο έχει το όνοµα
(<servlet-name>) hello και η τάξη του (<servlet-class>) είναι η HelloWorld (εννοείται
ότι πρόκειται για το αρχείο HelloWorld.class στον κατάλογο WEB-INF/classes).
Επίσης ορίζουµε την αντιστοιχία του ονόµατος hello µε το request URI µετά το
-
9 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
όνοµα του context που στο παράδειγµα είναι το /hello. Αυτό γίνεται µε το στοιχείο
<servlet-mapping>. Έτσι ο χρήστης θα µπορεί να πληκτρολογεί το URL:
http://localhost:8080/webprog/hello για να εκτελεσθεί το servlet στο container.
Σηµειώστε πως στον Tomcat είναι επίσης δυνατόν να εκτελέσουµε ένα servlet
δίνοντας http://localhost:8080/{context-name}/servlet/{όνοµα-τάξης}. Παρόλα αυτά
το χαρακτηριστικό αυτό είναι µία ευκολία που παρέχει ο Tomcat αλλά δεν είναι
εγγυηµένα συµβατή µε άλλα containers.
Φυλάξτε το αρχείο web.xml και στην συνέχεια δηµιουργείστε µέσα στον κατάλογο
WEB-INF τον κατάλογο classes. Μέσα στον κατάλογο classes θα βάλουµε το πρώτο
µας servlet που είναι το HelloWorld.class. Θα γράψουµε επίσης το HelloWorld.java
µέσα σε οποιοδήποτε κατάλογο. Το µόνο που χρειάζεται µέσα στον κατάλογο classes
είναι το HelloWorld.class.
HelloWorld
Τώρα είµαστε έτοιµοι να γράψουµε, να µεταφράσουµε, να εγκαταστήσουµε και να
τρέξουµε την πρώτη εφαρµογή µας µε servlets, που θα είναι φυσικά το HelloWorld.
Θα υποθέσουµε ότι χρησιµοποιούµε το JCreator για να γράψουµε το πρόγραµµα και
να το µεταφράσουµε.
Ανοίξτε το JCreator και δηµιουργείστε ένα νέο αρχείο Java µε το όνοµα
HelloWorld.java. Στην συνέχεια πληκτρολογήστε τον κώδικα που ακολουθεί:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/html");
-
10 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Hello World</title>");
out.println("</head>");
out.println("<body bgcolor=\"white\">");
out.println("<h1>Hello World</h1>");
out.println("</body>");
out.println("</html>");
}
}
Πρίν µεταγλωττίσετε το HelloWorld.java θα πρέπει να προσθέσετε στο classpath το
servlet.jar. Αυτό είναι το jar αρχείο που περιέχει τα απαραίτητα πακέτα της Java για
την µετάφραση και εκτέλεση Servlets και Java Server Pages. Το αρχείο αυτό
βρίσκεται στον κατάλογο common/lib που βίσκεται µέσα στον κατάλογο που
εγκαταστήσατε τον Tomcat. Στον JCreator η προσθήκη γίνεται από το µενού
Configure->Options->JDK Profiles->Edit->Add->Package.

-
11 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Αν γράψατε το αρχείο σε διαφορετική θέση από τον κατάλογο WEB-INF/classes θα
πρέπει να αντιγράψετε το .class αρχείο που παράχθηκε από την µεταγλώττιση στην
θέση αυτή.
Στην συνέχεια θα πρέπει να σταµατήσετε και να ξεκινήσετε και πάλι τον Tomcat για
να ενηµερωθεί για τις αλλαγές στο web.xml.
Τέλος από τον browser µπορείτε να δώσετε το ακόλουθο URL:
http://localhost:8080/webprog/hello για να δείτε το αποτέλεσµα. Αν όλα πάνε καλά
θα πρέπει να δείτε το εξής:


Επειδή είναι "κουραστικό" να σταµατάµε και να ξεκινάµε τον Tomcat κάθε φορά που
προσθέτουµε ένα όνοµα στο web.xml, για τους σκοπούς αυτών των µαθηµάτων θα
χρησιµοποιήσουµε την τεχνική εκτέλεσης:
http://localhost:8080/webprog/servlet/όνοµα-servlet έτσι ώστε να αποφύγουµε την
δήλωση των mappings στο web-xml. Σηµειώστε πάντως πως τώρα που ο Tomcat
γνωρίζει το όνοµα hello αν αλλάξουµε το HelloWorld αυτή η αλλαγή θα γίνει ορατή
άµεσα λόγω του ότι δηλώσαµε ότι το context είναι reloadable στο server.xml.
Σηµειώνεται πως µπορείτε µε τον Tomcat να φορτώνετε εφαρµογές και contexts από
την αρχή χωρίς να σταµατάτε και να ξεκινάτε τον server µέσω µιας web εφαρµογής
που λέγεται manager.
Επειδή ο manager είναι πιστοποιηµένη εφαρµογή για να χρησιµοποιηθεί θα πρέπει να
προσθέσετε στο αρχείο conf/tomcat-users.xml µία γραµµή σαν την ακόλουθη
(βάζοντας προφανώς το δικό σας username και password).
<user name="george" password="cangetin" roles="standard,manager" />
-
12 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Στην συνέχεια µπορούµε να φορτώνουµε ένα νέο context που τοποθετήσαµε στο
server.xml ως εξής:
http://localhost:8080/manager/install?path=/webprog&war=file:/webprog
Στην περίπτωσή µας επειδή το context υπάρχει ήδη θα µας βγάλει το µήνυµα:
FAIL - Application already exists at path /webprog
Επίσης µπορείτε να φορτώνετε και πάλι µία εφαρµογή µε την εντολή:
http://localhost:8080/manager/reload?path=/webprog
Περισσότερες πληροφορίες για τον manager και τις εντολές του µπορείτε να βρείτε
στο http://localhost:8080/tomcat-docs/manager-howto.html
Web εφαρμογές με την μορφή WAR αρχείου
Στην J2EE υπάρχει επίσης η δυνατότητα να πακετάρουµε µία ολόκληρη web
εφαρµογή (ολόκληρη την ιεραρχική δοµή που ήδη συζητήσαµε σε ένα αρχείο µε την
επέκταση war = web archive). Το war αρχείο µπορεί να δηµιουργηθεί µε το
βοηθητικό εργαλείο jar το οποίο διατίθεται µε την Java Standard edition.
Για να δηµιουργήσουµε µία web εφαρµογή µε το jar αρκεί να πάµε στον root
κατάλογο της web εφαρµογής και να δώσουµε την εντολή:
jar cvf όνομα-αρχείο.war .
Για παράδειγµα για να πακετάρουµε σε ένα war αρχείο την εφαρµογή webprog
µπορούµε να πάµε στον κατάλογο webapps/webprog και να δώσουµε την εντολή:
jar cvf test.war .
Στην συνέχεια µεταφέρουµε το war αρχείο στον κατάλογο webapps όπου περιέχονται
όλες οι εφαρµογές του host και αρκεί να προσθέσουµε ένα νέο context για την
εφαρµογή στο αρχείο conf/server.xml όπως ήδη συζητήσαµε. Για παράδειγµα για το
test.war θα µπορούσαµε να κάνουµε την ακόλουθη προσθήκη στο server.xml:
<Context path="/test" docBase="test.war" />
Όπως βλέπετε το path για την εφαρµογή θα είναι /test, δηλαδή για να αναφερθούµε
στην εφαρµογή θα πρέπει να δώσουµε το URL:
http://localhost:8080/test
Το docBase είναι το όνοµα του war αρχείου που αντιγράψαµε στο webapps.
-
13 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Κατόπιν σταµατάµε και ξεκινάµε και πάλι τον Tomcat. Αφού γίνει αυτό δίνοντας
στον browser την διεύθυνση http://localhost:8080/test/hello.htm θα πρέπει να δούµε
το αρχείο hello.htm και δίνοντας http://localhost:8080/test/hello θα πρέπει να δούµε
τα αποτελέσµατα του servlet HelloWorld.
-
14 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Δομή ενός βασικού servlet
Ας δούµε σε αυτό το σηµείο λίγο πιο προσεκτικά το HelloWorld servlet προκειµένου
να εξετάσουµε την βασική δοµή ενός servlet. Επαναλαµβάνουµε τον κώδικα του
HelloWorld:
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Hello World</title>");
out.println("</head>");
out.println("<body bgcolor=\"white\">");
out.println("<h1>Hello World</h1>");
out.println("</body>");
out.println("</html>");
}
}
Παρατηρείστε πως το HelloWorld επεκτείνει το HttpServlet. Το HttpServlet θα είναι
η υπερτάξη για το 99% των τάξεων που θα κατασκευάσουµε. Η τάξη HttpServlet του
πακέτου javax.servlet.http είναι υποτάξη της τάξης javax.servlet.GenericServlet και
είναι µία αφηρηµένη τάξη που θα πρέπει να επεκτείνουµε για να δηµιουργήσουµε ένα
HttpServlet κατάλληλο για χρήση σε ένα website. Οι τάξεις που επεκτείνουν το
HttpServlet θα πρέπει να υπερβούν τουλάχιστον µία από τις µεθόδους doGet, doPost,
-
15 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
doPut, doDelete, init, destroy και getServletInfo. Η χρήση των doPut και doDelete
είναι σπάνια. Συνηθέστερα οι µέθοδοι που υπερβαίνουµε είναι µία από τις doPost ή
doGet και ίσως να χρησιµοποιήσουµε και τις init, destroy και getServletInfo.
Η µέθοδος doGet χρησιµοποιείται όταν τα δεδοµένα µίας φόρµας αποστέλλονται µε
προσάρτηση στο URL (method="get"). Η µέθοδος doPost χρησιµοποιείται όταν τα
δεδοµένα µίας φόρµας αποστέλλονται σε ένα ανεξάρτητο ρεύµα (method="post").
Εδώ επεκτείνουµε την µέθοδο doGet διότι δεν αποστέλλονται δεδοµένα στο servlet.
Όπως βλέπετε η µέθοδος doGet (όπως και η doPost) δέχονται ως παραµέτρους δύο
αντικείµενα, το requst και το response, που υλοποιούν τις διασυνδέσδεις
javax.servlet.http.HttpServletRequest και javax.servlet.http.HttpServletResponse
αντίστοιχα. Τα δύο αυτά αντικείµενα παρέχουν µεθόδους για την επεξεργασία της
αίτησης του χρήστη (HttpServletRequest) αλλά και την αποστολή της απόκρισης του
servlet (HttpServletResponse). Για τις λεπτοµέρειες των µεθόδων αυτών αλλά και
όλων των τάξεων, διασυνδέσεων, εξαιρέσεων και µεθόδων του Java Servlet API
µπορείτε να συµβουλευτείτε την τεκµηρίωση του API σε javadoc µορφή στην
εγκατάσταση του Tomcat στο URL http://localhost:8080/tomcat-
docs/servletapi/index.html.
Επίσης παρατηρείστε πως η µέθοδος doGet, όπως και η doPost, δηλώνει πως
ενδέχεται να προκαλέσει τις εξαιρέσεις javax.servlet.ServletException και
java.io.IOException. Η πρώτη εξαίρεση είναι µία γενική εξαίρεση που µπορεί να
προκληθεί όταν το servlet αντιµετωπίσει δυσκολίες. Η δεύτερη σχετίζεται µε το
γεγονός ότι για να σχηµατίσουµε την απόκριση του χρήστη γράφουµε δεδοµένα στον
PrintWriter του αντικειµένου Response καλώντας την µέθοδο println του PrintWriter.
Τον PrintWriter τον ανακτούµε καλώντας την µέθοδο getWriter του αντικειµένου
response. Αυτήν η µέθοδος ενδέχεται να προκαλέσει την εξαίρεση IOException, όπως
και η µέθοδος println του PrintWriter που καλούµε στην συνέχεια εξακολουθητικά
για να σχηµατίσουµε την απόκριση του χρήστη. Επειδή η εξαίρεση IOException είναι
ελεγχόµενη (checked exception) θα πρέπει να δηλωθεί πως προκαλείται µε την φράση
throws στην µέθοδο doGet.
Βασικά οι µέθοδοι που καλούµε σε αυτό το Servlet είναι τρεις:

Η µέθοδος setContentType του αντικειµένου response θα πρέπει να κληθεί για
να προσδιορισθεί ο τύπος της απόκρισης. Στην περίπτωσή µας η απόκριση θα
είναι "text/html". Αυτήν η µέθοδος θέτει το ContentType response Header
-
16 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
στην HTML σελίδα που σχηµατίζεται και θα δει ο χρήστης. Ο πιο κοινός
τύπος απόκρισης είναι "text/html" αλλά δεν είναι ο µόνος. Για παράδειγµα αν
η απόκριση ήταν µια εικόνα ο τύπος θα έπρεπε να είναι "image/gif" και αν
ήταν ένα έγγραφο του excel "application/vnd.ms-excel". Κάτι χρήσιµο για
την εµφάνιση Ελληνικών είναι πως µε την setContentType µπορούµε να
προσδιορίσουµε και το charset δηλαδή την κωδικοσελίδα στην οποία ο
PrintWriter θα µετατρέψει τους Unicode χαρακτήρες της java για να τους
αποστείλλει στον χρήστη. Για παράδειγµα θα µπορούσαµε να προσδιορίσουµε
το ContentType ως "text/html; charset=UTF-8" για να σταλλεί το αποτέλεσµα
σε µορφή Unicode και "text/html;charset=ISO-8859-7" για να σταλλεί το
αποτέλεσµα σε κωδικοποίηση Ελληνική ISO. Σε περίπτωση που δεν
προσδιορίσουµε το charset τότε χρησιµοποιείται το ISO Latin1.

Η µέθοδος getWriter όπως ήδη αναφέραµε, επιστρέφει ένα PrintWriter
αντικείµενο, στο παράδειγµά µας το out, το οποίο είναι ένα ρεύµα
χαρακτήρων εισόδου του αντικειµένου response, στο οποίο γράφουµε (µε την
println) την HTML σελίδα. Ο PrintWriter µετατρέπει τους Unicode
χαρακτήρες της Java στο charset που προσδιορίσαµε µε την setContentType
και τους εξάγει στον browser.

Τέλος καλούµε την println του αντικειµένου out για να σχηµατίσουµε την
ιστοσελίδα-αποτέλεσµα που θα δει ο χρήστης. Στις συµβολοσειρές της
out.println συνήθως περιέχονται και ετικέτες HTML για την µορφοποίηση του
κειµένου της ιστοσελίδας που θα δει ο χρήστης.
Αυτό το απλό servlet που είδαµε στο παράδειγµα, µπορεί να χρησιµεύσει σαν ένα
πρότυπο για πιο πολύπλοκα servlets που θα δούµε στην συνέχεια.
Ένα παράδειγμα αίτησης και απόκρισης
Στο παράδειγµα που ακολουθεί θα κάνουµε µία HTML σελίδα, µε µία φόρµα. Στην
φόρµα αυτή θα υπάρχει ένα text στοιχείο εισόδου µε το όνοµα "name" στο οποίο ο
χρήστης θα γράψει το όνοµά του. Στην συνέχεια ο χρήστης θα πατήσει το πλήκτρο
submit. Σαν αποτέλεσµα θα εκτελεσθεί το servlet HelloToYou, γιατί αυτό
προσδιορίζεται ως action στη φόρµα. Το servlet θα ανακτήσει την τιµή που έδωσε ο
-
17 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
χρήστης στο στοιχείο κειµένου name, και θα σχηµατίσει µία σελίδα απόκρισης στον
χρήστη η οποία θα λέει "Γεια σου"+name (π.χ. "Γεια σου Γιώργο" αν ο χρήστης είχε
δώσει την τιµή "Γιώργο" στο name). Το παράδειγµα αυτό είναι πολύ απλό αλλά
δείχνει τα βασικά συστατικά µίας αποστολής στοιχείων µέσω µίας φόρµας σε ένα
servlet και την ανάκτησή τους από το servlet µέσω της getParameter. Να
επισηµάνουµε επίσης πως αν η τιµή που ήθελε να στείλει ο χρήστης στο servlet ήταν
αριθµητική και όχι String, το servlet θα έπρεπε να µετατρέψει την τιµή σε αριθµό
(π.χ. µε την Integer.ParseInt) και αυτό διότι η getParameter επιστρέφει την τιµή που
έδωσε ο χρήστης µε µορφή String.
Η ιστοσελίδα µε την φόρµα, έχει το όνοµα Hello2u.htm και είναι η εξής:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-7">
<title>Hello To You</title>
</head>
<body>
<p>Hello με φόρμα</p>
<form method="post" action="http://localhost:8080/webprog/servlet/HelloToYou">
<p>Πως σε λένε;
<input type="text" name="name">
<input type="submit">
</form>
</body>
</html>
Όπως βλέπετε η φόρµα έχει ένα πεδίο text που ονοµάζεται name. Επίσης η action της
φόρµας είναι το servlet HelloToYou (ο κώδικάς του ακολουθεί). Όταν ο χρήστης
πατήσει το πλήκτρο submit, το name αποστέλλεται µε την µέθοδο post στο servlet
HelloToYou. Παρατηρείστε επίσης πως στο <head> της σελίδας και στην ετικέτα
<meta http-equiv...> καθορίζουµε ως κωδικοσελίδα της ιστοσελίδας την ISO-8859-7
-
18 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
(Ελληνικό ISO). Έτσι ότι πληκτρολογήσει ο χρήστης στην φόρµα θα αποσταλλεί στο
servlet µε αυτήν την κωδικοποίηση.
Το servlet HelloToYou.java είναι το εξής:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloToYou extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
request.setCharacterEncoding("ISO-8859-7");
response.setContentType("text/html; charset=ISO-8859-7");
String s = request.getParameter("name");
PrintWriter pw = response.getWriter();
pw.println("Hello to you "+s);
}

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doPost(request, response);
}
}
To HelloToYou υλοποιεί την µέθοδο doPost και καλεί στο αντικείµενο request την
µέθοδο getParameter µε παράµετρο το "name". Αυτό θα έχει ως αποτέλεσµα την
ανάκτηση της τιµής του πεδίου name της φόρµας διότι αυτό έχει το όνοµα "name".
Πριν την κλήση της getParameter, προσδιορίζουµε την κωδικοσελίδα την οποία θα
χρησιµοποιήσει η getParameter για να µετατρέψει τους χαρακτήρες που διαβάζει σε
-
19 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Unicode. Επειδή η ιστοσελίδα έχει κωδικοσελίδα ISO-8859-7 η ίδια κωδικοσελίδα
προσδιορίζεται και για το request µε την κλήση της µεθόδου setCharacterEncoding:
request.setCharacterEncoding("ISO-8859-7"). Επίσης η ίδια κωδικοσελίδα
χρησιµοποιείται και για την επιστροφή του αποτελέσµατος µε την κλήση της µεθόδου
setContentType του αντικειµένου response. Στην συνέχεια ακολουθεί η ανάκτηση
της τιµής της παραµέτρου name µε την κλήση της µεθόδου getParameter στο
αντικείµενο request. Τέλος το αποτέλεσµα γράφεται στο αντικείµενο pw που είναι ο
PrintWriter του response.
Παρατηρείστε πως το servlet υποστηρίζει επίσης την µέθοδο get µέσω της doGet. Η
doGet απλά καλεί την doPost µε τα ίδια ορίσµατα, άρα κάνει την ίδια δουλειά που
κάνει και η doPost. Η µέθοδος αυτή επιτρέπει στο servlet HelloToYou να εκτελεσθεί
µε προσθήκη της name και της τιµής της απευθείας µετά το URL του servlet ως εξής:
http://localhost:8080/webprog/servlet/HelloToYou?name=George
∆ηλαδή το συγκεκριµένο servlet υποστηρίζει και τις δύο µορφές αποστολής
δεδοµένων (Get και Post). Η µέθοδος αυτή για την υποστήριξη και των δύο µεθόδων
αποστολής είναι ένα πολύ κοινό προγραµµατιστικό ιδίωµα στα Java Servlets.
-
20 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Κύκλος ζωής των Java Servlets
Δημιουργία ενός στιγμιότυπου ενός servlet (servlet
instance)
Το container που διαθέτει ένα Java Servlet δηµιουργεί ένα στιγµιότυπο (instance) την
πρώτη φορά που γίνεται µία αίτηση γι' αυτό. Σηµειώνεται πως στον Tomcat υπάρχει
και η δυνατότητα να δηµιουργηθεί ένα στιγµιότυπο µόλις αρχίσει να εκτελείται ο
server. Το στιγµιότυπο αυτό εξυπηρετεί την πρώτη και τις επόµενες αιτήσεις γι' αυτό
το servlet. Αυτό έχει τρία πλεονεκτήµατα:
1. ∆εν δηµιουργούνται πολλά αντικείµενα µε αποτέλεσµα να µην υπάρχει
απώλεια µνήµης.
2. ∆εν καθυστερεί η εξυπηρέτηση της αίτησης µια και το στιγµιότυπο είναι ήδη
στην µνήµη του υπολογιστή
3. Το κάθε servlet µπορεί να δεσµεύσει κάποιους πόρους κατά την στιγµή της
δηµιουργίας του (βλ. στην συνέχεια την µέθοδο init) και να τους
χρησιµοποιήσει στην συνέχεια για την εξυπηρέτηση όλων των αιτήσεων.
Αυτήν η τεχνική για παράδειγµα χρησιµοποιείται για την δηµιουργία και την
διατήρηση των συνδέσεων µε µία Βάση ∆εδοµένων.
Ουσιαστικά η κάθε αίτηση εξυπηρετείται από το container που χρησιµοποιεί ένα νέο
νήµα εκτέλεσης (thread) για την εξυπηρέτηση της αίτησης από το ίδιο αντικείµενο
που δηµιουργήθηκε όταν έγινε η πρώτη αίτηση. Αυτό βέβαια ενδέχεται να
δηµιουργήσει προβλήµατα όταν το servlet προσπελάζει µεταβλητές που δεν είναι
τοπικές (local variables) στην συνάρτηση που εκτελείται, µια και λόγω συνθηκών
αγώνων δρόµου (race conditions) µπορεί να προκύψουν ασυνέπειες.
Στον παράδειγµα που ακολουθεί έχουµε το servlet VisitCounter.java το οποίο έχει
ένα µετρητή επισκέψεων από την στιγµή που δηµιουργήθηκε. Ο µετρητής αυτός είναι
καθολική µεταβλητή του servlet και όχι κάποια τοπική µεταβλητή της µεθόδου
-
21 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
doGet, έτσι ώστε να διατηρεί την τιµή του ανάµεσα από διαδοχικές κλήσεις της
doGet. Αυτό σηµαίνει όµως πως θα πρέπει η πρόσβαση στην τρέχουσα τιµή αυτής
της µεταβλητής καθώς και η αύξησή της να είναι αδιαίρετη ενέργεια. Αυτό διότι θα
µπορούσε ένα νήµα να ανακτήσει την τρέχουσα τιµή και να διακοπεί πριν να την
αυξήσει από ένα άλλο νήµα το οποίο θα ανακτήσει την ίδια τιµή. Έτσι και οι δύο
αιτήσεις θα δούν τον ίδιο µετρητή επισκέψεων. Για να εξασφαλίσουµε την αδιαίρετη
ανάκτηση και αύξηση του µετρητή επισκέψεων χρησιµοποιούµε συγχρονισµό,
βάζοντας την εντολή ανάκτησης και αύξησης της τιµής της µεταβλητής count σε ένα
synchronized µπλοκ κώδικα που επιτρέπει µόνο σε ένα νήµα να προχωρήσει, αυτό
που θα ανακτήσει το λουκέτο (lock) του αντικειµένου this. Σηµειώνεται πως θα
µπορούσαµε να κάνουµε ολόκληρη την doGet να εκτελείται αποκλειστικά
δηλώνοντας την µέθοδο doGet ως synchronized, αλλά αυτό θα σήµαινε πως µόνο ένα
νήµα θα µπορούσε να εκτελέσει ολόκληρη την doGet κάθε φορά και όλα τα άλλα
νήµατα θα έπρεπε να περιµένουν την ολοκλήρωση της doGet από το νήµα που έχει το
λουκέτο για να συνεχίσουν. Μπορεί στο συγκεκριµένο παράδειγµα να ήταν σχεδόν το
ίδιο, µια και η doGet δεν είναι µεγάλη σε µέγεθος, σε άλλες όµως περιπτώσεις κάτι
τέτοιο µπορεί να µην είναι αποδεκτό.
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class VisitCounter extends HttpServlet {
int count=0;
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException
{
res.setContentType("text/html; charset=Cp1253");
int localCount;
synchronized (this) {
localCount = count++;
}
-
22 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
PrintWriter out = res.getWriter();
out.println("Πλήθος επισκέψεων από τότε που δημιουργήθηκα: " +localCount);
}
}
Παρατηρείστε πως η ανάκτηση του count και η αύξησή του γίνονται µε αµοιβαία
αποκλειστικότητα λόγω του ότι η εντολή localCount = count++ βρίσκεται µέσα σε
ένα synchronized µπλοκ εντολών. Αφού γίνει η τοποθέτηση στην τοπική µεταβλητή
localCount της doGet δεν χρειάζεται αµοιβαία αποκλειστικότητα, µια και οι τοπικές
µεταβλητές είναι διαφορετικές για κάθε νήµα εκτέλεσης.
Επίσης παρατηρείστε πως επειδή το µήνυµα που εµφανίζει το servlet είναι γραµµένο
στα Ελληνικά θα πρέπει να προσδιορίσουµε το charset µε την setContentType σε
Cp1253 (Ελληνική κωδικοσελίδα των Windows). Επίσης θα µπορούσαµε να
χρησιµοποιήσουµε τα ISO-8859-7 (Ελληνική κωδικοσελίδα ISO) ή και UTF-8
(Unicode), που επίσης θα εµφάνιζαν τα Ελληνικά χωρίς προβλήµατα.
Για να δείτε το servlet τοποθετείστε το VisitCounter.class στον κατάλογο
webapps/webprog και φορτώστε το από την διεύθυνση:
http://localhost:8080/webprog/servlet/VisitCounter.
Η μέθοδος init
Η µέθοδος init µπορεί να χρησιµοποιηθεί για την αρχικοποίηση ενός servlet.
Εκτελείται πριν εκτελεσθεί η doGet ή η doPost ή οποιαδήποτε άλλη µέθοδος, την
πρώτη φορά που δηµιουργείται ένα στιγµιότυπο. Υπάρχουν δύο παραλλαγές αυτής
της µεθόδου που είναι οι ακόλουθες:
1. public void init(), και
2. public void init(ServletConfig)
Η πρώτη µορφή χρησιµοποιείται όταν δεν χρειάζεται στην µέθοδο init να
αναφερθούµε στο αντικείµενο ServletConfig το οποίο µπορεί να χρησιµοποιηθεί για
πρόσβαση σε πληροφορίες σχετικά µε τις ρυθµίσεις ενός servlet. Η δεύτερη έχει
πρόσβαση στο αντικείµενο αυτό µια και περνιέται ως παράµετρος, αλλά θα πρέπει
-
23 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
πάντα να θυµηθούµε σαν πρώτη εντολή να καλέσουµε την
super.init(ServletConfig).
Και οι δύο µορφές καλούνται από το servlet container ακριβώς µετά την δηµιουργία
του πρώτου στιγµιοτύπου και πριν εξυπηρετηθεί η πρώτη αίτηση. Επίσης και οι δύο
µορφές ενδέχεται να προκαλέσουν την εξαίρεση ServletException σε περίπτωση που
παρουσιαστούν προβλήµατα. Η εξαίρεση αυτή θα πρέπει να δηλωθεί πως µπορεί να
προκληθεί µε την φράση throws στην δήλωση των µεθόδων.
Η μέθοδος destroy
Η µέθοδος destroy καλείται από το servlet container πριν ένα servlet γίνει µη
διαθέσιµο και αφού έχουν τερµατισθεί όλα τα threads που το προσπελάζουν ή έχει
λήξει η περίοδος µη χρήσης του στιγµιοτύπου για µια εφαρµογή. Αυτήν η µέθοδος
αποτελεί το κατάλληλο σηµείο για εργασίες εκκαθάρισης (clean up), όπως
αποδέσµευση µνήµης ή χειριστών αρχείων (file handles), καθώς και για την
αποθήκευση τυχόν στοιχείων που θα πρέπει να αποθηκευθούν και βρίσκονται στην
µνήµη του servlet.
Ένα παράδειγμα των init και destroy
Για να κάνουµε σαφέστερα τα παραπάνω θα χρησιµοποιήσουµε την init στην
δεύτερη µορφή της για να δηµιουργήσουµε ή να ανοίξουµε ένα αρχείο στον βασικό
κατάλογο της εφαρµογής που βρίσκεται το servlet έτσι ώστε να διαβάσουµε από
εκεί τον µετρητή µε την αρχικοποίηση του servlet. Ο µετρητής επισκέψεων θα
αυξάνεται στην µνήµη του servlet όπως και στο παράδειγµα VisitCounter που είδαµε
προηγουµένως, µόνο που θα αποθηκεύουµε το αποτέλεσµα στο αρχείο στην µέθοδο
destroy έτσι ώστε να είναι διαθέσιµος ο µετρητής επισκέψεων και στο µέλλον.
Ακολουθεί ο κώδικας του PersistentVisitCounter.java :
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
-
24 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
public class PersistentVisitCounter extends HttpServlet {
private int count;
private String filename;

public void init(ServletConfig config)
throws ServletException {
super.init(config);
ServletContext sctx = config.getServletContext();
String path = sctx.getRealPath("/");
filename=path+"PersistentVisitCounter.dat";
try {
FileReader fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);
String scount = br.readLine();
count = Integer.parseInt(scount);
return;
}
catch (FileNotFoundException ignored) {}
catch (IOException ignored) {}
catch (NumberFormatException ignored) {}
count = 0;
}

public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
res.setContentType("text/html; charset=Cp1253");
int localCount;
-
25 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
synchronized (this) {
localCount = count++;
}
PrintWriter out = res.getWriter();
out.println("Πλήθος επισκέψεων από τότε που δημιουργήθηκα: "+localCount);
out.println(filename);
}

public void destroy() {
if (filename!=null) {
try {
FileWriter fw = new FileWriter(filename);
String scount = Integer.toString(count);
fw.write(scount, 0, scount.length());
fw.close();
return;
}
catch (IOException e) {
log("File exception during writing visit counter", e);
}
}
}
}
Στην init συµβαίνουν τα εξής:

Καλείται η super.init(config), όπως πρέπει για κάθε servlet που υπερβαίνει
την µέθοδο init της µορφής που δέχεται ως παράµετρο το ServletConfig
-
26 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
αντικείµενο που δίνει πρόσβαση σε πληροφορίες µε στοιχεία ρυθµίσεων
(configuration) του servlet.

Στην συνέχεια µε την εντολή config.getServletContext() το servlet αποκτά
πρόσβαση στο περιβάλλον (context) της εφαρµογής στην οποία υπάρχει το
servlet. Η µέθοδος getServletContext είναι µέθοδος της τάξης ServletConfig.
Το αντικείµενο που επιστρέφει είναι ένα αντικείµενο ServletContext, το οποίο
παρέχει πληροφορίες για το context στο οποίο εκτελείται το servlet. Εδώ
χρησιµοποιούµε αυτό το αντικείµενο για να βρούµε ποιος είναι ο βασικός
κατάλογος της εφαρµογής στην οποία υπάρχει το servlet.

Η µέθοδος που µας δίνει τον βασικό κατάλογο της εφαρµογής είναι η
getRealPath του αντικειµένου sctx (το ServletContext του servlet). Αυτήν η
µέθοδος παίρνει ως παράµετρο ένα εικονικό όνοµα (virtual name) ενός
καταλόγου ή αρχείου της εφαρµογής και επιστρέφει την φυσική διαδροµή του
εικονικού ονόµατος στον δίσκο που βρίσκεται ο server. Εδώ καλούµε την
getRealPath µε παράµετρο τον βασικό κατάλογο της εφαρµογής και η κλήση
θα επιστρέψει την διαδροµή "c:\Program Files\Apache Tomcat
4.0\webapps\webprog" που είναι η φυσική διαδροµή που αντιστοιχεί στον
βασικό κατάλογο της εφαρµογής webprog στην οποία ανήκει το servlet (εδώ
υποθέτουµε πως ο server είναι εγκατεστηµένος στον εξ ορισµού κατάλογο
που γίνεται η εγκατάσταση του Tomcat 4.0 σε ένα σύστηµα Windows).

Στην συνέχεια προσδιορίζουµε το όνοµα του αρχείου το οποίο είναι καθολική
µεταβλητή του servlet έτσι ώστε να έχει πρόσβαση σε αυτό και η µέθοδος
destroy. Αυτό το όνοµα θα αποτελείται από την συνένωση του ονόµατος του
βασικού καταλόγου της εφαρµογής και του ονόµατος του αρχείου που είναι
PersistentVisitCounter.dat.

Στην συνέχεια δηµιουργούµε ένα BufferedReader για το αρχείο αυτό και
διαβάζουµε τον µετρητή από το αρχείο αυτό. Την πρώτη φορά που θα
εκτελεσθεί αυτό το servlet λόγω του ότι το αρχείο θα είναι νέο και άρα κενό, η
readLine που καλείται στην συνέχεια στον BufferedReader θα επιστρέψει null
και εποµένως θα προκύψει η εξαίρεση NumberFormatException όταν
προσπαθήσουµε να µετατρέψουµε το null σε αριθµό. Έτσι η µεταβλητή count
θα γίνει 0 (η εξαίρεση θα µας οδηγήσει µετά τα catch blocks). Τις επόµενες
φορές που θα εκτελεσθεί η init θα διαβασθεί η τελευταία τιµή που είχε
-
27 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
αποθηκευθεί στο αρχείο και εποµένως θα συνεχίσει ο count από εκεί που είχε
σταµατήσει την τελευταία φορά.
Η µέθοδος doGet είναι ίδια µε την doGet του VisitCounter που συζητήσαµε ήδη.
Η µέθοδος destroy κάνει τα εξής:

Αν το filename δεν είναι null, δηµιουργούµε ένα FileWriter για το αρχείο µε
το όνοµα αυτό και αποθηκεύουµε εκεί την τρέχουσα τιµή του µετρητή. Τέλος
κλείνουµε το αρχείο.

Αν προκύψει κάποια εξαίρεση το µόνο που µπορούµε να κάνουµε είναι να την
γράψουµε στο logfile του Tomcat µε την µέθοδο log του servlet. Η µέθοδος
αυτή παίρνει ως παράµετρο ένα µήνυµα και το αντικείµενο της εξαίρεσης που
προέκυψε. Στον Tomcat η εξαίρεση αυτή θα καταγραφεί στο αρχείο
localhost_log.<ηµεροµηνία>.txt στον κατάλογο logs της εγκατάστασης του
Tomcat και θα περιέχει το όνοµα του servlet, το κείµενο που δώσαµε στην
µέθοδο log ως πρώτη παράµετρο, και το stack trace της εξαίρεσης που
δώσαµε ως δεύτερη παράµετρο.
Επειδή το <tomcat-home>/webapps/webprog/PersistentVisitCounter.dat είναι ένα
αρχείο κειµένου µπορείτε να εξετάσετε τα περιεχόµενά του. Για να δείτε το
αποτέλεσµα της destroy µπορείτε να σταµατήσετε τον Tomcat. Επειδή όταν
σταµατάτε τον Tomcat καλείται η destroy η τιµή του count αποθηκεύεται στο αρχείο
και εποµένως θα δείτε την αλλαγή στην τιµή. Η τιµή αυτή θα ανακτηθεί την επόµενη
φορά που θα δηµιουργηθεί ένα στιγµιότυπο αυτού του servlet από την µέθοδο init.
-
28 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Παραμετρικά servlets
Υπάρχει η δυνατότητα να περάσουµε κάποιες τιµές αρχικοποίησης κατά την
δηµιουργία ενός στιγµιοτύπου του servlet από το container που το διαθέτει. Η
δυνατότητα αυτή έχει δύο όψεις: Η πρώτη είναι το πέρασµα των παραµέτρων
αρχικοποίησης στο servlet και η δεύτερη η ανάκτησή τους από το servlet.
Πέρασμα παραμέτρων αρχικοίησης σε ένα servlet
Στο Java Servlet API δεν προσδιορίζεται πως θα πρέπει να γίνεται το πέρασµα των
παραµέτρων αρχικοποίησης σε ένα servlet. Έτσι είναι ουσιαστικά διαφορετική η
µέθοδος για κάθε server. Εδώ θα συζητήσουµε την µέθοδο που χρησιµοποιείται στον
Tomcat για το πέρασµα των παραµέτρων αρχικοποίησης.
Ο τρόπος µε τον οποίο περνάµε µία παράµετρο αρχικοποίησης στον Tomcat είναι µε
την περιγραφή του servlet στο αρχείο WEB-INF/web.xml. Να θυµίσουµε εδώ πως
στο αρχείο web.xml περιγράφουµε ένα servlet µε την ετικέτα <servlet>...</servlet>.
Ένα από τα εµφωλευµένα στοιχεία αυτής της ετικέτας είναι το <init-param> µε την
ακόλουθη σύνταξη:
<init-param>
<param-name>
όνομα-παραμέτρου
</param-name>
<param-value>
τιμή-παραμέτρου
</param-value>
</init-param>
-
29 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Αν για παράδειγµα θέλαµε να δηµιουργήσουµε µία παράµετρος µε το όνοµα
username και τιµή george, για ένα servlet θα είχαµε µέσα στο στοιχείο servlet ένα
εµφωλευµένο στοιχεί <init-param> µε τα ακόλουθα:
<init-param>
<param-name>
username
</param-name>
<param-value>
george
</param-value>
</init-param>
Ανάκτηση τιμής παραμέτρου από το servlet
Η ανάκτηση της τιµής µιας παραµέτρου γίνεται από την µέθοδο init που όπως είδαµε
εκτελείται πριν το container ικανοποιήσει την πρώτη αίτηση για ένα servlet. Για την
ανάκτηση της τιµής µιας παραµέτρου αρχικοποίησης χρησιµοποιείται η µέθοδος
getInitParameter του αντικειµένου ServletConfig που είναι η παράµετρος της init.
Ο ακόλουθος σκελετός προγράµµατος δείχνει την χρήση της getInitParameter:
...
private String username;
...
public void init(ServletConfig sc) {
super.init(sc);
username = sc.getInitParameter("username");
...
}
...
-
30 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Επειδή η getInitParameter επιστρέφει String αν η τιµή της παραµέτρου είναι
διαφορετικού τύπου θα πρέπει να γίνει η µετατροπή τύπου µετά την ανάκτηση.
Παράδειγμα με παραμέτρους αρχικοποίησης
Στην συνέχεια θα κάνουµε ένα παράδειγµα µε την χρήση των παραµέτρων
αρχικοποίησης. Στο συγκεκριµένο παράδειγµα θα περάσουµε ως παραµέτρους
αρχικοποίησης το όνοµα ενός αρχείου στον δίσκο µε ονόµατα χρηστών και κωδικούς
πρόσβασης. Αυτό το αρχείο θα έχει µία γραµµή κειµένου για κάθε χρήστη µε την
µορφή: <όνοµα-χρήστη>,<κωδικός πρόσβασης>. Το αρχείο αυτό θα είναι το
C:\Program Files\Apache Tomcat 4.0\webapps\webprog\users.dat. Το servlet θα
ανακαλύψει ποιο είναι το αρχείο των κωδικών στην µέθοδο init µια και θα κάνουµε
το όνοµα του αρχείου παράµετρο αρχικοποίησης µε όνοµα filename και τιµή την
διαδροµή του αρχείου στον δίσκο.
Επίσης το class αρχείο για το servlet θα ονοµάζεται ProtectedServlet και θα κάνουµε
το απαραίτητο mapping στο web.xml έτσι ώστε να µπορέσουµε να έχουµε πρόσβαση
στο servlet µε το URI /protected.
Εποµένως το web.xml θα αλλάξει ως εξής:
<web-app>
...
<servlet>
<servlet-name>
protected
</servlet-name>
<servlet-class>
ProtectedServlet
</servlet-class>
<init-param>
<param-name>
filename
-
31 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
</param-name>
<param-value>
C:\Program Files\Apache Tomcat 4.0\webapps\webprog\users.dat
</param-value>
</init-param>
</servlet>
...
<servlet-mapping>
<servlet-name>protected</servlet-name>
<url-pattern>/protected</url-pattern>
</servlet-mapping>

</web-app>
Αφού γίνουν αυτές οι αλλαγές στο web.xml θα πρέπει να σταµατήσουµε και να
ξεκινήσουµε και πάλι τον Tomcat.
Για να δοκιµάσετε αυτό το servlet δηµιουργείστε στον κατάλογο C:\Program
Files\Apache Tomcat 4.0\webapps\webprog\ το αρχείο users.dat και εισάγετε τα
ακόλουθα περιεχόµενα:
george,cangetin
jim,micmac
Έχουµε εποµένως δύο χρήστες: Τον george µε κωδικό cangetin και τον jim µε κωδικό
micmac.
Για το συγκεκριµένο παράδειγµα θα µας χρειαστεί και µία βοηθητική τάξη, η τάξη
User. Ο κώδικάς της ακολουθεί:
public class User {
private String username;
private String password;

-
32 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
public User(String username, String password) {
this.username=username;
this.password=password;
}

public boolean equals(User u) {
if ( (this.username.equals(u.getUsername())) &&
(this.password.equals(u.getPassword())) ) {
return true;
}
return false;
}

public String getUsername() { return username; }

public String getPassword() { return password; }
}
Η τάξη αυτή αναπαριστά έναν χρήστη της σελίδας:

Έχει το όνοµα του χρήστη και τον κωδικό πρόσβασης (µεταβλητές username
και password)

Έναν κατασκευαστή που δέχεται αυτές τις δύο παραµέτρους και θέτει τις
µεταβλητές της τάξης ίσες µε τις παραµέτρους που δέχτηκε.

Μεθόδους get που επιστρέφουν το όνοµα του χρήστη (getUsername) και τον
κωδικό πρόσβασης (getPassword) και

Την µέθοδο equals η οποία παίρνει ως παράµετρο έναν χρήστη και επιστρέφει
true αν το όνοµά του και ο κωδικός του είναι ίδιος µε αυτά του User
αντικειµένου στο οποίο καλείται η µέθοδος (το this).
-
33 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Αφού µεταφράσετε αυτή τη τάξη τίθεται το θέµα πως θα την βρει ο Tomcat όταν θα
αναφερθεί σε αυτήν το ProtectedServlet. Μπορείτε να κάνετε τα εξής:
1. Να βάλετε την τάξη στον κατάλογο WEB-INF/classes της εφαρµογής (στον
ίδιο κατάλογο στον οποίο βρίσκεται και το servlet) Ή
2. Να βάλετε την τάξη σε ένα jar αρχείο (π.χ. µε την εντολή: jar -cvf user.jar
User.class) και να βάλετε το jar αρχείο (στο παράδειγµά µας το user.jar) στον
κατάλογο WEB-INF/lib της εφαρµογής.
Όταν ένα servlet χρειάζεται µία τάξη που δεν είναι τάξη της Java τότε την ψάχνει είτε
στον κατάλογο WEB-INF/lib (στα jar αρχεία που υπάρχουν εκεί) ή στον ίδιο
κατάλογο µε το servlet (στο WEB-INF/classes). Ας ακολουθήσουµε εδώ, για λόγους
διευκόλυνσης, την µέθοδο της τοποθέτησης στο WEB-INF/classes. Για περισσότερες
βοηθητικές τάξεις (π.χ. βιβλιοθήκες τάξεων) είναι καλύτερο να έχετε τις τάξεις αυτές
στον κατάλογο WEB-INF/lib προκειµένου να διατηρήσετε τον κατάλογο WEB-
INF/classes µόνο για τα servlets.
Τέλος ας δούµε το servlet. Το ProtectedServlet.java θα ανακτήσει στην µέθοδο init
την τιµή της παραµέτρου αρχικοποίησης filename που καταχωρήσαµε στο web.xml.
Στην συνέχεια θα ανοίξει το αρχείο των κωδικών την διαδροµή του οποίου θα
ανακτήσει από την παράµετρο αρχικοποίησης filename και θα διαβάσει τα ονόµατα
των χρηστών και τους κωδικούς τους. Η init για κάθε ζεύγος (όνοµα-χρήστη,
κωδικός) θα δηµιουργήσει έναν νέο χρήστη και θα τον τοποθετήσει στο Vector users.
Το servlet υποστηρίζει την µέθοδο doGet (για να µην χρειαστεί να κάνουµε φόρµα
για να το δοκιµάσουµε). Στην doGet ανακτούµε από την αίτηση του χρήστη (δηλ. από
το αντικείµενο request) µε την µέθοδο getParameter την τιµή της παραµέτρου
username και της παραµέτρου password, που είναι αυτά που έδωσε ο χρήστης που
ζήτησε την σελίδα. Για παράδειγµα ο χρήστης µπορεί να ζητήσει την σελίδα ως εξής:
http://localhost:8080/webprog/protected?username=george&password=cangetin
οπότε και θα έχει πρόσβαση γιατί ο χρήστης µε όνοµα χρήστη "george" και κωδικό
πρόσβασης "cangetin" υπάρχει στο αρχείο users.dat.
Η doGet για να ελέγξει αν ο χρήστης επιτρέπεται να δει το απόρρητο περιεχόµενο της
σελίδας, δηµιουργεί έναν χρήστη (τον u) µε τα στοιχεία που έδωσε ο χρήστης. Στην
συνέχεια διατρέχει το Vector users (µε την χρήση µιας Enumeration) και ελέγχει µε
την User.equals() αν κάποιος χρήστης στο Vector users.dat έχει αυτά τα στοιχεία. Αν
-
34 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
ισχύει αυτό εµφανίζει τα απόρρητα στοιχεία, διαφορετικά εµφανίζει το µήνυµα "∆εν
σε ξέρω. Λυπάµαι!".
Ο κώδικας του ProtectedServlet.java είναι ο εξής:
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ProtectedServlet extends HttpServlet {
private Vector users;
public void init(ServletConfig config)
throws ServletException {
super.init(config);
String filename = config.getInitParameter("filename");
try {
users = new Vector();
FileReader fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);
String line;
while ( (line = br.readLine()) != null) {
int commaPos = line.indexOf(",");
String un = line.substring(0, commaPos);
String pw = line.substring(commaPos+1);
User u = new User(un, pw);
users.add(u);
}
br.close();
}
-
35 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
catch (IOException ignored) {}
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=ISO-8859-7");
String username = request.getParameter("username");
String password = request.getParameter("password");
User u = new User(username, password);
PrintWriter out = response.getWriter();
Enumeration e = users.elements();
boolean authenticated = false;
while (e.hasMoreElements()) {
User lu = (User) e.nextElement();
if (lu.equals(u)) {
out.println("<h1><center>Καλώςήλθες
αφέντη...</center></h1>");
out.println("Πολύ απόρρητες πληροφορίες...");
authenticated=true;
break;
}
}
if (!authenticated) {
out.println("Δεν σε ξέρω. Λυπάμαι!");
}
out.close();
}
}
-
36 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Άλλες σχετικές μέθοδοι με τις παραμέτρους
αρχικοποίησης ενός servlet
Μία ακόµα σχετική µέθοδος της διασύνδεσης javax.Servlet.ServletConfig σχετική µε
τις παραµέτρους αρχικοποίησης είναι η getParameterNames() η οποία επιστρέφει ένα
αντικείµενο Enumeration µε String τα οποία είναι τα ονόµατα των παραµέτρων
αρχικοποίησης όπως αυτά δηλώθηκαν στο web.xml. Αν δεν υπάρχουν παράµετροι
αρχικοποίησης θα επιστρέψει ένα κενό αντικείµενο Enumeration.

-
37 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Παρακολούθηση της συνόδου του
χρήστη
Το HTTP είναι ένα stateless προτόκολλο. Αυτό σηµαίνει πως κάθε φορά που ο
χρήστης ζητά µία σελίδα από έναν web server η αίτηση αυτή δεν περιέχει
πληροφορίες σχετικά µε το ποιος κάνει την αίτηση αυτή ή ποιες αιτήσεις είχε κάνει
προηγούµενα. Αυτό δηµιουργεί προβλήµατα όταν θέλουµε να παρακαλοθήσουµε τι
κάνει ο χρήστης σε διαδοχικές σελίδες που επισκέπτεται σε ένα website.
Υπάρχουν τρεις ευρύτατα διαδεµένες µέθοδοι για την παρακολούθηση της συνόδου
του χρήστη (session tracking):
1. Cookies
2. URL rewritting, και
3. Κρυµµένα πεδία φόρµας
Αν και µε τα Java Servlets υπάρχει η δυνατότητα απευθείας να χρησιµοποιηθούν
αυτές οι µέθοδοι (για παράδειγµα υπάρχει ένα υψηλού επιπέδου API µε µεθόδους για
την διαχείριση των Cookies, βλ. τάξη javax.servlet.http.Cookie, και τις µεθόδους
HttpServletResponse.addCookie(Cookie cookie) και
HttpServletRequest.getCookies()), για την παρακολούθηση της συνόδου του χρήστη
είναι πολύ πιο εύκολο για ένα προγραµµατιστή να χρησιµοποιήσει απευθείας το API
παρακολούθησης συνόδου (session tracking API) που παρέχεται µέσω της
διασύνδεσης HttpSession του πακέτου javax.servlet.http.
Ανάκτηση της συνόδου του χρήστη
Για να βρούµε µέσα από ένα servlet ποιο είναι το HttpSession αντικείµενο που
σχετίζεται µε την αίτηση ενός χρήστη, χρησιµοποιούµε την µέθοδο
HttpServletRequest.getSession. Αυτήν έχει δύο παραλλαγές:
-
38 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
1. HttpSession getSession(): Ανακτά το αντικείµενο HttpSession που σχετίζεται
µε την σύνοδο ενός χρήστη µε το σύστηµα. Αν δεν υπάρχει αντικείµενο
συνόδου που συσχετίζεται µε αυτή τη σύνοδο του χρήστη (π.χ. είναι η πρώτη
αίτηση του χρήστη), τότε δηµιουργείται ένα νέο HttpSession αντικείµενο για
την σύνοδο του χρήστη και επιστρέφεται.
2. HttpSession getSession(boolean create): Η λειτουργία είναι παρεµφερής µε
την προηγούµενη µέθοδο. Η µόνη διαφορά είναι πως η boolean παράµετρος
καθορίζει αν θα δηµιουργηθεί νέα σύνοδος σε περίπτωση που δεν υπάρχει
(create=true) ή όχι (create=false).
Μέθοδοι του αντικειμένου HttpSession
Αφού έχουµε ένα αντικείµενο HttpSession µπορούµε να προσθέσουµε σε αυτό
αντικείµενα και να τα ανακτήσουµε αργότερα. Επειδή το HttpSession αντικείµενο
είναι προσπελάσιµο µέσω της µεθόδου HttpServletResponse.getSession(), τα επόµενα
servlets που θα ακολουθήσουν θα έχουν πρόσβαση στα αντικείµενα που θα βάλουµε
µέσα στο HttpSession µιας συνόδου.
Οι βασικότερες µέθοδοι του HttpSession interface είναι οι εξής:
• public void setAttribute(String name, Object value)
Η setAttribute εισάγει ένα αντικείµενο (το value) στην σύνοδο του
χρήστη, χρησιµοποιώντας το όνοµα name γι' αυτό το αντικείµενο. Αν
υπήρχε ένα αντικείµενο µε αυτό το όνοµα ήδη, το αντικείµενο αυτό
αντικαθίσταται από το νέο αντικείµενο. Αφού εκτελεσθεί αυτή η
µέθοδος και εφόσον το νέο αντικείµενο που εισάγουµε υλοποιεί την
διασύνδεση HttpSessionAttributeListener καλείται η µέθοδος
valueBound στο αντικείµενο. Η µέθοδος αυτή είναι µέθοδος της
διασύνδεσης HttpSessionAttributeListener. Αν το αντικείµενο
αντικαθιστά ένα άλλο αντικείµενο που υλοποιεί την διασύνδεση
HttpSessionAttributeListener τότε εκτελείται στο αντικείµενο που
αντικαθίσταται η µέθοδος valueUnbound του αντικειµένου αυτού.
• public java.lang.Object getAttribute(String name)
-
39 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Επιστρέφει το αντικείµενο που είχει εισαχθεί στην σύνοδο µε το όνοµα που
δίνεται ως παράµετρος. Αν δεν είχε γίνει εισαγωγή αντικειµένου µε αυτό το
όνοµα στην σύνοδο, τότε η µέθοδος επιστρέφει null.
• public java.util.Enumeration getAttributeNames()
Επιστρέφει µία Enumeration µε Strings που είναι τα ονόµατα όλων των
αντικειµένων που έχουν εισαχθεί σε µία σύνοδο.
• public void removeAttribute(String name)
Αφαιρεί το αντικείµενο το οποίο είχε εισαχθεί στην σύνοδο µε το όνοµα που
δίνεται ως παράµετρος. Αν η σύνοδος δεν έχει αντικείµενο που έχει
συσχετισθεί µε αυτό το όνοµα τότε η µέθοδος αυτή δεν κάνει τίποτα.
Αφού η µέθοδος εκτελεσθεί και εφόσον το αντικείµενο που αφαιρείται από
την σύνδεση υλοποιεί την διασύδεση HttpSessionBindingListener καλείται η
µέθοδος valueUnbound στο αντικείµενο.
• public int getMaxInactiveInterval()
Αυτή η µέθοδος επιστρέφει το µέγιστο διάστηµα µεταξύ δύο διαδοχικών
αιτήσεων για το servlet για το οποίο το servlet container δεν ακυρώνει την
σύνοδο.
• public void setMaxInactiveInterval(int interval)
Αυτήν η µέθοδος θέτει το µέγιστο διάστηµα µεταξύ δύο διαδοχικών αιτήσεων
για το servlet για το οποίο το servlet container δεν ακυρώνει την σύνοδο.
• public String getId()
Επιστρέφει ένα String µε το αναγνωριστικό της συνόδου (session ID). Αυτό
παράγεται όταν δηµιουργείται η σύνοδος.
• public void invalidate()
Αυτήν η µέθοδος ακυρώνει την σύνοδο και αποδεσµεύει τα ονόµατα και τα
αντικείµενα που είχαν εισαχθεί σε αυτήν.
• public boolean isNew()
Αυτήν η µέθοδος επιστρέφει true εφόσον µία σύνοδος που επιστράφηκε από
την HttpServletResponse.getSession() είναι νέα και false διαφορετικά.
Τρόποι υλοποίησης συνόδων
-
40 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Ο τρόπος που υλοποιείται η αναγνώριση της συνόδου είναι είτε µε Cookies είτε µε
URL rewritting. Με την πρώτη µέθοδο αποθηκεύεται στον browser του πελάτη ένα
Cookie (το Cookie παράγεται αυτόµατα από το Container και δεν χρειάζεται να
ανησυχεί ο προγραµµατιστής γι' αυτό). Στις επόµενες αιτήσεις το container ανακτά το
Cookie και µε βάση αυτό γνωρίζει αν πρόκειται για αίτηση της ίδιας συνόδου ή
διαφορετική σύνοδο. Με την δεύτερη µέθοδο το αναγνωριστικό της συνόδου (session
ID) προστίθεται στα URL που ζητάει ο χρήστης από αίτηση σε αίτηση, έτσι ώστε το
container να γνωρίζει για ποια σύνοδο πρόκειται. Συνήθως τα διάφορα servlet
containers χρησιµοποιούν Cookies και εφόσον δεν υποστηρίζονται από τον browser
(π.χ. ο χρήστης τα έχει απενεργοποιήσει για λόγους ασφαλείας) το container
χρησιµοποιεί URL rewritting.
Το ωραίο µε τα παραπάνω είναι πως ο προγραµµατιστής του servlet δεν χρειάζεται να
ανησυχεί για τον τρόπο µε τον οποίο υλοποιείται η αναγνώριση της συνόδου, µια και
η όλη διαδικασία είναι εσωτερική υπόθεση του container.
Υπάρχουν παρόλα αυτά δύο παρενέργειες της πιο πάνω διαδικασίας:

Όταν ο προγραµµατιστής περιλαµβάνει µέσα στα servlet του συνδέσµους σε
άλλα servlets µε την ετικέτα <a href> θα πρέπει να τα κωδικοποιεί µε την
µέθοδο HttpServletResponse.encodeURL(String url). Η µέθοδος αυτή
παίρνει ως παράµετρος ένα String που είναι το URL που θα έγραφε ο
προγραµµατιστής φυσιολογικά µέσα στην ετικέτα. Απλά η µέθοδος προσθέτει
στο URL αυτό το sessionID στην περίπτωση που χρησιµοποιείται URL
rewritting για την αναγνώριση της συνόδου.

Η δεύτερη παρενέργεια εντοπίζεται στις περιπτώσεις που από ένα servlet
χρησιµοποιούµε την µέθοδο HttpServletResponse.sendRedirect(String
location). Η µέθοδος sendRedirect προωθεί την αίτηση του χρήστη σε ένα νέο
servlet στο URL location που δίνεται ως παράµετρος. Επειδή το location είναι
URL θα πρέπει να κωδικοποιηθεί ώστε να προστεθεί το αναγνωριστικό της
συνόδου στην περίπτωση που χρησιµοποιείται URL rewritting για την
αναγνώριση της συνόδου. Επειδή οι κανόνες της κωδικοποίησης αυτής
διαφέρουν από τους κανόνες που χρησιµοποιούνται για τους κανονικούς
συνδέσµους (αυτούς µε την ετικέτα <a href>) θα πρέπει για την κωδικοποίηση
της διεύθυνσης της sendRedirect να χρησιµοποιήσουµε την µέθοδο
HttpServletResponse. encodeRedirectURL(String URL)
-
41 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Ένα παράδειγμα παρακολούθησης συνόδου
Στο παράδειγµα που ακολουθεί θα κάνουµε µία εφαρµογή στην οποία θα έχουµε τα
ακόλουθα:
1. Το servlet ProtectedResource: Το servlet αυτό ελέγχει αν ο χρήστης έχει
προηγουµένως πιστοποιηθεί ανακτώντας µία µεταβλητή συνόδου, την
logon.isDone, η οποία θα πρέπει να υπάρχει.
Αν δεν υπάρχει τότε το servlet θα ανακατευθύνει τον χρήστη σε µία HTML
φόρµα σύνδεσης στην οποία ο χρήστης θα δίνει το όνοµα και τον κωδικό του,
αφού πρώτα θέσει σε µία µεταβλητή συνόδου, την login.target, το URL του
έτσι ώστε αν η σύνδεση πετύχει ο χρήστης να κατευθυνθεί και πάλι πίσω στο
servlet που ζήτησε αρχικά. Αν υπάρχει η logon.isDone το servlet θα εµφανίζει
το απόρρητο περιεχόµενό του.
2. Την login.htm: Αυτή είναι η φόρµα σύνδεσης. Ο χρήστης θα δίνει εκεί το
όνοµα και τον κωδικό του. Το action της φόρµας θα είναι το servlet
LoginHandler.
3. Το servlet LoginHandler: Το servlet αυτό θα ανακτά το όνοµα και τον κωδικό
που έδωσε ο χρήστης στην φόρµα και αν είναι έγκυρα θα ανακατευθύνει τον
χρήστη στο URL της µεταβλητής συνόδου login.target ( η οποία είχε τεθεί
όταν ο χρήστης απέτυχε να προσπελάσει απευθείας τον προστατευµένο πόρο).
Αν δεν είναι έγκυρα τότε θα εµφανίζει ένα µήνυµα λάθους και ένα σύνδεσµο
πίσω στη φόρµα σύνδεσης έτσι ώστε ο χρήστης να προσπαθήσει να συνδεθεί
και πάλι µε την εφαρµογή.
Ο κώδικας για την φόρµα και τα δύο servlets ακολουθεί:
Login.htm
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1253">
<title>Σύνδεση</title>
-
42 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
</head>
<body>
<form ACTION="/webprog/servlet/LoginHandler" METHOD="POST">
<div align="center"><center><table BORDER="0">
<tr>
<td COLSPAN="2"><div align="center"><center><p>Καλώς ήλθατε! Δώστε
όνομα χρήστη<br>
και κωδικό για να συνδεθείτε. </td>
</tr>
<tr align="center">
<td><div align="right"><p><b>Όνομα χρήστη:</b> </td>
<td><input TYPE="TEXT" NAME="name" VLAUE SIZE="15"> </td>
</tr>
<tr align="center">
<td><div align="right"><p><b>Κωδικός:</b> </td>
<td><input TYPE="PASSWORD" NAME="passwd" VALUE SIZE="15"> </td>
</tr>
<tr align="center">
<td COLSPAN="2"><div align="center"><center><p><input TYPE="SUBMIT" VALUE=" OK ">
</td>
</tr>
</table>
</center></div>
</form>
</body>
</html>
-
43 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
LoginHandler.java
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class LoginHandler extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html; charset=Cp1253");
PrintWriter out = res.getWriter();
String name = req.getParameter("name");
String passwd = req.getParameter("passwd");
if (!allowUser(name, passwd)) {
out.println("<HTML><HEAD><TITLE>Ανεπιβεβαίωτος κωδικός</TITLE></HEAD>");
out.println("<BODY>Το όνομά σας και ο κωδικός είναι άκυρα.<BR>");
out.println("Προσπαθήστε <A HREF=\"/webprog/login.htm\">ξανά</A>");
out.println("</BODY></HTML>");
}
else {
HttpSession session = req.getSession();
session.setAttribute("logon.isDone", name);
String target = (String) session.getAttribute("login.target");
if (target != null) {
res.sendRedirect(target);
return;
}
-
44 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος

res.sendRedirect(req.getScheme() + "://" +
req.getServerName() + ":" + req.getServerPort());
}
}
protected boolean allowUser(String user, String passwd) {
if (user.equals("george") && passwd.equals("cangetin"))
return true;
else
return false;
}
}
ProtectedResource.java
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ProtectedResource extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html; charset=Cp1253");
PrintWriter out = res.getWriter();
HttpSession session = req.getSession();
Object done = session.getAttribute("logon.isDone");
if (done == null) {
session.setAttribute("login.target","/webprog/servlet/ProtectedResource");
-
45 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
res.sendRedirect("/webprog/login.htm");
return;
}
out.println("Απόρρητο περιεχόμενο");
}
}
-
46 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
Σχεσιακές ΒΔ, SQL και JDBC
Οι εφαρµογές του ∆ιαδικτύου σήµερα παρέχουν δυνατότητες πρόσβασης σε
πληροφορίες που βρίσκονται αποθηκευµένες σε Βάσεις ∆εδοµένων (Β∆-DataBases).
Τα Συστήµατα ∆ιαχείρισης Βάσεων ∆εδοµένων (DBMS - DataBase Management
Systems) που χρησιµοποιούνται στην µεγάλη πλειοψηφία των εφαρµογών είναι οι
λεγόµενες Σχεσιακές Βάσεις ∆εδοµένων (Relational Databases).
Η κλασική δοµή µε την οποία κατασκευάζονται εφαρµογές που προσπελάζουν Β∆ µε
τα java servlets είναι η ακόλουθη:

Όπως φαίνεται και από την πιο πάνω εικόνα η εφαρµογή δοµείται σε τρία επίπεδα (3-
tier architecture).

Στο Επίπεδο Παρουσίασης ο χρήστης χρησιµοποιεί HTML σελίδες, Java
Applets κλπ., για να αποστείλλει δεδοµένα στο δεύτερο επίπεδο της
επεξεργασίας µέσω HTTP

Στο Επίπεδο Επεξεργασίας τα servlets επεξεργάζονται την αίτηση του χρήστη
εφαρµόζοντας στα δεδοµένα τους κανόνες της επιχείρησης και στην συνέχεια
επικοινωνούν µε την Βάση ∆εδοµένων µέσω JDBC
-
47 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος

Στο Επίπεδο ∆εδοµένων υπάρχει το Σ∆Β∆ στο οποίο αποθηκεύονται τα
δεδοµένα.
Λίγα λόγια για τις Σχεσιακές Βάσεις Δεδομένων
Μία Σχεσιακή Βάση ∆εδοµένων (Relational DataBase) είναι ένα σύνολο πινάκων που
συσχετίζονται µεταξύ τους έτσι ώστε να αποφευχθεί η επανάληψη των ίδιων
δεδοµένων σε δύο ή και περισσότερους πίνακες. Για παράδειγµα θα µπορούσαµε να
είχαµε έναν πίνακα φοιτητών STUDENTS µε τα ακόλουθα στοιχεία (SID, SFNAME,
SLNAME) για τον κωδικό του φοιτητή, το όνοµα και το επώνυµό του και έναν άλλο
πίνακα COURSES µε µαθήµατα µε τα ακόλουθα στοιχεία (CID, CTITLE,
CDESCRIPTION) για τον κωδικό του µαθήµατος, τον τίτλο του και µία περιγραφή
του. Αν θέλαµε να καταγράψουµε την εγγραφή ενός φοιτητή σε ένα ή περισσότερα
µαθήµατα θα µπορούσαµε να δηµιουργήσουµε ένα πίνακα REGISTRATION µε τα
ακόλουθα στοιχεία (SID, CID, MARK) που θα περιείχε γραµµές µε τους κωδικούς
του φοιτητή και του µαθήµατος στο οποίο έχει εγγραφεί και µε τον βαθµό που πήρε ο
φοιτητής στο µάθηµα αυτό.
Για παράδειγµα οι πίνακες που ακολουθούν περιέχουν κάποια στοιχεία για πιθανούς
φοιτητές, µαθήµατα και εγγραφές:

Πίνακας STUDENTS:
SID
SFNAME
SLNAME
1
ΓΙΩΡΓΟΣ
∆ΗΜΗΤΡΙΟΥ
2
ΠΑΥΛΟΣ
ΠΑΠΑ∆ΗΜΟΥΛΗΣ



Πίνακας COURSES:
CID
CTITLE
CDESCRIPTION
1
WEB
PROGRAMMING
ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΩΝ ΠΟΥ ΤΡΕΧΟΥΝ ΣΤΟ
INTERNET ...
-
48 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
2
ΛΕΙΤΟΥΡΓΙΚΑ
ΣΥΣΤΗΜΑΤΑ
ΑΝΑΛΥΣΗ ΤΩΝ ΤΜΗΜΑΤΩΝ ΑΠΟ ΤΑ ΟΠΟΙΑ
ΑΠΟΤΕΛΟΥΝΤΑΙ ΤΑ ΣΥΓΧΡΟΝΑ Λ.Σ....
Πίνακας REGISTRATION:
SID
CID
MARK
1
1
7.2
1
2
6.5
2
1
8
Από τα περιεχόµενα του πίνακα REGISTRATION προκύπτει πως ο φοιτητής µε
κωδικό 1 (∆ΗΜΗΤΡΙΟΥ) πήρε στο µάθηµα µε κωδικό 1 (WEB PROGRAMMING)
τον βαθµό 7.2 και στο µάθηµα µε κωδικό 2 (ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ) τον
βαθµό 6.5. Επίσης ο φοιτητής µε κωδικό 2 (ΠΑΠΑ∆ΗΜΟΥΛΗΣ) πήρε στο µάθηµα
µε κωδικό 1(WEB PROGRAMMING) τον βαθµό 8.
Το πεδίο SID για τον πίνακα STUDENTS ονοµάζεται πρωτεύον κλειδί (primary key)
γιατί δεν µπορεί να έχει την ίδια τιµή για δύο διαφορετικές εγγραφές (για δύο
διαφορετικές γραµµές του πίνακα STUDENTS). Το πρωτεύον κλειδί για τον πίνακα
COURSES είναι το CID. Τέλος το πρωτεύον κλειδί για τον πίνακα REGISTRATION
είναι το σύνθετο (composite) κλειδί (SID, CID). Τα SID και CID στον πίνακα
REGISTRATION ονοµάζονται ξένα κλειδιά (foreign keys) για τον πίνακα
REGISTRATION διότι είναι πρωτεύοντα κλειδιά των άλλων δύο πινάκων.
Οι πίνακες STUDENTS και COURSES συσχετίζονται µεταξύ τους µε τις εγγραφές
του πίνακα REGISTRATION. Παρατηρείστε πως µε αυτή την υλοποίηση δεν υπάρχει
επανάληψη τιµών πέρα από τα ξένα κλειδιά τα οποία επαναλαµβάνονται στον πίνακα
REGISTRATION. ∆ηλαδή για παράδειγµα δεν υπάρχει πουθενά δύο φορές το όνοµα
του φοιτητή ή ο τίτλος του µαθήµατος. Οι πληροφορίες του πίνακα REGISTRATION
είναι αρκετές για να µας δώσουν τις πληροφορίες της συσχέτισης των δύο άλλων
πινάκων.
Με αυτή την υλοποίηση δεν υπάρχει ανάγκη αν αλλάξει για παράδειγµα ο τίτλος ή η
περιγραφή ενός µαθήµατος να κάνουµε την αλλαγή σε πολλά σηµεία. Αρκεί η
αλλαγή σε µόνο ένα σηµείο. Αυτό που θα χρειάζοταν να αλλάξει σε πολλά σηµεία, αν
άλλαζε, θα ήταν για παράδειγµα ο κωδικός του φοιτητή ή του µαθήµατος. Γι' αυτό
ακριβώς το λόγο είναι λάθος να αποδίδουµε τον ρόλο πρωτεύοντος κλειδιού σε πεδία
που περιέχουν πληροφορίες που δεν είναι στον απόλυτο έλεγχό µας. Για παράδειγµα
-
49 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
θα µπορούσε κανείς να µπει στον πειρασµό να χρησιµοποιήσει για πρωτεύον κλειδί
των φοιτητών τον αριθµό της ταυτότητας του κάθε φοιτητή, ο οποίος είναι εγγυηµένα
διαφορετικός για κάθε φοιτητή. Κάτι τέτοιο θα ήταν κακή ιδέα, µια και είναι
θεωρητικά τουλάχιστον δυνατόν να αλλάξουν οι αριθµοί ταυτότητας µε βάση
απόφαση της κυβέρνησης. Τότε θα χρειάζονταν να αλλάξει η τιµή αυτή σε πολλά
σηµεία της Β∆, κάτι που σε µεγάλες Β∆ µπορεί να αποτελέσει σοβαρό πρόβληµα και
πηγή λαθών. Έτσι τα πρωτεύοντα κλειδιά θα πρέπει να είναι τεχνητές τιµές στον
απόλυτο έλεγχό µας, και δεν θα πρέπει να είναι φορείς οποιασδήποτε πληροφορίας,
δηλ. δεν θα πρέπει να σηµαίνουν τίποτα.Ο µοναδικός τους ρόλος θα πρέπει να είναι η
διάκριση των εγγραφών και τίποτα άλλο.
Όπως είναι αυτονόητο τα λίγα αυτά λόγια δεν είναι παρά µόνο µία µικρή εισαγωγή
στις σχεσιακές Β∆ για τους σκοπούς του συγκεκριµένου µαθήµατος. Για
περισσότερρες πληροφορίες θα πρέπει να διαβάσετε ένα από τα πολλά καλά βιβλία
γύρω από το θέµα.
Διαχείριση ΒΔ με την SQL
Για την διαχείριση των σχεσιακών Β∆ υπάρχει µία πρότυπη γλώσσα που
υποστηρίζεται από όλα τα µεγάλα Σ∆Β∆ και ονοµάζεται SQL (Structured Query
Language). Με τις εντολές της γλώσσας αυτής µπορεί κανείς να δηµιουργήσει Β∆, να
δηµιουργήσει πίνακες και ευρετήρια, να εισάγει δεδοµένα σε πίνακες, να αναζητήσει
δεδοµένα σε πίνακες, να διαγράψει δεδοµένα από πίνακες κλπ.
Η SQL είναι µία δηλωτική γλώσσα (declarative language) στην οποία διατυπώνουµε
τι θέλουµε να γίνει και αυτό γίνεται, χωρίς να πούµε πως ακριβώς θα γίνει αυτό που
θέλουµε. Αυτό είναι σε αντίθεση µε αυτό που συµβαίνει στις λεγόµενες
διαδικασιακές γλώσσες προγραµµατισµού (όπως η C/C++ ή η Java) στις οποίες ο
προγραµµατιστής διατυπώνει ακριβώς πως θα γίνει µια επεξεργασία. Έτσι είναι
ευθύνη του Σ∆Β∆ να βρει πως θα εκτελέσει την εντολή µας και συνήθως αυτό γίνεται
µε τον βέλτιστο δυνατό τρόπο. Αυτή η ιδέα επιτρέπει την ανεξαρτοποίηση της
φυσικής µορφής των δεδοµένων στο δίσκο από τους τρόπους που τα προσπελάζουµε.
Έτσι αν θέλαµε µε την SQL να δούµε την εγγραφή του πίνακα STUDENTS για τον
φοιτητή µε επώνυµο 'ΠΑΠΑ∆ΚΗΣ', θα δίναµε την ακόλουθη εντολή SELECT της
SQL:
-
50 -

Προγραµµατισµός Internet µε τα Java Servlets Κακαρόντζας Γιώργος
SELECT * FROM STUDENTS WHERE LNAME = 'ΠΑΠΑΔΑΚΗΣ';
που σηµαίνει: Επέλεξε όλα τα πεδία (*) από τον πίνακα STUDENTS (FROM
STUDENTS) για τα οποία το επώνυµο είναι 'ΠΑΠΑ∆ΑΚΗΣ' (WHERE
LNAME='ΠΑΠΑ∆ΑΚΗΣ'). Αυτήν η ερώτηση (query) θα εκτελεσθεί από το Σ∆Β∆
το οποίο θα καταστρώσει ένα σχέδιο για την εκτέλεσή της (Query Execution Plan).
Αν για παράδειγµα υπάρχει, ευρετήριο µε βάση το οποίο µπορεί να γίνει η αναζήτηση
(ευρετήριο µε βάση το επώνυµο στην συγκεκριµένη περίπτωση) τότε µπορεί να
χρησιµοποιηθεί για να γίνει η αναζήτηση πιο γρήγορα. Αν όχι τότε η αναζήτηση θα
γίνει ακολουθιακά. Το σηµαντικό είναι πως η εντολή SELECT είναι ίδια και στις δύο
περιπτώσεις. Γι' αυτό λέµε πως τα δεδοµένα είναι ανεξάρτητα από τα προγράµµατα
που τα επεξεργάζονται (data indepedence principle).
Η εκµάθηση της SQL που έχει εντολές όπως η CREATE DATABASE για την
δηµιουργία µιας Β∆, CREATE TABLE για την δηµιουργία ενός πίνακα, INSERT
INTO για την εισαγωγή εγγραφών σε ένα πίνακα, SELECT για την αναζήτηση
εγγραφών σε πίνακες, UPDATE για την ενηµέρωση των τιµών σε ένα πίνακα,
DELETE για την διαγραφή εγγραφών από ένα πίνακα κλπ. είναι έξω από τα πλαίσια
αυτού του µαθήµατος και αντικείµενο ενός µαθήµατος για Β∆. Πάντως σε αυτό το
µάθηµα όσες εντολές της SQL θα χρησιµοποιήσουµε θα τις εξηγήσουµε.
Μια καλή πηγή για πληροφορίες γύρω από την SQL µε tutorials στο Internet
βρίσκεται στο http://www.sql.org/online_resources.html#beginner
MySQL
Σε αυτά τα µαθήµατα θα χρειαστούµε ένα Σ∆Β∆. Επειδή τα εµπορικά Σ∆Β∆ είναι
αρκετά ακριβά, δεν θα υποθέσουµε πως µπορείτε να αγοράσετε ένα. Θα
χρησιµοποιήσουµε ένα ελεύθερο για χρήση Σ∆Β∆ την MySQL. Η MySQL είναι ένα