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.
String
Düz metin olarak dönen başlangıç örneği
/some.jsp
Aş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 /someservlet
veya /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 someservlet
JS 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.xml
eski 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/lib
klasö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ı responseJson
ve 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/plain
veya text/html
sonra responseJson
argü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>
Product
Long id
String name
BigDecimal 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-data
dosya 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/json
bunun 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 contentType
ile dataType
. contentType
Tipini temsil talep gövdesi. dataType
Ve (beklenen) tipini temsil yanıt jQuery zaten yanıtın göre bunu otomatik olarak tespit olarak genellikle gereksizdir vücut Content-Type
baş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/json
biçimlendirilmiş istekleri desteklemez , yalnızca application/x-www-form-urlencoded
veya multipart/form-data
biç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: