サーブレットとAjaxの使用方法


334

私はWebアプリとサーブレットに非常に慣れていないので、次の質問があります。

サーブレット内で何かを印刷してWebブラウザーで呼び出すと、そのテキストを含む新しいページが返されます。Ajaxを使用して現在のページのテキストを印刷する方法はありますか?

回答:


560

実際、キーワードは「ajax」:非同期JavaScriptおよびXMLです。ただし、昨年は非同期JavaScriptとJSONが頻繁に使用されています。基本的に、JSに非同期HTTPリクエストを実行させ、応答データに基づいてHTML DOMツリーを更新します。

すべてのブラウザー(特にInternet Explorerと他のブラウザー)で動作させるのはかなり退屈な作業であるため、単一の関数でこれを簡素化し、ブラウザー固有の可能な限り多くのバグ/問題をカバーするJavaScriptライブラリーがたくさんあります。 、jQueryPrototypeMootoolsなど。最近、jQueryが最も普及しているため、以下の例で使用します。

Stringプレーンテキストとして返されるキックオフの例

/some.jsp以下のようなものを作成します(注:コードは、JSPファイルがサブフォルダーに配置されることを想定していません。そうする場合は、それに応じてサーブレット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()ようなメソッドでサーブレットを作成します。

@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/*(当然、URLパターンはあなたの選択に自由ですが、変更する必要があると思い、以下のようsomeservletに応じてあらゆる場所にJSのコード例にURLを):

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

または、サーブレット3.0互換のコンテナ(Tomcat 7、Glassfish 3、JBoss AS 6以降)をまだ使用していない場合はweb.xml、古い方法でマッピングします(サーブレットの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>

今すぐ開く8080 /コンテキスト/なtest.jsp:// localhostを:HTTPをブラウザと押しボタンで。divのコンテンツがサーブレットの応答で更新されることがわかります。

List<String>JSONとして返す

JSONの代わりに、応答形式として平文あなたはさらにいくつかのステップを得ることができます。それはより多くのダイナミクスを可能にします。まず、JavaオブジェクトとJSON文字列の間で変換するツールが必要です。それらもたくさんあります(概要については、このページの下部を参照してください)。私の個人的なお気に入りはGoogle Gsonです。そのJARファイルをダウンロードして/WEB-INF/lib、Webアプリケーションのフォルダーに配置します。

これは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);
}

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として自動的に解析しresponseJson、応答のコンテンツタイプをに設定すると、関数の引数としてJSONオブジェクト()を直接提供することに注意してくださいapplication/json。設定を忘れるtext/plaintext/html、デフォルトのorに依存する場合、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>場所に表示される例です。サーブレット:ProductLong idString nameBigDecimal 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は、実際に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>

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フレームワークは、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のフォームプラグインは 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の一部ではなく、それを使用して文字列にシリアル化し、リクエストコンテンツタイプをapplication/json代わりに設定するようにjQueryに指示する必要があります。of(デフォルト)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とをdataTypecontentType種類を表し、リクエストボディを。dataType(予想される)タイプを表し応答 jQueryの既に応答者に基づいてそれを自動検出として通常不要である体、Content-Typeヘッダ。

次に、個別のリクエストパラメータとしてではなく、上記の方法でJSON文字列全体として送信されているサーブレットのJSONオブジェクトを処理するにはgetParameter()、通常の方法を使用する代わりに、JSONツールを使用してリクエストの本文を手動で解析するだけです。仕方。つまり、サーブレットはapplication/jsonフォーマットされたリクエストをサポートしていませんがapplication/x-www-form-urlencodedmultipart/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文字列のみを消費できるJAX-RS(RESTful)サービスです。

サーブレットからリダイレクトを送信する

実現し、理解することが重要任意の点であるsendRedirect()forward()AJAXリクエストに応じてサーブレットでコールだけ前方またはリダイレクトします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;
    }

    // ...
}

以下も参照してください。


最後の例でjsonを解析する必要があります。
しんぞう2016年

4
@kuhaku:いいえ。投稿を上から下に読むと、その理由がわかります。
BalusC 2016年

1
この答えは、先月か私の笑いでした。それからたくさんを学ぶ。XMLの例が大好きです。これをまとめてくれてありがとう!時間があるなら、1つのnoob質問。xmlフォルダーをWEB-INFに配置する理由はありますか?
Jonathan Laliberte 2017年

1
@JonathanLaliberte:ユーザーはそれらをダウンロードできません。
BalusC 2017年

@BalusC、あなたのXMLの例は素晴らしいです、ありがとう。しかし、$("#somediv").html($(responseXml).find("data").html())この行に対して「未定義またはnull参照のプロパティ 'replace'を取得できません」と表示されます。また、「引数の数が間違っているか、プロパティの割り当てが無効です」とも表示されます。デバッグすると、XMLにデータが入力されていることもわかります。何か案は ?
629

14

ユーザーのブラウザに現在表示されているページを(リロードせずに)更新する正しい方法は、ブラウザでコードを実行してページのDOMを更新することです。

そのコードは通常、HTMLページに埋め込まれている、またはHTMLページからリンクされているJavaScriptであるため、AJAXの提案です。(実際、更新されたテキストがHTTPリクエストを介してサーバーから送信されたと仮定すると、これは従来のAJAXです。)

プラグインがブラウザのデータ構造にアクセスしてDOMを更新するのは難しいかもしれませんが、ブラウザのプラグインやアドオンを使用してこの種のことを実装することも可能です。(ネイティブコードプラグインは通常、ページに埋め込まれているグラフィックフレームに書き込みます。)


13

サーブレットの完全な例と、どのようにajaxを呼び出すかを紹介します。

ここでは、サーブレットを使用してログインフォームを作成する簡単な例を作成します。

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サーブレットコード:-

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

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

7

Ajax(AJAX)は、非同期JavaScriptおよびXMLの頭字語です。非同期Webアプリケーションを作成するためにクライアント側で使用される相互に関連するWeb開発手法のグループです。Ajaxを使用すると、Webアプリケーションはサーバーに非同期でデータを送信したり、サーバーからデータを取得したりできます。以下はサンプルコードです。

2つの変数firstNameおよびlastNameを使用してサーブレットにデータを送信するためのJSPページのJavaスクリプト関数:

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

    }

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

5

通常、サーブレットからページを更新することはできません。クライアント(ブラウザ)は更新を要求する必要があります。Eiterクライアントは新しいページ全体をロードするか、既存のページの一部の更新を要求します。この手法はAjaxと呼ばれます。


4

ブートストラップ複数選択の使用

アヤックス

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

サーブレット内

request.getParameter("input")
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.