352 Stimmen

Wie sollte ich Servlets und Ajax verwenden?

Immer, wenn ich etwas innerhalb des Servlets ausdrucke und es über den Webbrowser aufrufe, wird eine neue Seite mit diesem Text zurückgegeben. Gibt es eine Möglichkeit, den Text auf der aktuellen Seite mit Ajax zu drucken?

Ich bin ein Neuling in Sachen Webanwendungen und Servlets.

585voto

BalusC Punkte 1034465

Das Schlüsselwort lautet in der Tat "Ajax": Asynchrones JavaScript und XML . Doch in den letzten Jahren ist es mehr als oft Asynchrones JavaScript und JSON . Im Wesentlichen lassen Sie JavaScript eine asynchrone HTTP-Anfrage ausführen und den HTML-DOM-Baum auf der Grundlage der Antwortdaten aktualisieren.

Da es ziemlich mühsame Arbeit, um es zum Laufen zu bringen in allen Browsern (insbesondere Internet Explorer gegenüber anderen), gibt es viele JavaScript-Bibliotheken, die dies in einzelnen Funktionen vereinfachen und möglichst viele browserspezifische Fehler/Ungereimtheiten abdecken, wie z. B. jQuery , Prototyp , Mootools . Da jQuery heutzutage sehr beliebt ist, werde ich es in den folgenden Beispielen verwenden.

Beispiel Kickoff-Rückgabe String als Klartext

Erstellen einer /some.jsp wie unten (Hinweis: Die Codeschnipsel in dieser Antwort erwarten nicht, dass die JSP-Datei in einem Unterordner platziert wird; wenn Sie dies tun, ändern Sie die Servlet-URL entsprechend von "someservlet" a "${pageContext.request.contextPath}/someservlet" (sie wird in den Codeschnipseln nur der Kürze halber weggelassen):

<!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>

Erstellen Sie ein Servlet mit einer doGet() Methode, die wie folgt aussieht:

@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.
}

Bilden Sie dieses Servlet auf ein URL-Muster von /someservlet または /someservlet/* wie unten (natürlich ist das URL-Muster frei wählbar, aber Sie müssen die someservlet URL in JS-Codebeispielen über alles entsprechend platzieren):

package com.example;

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

Oder, wenn Sie nicht auf einer Servlet 3.0-kompatiblen Container noch nicht ( Tomcat 7, GlassFish 3, JBoss AS 6, etc. oder neuer), dann in web.xml auf die altmodische Weise (siehe auch unsere Servlets-Wiki-Seite ):

<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>

Öffnen Sie nun die Seite http://localhost:8080/context/test.jsp im Browser und drücken Sie die Schaltfläche. Sie werden sehen, dass der Inhalt des Divs mit der Servlet-Antwort aktualisiert wird.

Rücksendung List<String> als JSON

Mit JSON anstelle von Klartext als Antwortformat können Sie sogar einige Schritte weiter gehen. Es ermöglicht eine größere Dynamik. Zunächst benötigen Sie ein Tool, das zwischen Java-Objekten und JSON-Strings konvertiert. Auch davon gibt es eine ganze Menge (siehe den unteren Teil von diese Seite für einen Überblick). Mein persönlicher Favorit ist Google Gson . Laden Sie die JAR-Datei herunter und legen Sie sie in /WEB-INF/lib Ordner Ihrer Webanwendung.

Hier ist ein Beispiel, das Folgendes anzeigt List<String> como <ul><li> . Das 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);
}

Der JavaScript-Code:

$(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>.
        });
    });
});

Beachten Sie, dass jQuery die Antwort automatisch als JSON parst und Ihnen direkt ein JSON-Objekt ( responseJson ) als Funktionsargument, wenn Sie den Inhaltstyp der Antwort auf application/json . Wenn Sie die Einstellung vergessen oder sich auf die Vorgabe von text/plain または text/html dann ist die responseJson Argument würde Ihnen kein JSON-Objekt, sondern eine einfache Zeichenkette liefern und Sie müssten manuell mit JSON.parse() was also völlig unnötig ist, wenn Sie den Inhaltstyp von vornherein richtig einstellen.

Rücksendung Map<String, String> als JSON

Hier ist ein weiteres Beispiel, das Folgendes anzeigt Map<String, String> como <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);
}

Und die 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>.
        });
    });
});

mit

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

Rücksendung List<Entity> als JSON

Hier ist ein Beispiel, das Folgendes anzeigt List<Product> en un <table> wo die Product Klasse hat die Eigenschaften Long id , String name y BigDecimal price . Das 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);
}

Der JS-Code:

$(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>.
        });
    });
});

Rücksendung List<Entity> als XML

Hier ist ein Beispiel, das im Grunde dasselbe tut wie das vorherige Beispiel, aber dann mit XML statt JSON. Wenn Sie JSP als XML-Ausgabegenerator verwenden, werden Sie sehen, dass es weniger mühsam ist, die Tabelle und alles andere zu codieren. JSTL ist auf diese Weise viel hilfreicher, da Sie damit über die Ergebnisse iterieren und serverseitige Datenformatierungen vornehmen können. Das 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);
}

Der JSP-Code (Hinweis: Wenn Sie die <table> en un <jsp:include> kann sie an anderer Stelle in einer Nicht-Ajax-Antwort wiederverwendet werden):

<?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>

Der JavaScript-Code:

$(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".
    });
});

Sie wissen jetzt wahrscheinlich, warum XML für den speziellen Zweck der Aktualisierung eines HTML-Dokuments mit Ajax so viel leistungsfähiger ist als JSON. JSON ist zwar witzig, aber im Grunde genommen nur für so genannte "öffentliche Webdienste" nützlich. MVC-Frameworks wie JSF verwenden XML als Deckmantel für ihre Ajax-Magie.

Ajaxifizierung eines bestehenden Formulars

Sie können jQuery verwenden $.serialize() um bestehende POST-Formulare einfach ajaxifizieren zu können, ohne sich mit dem Sammeln und Übergeben der einzelnen Formular-Eingabeparameter herumzuschlagen. Angenommen, ein bestehendes Formular, das ohne JavaScript/jQuery einwandfrei funktioniert (und sich daher anständig verschlechtert, wenn der Endbenutzer JavaScript deaktiviert hat):

<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>

Sie können sie schrittweise mit Ajax wie unten beschrieben erweitern:

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

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

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

Sie können im Servlet zwischen normalen Anfragen und Ajax-Anfragen wie folgt unterscheiden:

@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.
    }
}

のことです。 jQuery-Formular-Plugin macht mehr oder weniger das Gleiche wie das obige jQuery-Beispiel, aber es hat zusätzliche transparente Unterstützung für multipart/form-data Formulare, die für das Hochladen von Dateien erforderlich sind.

Manuelles Senden von Anfrageparametern an das Servlet

Wenn Sie überhaupt kein Formular haben, sondern nur mit dem Servlet "im Hintergrund" interagieren wollen, wobei Sie einige Daten POSTEN möchten, können Sie jQuery verwenden $.param() um ein JSON-Objekt einfach in einen URL-kodierten Abfrage-String zu konvertieren.

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

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

Das gleiche doPost() Methode, wie hier oben gezeigt, wiederverwendet werden. Bitte beachten Sie, dass die obige Syntax auch mit $.get() in jQuery und doGet() im Servlet.

Manuelles Senden eines JSON-Objekts an ein Servlet

Wenn Sie jedoch beabsichtigen, das JSON-Objekt aus irgendeinem Grund als Ganzes und nicht als einzelne Anforderungsparameter zu senden, dann müssen Sie es mit JSON.stringify() (nicht Teil von jQuery) und weisen jQuery an, den Inhaltstyp der Anfrage auf application/json anstelle von (Standard) application/x-www-form-urlencoded . Dies ist nicht möglich über $.post() Komfortfunktion, sondern muss über $.ajax() wie unten.

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) {
        // ...
    }
});

Bitte beachten Sie, dass viele Vorspeisen contentType avec dataType . En contentType steht für den Typ des Anfrage Körper. Die Website dataType steht für den (erwarteten) Typ des Antwort Körper, was in der Regel unnötig ist, da jQuery es bereits automatisch anhand der Antwort des Content-Type Kopfzeile.

Um dann das JSON-Objekt im Servlet zu verarbeiten, das nicht als einzelne Request-Parameter, sondern als ganzer JSON-String auf die oben beschriebene Weise gesendet wird, müssen Sie den Request-Body nur noch manuell mit einem JSON-Tool parsen, anstatt mit getParameter() auf die übliche Weise. Servlets unterstützen nämlich nicht application/json formatierte Anfragen, sondern nur application/x-www-form-urlencoded または multipart/form-data formatierte Anfragen. Gson unterstützt auch das Parsen eines JSON-Strings in ein JSON-Objekt.

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();
// ...

Beachten Sie, dass dies alles etwas umständlicher ist, als wenn Sie einfach $.param() . Normalerweise sollten Sie JSON.stringify() nur, wenn der Zieldienst z. B. ein JAX-RS (RESTful)-Dienst ist, der aus irgendeinem Grund nur JSON-Strings und keine regulären Anfrageparameter verarbeiten kann.

Senden einer Weiterleitung vom Servlet

Es ist wichtig zu erkennen und zu verstehen, dass jede sendRedirect() y forward() Aufruf durch das Servlet bei einer Ajax-Anfrage würde nur weiterleiten oder umleiten die Ajax-Anfrage selbst und nicht das Hauptdokument/Fenster, aus dem die Ajax-Anfrage stammt. JavaScript/jQuery würde in einem solchen Fall nur die umgeleitete/weitergeleitete Antwort als responseText in der Callback-Funktion. Wenn es sich um eine ganze HTML-Seite und nicht um eine Ajax-spezifische XML- oder JSON-Antwort handelt, können Sie lediglich das aktuelle Dokument durch diese ersetzen.

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

Beachten Sie, dass dies die URL, die der Endbenutzer in der Adressleiste des Browsers sieht, nicht ändert. Es gibt also Probleme mit der Lesezeichenfähigkeit. Daher ist es viel besser, nur eine "Anweisung" für JavaScript/jQuery zurückzugeben, um eine Umleitung durchzuführen, anstatt den gesamten Inhalt der umgeleiteten Seite zurückzugeben. Z. B. durch Rückgabe eines booleschen Wertes oder einer 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;
    }

    // ...
}

Siehe auch:

14voto

Stephen C Punkte 665668

Der richtige Weg, die aktuell im Browser des Benutzers angezeigte Seite zu aktualisieren (ohne sie neu zu laden), besteht darin, dass ein im Browser ausgeführter Code das DOM der Seite aktualisiert.

Bei diesem Code handelt es sich in der Regel um JavaScript, das in die HTML-Seite eingebettet oder mit ihr verlinkt ist, daher der Ajax-Vorschlag. (Wenn wir davon ausgehen, dass der aktualisierte Text über eine HTTP-Anfrage vom Server kommt, handelt es sich um klassisches Ajax).

Es ist auch möglich, diese Art von Dingen mit einem Browser-Plugin oder Add-on zu implementieren, obwohl es für ein Plugin schwierig sein kann, in die Datenstrukturen des Browsers zu gelangen, um das DOM zu aktualisieren. (Native Code-Plugins schreiben normalerweise in einen Grafikrahmen, der in die Seite eingebettet ist).

13voto

Mitul Maheshwari Punkte 2597

Ich zeige Ihnen ein ganzes Beispiel für ein Servlet und wie man einen Ajax-Aufruf macht.

Hier werden wir ein einfaches Beispiel für die Erstellung eines Anmeldeformulars mit einem Servlet erstellen.

Datei 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>

Ein Ajax-Beispiel

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

LoginServlet-Servlet-Code:

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);
        }
    }
}

8voto

SUBZ Punkte 139
$.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);
    }
});

7voto

user3468976 Punkte 599

Ajax (auch AJAX), ein Akronym für Asynchronous JavaScript and XML, ist eine Gruppe miteinander verbundener Web-Entwicklungstechniken, die auf der Client-Seite zur Erstellung asynchroner Web-Anwendungen verwendet werden. Mit Ajax können Webanwendungen asynchron Daten an einen Server senden und Daten von diesem abrufen.

Nachstehend finden Sie den Beispielcode:

Eine JavaScript-Funktion auf einer JSP-Seite zur Übermittlung von Daten an ein Servlet mit zwei Variablen, firstName und 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 zum Lesen von Daten, die im XML-Format an die JSP zurückgeschickt werden (Sie können auch Text verwenden. Sie müssen nur den Inhalt der Antwort in Text ändern und die Daten mit der JavaScript-Funktion darstellen).

/**
 * @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>");
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X