Avant d'entrer dans les détails, je sais qu'il y a eu beaucoup de conversations et de questions connexes sur Stackoverflow. Tous m'aident en quelque sorte de différentes manières, j'ai donc pensé regrouper mes résultats en un seul FAQ pour résumer mes résultats).
Vous les connaissez sûrement, mais je les écris comme un bref examen. N'hésitez pas à modifier au cas où je manquerais quelque chose.
Une demande de publication est utilisée lorsque vous souhaitez envoyer un objet à un service Web ou à une application côté serveur.
Processus consistant à transférer l'objet de votre navigateur Web vers votre application côté serveur. Un appel jQuery Ajax ou une demande de publication Curl peut être utilisé.
Les jours les plus populaires ces jours-ci sont JSON et XML. XML est de moins en moins populaire car les objets xml sérialisés sont de taille relativement plus grande en raison de la nature du balisage XML. Dans ce FAQ l'objectif principal est JSON2 la sérialisation.
Le framework Spring et sa puissante annotation permettent d'exposer le service web de manière efficace. Il existe de nombreuses bibliothèques différentes au printemps. Celui qui est notre objectif ici est Spring web MVC .
Ce sont les outils que vous pouvez utiliser pour faire une demande de publication dans votre côté client. Même si vous prévoyez d'utiliser l'appel ajQuery JQuery, je vous suggère d'utiliser Curl à des fins de débogage car il vous fournit une réponse détaillée après avoir effectué la demande de publication.
Dans les cas où vous disposez d'un service Web qui ne dépend pas de votre Java EE, @RequestBody doit être utilisé. Si vous utilisez le modèle et que votre objet JSON est ajouté au modèle, vous peut accéder à l'objet via @ModelAttribute. Uniquement pour les cas où votre demande est soit une demande GET soit une combinaison GET et POST combinaison de demandes, vous devrez utiliser @ RequestParam/@ PathVariable.
Comme vous pouvez le voir sur le nom, c'est aussi simple que cela, vous n'avez besoin de @ResponseBody que si vous envoyez une réponse au client après que la méthode côté serveur a traité la demande.
RequestMappingHandlerAdapter est le nouveau gestionnaire de mappage pour le framework Spring qui a remplacé AnnotationMethodHandlerAdapter depuis Spring 3.1. Si votre configuration existante est toujours dans AnnotationMethodHandlerAdapter, vous pourriez trouver ce message utile. La configuration fournie dans mon article vous donnera une idée de la façon de configurer le RequestMappingHandlerAdapter.
Vous devrez configurer un convertisseur de messages. C'est ainsi que votre corps de message JSON sérialisé est converti en un objet local Java côté serveur).
Configuration de base de ici . Les convertisseurs étaient MarshallingHttpMessageConverter et CastorMarshaller dans l'exemple exemple de configuration de base , je les ai remplacés par MappingJackson2HttpMessageConverter et MappingJacksonHttpMessageConverter.
La façon dont mon projet est mis en place, j'ai deux fichiers de configuration:
le bean hadlerAdapter doit être situé dans la dernière version du fichier XML MVC Dispatcher.
<bean name="handlerAdapter"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
<ref bean="jsonConverter"/>
</list>
</property>
<property name="requireSession" value="false"/>
</bean>
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json"/>
</bean>
Vous pouvez avoir plusieurs convertisseurs de messages. ici, j'ai créé un JSON normal ainsi qu'un convertisseur de message JSON 2. Le format Ref et le bean normal dans le fichier XML ont tous deux été utilisés (personnellement, je préfère la balise ref comme plus nette).
Voici un exemple de contrôleur qui expose l'API REST.
C'est là que votre API REST pour une demande de publication HTTP est exposée.
@Component
@Controller
@RequestMapping("/api/user")
public class UserController {
@RequestMapping(value = "/add", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String insertUser(@RequestBody final User user) {
System.out.println(user.toString());
userService.insertUser(user);
String userAdded = "User-> {" + user.toString() + "} is added";
System.out.println(userAdded);
return userAdded;
}
}
@JsonAutoDetect
public class User {
private int id;
private String username;
private String name;
private String lastName;
private String email;
public int getId() {
return externalId;
}
public void setId(final int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(final String email) {
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(final String username) {
this.username = username;
}
public String getLastName() {
return lastName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return this.getName() + " | " + this.getLastName() + " | " + this.getEmail()
+ " | " + this.getUsername() + " | " + this.getId() + " | ";
}
}
curl -i -H "Content-Type: application/json" -X POST -d '{"id":100,"username":"JohnBlog","name":"John","lastName":"Blog","email":"[email protected]"}' http://localhost:8080/[YOURWEBAPP]/api/user/add
Ceci FAQ n'était pas possible si ce n'était pas pour toutes les personnes qui ont fourni les messages et questions suivants (cette liste se développera si je rencontre des messages/questions utiles)):
curl -i -H "Content-Type: application/json" -X POST -d '{"id":100,"username":"JohnBlog","name":"John","lastName":"Blog","email":"[email protected]"}' http://localhost:8080/[YOURWEBAPP]/api/user/add
Ici, j'explore différentes erreurs que vous pourriez rencontrer après avoir effectué un appel curl et ce qui pourrait avoir mal tourné.
HTTP/1.1 404 Not Found
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 949
Date: Tue, 04 Jun 2013 02:59:35 GMT
Cela implique que l'API REST n'existe pas dans l'URL que vous avez fournie.
Après vous être assuré que tout est parfaitement bien fait et que rien ne va mal avec votre configuration ni votre URL: - Exécutez un maven clean. - Annulez le déploiement de votre application Web ou supprimez-la simplement. - Redéployez l'application web - Assurez-vous d'utiliser une seule version de Spring dans votre maven/gradle
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 968
Date: Tue, 04 Jun 2013 03:08:05 GMT
Connection: close
La seule raison derrière cela est le fait que votre demande n'est pas formatée correctement. Si vous extrayez la réponse détaillée de curl, vous devriez pouvoir voir "La demande envoyée par le client était syntaxiquement incorrecte.".
Soit votre format JSON n'est pas correct, soit il vous manque un paramètre obligatoire pour l'objet Java.
Assurez-vous de fournir l'objet JSON au format correct et avec le bon nombre de paramètres. Les propriétés Nullable ne sont pas obligatoires mais vous devez fournir des données pour toutes les propriétés NotNullable. Il est TRÈS important de se rappeler que Spring utilise Java réflexion pour transformer votre fichier JSON en Java objets, qu'est-ce que cela signifie? Cela signifie que la variable et la méthode les noms sont CasE SensItiVe. Si votre fichier JSON envoie la variable "userName", alors votre variable correspondante dans votre Java objet DOIT également être nommé "userName". Si vous avez des getters et setters, ils doivent également suivre la même règle. getUserName et setUserName pour correspondre à notre exemple précédent.
HTTP/1.1 415 Unsupported Media Type
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 1051
Date: Wed, 24 Aug 2011 08:50:17 GMT
Le type de support Json n'est pas pris en charge par votre service Web. Cela peut être dû au fait que votre annotation ne spécifie pas le type de média ou que vous ne spécifiez pas le type de média dans la commande Curl post.
Vérifiez que votre convertisseur de messages est correctement configuré et assurez-vous que l'annotation du service Web correspond à l'exemple ci-dessus. Si cela était correct, assurez-vous de spécifier le type de contenu dans votre demande de publication Curl.
Le type de support json n'est pas pris en charge par votre service Web.
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 04 Jun 2013 03:06:16 GMT
Félicitations, l'utilisateur est réellement envoyé à votre serveur REST.
Pour plus de détails sur la configuration de votre commande de printemps, consultez le guide Spring MVC.
Ceci FAQ n'était pas possible si ce n'était pas pour toutes les personnes qui ont fourni les messages et questions suivants (cette liste se développera si je rencontre des messages/questions utiles)):
Cela devrait être bon de remarquer qu'une classe de bean peut PAS être gérée si elle a 2 ou plus setter pour un champ sans @JsonIgnore
sur les options. Spring/Jackson throw HttpMediaTypeNotSupportedException
et statut http 415 Type de support non pris en charge.
Exemple:
@JsonGetter
public String getStatus() {
return this.status;
}
@JsonSetter
public void setStatus(String status) {
this.status = status;
}
@JsonIgnore
public void setStatus(StatusEnum status) {
if (status == null) {
throw new NullPointerException();
}
this.status = status.toString();
}
pdate: Nous devons également spécifier @JsonGetter
et @JsonSetter
dans ce cas, ne pas avoir de problèmes lorsqu'il est utilisé comme type de retour.
Je viens de le tester avec Spring 3.2.2 et Jackson 2.2. Cela fonctionne très bien comme paramètre (@RequestBody
) et/ou comme type de retour (@ResponseBody
).
Mise à jour 2:
Si @JsonGetter
et @JsonSetter
sont spécifiés, @JsonIgnore
ne semble pas nécessaire.