[Ajax]/Program source (Ajax)
[AJax] 20231227 [프로그램 소스] - AjaxTest01, ajaxTarget, web.xml, AjaxTest02, Test02, Test02Send, Test02_ok
Jelly-fish
2023. 12. 27. 16:49
`AjaxTest01` - ajaxTarget.txt 에 들어있는 텍스트를 AjaxTest01의 html에 넣기.
01
AjaxTest01
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>AjaxTest01.html</title>
<link rel="stylesheet" type="text/css" href="css/main.css">
<script type="text/javascript">
function loadXMLDocs()
{
// 확인
//alert("함수 호출~!!!");
// XMLHttpRequest 객체(→ AJAX 객체)를 담을 변수 선언
var xmlHttp;
// (클라이언트 측) 브라우저에 따른 분기
// (클라이언트 측에서) 자신의 브라우저가 XMLHttpRequest 를
// 지원하고 있는 상황이라면...
// XMLHttpRequest를 지원한다.
if (window.XMLHttpRequest)
{
// 테스트
//alert("XMLHttpRequest 지원~!!!");
// (이렇게...) 이와 같은 방법으로 객체를 생성하고
xmlHttp = new XMLHttpRequest();
}
// XMLHttpRequest를 지원하지 않는다.
else
{
// 테스트
//alert("XMLHttpRequest 지원하지 않음~!!!");
// (저렇게...) 이와 같은 방법으로 객체를 생성해라
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// ※ 객체를 생성하는 방법의 차이만 있을 뿐
// 여기까지 수행하면 XMLHttpRequest 객체 (→ AJAX 객체) 생성 완료~!!!
//****************************************************************************
// 함수 호출 -> 상황 연출
// 상황 연출 -> 함수 호출 ==> 콜백 함수(trigger처럼 호출된다. 피동적인 호출)
//****************************************************************************
// 『xmlHttp』 : XMLHttpRequest 객체
// 서버로부터 응답이 오면 『readystatechange』 이벤트가 발생하게 된다.
// 『onreadystatechange』 : readystatechange 이벤트가 발생했을 때
// 동작할 수 있도록 이벤트 핸들러를 등록하는 과정.
// 즉, 이와 같은 이벤트가 발생하게 되면... 다음의 내용처럼 동작해라~!!! 라는 의미.
//xmlHttp.onreadystatechange = 기능, 동작, 행위;
//****************************************************************
// 콜백함수. 상황이 연출되지 않으면 function()이 동작하지 않는다.
//****************************************************************
xmlHttp.onreadystatechange = function()
{
// 테스트
//alert("이벤트 발생 : readyState → " + xmlHttp.readyState);
// → 1 2 3 4(이때, ajaxTarget.txt 내용으로 HTML 변경됨.)
// 응답이 올 때 마다
// readyState 가 그 상황에서의 XMLHttpRequest 상태를 저장하게 된다.
// 즉, readyState 는 XMLHttpRequest 객체의 property 이다.
// ==> readystatechange 이벤트는
// readyState 가 변경될 때 마다 발생하게 된다.
// ※ 『XMLHttpRequest』 의 『readyState』 는 0 에서 4 까지 순차적으로 변화한다.
//====================================================
// 0 → 요청이 초기화 되지 않음
// 1 → 서버 연결이 이루어지지 않음.
// 2 → 요청이 수신됨.
// 3 → 요청을 처리중.
// 4 → 요청의 처리가 종료되고, 응답이 준비됨.
//====================================================
// 요청의 처리가 종료되고, 응답이 준비된 상태라면...
if (xmlHttp.readyState==4)
{
// ※ 『XMLHttpRequest』 의 『status』 는 『HTTP Status』코드를 의미한다.
// 200 → 올바른 응답
// 40x → 클라이언트 측 에러
// 50x → 서버 측 에러
if (xmlHttp.status==200)
{
// 이 구문을 통해 서버로부터 응답을 정상적으로 받았을 때
// 그 응답을 가져와서 DOM 을 업데이트 하겠다는 의미
// 응답의 속성에는 크게 두 가지가 있는데
// 『responseText』는 텍스트 형식의 응답일 경우 사용하게 되고
// 『responseXML』은 응답이 XML 형식일 경우 사용하게 된다.
document.getElementById("myDiv").innerHTML = xmlHttp.responseText;
}
}
};
// ↑ 위는 계획한 내용.
//------------------------------------------------------------------------
// ↓ 실제 실행!(동작...!! 액션~)
// 『XMLHttpRequest』의 『open("페이지 요청 방식", "URL", async)』
// XMLHttpRequest 객체를 필요한 설정으로 초기화하는데 사용하는 메소드이다.
// GET 방식이 아닌 POST 방식으로 요청하기 위해서는
// 『xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// xmlHttp.send(input1=value1&input2=value2);』
// 와 같은 구문으로 헤더를 추가해 주어야 한다.
// true : 비동기 방식(async) 허용
// false : 비동기 방식 비허용(async) → AJAX 를 사용할 수 없어짐.
xmlHttp.open("GET", "ajaxTarget.txt", true);
xmlHttp.send("");
}
</script>
</head>
<body>
<div id="myDiv">
<h1>AJAX 를 이용하여 이 텍스트를 바꾸어본다.</h1>
</div>
<button type="button" class="btn" onclick="loadXMLDocs()">Content 바꾸기</button>
</body>
</html>
ajaxTarget.txt
AJAX is not a programmig language.
AJAX is a technique for accessing web server from a web page.
`AjaxTest02.jsp` - 클라이언트로부터 두 개의 정수를 입력받고, 두 수의 합을 AJAX로 처리.
【페이지 이동 순서 정리】
① 사용자가 `http://localhost:3306/AjaxApp/test02send.do` url 요청
② web.xml 에 의해 컨트롤러(Controller) 클래스인 `Test02Send.java`가 동작
<servlet> <servlet-name>test02send</servlet-name> <servlet-class>com.test.ajax.Test02Send</servlet-class> </servlet> <servlet-mapping> <servlet-name>test02send</servlet-name> <url-pattern>/test02send.do</url-pattern> </servlet-mapping>
③ 컨트롤러 `Test02Send.java`에서 클라이언트를 최초 요청 View 페이지인 `AjaxTest02.jsp`로 이동시킴.
// 사용자 정의 메소드 protected void doGetPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // GET 방식이든 POST 방식이든 // 어떤 방식의 요청에도 모두 처리할 수 있는 사용자 정의 메소드 //String view = "WEB-INF/view/AjaxTest02.jsp"; // 클라이언트가 바로 접근할 수 없도록 // WEB-INF/view 폴더 내부에 jsp를 넣고 컨트롤러로 접근. String view = "AjaxTest02.jsp"; RequestDispatcher dispatcher = request.getRequestDispatcher(view); dispatcher.forward(request, response); }
④ View 페이지인 `AjaxTest02.jsp`에서 입력값을 클라이언트에게 입력한 후, `test02.do` 페이지에 AJAX를 요청하도록 환경 설정
『AjaxTest02.jsp - `sum()` 메소드 내부』
- `test02.do` 페이지에 GET 방식으로 비동기 처리 AJAX를 요청하는 구문
// URL 구성 var url = "test02.do?n1=" + n1 + "&n2=" + n2; // test01페이지 요청, num1, num2 GET 방식 전송 // XMLHttpRequest 객체 생성(→ AJAX 객체) ajax = createAjax(); //-- ajax.js의 메소드 // 『GET』 : 데이터 전송 및 페이지 요청 방식(POST 사용 가능, POST 사용 시 헤더 추가 필요) // 『url』 : AJAX 요청 페이지(데이터 수신 및 응답 페이지) // 『true』 : boolean → true(비동기), false(동기). AJAX 처리 과정에서 동기는 사용 안함. ajax.open("GET", url, true);
⑤ web.xml에 의해 컨트롤러(Controller) 클래스 `Test02.java`가 동작
<servlet> <servlet-name>test02</servlet-name> <servlet-class>com.test.ajax.Test02</servlet-class> </servlet> <servlet-mapping> <servlet-name>test02</servlet-name> <url-pattern>/test02.do</url-pattern> </servlet-mapping>
⑥ `Test02.java` 에서 업무 로직 처리(num1과 num2 덧셈 연산) 이후 `request.setAttribute`를 한 후,
`Test02_ok.jsp`로 forwarding 처리를 한다.
// 사용자 정의 메소드 protected void doGetPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // GET 방식이든 POST 방식이든 // 어떤 방식의 요청에도 모두 처리할 수 있는 사용자 정의 메소드 // 이전 페이지(AjaxTest02.jsp)로부터 넘어온 데이터 수신 // → n1, n2 int n1 = Integer.parseInt(request.getParameter("n1")); int n2 = Integer.parseInt(request.getParameter("n2")); // 업무 로직 처리 → 덧셈 연산 int result = n1 + n2; // 반환할 결과값 준비 request.setAttribute("result", result); RequestDispatcher dispatcher = request.getRequestDispatcher("Test02_ok.jsp"); dispatcher.forward(request, response); }
★★★
현재 `test02.do` 페이지에 GET 방식으로 비동기 처리 AJAX를 요청했기 때문에
( * AJAX는 불필요한 페이지를 새로 생성하는 과정을 없애기 위해 사용하는 것.)
클라이언트가 머무르는 페이지가 `Test02_ok.jsp`로 변경되는 것이 아니라
단일 데이터 값(`responseText`)을 가져오는 페이지가 `Test02_ok.jsp`가 되는 것이다.
○ [AJAX 처리]★★★
★ Test02_ok.jsp 의 조각 데이터 `result`를 가져와서, AjaxTest02.jsp에 끼워넣어 주는 것이다.
⑦ 최종적으로, `Test02_ok.jsp`에서 수신한 `result(num1 + num2의 결과값)` 를
AjaxTest02.jsp 의 `callBack()` 함수의 data 변수에 담아서 바인딩해 온다.
그 이후, `#result` input 객체의 value 값으로 넣어주는 것이다.
【`Test02_ok.jsp`】 - result를 EL(JSTL)로 수신.
<%@ page contentType="text/html; charset=UTF-8"%> ${result}
『AjaxTest02.jsp - `callBack()` 메소드』
- data 변수에 `ajax.responseText`로 `result`를 받아와서 저장한 후
그 값을 `#result` input 객체의 value 값으로 넣어준다.
function callBack() { // 1. 서버에서 응답한 데이터가 텍스트일 경우(단일 데이터) var data = ajax.responseText; // 바인딩한 데이터를 업무에 적용한다. document.getElementById("result").value = data; }
web.xml (send Controller)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>WebApp00</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- AJAX 관련 실습 -->
<!-- AjaxTest02 → 페이지 내 컨트롤 확인-->
<servlet>
<servlet-name>test02send</servlet-name>
<servlet-class>com.test.ajax.Test02Send</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test02send</servlet-name>
<url-pattern>/test02send.do</url-pattern>
</servlet-mapping>
</web-app>
Test02Send.java
/*========================
Test02Send.java
=========================*/
package com.test.ajax;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// Test004.java (Servlet) 에서는
// GenericServlet 을 extends 를 상속하자마자 에러가 났었지만,
// HttpServlet 을 extends 하겠다고 했을 땐, 에러가 나지 않았다.
// ★ 추상 클래스이지만 추상 메소드를 갖고 있지 않은 것이다!!
// [GenericServlet] → service() Overriding
// [HttpServlet] → doGet(), doPost() Overriding
public class Test02Send extends HttpServlet
{
private static final long serialVersionUID = 1L;
// 사용자의 http 프로토콜 요청이 GET 방식일 경우 호출되는 메소드
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doGetPost(request, response);
}
// 사용자의 http 프로토콜 요청이 POST 방식일 경우 호출되는 메소드
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doGetPost(request, response);
}
// 사용자 정의 메소드
protected void doGetPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// GET 방식이든 POST 방식이든
// 어떤 방식의 요청에도 모두 처리할 수 있는 사용자 정의 메소드
//String view = "WEB-INF/view/AjaxTest02.jsp"; // 클라이언트가 바로 접근할 수 없도록
// WEB-INF/view 폴더 내부에 jsp를 넣고 컨트롤러로 접근.
String view = "AjaxTest02.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(view);
dispatcher.forward(request, response);
}
}
AjaxTest02.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
request.setCharacterEncoding("UTF-8");
String cp = request.getContextPath();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>AjaxTest02.jsp</title>
<link rel="stylesheet" type="text/css" href="<%=cp %>/css/main.css">
<style type="text/css">
.short
{
width: 50px;
text-align: right;
}
</style>
<script type="text/javascript" src="<%=cp%>/js/ajax.js"></script>
<script type="text/javascript">
function sum()
{
// 확인
//alert("함수 호출~!!!");
// 데이터 수집
var n1 = document.getElementById("num1").value;
var n2 = document.getElementById("num2").value;
// URL 구성
var url = "test02.do?n1=" + n1 + "&n2=" + n2;
// test01페이지 요청, num1, num2 GET 방식 전송
//---> Servlet 을 사용하겠다는 의미이다. (Java Resources)
// XMLHttpRequest 객체 생성(→ AJAX 객체)
ajax = createAjax(); //-- ajax.js
// 『GET』 : 데이터 전송 및 페이지 요청 방식(POST 사용 가능, POST 사용 시 헤더 추가 필요)
// 『url』 : AJAX 요청 페이지(데이터 수신 및 응답 페이지)
// 『true』 : boolean → true(비동기), false(동기). AJAX 처리 과정에서 동기는 사용 안함.
ajax.open("GET", url, true);
//-- 실제 서버와의 연결이 아니고, 일종의 큰 의미에서 환경 설정 부분으로 이해하는 것이 좋겠다.
// (실제 서버 연결은 나중에...)
// ajax 객체(→ XMLHttpRequest 객체)의 readyState 속성은
// 각 단계별로 변화되며, 0 부터 4 까지 순차적으로 증가하는 형태로 변화한다.
// 그 때 마다... 『readystatechange』 이벤트가 발생하게 된다.
ajax.onreadystatechange = function()
{
// 그 중에서... (0 부터 4 까지의 상태 중에서...)
// 4 가 되는 순간이 요청했던 서버로부터 응답 준비가 완료된 시점이기 때문에
// 4 인 경우... 수행해야 할 업무를 진행할 수 있도록 처리한다.
if (ajax.readyState == 4)
{
// 서버로부터 응답이 완료되었다 하더라도
// 그 과정에서 데이터가 올바른 것인지, 에러 메세지를 받은 것인지
// 알 수 없기 때문에 서버로부터 응답 받은 코드를 확인한 후
// 업무를 진행할 수 있도록 처리(구성)한다.
if (ajax.status == 200)
{
// 업무 진행
//-- 업무 코드를 외부로 추출
//(callBack() 메소드는 사용자가 직접 호출 Ⅹ)
callBack();
}
}
};
// 실제 서버에서 AJAX 요청을 한다. (즉, 이 부분이 진짜 연결 작업이다.)
// GET 방식으로 데이터를 전송하는 경우... 인자값이 ""
// POST 방식으로 데이터를 전송하는 경우... 인자값에 해당 데이터를 넣는다.
// 현재는 GET 방식의 요청이다. (비워두는 것은 하지 말자.)
ajax.send("");
}
// 추출된 업무 코드
//-- AJAX 요청이 완료된 후 호출되는 최종 업무 처리 함수
function callBack()
{
// 여기서는 두 가지 방법 중 하나로 데이터를 바인딩한다.
// 1. 서버에서 응답한 데이터가 텍스트일 경우(단일 데이터)
var data = ajax.responseText;
//****************************************
// [XML] : 데이터를 구조화하는데 특화 됨.
//****************************************
// 2. 서버에서 응답한 데이터가 XML 일 경우(다량의 데이터)
//var data = ajax.responseXML;
// 바인딩한 데이터를 업무에 적용한다.
document.getElementById("result").value = data;
}
</script>
</head>
<body>
<div>
<h1>AJAX 기본 실습</h1>
<hr>
</div>
<input type="text" id="num1" class="txt short">
+
<input type="text" id="num2" class="txt short">
<input type="button" value=" = " class="btn" onclick="sum()">
<input type="text" id="result" class="txt short">
<br><br>
<p>같은 페이지에 있는 기타 다른 요소들</p>
<input type="text">
<br>
<input type="checkbox" name="check" value="check1"> 체크1
<input type="checkbox" name="check" value="check2"> 체크2
<br>
<input type="radio" name="rdo" value="rdo1"> 라디오1
<input type="radio" name="rdo" value="rdo2"> 라디오2
<br>
<select>
<option value="1">선택1</option>
<option value="2">선택2</option>
<option value="3">선택3</option>
</select>
</body>
</html>
web.xml (+ 업무처리 Controller)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>WebApp00</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- AJAX 관련 실습 -->
<!-- AjaxTest02 → 페이지 내 컨트롤 확인-->
<servlet>
<servlet-name>test02send</servlet-name>
<servlet-class>com.test.ajax.Test02Send</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test02send</servlet-name>
<url-pattern>/test02send.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>test02</servlet-name>
<servlet-class>com.test.ajax.Test02</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test02</servlet-name>
<url-pattern>/test02.do</url-pattern>
</servlet-mapping>
</web-app>
Test02.java
/*========================
Test02.java
=========================*/
package com.test.ajax;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// Test004.java (Servlet) 에서는
// GenericServlet 을 extends 를 상속하자마자 에러가 났었지만,
// HttpServlet 을 extends 하겠다고 했을 땐, 에러가 나지 않았다.
// ★ 추상 클래스이지만 추상 메소드를 갖고 있지 않은 것이다!!
// [GenericServlet] → service() Overriding
// [HttpServlet] → doGet(), doPost() Overriding
public class Test02 extends HttpServlet
{
private static final long serialVersionUID = 1L;
// 사용자의 http 프로토콜 요청이 GET 방식일 경우 호출되는 메소드
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doGetPost(request, response);
}
// 사용자의 http 프로토콜 요청이 POST 방식일 경우 호출되는 메소드
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doGetPost(request, response);
}
// 사용자 정의 메소드
protected void doGetPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// GET 방식이든 POST 방식이든
// 어떤 방식의 요청에도 모두 처리할 수 있는 사용자 정의 메소드
// 이전 페이지(AjaxTest02.jsp)로부터 넘어온 데이터 수신
// → n1, n2
int n1 = Integer.parseInt(request.getParameter("n1"));
int n2 = Integer.parseInt(request.getParameter("n2"));
// 업무 로직 처리 → 덧셈 연산
int result = n1 + n2;
// 반환할 결과값 준비
request.setAttribute("result", result);
RequestDispatcher dispatcher = request.getRequestDispatcher("Test02_ok.jsp");
dispatcher.forward(request, response);
}
}
Test02_ok.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
${result}