Lihtsaks trükkimiseks tuleb luua liidest Printable realiseeriv klass, kus meetodis print öeldakse, kuidas tuleb trükkida. Printerisse joonistamine käib samuti graafilise konteksti Graphics abil nagu ekraanile või mällugi joonistamine. Meetodi print parameetrina tuleva PageFormat'i abil saab teada, kui suure trükitava lehega tegemist on ning millisele osale lehest on võimalik joonistada. Enamasti on lehe serva määratud vaikimisi selline osa, kuhu joonistada ei saa. Joonistuskõlbuliku osa alguse x-koordinaadi annab getImageableX(). Samuti saab PageFormat'i käest küsida y-koordinaati ning joonistatava ala kõrgust ja laiust. Siin näites transleeritakse graafilise konteksti nullkoht joonistatava ala algusesse. Kolmanda parameetrina tulev leheküljenumber näitab, millist lehekülge soovitakse trükkida. Isendil on täiesti võimalik mitmele leheküljele trükkida. Lihtsalt tuleb meetodis print igale leheküljenumbrile vastavalt reageerida. Kui vastava numbriga lehekülge ei soovita trükkida, peab meetod tagastama väärtuse Printable.NO_SUCH_PAGE, muul juhul Printable.PAGE_EXISTS.
Trükkimise käivitamiseks luuakse isend tüübist PrinterJob, määrakse, milline Printable oskusega isend trükitöö ära teeb ning siis palutakse trükkima hakata.
import java.awt.print.*;
import java.awt.*;
public class Trykk1{
public static
void main(String argumendid[])
throws PrinterException{
PrinterJob
pj=PrinterJob.getPrinterJob();
pj.setPrintable(new Trykitoo1());
pj.print();
}
}
class Trykitoo1 implements Printable{
public int
print(Graphics g, PageFormat pf, int lk)
throws PrinterException{
if(lk>0)
return Printable.NO_SUCH_PAGE;
g.translate((int)pf.getImageableX(), (int)pf.getImageableY());
g.drawOval(10, 10, 200, 200);
return
Printable.PAGE_EXISTS;
}
}
Kuna nii ekraanile kui printerisse joonistab klassi Graphics järglane, siis saab joonistamisel kasutada sama meetodit. Siin näites joonistatakse mõlemasse meetodi paint abil. Programm loob ekraanile nupu ning omaloodud komponendi Kiri2. Nupule vajutades trükitakse Kiri2 printerisse. Trükkimine on korraldatud nii, et vajutamise peale trükitakse Kiri2 tüüpi isendit 2 lehekülge, kummalegi lehele joonistatakse tema kujutis ning lehe alla kirjutatakse lehekülje number. Klassi PrinterJob meetod printDialog kutsub välja dialoogiakna, kust kasutaja saab määrata printerit ning väljastatavate lehekülgede numbreid ja koopiate arvu.
import java.awt.*;
import java.awt.event.*;
import java.awt.print.*;
class Kiri2 extends Canvas implements Printable {
public void
paint(Graphics g) {
g.setColor(Color.black);
int W =
(int)getSize().getWidth();
int H =
(int)getSize().getHeight();
g.drawRect(1, 1, W-3, H-3);
g.drawString("Tere!", W/2, H/2);
}
public int
print(Graphics g, PageFormat pf, int lk)
throws PrinterException {
if (lk >=
2) {
return
Printable.NO_SUCH_PAGE;
}
g.translate((int)pf.getImageableX(), (int)pf.getImageableY());
g.setColor(Color.black);
paint(g);
g.drawString("lk nr. "+(lk+1), 100,
(int)pf.getImageableHeight()-50);
return
Printable.PAGE_EXISTS;
}
}
public class Trykk2 extends Panel implements
ActionListener {
Kiri2
kiri=new Kiri2();
Button b
= new Button("Tryki");
public
Trykk2() {
b.addActionListener(this);
add(b);
kiri.setSize(100, 50);
add(kiri);
}
public void
actionPerformed(ActionEvent e) {
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(kiri);
try {
if(pj.printDialog())
pj.print();
} catch
(Exception PrintException) { }
}
public
static void main(String s[]) {
Frame f
= new Frame("Trykkimisraam");
f.add("Center", new Trykk2());
f.pack();
f.setSize(400,300);
f.show();
}
}
Trükitava
ala suurust lehel saab ka ise muuta. Sel juhul tuleb PageFormat'i käest küsida
Paper tüüpi isend, talle määrata soovitud suurusega joonistusala. Siis määrata
PageFormat'ile vastav paber ning paluda PrinterJob'il vastava PageFormat'i
järgi trükkida. Siin näites luban trükkida lehel servast serva.
import java.awt.print.*;
import java.awt.*;
public class Trykk3{
public static
void main(String argumendid[])
throws PrinterException{
PrinterJob
pj=PrinterJob.getPrinterJob();
PageFormat
pf=pj.defaultPage();
Paper
p=pf.getPaper();
p.setImageableArea(0, 0, p.getWidth(), p.getHeight());
pf.setPaper(p);
pj.setPrintable(new Trykitoo3(), pf);
pj.print();
}
}
class Trykitoo3 implements Printable{
public int
print(Graphics g, PageFormat pf, int lk)throws PrinterException{
if(lk>0)
return Printable.NO_SUCH_PAGE;
g.drawOval(0, 0, 300, 200);
return
Printable.PAGE_EXISTS;
}
}
Trükitava ala suurust saab lasta ka kasutajal dialoogiakna abil määrata. Sellise akna manab ekraanile pageDialog.
public class Trykk3a{
public static
void main(String argumendid[])
throws
PrinterException{
PrinterJob
pj=PrinterJob.getPrinterJob();
pj.setPrintable(new Trykitoo3a(),
pj.pageDialog(pj.defaultPage()));
pj.print();
}
}
Printable liidese abil saab trükkida ühesuguse suurusega lehekülgi. Kui peaks aga vaja olema ühte trükitavasse dokumenti kokku panna mitmesuguseid (näiteks püsti- ning põikiformaadis) lehti, siis tuleb algul panna kirjutatavatest lehtedest kokku Book ning seda trükkima hakata.
Algusest peale ning ka praegu kõige kindamalt suudavad java programmid mängida au lihtsamas formaadis faile. Versioonist 1.2 on juurde liidetud ka muude (wav, midi) helifailitüüpide mängimise võimalus. Muusika mängimiseks tuleb luua AudioClip. Selle meetoditega play, loop ning stop saab panna klipi mängima ning mängimine katkestada. Loop tähendab, et klippi mängitakse pidevalt, s.t. pärast lõpetamist hakatakse mängimisega uuesti algusest peale.
Keerulisemaid helisünteesi ning muid muusika juurde kuuluvaid valdkondi java keele juures alles luuakse (1999).
import
java.applet.*;
public class
Muusika1 extends Applet{
public void start(){
AudioClip lugu=getAudioClip(getCodeBase(),
"spacemusic.au");
lugu.play();
}
}
Järgneva
näite puhul hakatakse korduvalt mängima lehele tulles ning lehelt lahkudes
lõpetatakse mängimine.
import
java.applet.*;
public class
Muusika2 extends Applet{
AudioClip lugu;
public void init(){
lugu=getAudioClip(getCodeBase(),
"spacemusic.au");
}
public void start(){
lugu.loop();
}
public void stop(){
lugu.stop();
}
}
Iseseisva
programmi puhul saab klipi kätte klassi Applet staatilise meetodi newAudioClip
abil, meetodi parameetriks on helifaili URL.
import java.applet.*;
import
java.net.URL;
public class
Muusika3a{
public static void main(String argumendid[])
throws Exception{
AudioClip lugu=Applet.newAudioClip(
new
URL("http://minitorn.tpu.ee/~jaagup/kool/java/"+
"abiinfo/tutorial/sound/example-1dot2/bottle-open.wav")
);
lugu.play();
Thread.sleep(5000);
}
}
Kui
soovitakse mängida lugu samast masinast, siis tuleb ka see kohalik aadress enne
URLiks muuta.
import
java.applet.*;
import java.net.URL;
public class
Muusika3{
public static void main(String argumendid[])
throws Exception{
AudioClip lugu=Applet.newAudioClip(
new
File("spacemusic.au").toURL()
);
lugu.play();
Thread.sleep(5000);
}
}
Lisaks varemvalminud lugude esitamisele saab ka ise meloodiaid kokku panna. MIDI abil saame määrata, millist nooti millal mängida. Salvestatud pillide helinäidete järgi luuakse selle tulemusena meie poolt küsitud hääl. Kui soovitakse samaaegselt kuulda mitme pilli meloodiat, tuleb need paigutada eri kanalitele. Iga kanal võib korraga teha ühe pilli häält ning harilikult on kanaleid kokku kuni 16.
Kanalist väljuvat heli saab kontrollida sinna saadetavate käskudega. Enamkasutatavad on noteOn ja noteOff. Esimene neist palub nooti mängima hakata, teine mängimise lõpetada. Meetod noteOn vajab kahte parameetrit: heli kõrgust ja valjust, noodi kõlamise lõpetamiseks piisab noodi numbrist. MIDI standardi järgi on igal pooltoonil oma number vahemikus 0-127. Esimese oktaavi C väärtuseks on näiteks 60, sealt saab siis vastavalt poole tooni kaupa üles ja allapoole arvutada. Valjust tähistab samuti number samast vahemikust.
MIDI vahendid asuvad paketis javax.sound, mis kuulub standardvahendite hulka alates JDK versioonist 1.3. Operatsiooni muusikavahendite poole pöördumiseks saab kasutada klassi MidiSystem. Järgnevas näites küsitakse selle klassi kaudu helitekitamise seade ehk süntesaator ning avatakse. Viimase käest küsitakse tema külge kuuluv kanalite massiiv ning sealt omakorda kanal nr. 0. Järgnevalt palun vastaval kanalil mängida A nooti (noot nr. 69) valjusega 65. Ootan sekundi ning siis lasen noodi kõlamise lõpetada. System.exit viimase käsuna on tarvilik, kuna MIDI vahendite tarvitamisega virtuaalmasina poolt loodud lõim ei oska nootide lõpuga oma tööd lõpetada ning programm jääks viimasele reale rippuma. Analoogiline olukord on ka graafikakomponentide juures, kus programmi töö lõpetamiseks tuleb kirjutada System.exit(0).
import javax.sound.midi.*;
public class Noot{
public static
void main(String argumendid[]) throws Exception{
Synthesizer
synthesizer=MidiSystem.getSynthesizer();
synthesizer.open();
MidiChannel
kanal=synthesizer.getChannels()[0]; //kanal 0;
int korgus=69;
//A
int
valjus=65; //keskmine
kanal.noteOn(korgus, valjus);
Thread.sleep(1000);
kanal.noteOff(korgus);
System.exit(0);
}
}
Kromaatilist heliredelit võib mängida
tsükli abil:
for(int i=40; i<120; i++){
kanal.noteOn(i, 60);
Thread.sleep(200);
kanal.noteOff(i);
}
Kui soovida, et samal kanalil mängiks korraga mitu nooti, tuleb lihtsalt ükshaaval määrata, millised helikõrgused peavad kõlama. Kõikide mängimise saab korraga lõpetada käsuga allNotesOff().
Kuigi MIDI puhul öeldakse helikõrgus numbriga ette, on ka siin võimalik toonil ujuda lasta. Seda saab käsuga setPitchBend, andes ette numbri, palju kõrgust muuta. Vaikimisi väärtuseks on 8192, sellisel juhul vastab noodi number tema helikõrgusele. Iga number sellest ülespoole viib helikõrgust kõrgemale, allapoole aga madalamaks. Vaikiva kokkuleppe järgi tähistab number 0 tooni võrra madalamat ning 16363 tooni jagu kõrgemat heli, kuid see kõikumise piirkond võib ka erineda. Järgnevas näites peaks tooni ülalt alla ujumine kuulda olema.
kanal.noteOn(60, 70);
kanal.noteOn(64, 70);
for(int
korgus=16383; korgus>0; korgus-=500){
Thread.sleep(200);
kanal.setPitchBend(korgus);
}
kanal.allNotesOff();
Kanalil mängivat instrumenti saab muuta käsuga programChange, andes parameetritena ette uue pilli helipanga ning panga sees sellele pillile vastava programmijupi järjenumbri. Süntesaatorile kättesaadavad pillid saab küsida getDefaultSoundbank().getInstruments() abil. All näites paiknevad trükitakse tsüklis järgemööda välja pillide nimed ning mängitakse igal pillil noot.
Instrument[] pillid=synthesizer.getDefaultSoundbank().
getInstruments();
MidiChannel
kanal=synthesizer.getChannels()[0];
for(int i=0;
i<pillid.length; i++){
System.out.println(i+": "+pillid[i]);
kanal.programChange(pillid[i].getPatch().getBank(),
pillid[i].getPatch().getProgram());
kanal.noteOn(60, 50);
Thread.sleep(500);
kanal.noteOff(60);
}
osa väljundist:
12:
Instrument Marimba (bank 0 program 12)
13:
Instrument Xylophone (bank 0 program 13)
14:
Instrument Tubular Bell (bank 0 program 14)
15:
Instrument Dulcimer (bank 0 program 15)
16:
Instrument Hammond Organ (bank 0 program 16)
Rajad
Kanalitele käske andes saab edukalt mängida programmi sees üksikuid noote ja luua kõlaefekte, kuid meloodiate ja viisijuppide esitamiseks on loodud täiendavad abivahendid: sekventser, sekventsid ja rajad. Rajal (track) on kirjas saadetavad teated koos ajatemplitega. Ühele rajale võib kanda näiteks ühe pillimehe mängitavad noodid. Sekvents on radade kogumik (nagu partituur). Sekventser on programmilõik, kes sekventsi kirjutatud käsklused õigel ajal süntesaatorile heli tekitamiseks edasi saadab.
Kanalile saadetava teate hoidmiseks on ShortMessage. Teate sisuks võib olla nii noodi mängimise algus, selle lõpp, kanalil oleva instrumendi vahetus kui muudki, näiteks klahvivajutuse tugevuse muutus. Rajale lisamiseks tuleb teatele ümber panna MidiEvent, mis lisab sinna aja – MIDI ajaühikutes mõõdetava vahemiku alates raja algushetkest. Esimeseks teateks kanalil peab olema PROGRAM_CHANGE, selle abil määratakse, millise pilliga hakatakse vastaval kanalil häält tegema. Siin näites määratakse kanalile 0 pill number 16, ehk praeguse helipanga järgi Hammondi orel.
Sekventsi
puhul tuleb määrata, milliselt seal aega arvatakse: kas kaadrite või löökide
järgi. Esimest võimalust kasutatakse video kõrvale heli loomiseks, teist
nootide ja taktide järgi lugu seades, viimast tähistab Sequence.PPQ nagu siin näites. Käsk new Sequence(Sequence.PPQ, 4) tähistab, et luuakse nootidepõhine
sekvents, mille iga löök (ehk veerandnoot 2/4, 3/3 ja 4/4 taktimõõdus)
jagatakse neljaks tiksuks. Tiks on vähim ajaühik MIDI mõõdustikus, seega
sellise jaotuse korral on võimalik lühimaks kestuseks panna
kuueteistkümnendiknoodid. Kui tahta näiteks ka kolmekümnekahendikke kasutada,
siis tuleks algselt veerandnoot mitte neljaks vaid kaheksaks tiksuks jagada.
Enne rajale sündmuste lisamist tuleb rada luua sekventsi käsuga createTrack(). Tulemuse kuulamiseks on vaja MidiSystem'i käest küsida sekventser, see avada. Siis määrata, et sekventseri poolt mängitavaks sekventsiks oleks (praegu meie üherajaline) sekvents ning käsuga start panna sekventser tööle.
import javax.sound.midi.*;
public class Rada1{
public static
void main(String argumendid[]) throws Exception{
ShortMessage lahti = new ShortMessage();
ShortMessage kinni = new ShortMessage();
ShortMessage algus = new ShortMessage();
algus.setMessage(ShortMessage.PROGRAM_CHANGE, 0, 16, 0);
lahti.setMessage(ShortMessage.NOTE_ON, 0, 65, 93);
kinni.setMessage(ShortMessage.NOTE_OFF, 0, 65, 93);
Sequence
sequence=new Sequence(Sequence.PPQ, 4);
Track
track=sequence.createTrack();
track.add(new MidiEvent(algus, 0));
track.add(new MidiEvent(lahti, 0));
track.add(new MidiEvent(kinni, 4));
track.add(new MidiEvent(lahti, 8));
track.add(new MidiEvent(kinni, 11));
track.add(new MidiEvent(lahti, 12));
track.add(new MidiEvent(kinni, 15));
track.add(new MidiEvent(lahti, 16));
track.add(new MidiEvent(kinni, 31));
Sequencer sequencer=MidiSystem.getSequencer();
sequencer.open();
sequencer.setSequence(sequence);
sequencer.start();
}
}
Loodud sekvetserile saab seada mitmeid parameetreid, samuti küsida andmeid mängitava loo kohta. Kui tahan määrata, et loo mängimise kiirus on 40 lööki minutis, siis tuleb kirjutada
sequencer.setTempoInBPM(40);
Kuna ennist olin määranud, et ühes löögis
on 4 tiksu, siis eelmainitud reast järeldub, et igas minutis on 4*40 ehk 160
tiksu ning ühe tiksu pikkuseks on 60/160 sekundit. Analoogiliselt on võimalik
määrata, millisest tiksust alates edasi mängitakse. Sekventseri käest saab
küsida mängimise kiirust, temas sisalduva sekventsi ehk lõigu pikkust tiksudes,
parasjagu mängitava tiksu numbrit ja muudki.
Kui
soovin, et lõiku mitu korda järjest mängitaks, siis tuleb sekventserile panna
külge kuular, mis lõputeate saabumisel paluks lõiku taas otsast mängima hakata.
Piiritleja final on sekventseri ette toodud seetõttu, et teda saaks kohaliku
muutujana sisemises klassis kasutada. Final ei luba muutujal vahetada isendit
millele osutada (st., sellele muutujale ei saa anda uut väärtust). Muul juhul
võiks juhtuda, et vahepeal pannakse sekventserile uus väärtus ning sisemise
klassi sees lükatakse vale sekventser käima. Kui anonüümses sisemises klassis
kasutada isendi (või klassi) tarvis kirjeldatud muutujat, siis seda probleemi
ei teki.
Lõigu
lõppu näitab kuularisse saabuv teade tüübiga nr. 47. Kui seepeale palun sekventseril uuesti otsast mängima hakata,
siis tundub kasutajale, nagu lugu kordaks end järjepanu.
final Sequencer sequencer=MidiSystem.getSequencer();
sequencer.open();
sequencer.setSequence(sequence);
sequencer.start();
sequencer.addMetaEventListener(new MetaEventListener(){
public void
meta(MetaMessage m){
//kui lugu
läbi, siis alustatakse uuesti
if(m.getType()==47)sequencer.start();
}
});
Kui soovida, et sekventsi kordamisel erinevalt mängitaks, siis võib sinna panna mitu rada ning igal korral määrata, milliseid radasid mängitakse, milliseid mitte. Sekventseri käsu setTrackMute abil saab määrata, kas rada on tumm või mitte. Kui soovitakse, et ainult üks rada mängiks ning teised oleksid vait, siis tuleb see rada panna soleerima käsu setTrackSolo abil.
Brauseriga lehekülgede vaatamisel võtab brauser ühenduse soovitud serveri vastavasse väratisse ning palub seda kuulaval programmil saata omale vastav lehekülg. Lihtsamal juhul programm loeb kettal määratud nimega faili ning saadab sellest koopia mööda moodustatud ühendust brauseri poole tulema ning katkestab ühenduse. Brauser loeb saabuvat teksti ning vastavalt sellele manab kujutise ekraanile. Juhul, kui näiteks saabuvas HTML failis on kirjas, et tuleb teksti sisse pilti näidata, siis avab brauser ühenduse serveriga, kus pilt paikneb, palub sellegi omale saata ning näitab seejärel pilti omale sobivas kohas.
Brauserisse andmete saatmiseks ei pruugi neid tingimata failist kopeerida. Saadetavad andmed võib ka serveris paiknev programm kokku panna. Sel juhul saab igale kasutajale luua temale vastava lehekülje. Nii näiteks töötab külastuskordade lugeja: igal korral saadetakse kasutajale ühe võrra suurem number.
Selliseid serveris brauseri väljakutse peale tööle hakkavaid programme nimetatakse CGI (ehk Common Gateway Interface) programmideks. Juhul kui URLile vastav fail on serveri sisemiste määrangute (näiteks faililaiendi) järgi määratud CGI programmifailiks, siis käivitab http väratit kuulav ning andmeid brauserile saatev rakendus URLile vastava programmi. Kasutaja ei pruugi teadagi, kas veebilehitsejasse saabuv tekst kopeeritakse failist või loob selle programm. Sageli siiski reedab URLis sisalduv faili või kataloogi nimi, et tegemist on tõenäoliselt CGI-programmiga. Sellele viitab enamasti kataloogi nimi cgi-bin või skriptiprogrammi tähistav faililaiend (.sh shelli programmidel, .pl Perl, .c C keelse programmifaili laiendiks), kuid CGI abil saab käivitada ka programmi, mille nimi kasutajale kuidagi teada ei anna, et tegemist programmiga oleks.
CGI programmi abil on võimalik luua kasutajale leht vastavalt parasjagu kehtivatele andmetele, lugedes need siis näiteks failist või pöördudes selleks andmebaasi poole. Juhul, kui andmed muutuvad sageli ning andmepäringuid on vähe, siis on mõistlik andmete põhjal igale kasutajale uus lehekülg kokku panna. Kui aga andmeid muudetakse tulemuste küsimisest harvemini ning erinevaid päringuid on vaid paar tükki, siis tuleks andmete muutumisel luua uued infolehed, mis siis küsimisel brauseri poole teele saadetakse.
CGI protokolli abil on võimalik andmeid vahetada mõlemas suunas. Nii kasutajalt serverisse kui tagasi. Tüüpiline otsingumootor saab kasutajalt märksõnad ning väljastab nende põhjal vastustelehe. Samuti saab säärase võimaluse abil lisada oma andmeid serveris asuvasse nimistusse, pidada külalisraamatut ning tellida kataloogist kaupu.
CGI programmide üldkasutatavasse serverisse ülespanekuks on enamasti tarvis süsteemihalduri luba, sest vigase programmi või näiteks vörgust kopeeritud külalisraamatu ülespanek võib serverisse luua turvaaugu. Kui väljast tuleval häkkeril õnnestub leida CGI-programmist ettenägemata juurdepääsu lubav viga, siis saab selle kaudu serverile kurja teha või salajasi andmeid lugeda ja muuta. Üks oluallikas tekib näiteks, kui lubada kasutajal määrata lugemise-kirjutamise faili nime. Kui on võimalik määrata failiks ülemkataloogi fail, siis on võõral sisuliselt juurdepääs tervesse serverarvutisse. Kui kasutada kellegi teise pool varem kirjutatud ning üles riputatud programmi, siis võib juhtuda, et sinna on lisaks tarvilikule juurde lisatud masinasse sisse murdmist võimaldav koodilõik.
Andmete vahetamiseks pakub CGI-le sarnaseid võimalusi veebilehel olev rakend. Ka seal saab andmeid väljadesse paigutada, töödelda, serverisse saata ning sealt lugeda. Rakenditel on võimalusi enam, kuid mitmed eelised räägivad (vähemalt esialgu) CGI-programmide kasuks.
CGI puhul on arvutustöö jäetud serveri hooleks, brauseril tuleb vaid saabuvat teksti näidata ning andmed serverisse saata. Kui andmeid edastada rakendi ning serveri väratit kuulava programmi abil, siis peab lehitsejas tööle hakkama rakendikäitur, mis nõuab mõnevõrra enam ressursse. Mõnes (näiteks tekstipõhises või Windows 3.1 all töötavas) lehitsejas rakendikäiturit polegi, kuid vormide täitmise ning CGI-programmi jooksutavasse serverisse saatmisega saavad nad ilusti hakkama.
Java rajajad lõid brauseri kasutajaga andmevahetuseks uue võimaluse. Kui CGI-ks kasutati java-programmi, siis tuli igal kasutamisel java-intepretaator uuesti käivitada. Lisaks sellele püüti lahendada turvaprobleeme.
Servleti käivitamiseks töötab serveris pidevalt java intepretaator. Kui brauser soovib servleti hallatavat URLi lugeda, siis käivitab intepretaator vastava servleti eraldi lõimena. Kuna intepretaatorit pole vaja uuesti käivitada, siis hoitakse käivitamisel aega kokku. Servleti käivitumine võtab ligikaudu kolm korda vähem aega kui CGI programmi oma.
Turvanõuete tõttu ei saa servlet otse serveri faile lugeda ega kirjutada. Vajadusel tuleb andmeid vahetada pistiku kaudu või selle juurde ehitatud andmebaasiühendust kasutades.
Järgnev näide peaks olema võimalikult lihtne servlet. Veebiservlet luuakse HttpServleti alamklassina. Meetodid, mida soovitakse muuta, tuleb üle katta. Tähtsamad meetodid on doGet ja doPost. Sisult on nad sarnased, kuid nad käivitatakse vastavalt selle, kumma tüübi abil servlet välja kutsutakse. Kui servlet käivitatakse get abil, siis saadetakse andmed URL küljes, pärast küsimärki. Post meetodi puhul saadetakse andmed eraldi voona. Get-võimalust kasutatakse enamasti lihtsate ja lühikeste andmete saatmiseks, post-meetodi abil kantakse üle pikemaid tekste ning vähemtähtsaid salasõnu. Tähtsamad salasõnad tuleb muul moel kodeerida.
Meetod doGet saab saab kaks parameetrit: esimene kannab andmeid väljakutsuja kohta. Tema kaudu saab teada, millisest masinast ning milliselt leheküljelt servlet välja kutsutakse, samuti tulevad sealt kaudu ka kasutaja poolt saadetavad andmed. HttpServletResponse abil saadetakse brauserile vastus tagasi.
Vastuslehekülje loomisel tuleb määrata ta formaat (näiteks text/html või text/plain). Vastuselt saab küsida Writeri ning selle abil temasse tekst kirjutada.
import
javax.servlet.*;
import
javax.servlet.http.*;
import java.io.*;
public class
Servlet1 extends HttpServlet{
public void doGet(HttpServletRequest
kysimus,
HttpServletResponse
vastus)
throws IOException,
ServletException{
vastus.setContentType("text/html");
PrintWriter valja=new
PrintWriter(vastus.getWriter());
valja.println(
"<body>\n"+
"
<h2> Tervist! </h2>\n"+
"</body>"
);
}
}
HttpServletRequesti meetod getQueryString annab URLi küsimärgile järgneva osa. Näiteks http://www.ee/kass.html?nurr puhul on QueryStringiks nurr. Juhul kui servletti välja kutsuval lehel on vorm ning väljad, siis laotakse väljade nimed ning nende väärtused üksteise otsa ja paigutatakse QueryStringi. Eri väljade andmed eraldatakse teineteisest & märgiga, välja nimi ning väärtus = märgiga. Alljärgneva näite puhul võib see välja näha näiteks: eesnimi=Peeter&perenimi=Tamm. Servlet saab vajaduse korral saabunud sõne jälle osadeks jaotada.
import
javax.servlet.*;
import
javax.servlet.http.*;
import
java.util.StringTokenizer;
import java.io.*;
public class
ServletGet1 extends HttpServlet{
public void doGet(HttpServletRequest
kysimus,
HttpServletResponse
vastus)
throws IOException,
ServletException{
vastus.setContentType("text/html");
PrintWriter valja=new
PrintWriter(vastus.getWriter());
valja.println(
"Edastati info:
"+kysimus.getQueryString()+"<br>\n"+
"Ühendus tuli masinast
"+kysimus.getRemoteHost()+"<br>\n"+
"Selle masina number on
"+kysimus.getRemoteAddr()+"<p>\n"
);
StringTokenizer stk=new
StringTokenizer(kysimus.getQueryString(), "&");
while(stk.hasMoreTokens()){
valja.println(stk.nextToken()+"<br>\n");
}
}
}
<body>
<form action=servlet/ServletGet1
method=GET>
Eesnimi: <input type=text name=eesnimi
size=10><br>
Perekonnanimi: <input type=text
name=perenimi sise=10><br>
<input type=submit value=" OK
">
</form>
</body>
Kui andmeid saadetakse post-protokolli abil, siis jõuavad nad kohale eraldi voona. HttpServletRequestilt saab küsida selle voo ning sealt andmeid lugema hakata. Samas on siia loodud ka automaatsed vahendid parameetrite väärtuste leidmiseks, et programmeerija ei peaks oma pead vaevama pika sõne osadeks jagamise, kodeeritud tähtede lahtiharutamise ning vajalike parameetrite väärtuste üles leidmisega. Kui meetodi getParameter parameetriks anda välja nimi, siis tulemusena väljastatakse selle välja väärtus.
import java.io.*;
import
javax.servlet.*;
import
javax.servlet.http.*;
public class
ServletPost1 extends HttpServlet{
public void doPost(HttpServletRequest
kysimus,
HttpServletResponse vastus)throws
IOException, ServletException{
String
eesnimi=kysimus.getParameter("eesnimi");
String
perenimi=kysimus.getParameter("perenimi");
vastus.setContentType("text/plain");
PrintWriter valja=vastus.getWriter();
valja.println(eesnimi+"
"+perenimi);
}
}
<body>
<form action=servlet/ServletPost1
method=POST>
Eesnimi: <input type=text name=eesnimi
size=10><br>
Perekonnanimi: <input type=text
name=perenimi sise=10><br>
<input type=submit value=" OK
">
</form>
</body>
Nii väljade väärtused kui väljakutsujat iseloomustavad suurused on võimalik kätte saada üheskoos. HtteServletRequesti getParameterNames() annab väljade nimed Enumerationi ehk jadana. Samuti annab getHeaderNames() väljakutsuja tunnuste loetelu. Nime järgi saab küsida tunnuse väärtuse.
Kui soovida, et servlet oskaks nii get- kui post-protokollis andmeid saata, siis võib ühte servletti kirjutada mõlemad meetodid. Kui soovitakse, et nad käituksid sarnaselt, siis võib üks meetod lihtsalt teise välja kutsuda.
import java.io.*;
import
javax.servlet.*;
import
javax.servlet.http.*;
import
java.util.Enumeration;
public class
ServletPost2 extends HttpServlet{
public void doPost(HttpServletRequest
kysimus,
HttpServletResponse vastus)throws
IOException, ServletException{
vastus.setContentType("text/plain");
PrintWriter valja=vastus.getWriter();
Enumeration
parameetrid=kysimus.getParameterNames();
while(parameetrid.hasMoreElements()){
String
parameetriNimi=(String)parameetrid.nextElement();
valja.println(parameetriNimi+" =
"+kysimus.getParameter(parameetriNimi)+"\n");
}
valja.println();
Enumeration
teated=kysimus.getHeaderNames();
while(teated.hasMoreElements()){
String
teateNimi=(String)teated.nextElement();
valja.println(teateNimi+" -
"+kysimus.getHeader(teateNimi)+"\n");
}
}
public void doGet(HttpServletRequest
kysimus,
HttpServletResponse vastus)throws
IOException, ServletException{
doPost(kysimus, vastus);
}
}
<body>
<form action=servlet/ServletPost2
method=POST>
kasutajanimi: <input type=text name=nimi
size=10><br>
parool: <input type=password
name=salasona sise=10><br>
<input type=submit value=" OK
">
</form>
</body>
ASP, PHP, JSP
CGI või servlettide kirjutamisel tuleb paratamatult kokku puutuda märkimisväärse hulga programmikoodiga. Mõnele tundub igasugune kodeerimine hirmuäratav, teisalt on ka tülikas, kui peab pikemaid tekste väljundisse kirjutama selleks, et saaks seal sees üksikuid väärtusi muuta. Kliendipoolsete arvutuste puhul saab selliseks tegevuseks kasutada Javaskripti, serveripoolsete lisanduste jaoks mõeldi aga välja mitmesugused *SP-d. Seal saab HTML teksti sisse vastavate märkide (kas <% %> või siis <? ?>) vahele kirjutada käsud, mida programm tegema peaks. Eeliseks kliendipoolse skripti ees on, et saab kasutada ka serveris paiknevaid andmeid, puuduseks, et ei saa kasutaja tegevusele vahetult reageerida, kogu teave jõuab temani alles uue lehe laadimise järel. ASP töötab peamiselt MS Windowsi keskkonna all ja seal sees levinumaks programmeerimiskeeleks on Visual Basicust loodud VBScript. JSP käsud kirjutatakse Java keeles, andmeid talletatakse ja töödeldakse enamjaolt ubade (bean) abil. Kasutajale järjestikuseid näidatavaid lehti nimetatakse sessioonideks. Nende abil hoitakse näiteks meeles sisestatud kasutajanime ja parooli, et neid ei tuleks igale lehele sisenedes uuesti sisestada.