Laboratorio di sistemi Fortune Java/Jsp Ricordiamo che in Ubuntu il

Laboratorio di sistemi
Fortune
Java/Jsp
Ricordiamo che in Ubuntu il comando “fortune” impartito da shell produce una frase
umoristica, un anedotto o una frase bizzarra ecc. Si può installare e localizzare nella
lingua italiana mediante il comando apt-get.
Proviamo anche noi a scrivere due differenti versioni dello stesso applicativo,
ovviamente usando il linguaggio di programmazione java; il primo sarà dotato di una
GUI (interfaccia utente grafica) mentre l'altro consisterà in una web application e
manderà il proprio output all'interno di un browser come IE o Firefox; lasciamo a voi il
compito di scrivere la versione da riga di comando.
Come prima cosa, supponiamo che le frasi (e i relativi autori) siano archiviati in un file
testuale (fortune.txt). Frase e autore sono separati dal carattere | come nell'esempio.
-"In realta', agente, il mio nome e' Bond. James Bond". -"Gia', e io sono Superman.
E lei e' sempre in arresto".|Roger Moore, da "007 Bersaglio mobile"
Così facendo possiamo poi aggiungere a piacimento le frasi più simpatiche ed
eliminare quelle col tempo ritenute meno interessanti. Facciamo in modo che l'utente
abbia l'opportunità di scegliere a caso una delle frasi precaricate nel database.
fortune.pdf
Pag. 1/13
Cozzetto ©
Laboratorio di sistemi
Fortune
Java/Jsp
Classi di supporto
Progettiamo due classi Frase e ListaFrasi:
package fortunejavaapp;
import java.util.Scanner;
/**
*
* @author maurizio
*/
public class Frase {
String contenuto;
String autore;
Frase() {
contenuto = "Tanto va la gatta al lardo che ci lascia lo zampino";
autore = "Anonimo";
}
Frase(String contenuto, String autore) {
this.contenuto = contenuto;
this.autore = autore;
}
Frase leggiFrase() {
Scanner sc = new Scanner(System.in);
String content = sc.next();
String author = sc.next();
return new Frase(content, author);
}
@Override
public String toString() {
return contenuto+"
\n-- "+autore;
}
void stampaFrase() {
System.out.println(toString());
}
} // fine classe Frase
fortune.pdf
Pag. 2/13
Cozzetto ©
Laboratorio di sistemi
Fortune
Java/Jsp
/*
* ListaFrasi.java
*
*/
package fortunejavaapp;
import
import
import
import
import
import
java.io.BufferedReader;
java.io.FileNotFoundException;
java.io.FileReader;
java.io.IOException;
java.util.Random;
java.util.StringTokenizer;
/**
* @author maurizio
*/
public class ListaFrasi {
public Frase[] frasi;
public int numFrasi = 0;
/** Numero massimo di frasi che è possibile caricare in memoria */
public static final int MAX_FRASI = 100;
/** Costruttore nullo */
public ListaFrasi() {
frasi = new Frase[MAX_FRASI];
}
/** Costruttore con parametro il numero di frasi */
public ListaFrasi(int n) {
if (n>=1 && n<=MAX_FRASI)
frasi = new Frase[n];
else
frasi = new Frase[MAX_FRASI];
}
/** Genero una frase casuale tra quelle caricate in memoria */
public Frase getFraseACaso() {
Random generatore = new Random();
int i = generatore.nextInt(numFrasi);
return frasi[i];
}
/** Aggiungo una nuova frase */
public void aggiungiFrase(Frase f) {
if (numFrasi<MAX_FRASI && f!=null) {
frasi[numFrasi++]=f;
}
}
fortune.pdf
Pag. 3/13
Cozzetto ©
Laboratorio di sistemi
Fortune
Java/Jsp
/** Prelevo dal disco le frasi e le porto in RAM */
public int caricaFrasi(String file) throws FileNotFoundException, IOException {
int numRecord=0;
try {
// apertura del file in lettura
FileReader fr = new FileReader(file);
BufferedReader bfr = new BufferedReader(fr);
// lettura di tutti i record e caricamento nel vettore
String s = bfr.readLine();
while (s!=null) {
StringTokenizer st = new StringTokenizer(s,"|");
Frase frase = new Frase();
frase.contenuto = st.nextToken();
frase.autore = st.nextToken();
aggiungiFrase(frase);
numRecord++;
s = bfr.readLine();
} // fine while
// chiusura
bfr.close();
fr.close();
} catch(FileNotFoundException e) {
throw new FileNotFoundException(e.getMessage());
} catch (IOException e) {
throw new IOException(e.getMessage());
}
return numRecord;
} // fine metodo caricaFrasi()
} // fine classe ListaFrasi
fortune.pdf
Pag. 4/13
Cozzetto ©
Laboratorio di sistemi
Fortune
Java/Jsp
Versione GUI
Nel caso di una GUI, la frase appare in una textarea e l'utente sceglie la frase
successiva cliccando sul pulsante “Random” come in figura. Per comodità, ipotizziamo
che tutto il nostro database sia caricato interamente in memoria. Il file fortune.txt si
trova nel package risorse.
/*
* Fortune.java
*/
package fortunejavaapp;
import
import
import
import
import
import
import
java.awt.FlowLayout;
java.io.FileNotFoundException;
java.io.IOException;
javax.swing.JButton;
javax.swing.JFrame;
javax.swing.JOptionPane;
javax.swing.JTextArea;
/**
*
* @author maurizio
*/
public class Fortune extends JFrame {
ListaFrasi lf = new ListaFrasi();
JTextArea frase;
JButton random;
/** Costruttore */
public Fortune(String title) {
this.setTitle(title);
int numRecord = 0;
try {
numRecord=lf.caricaFrasi(System.getProperty("user.dir")
+"/build/classes/risorse/fortune.txt");
} catch (FileNotFoundException e) {
fortune.pdf
Pag. 5/13
Cozzetto ©
Laboratorio di sistemi
Fortune
Java/Jsp
JOptionPane.showMessageDialog(null, "Il file non è stato trovato:
"+e.getMessage());
System.exit(1);
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Vi è un errore di I/O:
"+e.getMessage());
System.exit(1);
}
JOptionPane.showMessageDialog(null, "Sono stati caricati "+numRecord+"
record dal database fortune.txt");
inizializzaComponenti();
// istruzione necessaria altrimenti la finestra continua ad essere
// residente in memoria
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
} // fine Costruttore
/** predispone il layout grafico e istanzia l'oggetto delegato a gestire l'evento click
sul pulsante */
void inizializzaComponenti() {
random = new JButton("Random");
frase = new JTextArea(" L'amore e' come una clessidra: \nquando si riempie il
cuore, si svuota il cervello.\n\n--Anonimo");
/** Impostiamo il layout FlowLayout */
this.setLayout(new FlowLayout());
/** Aggiungo al frame il testo */
this.add(frase);
/** Aggiungo al frame il bottone */
this.add(random);
/** Creo un ascoltatore per il bottone */
GestorePulsante gp = new GestorePulsante(frase, lf, this);
/** Registro il gestore presso il bottone */
random.addActionListener(gp);
// si può anche scrivere più brevemente
// random.addActionListener(new GestorePulsante(frase, lf, this));
} // fine inizializzaComponenti
} // fine classe Fortune
fortune.pdf
Pag. 6/13
Cozzetto ©
Laboratorio di sistemi
Fortune
Java/Jsp
/*
* GestorePulsante.java
*
*/
package fortunejavaapp;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
/**
*
* @author maurizio
*/
class GestorePulsante implements ActionListener {
JTextArea frase;
ListaFrasi lf;
JFrame frame;
/** Costruttore con 3 parametri */
public GestorePulsante(JTextArea frase, ListaFrasi lf, JFrame frame) {
this.frase = frase;
this.lf = lf;
this.frame = frame;
}
/** L'interfaccia ActionListener dispone di un solo metodo da implementare
actionPerformed appunto */
public void actionPerformed(ActionEvent evt) {
/* se l'evento è stato generato da un pulsante */
if (evt.getSource() instanceof JButton) {
frase.setLineWrap(true);
/* Genero una frase a caso tra quelle disponibili in RAM */
Frase f = lf.getFraseACaso();
if (f!=null)
frase.setText(f.contenuto+"\n\n-- "+f.autore);
frame.pack();
}
} // fine metodo gestore dell'evento
} // fine classe GestorePulsante
fortune.pdf
Pag. 7/13
Cozzetto ©
Laboratorio di sistemi
Fortune
Java/Jsp
/*
* Main.java
*/
package fortunejavaapp;
import javax.swing.WindowConstants;
/**
* @author maurizio
*/
public class Main {
public static void main(String[] args) {
Fortune f = new Fortune("Versione grafica di 'Fortune'");
} // fine metodo main
} // fine classe Main
Versione Web
Nel caso di una versione web, le cose cambiano leggermente. Intanto il caricamento
delle frasi deve avvenire la prima volta che l'utente si collega alla pagina.
Per il messaggio, usiamo un po' di Javascript e formattiamo la frase usando i fogli di
stile. Il codice delle due classi non cambia. Ipotizziamo inoltre che il file fortune.txt sia
contenuto nel package risorsePkg.
Dal momento che il caricamento delle frasi in memoria deve avvenire una sola volta,
fortune.pdf
Pag. 8/13
Cozzetto ©
Laboratorio di sistemi
Fortune
Java/Jsp
ricorriamo ad una variabile di sessione. Se non ha nessun valore, vuol dire che è la
prima volta che carichiamo la pagina per cui va fatto il caricamento delle frasi in Ram,
altrimenti vuol dire che la fase di caricamento è già stata effettuata per cui il sistema
genera una frase a caso. Per generare altre frasi è sufficiente cliccare sul pulsante
Aggiorna del browser.
Pagina index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page errorPage="gestioneErrori.jsp" %>
<!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>Fortune - Versione web</title>
<style>
body {
font-family: Verdana, "Trebuchet MS";
font-size: 11pt;
}
#box {
width: 400px;
border: 1px blue dashed;
padding: 5px;
margin-left: auto;
margin-right: auto;
}
fortune.pdf
Pag. 9/13
Cozzetto ©
Laboratorio di sistemi
Fortune
Java/Jsp
.centro {
text-align: center;
}
</style>
</head>
<body>
<h3 class="centro">Versione web di Fortune</h3>
<div id="box">
<%
/* è la prima volta che carico la pagina */
if (session.getAttribute("lf")==null) {
/* istanzio l'oggetto lf che rappresenta le frasi */
fortunePkg.ListaFrasi2 lf = new fortunePkg.ListaFrasi2();
/* carico tutte le frasi in memoria */
int numRecord=lf.caricaFrasi(application.getRealPath("/")+"WEBINF/classes/risorsePkg/fortune.txt");
/* ne prendo una a caso */
fortunePkg.Frase f = lf.getFraseACaso();
/* la visualizzo nel browser */
if (f!=null) {
out.println(f.contenuto+"<br/><br/>-- "+f.autore);
}
/* imposto la variabile di sessione lf */
session.setAttribute("lf", lf);
String s = "<script>alert('Sono state caricate "+numRecord+ "
frasi');</script>";
out.println(s);
} else {
/* non è la prima volta che accedo alla pagina */
fortunePkg.ListaFrasi2 lf = (fortunePkg.ListaFrasi2)
session.getAttribute("lf");
/* prendo una frase a caso */
fortunePkg.Frase f = lf.getFraseACaso();
/* la visualizzo nel browser */
if (f!=null) {
out.println(f.contenuto+"<br/><br/>-- "+f.autore);
}
} // fine if
%>
</div>
</body>
</html>
fortune.pdf
Pag. 10/13
Cozzetto ©
Laboratorio di sistemi
Fortune
Java/Jsp
Pagina gestioneErrori.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@page isErrorPage="true" %>
<%@page import="java.io.PrintWriter" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<% PrintWriter writer=new PrintWriter(out); %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Pagina di errore</title>
<style type="text/css">
<!-body,td,th {
font-family: Trebuchet MS;
font-size: 10pt;
}
-->
</style>
</head>
<body>
<h3>Gestione degli errori</h3>
<p>Si è verificato il seguente errore: <%=exception.getMessage()%></p>
</body>
</html>
Nella versione web, abbiamo usato in realtà al posto della solita classe ListaFrasi (che
avremmo potuto ugualmente usare senza alcuna modifica) la classe ListaFrasi2 che
ottimizza lo spazio in RAM allocando lo spazio strettamente necessario (nella classe
facciamo uso degli ArrayList e dei Generics). La logica nel complesso tuttavia non
cambia.
/*
* ListaFrasi2.java
*
*/
package fortunePkg;
import
import
import
import
import
import
import
java.io.BufferedReader;
java.io.FileNotFoundException;
java.io.FileReader;
java.io.IOException;
java.util.ArrayList;
java.util.Random;
java.util.StringTokenizer;
fortune.pdf
Pag. 11/13
Cozzetto ©
Laboratorio di sistemi
Fortune
Java/Jsp
/**
* @author maurizio
*/
public class ListaFrasi2 {
ArrayList<Frase> frasi;
int numFrasi =0;
/** Costruttore senza parametri */
public ListaFrasi2() {
frasi = new ArrayList<Frase>();
}
/** Costruttore con parametro il numero di frasi */
public ListaFrasi2(int n) {
if ( n >= 1 )
frasi = new ArrayList<Frase>(n);
else
frasi = new ArrayList<Frase>();
}
/** Genero una frase casuale tra quelle caricate in memoria */
public Frase getFraseACaso() {
Random generatore = new Random();
int i = generatore.nextInt(numFrasi);
return frasi.get(i); // non è necessario il cast visto che
// usiamo i generics
}
/** Aggiungo una nuova frase */
public void aggiungiFrase(Frase f) {
if ( f != null ) {
frasi.add(f);
numFrasi++;
}
}
/** Prelevo dal disco le frasi e le porto in RAM */
public int caricaFrasi(String file) throws FileNotFoundException, IOException {
int numRecord=0;
try {
// apertura del file in lettura
FileReader fr = new FileReader(file);
BufferedReader bfr = new BufferedReader(fr);
// lettura di tutti i record e caricamento nell'arraylist
String s = bfr.readLine();
while (s != null) {
fortune.pdf
Pag. 12/13
Cozzetto ©
Laboratorio di sistemi
Fortune
Java/Jsp
StringTokenizer st = new StringTokenizer(s,"|");
Frase frase = new Frase();
frase.contenuto = st.nextToken();
frase.autore = st.nextToken();
aggiungiFrase(frase);
numRecord++;
s = bfr.readLine();
} // fine while
// chiusura
bfr.close();
fr.close();
} catch(FileNotFoundException e) {
throw new FileNotFoundException(e.getMessage());
} catch (IOException e) {
throw new IOException(e.getMessage());
}
return numRecord;
} // fine metodo caricaFrasi()
} // fine classe ListaFrasi2
fortune.pdf
Pag. 13/13
Cozzetto ©