C'est un design pattern qui permet de modéliser des applications « interactives » :
Ces trois aspects sont représentés par trois composants :
Une application Web typique :
La séparation permet d'obtenir :
Dans une application JSP typique, le modèle MVC peut être implémenté de la manière suivante :
On se place dans le cadre d'une application permettant d'accéder à une annuaire. Un annuaire est juste une liste de contacts
class Contact {
final private String lastname;
final private String firstname;
final private String phone;
final private String email;
public Contact(String l, String f, String p, String e) {
lastname = l;
firstname = f;
phone = p;
email = e;
}
public String getLastname () { return lastname; }
public String getFirstname () { return firstname; }
public String getPhone () { return Phone; }
public String getEmail () { return email; }
}
Le getter pour une propriété foo est une méthode publique getFoo()
public class ContactDB {
private List<Contacts>contacts;
public ContactDB() {
contacts = new ArrayList<>();
}
public List<Contact> getContactsByLastname (String s) {
ArrayList<Contact> res = new ArrayList<>();
String u = s.toUpperCase();
for (Contact c : this.contacts) {
if (c.getLastname().toUpperCase().contains(u)) {
res.add(c);
}
}
return res;
}
//autres méthodes ici
}
La classe HttpServlet permet d'implémenter le contrôleur. C'est vers cette classe que son compilées les pages JSP, mais dans le contrôleur, on ne va faire aucun affichage. On va calculer un résultat et le stocker pour que la vue puisse l'afficher.
On imagine le code de formulaire suivant dans une page contact.html:
<form method="get" action="FindContactByNameServlet">
Nom : <input type="text" name="s"/></input><br/>
<button type="submit">Rechercher</button>
</form>
//Cette annotation permet de dire que le Servlet sera
//associée à l'URL /APPNAME/FindContactByNameServlet
@WebServlet("/FindContactByNameServlet")
public class FindContactByNameServlet extends HttpServlet {
//Tomcat se sert de l'ID Pour savoir qu'un servlet a été
//modifié et donc que la version en cache doit être invalidée
private static final long serialVersionUID = 1234L;
//La méthode appelée si la requête est POST
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(request, response);
}
//La méthode appelée si la requête est GET
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
…
}
}
Dans notre exemple on dit que si on est appelé en POST alors on fait la même chose qu'en GET.
try {
//On crée un Modèle et on le stocke dans la session
ContactDB db = (ContactDB) getServletContext().getAttribute("db");
if (db == null) {
db = new ContactDB();
getServletContext().setAttribute("db", db);
}
//Récupération du paramètre GET comme dans un JSP
String s = request.getParameter("s");
ArrayList<Person> v = db.getContactsByLastname(s);
request.setAttribute("contacts", v);
RequestDispatcher rd =
request.getRequestDispatcher("WEB-INF/jsp/contact_list.jsp");
rd.forward(request,response);
} catch (Exception e) { throw new ServletException(e); }
request.getRequestDispatcher("S2").forward (request,response)
request.getRequestDispatcher("S3").forward (request,response)
request.getRequestDispatcher("view.jsp").forward (request,response)
On peut ainsi enchaîner les servlets. Les Si peuvent travailler sur l'objet request ainsi que sur les headers de la réponse via l'objet response (.addCookie, addHeader, …).
Les Si ne doivent pas écrire le contenu de la réponse (i.e. pas de .getWriter() dans les servlets), sinon Si+1 renverra une erreur.
Dans un premier temps, la vue est uniquement un fichier jsp. Elle va récupérer dans l'objet request les attributs déposés par le contrôleur pour les afficher.
Dans le fichier WEB-INF/jsp/contact_list.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.List,mypackage.Contact" %>
Liste de contacts
]]><%
for(Concact c : (List<Conctact>)request.getAttribute("conctacts")){
out.println(String.format("<li>%s <b>%s</b>(%s, %s)</li>"),
c.getFirstname(),
c.getLastname(),
c.getEmail(),
c.getPhone())
}
%>
]]>
On ne présente ici qu'une petite partie de JSP. Les problèmes restant :