Dans ma société actuelle, nous commençons un nouveau projet qui sera une API REST en Java, déployée dans un conteneur de servlets comme Tomcat. Dans mon expérience précédente avec des frameworks REST tels que JAX-RS avec Jersey, JBOSS REST, Spring, MVC, je sais quels sont les avantages d'utiliser un framework comme ceux d'écrire directement les servlets pour le traitement du demandes.
(Bien sûr, nous savons que les frameworks mentionnés utilisent encore Servlets sous les couvertures)
Je trouve difficile de les convaincre. Comme ils proposent d’écrire des servlets en pensant que c’est mieux pour la performance (ce qui peut être le cas, mais je pense que l’utilisation d’un de ces frameworks devrait être négligeable pour une API REST).
Voici mes raisons:
1) Moins de code passe-partout et un code plus concis (plus facile à gérer et à tester). Avec un framework JAX-RS ou SpringMVC, vous pouvez définir une ressource REST très facilement en écrivant des méthodes avec des annotations indiquant le PATH de la ressource, la méthode http à utiliser, les paramètres de requête et d'URL, les en-têtes tels que le codage accepté, etc.
Exemple:
@GET
@Path("/users")
@Produces({MediaType.APPLICATION_JSON})
public UserList getUsers(@QueryParam("group") String group) {
return userService.findUsers(group);
}
Avec les servlets, vous aurez besoin d'au moins quelque chose comme ceci:
Mappez l'URL de chaque servlet dans le fichier web.xml (ce qui n'est pas nécessaire dans et au-dessus de Servlet 3.0):
<servlet>
<servlet-name>UsersServlet</servlet-name>
<servlet-class>test.UsersServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UsersServlet</servlet-name>
<url-pattern>/users</url-pattern>
</servlet-mapping>
Puis à l'intérieur de la classe servlet:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String group = request.getParameter("group");
response.setContentType("application/json");
PrintWriter out = response.getWriter();
JsonSerializer someJsonSerializer = new JsonSerializer();
String json = someJsonSerializer.serialize(userService.findUsers(group));
out.print(json);
}
2) Adaptabilité . Les structures mentionnées vous permettent d’ajouter facilement à votre application des fonctionnalités qui, sinon, vous devrez le faire manuellement, telles que l’utilisation de plusieurs entrées et sorties de types de supports. Par exemple, créer un service pour renvoyer xml ou json ou tout autre en fonction de l'en-tête d'acceptation. Des structures telles que SpringMVC et Jersey facilitent la configuration de sérialiseurs/désérialiseurs pour vos demandes et vos réponses.
3) REST meilleures pratiques . Normalement, ces frameworks reposent sur une solide compréhension des meilleures pratiques à suivre par une API REST et sont définis en fonction des normes de l'architecture REST, ce qui facilite la création d'une application solide et conforme aux normes. D'autre part, les servlets vous offrent un degré de liberté sur le traitement des demandes/réponses tel qu'il sera plus difficile de réaliser que vous n'êtes pas du tout RESTfull.
Tout autre?
Permettez-moi de me faire l'avocat du diable avec ma réponse.
Tout d'abord, vous n'avez pas besoin d'ajouter les servlets au fichier web.xml. Servlets 3.0 vous permet d'utiliser annotations .
Deuxièmement, ces frameworks ont un impact significatif sur les performances. Voir ces repères
Troisièmement, vous pouvez utiliser GSON dans une servlet, ce qui est plus rapide que Jackson (utilisé par défaut dans Spring et Jersey). Vous obtenez ainsi encore plus de performances, d'autant plus que ces performances sont essentielles pour vos besoins.
Enfin, si vous êtes préoccupé par le comportement du client, placez le code que vous avez écrit dans le servlet dans une classe d'utilitaires et utilisez-le à partir de plusieurs servlets. Cela vaut mieux que de supporter la charge énorme d'un framework lorsque vous (comme la plupart des gens) utilisez probablement une petite fraction de ses fonctionnalités.
Premièrement, je souhaiterais mettre en place un test simple avec deux applications ayant un servlet "Hello World" - un avec des servlets pures, une avec Spring MVC ou Apache CXF ou votre framework de choix. Ensuite, effectuez un test de performance pour prouver (espérons-le) que l'impact sur les performances est insignifiant.
Les sérialiseurs et les désérialiseurs en sont un bon exemple, mais le modèle intercepteur/filtre disponible dans ces frameworks est également très utile:
De plus, il existe des outils qui se connectent à ces infrastructures pour générer de la documentation (WADLs/WSDLs/Enunciate) et des bibliothèques de classes client. Il existe également des bibliothèques de tests qui peuvent être utilisées pour générer des tests automatisés sur des frameworks bien connus.
Je réinventais aussi la roue. Mais cela n’a plus de sens (si cela a déjà été le cas).
Il y a quelques mois, Serveral a mis un commentaire disant que j'étais pour la solution pure Servlet 3.0 contre l'utilisation des frameworks RES MVC.
Après des mois d'utilisation, je confirme mon choix!
J'ai essayé d'installer Jackson et d'autres frameworks mais cela demande plus de travail que l'écriture des 5 lignes de code supplémentaires et je n'ai pas à faire face à un composant logiciel supplémentaire pour configurer, apprendre, mettre à jour ...
Voici mon exemple de travail:
package example;
import Java.io.IOException;
import Java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
/**@WebServlet(name = "booking", urlPatterns = { "/api/v1/booking" })*/
public class BookingWs extends javax.servlet.http.HttpServlet {
public static final Logger LOGGER = LoggerFactory.getLogger(BookingWs.class);
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
// Used for JSON handling
Gson gson = new Gson();
// De-serialize from request
BookingRequest bRequest = gson.fromJson(request.getReader(), BookingRequest.class);
// Do your business logic.
BookingResponse bResponse = new BookingResponse();
bResponse.request = bRequest;
bResponse.accepted = "bar".equalsIgnoreCase(bRequest.type);
bResponse.reason = bResponse.accepted ? "Welcome" : "Only bar table booking left";
// Serialize and send response back;
response.setContentType("application/json");
PrintWriter pw = response.getWriter();
gson.toJson(bResponse, pw);
} catch (Throwable t) {
response.setStatus(500);
PrintWriter pw = response.getWriter();
pw.write("{\"error\":\"" + t.getLocalizedMessage() + "\"}");
}
}
}
class BookingRequest{
String type;
int seats;
String name;
long requiredTimestamp;
}
class BookingResponse{
BookingRequest request;
boolean accepted;
String reason;
}
Peut-être que ces frameworks ont une fonctionnalité dont vous avez absolument besoin, mais pour moi, cela devrait être assez décisif pour mériter la peine des libs supplémentaires.
Comme l'écrivain français Antoine de Saint Exupery a déclaré:
"La perfection n'est pas atteinte quand il n'y a plus rien à ajouter, mais quand il n'y a plus rien à enlever".
J'ai emmené Jackson pour m'en rapprocher :-)
(Oui, je dois l'avouer, j'ai utilisé GSON, mais c'est un petit pot, sans aucune configuration nécessaire).
Pour moi, le véritable avantage de Spring MVC est l’augmentation de la productivité. Tout écrire à partir de zéro pour ajuster les choses est logique si vous avez besoin d'une application vraiment personnalisée. Bien que créer quelque chose de nouveau sans aucun framework puisse être une bonne idée, une fois que celui-ci grandira, vous devrez faire face à des problèmes déjà résolus par des centaines de développeurs. En utilisant Spring MVC, vous épargnerez beaucoup de temps et vous gaspilleriez probablement à réinventer la roue, et encore plus de temps lorsque vous devrez former quelqu'un pour gérer votre code personnalisé génial.