Bagaimana cara menggunakan Servlets dan Ajax?


334

Saya sangat baru di aplikasi web dan Server dan saya punya pertanyaan berikut:

Setiap kali saya mencetak sesuatu di dalam servlet dan menyebutnya oleh browser web, ia akan mengembalikan halaman baru yang berisi teks itu. Apakah ada cara untuk mencetak teks di halaman saat ini menggunakan Ajax?

Jawaban:


561

Memang, kata kuncinya adalah "ajax": Asynchronous JavaScript and XML . Namun, tahun-tahun terakhir ini lebih sering Asynchronous JavaScript dan JSON . Pada dasarnya, Anda membiarkan JS mengeksekusi permintaan HTTP asinkron dan memperbarui pohon DOM HTML berdasarkan data respons.

Karena cukup membosankan untuk membuatnya bekerja di semua browser (terutama Internet Explorer versus yang lain), ada banyak pustaka JavaScript yang menyederhanakan ini dalam fungsi tunggal dan mencakup sebanyak mungkin bug / quirks khusus browser di bawah tenda. , seperti jQuery , Prototype , Mootools . Karena jQuery paling populer akhir-akhir ini, saya akan menggunakannya dalam contoh di bawah ini.

Contoh kickoff kembali Stringsebagai teks biasa

Buat /some.jspseperti di bawah ini (catatan: kode tidak mengharapkan file JSP ditempatkan di subfolder, jika Anda melakukannya, ubah URL servlet yang sesuai):

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

Buat servlet dengan doGet()metode yang terlihat seperti ini:

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

Petakan servlet ini pada pola URL /someservletatau /someservlet/*seperti di bawah ini (jelas, pola URL bebas untuk pilihan Anda, tetapi Anda harus mengubah someservletURL dalam contoh kode JS di semua tempat yang sesuai):

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

Atau, ketika Anda belum menggunakan wadah yang kompatibel dengan Servlet 3.0 (Tomcat 7, Glassfish 3, JBoss AS 6, dll atau yang lebih baru), maka petakan dengan web.xmlcara lama (lihat juga halaman wiki Servlets kami ):

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

Sekarang buka http: // localhost: 8080 / context / test.jsp di browser dan tekan tombol. Anda akan melihat bahwa konten div diperbarui dengan respons servlet.

Kembali List<String>sebagai JSON

Dengan JSON alih-alih plaintext sebagai format respons Anda bahkan bisa mendapatkan beberapa langkah lebih lanjut. Ini memungkinkan lebih banyak dinamika. Pertama, Anda ingin memiliki alat untuk mengkonversi antara objek Java dan string JSON. Ada banyak juga (lihat bagian bawah halaman ini untuk ikhtisar). Favorit pribadi saya adalah Google Gson . Unduh dan letakkan file JAR-nya di /WEB-INF/libfolder aplikasi web Anda.

Berikut ini contoh yang ditampilkan List<String>sebagai <ul><li>. 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);
}

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

Perhatikan bahwa jQuery secara otomatis mem-parsing respons sebagai JSON dan memberi Anda secara langsung objek JSON ( responseJson) sebagai argumen fungsi ketika Anda mengatur tipe konten respons application/json. Jika Anda lupa untuk mengatur atau mengandalkan default text/plainatau text/html, maka responseJsonargumen tidak akan memberi Anda objek JSON, tetapi string vanilla polos dan Anda harus bermain-main dengan secara manual JSON.parse()setelah itu, yang dengan demikian sama sekali tidak perlu jika Anda atur jenis konten di tempat pertama.

Kembali Map<String, String>sebagai JSON

Berikut ini contoh lain yang ditampilkan Map<String, String>sebagai <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);
}

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

dengan

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

Kembali List<Entity>sebagai JSON

Berikut adalah contoh yang menampilkan List<Product>di <table>mana Productkelas memiliki properti Long id, String namedan BigDecimal price. 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);
}

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

Kembali List<Entity>sebagai XML

Berikut ini adalah contoh yang secara efektif sama dengan contoh sebelumnya, tetapi kemudian dengan XML dan bukan JSON. Saat menggunakan JSP sebagai generator keluaran XML, Anda akan melihat bahwa tidak terlalu membosankan untuk mengkodekan tabel dan semuanya. JSTL adalah cara ini jauh lebih bermanfaat karena Anda benar-benar dapat menggunakannya untuk beralih pada hasil dan melakukan format data sisi server. 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);
}

Kode JSP (catatan: jika Anda memasukkan <table>a <jsp:include>, mungkin dapat digunakan kembali di tempat lain dalam respons 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>

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

Anda sekarang mungkin akan menyadari mengapa XML jauh lebih kuat daripada JSON untuk tujuan memperbarui dokumen HTML menggunakan Ajax. JSON memang lucu, tetapi bagaimanapun umumnya hanya berguna untuk apa yang disebut "layanan web publik". Kerangka MVC seperti JSF menggunakan XML di bawah selimut untuk sihir ajax mereka.

Ajaxifikasi formulir yang ada

Anda dapat menggunakan jQuery $.serialize()untuk dengan mudah melakukan ajaxify formulir POST yang ada tanpa mengotak-atik pengumpulan dan melewati parameter input formulir individual. Dengan asumsi bentuk yang ada yang berfungsi dengan baik tanpa JavaScript / jQuery (dan karenanya terdegradasi dengan anggun ketika pengguna akhir JavaScript dinonaktifkan):

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

Anda dapat semakin meningkatkannya dengan ajax seperti di bawah ini:

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

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

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

Anda dapat di servlet membedakan antara permintaan normal dan permintaan ajax seperti di bawah ini:

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

The jQuery Form Plugin tidak kurang atau lebih sama seperti di atas jQuery contoh, tetapi memiliki dukungan transparan tambahan untuk multipart/form-databentuk seperti yang dipersyaratkan oleh file upload.

Secara manual mengirim parameter permintaan ke servlet

Jika Anda tidak memiliki formulir sama sekali, tetapi hanya ingin berinteraksi dengan servlet "di latar belakang" di mana Anda ingin POST beberapa data, maka Anda dapat menggunakan jQuery $.param()untuk dengan mudah mengkonversi objek JSON ke URL yang dikodekan. string kueri.

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

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

doPost()Metode yang sama seperti yang ditunjukkan di sini di atas dapat digunakan kembali. Perhatikan bahwa sintaks di atas juga berfungsi dengan $.get()di jQuery dan doGet()di servlet.

Mengirim objek JSON secara manual ke servlet

Namun, jika Anda berniat untuk mengirim objek JSON secara keseluruhan alih-alih sebagai parameter permintaan individu untuk beberapa alasan, maka Anda perlu membuat serialisasi ke string menggunakan JSON.stringify()(bukan bagian dari jQuery) dan menginstruksikan jQuery untuk mengatur tipe konten permintaan application/jsonsebagai gantinya dari (default) application/x-www-form-urlencoded. Ini tidak dapat dilakukan melalui $.post()fungsi kenyamanan, tetapi perlu dilakukan melalui $.ajax()seperti di bawah ini.

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

Apakah dicatat bahwa banyak pemula campuran contentTypedengan dataType. The contentTypemewakili tipe dari permintaan tubuh. The dataTypemewakili (diharapkan) tipe respon tubuh, yang biasanya tidak diperlukan sebagai jQuery sudah autodetects itu berdasarkan respon ini Content-Typesundulan.

Kemudian, untuk memproses objek JSON dalam servlet yang tidak dikirim sebagai parameter permintaan individu tetapi sebagai keseluruhan string JSON dengan cara di atas, Anda hanya perlu mengurai tubuh permintaan secara manual menggunakan alat JSON alih-alih menggunakan getParameter()yang biasa cara. Yakni, servlets tidak mendukung application/jsonpermintaan diformat, tetapi hanya application/x-www-form-urlencodedatau multipart/form-datapermintaan diformat. Gson juga mendukung parsing string JSON menjadi objek 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();
// ...

Perhatikan bahwa ini semua lebih canggung daripada hanya menggunakan $.param(). Biasanya, Anda hanya ingin menggunakan JSON.stringify()jika layanan target mis. Layanan JAX-RS (RESTful) yang karena alasan tertentu hanya mampu mengkonsumsi string JSON dan bukan parameter permintaan reguler.

Mengirim redirect dari servlet

Penting untuk disadari dan dipahami adalah bahwa siapa pun sendRedirect()dan forward()panggilan oleh servlet pada permintaan ajax hanya akan meneruskan atau mengarahkan permintaan ajax itu sendiri dan bukan dokumen / jendela utama tempat permintaan ajax berasal. JavaScript / jQuery dalam hal demikian hanya akan mengambil respons yang dialihkan / diteruskan sebagai responseTextvariabel dalam fungsi panggilan balik. Jika itu mewakili seluruh halaman HTML dan bukan respons XML atau JSON khusus ajax, maka yang dapat Anda lakukan hanyalah mengganti dokumen saat ini dengannya.

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

Perhatikan bahwa ini tidak mengubah URL seperti yang dilihat pengguna di bilah alamat browser. Jadi ada masalah dengan kemampuan bookmark. Oleh karena itu, jauh lebih baik untuk mengembalikan "instruksi" untuk JavaScript / jQuery untuk melakukan pengalihan alih-alih mengembalikan seluruh konten halaman yang diarahkan. Misalnya dengan mengembalikan boolean, atau 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;
    }

    // ...
}

Lihat juga:


perlu mengurai json pada contoh terakhir.
shinzou

4
@kuhaku: nggak. Jika Anda membaca posting dari atas ke bawah, Anda akan tahu alasannya.
BalusC

1
Jawaban ini telah menjadi urat nadi saya selama sebulan terakhir ini. Belajar banyak dari itu. Saya SUKA contoh XML. Terima kasih telah menyatukan ini! Satu pertanyaan noob sekalipun jika Anda punya waktu. Apakah ada alasan untuk meletakkan folder xml di WEB-INF?
Jonathan Laliberte

1
@ JonathanLaliberte: Jadi pengguna tidak dapat mengunduhnya.
BalusC

@ BalusC, contoh XML Anda hebat, terima kasih. Tetapi saya mendapatkan "Tidak dapat memperoleh properti 'ganti' dari referensi yang tidak ditentukan atau nol" untuk $("#somediv").html($(responseXml).find("data").html())baris ini. Itu juga mengatakan "Jumlah argumen salah atau penugasan properti tidak valid". Saya juga bisa melihat bahwa XML saya diisi dengan data ketika saya debug itu. Ada ide?
629

14

Cara yang tepat untuk memperbarui halaman yang saat ini ditampilkan di browser pengguna (tanpa memuat ulang) adalah dengan memiliki beberapa kode yang dieksekusi di browser memperbarui DOM halaman.

Kode itu biasanya javascript yang disematkan atau ditautkan dari halaman HTML, oleh karena itu saran AJAX. (Faktanya, jika kita mengasumsikan bahwa teks yang diperbarui berasal dari server melalui permintaan HTTP, ini adalah AJAX klasik.)

Dimungkinkan juga untuk mengimplementasikan hal semacam ini menggunakan beberapa plugin browser atau add-on, meskipun mungkin sulit bagi plugin untuk menjangkau ke dalam struktur data browser untuk memperbarui DOM. (Plugin kode asli biasanya menulis ke beberapa bingkai grafis yang tertanam di halaman.)


13

Saya akan menunjukkan kepada Anda seluruh contoh servlet & bagaimana panggilan ajax.

Di sini, kita akan membuat contoh sederhana untuk membuat formulir login menggunakan 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>  

Berikut adalah contoh ajax

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

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

7

Ajax (juga AJAX) singkatan dari Asynchronous JavaScript and XML) adalah sekelompok teknik pengembangan web yang saling terkait yang digunakan pada sisi klien untuk membuat aplikasi web asinkron. Dengan Ajax, aplikasi web dapat mengirim data ke, dan mengambil data dari, server asinkron Di bawah ini adalah contoh kode:

Fungsi skrip java halaman Jsp untuk mengirim data ke servlet dengan dua variabel firstName dan 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 untuk membaca data mengirim kembali ke jsp dalam format xml (Anda juga dapat menggunakan teks. Anda hanya perlu mengubah konten respons menjadi teks dan merender data pada fungsi 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>");
}

5

Biasanya Anda tidak dapat memperbarui halaman dari servlet. Klien (browser) harus meminta pembaruan. Klien Eiter memuat seluruh halaman baru atau meminta pembaruan ke bagian dari halaman yang ada. Teknik ini disebut Ajax.


4

Menggunakan bootstrap multi pilih

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

Dalam Servlet

request.getParameter("input")
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.