Laboratorio di Sistemi Fattoriale di un numero Jsp [Java] Desideriamo realizzare una applicazione web che ci consenta di calcolare il fattoriale di un numero. L'esercizio in sé non particolarmente difficile, tuttavia esso ci consentirà di affrontare il problema da diversi punti di vista. Modalità 1) Realizziamo l'applicativo usando gli scriplet: Pagina index.jsp <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <h3>Calcolo del fattoriale</h3> <form name="provaFrm" action="${request.requestURI}"> Dammi un numero intero <input type="text" name="numberTxt" value=""/> <input type="submit" name="inviaBtn" value="Invia"/> </form> <% // se è stato premuto il pulsante if (request.getParameter("inviaBtn")!=null) { // acquisisco il valore stringa della casella testuale String numberStr = request.getParameter("numberTxt"); try { // converto la stringa in un numero intero "grande" long number = Long.parseLong(numberStr); // cambio il segno se il numero è negativo if (number < 0) number = -number; // trovo il fattoriale col classico algoritmo iterativo long fatt = 1; for (int i = 1; i <= number; i++) fatt = fatt * i; fattoriale.pdf Pag. 1/12 Cozzetto © Laboratorio di Sistemi Fattoriale di un numero Jsp [Java] // visualizzo il risultato out.println("<br/><br/>Il fattoriale di "+number+ " è "+fatt); } catch(NumberFormatException e) { out.println("<br/><br/>Attenzione! Controlla il valore inserito"); } catch(Exception e) { out.println("<br/><br/>Errore generico. Messaggio: "+e.getMessage()); } } // fine if %> </body> </html> Nel codice precedente, abbiamo anche gestito l'eccezione che si può verificare se l'utente immette una sequenza qualsiasi di caratteri invece che un numero intero (non possiamo infatti calcolare il fattoriale di una stringa). Questo approccio che consiste nell'inserire tutta la logica (la cosiddetta business logic) nella pagina web index.jsp non è consigliabile in quanto, se vogliamo riutilizzare l'algoritmo, siamo costretti a fare un copia-incolla del codice. Modalità 2) Decidiamo ora di inserire il codice in una classe java molto semplice, che possiamo riutilizzare tutte le volte che è necessario e in contesti differenti. Ad esempio, riutilizzando la classe, possiamo progettare un'applicazione GUI (lo sviluppo è lasciato come esercizio): fattoriale.pdf Pag. 2/12 Cozzetto © Laboratorio di Sistemi Fattoriale di un numero Jsp [Java] o un'applicazione”console”: La classe cioè può essere considerata un “componente” riutilizzabile. /* * Fattoriale.java * */ package fattPkg; /** * * @author maurizio */ public class Fattoriale { private long number; /** Creates a new instance of Fattoriale */ public Fattoriale() { number=1; } // “getter” public long getNumber() { return number; } // “setter” public void setNumber(long number) { this.number = number; } // metodo che restituisce il fattoriale di number public long getFattoriale() { // trovo il fattoriale col classico algoritmo iterativo long fatt = 1; fattoriale.pdf Pag. 3/12 Cozzetto © Laboratorio di Sistemi Fattoriale di un numero Jsp [Java] for (int i = 1; i <= number; i++) fatt = fatt * i; return fatt; } // fine metodo getFattoriale } // fine classe Fattoriale Questa volta l'algoritmo non si trova più nella pagina web ma è “cablato” nella classe Fattoriale. Quello che noi dobbiamo fare è utilizzare la classe, istanziando un oggetto di tipo Fattoriale. Pagina index2.jsp <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <h3>Calcolo del fattoriale</h3> <form name="provaFrm" action="${request.requestURI}"> Dammi un numero intero <input type="text" name="numberTxt" value=""/> <input type="submit" name="inviaBtn" value="Invia"/> </form> <% // se è stato premuto il pulsante if (request.getParameter("inviaBtn")!=null) { // acquisisco il valore stringa della casella testuale String numberStr = request.getParameter("numberTxt"); try { // converto in un numero intero "grande" long number = Long.parseLong(numberStr); // cambio il segno se l'utente introduce un valore negativo if (number < 0) number = -number; // istanzio l'oggetto fatt che mi servirà per calcolare il fattoriale fattPkg.Fattoriale fatt = new fattPkg.Fattoriale(); // "settiamo" il valore su cui calcolare il fattoriale fattoriale.pdf Pag. 4/12 Cozzetto © Laboratorio di Sistemi Fattoriale di un numero Jsp [Java] // (è quello inserito nella casella testuale) fatt.setNumber(number); // visualizzo il risultato out.println("<br/><br/>Il fattoriale di "+number+ " è "+fatt.getFattoriale()); } catch (NumberFormatException e) { out.println("<br/><br/>Errore! Ricontrolla i dati inseriti."); } catch (Exception e) { out.println("<br/><br/>Errore generico. Messaggio: "+e.getMessage()); } } // fine if %> </body> </html> Il vantaggio di questo approccio è quello di svincolare la logica dalla parte di presentazione affidata alla pagina jsp. Modalità 3) Non vi sono sostanziali differenze rispetto all'approccio precedente. Utilizziamo l'azione standard <jsp:useBean> che equivale a istanziare un oggetto. Impostiamo successivamente la proprietà (variabile attributo) number al valore inserito nella casella testuale (dato di input). Pagina index3.jsp <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <h3>Calcolo del fattoriale</h3> <form name="provaFrm" action="${request.requestURI}"> Dammi un numero intero <input type="text" name="numberTxt" value=""/> <input type="submit" name="inviaBtn" value="Invia"/> </form> fattoriale.pdf Pag. 5/12 Cozzetto © Laboratorio di Sistemi Fattoriale di un numero Jsp [Java] <% // se è stato premuto il pulsante if (request.getParameter("inviaBtn")!=null) { // acquisisco il valore stringa della casella testuale String numberStr = request.getParameter("numberTxt"); try { // converto la stringa in un numero intero long number = Long.parseLong(numberStr); // cambio il segno se l'utente introduce un valore negativo if (number < 0) number = -number; %> <jsp:useBean id="fatt" class="fattPkg.Fattoriale"/> <jsp:setProperty name="fatt" property="number" value="<%=number %>" /> <% // visualizzo il risultato out.println("<br/><br/>Il fattoriale di "+number+ " è "+fatt.getFattoriale()); } catch (NumberFormatException e) { out.println("<br/><br/>Errore! Ricontrolla i dati inseriti."); } catch (Exception e) { out.println("<br/><br/>Errore generico. Messaggio: "+e.getMessage()); } } // fine if %> </body> </html> Lo svantaggio di questo approccio è che mescolando HTML e scriplet rendiamo poco leggibile e mantenibile nel tempo il codice (lo stesso problema affligge anche Php) Modalità 4) Questa volta invece di alternare codice java (scriplet) e codice HTML (testo template) nella pagina web, decidiamo di usare le azioni disponibili nel framework JSTL (JavaServer Pages Standard Tag Library). Ricordiamoci di inserire nel progetto tali librerie (tasto destro del mouse su nome del progetto > Properties > Libraries > Compile > Add Libraries > JSTL 1.1). Pagina index4.jsp <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> fattoriale.pdf Pag. 6/12 Cozzetto © Laboratorio di Sistemi Fattoriale di un numero Jsp [Java] <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <h3>Calcolo del fattoriale</h3> <form name="provaFrm" action="${request.requestURI}"> Dammi un numero intero <input type="text" name="numberTxt" value=""/> <input type="submit" name="inviaBtn" value="Invia"/> </form> <c:if test="${!empty param.inviaBtn}"> <c:set var="number" value="${param.numberTxt}"/> <c:catch var="e"> <c:if test="${empty number}"> <c:set var="number" value="1"/> </c:if> <c:if test="${number<0}"> <c:set var="number" value="${-number}"/> </c:if> <jsp:useBean id="fatt" class="fattPkg.Fattoriale"/> <jsp:setProperty name="fatt" property="number" value="${number}" /> <br/><br/>Il fattoriale di ${number} è <c:out value="${fatt.fattoriale}"/> </c:catch> <c:if test="${!empty e}"> <br/><br/>Errore: ricontrolla i dati inseriti </c:if> </c:if> </body> </html> fattoriale.pdf Pag. 7/12 Cozzetto © Laboratorio di Sistemi Fattoriale di un numero Jsp [Java] Modalità 5) In quest'ultimo esempio, introduciamo la nuova classe StringValidation.java. Essa conterrà una serie di metodi statici che ci consentiranno ad esempio di validare un numero intero (come nel nostro caso), indirizzi di posta elettronica, codici di avviamento postale, ssn (social security number) ecc mediante l'utilizzo delle cosiddette “regular expression” (espressioni regolari). /* * StringValidation.java */ package fattorialePkg; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author maurizio */ public class StringValidation { /** Creates a new instance of StringValidation */ public StringValidation() { } public static boolean isNumeric(String number){ boolean isValid = false; // denota una sequenza di caratteri String expression = "[0-9]*"; CharSequence inputStr = number; // una breve e utile guida sulle espressioni regolari si trova all'indirizzo // http://www.zparacha.com/java_regex_validation/ Pattern pattern = Pattern.compile(expression); Matcher matcher = pattern.matcher(inputStr); if(matcher.matches()){ isValid = true; } return isValid; } // fine metodo isNumeric // altri metodi di validazione } // fine classe StringValidation fattoriale.pdf Pag. 8/12 Cozzetto © Laboratorio di Sistemi Fattoriale di un numero Jsp [Java] Riscriviamo inoltre la classe Fattoriale introducendo alcune modifiche dettate da motivi di opportunità (sostanzialmente cambiamo il tipo della variabile attributo da long a String) e scegliamo un valore minimo e un valore massimo per il calcolo del fattoriale. Per distinguere questa nuova classe dalla precedente, la inseriamo in un altro package e le assegnamo il nuovo nome FattorialeBean. /* * FattorialeBean.java * * Created on 31 gennaio 2008, 4.34 * * */ package fattorialePkg; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * * @author maurizio */ public class FattorialeBean implements java.io.Serializable { private String number; private final static int MIN=0; private final static int MAX=20; /** Creates a new instance of FattorialeBean */ public FattorialeBean() { number="1"; } // setter di number public void setNumber(String number) { this.number=number; } // getter di number public String getNumber() { return number; } // metodo per il calcolo del fattoriale public long getFattoriale() { long f=1; for (int i=1; i<=Long.parseLong(number); i++) f=f*i; return f; } fattoriale.pdf Pag. 9/12 Cozzetto © Laboratorio di Sistemi Fattoriale di un numero Jsp [Java] // metodo per controllare la validità di un numero intero public boolean isValidNumber() { boolean isValid=false; if (StringValidation.isNumeric(number) && Long.parseLong(number)>=MIN && Long.parseLong(number)<=MAX) isValid=true; return isValid; } // fine metodo isValidNumber } // fine classe FattorialeBean File index5.jsp <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Calcolo del fattoriale di un numero</title> </head> <body> <h3>Calcolo del fattoriale mediante javabean</h3> <form name="provaFrm" action="${request.requestURI}" method="post"> Introduci un valore intero <input type="text" name="number" value="$ {fatt.number}" /> <input type="submit" name="submit" value="Invia" /> </form> <c:if test="${!empty param.submit}"> <jsp:useBean id="fatt" class="fattorialePkg.FattorialeBean"/> <jsp:setProperty name="fatt" property="*"/> <c:choose> <c:when test="${fatt.validNumber}"> <br/>Il fattoriale è ${fatt.fattoriale} </c:when> <c:otherwise> <br/>Attenzione! Ricontrolla il valore inserito. Deve essere compreso tra 1 e 20. </c:otherwise> </c:choose> </c:if> </body> </html> fattoriale.pdf Pag. 10/12 Cozzetto © Laboratorio di Sistemi Fattoriale di un numero Jsp [Java] Proviamo a introdurre un valore non previsto dal sistema fattoriale.pdf Pag. 11/12 Cozzetto © Laboratorio di Sistemi Fattoriale di un numero Jsp [Java] Il valore 21 non è infatti consentito e appare quindi un messaggio di avviso. Anche l'inserimento di un valore negativo o di una stringa, produce lo stesso effetto. fattoriale.pdf Pag. 12/12 Cozzetto ©