아~이건 쫌 나중에 올릴려고 했는데...시간이 남는 관계로 후딱 해치워 버려야겠다.
현재 Struts2 + ibatis를 이용하여 간단한 프로젝트를 진행중이다.
그러던 와중. DB의 값을 5초마다 불러와서 페이지에 뿌려줘야 하는 그런 상황이 발생하였다.
이걸 어떻게 할까.!-_ -+ 5초마다 action을 태워야 하는데. 그럴려고 하니 그 뿌려질 페이지가 include된 페이지 인데.
스크립트에서 인터발을 사용하여 5초마다 action을 돌리려고 하니. 전체 페이지가 리로드 되는 상황이 발생.ㅠ _ㅠ
즉. 현재의 상황이 어떻게 되었냐면...
이런것을 만들어야 하는데. 본 페이지가 있고, 본 페이지에서 게시판이 만들어 지고~
그 위에 다른 페이지를 include 시켜서 5초마다 뿌려줘야 하는 상황이다.
즉 본 페이지는 리로드가 없어야 하고, 불러와지는 저 부분만 계속 변화하해야 한다.
이때 문득 생각난것이 ajax 였으나. Struts2를 사용하는 나로써! Struts2의 기능을 사용하기로 결씸.-_ -v
Struts2에서 지원해주는 ajax를 이용하기로 맘 먹었다. 짝짝짝~ 개고생의 길이 열리기 시작함.;;;
무튼 이것 또한 struts2.0 과 struts2.1 의 차이가 있으니...이런 쉬벡.! 한 3일 고생...;;;
그 차이는 앞부분에서 설명한 것을 읽어보면 나름 차이를 느낄 수 있다고 생각하며
여기서 사용되어질 태그 및 속성은 s태그의 url 속성과 sx 태그의 div속성이다.
나중에 언급하겠지만 struts2.0대에서의 s:url, s:div를 이용하는 방법을 말하겠다. 이건 뭐 책에 있으니.;;;
일단은 struts2.1로 하는것.!!!!!
무튼 여기서도 lib를 점검을 해보자면 나는
struts2-core-2.1.8.1.jar
struts2-dojo-plugin-2.1.8.1.jar
를 사용한다. 또 이런거 보고 저거만 lib에 넣고 되니 안되니 하면 곤란하다.;;;
struts2 + ibaits 설정 관련해서 글 올린게 있으니 참고바람.
암튼 서론이 길었다. 코딩을 시작해보도록합시다.
여기서 테스트로 프로그램을 만들 것은 간단하게 하나의 jsp에서 다른 jsp를 ajax 형태로 불러와서
몇초간격으로 계속 호출(action 호출)하는 것을 만들어 보도록 하겠다. 어떻게 액션이 계속 실행이 되고 있느냐는
호출되어질 페이지에 date를 사용하여 시간이 변하는 것으로 확인이 가능하겠다.
일단 ajaxAction.java, ajaxLayout.jsp, ajaxTest.jsp 를 만든다.
ajaxLayout.jsp는 원래의 페이지이고, ajaxTest.jsp는 호출되어질 즉, include되어질 페이지이다.
ajaxLayout.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sx" uri="/struts-dojo-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script language="javascript">
var controller = {
refresh : function() {},
start : function() {},
stop : function() {}
};
dojo.event.topic.registerPublisher("/refresh", controller, "refresh");
dojo.event.topic.registerPublisher("/startTimer", controller, "start");
dojo.event.topic.registerPublisher("/stopTimer", controller, "stop");
</script>
<sx:head parseContent="true" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ajax page autoRefresh</title>
</head>
<body>
<s:form>
<div>
<table width="400" >
<tr>
<td align="center">
<s:url id="goAjaxTest" value="ajaxTest.action" />
<sx:div
id="divAjax"
href="%{#goAjaxTest}"
updateFreq="1000"
showLoadingText="false"
listenTopics="/refresh"
autoStart="true"
executeScripts="true"></sx:div>
</td>
</tr>
</table>
</div>
<div>
<table width="400" bgcolor="#999999">
<tr>
<td>ajaxLayout Jsp 페이지</td>
<td>에서 만들어지는 리스트</td>
</tr>
<tr>
<td><s:property value="layout1" /></td>
<td><s:property value="layout2" /></td>
</tr>
</table>
</div>
</s:form>
</body>
</html>
자 여기서 보자면 일단 빨간색 형광펜으로 해놓은 것 중에 sx 태그라이브러리 추가.
head에 뭐 이상한거 그게 ajax 즉, dojo를 이용하기 위해 설정해놓은 것이다.
s 태그라이브러리는 왜 추가했나요~라고 하는 사람은 당장 저기 오른쪽 상단 모서리에 있는 X를 눌러라.
글을 제대로 안읽으면 다음 부분을 읽을 필요도 없다. 암튼 앞에 언급했듯이 s:url을 쓰기 위해서다.-_ -+
그리고 빨간색 글자로 된 부분이 인클루드를 시키는 부분이다. 저 부분에 ajaxTest.jsp가 불러 와지는것이다.
그냥 jsp가 include되는 것이 아닌 action이 행해진 후 include가 되는 것이다.
<s:url id="goAjaxTest" value="ajaxTest.action" /> 은 id를 goAjaxTest 하고,
value는 액션의 값, 즉 실행되는 액션의 주소를 적는 부분이다. 저렇게 되어 있으면 struts.xml에 설정된 ajaxTest라는 액션을 실행한다.
그리고 밑에 sx:div 부분인데. 이게 원래 struts2.0 버전에서는 그냥 s:div로 되어 있단 말이지. 그렇게 된다면 head에 지금처럼
선언하는게 아닌 <s:head theme="ajax" />라고 선언해야 된다.
그리고 sx:div 태그에서 빠진 theme="ajax"라는 속성도 추가 해주어야 한다. 흠흠. 이건 struts2.0의 버전에서 하는 것이고
지금 우리는 2.1에서 하는 것이니 속성들을 살펴보도록 하자.
href="%{goAjaxTest}" 는 눈치 빠른 분들은 알겠지만 s:url에서의 id 값을 설정하게 되는 것이다.
그렇게 url값인 action을 호출하게 되는 것이다.
updateFreg 속성은 1/1000 초 단위로 1000을 설정하게 되면 1초마다 호출하겠다는 것이다.
showLoadingTest 는 ajax를 구동할때 시간 텀에 어떠한 텍스트를 보여준다. true로 한번 해보시라.;;;
listenTopics="/refresh" 이게 저기 위에 스크립트에 설정되어진 refresh함수를 호출해서 dojo 이벤트를 실행시키는 것이다.
autoStart="true" 당연히 true가 되어야 자동으로 돌아가겠지.
그리고 속성중에 indicator 이란게 있는데 이걸 <img src>로 이미지를 불러 놓고 id 를 설정해서
indicator="설정된 id" 를 해놓게 되면 그 왜 자주 보는거 있지 않나. 톱니바퀴 뱅그르르 돌아 가는거. 그게 실행이 된다.ㅋㅋ;;;
그리고 젤 중요한 이 씨발 속성.!-_ -+ executeScripts="true" 이게 되어 있어야 include 되는 페이지에서 script를 실행할 수 있다.
아놔. 이걸 몰라서 스크립트 실행 왜 안되냐고 졸라 썽냈네.;;; 아오.!!!!-_ -+ 정말 짜증나!ㅋㅋ
그리 밑에 div로 잡아 놓은 것은 ajaxLayout.action에서 들고오는 값들을 뿌리기 위해서 해놓은것.
저게 본페이지 액션을 호출하여 생성된 리스트다. 라고 생각하면 될듯.
ajaxTest.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ajaxTest</title>
</head>
<script language="javascript">
function timer(){
var src = "<table border=0 width=400><tr>";
var color;
today=new Date();
y=today.getYear();
m=today.getMonth()+1;
d=today.getDate();
hh=today.getHours();
mmm=today.getMinutes();
ss=today.getSeconds();
if(ss % 2 == 0){
color = '#FFB6C1';
}
else{
color = '#40E0D0';
}
src += "<td align=center bgcolor=" + color + ">" + y + "년" + m + "월" + d + "일" + hh + ":"
+ mmm + ":" + ss + "</td>";
src +="</tr>";
src +="</table>";
document.getElementById('tb').innerHTML = src;
}
</script>
<body>
<script>timer();</script>
<div id="tb"></div>
<div><s:property value="test1"/> 오예 <s:property value="test2"/></div>
</body>
</html>
이 페이지는 역활은 ajaxTest.action을 타고 들어 오면 script를 바로 호출해서 시간을 뿌리는 형태이다.
그리고 s 태그라이브러리를 추가하여 ajaxTest.action 에서 값을 들고 오는 것을 뿌려준다. 하단에 <s:property value="test"/> 이부분.
그리고 스크립트를 바로 온로드 하기 위해서 <script>timer();</script> 이렇게 하였다. -_ -;;;
안다. body 부분에 onload="timer()" 로 안했나여~~ 왜 안했겠습니까? 안되니까.;;
안다. 그럼 script에서 window.onload = timer; 하면 되잖아여~ 왜 안했겠나. 안되니까.;;;
안다. 그럼 <body><script type="text/javascript"> window.onload = function(){ timer(); }; 로 하면 되잖아여~</script></body>
이런 씨발~! 안되잖아.!!!-_ -+ ㅎㅎㅎ 죄송..;;;
무튼 저렇게 스크립트로 작성된 것이 <div id="tb"> 라는 곳에 담겨서 시계가 출력이 되게 된다.
지금 ajaxLayout.jsp와 ajaxTest.jsp가 이렇게 되어 있다면 1초마다 ajaxTest.action을 호출 하게 될 것이고
include 된 페이지에서 시계가 출력되며 시계바탕 색이 계속 바뀌게 될 것이다.
ajaxAction.java
package sample;
import com.opensymphony.xwork2.ActionSupport;
public class ajaxAction extends ActionSupport {
private String layout1;
private String layout2;
private String test1;
private String test2;
public ajaxAction(){}
public String ajaxLayout(){
layout1 = "ajaxLayout Action Method";
layout2 = "TEST SUCCESS";
return SUCCESS;
}
public String ajaxTest(){
test1 = "ajaxTest Action Method";
test2 = "TEST SUCCESS";
return SUCCESS;
}
public String getLayout1() {
return layout1;
}
public void setLayout1(String layout1) {
this.layout1 = layout1;
}
public String getLayout2() {
return layout2;
}
public void setLayout2(String layout2) {
this.layout2 = layout2;
}
public String getTest1() {
return test1;
}
public void setTest1(String test1) {
this.test1 = test1;
}
public String getTest2() {
return test2;
}
public void setTest2(String test2) {
this.test2 = test2;
}
}
뭐 여기서는 특별한 것은 없고 각 액션 호출 했을때마다 값을 넘겨주는 것이랄까.
현재 기본은 이렇지만 이 액션 메소드들에서 많은 작업이 이루어 질 것이다.
DB값을 5초마다 뿌려줄려면 ajaxTest 메소드에서 DB값을 들고 오는 로직을 작성해야겟지.
뭐 기분으로 struts.xml 도 함 올리준다.
struts.xml
<action name="ajaxLayout" class="sample.ajaxAction" method="ajaxLayout">
<result>/sample/ajaxLayout.jsp</result>
</action>
<action name="ajaxTest" class="sample.ajaxAction" method="ajaxTest">
<result>/sample/ajaxTest.jsp</result>
</action>
action name이나 method는 같겠지만 class나 result 같은 값은 자기 속성에 잘 맞추도록.
아무튼 이렇게 그냥 jsp include가 아닌 액션이 이루어진 jsp를 include 하는 시간을 가져보았다.
이걸 좀더 유도리 있게 사용하게 되면 아주 괜찮은 프로그램이 나오지 않을까 생각한다.
예를 들면 10초 단위로 판매량이 DB에 값이 들어 온다고 치면
refresh를 30초 또는 1분으로 DB에서 판매량을 카운트해서 실시간 판매량을 보여준다던지.
딱 고부분만 변하게 되는 것이니까 웹페이지 자체가 리로딩 될 필요도 없고. 아주 멋지고 깔끔한게 탄생하지 않을까.ㅋ
음. 예제를 실행하기 전에 ajaxTest.jsp 페이지에서 <body onload="timer()">를 추가해주도록 하자.
원래는 액션을 어떤것을 호출해야 할까? 당연히 원래는 ajaxLayout.action을 실행하여야 한다.
하지만 ajaxTest라는 놈이 어떻게 생겼는가...확인 하기 위해서 일단은 ajaxTest.jsp 및 ajaxTest.action을 호출 하여 보자.
ajaxTest.jsp 실행 화면
이렇게 액션을 수행하지 않은 모습을 알 수 있다. 뭘로? s:property value="test1" "test2"의 값이 보이지 않으니까.
ajaxTest.action 실행 화면
성공적으로 action을 수행하였다. 저 보이는 값들.
그리고 이제 진짜 실행해야 할 것. ajaxLayout.jsp 와 ajaxLayout.action을 실행해보자.
jsp로 실행을 하던, action으로 실행을 하던 상단에 include되어 시계가 나올것이다.
왜냐. jsp를 호출하던 action으로 호출을 하던 ajaxLayout.jsp에 코딩되어진 s:url과 sx:div는 유지 되고 있기때문에
계속 ajaxTest.action을 호출을 하고 있기 때문이다.
다만 다른 것은 아래 회색의 텍스트 중에 .jsp로 실행을 하였을때는 ajaxLayout Action Method TEST SUCCESS가
보이지 않을 것이다. 이로써 action을 거치지 않고 그냥 jsp를 호출 했다는 것을 알 수 있다.
아래의 그림은 ajaxLayout.action을 실행한 최종 결과의 모습이다.
이미지의 시간은 다르지만. 실제 1초마다 분홍색과 초록색으로 색이 바뀌고 초시계도 1초단위로 변화하고 있을 것이다.
뭐 이 예제는 간결한 코딩으로 이루어져 있기때문에 1초마다의 변화가 눈에 보이겠지만 action단이나 serviceImple단, DB작업이
많은 경우에는 속도는 어느정도 느려질꺼라는 예상은 해야 할듯. 뭐 나는 참고로 DB 두번 돌리고 여러작업을 했는데 1초 단위로
작업 잘 되더라.ㅋ 그래도 혹여나 몰라서 5초단위로 바꿨지만.;;;
지금까지 struts2의 각 s:url 태그 및 sx:div 태그를 이용해서 자동 refresh 되는 것을 해보았다.
여러 속성들. 그리고 예상치 못한 일들이 많았지만 위 처럼하면 무리 없이 예제정도는 할 수 있으리라 생각한다.
정작 한건 별로 없는데 글만 디게 길어 졌구만.ㅋㅋ
이 글의 요는!!! 자동 refresh 기능도 struts2에서 지원한다.!
그리고 2.1과 2.0의 버전에서는 좀 다르게 사용해야 한다. 고정도만 알면 뭐 다 안거랑 마찬가지란 말.
그럼 수고하였소.!!!
다음엔 s:action에 대해서 알아보도록 합시다. 이것도 뭐 이번 예제인 include 하는 비슷한 상황인데.
사용법도 틀리고 사용하는 상황에서도 틀리니. 담에 기회되면 글을 남겨보도록 하겠소.