[解決済み] サーブレットとAjaxはどのように使い分ければよいのですか?
質問
サーブレット内で何かを印刷し、それをウェブブラウザで呼び出すと、必ずそのテキストを含む新しいページが返されます。Ajaxを使用して、現在のページにテキストを印刷する方法はありますか?
<サブ 私はウェブアプリケーションとサーブレットについて非常に初心者です。
どのように解決するのですか?
確かに、キーワードは「Ajax」ですね。 非同期JavaScriptおよびXML . しかし、昨年はもっと頻繁に 非同期JavaScriptとJSON . 基本的には、JavaScriptに非同期のHTTPリクエストを実行させ、そのレスポンスデータに基づいてHTMLのDOMツリーを更新します。
かなり を動作させるのは面倒な作業です。 すべてのブラウザ (特に Internet Explorer とそれ以外) にまたがって、これを単一の関数で単純化し、ブラウザ固有のバグやクラックを可能な限りカバーする JavaScript ライブラリがたくさん出ています。 jQuery , プロトタイプ , ムートゥール . 最近はjQueryが人気なので、以下の例ではjQueryを使っています。
キックオフのリターン例
String
プレーンテキストとして
を作成します。
/some.jsp
以下のように(注:この回答のコードスニペットは、JSPファイルがサブフォルダに配置されることを想定していません。
"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()
メソッドは次のようなものです。
@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.
}
のURLパターンでこのサーブレットをマッピングします。
/someservlet
または
/someservlet/*
を変更する必要があります。
someservlet
のURLは、それに応じて、すべての場所のJSコードの例で)。
package com.example;
@WebServlet("/someservlet/*")
public class SomeServlet extends HttpServlet {
// ...
}
また、その際に
サーブレット
3.0 互換コンテナ (
トムキャット
7,
GlassFish
3,
JBoss
AS 6 などの新しいバージョン) にマッピングし、それを
web.xml
は、昔ながらの方法です。
サーブレットウィキのページ
):
<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の内容が更新されるのがわかると思います。
戻る
List<String>
JSONとして
と
JSON
レスポンスフォーマットとしてプレーンテキストではなく、さらに一歩進んだものを使用することができます。よりダイナミックな動きが可能になるのです。まず、JavaオブジェクトとJSON文字列の間で変換するツールが欲しいところです。それらもたくさんあります(
このページ
をご覧ください。) 個人的に気に入っているのは
グーグルGson
. ダウンロードし、そのJARファイルを
/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>.
});
});
});
jQuery は自動的にレスポンスを JSON として解析し、直接 JSON オブジェクト (
responseJson
を指定した場合は、関数の引数として
application/json
. この設定を忘れたり、デフォルトの
text/plain
または
text/html
を指定した場合、その後に
responseJson
の引数はJSONオブジェクトではなく、単なる文字列を与えるので、手動で
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>
の中に
<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のコードです。
$(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として
前の例と実質的に同じですが、JSONの代わりにXMLを使用した例を示します。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は面白いですが、結局のところ、一般的にいわゆる「公開Webサービス」に対してのみ有用です。MVCフレームワークのような JSF は、AjaxマジックのためにXMLを隠蔽して使用しています。
既存のフォームをAjax化する
jQueryを使用することができます。
$.serialize()
を使えば、個々のフォーム入力パラメータの収集や受け渡しに煩わされることなく、既存のPOSTフォームを簡単にajax化することができます。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.
});
サーブレットでは、通常のリクエストと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
フォームを使用することができます。
サーブレットにリクエストパラメータを手動で送信する
フォームがなく、サーブレットとバックグラウンドで対話し、データを POST したい場合は、jQuery を使用することができます。
$.param()
を使用すると、JSONオブジェクトをURLエンコードされたクエリ文字列に簡単に変換することができます。
var params = {
foo: "fooValue",
bar: "barValue",
baz: "bazValue"
};
$.post("someservlet", $.param(params), function(response) {
// ...
});
同じく
doPost()
メソッドを再利用することができます。上記の構文は
$.get()
はjQueryで
doGet()
をサーブレットで使用します。
サーブレットにJSONオブジェクトを手動で送信する
しかし、何らかの理由で個々のリクエストパラメータとしてではなく、全体としてJSONオブジェクトを送信するつもりであるなら、それを
JSON.stringify()
(jQueryの一部ではありません)、jQueryにリクエストのcontent typeを
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
の(予想される)タイプを表します。
応答
ボディを自動検出するため、通常は不要です。
Content-Type
ヘッダを作成します。
そして、個々のリクエストパラメータとしてではなく、上記の方法で全体のJSON文字列として送信されたサーブレット内のJSONオブジェクトを処理するためには、JSONツールを使ってリクエストボディを手動でパースするだけでよく、その代わりに
getParameter()
は、通常の方法です。すなわち、サーブレットは
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()
. 通常は
JSON.stringify()
は、ターゲットサービスが JAX-RS (RESTful) サービスであり、何らかの理由で通常のリクエストパラメータではなく JSON 文字列のみを消費することができる場合にのみ使用します。
サーブレットからリダイレクトを送信する
重要なことは、すべての
sendRedirect()
と
forward()
は、ajax リクエストに対してサーブレットが呼び出すと、転送またはリダイレクトされるだけです。
Ajaxリクエストそのもの
であり、Ajaxリクエストが発生したメインドキュメント/ウィンドウではありません。JavaScript/jQueryはこのような場合、リダイレクトされた/転送されたレスポンスを
responseText
をコールバック関数内で使用することができます。もしそれがAjax特有のXMLやJSONレスポンスではなく、HTMLページ全体を表しているなら、あなたができることは現在のドキュメントをそれに置き換えることだけです。
document.open();
document.write(responseText);
document.close();
これは、エンドユーザーがブラウザのアドレスバーに表示されるURLを変更するものではないことに注意してください。そのため、ブックマーク性に問題がある。したがって、リダイレクト先のページの内容をすべて返すのではなく、JavaScript/jQueryにリダイレクトを実行させるための命令("instruction")を返すだけの方がずっとよいでしょう。例えば、ブール値を返すとか、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;
}
// ...
}
こちらもご覧ください。
関連
-
javax.net.ssl.SSLException: 読み取りエラー: ssl=0xdeae5100: システムコール中の I/O エラー、接続 res
-
コミットには何も追加されないが、未追跡のファイルが存在し、gitで未追跡のファイルに対する完璧な解決策
-
[解決済み] serialVersionUIDとは何ですか、またなぜそれを使用する必要がありますか?
-
[解決済み] Microsoft JSONの日付はどのようにフォーマットするのですか?
-
[解決済み] jQuery Ajax呼び出し後のリダイレクトリクエストを管理する方法
-
[解決済み] jQuery AJAX送信フォーム
-
[解決済み] divの一番下までスクロールしますか?
-
[解決済み】Android UserManager.isUserAGoat()の正しい使用例?)
-
[解決済み】JSP 2を使用して、JSPファイル内のJavaコードを回避するにはどうすればよいですか?
-
[解決済み】サーブレットはどのように動作するのですか?インスタンス化、セッション、共有変数とマルチスレッド
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
springboot project MIMEタイプ text/htmlで転送された静的ファイルを読み込む。
-
[解決済み] javascriptからjavaサーブレットを呼び出す [重複]。
-
ファインバグタイプ
-
javaで非静的な解を静的な参照にすることができない
-
java Mail send email smtp is not authenticated by TLS encryption solution.
-
プロジェクトの依存関係を解決できなかった 解決
-
自動配線された依存性のインジェクションに失敗しました。
-
アイデア Springboot Web プロジェクトを jar にパッケージ化する場合、Error: 無効または破損した jarfile x.jar 解決策
-
javaでよく使われる英単語
-
このラインで複数のマーカーを解決する方法