Servlets ve Ajax nasıl kullanılır?


334

Web uygulamaları ve Servlet'lerde çok yeniyim ve şu sorum var:

Sunucu uygulamasının içine bir şey yazdırıp webbrowser tarafından çağırdığımda, o metni içeren yeni bir sayfa döndürür. Ajax kullanarak geçerli sayfadaki metni yazdırmanın bir yolu var mı?

Yanıtlar:


561

Gerçekten de, anahtar kelime "ajax": Eşzamansız JavaScript ve XML . Ancak, geçen yıllarda bu genellikle Asenkron JavaScript ve JSON'dan daha fazladır . Temel olarak, JS'nin eşzamansız bir HTTP isteği yürütmesine ve yanıt verisine dayanarak HTML DOM ağacını güncellemesine izin verirsiniz.

Tüm tarayıcılarda (özellikle Internet Explorer'ın diğerlerine karşı) çalışmasını sağlamak oldukça sıkıcı bir çalışma olduğundan, bunu tek işlevlerde basitleştiren ve başlıkların altındaki tarayıcıya özgü hataları / tuhaflıkları olabildiğince kapsayan birçok JavaScript kitaplığı vardır. gibi jQuery , Prototip , Mootools . JQuery bu günlerde en popüler olduğu için, aşağıdaki örneklerde kullanacağım.

StringDüz metin olarak dönen başlangıç ​​örneği

/some.jspAşağıdakine benzer bir not oluşturun (not: kod, JSP dosyasının bir alt klasöre yerleştirilmesini beklemez, bunu yaparsanız sunucu uygulaması URL'sini uygun şekilde değiştirin):

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

doGet()Şuna benzeyen bir yöntemle sunucu uygulaması oluşturun :

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

Bu sunucu uygulamasını aşağıdaki gibi /someservletveya /someservlet/*aşağıdaki gibi bir URL kalıbıyla eşleştirin (açıkçası, URL kalıbı seçiminiz için ücretsizdir, ancak someservletJS kodu örneklerindeki URL'yi her yere göre değiştirmeniz gerekir ):

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

Veya henüz Servlet 3.0 uyumlu bir kapta değilseniz (Tomcat 7, Glassfish 3, JBoss AS 6, vb. Veya daha yeni), web.xmleski moda şekilde eşleyin (ayrıca Servlets wiki sayfamıza bakın ):

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

Şimdi tarayıcıda http: // localhost: 8080 / context / test.jsp dosyasını açın ve düğmesine basın. Div içeriğinin sunucu uygulaması yanıtıyla güncellendiğini göreceksiniz.

Geri dönen List<String>JSON olarak

Yanıt biçimi olarak düz metin yerine JSON ile bazı adımlar daha da ileri gidebilirsiniz. Daha fazla dinamiğe izin verir. İlk olarak, Java nesneleri ve JSON dizeleri arasında dönüştürme yapmak için bir araca sahip olmak istersiniz. Bunların birçoğu da var ( genel bakış için bu sayfanın altına bakın ). Kişisel favorim Google Gson . JAR dosyasını indirin ve web uygulamanızın /WEB-INF/libklasörüne yerleştirin.

İşte List<String>olarak görüntülenen bir örnek <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);
}

JS kodu:

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

JQuery'nin yanıtı otomatik olarak JSON olarak ayrıştırdığını responseJsonve yanıt içeriği türünü ayarladığınızda size doğrudan işlev argümanı olarak bir JSON nesnesi ( ) verdiğini unutmayın application/json. Eğer unutursanız ayarlayın veya varsayılan güvenmek text/plainveya text/htmlsonra responseJsonargüman size bir JSON nesnesi, ancak düz vanilya dize vermezdim ve manuel keman civarını gerekiyordu JSON.parse()böylece eğer tamamen gereksiz olan sonradan içerik türünü ilk etapta ayarlayın.

Geri dönen Map<String, String>JSON olarak

İşte hangi görüntüler başka bir örnek Map<String, String>olarak <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);
}

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

ile

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

Geri dönen List<Entity>JSON olarak

İşte görüntüler bir örnek List<Product>bir yer sınıf özellikleri vardır , ve . Servlet:<table>ProductLong idString nameBigDecimal price

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

JS kodu:

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

List<Entity>XML olarak döndürme

Önceki örnekle aynı şekilde etkili olan ancak JSON yerine XML ile bir örnek. JSP'yi XML çıkış oluşturucusu olarak kullanırken, tabloyu ve tümünü kodlamanın daha az sıkıcı olduğunu göreceksiniz. JSTL, sonuçlar üzerinde yineleme yapmak ve sunucu tarafı veri biçimlendirmesi yapmak için kullanabileceğiniz için bu şekilde çok daha yararlıdır. 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);
}

JSP kodu (not: içine <table>a koyarsanız, <jsp:include>ajax olmayan bir yanıtta başka bir yerde yeniden kullanılabilir):

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

JS kodu:

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

Artık muhtemelen bir HTML belgesini Ajax kullanarak güncellemek için XML'in neden JSON'dan çok daha güçlü olduğunu anlayacaksınız. JSON komiktir, ancak sonuçta sadece "genel web servisleri" için kullanışlıdır. JSF gibi MVC çerçeveleri , ajax sihirleri için kapakların altında XML kullanır.

Mevcut bir formun ajanslaştırılması

Tek $.serialize()tek form giriş parametrelerini toplama ve iletme ile mevcut POST formlarını kolayca çözmek için jQuery'yi kullanabilirsiniz . JavaScript / jQuery olmadan mükemmel çalışan mevcut bir form olduğunu varsayarsak (ve böylece enduser JavaScript devre dışı bırakıldığında zarif bir şekilde bozulur):

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

Aşağıdaki gibi ajax ile aşamalı olarak geliştirebilirsiniz:

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

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

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

Sunucu uygulamasında normal istekleri ve ajax isteklerini aşağıdaki gibi ayırt edebilirsiniz:

@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 Form eklentisi az veya jQuery Örneğin yukarıdaki gibi daha aynısını yapar, ancak ek şeffaf desteği vardır multipart/form-datadosya yüklemeleri gerektirdiği gibi formlar.

İstek parametrelerini sunucu uygulamasına el ile gönderme

Hiç bir formunuz yoksa, ancak yalnızca bazı verileri POST yapmak istediğiniz "arka planda" sunucu uygulamasıyla etkileşim kurmak istiyorsanız, $.param()bir JSON nesnesini kolayca URL kodlu bir hale dönüştürmek için jQuery kullanabilirsiniz sorgu dizesi.

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

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

doPost()Yukarıda gösterilenle aynı yöntem tekrar kullanılabilir. Yukarıdaki sözdiziminin $.get()jQuery ve doGet()sunucu uygulamasında da çalıştığını unutmayın .

JSON nesnesini sunucu uygulamasına el ile gönderme

Bununla birlikte, JSON nesnesini herhangi bir nedenle bireysel istek parametreleri yerine bir bütün olarak göndermek istiyorsanız, JSON.stringify()(jQuery'nin bir parçası değil) kullanarak bir dizeye serileştirmeniz ve application/jsonbunun yerine jQuery'ye istek içeriği türünü ayarlamasını bildirmeniz gerekir. / (varsayılan) application/x-www-form-urlencoded. Bu $.post()kolaylık işlevi ile yapılamaz , ancak $.ajax()aşağıdaki gibi yapılması gerekir .

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

Yeni başlayanlar bir sürü karıştırmak o notu Do contentTypeile dataType. contentTypeTipini temsil talep gövdesi. dataTypeVe (beklenen) tipini temsil yanıt jQuery zaten yanıtın göre bunu otomatik olarak tespit olarak genellikle gereksizdir vücut Content-Typebaşlığı.

Daha sonra, ayrı ayrı istek parametreleri olarak değil, bir bütün JSON dizesi olarak yukarıdaki yolla gönderilmeyen sunucu uygulamasındaki JSON nesnesini işlemek için, istek gövdesini getParameter(), normalde kullanmak yerine yalnızca bir JSON aracı kullanarak ayrıştırmanız gerekir. yol. Yani, sunucu uygulamaları application/jsonbiçimlendirilmiş istekleri desteklemez , yalnızca application/x-www-form-urlencodedveya multipart/form-databiçimlendirilmiş istekleri destekler. Gson ayrıca bir JSON dizesini bir JSON nesnesine ayrıştırmayı da destekler.

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

Tüm bunların sadece kullanmaktan daha beceriksiz olduğunu unutmayın $.param(). Normalde, JSON.stringify()yalnızca hedef hizmet, örneğin, belirli istek parametrelerini değil, yalnızca JSON dizelerini tüketebilen bir JAX-RS (RESTful) hizmeti ise kullanmak istersiniz .

Sunucu uygulamasından yönlendirme gönderme

Gerçekleştirilmesi ve anlaşılması önemli olan, ajax isteği üzerine sunucu uygulaması tarafından yapılan herhangi bir çağrı sendRedirect()ve forward()çağrı , ajax isteğinin kaynağı olan ana belge / pencereyi değil, yalnızca ajax isteğinin kendisini yönlendirir veya yönlendirir . JavaScript / jQuery bu durumda, yalnızca geri responseTextçağrı işlevinde değişken olarak yönlendirilen / yönlendirilen yanıtı alır . Bir ajax'a özgü XML veya JSON yanıtı değil, tam bir HTML sayfasını temsil ediyorsa, yapabileceğiniz tek şey geçerli belgeyi onunla değiştirmek.

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

Bu, URL'nin tarayıcının adres çubuğunda gördüğü gibi URL'yi değiştirmediğini unutmayın. Yer imi ile ilgili sorunlar var. Bu nedenle, yeniden yönlendirilen sayfanın tüm içeriğini döndürmek yerine JavaScript / jQuery için bir yönlendirme gerçekleştirmesi için bir "talimat" döndürmek çok daha iyidir. Örneğin, bir boole veya URL döndürerek.

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

    // ...
}

Ayrıca bakınız:


son örnek üzerinde json ayrıştırılması gerekir.
shinzou

4
@kuhaku: hayır. Gönderiyi yukarıdan aşağıya okursanız, nedenini öğreneceksiniz.
BalusC

1
Bu cevap geçen ay ya da öylesine lol benim hayatım oldu. Ondan bir grup öğrenme. XML örneğini seviyorum. Bunu bir araya getirdiğiniz için teşekkürler! Zamanınız varsa bir noob soru olsa. Xml klasörünü WEB-INF içine koymanın bir nedeni var mı?
Jonathan Laliberte

1
@JonathanLaliberte: Kullanıcılar bunları indiremez.
BalusC

@BalusC, XML örneğiniz harika, teşekkür ederim. Ama $("#somediv").html($(responseXml).find("data").html())bu satır için "undefined veya null referansın" replace "özelliği alınamıyor . Ayrıca "Yanlış sayıda argüman veya geçersiz mülk ataması" yazıyor. Hata ayıkladığımda XML'imin verilerle doldurulduğunu da görebiliyorum. Herhangi bir fikir ?
629

14

Kullanıcının tarayıcısında görüntülenmekte olan sayfayı güncellemenin doğru yolu (yeniden yüklemeden) tarayıcıda bazı kodların sayfanın DOM'sini güncellemesini sağlamaktır.

Bu kod genellikle HTML sayfasına gömülü veya HTML sayfasından bağlanan javascript'tir, dolayısıyla AJAX önerisidir. (Aslında, güncellenen metnin bir HTTP isteği yoluyla sunucudan geldiğini varsayarsak, bu klasik AJAX'tır.)

Bir tarayıcı eklentisi veya eklentisi kullanarak bu tür bir şey uygulamak da mümkündür, ancak bir eklentinin DOM'u güncellemek için tarayıcının veri yapılarına ulaşması zor olabilir. (Yerel kod eklentileri normalde sayfaya gömülü bazı grafik çerçevelerine yazılır.)


13

Size sunucu uygulamasının bütün bir örneğini ve ajax'ın nasıl çağırdığını göstereceğim.

Burada, servlet kullanarak giriş formu oluşturmak için basit bir örnek oluşturacağız.

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>  

İşte ajax örneği

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

LoginServlet Sunucu Uygulaması Kodu: -

    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 (ayrıca AJAX), Eşzamansız JavaScript ve XML için bir kısaltma), eşzamansız web uygulamaları oluşturmak için istemci tarafında kullanılan birbiriyle ilişkili web geliştirme tekniklerinden oluşan bir gruptur. Ajax ile web uygulamaları bir sunucuya eşzamansız olarak veri gönderebilir ve bu sunucudan veri alabilir Aşağıda örnek kod verilmiştir:

Firstname ve lastName değişkenleri ile sunucuya veri göndermek için jsp page java script fonksiyonu:

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

    }

Veri okumak için sunucu uygulaması jsp'ye xml formatında geri gönderilir (Metin de kullanabilirsiniz. Yanıt içeriğini metne değiştirmeniz ve javascript işlevinde veri oluşturmanız yeterlidir.)

/**
 * @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

Normalde bir sunucu uygulamasından bir sayfayı güncelleyemezsiniz. İstemci (tarayıcı) bir güncelleme istemelidir. Eiter istemcisi tamamen yeni bir sayfa yükler veya mevcut bir sayfanın bir kısmının güncellenmesini ister. Bu tekniğe Ajax adı verilir.


4

Bootstrap multi select kullanma

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

Servlet'te

request.getParameter("input")
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.