实际上,关键字是“Ajax”:异步 JavaScript 和 XML。然而,去年它比异步 JavaScript 和 JSON 更常见。基本上,您让 JavaScript 执行异步 HTTP 请求并根据响应数据更新 HTML DOM 树。
由于它在所有浏览器中都非常tedious work to make it to work(尤其是 Internet Explorer 与其他浏览器相比),因此有大量 JavaScript 库可以在单个函数中简化此操作,并涵盖尽可能多的浏览器特定错误/怪癖,例如 {2 },Prototype,Mootools。由于 jQuery 现在最流行,我将在下面的示例中使用它。
以纯文本形式返回字符串的启动示例
创建一个如下所示的 /some.jsp
(注意:此答案中的代码片段不希望将 JSP 文件放置在子文件夹中,如果这样做,请将 servlet URL 相应地从 "someservlet"
更改为 "${pageContext.request.contextPath}/someservlet"
;它只是被省略了为简洁起见,来自代码片段):
<!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()
方法创建一个 servlet:
@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.
}
将此 servlet 映射到 /someservlet
或 /someservlet/*
的 URL 模式,如下所示(显然,您可以自由选择 URL 模式,但您需要相应地更改 JS 代码示例中的 someservlet
URL) :
package com.example;
@WebServlet("/someservlet/*")
public class SomeServlet extends HttpServlet {
// ...
}
或者,当您还没有使用 Servlet 3.0 兼容容器(Tomcat 7、GlassFish 3、JBoss AS 6 等或更新版本)时,然后以 web.xml
老式方式映射它(另见our Servlets wiki page):
<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>
现在在浏览器中打开 http://localhost:8080/context/test.jsp 并按下按钮。您将看到 div 的内容随着 servlet 响应而更新。
以 JSON 形式返回 List
使用 JSON 而不是纯文本作为响应格式,您甚至可以更进一步。它允许更多的动态。首先,您需要一个工具来在 Java 对象和 JSON 字符串之间进行转换。它们也有很多(请参阅 this page 底部的概述)。我个人最喜欢的是Google Gson。下载其 JAR 文件并将其放在您的 Web 应用程序的 /WEB-INF/lib
文件夹中。
这是一个将 List<String>
显示为 <ul><li>
的示例。小服务程序:
@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);
}
JavaScript 代码:
$(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>.
});
});
});
请注意,当您将响应内容类型设置为 application/json
时,jQuery 会自动将响应解析为 JSON,并直接为您提供 JSON 对象 (responseJson
) 作为函数参数。如果您忘记设置它或依赖 text/plain
或 text/html
的默认值,那么 responseJson
参数不会给您一个 JSON 对象,而是一个普通的香草字符串,您需要手动摆弄JSON.parse()
之后,如果您首先正确设置内容类型,则完全没有必要这样做。
以 JSON 形式返回 Map
下面是另一个将 Map<String, String>
显示为 <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);
}
和 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>.
});
});
});
和
<select id="someselect"></select>
以 JSON 形式返回 List
这是在 <table>
中显示 List<Product>
的示例,其中 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代码:
$(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>.
});
});
});
以 XML 形式返回 List
这是一个与前面的示例有效相同的示例,但使用 XML 而不是 JSON。当使用 JSP 作为 XML 输出生成器时,您会发现对表格和所有内容进行编码变得不那么乏味了。 JSTL 这种方式更有帮助,因为您实际上可以使用它来迭代结果并执行服务器端数据格式化。小服务程序:
@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 代码(注意:如果您将 <table>
放在 <jsp:include>
中,它可能可以在非 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>
JavaScript 代码:
$(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".
});
});
您现在可能会意识到为什么在使用 Ajax 更新 HTML 文档的特定目的方面,XML 比 JSON 强大得多。 JSON 很有趣,但毕竟一般只对所谓的“公共网络服务”有用。像 JSF 这样的 MVC 框架使用 XML 来实现它们的 ajax 魔法。
Ajaxifying 现有表单
您可以使用 jQuery $.serialize()
轻松地 ajaxify 现有的 POST 表单,而无需摆弄收集和传递单个表单输入参数。假设一个现有的表单在没有 JavaScript/jQuery 的情况下工作得很好(因此当最终用户禁用 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>
您可以使用 Ajax 逐步增强它,如下所示:
$(document).on("submit", "#someform", function(event) {
var $form = $(this);
$.post($form.attr("action"), $form.serialize(), function(response) {
// ...
});
event.preventDefault(); // Important! Prevents submitting the form.
});
您可以在 servlet 中区分普通请求和 Ajax 请求,如下所示:
@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 plugin 与上面的 jQuery 示例大致相同,但它对文件上传所需的 multipart/form-data
表单提供了额外的透明支持。
手动向 servlet 发送请求参数
如果您根本没有表单,而只是想与“在后台”的 servlet 交互,您想发布一些数据,那么您可以使用 jQuery $.param()
轻松地将 JSON 对象转换为URL 编码的查询字符串。
var params = {
foo: "fooValue",
bar: "barValue",
baz: "bazValue"
};
$.post("someservlet", $.param(params), function(response) {
// ...
});
可以重复使用上面显示的相同 doPost()
方法。请注意,上述语法也适用于 jQuery 中的 $.get()
和 servlet 中的 doGet()
。
手动将 JSON 对象发送到 servlet
但是,如果您出于某种原因打算将 JSON 对象作为一个整体而不是作为单个请求参数发送,那么您需要使用 JSON.stringify()
(不是 jQuery 的一部分)将其序列化为字符串并指示 jQuery 设置请求内容键入 application/json
而不是(默认)application/x-www-form-urlencoded
。这不能通过 $.post()
便利功能完成,但需要通过 $.ajax()
完成,如下所示。
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) {
// ...
}
});
请注意,许多初学者将 contentType
与 dataType
混合使用。 contentType
表示 request 正文的类型。 dataType
表示 response 主体的(预期)类型,这通常是不必要的,因为 jQuery 已经根据响应的 Content-Type
标头自动检测它。
然后,为了处理 servlet 中的 JSON 对象,它不是作为单独的请求参数发送,而是作为整个 JSON 字符串以上述方式发送,您只需要使用 JSON 工具手动解析请求正文,而不是使用 {1 } 通常的方式。也就是说,servlet 不支持 application/json
格式的请求,而只支持 application/x-www-form-urlencoded
或 multipart/form-data
格式的请求。 Gson 还支持将 JSON 字符串解析为 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();
// ...
请注意,这一切都比仅使用 $.param()
更笨拙。通常,只有当目标服务是例如 JAX-RS (RESTful) 服务时,您才希望使用 JSON.stringify()
,该服务由于某种原因只能使用 JSON 字符串而不是常规请求参数。
从 servlet 发送重定向
需要意识到和理解的重要一点是,servlet 对 ajax 请求的任何 sendRedirect()
和 forward()
调用只会转发或重定向 Ajax 请求本身,而不是 Ajax 请求所在的主文档/窗口起源。在这种情况下,JavaScript/jQuery 将仅检索重定向/转发的响应作为回调函数中的 responseText
变量。如果它代表整个 HTML 页面而不是 Ajax 特定的 XML 或 JSON 响应,那么您所能做的就是用它替换当前文档。
document.open();
document.write(responseText);
document.close();
请注意,这不会更改最终用户在浏览器地址栏中看到的 URL。因此,可收藏性存在问题。因此,最好只返回一个“指令”让 JavaScript/jQuery 执行重定向,而不是返回重定向页面的全部内容。例如,通过返回布尔值或 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;
}
// ...
}
也可以看看:
调用 Servlet 并从 JavaScript 调用 Java 代码以及参数
在 JavaScript 中访问 Java / Servlet / JSP / JSTL / EL 变量
如何在基于 Ajax 的网站和基本的 HTML 网站之间轻松切换?
如何使用 JSP/Servlet 和 Ajax 将文件上传到服务器?
更新当前显示在用户浏览器中的页面(无需重新加载)的正确方法是让浏览器中执行的一些代码更新页面的 DOM。
该代码通常是嵌入或链接自 HTML 页面的 JavaScript,因此是 Ajax 建议。 (事实上,如果我们假设更新的文本通过 HTTP 请求来自服务器,这就是经典的 Ajax。)
也可以使用一些浏览器插件或附加组件来实现这种事情,尽管插件进入浏览器的数据结构以更新 DOM 可能很棘手。 (本机代码插件通常会写入页面中嵌入的某些图形框架。)
我将向您展示一个 servlet 的完整示例以及如何进行 Ajax 调用。
在这里,我们将创建一个简单的示例来使用 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>
Ajax 示例
$.ajax
({
type: "POST",
data: 'LoginServlet=' + name + '&name=' + type + '&pass=' + password,
url: url,
success:function(content)
{
$('#center').html(content);
}
});
LoginServlet servlet 代码:
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);
}
}
}
$.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);
}
});
Ajax(也称为 AJAX)是异步 JavaScript 和 XML 的首字母缩写词,是一组相互关联的 Web 开发技术,用于在客户端创建异步 Web 应用程序。使用 Ajax,Web 应用程序可以异步地向服务器发送数据和从服务器检索数据。
下面是示例代码:
一个 JSP 页面 JavaScript 函数,用于将数据提交给带有两个变量 firstName 和 lastName 的 servlet:
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 读取以 XML 格式发送回 JSP 的数据(您也可以使用文本。您只需将响应内容更改为文本并在 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>");
}
通常您不能从 servlet 更新页面。客户端(浏览器)必须请求更新。客户端要么加载一个全新的页面,要么请求更新现有页面的一部分。这种技术称为 Ajax。
使用 Bootstrap 多选:
阿贾克斯
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 中
request.getParameter("input")
$("#somediv").html($(responseXml).find("data").html())
这一行的“无法获取未定义或空引用的属性'替换'”。它还说“参数数量错误或属性分配无效”。当我调试它时,我还可以看到我的 XML 填充了数据。有任何想法吗 ?