gpt4 book ai didi

java - 如何使用Servlet和Ajax?

转载 作者:行者123 更新时间:2023-11-29 21:02:31 25 4
gpt4 key购买 nike

我是Web应用程序和Servlet的新手,我有以下问题:

每当我在Servlet中打印某些内容并由网络浏览器调用它时,它都会返回一个包含该文本的新页面。有没有一种方法可以使用Ajax在当前页面中打印文本?

最佳答案

实际上,关键字是“ ajax”:异步JavaScript和XML。但是,近年来,它比异步JavaScript和JSON更为常见。基本上,让JS执行异步HTTP请求并根据响应数据更新HTML DOM树。

由于要使其在所有浏览器(尤其是Internet Explorer与其他浏览器)上都能正常工作,因此有很多JavaScript库可以简化单个功能,并涵盖了尽可能多的特定于浏览器的错误/怪癖。引擎盖,例如tediousjQueryPrototype。由于jQuery目前最流行,因此我将在以下示例中使用它。

启动示例以纯文本形式返回String

创建如下所示的/some.jsp(注意:该代码不希望将JSP文件放置在子文件夹中,如果这样做,请相应地更改servlet URL):

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

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


或者,如果您还没有使用与Servlet 3.0兼容的容器(Tomcat 7,Glassfish 3,JBoss AS 6等,或更新的容器),请以 web.xml老式的方式进行映射(另请参见 Mootools):

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


现在,在浏览器中打开 our Servlets wiki page并按按钮。您将看到div的内容随servlet响应一起更新。

返回 List<String>作为JSON

使用 http://localhost:8080/context/test.jsp而不是纯文本作为响应格式,您甚至可以进一步采取一些措施。它允许更多的动态。首先,您想要一个工具来在Java对象和JSON字符串之间进行转换。也有很多(有关概述,请参见 JSON的底部)。我个人最喜欢的是 this page。下载其JAR文件并将其放在Web应用程序的 /WEB-INF/lib文件夹中。

这是一个将 List<String>显示为 <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代码:

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


请注意,当您将响应内容类型设置为 responseJson时,jQuery会自动将响应解析为JSON,并直接为您提供JSON对象( application/json)作为函数参数。如果您忘记设置它或依靠默认的 text/plaintext/html,则 responseJson参数将不会为您提供JSON对象,而是一个普通的香草字符串,您需要手动操作之后是 Google Gson,因此,如果首先将内容类型设置为正确,则完全没有必要。

返回 JSON.parse()作为JSON

这是另一个将 Map<String, String>显示为 Map<String, String>的示例:

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


返回 <option>作为JSON

这是一个在 List<Entity>中显示 List<Product>的示例,其中 <table>类具有属性 ProductLong idString name。 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);
}


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


BigDecimal price返回为XML

这是一个与上一个示例实际上有效的示例,但是使用XML而不是JSON。当使用JSP作为XML输出生成器时,您会发现对表和所有代码进行编码都比较麻烦。 JSTL如此有用,因为您可以实际使用它来遍历结果并执行服务器端数据格式化。 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代码(请注意:如果将 List<Entity>放在 <table>中,则它可以在非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>


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


您现在可能已经意识到,出于使用Ajax更新HTML文档的特定目的,为什么XML比JSON强大得多。 JSON很有趣,但毕竟通常只对所谓的“公共Web服务”有用。像 <jsp:include>这样的MVC框架在其ajax魔术的底层使用XML。

合并现有表格

您可以使用jQuery JSF轻松地将现有的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.
}
}


$.serialize()的功能与上面的jQuery示例差不多,但它具有文件上传所需的对 multipart/form-data表单的额外透明支持。

手动将请求参数发送到servlet

如果您根本没有表单,而只想与“后台”与servlet交互,从而希望发布一些数据,则可以使用jQuery jQuery Form plugin轻松地将JSON对象转换为URL编码的查询字符串。

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

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


可以重复使用与上述相同的 $.param()方法。请注意,以上语法也可用于jQuery中的 doPost()和servlet中的 $.get()

手动将JSON对象发送到servlet

但是,如果出于某种原因打算将JSON对象作为一个整体而不是作为单个请求参数发送,则需要使用 doGet()(不是jQuery的一部分)将其序列化为字符串,并指示jQuery设置请求内容键入 JSON.stringify()代替(默认) application/json。这不能通过 application/x-www-form-urlencoded便捷功能来完成,但是需要通过 $.post()来完成,如下所示。

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


请注意,许多启动器将 $.ajax()contentType混合在一起。 dataType代表请求正文的类型。 contentType代表响应主体的(预期)类型,通常是不必要的,因为jQuery已经基于响应的 dataType标头自动检测到它。

然后,为了以上述方式处理不是作为单独的请求参数而是作为整个JSON字符串发送的Servlet中的JSON对象,您只需要使用JSON工具而不是使用 通常的方式。即,servlet不支持 Content-Type格式的请求,而仅支持 getParameter()application/json格式的请求。 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();
// ...


请注意,这比仅使用 application/x-www-form-urlencoded更笨拙。通常,仅当目标服务是例如一个JAX-RS(RESTful)服务,由于某种原因,该服务只能使用JSON字符串,而不能使用常规请求参数。

从Servlet发送重定向

认识和理解的重要之处在于,servlet对ajax请求的任何 multipart/form-data$.param()调用都只会转发或重定向ajax请求本身,而不转发或重定向ajax请求产生的主文档/窗口。在这种情况下,JavaScript / jQuery仅在回调函数中以 JSON.stringify()变量的形式检索重定向/转发的响应。如果它代表整个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;
}

// ...
}


也可以看看:


sendRedirect()
Call Servlet and invoke Java code from JavaScript along with parameters
Access Java / Servlet / JSP / JSTL / EL variables in JavaScript
How to switch easily between ajax-based website and basic HTML website?

关于java - 如何使用Servlet和Ajax?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37091826/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com