Apache Struts è un framework open source per lo sviluppo di applicazioni studiato come estensione/evoluzione delle servlet dei progetti J2EE. Permette di creare applicazioni Web di grandi dimensioni, agevola la parallelizazione degli sviluppi e offre delle potentissime tag-lib, la validazione dei form e la gestione della localizzazione/l’internazionalizzazione. In questo sito si fa riferimento sempre alla mitica versione 1.3 del framework, la versione 2 non mi è mai piaciuta ma una guida è disponile vecchia versione del sito. La base del framework si basa su alcuni concetti:
- classi Action gestiscono la logica di business e la logica di forward tramite metodi specifici, di fatto sono estensioni evolute delle classi Servelet
- classi Form gestiscono i dati inseriti dall’utente nelle pagine definendo le regole di validazione dei dati
- le pagine jsp non devono aver nessuna logica ma hanno solo il compito di visualizzare i dati
Un utente esperto avrà notato che queste tre componenti rispettano l’architettura MVC dove il Model sono le classi Form, le view sono le classi jsp e il controtroller sono le classi Action. Il framework per funzionare correttamente ha bisogno che tutte le classi Form e le classi action vengano censite in file di configurazione che storicamente viene sempre chiamato:
struts-config.xml
che deve essere censito nel web.xml. Per creare un semplice esempio di progetto con questo framework si parte da un progetto webapp standard con maven:
mvn archetype:generate -DgroupId=it.alnao -DartifactId=06Struts -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
E bisogna importare le dipendenze del core e della tablib:
<dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts-core</artifactId> <version>1.3.10</version> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts-taglib</artifactId> <version>1.3.10</version> </dependency>
Nel web.xml si vede censire una (e una sola) servlet dove si indica la posizione del file di configurazione xml previsto dal framework:
<servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.nao</url-pattern> </servlet-mapping>
Nel file di configurazione si deve procedere al censimento di due blocchi: il primo riguarda i form-beans, cioè tutte le classi Form del progetto, il secondo definisce l’elenco di tutte le action con il corrispettivo form, path, classe e tutte le classi jsp sulle quali le classi Action potranno fare il forward:
<struts-config> <form-beans> <form-bean name="loginForm" type="it.alnao.mavenExamples.PrimoForm" /> </form-beans> <action-mappings> <action name="loginForm" path="/login" type="it.alnao.mavenExamples.PrimaAction" scope="request" input="/index.jsp"> <forward name="failure" path="/index.jsp" redirect="true" /> <forward name="success" path="/success.jsp" redirect="true" /> </action> </action-mappings> </struts-config>
La classe Action estende un tipo previsto dall’architettura e deve definire obbligatoriamente un metodo execute
che permette di definire logiche di business (come per esempio la validazione di un username-password) con conseguenti logiche di business (per esempio quale pagina visualizzare a seconda se le credenziali sono valide):
public class PrimaAction extends Action { @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { PrimoForm loginForm = (PrimoForm) form; if (loginForm.getUserName() == null || loginForm.getPassword() == null || ! loginForm.getUserName().equalsIgnoreCase("alnao") || ! loginForm.getPassword().equals("bellissimo")) { return mapping.findForward("failure"); } else{ return mapping.findForward("success"); } } }
La classe Form oltre a definire tutti i campi come un semplice Bean/model definiscono due metodi: reset e validate, il primo serve ad inizializzare i dati di un form, il secondo serve a validarli. Qualora una classe action viene eseguita e il suo form non sia valido, la servlet non viene eseguita ma viene eseguito un forward automatico nella pagina definita come input nel file xml di configurazione:
public class PrimoForm extends ActionForm { private String userName = null; //TODO Setter & Getter private String password = null; @Override public void reset(ActionMapping mapping, HttpServletRequest request) { this.password = null; } @Override public ActionErrors validate(ActionMapping mapping, HttpServletRequest request){ // TODO Auto-generated method stub return super.validate(mapping, request); } }
Il sistema di validazione dei dati viene attivato solo se nella pagina jsp viene essere usato un tag form previsto dalla libreria standard struts e gli input previsti dalla libreria standard del framework. Nel metodo presente nella classe ActionForm è possibile creare logiche di validazione come nell’esempio. Il form della pagina che invia dati:
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%> ... <html:form action="/login" focus="userName"> <p>Username : <html:text property="userName" /></p> <p>Password : <html:password property="password" /></p> <p><html:submit value="login" /></p> </html:form>
La tag-lib di struts prevede tre grandi tag: html, bean e logic che verranno descritti in un articolo dedicato.
Il tag più usato è il bean:message per la visualizzazione delle label, questo viene usato perché il framework gestisce nativamente il concento di localizzazione e multilingua: i messaggi vengono censiti in file di proprietà, per esempio il file di default di solito si chiama Application.properties
e deve essere posizionato in un package dell’applicazione:
success.message=Benvenuto
E’ possibile creare un secondo file per una specifica lingua, per esempio un file dedicato ai messaggi in lingua inglese Application_en.properties
che deve essere posizionato nello stesso package del generale:
success.message=Welcome
Il bundle (cioè il gruppo di file di tipo properties) deve essere censito nel file di xml di configurazione con l’indicazione del package e del nome:
<message-resources parameter="it.alnao.Application" key="ApplicationBundle" />
Nella pagina jsp, per visualizzare i messaggi, bisogna prima importare la libreria e poi visualizzare i messaggi indicando il nome del bundle e il nome del messaggio:
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> ... <p><bean:message key="success.message" bundle="ApplicationBundle"/></p>
Per attivare la gestione del multi-lingua nel framework bisogna impostare il “locale” nella prima action chiamata:
request.getSession().setAttribute(Globals.LOCALE_KEY, request.getLocale());
con questa istruzione il framework riuscirà a recuperare la lingua del browser (della request) e selezionerà il messaggio corrispondente al file indicato nel file di configurazione. L’esempio completo funzionante può essere trovato al solito repository:
https://github.com/alnao/JavaExamples/tree/master/GenericJava/06Struts
La caratteristica principale della programmazione di Java è l’uso delle classi e degli oggetti, esattamente come nei file di una classe, all’interno di un file jsp è possibile ed usare usare classi se importate ovviamente metatag:
<%@ page import="it.alnao.manuali.java.NomeClasse"%>
dopo l’import è possibile usare la classe nelle scriptlet, per esempio un metodo statico è richiamabile con:
<% NomeClasse.NomeMetodoStatico(); %>
Per JSP Tags si intendono elementi java utilizzabili nel codice delle pagine jsp, distribuiti dentro a delle librerie particolari dette TagLib che definiscono la “firma” del tag e anche la propria implementazione, l’uso di questi permette di separare il codice “client” da quello “server” con lo scopo di evitare di scrivere codice Java puro nelle pagine jsp e di superare i limiti della programmazione XHTML. Tutti i Custom tag hanno questa sintassi:
<prefix:tag attr1="value" ... attrN="value" />
oppure:
<prefix:tag attr1="value" ... attrN="value" >Body</prefix:tag>
esattamente come un tag di HTML o come i tag standard JSP. Per usare un custom tag dentro ad una jsp bisogna importgare la TagLib e poi definirla, all’interno di ogni TagLib è presente un file TLD che rappresenta le firme dei tag e definisce quali classi java implementano quel tag, è fondamentale conscere il TLD di una taglib.
Il più semplice tag è quello messo a disposizione proprio dal J2EE, nello specifico il tag jsp permette di eseguire operazioni basiche su request e response, per esempio se si vuole usare un oggetto che è già presente in request o in sessione si può ridurre il codice scritto usando il tag usebean, per esempio:
<jsp:useBean id="NomeBean" scope="session" class="it.alnao.manuali.java.NomeClasse"/>
questo tag prende dalla sessione l’oggetto NomeVariabile, lo casta al tipo indicato e crea nella pagina una variabile di nome NomeVariabile con quel valore, cioè questo tag sostituisce l’istruzione
<% NomeClasse var=(NomeClasse) request.getSession().getAttribute("NomeBean"); %>
molto usato in quei progetti dove vengono usate le scriplet e non linguaggi più evoluti come le jstl o i tag Struts, analogamente al tag useBean esistono i tag setProperty e getProperty che servono a valorizzare e leggere proprietà di un oggetto bean, la sintassi è
<jsp:setProperty name="NomeBean" property="NomeProp" param="Valore" /> <jsp:getProperty name="NomeBean" property="NomeProp">
Da notare che per usare questi tag non serve importare nessuna libreria jar perchè sono tag “standard” java e vengono riconosciuti automaticamente dal WebServer, è presente anche un tag per importare altre pagine jsp in maniera dinamica:
<jsp:import
alternativa al bruttissimo:
<%@ include file="filedaincludere.jsp" %>
ma è corretto nominarlo ed evitarlo se possibile.
Per Custom tags si intendoo tag sviluppati all’interno del progetto o comunque non rilasciati ufficialmente dalla libreria J2EE, all’interno delle applicazioni JEE si hanno a disposizione più modi di creare un custom-tag, uno dei metodi più classici è quello di usare una classe java e un TLD per la descrizione del tag detti TLD acronimo di Tag Library Descriptor. Il primo passo per creare un TLD-TAG è quello di creare un file TLD nella giusta cartella del progetto WebContent/WEB-INF/tld/nome.tld
, ricordandosi che ad un tld non corrisponde un solo tag ma corrisponde una libreria che può comprendere anche più tag, una documentazione completa dei file TLD può essere trovata nella documentazione ufficiale , lo scheletro base di questo tipo di file è:
<?xml version="1.0" encoding="UTF-8"?> <taglib version="2.0" 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-jsptaglibrary_2_0.xsd"> <description>Alnao tag library</description> <tlib-version>1.0</tlib-version> <short-name>alnao</short-name> <tag> <name>TagCommentoSenzaParametri</name> <tag-class>it.alnao.prova.tags.TagCommentoSenzaParametri</tag-class> <body-content>JSP</body-content> </tag> <tag> <description>Importo</description> <name>Importo</name> <tag-class>it.alnao.prova.tags.ImportoTag</tag-class> <body-content>JSP</body-content> <attribute> <name>positiveStyle</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>negativeStyle</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib>
in questo file viene definita una libreria assegnandogli anche uno short-name e un elenco di tag dove, per ogni elemento, è definito il nome, la classe e gli attributi se presenti. Poi serve implementare la classe TagCommentoSenzaParametri che deve espandere la classe TagSupport, per esempio un tag java che scrive un commento in pagina è
package it.alnao.prova.tags; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.TagSupport; public class TagCommentoSenzaParametri extends TagSupport { private static final long serialVersionUID = 1L; public int doStartTag() throws JspException { String s="\n\n<!-- prova tag AlNao.it -->\n\n"; try { JspWriter out = pageContext.getOut(); out.println(s); } catch (Exception e) { e.printStackTrace(); } return SKIP_BODY; } public int doEndTag() throws JspException { return EVAL_PAGE; } }
mentre un esempio di tag per la visualizzazione di importi è:
package it.alnao.prova.tags; import java.io.IOException; import java.math.BigDecimal; import java.util.Locale; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.BodyTagSupport; public class ImportoTag extends BodyTagSupport { private static final long serialVersionUID=1L; private String positiveStyle = null; private String negativeStyle = null; private String bodyTag = null; public int doStartTag() throws JspException { return EVAL_BODY_BUFFERED; } public int doAfterBody() throws JspException { bodyTag = getBodyContent().getString().trim(); if (bodyTag != null) { Number decimal; DecimalFormat df = new DecimalFormat(); decimal = df.parse(bodyTag); if (decimal != null) { if (decimal.doubleValue() > 0) { //positivo bodyTag = "<span class=\"" + getPositiveStyle() + "\">"; } else { if (decimal.doubleValue() < 0) { //negativo bodyTag = "<span class=\"" + getNegativeStyle() + "\">"; } } else { //zero bodyTag = "<span class=\"defaultClass\">" ;//+ bodyTag } } else { //non è un numero bodyTag = "<span>"; } return (SKIP_BODY); } public int doEndTag() throws JspException { bodyTag = bodyTag + "</span>"; try { this.pageContext.getOut().print(this.bodyTag); } catch (IOException ioe) { throw new JspException(ioe); } return EVAL_PAGE; } ... metodi get e set delle proprietà ... }
All’interno delle pagine jsp, per poter usare questi tag è necessario importarli con una scriptlet:
<%@ taglib uri="/WEB-INF/tld/nome.tld" prefix="nomeTLD" %>
e poi è necessario usare il prefisso definito per chiamare i singoli tag, per esempio:
<nomeTLD:TagCommentoSenzaParametri /> <nomeTLD:Importo positiveStyle="classeCCS1" negativeStyle="classeCCS2">-12.12</nomeTLD:Importo>
Un metodo più semplice per creare TLD-TAG è usare classi java pure e, grazie alla tecnica dell’ereditarietà di Java, utilizzare classi già esistenti per evitare di scrivere codice già presente in altri tag, per esempio è possibile creare un tag condizionale “if” personalizzato che abbia due parametri in input, se sono uguali il corpo del tag verrà visualizzato in pagina, altrimenti il codice verrà saltato, riportando il codice di esempio di questo tag condizionale:
import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.jstl.core.ConditionalTagSupport; public class IfTag extends ConditionalTagSupport { private String value1 = null; private String value2 = null; public IfTag() { super(); } protected boolean condition() throws JspTagException { if (value1==null || value2==null) throw new JspTagException ("Parametri nulli"); return value1.equals(value2); } }
dopo aver definito il file tld corrispettivo, in una qualsiasi pagina jsp poi basta usare il tag così:
<MieiTag:IfTag value1="uno" value2="due"> <% //questo codice non viene eseguito perchè "uno" è diverso da "due" %> </MieiTag:IfTag> <MieiTag:IfTag value1="tre" value2="tre"> <% //questo codice viene eseguito perchè le stringhe sono uguali %> Viene mostrato questo messaggio perchè "tre"=="tre" </MieiTag:IfTag>
Allo stesso modo è possibile scrivere un tag “else” che estende la classe “if” in questo modo ma che nega il valore del metodo condition:
public class ElseTag extends IfTag{ protected boolean condition() throws JspTagException { return ! super(); } }
nota: la classe ConditionalTagSupport si trova nella libreria jstl che deve essere importata nel file di configurazione di Maven.
Creare un custom-tag con una classe java è una tecnica molto elegante ma può risultare complicata se si deve scrivere un TAG che comprende molto codice client all’interno perché, per scrivere codice HTML dalla classe, si usa il metodo out che può risultato non semplicissimo da usare e il risultato rischia di diventare una classe molto lunga con molte stringhe costanti all’interno del codice. Esiste una alternativa alla tecnica dei Java-TLD: usare un file jsp dedicato al posto di una classe Java. Prima di tutto bisogna sempre definire un TLD e il riferimento al tag senza però nessun parametro anche se previsti, per esempio:
<tag-file> <name>tag_esempio</name> <path>/WEB-INF/tags/esempio.tag</path> </tag-file>
poi è necessario creare il file che per convenzione ha estensione tag anche se in realtà è un file jsp, questo file deve sempre iniziare con il meta-tag specifico previsto da J2EE:
<%@ tag %>
e al suo interno deve essere presente l’elenco degli attributi, cioè i parametri del tag, per esempio:
<%@ attribute name="oggetto" required="true" rtexprvalue="true" description="." %>
e dopo si inserisce il codice HTML/Java del tag come se fosse un file jsp, per esempio
<DIV class="classeDiv"> L'oggetto ha nome <%=request.getParameter("oggetto")%> </DIV>
Per richiamare il tag da qualsiasi pagina JSP basta invocarlo richiamando il tag definito nel TLD:
<tagLib:tag_esempio oggetto="valore" />
Scegliere tra con una classe Java o con un file jsp è una questione di gusti, tipicamente si usano i file jsp quando il codice HTML è tanto e il codice Java è poco, viceversa si usano le classi quando il codice Java è molto complicato oppure se si deve definire un tag che estende un altro tag. La documentazione ufficiale è sempre il punto di riferimento per tutti gli sviluppatori.
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>
Eclipse è un ambiente di sviluppo (SDK), in questi articoli viene usato per la gestione di tutti i progetti Java, è possibile usare anche altri tool compatibili con Java-Maven come Visual Studio Code di Microsoft o i tool a pagamento come IntelliJ.
In Eclipse i progetti sono raggruppati in un workspace, tipicamente si usa una cartella del sistema come base di tutto lo spazio di lavoro e ogni sotto-cartella rappresenta un progetto, in questi articoli saranno usati solo progetti Java-Maven ma è possibile usare questo programma anche per altri tipi di progetto come i vecchi progetti J2EE e i progetti java puri.
Per creare un progetto Maven, si deve avvia la procedura guidata di creazione di un progetto dal menù principale e selezionando la voce “New”, il tipo “Project” e poi cercare il wizard “Maven project”. Nella finestra successiva si deve selezionare il Archetype, esattamente si si esegue in fase di creazione con la console testuale vista nel precedente articolo. Qui è possibile anche selezionare un tipo da una lista che Eclipse scarica da internet dai vari repository ufficiali e non, disponibili in tutto il monto. Se si vuole creare un progetto base senza particolari esigenze, è consigliato usare gli archetipi disponibili dal sito “org.apache.maven.archetypes”, per esempio selezionando il tipo “maven-archetype-simple”.
Nella seconda videata della procedura guidata è richiesto l’inserimento dei valori come il GroupId e il ArtifactId, esattamente come nella procedura da riga di mando. Una volta lanciato il processo di creazione nella vista console di Eclipse è possibile verificare tutti i messaggi di conferma che maven darebbe se il comando fosse lanciato da riga di comando. Al termine il progetto è pronto all’uso nella vista dei progetti con il suo pom.xml generato in automatico.
Eclipse permette anche di importare un progetto Maven non presente nel workspace, è consigliato importare progetti che si trovano nella stessa cartella del workspace stesso altrimenti potrebbero esserci problemi di conflitti da files, la procedura di import può essere lanciata dal menù principale nella voce “Import” e selezionando il wizard “Existing maven projects”. Nella procedura guidata è necessario indicare la posizione esatta del file pom.xml, senza questo file infatti non si può parlare di progetto di tipo Maven.
Un progetto di tipo Maven in Eclipse si può riconoscere da una piccola lettera M presente nell’icona del progetto a fianco dell’icona J che indica Java come tipo di linguaggio del progetto, questo tipo di progetti hanno un menù dedicato tra le opzioni del progetto accessibili cliccando con il tasto destro nel progetto stesso. La funzionalità più interessante è la possibilità di aggiungere con una piccola procedura guidata una dipendenza la progetto, questa è l’alternativa più semplice al modificare il file pom.xml manualmente, per esempio per voler inserire la dipendenza dalla libreria log4j, disponbile all’indirizzo ufficiale è possibile aggiungere manualmente nel pom il tag:
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
oppure è possibile inserire i tre valori (groupId, artifactId e version) nella procedura guidata di Eclipse. Un semplice esempio di utilizzo di Log4J
package it.alnao.mavenEclipse;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
public class App {
private static final Logger logger = LogManager.getLogger(App.class);
public static void main( String[] args ){
BasicConfigurator.configure();
System.out.println( "Hello World!" );
logger.info("Hello world");
//set a breakpoint here to debug project
System.out.println( "END!" );
}
}
Per i progetti di questo tipo il programma mette a disposizione di compilazione nel sotto-menù “Run as” dove è possibile lanciare i comandi standard maven:
- “Maven install” che esegue il comando di installazione delle librerie dipendenti
- “Maven build” esegue la compilazione del progetto, alla prima esecuzione bisogna impostare “package” come Goal della compilazione così maven usa la cartella target come destinazione del jar corrispondente
- “Maven test” esegue tutte i test indicati nel file di configurazione
- “Java application” esegue il progetto come fosse una applicazione java senza compilare il jar
Eclipse dispone anche di una procedura per eseguire i debug di un progetto, per esempio inserendo un breakpoint in un punto del codice Java e poi cliccando sul sotto-menu “Debug” del progetto e selezionando la voce “Java application”.