서블릿과 Ajax를 사용하는 방법?


334

나는 웹 앱과 서블릿을 처음 접했고 다음과 같은 질문이 있습니다.

서블릿 내부에 무언가를 인쇄하고 웹 브라우저로 호출 할 때마다 해당 텍스트가 포함 된 새 페이지가 반환됩니다. Ajax를 사용하여 현재 페이지의 텍스트를 인쇄하는 방법이 있습니까?

답변:


561

실제로 키워드는 "ajax": Asynchronous JavaScript and XML 입니다. 그러나 지난 몇 년 동안 종종 비동기 JavaScript 및 JSON 이상 입니다. 기본적으로 JS가 비동기 HTTP 요청을 실행하고 응답 데이터를 기반으로 HTML DOM 트리를 업데이트 할 수 있습니다.

모든 브라우저 (특히 Internet Explorer와 다른 브라우저)에서 작동하도록 하는 것은 지루한 작업이므로 단일 기능으로이를 단순화하고 가능한 많은 브라우저 관련 버그 / 질문을 다루는 JavaScript 라이브러리가 많이 있습니다. 같은 jQuery를 , 원형 , Mootools의 . 요즘 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 {
    // ...
}

또는 아직 Servlet 3.0 호환 컨테이너가 아닌 경우 (Tomcat 7, Glassfish 3, JBoss AS 6 등 이상), web.xml구식으로 매핑 하십시오 ( Servlet 위키 페이지 참조 ).

<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 문자열 사이를 변환하는 도구가 필요합니다. 그것들도 많이 있습니다 ( 개요 는 이 페이지 의 하단을 참조하십시오 ). 내가 가장 좋아하는 것은 Google 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);
}

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/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>A의 클래스는 특성을 가지고는 , 하고 . 서블릿 :<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은 실제로 결과를 반복하고 서버 측 데이터 형식을 수행하는 데 사용할 수 있으므로 훨씬 유용합니다. 서블릿 :

@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>A의 <jsp:include>그것이 아닌 아약스 응답 재사용 다른 곳에있을 수 있습니다)

<?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은 재미 있지만 결국 "공공 웹 서비스"에만 유용합니다. JSF 와 같은 MVC 프레임 워크 는 아약스 마법을 위해 XML을 사용합니다.

기존 양식의 아약시

jQuery $.serialize()를 사용 하면 개별 양식 입력 매개 변수를 수집하고 전달하지 않고도 기존 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.
});

서블릿에서 다음과 같이 일반 요청과 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 $.param()하려는 경우 jQuery 를 사용 하여 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에 요청 콘텐츠 유형을 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헤더.

그런 다음 개별 요청 매개 변수로 전송되지 않고 위의 전체 JSON 문자열로 전송되는 서블릿에서 JSON 객체를 처리 getParameter()하려면 일반적인 방법 을 사용 하는 대신 JSON 도구를 사용하여 요청 본문을 수동으로 구문 분석하면됩니다. 방법. 즉, 서블릿은 지원하지 않는 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) 서비스 인 경우에만 사용하려고합니다 . JAX-RS (RESTful) 서비스는 어떤 이유로 든 일반 요청 매개 변수가 아닌 JSON 문자열 만 사용할 수 있습니다.

서블릿에서 리디렉션 보내기

깨닫고 이해하는 것이 중요하는 것은 어떤 것입니다 sendRedirect()forward()아약스 요청 서블릿에 의해 호출은 앞으로 또는 리디렉션 것 아약스 요청 자체 가 아니라 아약스 요청이 시작된 주 문서 / 창을여십시오. 이러한 경우 JavaScript / jQuery는 리디렉션 / 전달 된 응답 만 responseText콜백 함수의 변수 로 검색합니다 . Ajax 관련 XML 또는 JSON 응답이 아닌 전체 HTML 페이지를 나타내는 경우 현재 문서를 해당 페이지로 바꾸면됩니다.

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을 구문 분석해야합니다.
shinzou

4
@kuhaku : 아뇨. 위에서 아래로 게시물을 읽으면 그 이유를 알게됩니다.
BalusC

1
이 답변은 지난 한 달 동안 나의 생명선이었습니다. 그것으로부터 무리를 배우기. 나는 XML 예제를 좋아한다. 이것을 합쳐 주셔서 감사합니다! 시간이 있다면 하나의 멍청한 질문입니다. xml 폴더를 WEB-INF에 넣는 이유가 있습니까?
Jonathan Laliberte 2016 년

1
@JonathanLaliberte : 따라서 사용자는 다운로드 할 수 없습니다.
BalusC

@BalusC, XML 예제가 훌륭합니다. 감사합니다. 그러나이 $("#somediv").html($(responseXml).find("data").html())줄에 대해 "정의되지 않은 또는 null 참조의 속성 '대체'를 가져올 수 없습니다"가 표시됩니다. "잘못된 인수 수 또는 잘못된 속성 할당"이라고도합니다. 또한 디버깅 할 때 XML에 데이터가 채워져 있음을 알 수 있습니다. 어떤 아이디어?
629

14

다시로드하지 않고 사용자 브라우저에 현재 표시된 페이지를 업데이트하는 올바른 방법은 브라우저에서 일부 코드를 실행하여 페이지의 DOM을 업데이트하는 것입니다.

이 코드는 일반적으로 HTML 페이지에 포함되거나 연결된 자바 스크립트이므로 AJAX 제안입니다. (실제로, 업데이트 된 텍스트가 HTTP 요청을 통해 서버에서 온 것으로 가정하면 이것이 전형적인 AJAX입니다.)

플러그인이 브라우저의 데이터 구조에 도달하여 DOM을 업데이트하는 것은 까다로울 수 있지만 일부 브라우저 플러그인 또는 애드온을 사용하여 이런 종류의 것을 구현할 수도 있습니다. 기본 코드 플러그인은 일반적으로 페이지에 포함 된 일부 그래픽 프레임에 씁니다.


13

서블릿의 전체 예와 아약스 호출 방법을 보여 드리겠습니다.

여기서는 서블릿을 사용하여 로그인 양식을 작성하는 간단한 예제를 작성합니다.

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
        ({
            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) (Asynchronous JavaScript and XML의 약어)는 클라이언트 측에서 비동기 웹 애플리케이션을 작성하는 데 사용되는 상호 관련된 웹 개발 기술 그룹입니다. Ajax를 사용하면 웹 애플리케이션이 서버와 비동기 적으로 데이터를주고받을 수 있습니다. 아래는 예제 코드입니다.

두 개의 변수 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.