AJAX
1. 동기와 비동기방식
- 동기방식
- 요청 후, 응답이 올 때까지 client는 대기만 하는 것.
- 비동기방식
- 요청 후, 응답이 올 때까지 client가 다른 Background 작업을 할 수 있는 것.
- client는 멈추지 않고 동작
2. AJAX 구성 및 특징
- JavaScript
- css
- DOM
- XMLHttpRequest
- 자바스크립트 객체
- 대부분의 브라우저에서 지원
- 표준 HTTP방식(GET/POST)으로 서버와 통신
- 서버와 통신시 비동기적으로 작업
- 기존 서버 작업 방식 사용 (Servlet, JSP, …)
- 응답문서 타입 : html외에 xml, json, 단순 텍스트 사용
- client의 요청을 AJAX Engine이 가로채서 대신 요청과 응답을 Http프로토콜로 처리하는 기술
3. AJAX프로그래밍 순서
- 클라이언트 이벤트 발생 (ex. 버튼클릭, 텍스트 입력…)
- XMLHttpRequest 객체 생성
- XMLHttpRequest 객체 콜백함수 설정 ( 서버의 상태가 바뀔때마다 호출되는 함수 )
- XMLHttpRequest 객체를 통한 비동기화 요청
- 서버 응답결과를 생성하여 클라이언트로 전송
- XMLHttpRequest 객체는 서버 결과를 처리할 콜백함수 호출
- 결과를 클라이언트 화면에
4. 예제
4-1. ajaxTest.jsp에서 버튼을 누르면 hello.jsp의 값이 날아오게 하기
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<h1>Hello AJAX!</h1>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
#msgView{
border:1px solid red;
height:200px;
width: 500px;
margin-bottom:20px;
text-align:center;
}
</style>
<script>
let httpRequest = null
function requestMsg(){
// 1단계 : XMLHttpRequest객체 생성
if(window.XMLHttpRequest)
httpRequest = new XMLHttpRequest()
else if(window.ActiveXObject)
// explore버전때문에 해주는거임. 최소한의 안전장치
httpRequest = new ActiveXObject("Microsoft.XMLHTTP")
else
httpRequest = null
// 2단계 : Callback함수 설정( 서버요청이 바뀔때마다 호출되는 함수 )
/*
httpRequest.onreadystatechage = function(){
}아래와 같은 뜻
*/
httpRequest.onreadystatechange = responseMsg
// 3단계 : 서버에 비동기 요청
httpRequest.open('GET', 'hello.jsp' ,true) // 비동기방식 true
httpRequest.send(null)
}
function responseMsg(){
if(httpRequest.readyState == 4){
// 모든 데이터 전송완료(응답완료 4) 했고 결과가 올바르다면(200) responseText한다.
if(httpRequest.status == 200){
let msgView = document.getElementById("msgView");
msgView.innerHTML = httpRequest.responseText // +=는 계속 추가됨
}
}
}
</script>
</head>
<body>
<h2>서버에서 받은 메시지</h2>
<div id="msgView">
</div>
<input type="button" value="서버에서 자료 요청" onclick="requestMsg()">
</body>
</html>
4-1. 가상의 url로 넘어가게 하기.
- ajaxText2.jsp
- 위의 ajaxText.jsp복사
- httpRequest.open(‘GET’, ‘hello.jsp’ ,true)부분 httpRequest.open(‘GET’, ‘/Lecture-Web/ajax/hello’,true)로 수정
- HelloServlet.java
package kr.ac.kopo.ajax;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class HelloServlet
*/
@WebServlet("/ajax/hello")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
out.write("<h1>Hello AJAX!!!</h1>");
out.close();
}
}
5. GET방식과 POST방식의 파라미터 전달방법
5-1. GET방식
- open(‘GET’, ‘hello.jsp?id=duke’, true)
- send(null)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script>
let httpRequest = null
function getXMLHttpRequest(){
let httpRequest=null
if(window.XMLHttpRequest)
httpRequest = new XMLHttpRequest()
else if(window.ActiveXObject)
// explore버전때문에 해주는거임. 최소한의 안전장치
httpRequest = new ActiveXObject("Microsoft.XMLHTTP")
return httpRequest
}
function sendProcess(param){
httpRequest = getXMLHttpRequest()
httpRequest.onreadystatechange = callbackFunction
let msg="==================================================\n";
msg += "/Lecture-Web/eaxm02/param.jsp?name=" + param + "\n";
debugTrace(msg)
let url = "param.jsp?name=" + param
httpRequest.open('GET', url, true)
httpRequest.send(null)
}
function callbackFunction(){
let msg =''
switch(httpRequest.readyState){
case 1:
msg += 'Loading...\n'
break
case 2:
msg += 'Loaded...\n'
break
case 3:
msg += 'Interaction...\n'
break
case 4:
msg += 'Completed...\n'
if(httpRequest.status == 200){
msg += '웹서버에서 정상적으로 수행...\n'
msg += '실행결과 : ' + httpRequest.responseText + '\n'
}else{
msg += '웹서버에서 오류 발생...\n'
msg += '오류코드 : ' + httpRequest.status + '\n'
// Explorer에서 한글인자호출시 400에러가 난다?
}
msg += "===================================================\n"
break
}
debugTrace(msg)
}
function debugTrace(msg){
//debug메시지 출력하는 메소드
let degug = document.getElementById("debug")
debug.value += msg
}
</script>
</head>
<body>
<textarea rows="10" cols="80" id="debug"></textarea><br>
<button onclick="sendProcess('hong gill-dong')">영문인자호출</button>
<button onclick="sendProcess('홍길동')">한글인자호출</button>
</body>
</html>
- Explorer에서 한글인자호출시 400에러가 난다?
- 400Error : Explorer에서 한글을 인식 못해서 나오는것.
- Chrome은 알아서 인코딩이 되지만, Explorer는 인코딩이 안되기 때문.
param = encodeURIComponent(param)
// 모든 브라우저에서 동작하기 위해서는 encode해줘야함
let url = "param.jsp?name=" + param
5-2. POST방식
- open(‘POST’, ‘hello.jsp’, true)
- send(‘id=duke’)
- POST방식은 html에서 form태그를 써야만 넘길 수 있음
- 함수안에 처리를 해주면 form없이도 가능
- form enctype=”application/x-www-form-urlencoded”
- 그래서 httpRequest.setRequestHeader(‘Content-type’, ‘application/x-www-form-urlencoded’)가 필요
- 근데 한글이 깨지네?
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script>
let httpRequest = null
function getXMLHttpRequest(){
let httpRequest=null
if(window.XMLHttpRequest)
httpRequest = new XMLHttpRequest()
else if(window.ActiveXObject)
// explore버전때문에 해주는거임. 최소한의 안전장치
httpRequest = new ActiveXObject("Microsoft.XMLHTTP")
return httpRequest
}
function sendProcess(method, param){
httpRequest = getXMLHttpRequest()
httpRequest.onreadystatechange = callbackFunction
let msg="==================================================\n";
msg += method + " /Lecture-Web/eaxm02/param2.jsp?name=" + param + "\n";
// method인자가 안들어올 수도 있어서 위험한 방식이긴 함 (예제를 위한 예제)
debugTrace(msg)
let url = 'param2.jsp'
param = encodeURIComponent(param)
let args = 'name=' + param
if(method == 'GET'){
//GET일때
httpRequest.open(method, url + '?' + args, true)
httpRequest.send(null)
}else if(method == 'POST'){
//POST일때
httpRequest.open(method, url, true)
httpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
/* 1. POST방식인데 왜 올바르게 날아가지 않을까?
html에서 POST방식으로 넘기기 위해서는 form태그를 쓸때만 POST방식으로 넘길 수 있다.
form enctype="application/x-www-form-urlencoded"
그래서 위의 httpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')가 필요
2. 근데 한글이 깨지네?
param2.jsp에서 인코딩 수행
*/
httpRequest.send(args)
}
}
function callbackFunction(){
let msg =''
switch(httpRequest.readyState){
case 1:
msg += 'Loading...\n'
break
case 2:
msg += 'Loaded...\n'
break
case 3:
msg += 'Interaction...\n'
break
case 4:
msg += 'Completed...\n'
if(httpRequest.status == 200){
msg += '웹서버에서 정상적으로 수행...\n'
msg += '실행결과 : ' + httpRequest.responseText + '\n'
}else{
msg += '웹서버에서 오류 발생...\n'
msg += '오류코드 : ' + httpRequest.status + '\n'
// Explorer에서 한글인자호출시 400에러가 난다?
}
msg += "===================================================\n"
break
}
debugTrace(msg)
}
function debugTrace(msg){
//debug메시지 출력하는 메소드
let degug = document.getElementById("debug")
debug.value += msg
}
</script>
</head>
<body>
<textarea rows="10" cols="80" id="debug"></textarea><br>
<button onclick="sendProcess('GET','hong gill-dong')">GET영문인자호출</button>
<button onclick="sendProcess('GET','홍길동')">GET한글인자호출</button><br>
<button onclick="sendProcess('POST','hong gill-dong')">POST영문인자호출</button>
<button onclick="sendProcess('POST','홍길동')">POST한글인자호출</button>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
// POST방식은 한글 출력시 인코딩이 필요함
if(request.getMethod().equalsIgnoreCase("POST"))
request.setCharacterEncoding("utf-8");
%>
name=${ param.name }
6. httpRequest라이브러리 만들기
6-1. httpRequest.js
/**
* AJAX 통신과 관련된 함수의 집합
*/
let hgttpRequest = null
function getXMLHttpRequest(){
let httpRequest=null
if(window.XMLHttpRequest)
httpRequest = new XMLHttpRequest()
else if(window.ActiveXObject)
// explore버전때문에 해주는거임. 최소한의 안전장치
httpRequest = new ActiveXObject("Microsoft.XMLHTTP")
return httpRequest
}
function sendProcess(method, url, params, callback){
httpRequest = getXMLHttpRequest()
httpRequest.onreadystatechange = callback
let httpMethod = method
if(httpMethod !='GET' && httpMethod != 'POST')
httpMethod = 'GET'
let httpParams=''
if(params !=null && params != '' ){
/*
// name=홍길동&age=24
paramArr = params.split('&')
for(let param of paramArr){
pdata = param.split('=')
if(httpParams != '')
// &로 다시 결합
httpParams += '&'
//name=value로만들기
httpParams += pdata[0] + '=' + encodeURIComponent(pdata[1])
===== 원리설명==============================
name=홍길동&age=24
paramArr[0] -> name = 홍
paramArr[1] -> age = 24
-----------------------------------
pdata[0] -> name
pdata[1] -> 홍 (인코딩필요) : encodeURIComponent(pdata[1]
...
-----------------------------------
httpParams -> name=0xAAxVVBB0xCC...
...
-----------------------------------
}
*/
if(params instanceof String){
paramArr = params.split('&')
for(let param of paramArr){
pdata = param.split('=')
if(httpParams != '')
// &로 다시 결합
httpParams += '&'
//name=value로만들기
httpParams += pdata[0] + '=' + encodeURIComponent(pdata[1])
}
}else{// object형일때
// {name:name ,age:age, addr:addr}를 "name=홍길동&age=30&addr=서울시서초구"로
for(let key in params){
console.log(key, params[key])
if(httpParams!=''){
httpParams +='&'
}
httpParams += key + '=' + encodeURIComponent(params[key])
}
}
}
// Method, GET방식일때는 httpURL에 ?도 들어가게
// GET방식에서는 파라미터가 ?뒤에 붙어오기 떄문에
let httpURL = url
if(httpMethod == 'GET' && httpParams!='')
httpURL = url + '?' + httpParams
console.log(httpMethod, httpURL, httpParams)
httpRequest.open(httpMethod, httpURL, true)
if(httpMethod=='GET'){
httpRequest.send(null)
}else if(httpMethod == 'POST'){
httpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
httpRequest.send(httpParams)
}
}
6-2. module.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="httpRequest.js"></script>
<script>
function clickBtn(){
// 비동기 통신을 위한 함수
let name = document.inputForm.name.value
let age = document.inputForm.age.value
let addr = document.inputForm.addr.value
// 비동기 통신
// 1단계
// sendProcess('POST', 'sample.jsp', "name=홍길동&age=30&addr=서울시서초구", callback)
//2단계
// let params = 'name=' + name + '&age=' + age + '&addr=' + addr
// sendProcess('POST', 'sample.jsp', params, callback)
//3단계
let params = {name:name ,age:age, addr:addr}
//json으로 들어온 값을 "name=홍길동&age=30&addr=서울시서초구"이렇게 만들어주어야함.
sendProcess('POST', 'sample.jsp', params, callback)
}
function callback(){
let msg =''
switch(httpRequest.readyState){
case 1:
msg += 'Loading...\n'
break
case 2:
msg += 'Loaded...\n'
break
case 3:
msg += 'Interaction...\n'
break
case 4:
msg += 'Completed...\n'
if(httpRequest.status == 200){
msg += '웹서버에서 정상적으로 수행...\n'
msg += '실행결과 : ' + httpRequest.responseText + '\n'
}else{
msg += '웹서버에서 오류 발생...\n'
msg += '오류코드 : ' + httpRequest.status + '\n'
// Explorer에서 한글인자호출시 400에러가 난다?
}
msg += "===================================================\n"
break
}
debugTrace(msg)
}
function debugTrace(msg){
//debug메시지 출력하는 메소드
let degug = document.getElementById("debug")
debug.value += msg
}
</script>
</head>
<body>
<h2>XMLHTTPRequest 모듈을 이용한 예제</h2>
<form name="inputForm">
<textarea rows="10" cols="80" id="debug"></textarea><br>
이름 : <input type="text" name="name"><br>
나이 : <input type="text" name="age"><br>
주소 : <input type="text" name="addr"><br>
<button type="button" onclick="clickBtn()">서버에 자료 요청</button>
</form>
</body>
</html>
6-3. sample.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
if(request.getMethod().equals("POST")){
request.setCharacterEncoding("utf-8");
}
%>
안녕하세요 ${ param.name } 회원님<br>
회원님의 나이는 ${param.age}<br>
회원님의 주소는 ${param.addr}