web-dev-qa-db-fra.com

Comment utiliser Servlets et Ajax?

Je suis très nouveau dans les applications Web et les servlets et j'ai la question suivante:

Chaque fois que j'imprime quelque chose à l'intérieur du servlet et que je l'appelle par le navigateur Web, il renvoie une nouvelle page contenant ce texte. Est-il possible d'imprimer le texte de la page en cours en utilisant Ajax?

324
Amir Rachum

En effet, le mot clé est "ajax": JavaScript asynchrone et XML . Cependant, ces dernières années, c'est plus que souvent JavaScript asynchrone et JSON . Fondamentalement, vous laissez JS exécuter une requête HTTP asynchrone et mettre à jour l'arborescence DOM HTML en fonction des données de réponse.

Étant donné que c'est assez fastidieux de le faire fonctionner sur tous les navigateurs (en particulier Internet Explorer par rapport aux autres), il existe de nombreuses bibliothèques JavaScript qui simplifient cela dans des fonctions uniques et en couvrent autant que possible. bugs/bizarreries spécifiques sous le capot, tels que jQuery , Prototype , Mootools . Comme jQuery est le plus populaire de nos jours, je l’utiliserai dans les exemples ci-dessous.

Exemple de démarrage renvoyant String sous forme de texte brut

Créez un /some.jsp comme ci-dessous (remarque: le code n'attend pas que le fichier JSP soit placé dans un sous-dossier. Si vous le faites, modifiez l'URL du servlet en conséquence):

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>SO question 4112686</title>
        <script src="http://code.jquery.com/jquery-latest.min.js"></script>
        <script>
            $(document).on("click", "#somebutton", function() { // When HTML DOM "click" event is invoked on element with ID "somebutton", execute the following function...
                $.get("someservlet", function(responseText) {   // Execute Ajax GET request on URL of "someservlet" and execute the following function with Ajax response text...
                    $("#somediv").text(responseText);           // Locate HTML DOM element with ID "somediv" and set its text content with the response text.
                });
            });
        </script>
    </head>
    <body>
        <button id="somebutton">press here</button>
        <div id="somediv"></div>
    </body>
</html>

Créez un servlet avec une méthode doGet() qui ressemble à ceci:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String text = "some text";

    response.setContentType("text/plain");  // Set content type of the response so that jQuery knows what it can expect.
    response.setCharacterEncoding("UTF-8"); // You want world domination, huh?
    response.getWriter().write(text);       // Write response body.
}

Mappez cette servlet sur un modèle d'URL de /someservlet ou /someservlet/* comme ci-dessous (le modèle d'URL est évidemment libre de votre choix, mais vous devez modifier l'URL someservlet en code JS. des exemples sur tous les lieux en conséquence):

@WebServlet("/someservlet/*")
public class SomeServlet extends HttpServlet {
    // ...
}

Ou bien, lorsque vous n'êtes pas encore sur un conteneur compatible Servlet 3.0 (Tomcat 7, Glassfish 3, JBoss AS 6, etc. ou une version plus récente), mappez-le dans web.xml à l'ancienne (voir aussi notre page wiki Servlets ):

<servlet>
    <servlet-name>someservlet</servlet-name>
    <servlet-class>com.example.SomeServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>someservlet</servlet-name>
    <url-pattern>/someservlet/*</url-pattern>
</servlet-mapping>

Maintenant, ouvrez le http: // localhost: 8080/context/test.jsp dans le navigateur et appuyez sur le bouton. Vous verrez que le contenu de la div est mis à jour avec la réponse du servlet.

Renvoyer List<String> en tant que JSON

Avec JSON au lieu du texte en clair comme format de réponse, vous pouvez même obtenir des étapes supplémentaires. Cela permet plus de dynamique. Tout d'abord, vous souhaitez disposer d'un outil pour convertir entre les objets Java et les chaînes JSON. Il y en a beaucoup aussi (voir le bas de cette page pour un aperçu). Mon favori personnel est Google Gson . Téléchargez et mettez son fichier JAR dans le dossier /WEB-INF/lib de votre application Web.

Voici un exemple qui affiche List<String> en tant que <ul><li>. Le servlet:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    List<String> list = new ArrayList<>();
    list.add("item1");
    list.add("item2");
    list.add("item3");
    String json = new Gson().toJson(list);

    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");
    response.getWriter().write(json);
}

Le code JS:

$(document).on("click", "#somebutton", function() {  // When HTML DOM "click" event is invoked on element with ID "somebutton", execute the following function...
    $.get("someservlet", function(responseJson) {    // Execute Ajax GET request on URL of "someservlet" and execute the following function with Ajax response JSON...
        var $ul = $("<ul>").appendTo($("#somediv")); // Create HTML <ul> element and append it to HTML DOM element with ID "somediv".
        $.each(responseJson, function(index, item) { // Iterate over the JSON array.
            $("<li>").text(item).appendTo($ul);      // Create HTML <li> element, set its text content with currently iterated item and append it to the <ul>.
        });
    });
});

Notez que jQuery analyse automatiquement la réponse au format JSON et vous donne directement un objet JSON (responseJson) comme argument de fonction lorsque vous définissez le type de contenu de la réponse sur application/json. Si vous oubliez de le définir ou si vous vous appuyez sur la valeur par défaut text/plain ou text/html, alors l'argument responseJson ne vous donnera pas un objet JSON, mais une chaîne simple. besoin de bidouiller manuellement avec JSON.parse() , ce qui est donc totalement inutile si vous définissez le type de contenu à la première place.

Renvoyer Map<String, String> en tant que JSON

Voici un autre exemple qui affiche Map<String, String> comme <option>:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Map<String, String> options = new LinkedHashMap<>();
    options.put("value1", "label1");
    options.put("value2", "label2");
    options.put("value3", "label3");
    String json = new Gson().toJson(options);

    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");
    response.getWriter().write(json);
}

Et le JSP:

$(document).on("click", "#somebutton", function() {               // When HTML DOM "click" event is invoked on element with ID "somebutton", execute the following function...
    $.get("someservlet", function(responseJson) {                 // Execute Ajax GET request on URL of "someservlet" and execute the following function with Ajax response JSON...
        var $select = $("#someselect");                           // Locate HTML DOM element with ID "someselect".
        $select.find("option").remove();                          // Find all child elements with tag name "option" and remove them (just to prevent duplicate options when button is pressed again).
        $.each(responseJson, function(key, value) {               // Iterate over the JSON object.
            $("<option>").val(key).text(value).appendTo($select); // Create HTML <option> element, set its value with currently iterated key and its text content with currently iterated item and finally append it to the <select>.
        });
    });
});

avec

<select id="someselect"></select>

Renvoyer List<Entity> en tant que JSON

Voici un exemple qui affiche List<Product> dans un <table> où la classe Product a les propriétés Long id, String name et BigDecimal price. Le servlet:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    List<Product> products = someProductService.list();
    String json = new Gson().toJson(products);

    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");
    response.getWriter().write(json);
}

Le code JS:

$(document).on("click", "#somebutton", function() {        // When HTML DOM "click" event is invoked on element with ID "somebutton", execute the following function...
    $.get("someservlet", function(responseJson) {          // Execute Ajax GET request on URL of "someservlet" and execute the following function with Ajax response JSON...
        var $table = $("<table>").appendTo($("#somediv")); // Create HTML <table> element and append it to HTML DOM element with ID "somediv".
        $.each(responseJson, function(index, product) {    // Iterate over the JSON array.
            $("<tr>").appendTo($table)                     // Create HTML <tr> element, set its text content with currently iterated item and append it to the <table>.
                .append($("<td>").text(product.id))        // Create HTML <td> element, set its text content with id of currently iterated product and append it to the <tr>.
                .append($("<td>").text(product.name))      // Create HTML <td> element, set its text content with name of currently iterated product and append it to the <tr>.
                .append($("<td>").text(product.price));    // Create HTML <td> element, set its text content with price of currently iterated product and append it to the <tr>.
        });
    });
});

Renvoyer List<Entity> en XML

Voici un exemple qui fait exactement la même chose que l'exemple précédent, mais avec XML au lieu de JSON. Lorsque vous utilisez JSP comme générateur de sortie XML, vous constaterez qu'il est moins fastidieux de coder la table et tout le reste. JSTL est ainsi beaucoup plus utile car vous pouvez l'utiliser pour parcourir les résultats et effectuer le formatage des données côté serveur. Le servlet:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    List<Product> products = someProductService.list();

    request.setAttribute("products", products);
    request.getRequestDispatcher("/WEB-INF/xml/products.jsp").forward(request, response);
}

Le code JSP (note: si vous mettez le <table> dans un <jsp:include>, il pourra être réutilisé ailleurs dans une réponse non-ajax):

<?xml version="1.0" encoding="UTF-8"?>
<%@page contentType="application/xml" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://Java.Sun.com/jsp/jstl/core" %>
<%@taglib prefix="fmt" uri="http://Java.Sun.com/jsp/jstl/fmt" %>
<data>
    <table>
        <c:forEach items="${products}" var="product">
            <tr>
                <td>${product.id}</td>
                <td><c:out value="${product.name}" /></td>
                <td><fmt:formatNumber value="${product.price}" type="currency" currencyCode="USD" /></td>
            </tr>
        </c:forEach>
    </table>
</data>

Le code JS:

$(document).on("click", "#somebutton", function() {             // When HTML DOM "click" event is invoked on element with ID "somebutton", execute the following function...
    $.get("someservlet", function(responseXml) {                // Execute Ajax GET request on URL of "someservlet" and execute the following function with Ajax response XML...
        $("#somediv").html($(responseXml).find("data").html()); // Parse XML, find <data> element and append its HTML to HTML DOM element with ID "somediv".
    });
});

Vous réaliserez probablement maintenant pourquoi XML est tellement plus puissant que JSON dans le but particulier de mettre à jour un document HTML à l'aide d'Ajax. JSON est amusant, mais après tout, il n'est généralement utile que pour les "services Web publics". Les frameworks MVC comme JSF utilisent XML sous les couvertures pour leur magie ajax.

Ajaxifier un formulaire existant

Vous pouvez utiliser jQuery $.serialize() pour ajuster facilement les formulaires POST existants sans passer au travers de la collecte et de la transmission des paramètres de saisie de formulaire individuels. En supposant qu'un formulaire existant fonctionne parfaitement sans JavaScript/jQuery (et dégrade ainsi normalement lorsque l'utilisateur final a désactivé JavaScript):

<form id="someform" action="someservlet" method="post">
    <input type="text" name="foo" />
    <input type="text" name="bar" />
    <input type="text" name="baz" />
    <input type="submit" name="submit" value="Submit" />
</form>

Vous pouvez progressivement l’améliorer avec ajax comme ci-dessous:

$(document).on("submit", "#someform", function(event) {
    var $form = $(this);

    $.post($form.attr("action"), $form.serialize(), function(response) {
        // ...
    });

    event.preventDefault(); // Important! Prevents submitting the form.
});

Dans le servlet, vous pouvez faire la distinction entre les requêtes normales et les requêtes ajax comme ci-dessous:

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String foo = request.getParameter("foo");
    String bar = request.getParameter("bar");
    String baz = request.getParameter("baz");

    boolean ajax = "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));

    // ...

    if (ajax) {
        // Handle ajax (JSON or XML) response.
    } else {
        // Handle regular (JSP) response.
    }
}

Le plugin de formulaire jQuery fait plus ou moins la même chose que l'exemple ci-dessus, mais il prend en charge de manière transparente les formulaires multipart/form-data comme le requièrent les téléchargements de fichiers.

Envoi manuel des paramètres de requête au servlet

Si vous n'avez pas du tout de formulaire mais que vous vouliez simplement interagir avec le servlet "en arrière-plan" par lequel vous souhaitez POST quelques données, vous pouvez utiliser jQuery $.param() pour convertir facilement un objet JSON en une chaîne de requête codée par URL.

var params = {
    foo: "fooValue",
    bar: "barValue",
    baz: "bazValue"
};

$.post("someservlet", $.param(params), function(response) {
    // ...
});

La même méthode doPost() que celle illustrée ci-dessus peut être réutilisée. Notez que la syntaxe ci-dessus fonctionne également avec $.get() dans jQuery et doGet() dans servlet.

Envoi manuel d'objet JSON au servlet

Si vous avez toutefois l'intention d'envoyer l'objet JSON dans son ensemble plutôt que sous la forme de paramètres de requête individuels pour une raison quelconque, vous devez le sérialiser en chaîne à l'aide de JSON.stringify() (ne faisant pas partie de jQuery) et d'instruire jQuery pour définir le type de contenu de la demande sur application/json au lieu de (valeur par défaut) application/x-www-form-urlencoded. Cela ne peut pas être fait via la fonction de confort $.post(), mais doit être fait via $.ajax() comme ci-dessous.

var data = {
    foo: "fooValue",
    bar: "barValue",
    baz: "bazValue"
};

$.ajax({
    type: "POST",
    url: "someservlet",
    contentType: "application/json", // NOT dataType!
    data: JSON.stringify(data),
    success: function(response) {
        // ...
    }
});

Notez que beaucoup de démarreurs mélangent contentType avec dataType. La contentType représente le type du corps de la requête . La dataType représente le type (attendu) du corps de la réponse , ce qui est généralement inutile car jQuery le détecte déjà automatiquement en fonction du résultat de la réponse Content-Type entête.

Ensuite, afin de traiter l'objet JSON dans le servlet qui n'est pas envoyé comme paramètre de requête individuel mais comme une chaîne JSON complète de la manière ci-dessus, il vous suffit d'analyser manuellement le corps de la requête à l'aide d'un outil JSON au lieu d'utiliser getParameter(). Manière habituelle. Ainsi, les servlets ne prennent pas en charge les demandes formatées application/json, mais uniquement les demandes application/x-www-form-urlencoded ou multipart/form-data. Gson prend également en charge l'analyse d'une chaîne JSON dans un objet JSON.

JsonObject data = new Gson().fromJson(request.getReader(), JsonObject.class);
String foo = data.get("foo").getAsString();
String bar = data.get("bar").getAsString();
String baz = data.get("baz").getAsString();
// ...

Notez que tout cela est plus maladroit que d'utiliser simplement $.param(). Normalement, vous souhaitez utiliser JSON.stringify() uniquement si le service cible est par exemple. un service JAX-RS (RESTful) qui, pour une raison quelconque, n'est capable que de consommer des chaînes JSON et non des paramètres de requête normaux.

Envoi d'une redirection depuis un servlet

Il est important de comprendre et de comprendre que tout appel de sendRedirect() et forward() par le servlet sur une requête ajax ne ferait que renvoyer ou rediriger la requête ajax elle-même et non le document/la fenêtre principale où ajax demande à l'origine. Dans ce cas, JavaScript/jQuery extrairait uniquement la réponse redirigée/transmise sous forme de variable responseText dans la fonction de rappel. S'il représente une page HTML entière et non une réponse XML ou JSON spécifique à ajax, il vous suffit de remplacer le document actuel par celle-ci.

document.open();
document.write(responseText);
document.close();

Notez que cela ne modifie pas l'URL comme l'utilisateur final le voit dans la barre d'adresse du navigateur. Il existe donc des problèmes de bookmarkability. Par conséquent, il est bien préférable de simplement renvoyer une "instruction" pour que JavaScript/jQuery effectue une redirection au lieu de renvoyer tout le contenu de la page redirigée. Par exemple. en retournant un booléen ou une URL.

String redirectURL = "http://example.com";

Map<String, String> data = new HashMap<>();
data.put("redirect", redirectURL);
String json = new Gson().toJson(data);

response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(json);
function(responseJson) {
    if (responseJson.redirect) {
        window.location = responseJson.redirect;
        return;
    }

    // ...
}

Voir également:

545
BalusC

La bonne façon de mettre à jour la page actuellement affichée dans le navigateur de l'utilisateur (sans la recharger) est de faire exécuter du code s'exécutant dans le navigateur sur le DOM de la page.

Ce code est généralement du code javascript intégré ou lié à la page HTML, d'où la suggestion AJAX. (En fait, si nous supposons que le texte mis à jour provient du serveur via une requête HTTP, c'est AJAX classique.)

Il est également possible d'implémenter ce genre de chose en utilisant un plugin ou un add-on de navigateur, bien qu'il puisse être difficile pour un plugin d'accéder aux structures de données du navigateur pour mettre à jour le DOM. (Les plug-ins de code natif écrivent normalement dans un cadre graphique intégré à la page.)

14
Stephen C

Je vais vous montrer un exemple complet de servlet et comment appeler ajax.

Ici, nous allons créer l'exemple simple pour créer le formulaire de connexion à l'aide de servlet.

index.html

<form>  
   Name:<input type="text" name="username"/><br/><br/>  
   Password:<input type="password" name="userpass"/><br/><br/>  
   <input type="button" value="login"/>  
</form>  

Voici un exemple ajax

       $.ajax
        ({
            type: "POST",           
            data: 'LoginServlet='+name+'&name='+type+'&pass='+password,
            url: url,
        success:function(content)
        {
                $('#center').html(content);           
            }           
        });

Code de servlet LoginServlet: -

    package abc.servlet;

import Java.io.File;


public class AuthenticationServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {   
        doPost(request, response);
    }

    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {

        try{
        HttpSession session = request.getSession();
        String username = request.getParameter("name");
        String password = request.getParameter("pass");

                /// Your Code
out.println("sucess / failer")
        } catch (Exception ex) {
            // System.err.println("Initial SessionFactory creation failed.");
            ex.printStackTrace();
            System.exit(0);
        } 
    }
}
13
Mitul Maheshwari
$.ajax({
type: "POST",
url: "url to hit on servelet",
data:   JSON.stringify(json),
dataType: "json",
success: function(response){
    // we have the response
    if(response.status == "SUCCESS"){
        $('#info').html("Info  has been added to the list successfully.<br>"+
        "The  Details are as follws : <br> Name : ");

    }else{
        $('#info').html("Sorry, there is some thing wrong with the data provided.");
    }
},
 error: function(e){
   alert('Error: ' + e);
 }
});
8
SUBZ

Ajax (également AJAX) est un ensemble de techniques de développement Web interdépendantes utilisées côté client pour créer des applications Web asynchrones. Avec Ajax, les applications Web peuvent envoyer des données à un serveur et en extraire des données de manière asynchrone. Voici un exemple de code:

Jsp page Java fonction de script permettant de soumettre des données à une servlet avec deux variables firstName et lastName:

function onChangeSubmitCallWebServiceAJAX()
    {
      createXmlHttpRequest();
      var firstName=document.getElementById("firstName").value;
      var lastName=document.getElementById("lastName").value;
      xmlHttp.open("GET","/AJAXServletCallSample/AjaxServlet?firstName="
      +firstName+"&lastName="+lastName,true)
      xmlHttp.onreadystatechange=handleStateChange;
      xmlHttp.send(null);

    }

Servlet pour lire les données renvoyées à jsp au format xml (vous pouvez aussi utiliser du texte. Vous avez juste besoin de changer le contenu de la réponse en texte et de rendre les données avec la fonction javascript.)

/**
 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
 */
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    String firstName = request.getParameter("firstName");
    String lastName = request.getParameter("lastName");

    response.setContentType("text/xml");
    response.setHeader("Cache-Control", "no-cache");
    response.getWriter().write("<details>");
    response.getWriter().write("<firstName>"+firstName+"</firstName>");
    response.getWriter().write("<lastName>"+lastName+"</lastName>");
    response.getWriter().write("</details>");
}
7
user3468976

Normalement, vous ne pouvez pas mettre à jour une page à partir d'un servlet. Le client (navigateur) doit demander une mise à jour. Eiter client charge une nouvelle page ou demande une mise à jour d'une partie d'une page existante. Cette technique s'appelle Ajax.

5
Peter Knego

Utilisation de bootstrap multi select

Ajax

function() { $.ajax({
    type : "get",
    url : "OperatorController",
    data : "input=" + $('#province').val(),
    success : function(msg) {
    var arrayOfObjects = eval(msg); 
    $("#operators").multiselect('dataprovider',
    arrayOfObjects);
    // $('#output').append(obj);
    },
    dataType : 'text'
    });}
}

dans Servlet

request.getParameter("input")
4
Thakhani Tharage