Nova verzija JSP specifikacije, JSP v2.0, se pojavila u okviru specifikacije za J2EE v1.4. JSP v2.0 postoji već neko vreme i svi JSP kontejneri koji drže do sebe implementiraju ovu specifikaciju. Međutim, čini se da se developeri po navici drže starih stvari i da nisu dovoljno upoznati sa novinama koje donosi JSP v2.0 specifikacija. Što je u ovom slučaju šteta, jer JSP v2.0 donosi puno toga što može da značajno ubrza i olakša svakodnevni rad sa JSPom. Ovaj članak je upravo namenjen developerima koji već imaju iskustva u radu sa dosadašnjim verzijama JSP i Servlet specifikacijama.
Zbog obimnosti i velikog broja detalja, ovaj pregled JSP v2.0 specifikacije neće moći da se temeljno bavi i objasni baš sve pojedinosti nove specifikacije. Umesto toga, fokus i cilj članka je da pruži pregled što više novosti.
Expression Language (EL) je specifikacija koja definiše kako se pristupa atributima objekata u run-time okruženju. EL je prvi put predstavljen u okviru JSTL v1.0 specifikacije. U JSP v2.0 je sam JSP kontejner zadužen da 'razume' i da izvršava EL izraze, tako da nije potrebno nikakvo dodatno podešavanje.
EL specifikacija konačno oslobađa programera od zamornog i nepraktičnog pisanja dugačkih izraza samo da bi se pristupilo nekom atributu, tj. propertiju objekta. EL uvodi novu i elegantnu sintaksu, koja je logična, kraća za pisanje i laka za upotrebu.
Svaki EL izraz se zadaje u obliku: ${izraz}. Izraz uključuje literale, varijable i operatore.
Literali su brojevi, tekst (pod jednostrukim ili dvostrukim navodnicima), Boolean vrednosti i null.
Varijable uglavnom predstavljaju vrednosti atributa beanova ili atributi/parametri JSP scopeova. Svaki bean iz
bilo kog JSP scopea može biti iskorišćen kao varijabla. EL dodatno specificira sledeće predefinisane varijable:
| Ime varijable | Opis |
pageScope | java.util.Map kolekcija svih atributa iz page scopea. |
requestScope | java.util.Map kolekcija svih atributa iz request scopea. |
sessionScope | java.util.Map kolekcija svih atributa iz session scopea. |
applicationScope | java.util.Map kolekcija svih atributa iz application scopea. |
param | java.util.Map kolekcija svih request parametara predstavljenih kao jedan String po parametru. |
paramValues | java.util.Map kolekcija svih request parametara predstavljenih kao String[] niz po jednom parametru. |
header | java.util.Map kolekcija svih header parametara predstavljenih kao jedan String po parametru. |
headerValues | java.util.Map kolekcija svih header parametara predstavljenih kao String[] niz po jednom parametru. |
cookie | java.util.Map kolekcija svih cookie vrednosti datih kao jedan javax.servlet.http.Cookie value po cookie-ju. |
initParam | java.util.Map kolekcija svih init parametara aplikacije, datih kao jedan String vrednost po parametru. |
pageContext | instanca javax.servlet.jsp.PageContext klase, omogućava pristup raznim podacima iz request-a. |
Od operatora, EL podržava sledeće, od kojih je većina sama po sebi jasna:
| Operator | Opis |
| . | Pristup propertiju beana ili elementu Mape. |
| [] | Pristup elementu niza ili Liste. |
| () | Grupisanje izraza. |
| ? : | Kondicionalini test. |
| + | Sabiranje. |
| - | Oduzimanje ili negacija vrednosti. |
| * | Množenje. |
| E | Eksponent. |
| / ili div | Deljenje. |
| % ili mod | Moduo (ostatak). |
| == ili eq | Test jednakosti. |
| != ili ne | Test nejednakosti. |
| < ili lt | Test za manje. |
| > ili gt | Test za veće. |
| <= ili le | Test za manje ili jednako. |
| >>= ili ge | Test za veće ili jednako. |
| && ili and | Test za logičko I (AND). |
| || ili or | Test za logičko ILI (OR). |
| ! ili not | Komplement. |
| empty | Test da li je varijabla prazna: null, prazan String ili niz, Mapa, ili Collection bez elemenata. |
| foo(args) | Poziv funkcije foo sa odgovarajućim argumentima (0, 1 ili više). |
EL parser je zadužen da ispravno protumači izraz i da poštuje tipove elemenata izraza. Znači, ako se izraz sastoji od sabiranja dve brojčane varijable i/ili literala, rezultat će biti njihova brojčana suma. Tip rezultata matematičkog izraza zavisi od tipova brojčanih vrednosti, na primer: rezultat delenja je uvek realan broj, pri čemu se vodi računa i o delenju s nulom. Operatori za poređenje rade i sa brojčanim vrednostima i sa stringovima. Korisno je i postojanje alternativnih 'tekstualnih' operatora za poređenje kako uobičajeni znaci ne bi remetili strukturu ili smanjivali čitljivost JSP/HTML strane.
Velika prednost EL je lak pristup atributima bean-ova. Dosadašnji način pristupa atributima u raznim scope-ovima je glomazan. Primer sa skripletima:
<%=pageContext.getAttribute("pagevar")%>
<%=request.getAttribute("requestvar")%>
<%=session.getAttribute("sessionvar")%>
<%=application.getAttribute("appvar")%>
Korišćenjem predefinisanih varijabli (tipa java.util.Map) u EL je ovaj blok moguće napisati na dva načina.
Prvi je nešto kraći i koristi 'tačka' operator (.):
${pageScope.pagevar}
${requestScope.requestvar}
${sessionScope.sessionvar}
${applicationScope.appvar}
Drugi, ekvivalentan način, koristi operator 'srednje zagrade' ([]):
${pageScope['pagevar']}
${requestScope['requestvar']}
${sessionScope['sessionvar']}
${applicationScope['appvar']}
To nije sve: EL donosi mogućnost 'skraćenog' pisanja varijabli. Ako se navede samo ime beana, bez predefinisane varijable koja bi određivala scope, onda EL pretražuje redom page, request, session i application scope dok ne nađe traženi element. Prethodni primer se zato može pisati i na sledeći način, mnogo kraće:
${pagevar}
${requestvar}
${sessionvar}
${appvar}
Jasno, ako postoje 2 atributa sa istim imenom u različitim scope-ovima, EL će vratiti prvi na koji naiđe, prema navedenom redosledu traženja.
Nova verzija JSTL-a ne donosi mnogo novina i više služi da se bolje uklopi u JSP v2.0 specifikaciju. Pored 4 postojeće biblioteke tagova, dodata je još jedna, pod imenom "Functions". Ona ima veze s pozivanjem JSTL funkcija iz EL izraza i biće objašnjena nešto kasnije. Važno je da se URI za JSTL v1.1 biblioteke izmenio (sadrži '/jsp'), o čemu treba voditi računa. Prefiks tagova je ostao isti:
| Biblioteka | URI | Prefiks |
| Core | http://java.sun.com/jsp/jstl/core | c |
| XML | http://java.sun.com/jsp/jstl/xml | x |
| I18N | http://java.sun.com/jsp/jstl/fmt | fmt |
| Database | http://java.sun.com/jsp/jstl/sql | sql |
| Functions | http://java.sun.com/jsp/jstl/functions | fn |
Instalacija JSTL v1.1 je jednostavna: najčešće sve što treba uraditi je staviti jstl.jar i standard.jar u
WEB-INF/lib folder. JSP stranica koja koristi JSTL na stadardni način uključuje biblioteke @taglib direktivom,
koristeći nove vrednosti za URI.
Evo čestog primera u JSP v1.x, iteriranje liste elemenata, s puno skriptleta:
<ul>
<%
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object elem = iterator.next();
if (elem == null) elem = "";
%>
<li> <%=elem%> </li>
<%
}
%>
</ul>
Ne može se reći da je gornji kod preterano elegantan:) Ista logike, napisana u duhu JSP v2.0 izgleda ovako:
<ul>
<c:forEach var="elem" items="${list}">
<li> ${elem} </li>
</c:forEach>
</ul>
EL i JSTL v1.1 uvode novi koncept EL funkcija. Funkcije su definisane u okviru standardne JSTL biblioteke i koriste se iz EL izraza:
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...
<%
int[] array = new int[3]; array[0] = 7; array[1] = 8; array[2] = 9;
pageContext.setAttribute("arr", array);
%>
...
${fn:length(arr)}
Smisao EL funkcija je da budu globalne statičke pomoćne funkcije. Njihova prednost je, na primer, to što ispravno tumače tipove
argumenata. Tako funkcija fn:length() vraća dužinu niza ili broj elemenata kolekcije, ili
dužinu Stringa, ili broj elemenata Mape, ili ako je argument Iterator
ili Enumeration ukupan broj elemenata u iteraciji, tj. enumeraciji.
Od ostalih predefinisanih JSTL v1.1 funkcija, tu su uglavnom razne standardne funkcije za rad sa stringovima. Možda je interesantno
pomenuti funkciju: fn:escapeXml() koja enkodira argument u 'bezbedan' XML/HTML sadržaj koji ne narušava
strukturu dokumenta.
Moguće je praviti i biblioteke sa custom funkcijama. Pored Java koda same funkcije, potrebno je i definisati je u TLD deskriptoru.
Skoro svaka web aplikacija koristi fragmente JSP koda koji se uključuju na velikom broju stranica. Uobičajeni sajt ima zaglavlje, meni sa leve strane, centralni deo... Zaglavlje se, na primer, pojavlje na svim stranama bez izmena. Jasno, bilo bi glupo pisati iste delove koda na svim stranama. Zato se ovakvi fragmenti JSP koda stavljaju u zasebne fajlove koji se zatim uključuju (include) na stranama.
Sve ovo je već moguće bilo raditi u JSP v1.x. JSP v2.0 donosi i preporučenu ekstenziju za fajlove koji predstavljaju JSP segmente: .jspf.
Važno je uočiti da specifikacija nalaže da se extenzija ".jspf" koristi samo za statičke fragmente. Za dinamičke fragmente, treba nastaviti koristiti dosadašnju ekstenziju ".jsp". Dalje, po specifikaciji, preporuka je da se statički fragmenti drže u folderu "WEB-INF/jspf".
Primer uključivanja fragmenata:
<%@ include file="WEB-INF/jspf/header.jspf" %>
<jsp:include page="<%= pageBody %>" />
<%@ include file="WEB-INF/jspf/footer.jspf" %>
Uočiti da se za jsp:include ne koristi više flush="true".
Ovo važi i za JSP v1.2, ali nije loše pomenuti ponovo, jer se čini da se i dalje po navici (nepotrebno) koristi.
Inače, JSP v2.0 predlaže da se ovakvi statički delovi JSP koda zovu "JSP segmenti",
pošto se izraz "fragment" koristi već za puno stvari.
JSP v2.0 uvodi mogućnost postojanja custom tag handlera definisanih u JSP fajlovima, a ne samo u Javi. Ovo je zanimljiv koncept, koji je praktično sve vreme bio "tu negde", dok ga nisu sada konačno definisali i uvrstili u specifikaciju. O JSP tag fajlovima može puno da se priča, ali se zbog prirode članka neće ići u sve detalje.
Čest je slučaj da custom JSP tagovi jednostavno moraju da manipulišu sa HTML kodom. Dosadašnje rešenje bi zahtevalo pisanje custom JSP taga kao Java klase, što bi značilo da se rad sa HTML-om obavlja ili u Java kodu, ili na komplikovani način u telu taga, koji dodatno usložnjava upotrebu taga. Dodatnu komplikaciju predstavlja čunjenica da se svaki Java custom tag mora pisati prema možda ne baš intuitivnim pravilima, poštojući odgovarajući life-cycle izvršavanja taga.
JSP tag fajlovi omogućuju jednostavno definisanje custom tag handlera u JSP fajlovima. Sve je, dakle, u JSP fajlovima, pa je lako raditi izmene tagova. Evo primera jednog JSP tag fajla:
<%@ tag body-content="scriptless" %>
<%@ attribute name="alienId" required="true" %>
<%@ attribute name="namesMap" required="true" type="java.lang.Object" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<p>
<jsp:doBody/>
</p>
<c:forEach items="${namesMap}" var="name">
${name.value} ${name.key == alienId ? 'alien:)' : ''}<br>
</c:forEach>
Definicija JSP tag fajla bi trebalo (mada nije obavezno) da počne s odgovarajućom direktivom
(@tag). Može se specifirati i tip JSP tag fajla prema tome da li i kako uključuje telo taga:
empty - tag je bez tela,scriptless (default) - tag ima telo koje pored HTMLa sadrži sve (na pr.: standardne tagove) osim skripting elemenata,tagdependent - telo taga se jednostavno predaje handleru.Ostatak JSP taga je manje-više jasan: sledi definicija njegovih atributa, a zatim i samo telo tag handlera. Gornji JSP tag fajl se poziva na sledeći način:
<%@ taglib prefix="foot" tagdir="/WEB-INF/tags" %>
...
<foot:foo alienID="1" namesMap="${whoismap}">
Who is the alien?
</foot:foo>
Uključivanje custom JSP tag fajla se može obaviti direktnim pokazivanjem na folder koji sadrži '.tag' fajlove
(direktiva @taglib, atribut tagdir), kao u primeru. Ime '.tag' fajla je ujedno i ime taga.
Inače, ovde je 'whoismap' page scope atribut, tipa java.util.Map.
Alternativno, JSP tag fajlovi se mogu definisati i u deskriptoru, na sličan načina kao i uobičajeni JSP Java tagovi.
Tada se na JSP strani umesto tagdir koristi atribut taglib u okviru @taglib direktive.
Tako definisane JSP tag fajlove je moguće uključiti i u distribucioni jar, zajedno sa TLD-ovima.
JSP tag fajlovi imaju mogućnost da koriste tkzv. dinamičke atribute, koji se koriste u slučajevima kada nije
unapred poznat broj atributa taga. Tada se svi atributi navedeni u pozivu JSP taga, a koji nisu konkretno
specificirani u njegovoj definiciji, smatraju dinamičkim. Dinamički atributi se jednostavno prenose kao java.util.Map
objekat.
Da bi JSP tag fajl koristio dinamičke atribute, treba jednostavno dopuniti definiciju taga:
<%@ tag body-content="scriptless" dynamic-attributes="attrMap" %>
U attrMap mapi se sada nalaze svi dinamički atributi. Kako je u pitanju mapa,
dinamičkim atributima se u handleru taga pristupa na uobičajen način:
<c:forEach var="attr" items="${attrMap}">
${attr.key} = ${attr.value}
</c:forEach>
JSP tagovi i strana odakle su pozvani dele sve scopeove osim page scopea. Da bi JSP tag setovao neku varijablu koja će biti vidljiva na strani odakle je tag pozvan, a posle poziva i izvršavanja taga, treba je samo uključiti u neki od preostala tri vidljiva scopea, recimo u request scope:
<c:set var="vlocal" value="Local Troll"/> <c:set var="vglobal" value="Global Troll" scope="request"/>
vlocal je u page scopeu i vidi se samo u handleru taga, dok se vglobal vidi
i posle izvršavanja taga.
Postoji još jedan način kako se prenose varijable između taga i JSP strane: korišćenjem direktive variable.
Ovom direktivom se jednostavno definišu varijable koje će se videti i posle taga, bez potrebe da se one implicitno
smeštaju u neki scope. Ovako definisane varijable moraju da imaju jedan od tri scopea varijabli
(ne treba ih mešati sa JSP scopeovima!), a označavaju kada će varijabla u tagu biti setovana:
<jsp:doBody> i pre svake <jsp:invoke> i na kraju izvršavanja taga;<jsp:doBody> i pre svake <jsp:invoke>;U pitanju su nijanse koje je najbolje razumeti kroz primer, dat na kraju članka.
Postoji još i mogućnost da se ova imena varijabli setuju dinamički, pomoću atributa taga.
Rečeno je da atributi taga mogu biti obični i dinamički. Postoji još jedan tip: tkzv. fragment atributi. Fragment atribut predstavlja JSP fragment (smisleni isečak JSP koda) koji se može izvršiti u JSP tag fajl handleru, a definisan je pri pozivu taga.
Primer jednog JSP tag fajl handlera:
<%@ attribute name="voodoo" required="true" %>
<%@ attribute name="template" fragment="true" %>
<%@ variable name-given="data" scope="NESTED" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="data" value="${voodoo}"/<
<jsp:invoke fragment="template"/>
<c:set var="data" value="${voodoo} #1"/>
<jsp:doBody/>
<c:set var="data" value="${voodoo}"/>
<jsp:invoke fragment="template"/>
<c:set var="data" value="${voodoo} #2"/>
<jsp:doBody/>
i njegove upotrebe:
<example:doo voodoo="zulu">
<jsp:attribute name="template">
hello from template: ${data}
</jsp:attribute>
<jsp:body>
hello from body: ${data}
</jsp:body>
</example:doo>
Ovde je pravo mesto da se uoče <jsp:doBody> i <jsp:invoke>. Oba
mogu da se koriste samo u JSP tag fajlovima. Oba taga rade vrlo slično: invokuju odgovarajući specificirani JSP fragment.
<jsp:doBody> invokuje telo taga, dok <jsp:invoke> invokuje neki specificirani
JSP tag fragment. Oba imaju i tri ista neobavezna atributa kojima se dodatno upravlja izvršavanjem.
Još jedna novina JSP v2.0 se tiče custom tagova. Ovaj put je reč o Java implementaciji tag handlera i o novom
javax.servlet.jsp.tagext.SimpleTag interfejsu. Dosadašnji način razvoja custom tagova zahteva
poštovanje nešto složenijeg life-cyclea tagova i interfejsa
(doStartTag(), doAfterBody(), doEndTag()).
JSP v2.0 specifikacija donosi novi interfejs za razvoj custom tagova, čiji life-cycle zahteva da se u samo
jednoj metodi handlera odradi sva logika. Evo kako bi izgledao kostur jednog ovakvog taga:
public class FooCustomTag extends SimpleTagSupport {
/* get/set metode za sve atribute taga */
/* definicija tag handlera */
public void doTag() throws JspException, IOException {
JspWriter out = getJspContext().getOut();
out.println("....");
JspFragment body = getJspBody();
if (body != null) {
body.invoke(null);
}
out.print("....");
//...
}
}Od novih stvari tu je getJspBody() koji vraća telo taga, a koje se ispisuje u JspWriter
output stream metodom JspFragment.invoke(). Ostatak handlera može da na standardan
način ispisuje sadržaj, koristeći print() i println() metode. Dalje,
SimpleTagSupport podržava i dinamičke atribute, slično JSP tagovima.
Ovaj način jeste lakši za razvoj, ali navodi programera da koristi HTML unutar Java klase, što, po mišljenju autora, nije baš dobra praksa. Zato treba biti pažljiv u korišćenju ovog interfejsa. Njegova primena bi imala više smisla na mestima gde custom tag treba da izmeni postojeći HTML kod, pre nego tamo gde treba da ga generiše.
Stranice za greške su stranice koje će JSP kontejner vratiti u slučaju neke HTTP ili sistemske greške (404, 405, 500...).
JSP specifikacija odavno pruža mogućnost da programer sam definiše koje će se stranice prikazati u slučaju grešaka
(web.xml tag error-code). Međutim, problem je bio prikazivanje informacija o exception-u koji
je prouzrokovao grešku.
JSP v2.0 koristi isti javax.servlet.error.exception atribut. Pored njega, uvedena je pageContext.errorData
varijabla, koja sadrži sleće propertije:
requestURI (URI na kome je nastala greška),servletName (JSP strana ili ime servleta koji je prouzrokovao grešku),statusCode (broj greške),throwable (konkretni Throwable exception koji je nastao).Način korišćenja je trivijalan i dat je u primeru.
I Servlet API je doživeo promene. Evo pregleda nekih najznačajnijih.
Dodati su novi listeneri: ServletRequestListener i ServletRequestAttributeListener.
Prvi listener se aktivira svaki put kada aplikacija primi novi request. Drugi listener
se aktivira svaki put kada se objekat smešta, uklanja ili zamenjuje u requestu.
Filteri se sada mogu koristiti i pri upotrebi Request Dispatchera. Sledeća definicija filtra:
<filter> <filter-name>FooFilter</filter-name> <filter-class>com.doe.john</filter-class> </filter> <filter-mapping> <filter-name>FooFilter</filter-name> <url-pattern>/doo</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping>
definiše filter koji se izvršava na svaki '/doo' request, ali i na svaki
javax.servlet.RequestDispatcher objekat koji sadrži pomenutu putanju.
Slično, ako treba izvršavati filter pri nekom forwardu, u gornjoj definiciji treba koristiti
ključnu reč FORWARD umesto INCLUDE.
Kada se pomoću Request Dispatcher uradi forward, takav request objekat će sadržati i još neke dodatne atribute. Ovi atributi, dakle, postoje samo posle forwarda:
Iz imena atributa se može zaključiti čemu služe.
Interfejs javax.servlet.ServletRequest je dobio četiri nove metode:
getRemotePort() - vraća port klijenta ili poslednjeg proksija koji je poslao request,getLocalName() - vraća ime hosta koji je primio request,getLocalAddr() - vraća IP adresu hosta koji je primio request,getLocalPort() - vraća IP port hosta koji je primio request.Postojeće metode getServerName() i getServerPort() u v2.4 vraćaju drugačije vrednosti, pošto
su u v2.3 vraćali ono što sada vraćaju getLocalName() i getLocalPort().
U Servlet v2.3 specifikaciji nije postojao direktan način kako naznačiti klijentskom browseru koji
karakter enkoding treba da koristi. Da bi se postavio željeni enkoding, trebalo ga je setovati korišćenjem
instance java.util.Locale, ili da se koristeći setContentType() setuje u isto vreme
i tip kontenta i karakter set.
U Servlet v2.4 specifikaciji, javax.servlet.ServletResponse ima novi metod: setCharacterEncoding()
kome se jednostavno prosleđuje ime karakter enkodinga kao string. Važno: da bi ovaj metodu funkcionisao,
mora biti pozvan pre prvog poziva getWriter() metode! Paralelno sa ovim, ubačen je i
getContextType() metod, koji vraća tip kontenta responsea.
Pored ovih metoda, postoji način da se definiše veza locale - karakter enkoding, pa programer sada ne mora da to ručno radi u servletima, već samo u 'web.xml'-u:
<locale-encoding-mapping-list> <locale-encoding-mapping> <locale>ja</locale> <encoding>ISO-2022-JP</encoding> </locale-encoding-mapping> </locale-encoding-mapping-list>
I jos ponešto:
SingleThreadModel interfejs je sada deprecated. Njegova namera je bila da nagovesti
kontejneru da ne dozvoli da 2 threada u isto vreme izvršavaju servlet. Pokazalo se da se ovaj interfejs
pogrešno koristio, jer je navodio programere na (netačno) mišljenje da se njime rešavaju problemi vezani za
thread safety.
JSP specifikacija definiše 2 tipa JSP dokumenata: standardne, koji mogu da sadrže bilo kakav markup jezik ili tekst, i tkzv. JSP dokumente - čiste XML dokumente. JSP dokumenta se u osnovi sastoje od XHTML i JSP elemenata.
Uobičajeno je da se JSP dokumenta pišu u fajlovima sa ekstenzijom '.jspx'. Kontejner za fajlove sa '.jspx' ekstenzijom
automatski podrazumeva da su XML. Postoji i drugi, eksplicitni, način naznačavanja koji će JSP fajlovi biti JSP dokumenti:
u 'web.xml' deskriptoru se za jsp-property-group definiše <is-xml>true</is-xml> (o JSP
setovanjima će biti više reči kasnije). Na ovaj način je moguće setovati da se, na primer, svi '.html' fajlovi posmatraju
kao JSP dokumenta, tj. XHTML. Za razliku od običnog HTMLa, XHTML mora da počne sa:
<html xmlns="http://www.w3c.org/1999/xhtml" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core" xml:lang="en" lang="en">
Rezultujuća stranica koja se vraća klijentu je XML sadržaj. Kontejner sam uključuje default
<?xml version="1.0" encoding="..."?> liniju na početak dokumenta, na koju se može uticati
korišćenjem <jsp:root> taga (nije obavezan). Inače, automatsko generisanje ove XML deklarativne
linije se može eksplicitno zabraniti (<jsp:output omit-xml-declaration="true" />). Dalje, u JSP v2.0 sadržaj dokumenta (konačno:)
ne mora da se nalazi ispod <jsp:root> taga, kao što je to do sada bio slučaj, već može da se
jednostavno piše kao svaki uobičajeni XHTML.
Kako je i dalje u pitanju JSP, postoji način kako koristiti skriplete, deklaracije, direktive, itd. pošto njihov uobičajen način korišćenja nije moguć zbog narušavanja XHTML strukture. Zato su uvedeni odgovarajući tagovi:
| JSP strana | JSP dokument |
<%@ page attribute list %> | <jsp:directive.page attribute list /> |
<%@ include file="path" %> | <jsp:directive.include file="path" /> |
<%! declaration %> | <jsp:declaration>declaration |
<%= expression %> | <jsp:expression>expression |
<% scriptlet %> | <jsp:scriptlet>scriptlet |
Veliki problem do sada je bio dinamičko setovanje vrednosti atributa XHTML tagova. Sledeće dve linije su primeri koje nisu primenjljive u JSP dokumentima:
<table class="%= foo.getTableClass() %">
<table class="<c:out value="${foo.tableClass}" />">
Rešenje bi bilo korišćenje CDATA sekcija, što zahteva mnogo više koda samo radi jedne jednostavne stvari. U JSP v2.0 su te stvari unapređene, pa je moguće jednostavno koristiti EL:
<table class="${user.tableClass}">
Za zahtevnije dinamičke operacije, postoje tagovi za kreiranje celih XML elemenata: <jsp:element>,
<jsp:body>, <jsp:attribute> itd.
JSP v2.0 donosi i mnogo manjih izmena koje mogu biti interesantne. Evo nekih od njih.
'web.xml' fajl je pretrpeo izmene. Najvažnija je da se u JSP v2.0 on validira
prema šemi (schema), a ne kao do sada prema DTD fajlu. Korišćenje šema za validiranje ima značajne
prednosti u odnostu na DTD. Jedna od korisnih prednosti je i ta da sada svi top-level elementi
mogu biti navedeni u bilo kojem redosledu, što doprinosi znatno većoj čitljivosti deskriptora (za početak je
sada moguće grupisati servlet i servlet-mapping definicije:). Redosled unutar
top-level elemenata i dalje mora da se poštuje, ali to ne predstavlja problem.
Svi elementi 'web.xml' koji se tiču JSP konfiguracija se sada nalaze ispod top-level elementa:
<jsp-config>. On može da sadrži samo:
<taglib> i <jsp-property-group>
pod-elemente. Prvi se koriste kao i do sada, a drugi su novi i definišu neke osobenosti JSP stranica (pogledati primere koji slede).
Na kraju, 'web-app' tag sada izgleda ovako:
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
U JSP v2.0 postoji mogućnost da se zabrani korišćenja skripleta na JSP strani:
<%@ page isScriptingEnabled="false" %>
Drugi, ekonomičniji način je njihova zabrana u 'web.xml' fajlu:
<jsp-property-group> <url-pattern>/template/*.jsp</url-pattern> scripting-invalid>true</scripting-invalid> </jsp-property-group>
Slično (i jedino tako) se može zabraniti i korišćenje EL, ako je to već potrebno iz nekog razloga:
<jsp-property-group> <url-pattern>/template/*.jsp</url-pattern> <el-ignored>true</el-ignored> </jsp-property-group>
Sada je moguće odjednom setovati enkoding za grupu JSP stranica:
<jsp-property-group> <url-pattern>*.jsp</url-pattern> <page-encoding>UTF-8</page-encoding> </jsp-property-group>
Slično je moguće implicitno setovati statički header i footer za grupu JSP stranica, odjednom:
<jsp-property-group> <url-pattern>/*.jsp</url-pattern> <include-prelude>/template/prelude.jspf</include-prelude> <include-coda>/template/coda.jspf</include-coda> </jsp-property-group>
JSP v2.0 definitivno donosi stvari koje mogu da olakšaju razvoj web aplikacija, tako da vredi posvetiti pažnju novim mogućnostima.
Inače, u pripremi je JSP v2.1 koji će se baviti i lakšem integrisanju JSF i JSP.
Primer je namenjen za Tomcat 5.x, pošto tek od verzije 5 potpuno podržava JSP v2.0 standard.
Napomena: Tomcat kontejner zna da ignoriše izmene u 'web.xml' koje se tiču JSP setovanja, pa nekada pomaže samo brisanje celog keša.