Utilizzare Spring nelle web application – parte 12

Dopo esserci presi una “pausa di riflessione” nello scorso articolo, riprendiamo con lo sviluppo dell’applicazione. In questo appuntamento realizzeremo la pagina di dettaglio di un’inserzione.

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:

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;
    }
}

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:

<%@ 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)} €</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>

Questa pagina “chiude il giro”, mostrando i dettagli delle inserzioni il cui ID è passato nella URL.

Linkografia