El codi de la solució d’aquesta activitat el podeu descarregar del següent
.
No obstant això, es recomana desenvolupar el projecte pas a pas, com es detalla a continuació.
Amb NetBeans, copieu el projecte “stmedioc404” amb el nom “ajaxxmljson”. El projecte “stmedioc404” el podeu descarregar al següent
.
CAS A. AMB L’ANOTACIÓ @ResponseBody
Afegint la configuració i les dependències
En aquest cas no calen dependències ni configuracions addicionals. Spring MVC, de manera nativa, permet la construcció de respostes amb XML o amb JSON.
Adaptant el model
El domain object
l’adaptarem per permetre la generació de XML amb diverses anotacions. En aquest cas, no afegirem més configuració a la resposta JSON.
A la capa de domini, a Medicament
, afegiu l’anotació @XmlRootElement
a nivell de la classe.
@XmlRootElement
public class Medicament {
Adaptant el controlador
En aquest cas s’han de diferenciar les peticions XML i JSON de les normals (/medicament), atès que el mètode getMedicamentById
que recull aquestes peticions no les sabrà diferenciar i sempre mostrarà la vista jsp.
Afegiu el mètode getMedicamentByIdRB
al controlador getMedicamentByIdRB
amb el codi i l’anotació que es mostra a continuació.
@RequestMapping(value="/medicament/responsebody")
public @ResponseBody Medicament getMedicamentByIdRB(@RequestParam("codi") String medicamentId, HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
return medicamentService.getMedicamentById(medicamentId);
}
Provant l’aplicació
Si executeu la petició normal, localhost:8080/ajaxxmljson/medicaments/medicament?codi=M020 us ha de mostrar el detall de medicament amb la vista jsp ja coneguda.
En canvi, podeu obtenir les mateixes dades en format JSON amb l’URL localhost:8080/ajaxxmljson/medicaments/medicament/responsebody.json?codi=M020.
I també en XML amb l’URL localhost:8080/ajaxxmljson/medicaments/medicament/responsebody.xml?codi=M020.
Amb l’URL /medicament sense més, agafa el control el mètode ja desenvolupat i, per tant, mostra el detall en jsp. En canvi, amb l’URL /medicament/responsebody.xxx el control el pren el mètode public @ResponseBody Medicament getMedicamentByIdRB
.
En aquest mètode es construeix una llista de domain objects
i, com que no es pot construir una view amb una List, Spring MVC, a partir de @ResponseBody
i l’extensió xxx de l’URL, la converteix en el format adient (XML per defecte o JSON).
CAS B. AMB L’OBJECTE ContentNegotiatingViewResolver
En aquest cas volem aconseguir que, amb l’URL inicial /medicament i afegint l’extensió (cap extensió, .json, .xml), Spring MVC sàpiga retornar la vista en format adient.
Afegint la configuració i les dependències
Al fitxer dependències pom.xml hem d’afegir la dependència que es mostra a continuació, perquè baixarà les llibreries necessàries per generar JSON. Per a XML no calen dependències addicionals.
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.10</version>
</dependency>
A DispatcherServlet-context.xml s’ha de configurar el bean ContentNegotiatingViewResolver
, que ens permetrà compondre i retornar les vistes XML i JSON.
Heu d’afegir el següent bean a DispatcherServlet-context.xml:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
<property name="defaultViews">
<list>
<ref bean="jsonView"/>
<ref bean="xmlView"/>
</list>
</property>
</bean>
Fixeu-vos que fem referència a jsonView
i xmlView
. Per tant, afegiu aquests beans amb les etiquetes que es mostren a continuació.
<bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
<property name="prettyPrint" value="true"/>
</bean>
<bean id="xmlView" class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>cat.xtec.ioc.domain.Medicament</value>
</list>
</property>
</bean>
</constructor-arg>
</bean>
Adaptant el model
Per a XML no necessitem més adaptacions, atès que ja hem afegit l’anotació @XmlRootElement
a la classe Medicament
.
En canvi, simplement a mode d’exemple, ara que tenim la nova dependència podem fer servir alguna de les anotacions que ens proporciona. En aquest cas farem servir l’anotació @JsonIgnore
per no generar la propietat active
quan la resposta és JSON.
A la capa de domini, a Medicament
, afegiu l’anotació @JsonIgnore
a nivell de la propietat active
.
@JsonIgnore
private boolean active;
Adaptant el controlador
Al controlador no s’ha de fer res, ja que davant d’una petició /medicament actuarà el bean ContentNegotiatingViewResolver
, que decidirà quin bean ha de construir la resposta.
Provant l’aplicació
Si executeu la petició normal, localhost:8080/ajaxxmljson/medicaments/medicament?codi=M020 us ha de mostrar el detall de medicament amb la vista jsp ja coneguda.
En canvi, podeu obtenir les mateixes dades en format JSON amb l’URL localhost:8080/ajaxxmljson/medicaments/medicament.json?codi=M020.
I també en XML amb l’URL localhost:8080/ajaxxmljson/medicaments/medicament.xml?codi=M020.
Amb l’URL /medicament sense més, ContentNegotiatingViewResolver
no el considera perquè no està a la seva llista de vistes a gestionar. Per tant, es mostra la resposta en el format per defecte jsp.
En els altres casos entra en joc ContentNegotiatingViewResolver
i retorna la vista adient segons la petició sigui JSON o XML.