Per la creazione di applicazioni web Java mette a disposizione la tecnologia Java 2 Enterprise Edition (spesso abbreviata con la sigla J2EE), tecnica diventata negli anni uno standard molto usato in quanto robusto, sicuro ma anche flessibile. Il successo è dovuto soprattutto al linguaggio Java stesso che può fondersi con le tecnologie di frontend come HTML e Javascript. La tecnologia si può dividere in alcune componenti base. Si tratta delle tecnologie legate alla produzione di interfacce web dinamiche, le cui componenti si possono dividere in tre parti:
- pagine web Java Server Pages (JSP), Java Server Faces (JSF), Custom Tag oppure framework specifici come Struts
- logiche di business con Enterprise JavaBeans (EJB, giunti alla specifica 3.0), JNDI e Java Message Service (JMS)
- librerie esterne: esposizione di webservice, gestione di protocolli di rete.
La tecnologia permette facilmente di gestire la tecnologia model-view-controller (MVC) infatti, come standard universalmente usato i componenti si dividono in:
- model: classi Bean/DAO java spesso esterne ai progetti J2EE
- view: pagine web/jsp scritte in HTML con i tag messe a disposizione dalle varie librerie importabili
- controller: classi servlet oppure uso di un framework specifico come Struts
Eclipse mette a disposizione una procedura guidata per creare “Dynamic web Project” che rispettano lo standard J2EE ma conviene usare l’archetipo messo a disposizione dal Maven che risulta più completo e oggi lo standard mondiale per le applicazioni web in Java, da riga di comando si può lanciare
mvn archetype:generate -DarchetypeArtifactId = maven-archetype-webapp
oppure è possibile usare la procedura guidata di Eclipse selezionando l’archetipo “maven-archetype-webapp” Nel progetto creato vengono create le cartelle e i files:
- src/main/java: contiene tutte le classi java del progetto
- src/main/resources: contiene i file di properties del progetto
- src/main/webapp: contiene tutti i file jsp e la sotto-cartella WEB-INF
- src/main/webapp/WEB-INF: contiene tutti i componenti dell’applicazione che non si trovano nella root dell’applicazione, difficile definizione.
- src/main/webapp/WEB-INF/web.xml: file di configurazione del progetto J2EE, questo descrive tutte le componenti del progetto web
- src/main/webapp/WEB-INF/index.jsp: pagina di esempio
- src/main/webapp/WEB-INF/lib: cartella che può contenere jar usati dall’applicazione
- src/main/webapp/resources: può contenere tutte le componenti statiche del progetto web come immagini e stili
Talvolta, in alcune vecchie versioni dello standard J2EE la cartella “WebApp” veniva indicata con il nome di “WebContent”. Una volta creato il progetto è possibile impostare la vista “Servers” di Eclipse per avviare dal programma il progetto web: prima bisogna impostare la “Server runtimes” nelle preferenze di Ecipse e poi agganciare l’applicazione nella view “Servers”. Trattandosi di un progetto Maven standard è possibile compilarlo con il comando
mvn clean package
oppure usando il “mvn build” di Eclipse impostando il goal di tipo “package”. Il risultato della compilazione non è un jar ma è un file war, questo può essere caricato in qualsiasi web-server java come Tomcat. In questo semplice progetto c’è solo una pagina che viene caricata e non c’è nessun codice java compilato.
Le servelt sono le classi java che, all’interno di un progetto web, hanno il compito di controllare il comportamento dell’applicazione, inteso proprio come controller nel paradigma MVC. Le classi sono composte da due proprietà una request (di tipo HttpServletRequest) e una response (di tipo HttpServletResponse), attraverso il primo oggetto è possibile accedere a tutte le informazioni utili come i parametri di input e gli oggetti in sessione mentre il secondo oggetto, inizialmente vuoto, deve essere valorizzato con la risposta che si vuole inviare al client, inoltre è disponibile anche un oggetto ServletContext (di tipo javax.servlet.ServletContext) con la quale è possibile accedere alle informazioni del contesto (context) di un’applicazione cioè tutte le informazioni generali. Le classe implementa uno dei metodi HTTP usati per la chiamata: doGet, doPost, doPut, doDelete.
Per creare una classe di questo tipo è possibile usare la procedura guidata di Eclipse che è possibile eseguire dal menù “New” selezionando il tipo “Classe Java Servlet” oppure è indispensabile creare a mano la classe con proprietà e metodi. Alla prima creazione, può comparire un errore di compilazione risolvibile facilmente impostando il “Java build path” del progetto java di Eclipse aggiugnendo le librerie ServerRuntime e WebAppLibraries. Da notare che, se si è usati la procedura guidata di Eclipse, questo avrà modificato in automatico il file web.xml impostando la servlet, se invece si è scelto di creare le classi a mano è indispensabile censire la servlet nel file:
<servlet>
<servlet-name>PrimaServlet</servlet-name>
<display-name>PrimaServlet</display-name>
<description></description>
<servlet-class>it.alnao.mavenExamples.PrimaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PrimaServlet</servlet-name>
<url-pattern>/PrimaServlet</url-pattern>
</servlet-mapping>
Questi due tag nel file di configurazione impostano due parametri: assegnano alla classe java un nome e assegnano a quel nome un pattern, questo ultimo sarà il endpoint nel quale la servelt sarà esposta nell’applicazione web. Infatti il webserver risponderà con la servelt dal endpoint:
http://localhost:<porta>/05mavenWebapp/PrimaServlet
Per stampare codice HTML da una servlet bisogna usare la classe “Printer”, un semplice esempio di codice di servlet per visualizzare una frase:
private static final String HTML_TOP = "<html><head><title>Primo esempio servlet: tabelline</title></head><body>";
private static final String HTML_BOTTOM = "</body></html>";
private static final String TABLE_TOP = "<h3>Tabelline</h3><table width='80%'>";
private static final String TABLE_BOTTOM = "</table>";
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println(HTML_TOP);
out.println("Questa tecnica non è molto usata");
out.println(HTML_BOTTOM);
}
Tuttavia questa tecnica è poco usata in quanto non rispetta il paradigma di MVC: le servlet devono solo occuparsi della fase controller e non del view, per separare i compiti il controller richiama le componenti view (cioè le classi JSP) con un dispatcher.
request.setAttribute("nomeInRequest", "Alberto");
request.getSession().setAttribute("cognomeInSessione","Nao");
request.getRequestDispatcher("prova.jsp").forward(request, response);
In questo semplice esempio alla pagina di prova è possibile trasmettere dei dati attraverso la request oppure attraverso la sessione, si rimanda alla documentazione ufficiale per un approfondimento di cosa sono e come usare queste due tecniche. La pagina di default è sempre “index.jsp”, tuttavia è possibile personalizzare la pagina di ingresso con un tag nel file di configurazione web.xml:
<welcome-file-list>
<welcome-file>prova.jsp</welcome-file>
</welcome-file-list>
La parte Java all’interno delle pagine JSP viene compilata in maniera sequenziale dalla prima riga, quindi all’inizio di ogni file si possono inserire le direttive che servono al compilatore Java per indicare come compilare la pagina, istruzioni simili alle import nelle classi Java, queste istruzioni vengno dette direttive e si indicano in una pagina con il tag:
<%@ page import="java.util.*" %>
per importare una o più classi e sono da usare come gli import java, usare una classe java in una jsp senza import genera un errore di compilazione che però viene segnalato solo in fase di esecuzione quindi solo quando la pagina jsp viene eseguita.
<%@ include file="filedaincludere.jsp" %>
in questo secondo esempio viene usata la direttiva include per includere nella corrente pagina un altro file jsp che verrà compilato assieme. Altre direttive molto usate sono sono:
<%@ page contentType="text/html" %>
<%@ taglib prefix="myprefix" uri="taglib/miataglib.tld" %>
importa nella pagina JSP una tag-lib che essere identificata tramite una URI (questo argomento viene approfondito nei prossimi articoli). Per quanto riguarda il codice java dentro le pagine jsp, di base si usano le scriptlet, sistema creato proprio per “mischiare” il codice HTML (client) e il codice Java (server) anche se questo sistema è considerato deprecato viene ancora usato ma molti anche per ragioni di retro-compatibilità nei progetti di grandi dimensioni. La prima disputa sul termine scriplet è se, in lingua italiana, il termine sia maschile (gli scriplet) o femminile (le scriptlet), ogni programmatore ha la propria opinione. In un corpo di pagina, una scriplet inizia con <%
e termina con %>
, per esempio:
<%
int i=0;
i++;
%>
In particolare si possono usare scriplet anche per fare cicli o condizioni di elementi HTML, per esempio
<%
for (int i = 0; i < 5; i++){
%> Ciao Mondo! <%
}
%>
<%!
, per esempio:<%!
public int void contaParole (String s){
StringTokenizer st = new StringTokenizer(s);
return st.countTokens();
}
%>
Ed è possibile definire il metodo jspInit che viene lanciato una sola volta e serve per inizializzare gli elementi in pagina e il metodo jspDestroy per la pulizia a fine caricamento. Le scriplet vengono usate soprattutto per inviare al client dei valori dal server, cioè passare dei valori da Java all’HTML, l’uso del tag <%=, da notare che in questo caso è possibile inserire una sola riga e NON si deve mettere il ; (punto e virgola) finale, credo sia l’unico caso in java:
<%=i%>
<%=contaParole("Quante sono queste parole?")%>
Da notare che gli oggetti request, session, out, exception e application sono oggetti considerati impliciti nella pagina quindi non serve importarli e/o definirli, per esempio è possibile usare:
<% out.print("valore"); %>
<%=valore%>
<%
String valoreId=request.getParameter("id");
session.setAttribute("id",valoreId);
%>
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+
":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Prova</title>
</head>
<body>
Pagina di prova
<br/>
BasePath = <%=basePath%>
<br />
<%=request.getAttribute("nomeInRequest") %>
<%=request.getSession().getAttribute("cognomeInSessione") %>
</body>
</html>