
Servizi esistenti
Negli articoli precedenti abbiamo già implementato le funzionalità necessarie a questo use case, sia nella classe InsertionService, utilizzata dai controller di Spring MVC, che in InsertionDao. In entrambi i casi il metodo realizzato è getInsertion(long id), che recupera un oggetto Insertion tramite l’ID progessivo (chiave primaria della tabella insertions). Non ci resta quindi che realizzare il controller e la pagina JSP che visualizza l’inserzione.
Realizzare il controller
Creiamo la classe InsertionDetailController nel package it.artera.springtut.controller:
[java]package it.artera.springtut.controller;
import it.artera.springtut.model.Insertion;
import it.artera.springtut.service.InsertionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/detail")
public class InsertionDetailController {
private InsertionService insertionService;
@Autowired
public void setInsertionService(InsertionService insertionService) {
this.insertionService = insertionService;
}
@RequestMapping(value = "/{id}.*", method = RequestMethod.GET)
public ModelAndView get(@PathVariable long id) {
ModelAndView mav = new ModelAndView("detail");
Insertion i = insertionService.getInsertion(id);
mav.addObject("insertion", i);
return mav;
}
}[/java]
Come potete notare abbiamo fatto un ampio uso di annotazioni:
- @Controller indica a Spring che questa classe risponderà a richieste HTTP;
- @RequestMapping utilizzata per configurare la reazione del controller alle richieste HTTTP;
- @Autowired provvede ad assegnare alla variabile insertionService un’istanza di it.artera.springtut.service.InsertionService già pronta per l’utilizzo.
L’annotazione @RequestMapping è uno strumento davvero molto potente e flessibile. A livello di classe è utilizzata per indicare il path principale a cui risponderà il controller, mentre a livello di metodo può essere arricchita da riferimenti a parametri nella URL, utilizando i cosiddetti URI templates (cfr. paragrafo 15.3.2.1 della Spring Reference). Il funzionamento in realtà è piuttosto intuitivo:
- l’indicazione method = RequestMethod.GET indica a quale verbo HTTP (GET, PUT, POST o DELETE) risponde il metodo get();
- il path utilizzato “/{id}.*” indica che nella url verrà specificato l’ID dell’inserzione, più un’estensione (ad esempio .html, .xml o altro);
- l’annotazione @PathVariable long id rende disponibile come parametro della funzione il valore intercettato dall’URI template.
Questo stile di configurazione delle applicazioni è denominato Representational State Transfer (REST), ed è lo stile adottato da Spring MVC dalla versione 2.5 in su (in questo tutorial utilizziamo la versione 3.0.x); il suo pregio principale è saper fornire ai client un modo molto semplice per accedere ai dati della nostra applicazione, in maniera stateless e utilizzando semplici URL. Ad esempio alla stessa URL
http://www.example.com/detail/1.html
possono essere associate diverse operazioni, a seconda del verbo HTTP utilizzato:
- GET: il client legge l’inserzione con ID = 1;
- POST: il client invia i dati da salvare per l’inserzione;
- DELETE: il client richiede la cancellazione dell’inserzione.
Infine, facciamo notare come l’istruzione:
mav = new ModelAndView("detail")
richieda a Spring di andare sulla view denominata “detail”, una volta terminata l’esecuzione del controller. La configurazione delle view di tipo JSP è definita nel bean con id=”viewResolver” nel file dispatcher-servlet.xml. Nel nostro caso la view con nome “detail” ci farà “atterrare” sulla pagina src/main/webapp/WEB-INF/pages/detail.jsp.
Pagina JSP
Nella detail.jsp dobbiamo inserire questo codice:
[html]<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ include file="common/taglibs.jsp"%>
<html>
<head>
<title>Dettaglio inserzione: ${fn:escapeXml(insertion.title)}</title>
</head>
<body>
<dl>
<dd>Titolo</dd>
<dt>${fn:escapeXml(insertion.title)}</dt>
<dd>Prezzo</dd>
<dt>${fn:escapeXml(insertion.price)} &euro;</dt>
<dd>Data di inserimento</dd>
<dt>
<fmt:formatDate value="${insertion.creationDate}" />
</dt>
<dt>Foto</dt>
<dd>
<c:choose>
<c:when test="${empty(insertion.photo)}">-</c:when>
<c:otherwise><img src="photos/${insertion.photo}" /></c:otherwise>
</c:choose>
</dd>
<dt>Descrizione</dt>
<dd>${fn:escapeXml(insertion.description)}</dd>
</dl>
</body>
</html>[/html]
Questa pagina “chiude il giro”, mostrando i dettagli delle inserzioni il cui ID è passato nella URL.





