如何使用Servlets和Ajax?
我对web应用程序和Servlet非常陌生,我有以下问题:
每当我在servlet内部打印一些内容并由webbrowser调用时,它会返回一个包含该文本的新页面。 有没有办法使用Ajax打印当前页面中的文本?
的确,关键字是“ajax”:异步JavaScript和XML。 然而,去年它不止是Asynchronous JavaScript和JSON。 基本上,你让JS执行一个异步HTTP请求,并基于响应数据更新HTML DOM树。
由于在所有浏览器(特别是Internet Explorer与其他浏览器)中工作都非常繁琐,因此有大量JavaScript库可以简化单个功能,并涵盖尽可能多的浏览器特定错误/怪癖。 ,比如jQuery,Prototype,Mootools。 由于jQuery现在最流行,我将在下面的例子中使用它。
Kickoff示例以纯文本形式返回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
中(请参阅我们的Servlets wiki页面):
<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响应更新。
将List<String>
作为JSON返回
使用JSON而不是明文作为响应格式,您甚至可以进一步获得一些步骤。 它允许更多的动态。 首先,你想有一个工具来转换Java对象和JSON字符串。 其中也有很多(参见本页底部的概述)。 我个人最喜欢的是Google Gson。 下载并将其JAR文件放入您的/WEB-INF/lib
程序的/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>.
});
});
});
请注意,jQuery自动将响应解析为JSON,并在将响应内容类型设置为application/json
时,直接为您提供JSON对象( responseJson
)作为函数参数。 如果你忘记设置它或者依赖默认的text/plain
或者text/html
,那么responseJson
参数不会给你一个JSON对象,而是一个普通的香草串,你需要用JSON.parse()
手动摆弄JSON.parse()
,因此如果您将内容类型设置在第一位,则完全不必要。
将Map<String, String>
返回为JSON
这是另一个将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>
将List<Entity>
作为JSON返回
下面是一个示例,其中显示了List<Product>
中的Product
类具有属性Long id
, String name
和BigDecimal price
的<table>
。 该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>.
});
});
});
将List<Entity>
作为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代码(注意:如果将<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>
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服务”有用。 像JSF这样的MVC框架使用XML作为其Ajax魔术的封面。
使现有表单Ajax化
您可以使用jQuery $.serialize()
轻松地对现有的POST表单进行Ajax化,而不必在收集和传递单个表单输入参数时进行调整。 假设没有JavaScript / jQuery的现有表单可以很好地工作(并且在enduser禁用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插件与上面的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的一部分JSON.stringify()
将它序列化为一个字符串,并指示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
表示请求主体的类型。 dataType
表示响应正文的(预期)类型,通常这是不必要的,因为jQuery已经基于响应的Content-Type
头自动检测它。
然后,为了处理servlet中的JSON对象,该对象不是作为单独的请求参数发送,而是作为整体JSON字符串以上述方式进行处理,您只需使用JSON工具手动解析请求主体,而不是使用getParameter()
通常的方式。 也就是说,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;
}
// ...
}
也可以看看:
更新当前在用户浏览器中显示的页面的正确方法(不重新加载)是让浏览器中的一些代码更新页面的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);
}
}
}
链接地址: http://www.djcxy.com/p/8039.html