Services Web RESTful - Guide rapide

Qu'est-ce que l'architecture REST?

REST signifie REpresentational State Transfer. REST est une architecture basée sur des standards Web et utilise le protocole HTTP. Il tourne autour de la ressource où chaque composant est une ressource et une ressource est accessible par une interface commune à l'aide de méthodes standard HTTP. REST a été introduit pour la première fois par Roy Fielding en 2000.

Dans l'architecture REST, un serveur REST fournit simplement un accès aux ressources et le client REST accède et modifie les ressources. Ici, chaque ressource est identifiée par des URI / ID globaux. REST utilise diverses représentations pour représenter une ressource comme le texte, JSON, XML. JSON est le plus populaire.

Méthodes HTTP

Les quatre méthodes HTTP suivantes sont couramment utilisées dans l'architecture basée sur REST.

  • GET - Fournit un accès en lecture seule à une ressource.

  • POST - Utilisé pour créer une nouvelle ressource.

  • DELETE - Utilisé pour supprimer une ressource.

  • PUT - Utilisé pour mettre à jour une ressource existante ou créer une nouvelle ressource.

Introduction aux services Web RESTFul

Un service Web est un ensemble de protocoles et de normes ouverts utilisés pour l'échange de données entre des applications ou des systèmes. Les applications logicielles écrites dans divers langages de programmation et s'exécutant sur diverses plates-formes peuvent utiliser des services Web pour échanger des données sur des réseaux informatiques comme Internet d'une manière similaire à la communication inter-processus sur un seul ordinateur. Cette interopérabilité (par exemple, entre Java et Python, ou entre les applications Windows et Linux) est due à l'utilisation de standards ouverts.

Les services Web basés sur l'architecture REST sont appelés services Web RESTful. Ces webservices utilisent des méthodes HTTP pour implémenter le concept d'architecture REST. Un service Web RESTful définit généralement un URI, Uniform Resource Identifier un service, fournit une représentation des ressources telle que JSON et un ensemble de méthodes HTTP.

Création du Webservice RESTFul

Dans les prochains chapitres, nous allons créer un service Web dit gestion des utilisateurs avec les fonctionnalités suivantes -

N ° Sr. URI Méthode HTTP Corps POST Résultat
1 / UserService / utilisateurs AVOIR vide Afficher la liste de tous les utilisateurs.
2 / UserService / addUser PUBLIER Chaîne JSON Ajoutez les détails du nouvel utilisateur.
3 / UserService / getUser /: id AVOIR vide Afficher les détails d'un utilisateur.

Ce tutoriel vous guidera sur la façon de préparer un environnement de développement pour commencer votre travail avec Jersey Frameworkpour créer des services Web RESTful. Outils de cadre JerseyJAX-RS 2.0API, qui est une spécification standard pour créer des services Web RESTful. Ce tutoriel vous apprendra également comment configurerJDK, Tomcat et Eclipse sur votre ordinateur avant la configuration de Jersey Framework.

Configurer le kit de développement Java (JDK)

Vous pouvez télécharger la dernière version du SDK à partir du site Java d'Oracle - Téléchargements Java SE . Vous trouverez les instructions d'installation de JDK dans les fichiers téléchargés. Suivez les instructions données pour installer et configurer la configuration. Enfin, définissez lePATH et JAVA_HOME variables d'environnement pour faire référence au répertoire qui contient Java et Javac, généralement rép_install_java / bin et rép_install_java respectivement.

Si vous exécutez Windows et avez installé le JDK dans C: \ jdk1.7.0_75, vous devrez mettre la ligne suivante dans votre fichier C: \ autoexec.bat.

set PATH = C:\jdk1.7.0_75\bin;%PATH% 
set JAVA_HOME = C:\jdk1.7.0_75

Alternativement, sous Windows NT / 2000 / XP, vous pouvez également cliquer avec le bouton droit sur Poste de travail → sélectionner Propriétés → puis Avancé → puis Variables d'environnement. Ensuite, vous mettriez à jour la valeur PATH et appuyez sur le bouton OK.

Sous Unix (Solaris, Linux, etc.), si le SDK est installé dans /usr/local/jdk1.7.0_75 et que vous utilisez le shell C, vous mettriez ce qui suit dans votre fichier .cshrc.

setenv PATH /usr/local/jdk1.7.0_75/bin:$PATH 
setenv JAVA_HOME /usr/local/jdk1.7.0_75

Sinon, si vous utilisez un environnement de développement intégré (IDE) tel que Borland JBuilder, Eclipse, IntelliJ IDEA ou Sun ONE Studio, compilez et exécutez un programme simple pour confirmer que l'EDI sait où vous avez installé Java, sinon effectuez la configuration appropriée comme document de l'IDE.

Configurer l'IDE Eclipse

Tous les exemples de ce didacticiel ont été écrits à l'aide de l'IDE Eclipse. Donc, je suggère que vous devriez avoir la dernière version d'Eclipse installée sur votre machine.

Pour installer Eclipse IDE, téléchargez les derniers binaires Eclipse à partir de https://www.eclipse.org/downloads/. Une fois que vous avez téléchargé l'installation, décompressez la distribution binaire dans un emplacement pratique. Par exemple, dans C: \ eclipse sous Windows, ou / usr / local / eclipse sous Linux / Unix et définissez enfin la variable PATH de manière appropriée.

Eclipse peut être démarré en exécutant les commandes suivantes sur une machine Windows, ou vous pouvez simplement double-cliquer sur eclipse.exe.

%C:\eclipse\eclipse.exe

Eclipse peut être démarré en exécutant les commandes suivantes sur une machine Unix (Solaris, Linux, etc.) -

$/usr/local/eclipse/eclipse

Après un démarrage réussi, si tout va bien, votre écran devrait afficher le résultat suivant -

Configurer les bibliothèques Jersey Framework

Maintenant, si tout va bien, vous pouvez procéder à la configuration du framework Jersey. Voici quelques étapes simples pour télécharger et installer le framework sur votre machine.

  • Choisissez si vous souhaitez installer Jersey sous Windows ou Unix, puis passez à l'étape suivante pour télécharger le fichier .zip pour Windows, puis le fichier .tz pour Unix.

  • Téléchargez la dernière version des binaires du framework Jersey à partir du lien suivant - https://jersey.java.net/download.html.

  • Au moment de la rédaction de ce tutoriel, j'ai téléchargé jaxrs-ri-2.17.zip sur ma machine Windows et lorsque vous décompressez le fichier téléchargé, il vous donnera la structure de répertoire dans E: \ jaxrs-ri-2.17 \ jaxrs-ri comme indiqué dans la capture d'écran suivante.

Vous trouverez toutes les bibliothèques Jersey dans les répertoires C:\jaxrs-ri-2.17\jaxrs-ri\lib et dépendances dans C:\jaxrs-ri-2.17\jaxrs-ri\ext. Assurez-vous de définir correctement votre variable CLASSPATH sur ce répertoire, sinon vous rencontrerez des problèmes lors de l'exécution de votre application. Si vous utilisez Eclipse, il n'est pas nécessaire de définir le CLASSPATH car tous les paramètres seront effectués via Eclipse.

Configurer Apache Tomcat

Vous pouvez télécharger la dernière version de Tomcat sur https://tomcat.apache.org/. Une fois que vous avez téléchargé l'installation, décompressez la distribution binaire dans un emplacement pratique. Par exemple dans C: \ apache-tomcat-7.0.59 sous Windows, ou /usr/local/apache-tomcat-7.0.59 sous Linux / Unix et définissez la variable d'environnement CATALINA_HOME pointant vers les emplacements d'installation.

Tomcat peut être démarré en exécutant les commandes suivantes sur une machine Windows, ou vous pouvez simplement double-cliquer sur startup.bat.

%CATALINA_HOME%\bin\startup.bat

ou

C:\apache-tomcat-7.0.59\bin\startup.bat

Tomcat peut être démarré en exécutant les commandes suivantes sur une machine Unix (Solaris, Linux, etc.) -

$CATALINA_HOME/bin/startup.sh

ou

/usr/local/apache-tomcat-7.0.59/bin/startup.sh

Après un démarrage réussi, les applications Web par défaut incluses avec Tomcat seront disponibles en visitant http://localhost:8080/. Si tout va bien, il devrait afficher le résultat suivant -

Vous trouverez de plus amples informations sur la configuration et l'exécution de Tomcat dans la documentation incluse sur cette page. Ces informations sont également disponibles sur le site Web de Tomcat -https://tomcat.apache.org.

Tomcat peut être arrêté en exécutant les commandes suivantes sur une machine Windows -

%CATALINA_HOME%\bin\shutdown

ou

C:\apache-tomcat-7.0.59\bin\shutdown

Tomcat peut être arrêté en exécutant les commandes suivantes sur une machine Unix (Solaris, Linux, etc.) -

$CATALINA_HOME/bin/shutdown.sh

ou

/usr/local/apache-tomcat-7.0.59/bin/shutdown.sh

Une fois que vous avez terminé cette dernière étape, vous êtes prêt à poursuivre votre premier exemple de Jersey que vous verrez dans le chapitre suivant.

Commençons par écrire les services Web RESTful réels avec Jersey Framework. Avant de commencer à écrire votre premier exemple à l'aide de Jersey Framework, vous devez vous assurer que vous avez correctement configuré votre environnement Jersey, comme expliqué dans le chapitre Services Web RESTful - Configuration de l'environnement . Ici, je suppose également que vous avez une petite connaissance pratique d'Eclipse IDE.

Alors, passons à écrire une application Jersey simple qui exposera une méthode de service Web pour afficher la liste des utilisateurs.

Créer un projet Java

La première étape consiste à créer un projet Web dynamique à l'aide de l'EDI Eclipse. Suivez l'optionFile → New → Project et enfin sélectionnez le Dynamic Web Projectassistant dans la liste des assistants. Maintenant, nommez votre projet commeUserManagement en utilisant la fenêtre de l'assistant comme indiqué dans la capture d'écran suivante -

Une fois votre projet créé avec succès, vous aurez le contenu suivant dans votre Project Explorer -

Ajout des bibliothèques requises

Dans un deuxième temps, ajoutons Jersey Framework et ses dépendances (bibliothèques) dans notre projet. Copiez tous les fichiers JAR des répertoires suivants du dossier zip de téléchargement du jersey dans le répertoire WEB-INF / lib du projet.

  • \jaxrs-ri-2.17\jaxrs-ri\api
  • \jaxrs-ri-2.17\jaxrs-ri\ext
  • \jaxrs-ri-2.17\jaxrs-ri\lib

Maintenant, faites un clic droit sur le nom de votre projet UserManagement puis suivez l'option disponible dans le menu contextuel - Build Path → Configure Build Path pour afficher la fenêtre Java Build Path.

Maintenant, utilisez Add JARs bouton disponible sous Libraries tab pour ajouter les JAR présents dans le répertoire WEBINF / lib.

Création des fichiers source

Maintenant, créons les fichiers source réels sous le UserManagementprojet. Nous devons d'abord créer un package appelécom.tutorialspoint. Pour ce faire, faites un clic droit sur src dans la section de l'explorateur de paquets et suivez l'option -New → Package.

Ensuite, nous allons créer UserService.java, User.java,UserDao.java fichiers sous le package com.tutorialspoint.

User.java

package com.tutorialspoint;  

import java.io.Serializable;  
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 
@XmlRootElement(name = "user") 

public class User implements Serializable {  
   private static final long serialVersionUID = 1L; 
   private int id; 
   private String name; 
   private String profession;  
   public User(){} 
    
   public User(int id, String name, String profession){  
      this.id = id; 
      this.name = name; 
      this.profession = profession; 
   }  
   public int getId() { 
      return id; 
   }  
   @XmlElement 
   public void setId(int id) { 
      this.id = id; 
   } 
   public String getName() { 
      return name; 
   } 
   @XmlElement
   public void setName(String name) { 
      this.name = name; 
   } 
   public String getProfession() { 
      return profession; 
   } 
   @XmlElement 
   public void setProfession(String profession) { 
      this.profession = profession; 
   }   
}

UserDao.java

package com.tutorialspoint;  

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException;  
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.util.ArrayList; 
import java.util.List;  

public class UserDao { 
   public List<User> getAllUsers(){ 
      
      List<User> userList = null; 
      try { 
         File file = new File("Users.dat"); 
         if (!file.exists()) { 
            User user = new User(1, "Mahesh", "Teacher"); 
            userList = new ArrayList<User>(); 
            userList.add(user); 
            saveUserList(userList); 
         } 
         else{ 
            FileInputStream fis = new FileInputStream(file); 
            ObjectInputStream ois = new ObjectInputStream(fis); 
            userList = (List<User>) ois.readObject(); 
            ois.close(); 
         } 
      } catch (IOException e) { 
         e.printStackTrace(); 
      } catch (ClassNotFoundException e) { 
         e.printStackTrace(); 
      }   
      return userList; 
   } 
   private void saveUserList(List<User> userList){ 
      try { 
         File file = new File("Users.dat"); 
         FileOutputStream fos;  
         fos = new FileOutputStream(file); 
         ObjectOutputStream oos = new ObjectOutputStream(fos); 
         oos.writeObject(userList); 
         oos.close(); 
      } catch (FileNotFoundException e) { 
         e.printStackTrace(); 
      } catch (IOException e) { 
         e.printStackTrace(); 
      } 
   }    
}

UserService.java

package com.tutorialspoint;  

import java.util.List; 
import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.MediaType;  
@Path("/UserService") 

public class UserService {  
   UserDao userDao = new UserDao();  
   @GET 
   @Path("/users") 
   @Produces(MediaType.APPLICATION_XML) 
   public List<User> getUsers(){ 
      return userDao.getAllUsers(); 
   }  
}

Il y a deux points importants à noter concernant le programme principal,

UserService.java

  • La première étape consiste à spécifier un chemin pour le service Web à l'aide de l'annotation @Path vers le UserService.

  • La deuxième étape consiste à spécifier un chemin pour la méthode de service Web particulière à l'aide de l'annotation @Path vers la méthode UserService.

Création du fichier de configuration Web.xml

Vous devez créer un fichier de configuration Web xml qui est un fichier XML et est utilisé pour spécifier le servlet du framework Jersey pour notre application.

web.xml

<?xml version = "1.0" encoding = "UTF-8"?> 
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"  
   xmlns = "http://java.sun.com/xml/ns/javaee"  
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
   id = "WebApp_ID" version = "3.0"> 
   <display-name>User Management</display-name> 
   <servlet> 
      <servlet-name>Jersey RESTful Application</servlet-name> 
      <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> 
      <init-param> 
         <param-name>jersey.config.server.provider.packages</param-name> 
         <param-value>com.tutorialspoint</param-value> 
      </init-param> 
   </servlet> 
   <servlet-mapping> 
      <servlet-name>Jersey RESTful Application</servlet-name> 
      <url-pattern>/rest/*</url-pattern> 
   </servlet-mapping>   
</web-app>

Déployer le programme

Une fois que vous avez terminé la création des fichiers de configuration source et Web, vous êtes prêt pour cette étape qui consiste à compiler et à exécuter votre programme. Pour ce faire, à l'aide d'Eclipse, exportez votre application en tant que fichier war et déployez la même chose dans tomcat.

Pour créer un fichier WAR en utilisant eclipse, suivez l'option File → export → Web → War Fileet enfin sélectionnez le projet UserManagement et le dossier de destination. Pour déployer un fichier war dans Tomcat, placez UserManagement.war dans leTomcat Installation Directory → webapps directory et démarrez le Tomcat.

Exécution du programme

Nous utilisons Postman , une extension Chrome, pour tester nos services Web.

Faites une demande à UserManagement pour obtenir la liste de tous les utilisateurs. Placez http: // localhost: 8080 / UserManagement / rest / UserService / users dans POSTMAN avec la requête GET et voyez le résultat suivant.

Félicitations, vous avez créé votre première application RESTful avec succès.

Qu'est-ce qu'une ressource?

L'architecture REST traite chaque contenu comme une ressource. Ces ressources peuvent être des fichiers texte, des pages Html, des images, des vidéos ou des données d'entreprise dynamiques. Le serveur REST fournit simplement l'accès aux ressources et le client REST accède et modifie les ressources. Ici, chaque ressource est identifiée par des URI / ID globaux. REST utilise diverses représentations pour représenter une ressource où Text, JSON, XML. Les représentations les plus populaires des ressources sont XML et JSON.

Représentation des ressources

Une ressource dans REST est un objet similaire dans la programmation orientée objet ou ressemble à une entité dans une base de données. Une fois qu'une ressource est identifiée, sa représentation doit être décidée en utilisant un format standard afin que le serveur puisse envoyer la ressource dans le format ci-dessus et que le client puisse comprendre le même format.

Par exemple, dans RESTful Web Services - First Application Chapter, un utilisateur est une ressource représentée au format XML suivant -

<user> 
   <id>1</id> 
   <name>Mahesh</name>
   <profession>Teacher</profession> 
</user>

La même ressource peut être représentée au format JSON comme suit -

{ 
   "id":1, 
   "name":"Mahesh", 
   "profession":"Teacher" 
}

Bonne représentation des ressources

REST n'impose aucune restriction sur le format d'une représentation de ressource. Un client peut demander une représentation JSON tandis qu'un autre client peut demander une représentation XML de la même ressource au serveur et ainsi de suite. Il est de la responsabilité du serveur REST de transmettre au client la ressource dans le format que le client comprend.

Voici quelques points importants à prendre en compte lors de la conception d'un format de représentation d'une ressource dans RESTful Web Services.

  • Understandability - Le serveur et le client doivent être capables de comprendre et d'utiliser le format de représentation de la ressource.

  • Completeness- Le format doit pouvoir représenter une ressource complètement. Par exemple, une ressource peut contenir une autre ressource. Le format doit pouvoir représenter des structures de ressources aussi bien simples que complexes.

  • Linkablity - Une ressource peut avoir un lien avec une autre ressource, un format doit être capable de gérer de telles situations.

Cependant, à l'heure actuelle, la plupart des services Web représentent des ressources au format XML ou JSON. De nombreuses bibliothèques et outils sont disponibles pour comprendre, analyser et modifier les données XML et JSON.

Les services Web RESTful utilisent les protocoles HTTP comme moyen de communication entre le client et le serveur. Un client envoie un message sous la forme d'une requête HTTP et le serveur répond sous la forme d'une réponse HTTP. Cette technique est appelée Messagerie. Ces messages contiennent des données de message et des métadonnées, c'est-à-dire des informations sur le message lui-même. Jetons un coup d'œil aux messages de requête HTTP et de réponse HTTP pour HTTP 1.1.

Requête HTTP

Une requête HTTP comprend cinq parties principales -

  • Verb - Indique les méthodes HTTP telles que GET, POST, DELETE, PUT, etc.

  • URI - Uniform Resource Identifier (URI) pour identifier la ressource sur le serveur.

  • HTTP Version- Indique la version HTTP. Par exemple, HTTP v1.1.

  • Request Header- Contient des métadonnées pour le message HTTP Request sous forme de paires clé-valeur. Par exemple, type de client (ou navigateur), format pris en charge par le client, format du corps du message, paramètres de cache, etc.

  • Request Body - Contenu du message ou représentation des ressources.

Réponse HTTP

Une réponse HTTP comprend quatre parties principales -

  • Status/Response Code- Indique l'état du serveur pour la ressource demandée. Par exemple, 404 signifie que la ressource est introuvable et 200 signifie que la réponse est correcte.

  • HTTP Version- Indique la version HTTP. Par exemple HTTP v1.1.

  • Response Header- Contient des métadonnées pour le message de réponse HTTP sous forme de paires de valeurs clés. Par exemple, la longueur du contenu, le type de contenu, la date de réponse, le type de serveur, etc.

  • Response Body - Contenu du message de réponse ou représentation des ressources.

Exemple

Comme nous l'avons expliqué dans le chapitre Services Web RESTful - Première application , mettons http: // localhost: 8080 / UserManagement / rest / UserService / users dans le POSTMAN avec une requête GET. Si vous cliquez sur le bouton Aperçu qui se trouve près du bouton d'envoi de Postman, puis sur le bouton Envoyer, vous pouvez voir la sortie suivante.

Ici, vous pouvez voir que le navigateur a envoyé une requête GET et a reçu un corps de réponse au format XML.

L'adressage fait référence à la localisation d'une ressource ou de plusieurs ressources se trouvant sur le serveur. Il est analogue de localiser l'adresse postale d'une personne.

Chaque ressource dans l'architecture REST est identifiée par son URI (Uniform Resource Identifier). Un URI est du format suivant -

<protocol>://<service-name>/<ResourceType>/<ResourceID>

Le but d'un URI est de localiser une ou plusieurs ressources sur le serveur hébergeant le service Web. Un autre attribut important d'une demande est VERB qui identifie l'opération à effectuer sur la ressource. Par exemple, dans le chapitre Services Web RESTful - Première application , l'URI esthttp://localhost:8080/UserManagement/rest/UserService/users et le VERBE est GET.

Construire un URI standard

Les points suivants sont importants à prendre en compte lors de la conception d'un URI -

  • Use Plural Noun- Utilisez un nom pluriel pour définir les ressources. Par exemple, nous avons utilisé des utilisateurs pour identifier les utilisateurs en tant que ressource.

  • Avoid using spaces- Utilisez un trait de soulignement (_) ou un trait d'union (-) lorsque vous utilisez un nom de ressource long. Par exemple, utilisez allowed_users au lieu de% 20users autorisés.

  • Use lowercase letters - Bien que l'URI ne soit pas sensible à la casse, il est recommandé de conserver l'URL uniquement en minuscules.

  • Maintain Backward Compatibility- Le service Web étant un service public, un URI une fois rendu public devrait toujours être disponible. Au cas où l'URI serait mis à jour, redirigez l'ancien URI vers un nouvel URI en utilisant le code d'état HTTP, 300.

  • Use HTTP Verb- Utilisez toujours le verbe HTTP comme GET, PUT et DELETE pour effectuer les opérations sur la ressource. Il n'est pas bon d'utiliser le nom d'opérations dans l'URI.

Exemple

Voici un exemple d'URI médiocre pour récupérer un utilisateur.

http://localhost:8080/UserManagement/rest/UserService/getUser/1

Voici un exemple d'un bon URI pour récupérer un utilisateur.

http://localhost:8080/UserManagement/rest/UserService/users/1

Comme nous l'avons vu dans les chapitres précédents, le service Web RESTful utilise de nombreux verbes HTTP pour déterminer l'opération à effectuer sur la ou les ressources spécifiées. Le tableau suivant présente les exemples des verbes HTTP les plus couramment utilisés.

N ° Sr. Méthode HTTP, URI et opération

1

GET

http: // localhost: 8080 / UserManagement / rest / UserService / users

Obtient la liste des utilisateurs.

(Lecture seulement)

2

GET

http: // localhost: 8080 / UserManagement / rest / UserService / users / 1

Obtient l'utilisateur de l'ID 1

(Lecture seulement)

3

PUT

http: // localhost: 8080 / UserManagement / rest / UserService / users / 2

Insère l'utilisateur avec l'ID 2

(Idempotent)

4

POST

http: // localhost: 8080 / UserManagement / rest / UserService / users / 2

Met à jour l'utilisateur avec l'ID 2

(N / A)

5

DELETE

http: // localhost: 8080 / UserManagement / rest / UserService / users / 1

Supprime l'utilisateur avec l'ID 1

(Idempotent)

6

OPTIONS

http: // localhost: 8080 / UserManagement / rest / UserService / users

Répertorie les opérations prises en charge dans un service Web.

(Lecture seulement)

sept

HEAD

http: // localhost: 8080 / UserManagement / rest / UserService / users

Renvoie l'en-tête HTTP uniquement, pas de corps.

(Lecture seulement)

Les points suivants doivent être pris en compte.

  • Les opérations GET sont en lecture seule et sont sûres.

  • Les opérations PUT et DELETE sont idempotentes, ce qui signifie que leur résultat sera toujours le même, quel que soit le nombre de fois que ces opérations sont appelées.

  • Les opérations PUT et POST sont presque les mêmes, la différence se situant uniquement dans le résultat où l'opération PUT est idempotente et l'opération POST peut entraîner un résultat différent.

Exemple

Mettons à jour un exemple créé dans le chapitre Services Web RESTful - Première application pour créer un service Web qui peut effectuer des opérations CRUD (Créer, Lire, Mettre à jour, Supprimer). Pour plus de simplicité, nous avons utilisé une E / S de fichier pour remplacer les opérations de base de données.

Laissez-nous mettre à jour le User.java, UserDao.java et UserService.java fichiers sous le package com.tutorialspoint.

User.java

package com.tutorialspoint; 

import java.io.Serializable;  
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 
@XmlRootElement(name = "user") 

public class User implements Serializable {  
   private static final long serialVersionUID = 1L; 
   private int id; 
   private String name; 
   private String profession;  
   public User(){}  
   
   public User(int id, String name, String profession){ 
      this.id = id; 
      this.name = name; 
      this.profession = profession; 
   }  
    
   public int getId() {
      return id; 
   } 
   @XmlElement 
   public void setId(int id) { 
      this.id = id; 
   } 
   public String getName() { 
      return name; 
   } 
   @XmlElement 
      public void setName(String name) { 
      this.name = name; 
   } 
   public String getProfession() { 
      return profession; 
   } 
   @XmlElement 
   public void setProfession(String profession) { 
      this.profession = profession; 
   }   
   @Override 
   public boolean equals(Object object){ 
      if(object == null){ 
         return false; 
      }else if(!(object instanceof User)){ 
         return false; 
      }else { 
         User user = (User)object; 
         if(id == user.getId() 
            && name.equals(user.getName()) 
            && profession.equals(user.getProfession())){ 
               return true; 
         }
      } 
      return false; 
   }  
}

UserDao.java

package com.tutorialspoint;  

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.util.ArrayList; 
import java.util.List;  

public class UserDao { 
   public List<User> getAllUsers(){ 
      List<User> userList = null; 
      try { 
         File file = new File("Users.dat"); 
         if (!file.exists()) { 
            User user = new User(1, "Mahesh", "Teacher"); 
            userList = new ArrayList<User>(); 
            userList.add(user); 
            saveUserList(userList);   
         } 
         else{ 
            FileInputStream fis = new FileInputStream(file); 
            ObjectInputStream ois = new ObjectInputStream(fis); 
            userList = (List<User>) ois.readObject(); 
            ois.close(); 
         }
      } catch (IOException e) { 
         e.printStackTrace(); 
      } catch (ClassNotFoundException e) { 
         e.printStackTrace(); 
      }   
      return userList; 
   }  
   public User getUser(int id){ 
      List<User> users = getAllUsers();  
      for(User user: users){ 
         if(user.getId() == id){ 
            return user; 
         } 
      } 
      return null; 
   }  
   public int addUser(User pUser){ 
      List<User> userList = getAllUsers(); 
      boolean userExists = false; 
      for(User user: userList){ 
         if(user.getId() == pUser.getId()){ 
            userExists = true; 
            break; 
         } 
      }   
      if(!userExists){ 
         userList.add(pUser); 
         saveUserList(userList); 
         return 1; 
      } 
      return 0; 
   }
   public int updateUser(User pUser){ 
      List<User> userList = getAllUsers();  
      for(User user: userList){ 
         if(user.getId() == pUser.getId()){ 
            int index = userList.indexOf(user);    
            userList.set(index, pUser); 
            saveUserList(userList); 
            return 1; 
         } 
      }   
      return 0; 
   }  
   public int deleteUser(int id){ 
      List<User> userList = getAllUsers();  
      for(User user: userList){ 
         if(user.getId() == id){ 
            int index = userList.indexOf(user);    
            userList.remove(index); 
            saveUserList(userList); 
            return 1;    
         } 
      }   
      return 0; 
   }  
   private void saveUserList(List<User> userList){ 
      try { 
         File file = new File("Users.dat"); 
         FileOutputStream fos;  
         fos = new FileOutputStream(file);
         ObjectOutputStream oos = new ObjectOutputStream(fos);   
         oos.writeObject(userList); 
         oos.close(); 
      } catch (FileNotFoundException e) { 
         e.printStackTrace(); 
      } catch (IOException e) { 
         e.printStackTrace(); 
      } 
   } 
}

UserService.java

package com.tutorialspoint;  

import java.io.IOException; 
import java.util.List;  
import javax.servlet.http.HttpServletResponse; 
import javax.ws.rs.Consumes; 
import javax.ws.rs.DELETE; 
import javax.ws.rs.FormParam; 
import javax.ws.rs.GET; 
import javax.ws.rs.OPTIONS; 
import javax.ws.rs.POST; 
import javax.ws.rs.PUT; 
import javax.ws.rs.Path; 
import javax.ws.rs.PathParam; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.Context; 
import javax.ws.rs.core.MediaType;  
@Path("/UserService") 

public class UserService { 
  
   UserDao userDao = new UserDao(); 
   private static final String SUCCESS_RESULT = "<result>success</result>"; 
   private static final String FAILURE_RESULT = "<result>failure</result>";  
   @GET 
   @Path("/users") 
   @Produces(MediaType.APPLICATION_XML) 
   public List<User> getUsers(){ 
      return userDao.getAllUsers(); 
   }  
   @GET 
   @Path("/users/{userid}") 
   @Produces(MediaType.APPLICATION_XML) 
   public User getUser(@PathParam("userid") int userid){ 
      return userDao.getUser(userid); 
   }  
   @PUT 
   @Path("/users") 
   @Produces(MediaType.APPLICATION_XML) 
   @Consumes(MediaType.APPLICATION_FORM_URLENCODED) 
   public String createUser(@FormParam("id") int id, 
      @FormParam("name") String name, 
      @FormParam("profession") String profession, 
      @Context HttpServletResponse servletResponse) throws IOException{ 
      User user = new User(id, name, profession); 
      int result = userDao.addUser(user); 
      if(result == 1){ 
         return SUCCESS_RESULT; 
      } 
      return FAILURE_RESULT; 
   }  
   @POST 
   @Path("/users")  
   @Produces(MediaType.APPLICATION_XML)
   @Consumes(MediaType.APPLICATION_FORM_URLENCODED) 
   public String updateUser(@FormParam("id") int id, 
      @FormParam("name") String name, 
      @FormParam("profession") String profession, 
      @Context HttpServletResponse servletResponse) throws IOException{ 
      User user = new User(id, name, profession); 
      int result = userDao.updateUser(user); 
      if(result == 1){ 
         return SUCCESS_RESULT; 
      } 
      return FAILURE_RESULT; 
   }  
   @DELETE 
   @Path("/users/{userid}") 
   @Produces(MediaType.APPLICATION_XML) 
   public String deleteUser(@PathParam("userid") int userid){ 
      int result = userDao.deleteUser(userid); 
      if(result == 1){ 
         return SUCCESS_RESULT; 
      } 
      return FAILURE_RESULT; 
   }  
   @OPTIONS 
   @Path("/users") 
   @Produces(MediaType.APPLICATION_XML) 
   public String getSupportedOperations(){ 
      return "<operations>GET, PUT, POST, DELETE</operations>"; 
   } 
}

Maintenant en utilisant Eclipse, exportez votre application en tant que WAR Fileet déployez le même dans Tomcat. Pour créer un fichier WAR en utilisant eclipse, suivez ce chemin -File → export → Web → War Fileet enfin sélectionnez le projet UserManagement et le dossier de destination. Pour déployer un fichier WAR dans Tomcat, placez UserManagement.war dans leTomcat Installation Directory → webapps répertoire et le démarrage Tomcat.

Test du service Web

Jersey fournit des API pour créer un client de service Web pour tester les services Web. Nous avons créé un exemple de classe de testWebServiceTester.java sous le package com.tutorialspoint dans le même projet.

WebServiceTester.java

package com.tutorialspoint;  

import java.util.List; 
import javax.ws.rs.client.Client; 
import javax.ws.rs.client.ClientBuilder; 
import javax.ws.rs.client.Entity; 
import javax.ws.rs.core.Form; 
import javax.ws.rs.core.GenericType; 
import javax.ws.rs.core.MediaType;  

public class WebServiceTester  {  
   private Client client; 
   private String REST_SERVICE_URL = "
   http://localhost:8080/UserManagement/rest/UserService/users"; 
   private static final String SUCCESS_RESULT = "<result>success</result>"; 
   private static final String PASS = "pass"; 
   private static final String FAIL = "fail";  
   private void init(){ 
      this.client = ClientBuilder.newClient(); 
   }  
   public static void main(String[] args){ 
      WebServiceTester tester = new WebServiceTester(); 
      //initialize the tester 
      tester.init(); 
      //test get all users Web Service Method 
      tester.testGetAllUsers(); 
      //test get user Web Service Method  
      tester.testGetUser();
      //test update user Web Service Method 
      tester.testUpdateUser(); 
      //test add user Web Service Method 
      tester.testAddUser(); 
      //test delete user Web Service Method 
      tester.testDeleteUser(); 
   } 
   //Test: Get list of all users 
   //Test: Check if list is not empty 
   private void testGetAllUsers(){ 
      GenericType<List<User>> list = new GenericType<List<User>>() {}; 
      List<User> users = client 
         .target(REST_SERVICE_URL) 
         .request(MediaType.APPLICATION_XML) 
         .get(list); 
      String result = PASS; 
      if(users.isEmpty()){ 
         result = FAIL; 
      } 
      System.out.println("Test case name: testGetAllUsers, Result: " + result ); 
   } 
   //Test: Get User of id 1 
   //Test: Check if user is same as sample user 
   private void testGetUser(){ 
      User sampleUser = new User(); 
      sampleUser.setId(1);  
      User user = client 
         .target(REST_SERVICE_URL) 
         .path("/{userid}") 
         .resolveTemplate("userid", 1) 
         .request(MediaType.APPLICATION_XML) 
         .get(User.class); 
      String result = FAIL; 
      if(sampleUser != null && sampleUser.getId() == user.getId()){
         result = PASS; 
      } 
      System.out.println("Test case name: testGetUser, Result: " + result ); 
   } 
   //Test: Update User of id 1 
   //Test: Check if result is success XML. 
   private void testUpdateUser(){ 
      Form form = new Form(); 
      form.param("id", "1"); 
      form.param("name", "suresh"); 
      form.param("profession", "clerk");  
      String callResult = client 
         .target(REST_SERVICE_URL) 
         .request(MediaType.APPLICATION_XML) 
         .post(Entity.entity(form, 
         MediaType.APPLICATION_FORM_URLENCODED_TYPE), 
         String.class); 
      String result = PASS; 
      if(!SUCCESS_RESULT.equals(callResult)){ 
         result = FAIL; 
      }  
      System.out.println("Test case name: testUpdateUser, Result: " + result); 
   } 
   //Test: Add User of id 2 
   //Test: Check if result is success XML. 
   private void testAddUser(){ 
      Form form = new Form(); 
      form.param("id", "2"); 
      form.param("name", "naresh"); 
      form.param("profession", "clerk");  
      String callResult = client 
         .target(REST_SERVICE_URL) 
         .request(MediaType.APPLICATION_XML) 
         .put(Entity.entity(form, 
         MediaType.APPLICATION_FORM_URLENCODED_TYPE), 
         String.class); 
    
      String result = PASS; 
      if(!SUCCESS_RESULT.equals(callResult)){ 
         result = FAIL; 
      }  
      System.out.println("Test case name: testAddUser, Result: " + result ); 
   } 
   //Test: Delete User of id 2 
   //Test: Check if result is success XML. 
   private void testDeleteUser(){ 
      String callResult = client 
         .target(REST_SERVICE_URL) 
         .path("/{userid}") 
         .resolveTemplate("userid", 2) 
         .request(MediaType.APPLICATION_XML) 
         .delete(String.class);  
      String result = PASS; 
      if(!SUCCESS_RESULT.equals(callResult)){ 
         result = FAIL; 
      } 
      System.out.println("Test case name: testDeleteUser, Result: " + result); 
   } 
}

Exécutez maintenant le testeur à l'aide d'Eclipse. Faites un clic droit sur le fichier et suivez l'optionRun as → Java Application. Vous verrez le résultat suivant dans la console Eclipse -

Test case name: testGetAllUsers, Result: pass 
Test case name: testGetUser, Result: pass 
Test case name: testUpdateUser, Result: pass 
Test case name: testAddUser, Result: pass 
Test case name: testDeleteUser, Result: pass

Conformément à l'architecture REST, un service Web RESTful ne doit pas conserver un état client sur le serveur. Cette restriction s'appelle l'apatridie. Il est de la responsabilité du client de transmettre son contexte au serveur, puis le serveur peut stocker ce contexte pour traiter la demande ultérieure du client. Par exemple, la session maintenue par le serveur est identifiée par l'identifiant de session transmis par le client.

Les services Web RESTful doivent respecter cette restriction. Nous avons vu cela dans le chapitre Services Web RESTful - Méthodes , que les méthodes du service Web ne stockent aucune information du client à partir duquel elles sont appelées.

Consider the following URL −

https: // localhost: 8080 / UserManagement / rest / UserService / users / 1

Si vous appuyez sur l'url ci-dessus en utilisant votre navigateur ou en utilisant un client Java ou en utilisant Postman, le résultat sera toujours le XML utilisateur dont l'ID est 1 car le serveur ne stocke aucune information sur le client.

<user> 
   <id>1</id> 
   <name>mahesh</name> 
   <profession>1</profession> 
</user>

Avantages de l'apatridie

Voici les avantages de l'apatridie dans les services Web RESTful -

  • Les services Web peuvent traiter chaque demande de méthode indépendamment.

  • Les services Web n'ont pas besoin de conserver les interactions précédentes du client. Cela simplifie la conception de l'application.

  • Comme HTTP est lui-même un protocole sans état, les services Web RESTful fonctionnent de manière transparente avec les protocoles HTTP.

Inconvénients de l'apatridie

Voici les inconvénients de l'apatridie dans les services Web RESTful -

  • Les services Web doivent obtenir des informations supplémentaires dans chaque requête, puis interpréter pour obtenir l'état du client au cas où les interactions avec le client seraient prises en charge.

La mise en cache fait référence au stockage de la réponse du serveur dans le client lui-même, de sorte qu'un client n'a pas besoin de faire une demande serveur pour la même ressource encore et encore. Une réponse de serveur doit contenir des informations sur la manière dont la mise en cache doit être effectuée, de sorte qu'un client met en cache la réponse pendant une période ou ne met jamais en cache la réponse du serveur.

Voici les en-têtes qu'une réponse de serveur peut avoir pour configurer la mise en cache d'un client -

N ° Sr. En-tête et description

1

Date

Date et heure de la ressource lors de sa création.

2

Last Modified

Date et heure de la dernière modification de la ressource.

3

Cache-Control

En-tête principal pour contrôler la mise en cache.

4

Expires

Date d'expiration et heure de la mise en cache.

5

Age

Durée en secondes à partir du moment où la ressource a été extraite du serveur.

En-tête Cache-Control

Voici les détails d'un en-tête Cache-Control -

N ° Sr. Directive et description

1

Public

Indique que la ressource peut être mise en cache par n'importe quel composant.

2

Private

Indique que la ressource peut être mise en cache uniquement par le client et le serveur, aucun intermédiaire ne peut mettre en cache la ressource.

3

no-cache/no-store

Indique qu'une ressource ne peut pas être mise en cache.

4

max-age

Indique que la mise en cache est valide jusqu'à l'âge maximum en secondes. Après cela, le client doit faire une autre demande.

5

must-revalidate

Indication au serveur pour revalider la ressource si l'âge maximum est passé.

Les meilleures pratiques

  • Gardez toujours les contenus statiques comme les images, CSS, JavaScript en cache, avec une date d'expiration de 2 à 3 jours.

  • Ne gardez jamais la date d'expiration trop élevée.

  • Le contenu dynamique ne doit être mis en cache que pendant quelques heures.

Comme les services Web RESTful fonctionnent avec des chemins d'URL HTTP, il est très important de protéger un service Web RESTful de la même manière qu'un site Web est sécurisé.

Voici les meilleures pratiques à respecter lors de la conception d'un service Web RESTful -

  • Validation- Validez toutes les entrées sur le serveur. Protégez votre serveur contre les attaques par injection SQL ou NoSQL.

  • Session Based Authentication - Utilisez l'authentification basée sur la session pour authentifier un utilisateur chaque fois qu'une demande est faite à une méthode de service Web.

  • No Sensitive Data in the URL - N'utilisez jamais de nom d'utilisateur, de mot de passe ou de jeton de session dans une URL, ces valeurs doivent être transmises au service Web via la méthode POST.

  • Restriction on Method Execution- Autoriser l'utilisation restreinte de méthodes telles que les méthodes GET, POST et DELETE. La méthode GET ne doit pas être en mesure de supprimer des données.

  • Validate Malformed XML/JSON - Vérifiez les entrées correctement formées transmises à une méthode de service Web.

  • Throw generic Error Messages - Une méthode de service Web doit utiliser des messages d'erreur HTTP tels que 403 pour afficher l'accès interdit, etc.

Code HTTP

N ° Sr. Code HTTP et description

1

200

OK - montre le succès.

2

201

CREATED- lorsqu'une ressource est créée avec succès à l'aide d'une requête POST ou PUT. Renvoie le lien vers la ressource nouvellement créée à l'aide de l'en-tête d'emplacement.

3

204

NO CONTENT- lorsque le corps de la réponse est vide. Par exemple, une demande DELETE.

4

304

NOT MODIFIED- utilisé pour réduire l'utilisation de la bande passante du réseau en cas de requêtes GET conditionnelles. Le corps de la réponse doit être vide. Les en-têtes doivent avoir la date, l'emplacement, etc.

5

400

BAD REQUEST- indique qu'une entrée invalide est fournie. Par exemple, erreur de validation, données manquantes.

6

401

UNAUTHORIZED - indique que l'utilisateur utilise un jeton d'authentification invalide ou incorrect.

sept

403

FORBIDDEN- indique que l'utilisateur n'a pas accès à la méthode utilisée. Par exemple, Supprimer l'accès sans droits d'administrateur.

8

404

NOT FOUND - indique que la méthode n'est pas disponible.

9

409

CONFLICT- indique la situation de conflit lors de l'exécution de la méthode. Par exemple, ajouter une entrée en double.

dix

500

INTERNAL SERVER ERROR - indique que le serveur a levé une exception lors de l'exécution de la méthode.

JAX-RSsignifie JAVA API pour RESTful Web Services. JAX-RS est une API de langage de programmation basée sur JAVA et une spécification pour prendre en charge les services Web RESTful créés. Sa version 2.0 a été publiée le 24 mai 2013. JAX-RS utilise les annotations disponibles à partir de Java SE 5 pour simplifier le développement de la création et du déploiement de services Web basés sur JAVA. Il fournit également des supports pour la création de clients pour les services Web RESTful.

Caractéristiques

Voici les annotations les plus couramment utilisées pour mapper une ressource en tant que ressource de service Web.

N ° Sr. Annotation et description

1

@Path

Chemin relatif de la classe / méthode de ressource.

2

@GET

Requête HTTP Get, utilisée pour récupérer la ressource.

3

@PUT

Requête HTTP PUT, utilisée pour mettre à jour la ressource.

4

@POST

Requête HTTP POST, utilisée pour créer une nouvelle ressource.

5

@DELETE

Requête HTTP DELETE, utilisée pour supprimer la ressource.

6

@HEAD

Requête HTTP HEAD, utilisée pour obtenir l'état de la disponibilité de la méthode.

sept

@Produces

Indique la réponse HTTP générée par le service Web. Par exemple, APPLICATION / XML, TEXT / HTML, APPLICATION / JSON etc.

8

@Consumes

Indique le type de requête HTTP. Par exemple, application / x-www-formurlencoded pour accepter les données de formulaire dans le corps HTTP lors de la requête POST.

9

@PathParam

Lie le paramètre passé à la méthode à une valeur dans path.

dix

@QueryParam

Lie le paramètre passé à la méthode à un paramètre de requête dans le chemin.

11

@MatrixParam

Lie le paramètre passé à la méthode à un paramètre de matrice HTTP dans path.

12

@HeaderParam

Lie le paramètre passé à la méthode à un en-tête HTTP.

13

@CookieParam

Lie le paramètre passé à la méthode à un cookie.

14

@FormParam

Lie le paramètre passé à la méthode à une valeur de formulaire.

15

@DefaultValue

Attribue une valeur par défaut à un paramètre passé à la méthode.

16

@Context

Contexte de la ressource. Par exemple, HTTPRequest en tant que contexte.

Note- Nous avons utilisé Jersey, une implémentation de référence de JAX-RS 2.0 par Oracle, dans les chapitres Services Web RESTful - Première application et Services Web RESTful - Méthodes .