JSP Action 태그는 XML을 이용하여 JSP의 태그 문법들을 확장시켜준다.


브라우져가 아닌 웹 컨테이너에서 실행되어 연산 결과를 브라우져에 전달해준다.





JSP 기본 제공 태그는 다음과 같다.


jsp:include             현재 페이지에 특정 페이지를 포함시킴


jsp:forward            페이지를 특정 페이지로 이동시킴 ( = request.forward())


jsp:param              해당 페이지에 전달할 값을 기록


jsp:usebean            Java bean 객체를 사용하기 위한 태그


jsp:setProperty        java 모델 vo의 Setter와 같음


jsp:getProperty        java 모델 vo의 Getter와 같음








간단한 예




- 페이지 포함


<jsp:include page="common.jsp"/>


- 다른 페이지로 이동 시킬 때 request 값까지 설정


    <% request.setAttribute("name", "김둘리"); %>


    <jsp:forward page="testForward.jsp"></jsp:forward>


값 설정에는 따로 키워드가 없어서 이전과 같은 방식으로 사용






useBean은 자바 객체 파일을 불러와 필드 값을 컨트롤 한다. setProperty와 getProperty가 함께 쓰임


    <jsp:useBean id="m" class="com.kh.el.model.vo.Member" scope="page"></jsp:useBean>
    <!-- java 파일에서 id = 변수명, class = import문 scope = 이 페이지에서만 쓰겠다. -->


    <jsp:setProperty property="name" name="m" value="김둘리"/>

    <!-- java에서 m.setName("김둘리"); 와 같음 -->


    <jsp:setProperty property="age" name="m" value="20"/>
    <jsp:setProperty property="phone" name="m" value="010-1234-5678"/>
    <jsp:setProperty property="email" name="m" value="dullee@kkan.or.kr"/>
   
    <!-- setProperty가 Setter 였다면??  getProperty는 Getter이다. -->
    이름 : <jsp:getProperty property="name" name="m"/><br>
    나이 : <jsp:getProperty property="age" name="m"/><br>
    전화번호 : <jsp:getProperty property="phone" name="m"/><br>
    이메일 : <jsp:getProperty property="email" name="m"/><br>





http://tomcat.apache.org/taglibs/standard/



위의 톰캣 사이트에서 Jar 파일 받아서 lib에 추가하면 된다.


버젼은 1.2를 사용하고


이후에 나온 버전은 여러가지 기능들이 분리되어 파일이 여러개가 된다고 한다..?



jstl-1.2.jar


같은 파일이므로 이것을 받아도 된다.








Action태그, EL 태그란 Session이나 Attribute Parameter와 같은 형식으로


받은 데이터나 직접 변수를 선언하여 사용하거나


함수들을 매우 간편하게 사용 할 수 있는 기능이다.







먼저 서블릿에서 데이터를 받았을 때 사용했던 방식을 살펴보자


JSP 페이지 상단에


<%@page import="com.jsp.member.model.vo.Member"%>



Member mem = (Member)session.getAttribute("member")


%>


바디 부분


<body>

<p><%=mem%></p>

</body>



위와 같은 형식으로


객체를 불러오고, 변수 선언, 값 불러오기, 형 변환을 거처서 사용했다.





하지만 JSTL을 사용하면 많이 줄어든다.


<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


위에 tag 라이브러리 c(core)를 사용한다고 선언하고


바로 바디 부분에서


<p>${ member }</p>


위와 같이 사용할 수 있다.


몰론 생략된 구문이 몇개가 있다.


Scope 연산자라고 불러온 값이 Session 값인지 parameter 값인지 등 구분하는 키워드를 앞에 붙여주는 것이다.


만약 Session과 parameter에 같은 이름으로 값을 전달했다면 어느 데이터를 가져오는지 확실치 않기 때문..


불러오는 우선순위가 있어 상관없지만 많은 값들을 기억하기 힘드니 명시하는것을 추천


${ sessionScope.member }


다음 글에서 자세히 설명한다.

















JSP에서 실시간으로 통신을 사용할 때 소켓을 이용하게 된다.


미리 구현이 되어 있기 때문에 선언만 하고 메소드를 사용하게 된다.


기본 형태는 JSP에서 Jquery 형식으로 스크립트에 작성하게 된다.


JSP 스크립트 < - > 서블릿과 유사한 ServerEndPoint로


맵핑된 주소로 실시간으로 통신을 하게된다.





기본형태




// 먼저 페이지 시작 시 바로 getConnection 함수를 호출해 Server와 연결한다고 선언


$(function(){
     getConnection();

})



// getConnection이 호출 될 때 연결을 위해 사용하는 메소드들


function getConnection(){
     ws = new WebSocket("ws://localhost:8001" + '<%=request.getContextPath()%>/serverStart');


     // 서버 시작할 때 동작
     ws.onopen = function(event){

     }


     // 서버로부터 메세지를 전달 받을 때 동작하는 메소드

     // 아래에 선언 할 onMessage로 event가 전달된다.

     ws.onmessage = function(event){
           onMessage(event);
     }
               
     // 서버에서 에러가 발생할 경우 동작할 메소드
     ws.onerror = function(event){
          onError(event);
     }
               
     // 서버와의 연결이 종료될 경우 동작하는 메소드
     ws.onclose = function(event){
          onClose(event);
     }
}
           
           


// 전달할 String형 msg를 ws.send를 통해서 소켓으로 전달한다.

function send(msg){
     ws.send(msg);
}




// 서버에서 메시지를 전달 받을 때 event 매개변수로 값을 받고

// 이 메소드에서 event 값을 통해 무엇을 할 것인지 정한다.

function onMessage(event){


     // String 형태로 데이터가 넘어오므로 구분자를 통해서 사용하면 된다.


     // 구분을 "메세지:구분:아이디"와 같다고 할 때

     // 만약 event값이 "메세지내용:msg:3"과 같이 전달 되었다면

     // ":"를 split 메소드를 이용하여 분리하면 담긴 변수에는


     // serverMessage[0] = "메세지내용"

     // serverMessage[1] = "msg"

     // serverMessage[2] = "3"


     // 위와 같이 분리된다.


     // 아래의 예처럼 if문을 이용해서 잘 쓰면 된다.


     var serverMessage = event.data.split(":");


     if(serverMessage[1] ==  "msg") // msg, 메세지일 때

          alert(serverMessage[2] + "님의 메세지 : " + serverMessage[0]);

     } else if (serverMessage[1] == "alarm") {

          alert("알람이 있습니다."):

     }


    

}



// 소켓통신 에러 발생 시
function onError(event){
     alert(event.data);
}
// 소켓통신이 끝낫을 때
function onClose(event){
     alert(event);
}








body 부분에서는 예를들어 버튼에다가


<button onclick="send("안녕하세요:msg:3")"></button>


위와 같이 버튼이 있고 클릭하면 위에서 선언된 메소드인 send가 실행되어


ws.send()로 소켓을 통해 서버로 메세지가 전달이 된다.





다음은 서버에서 메세지를 받을때 파일의 예



코드를 보면 어노테이션을 통해 @ServerEndpoint("/auctionStart") 를 통해서 맵핑이 이루어져 있고


ws = ~~~~ 하고 위에서 Jquery로 선언한 부분에 주소가 맞으면


이 EndPoint를 통해서 통신을 하게 된다.







package com.kh.auction.websocket;

import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/auctionStart")
public class AuctionStart {
    private static Set<Session> clients = Collections.synchronizedSet(new HashSet<Session>());

    @OnOpen
    public void onOpen(Session session) {
        //서버 연결한 시점에 동작하는 메소드
       
        //기존 사용자 리스트에 새로 연결 요청이 들어온 사용자를 추가한다
        clients.add(session);
    }

    @OnMessage
    public void onMessage(String msg, Session session) throws IOException {
        //서버로부터 데이터를 전송받을 경우 동작할 메소드
        System.out.println(msg);
       
        //하나의 일 처리를 수행하는동안 사용자의 변경이 일어나면 안된다.
        //즉 NullPointer를 방지하기 위해 동기화 처리를 해준다.
        synchronized(clients) {
            for(Session client : clients) {
                client.getBasicRemote().sendText(msg);
               
            }
        }
    }
   
    @OnError
    public void onError(Throwable e) {
        //데이터를 전달하는 과정에서 에러가 발생할 경우 동작하는 메소드
        e.printStackTrace();
    }
   
    @OnClose
    public void onClose(Session session) {
        //지워주지 않으면 Set에 이미 나간 사용자가 남아있기 때문에 메세지 전송시 에러 난다.
        clients.remove(session);
    }
   
   
   
}















private static Set<Session> clients = Collections.synchronizedSet(new HashSet<Session>());


위의 선언을 통해서 현재 통신 시점의 모든 Session들의 정보를 담는다.


다른 부분은 건들일 일이 없는데 @OnMessage 이쪽 부분만 잘 사용하면 된다.


OnMessage 메소드를 통해서 전달된 String형 메세지가 이쪽으로 전달되고


데이터를 처리 한 후




synchronized(clients) {
            for(Session client : clients) {
                client.getBasicRemote().sendText(msg);
               
            }
}



synchronized 부분에서 아까 담았던 모든 session에게 해당 메세지를 전달한다.


client.getBasicRemote().sendText(msg); 이 부분을 수정하여


client의 값에서 id값과 같은 키값을 뽑아 조건문을 통해서


특정 대상만 구분하여 메세지를 보낼 수 있다.







synchronized 바로 윗 부분에서 msg 데이터를 마음대로 가공해도 되고 Service, Dao를 거쳐서


새로운 msg를 만들어도 된다.








결론



Endpoint 서버와 연결(이 때부터 소켓(ws)는 onMessage(event)를 계속 기다리고 있다.)


- ws.send를 통해 서버에 메세지 전달


- 서버에서 데이터 처리 후 세션에 데이터 전송


- 서버에서 메시지가 도착하면 onMessage(event)로 처리





메세지는 전부 String형으로 잘 컨트롤 해야 한다.


+ Recent posts