[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.html


 

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로 처리.

 

 

AjaxTest02.jsp


 

【페이지 이동 순서 정리】

 

① 사용자가 `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}