2013년 9월 7일 토요일

[Head First]Servlets & JSP 내용정리-6장

Chapter.06 - 세션관리(대화 상태 유지하기)


  1. 클라이언트를 구분하기위해서 IP는 사용할수 없다. (NAT 사용하면 동일하다)
  2. HTTPS나 ID 요청은 꼭 필요할 때만 사용하도록 합니다.
  3. 클라이언트에게 필요한 것은 유일한 세션ID 가 필요하다.
  4. 클라이언트와 컨테이너 사이에 세션ID를 공유하는 방법 - Cookie
  5. 컨테이너가 모든 Cookie 작업을 수행 합니다.
    • Response 객체에 세션 Cookie 보내기 / 받기
      즉 HttpSession session = request.getSession();에서 getSession 부분에서 쿠기 생성 및 관련 모든 작업을 수행함.
    • session.isNew() : 세션이 새로 생성되었으면 true 입니다.
  6. Request 객체 이외 세션을 얻는 다른 방법은?
    HttpSessionEvent 혹은 HttpSessionBindingEvent에서 얻을 수 있음.
    HttpSessionListener 인터페이스 구현에서 아래와 같이
    public void sessionCreated(HttpSessionEvent event){
    HttpSesssion session = event.getSession();
    }
  7. 이미 만들어진 세션을 원할때
    getSession(boolean)에서 getSession(false)를 호출하면 되고 만약 존재하지 않으면 null을 리턴 합니다.
  8. 클라이언트가 Cookie를 사용하지 않는 경우에도 작동하도록 하는 방법
    URL 재작성 : URL + ;jessionid=1234567
    관련 메소드 : response.encodeURL(“”)
    public void doGet(HttpServletRequest request....){
     HttpSession session = request.getSession();
     out.println(“<a href=\””+response.encodeURL(“/BeerTest.do”)+”\”>click me</a>”);
    }

    • JSP로 보내고 세션은 계속 유지 하고 싶은 경우 : response.encodeRedirectURL(“$URL”);  
      JSP에서는 JSTL 태그 <c:URL>

    주요 HttpSession 메소드
    메소드명
    하는 일이 무얼까요?
    어떤 경우에 쓸가요?
    getCreationTime()
    세션이 생성된 시간을 리턴함.
    세션이 얼마나 오래 되었는지 알고 싶을 때.
    특정 시간만 세션을 사용하도록 제한하는데 사용될 수 있다. (로그인 후 10만 사용)
    getLastAccessedTime()
    이 세션으로 들어온 마지막 요청 시간을 리턴합니다.(밀리초 단위)
    클라이언트가 언제 마지막으로 세션에 접근 했는지 알고 싶을때. 클라이언트가 장시간 사용이 없을 경우, 메일을 보내 다시 사용하러 올것인지 물어 볼때 사용할 수 있겠죠.
    setMaxInactiveInterval()
    해당 세션에 대한 요청과 요청간의 최대 허용시간 (초 단위)을 지정
    클라이언트의 요청이 정해진 시간이 지나도 들어 오지 않을 경우. 해당 세션을 제거하기 위하여 사용함. 서버 상에 짝 잃은 세션을 최소화하기 위해 사용합니다.
    getMaxInactiveInterval()
    해당 세션에 대한 요청과 요청간의 최대 허용시간 (초 단위)을 리턴합니다.
    세션이 얼마나 오랫동안 비활성화 상태였는지, 여전히 살아있기는 한지 알고 싶을 때. 세션이 invalidate() 되기까지 시간이 얼마나 남았는지 알기 위하여 사용할 수도 있습니다.
    invalidate()
    세션을 종료합니다. 이 작업에는 현재 세션에 저장된 모든 세션 속성을 제거하는(unbind) 작업이 포함됩니다.
    클라이언트가 비활성화이거나 세션작업이 완료되어 강제로 세션을 종료할 때(예를 들면 장바구니 결제를 완료했을때). 세션 객체 자체는 컨테이너가 내부적으로 재사용합니다. 여기에 대해선 여려분의 신경쓸 필요가 없죠.
    invalidate()는 세션ID가 더 이상 존재하지 않으니, 관련 속성을 세션 객체에서 제거하라는 의미입니다.

    세션이 종료되는 세 가지 이유
    • 시간이 다 되어서(타임 아웃)
    • 개발자 세션 객체에 invalidate() 메소드를 실행하는 경우
    • 애플리케이션이 다운되는 경우(문제가 생겨 다운되거나, 언디플로이(undeploy)되는 경우).

    DD에서 세션 타임아웃을 설정하기 및 특정세션만 타임 아웃 설정하기
    <web-app ...>
     <session-config>
         <session-timeout>15</session-timeout>
         -------------------------------------
         15는 분을 의미 합니다.
     </session-config>
    </web-app>

    특정 세션만 타임 아웃 설정하는 코드
    session.setMaxInactiveInterval(20*60);  //여기서는 초단위 임.
                                  -----
    만약 0 초 이면 바로 타임 아웃 처리를 합니다.

    세션 관련 리스너들
    시나리오
    리스너
    인터페이스/메소드
    이벤트 타입
    일반적으로 구현하는
    클래스
    얼마나 많은 동시 사용자가 있는지 알고 싶을 때. 즉 활성화된 세션들 뒤를 캐고 싶을 때
    HttpSessionListener
    (javax.servlet.http)
    sessionCreated
    sessionDestroyed
    HttpSessionEvent
    An attribute class
    Some other class
    세션이 다른 VM으로 옮겨가는 것을 알고 싶을 때
    HttpSessionActivationListener
    (javax.servlet.http)
    sessionDidActivate
    sessionWillPassivate
    HttpSessionEvent
    An attribute class
    Some other class
    속성 클래스(속성의 값으로 사용되는 클래스)가 있고,이 타입의 클래스가 세션에 바인딩되거나 제거될 때를 알고 싶을 때.
    HttpSessionBindingListener
    (javax.servlet.http)
    valueBound
    valueUnbound
    HttpSessionBindingEvent
    An attribute class
    Some other class
    속성을 세션에 추가,제거, 대체를할 때를 아록 싶을 때
    HttpSessionAttributeListener
    (javax.servlet.http)
    attributeAdded
    attributeRemoved
    attributeReplaced
    HttpSessionBindingEvent
    An attribute class
    Some other class

[Head First]Servlets & JSP 내용정리-5장

Chapter.05 서블릿은 독불장군이 아니다.

서블릿 초기화 파라미터
  • 관련 클래스 javax.servlet.SevrletConfig
  • 서블릿 하나 마다 한개 생성됨.
  • 컨테이너를 DD에서 초기화 파라미터 정보를 읽어서 ServletConfig에게 넘기고 서블릿을 초기화 할때 init() 메소드에 넘김
  • 초기화 할때 단 한번만 서블릿 파라미터를 읽는다. (그러므로 변경을 하고 적용할때 컨테이너를 재구동해야 함.)
  • JSP에서 서블릿 파라미터 접근방법
    • request에 속성을 추가하여 전달 방식
서블릿 초기화 파라미터 web.xml (DD) 설정 예
<web-app ...>
 <servlet>
 -----------
 컨테이너가 관리하는 서블릿 클래스에 대한 정보를 알수 있음.
   <servlet-name>Chapter1 Servlet</servlet-name>
   <servlet-class>Ch1Servlet</servlet-class>
   <init-param>
   -------------
   서블릿 하위에 존재한다는 것에 주의 (getServletConfig() 메소드와 관련)
      <param-name>adminEmail</param-name>
      -----------------------------------
      파라미터 이름 (getServletConfig().getInitParameter(“adminEmail”))
      <param-value>cosmoslight.huni@gmail.com</param-value>
      -----------------------------------------------------
      파리미터 값
   </init-param>
 </servlet>
</web-app>

컨텍스트 초기화 파라미터
  • 관련 클래스 javax.servlet.ServletContext
  • 모든 웹 에플리케이션에서 이용할 수 있음.
  • 관련 메소드 getServletContext().getInitParameter(“$para_name”);
  • 웹 애플리케이션 당 하나
  • 동적으로 설정 불가능
  • 배포시 정해진 상수
  • JSP에서 내장된(implicit) 형태로 접근
  • ServletContext 얻는 방법
    1. getServletConfig().getServletContext();
    2. this.getServletContext();
  • ServletContext Interface (javax.servlet) :
    • 초기화 파라미터 및 속성 관련 메소드
      • getInitParameter(String)
      • getInitParameterNames()
      • getAttribute(String)
      • getAttributeNames()
      • setAttribute(String , Object)
      • removeAttribute(String)
    • 서버/컨테이너 정보
      • getServerInfo()
      • getMajorVersion()
    • 기타
      • getRealPath()
      • getResourceAsString(String)
      • getRequestDispatcher(String)
      • log(String)
컨텍스트 초기화 파라미터 web.xml (DD) 설정 예
<web-app ...>
 <context-param>
 ---------------
    <param-name>adminEmail</param-name>
    -----------------------------------
    파라미터 이름 (getServletContext().getInitParameter(“adminEmail”))
    <param-value>cosmoslight.huni@gmail.com</param-value>
    -----------------------------------------------------
    파리미터 값
 </context-param>
</web-app>

ServletContextListener
  • 역할 : ServletContext 생성(초기화)과 소멸 이벤트를 받을 수 있다.
  • 패키지명 : javax.servlet
  • 용도 : 켄텍스트 전체에 대한 초기화작업을 하거나 종료시 작업을 수행 할 수 있다.

컨텍스트 리스너 설정 web.xml (DD) 설정 예
<web-app ...>
 <listener>
   <listener-class>
     com.example.MyServletContextListener
   </listener-class>
 </listener>
</web-app>

리스너 8 종
시나리오
리스너 인터페이스
이벤트 타입
웹 애플리케이션 컨텍스에 속성을 추가/제거/수정 했는지 알고 싶을때
javax.servlet
ServletContextAttributeListener
  • attributeAdded
  • attributeRemoved
  • attributeReplaced
ServletContextAttributeEvent
얼마나 많은 사용자가 동시에 접속하고 있는지 알고 싶을 때  즉 현재 Active된 Session 정보를 알고 싶을 때
javax.servlet.http
HttpSessionListener
  • sessionCreated
  • sessionDestroyed
HttpSessionEvent
요청이 들어올 때마다 이 사실을 알 수 있을까?
javax.servlet
ServletRequestListener
  • requestInitialized
  • requestDestroyed
ServletRequestEvent
Request 속성(attribute)이
추가/제거/수정 되었는지 알고 싶을때
javax.servlet
ServletRequestAttributeListener
  • attributeAdded
  • attributeRemoved
  • attributeReplaced
ServletRequestAttributeEvent
속성 객체가 하난 있는데, 이 타입의 객체가 세션에 바인딩 되었는지 아니면 제거됐는지 알고 싶을 때
javax.servlet.http
HttpSessionBindingListener
  • valueBound
  • valueUnbound
HttpSessionBindingEvent
세션 속성이 추가/제거/수정 되었는지 알고 싶을 때
javax.servlet.http
HttpSessionAttributeListener
  • attributeAdded
  • attributeRemoved
  • attributeReplaced
HttpSessionBindingEvent
컨텍스트가 생성/소멸 되었는지 알고 싶을 때
javax.servlet
ServletContextListener
  • contextCreated
  • contextDestroyed
ServletContextEvent
속성 객체가 세션에 바인딩한 이 타입의 객체가 다른 JVM으로 옮겨 갔는지
javax.servlet.http
HttpSessionActivationListener
  • sessionDidActive
  • sessionWillPassivate
HttpSessionEvent

속성이란
3개의 서블릿 API 객체(ServletContext,HttpServletRequest(또는 ServletRequest),httpSession 객체 중 하나에 설정해놓는(바인딩) 객체를 말합니다. 저장형태는 Map(K,V) 라고 생각해도 무방

속성과 파라미터의 차이(표)
항목
속성
파라미터
타입
Application/context
Request
Session
Application/context 초기화 파라미터
Request 파라미터
Servlet 초기화 파라미터
설정 메소드
setAttribute(String name,Object value)
애플리케이션/서블릿 초기화 파라미터 값은 런타임 시 설정 불가. 오직 DD에서만 가능
Request 파라미터는 Query String을 설정할 수 있음.
리턴 타입
Object
String
참조 메소드
getAttribute(String name)
getInitParameter(String name)

속성의 생존 범위
인터페이스 종류
접근
생존범위
가장 적 당한곳
Context
스레드-안전(X)
웹 애플리케이션에 있는 것은 어떤 것이든. 서블릿, JSP,
ServletContextListener
ServletContextAttributeListener
ServletContext의 생존기간은 애플리케이션과 동일함.
서버나 애플리케이션이 내려가면 컨텍스트도 소멸됨.
전체 애플리케이션에서 공유하고자 하는 자원. DB Connection. JNDI 검색명, 이메일 주소
HttpSession
스레드-안전(x)
특정 세션에 접근할 수 있는 어떤 서블릿이나 JSP 모두.세션은 여러 개의 요청에 대하여 정보를 간직할 수 있습니다. 한 서블릿뿐만 아니라 여러 서블릿에 대해서도 가능합니다.
세션의 생존시간. 세션을 프로그램적으로 소멸시킬 수 있으며 간단히 시간이 만료될수도 있습니다.
하나의 Request에만 관련된것이 아니라 클라이언트 세션에 관련 데이터와 자원.
클라이언트와 지속적인 대화를 유지 하고 싶은 것들. 장바구니
Request
스레드-안전(O)
애플리케이션 내에서 Request객체에 직접 접근이 가능한 것모두. RequestDispatcher를 사용하여 요청을 처리할 수 있는 서블릿이나 JSP를 대부분 의미. 물론 Request 관련 리스너도 포함함.
Request의 생존 시간. 서블릿의 서비스 메소드가 끝날때 까지 입니다.
즉 스레드(스택)가 Request를 핸들링할 때 까지만 살아 있는 것 입니다.
모델 정보를 컨트롤러에서 뷰로 넘길때.. 또는 특정 요청에만 관련된 데이터등.

속성 API
  • Object getAttribute(String name)
  • setAttribute(String name,Object value)
  • removeAttribute(String name)
  • enumeration getAttributeNames()

스레드에 안전하게 하기 위해서(컨텍스트 속성을 보호하기 위해서)

  • 서비스 메소드(doGet 혹은 doPost)에 락을 걸면 느려지고 스레드가 보호되지 않는다.
  • 컨텍스트에 대한 락을 걸어야 합니다.
    public void doGet(HttpServletRequest request....){
     …
     synchronized(getServletContext()){
       getServletContext().setAttribute(“foo”,”22”);
       
       out.println(getServletContext().getAttribute(“foo”));
     }  
    }

    HttpSession 동기화로 세션 속성 보호하기
    public void doGet(HttpServletRequest request....){
     …
     HttpSession session = request.getSession();
     synchronized(session){
       .. 관련코드
     }  
    }

    서블릿에서 정보를 공유하기
    • 변수를 인스턴스 변수가 아닌 서비스 메소드의 지역 변수로 선언한다.
    • Context,Session,Request 중에서 가장 적당한 속성의 생존범위를 사용한다.

    RequestDispatcher에 대해서
    • forward(),include()를 가지고 있음.
    • forward()는 처리요청을 넘길때 주로 사용됨.
    • ServletRequest로 부터 RequestDispatcher를 리턴받는 경우
    • 경로가 ‘/’로 시작하지 않으면 상대경로 임. (그러나 현재 웝애플리케이션을 벗어나지 못함)
    • ServletContext로 부터 RequestDispatcher를 리턴받는 경우
    • 상대경로는 사용하지 못하고 절대 경로만 사용가능 하다.
    • include() : 처리하고 다시 서블릿으로 오도록 한다는 기능임.
    • 주의 : os.flush()와 같은 메소드를 forward()호출하기 전에 호출하됨. 모두 끝...