finerss's world!

컨테이너는 JSP 파일을 HttpJspPage 인터페이스를 구현한 서블릿 클래스로 변환하여 생성한다.
 
개발자로서 우리는 아래에 나와있는 서블릿 API만 이해하면된다.

 ▶jspInit()

init()메소드를 호출한다. 이 메소드는 재정의해도 무방하다.

▶jspDestroy()

서블릿의 destroy()메소드에서 호출한다. 이메소드또한 재정의해도 무방

▶_jspService()

서블릿의 service()메소드에서 호출한다. 즉 요청이 들어올떄마다 이 메소드는 새로운 스레드로 실행이 된다는 말이다
컨테이너가 알아서 Request 객체와 Response 객체를 매개변수로 넘겨준다
이 메소드는 재정의 하면 안됀다.(이메소드안에 들어갈 코드를 작성하는것 뺴고)


JSP 초기화 하기

JSP도 일반 서블릿과 마찬가지로 초기화 작업을 할 수 있다. 그러나 방식은 일반 서블릭과 조금 다른데

서블릿 초기화 파라미터 설정하기

일반 서블릿에서 서블릿 초기화 파라미터를 설정하는 방식과 유사하게 JSP 초기화 파라미터를 설정한다
차이점이라고는 <servlet-class> 태그가 아닌 <jsp-file> 태그를 사용한다는 것이다.
<web-app ...>
........
   <servlet>
            <servlet-name>MyTestInit</servlet-name>
            <jsp-file>/TestInit.jsp</jsp-file>
            <init-param>
            <param-name>Email</param-name>
            <param-value>abc@daum.com</param-value>
            </init-param>

   </servlet>
   <servlet-mapping>
//JSP에 대한 서블릿을 정의하려면, JSP 페이지에 대한 서블릿 매핑을 반드시 해야한다
            <servlet-name>MyTestInit</servlet-name>
            <url-pattern>/TestInif.jsp</url-pattern>
   </servlet-mapping>
</web-app>

jspInit() 재정의하기

방식은 아주 단순하다. jspInit() 메소드를 JSP 파일에 코딩해놓으면 컨테이너가 서블릿 인생이 시작하는
시점에 이 메소드를 호출한다. 물론 이메소드는 서블릿 init() 메소드에서 호출한다.
따라서 이 메소드가 실행되는 시점에서는 ServletConfig객체와 ServletContext 객체를 사용할수있다.

아래 예제는 jspInit()에서 DD에 설정되어 있는 서블릿 초기화 파라미터 값을 읽어오는 내용이다. 읽어온 값은
애플리케이션 범위에서 사용할 수 있도록 속성에 묶어둔다
<%! 
//jspInit()을 재정의하려면 <%! 선언문은 사용해야한다 <%를 쓰면 service()메소드 안으로 들어가버린다
     public void jspInit(){
             
            ServletConfig sConfig = getServletConfig()
            // 나중에 서블릿이 될 것이기 떄문에, 상속받은 getServletCOnfig() 메소드를 호출할수있다.

            String emailAddr = sConfig.getInitParameter("Email");

            ServletContext ctx = getServletContext();
         
            ctx.setAttribute("mail", emailAddr);
      }
%>




JSP 내에 있는 속성들

대부분의 경우 JSP에서 이용 가능한 4가지 생존범위 속성과 각각에 매치되는 내장 변수를 가지고 속성을 설정하고 읽고 한다.

표준 서블릿에 있는 request 범위, session 범위, application(context) 범위에 하나를 더추가해서

page 범위까지 총 4개이다. page 범위 속성은 pageContext 객체로 작업을한다.

  서블릿에서  JSP에서(내장 객체를 사용) 
 Application  getServletContext().setAttribute("foo",barObj);  application.setAttribute("foo",barObj);
 Request  request.setAttribute("foo",barObj);  request.setAttribute("foo",barObj);
 Session  request.getSession.setAttribute("foo",barObj);  session.setAttribute("foo",barObj);
 Page 제공하지않음   pageContext.setAttribute("foo",barObj);

pageContext로 속성 접근하기

pageContext는 자신에 설정되어 있는 page 범위 속성뿐만 아니라, 어떤 다른 생존범위 속성도 접근할 수 있을 정도로 매우 막강하다.

다른 생존범위 속성을 참조하려면, 메소드 매개변수로 범위를 나타내는 정수값을 넘겨야 한다. 사실 속성에 접근하는 메소드는

모두 JspContext로부터 상속받아 사용하지만, 속성을 나타내는 상수값은 PageContext에 정의되어 있다.





pageContext를 이용하여 속성을 읽고 설정하는 예제

page 생존범위의 속성 세팅하기
<% Float one = new Float(42.5); %>
<% pageContext.setAttribute("foo", one); %>


page 생존범위의 속성읽기
<%= pageContext.getAttribute("foo") %>


pageContext를 이용하여 session 생존범위 속성 세팅하기
<% Float two = new Float(23.5); %>
<%= pageContext.setAttribute("foo", two, PageContext.SESSION_SCOPE); %>


pageContext를 이용하여 session 생존범위 속성 읽기
<%= pageContext.getAttribute("foo", PageContext.SESSION_SCOPE) %>
(이것과 동일한 의미이다 <%= ssesion.getAttribute("foo")%> )


pageContext를 이용하여 application 생존범위 속성 읽기
<%= pageContext.getAttribute("mail", PageContext.APPLICATION_SCOPE) %>
(이것과 동일한 의미이다 <%= application.getAttribute("mail")%> )


pageContext를 이용하여 어떤 생존범위인지 모르는 속성찾기
<%= pageContext.findAttribute("foo") %>
//findAttribute() 메소드는 속성을 제일먼저 page 생존범위에서 찾는다. page생존범위 속성에 "foo"라는 이름을 가진놈이있으면
PageContext에서 getAttribute(String name)을 부르는 것과 똑같은 결과는 호출하는 것과 같다.
만약 "foo" 라는 이름이 page 생존범위에 없다면 가장작은 범위에서부터 시작해 가장 넓은 범위의 순으로 속성을 찾는다.
즉, request. session, application 속성범위 순으로 찾는다. 똑같은이름이 있더라도 가장 먼저찾은 놈이 넘어 간다.


3가지 지시자

1. page 지시자
<%@ page import="foo.*" session="false" %>
페이지 관련 환경(property)을 정의한다. 즉 문자 인코딩(character encoding), 응답페이지 컨텐츠 타입(content-type),
페이지가 내장 세션 객체를 가질 것인지 여부 등을 정의한다. page 지시자에는 서로다른 속성이 총13가지 존재

2. taglib 지시자
<%@ taglib tagdir="/WEB-INF/tags/cool" prefix="cool" %>
JSP에서 이용 가능한 태그 라이브러리를 정의한다. 뒤에서 자세히 설명

3. include 지시자

<%@ include file="wickedHeader.html" %>
변환시점에 현재 페이지에 포함할 코드나 문서를 정의한다. 여러 JSP페이지에 포함되어야 하는 코드가 있다면, 이를 따로 뽑아내어,
재사용 가능한 단위로 만들어 각각의 페이지에서 이를 포함하면 된다. 예를 들면 문서의 머리말이라든지 내비게이션 바 같은것등,,

'공부 > Sevlets&JSP' 카테고리의 다른 글

JSP 기초  (0) 2011.07.01
Session Listener(세션 리스너)  (0) 2011.06.30
세션(sisson) 관리  (0) 2011.06.29
RequestDispatcher  (0) 2011.06.29
동기화  (0) 2011.06.29

JSP 기초

공부/Sevlets&JSP2011. 7. 1. 10:34
JSP는 결국 웹 애플리케이션에서 돌아가는 서블릿으로 거듭나게된다.

컨테이너가 서블릿을 작성하는 과정은 JSP파일을 서블릿 소스코드(.java)파일로 바꾼ㄷ 뒤, 서블릿 클래스로 컴파일한다.

돌아왔는 바로왔든, 결국은 서블릿이된다. 컨테이너가 서블릿 클래스를 로딩하여 인스턴스화한 다음, 초기화 루틴을 호출하고,

요청이 들어올 때마다 스레드를 만들어, service() 메소드를 호출하는 과정이 정확히 일치한다.

JSP 안에서 자바코드는 <%...%> 태그안에 스크립틀릿(scriptlet)으로 작성한다.

JSP에서도 import문을 쓸수있는데 이걸 쓰려면 지시자를 알아야한다

패키지를 import하기 위해서는 page 지시자를 사용한다.

지시자(directive)는 컨테이너가 페이지를 자바 코드로 변환할 때 특별한 지시를 내릴 수 있도록 고안된 것이다.

지시자에는 3가지가 있는데 page, include, taglib이 그것이다.

일단 page 지시자만 알아보면 page지시자가 import를 가능하게 하는 녀석이다.

 <%@ page import="foo.*" %>
//패키지를 여러개 import할경우 <%@ page import="foo.*",java.util.*" %>
//지시자 끝에는 세미콜론이 없다.

<html>
<body>
the page count is:
<%
     out.println(Counter.getCount());
     //스크립틀릿에는 일반자바소스코드를 그대로 코딩하기떄문에 끝에 반드시 세미콜론이 있어야한다.
%>
</body>
</html>
자바코드는 퍼센트(%) 기호로 묶여있지만 지시자는 시작 부분에 다른문자가 포함되어있다.
JSP코드를보다가 <%@ 로 시작하는 구문을보면 지시자라는 것을 알아 차려야한다.

표현식

-스크립틀릿 코드- 
<%@ page import="foo.*" %>
<html>
<body>
the page count is:
<% out.println(Counter.getCount()); %>
</body>
</html>

-표현식코드-
<%@ page import="foo.*" %>
<html>
<body>
the page count is:
<%= Counter.getCount() %>
</body>
</html>
//표현식은 훨씬 간결하다. 여기서는 더이상 출력에 관련된 코딩을 할 필요가 없다.

<%= Counter.getCount() %> 에서 세미콜론이 빠진것이 이상하지않은가?

그이유는 표현식의 내용은 out.println()의 매개변수가 되기 떄문이다. 다시말하면 <%= 와 %> 사이에 입력한 내용을

내부 Response객체의 PrintWriter 객체인 out으로 출력하기 위한 매개변수로 넘긴다는 말이다.

컨테이너가 이런코드를 만나면

<%= Counter.getCount() %>

아래와같이 변환한다

out.print(Counter.getCount());

그러므로 표현식에 세미콜론을 입력했다면

<%= Counter.getCount(); %>

다음 같이 된다

out.print( Counter.getCount(); );

절대 표현식 끝에 세미콜론을 넣지 말자!



선언문

모든 스크립틀릿 코드와 표현식 코드는 service()메소드 안으로 들어간다

이는 스크립틀릿 안에 선언된 모든 변수는 모두 지역변수를 의미하는데,

선언문을사용해 인스턴스변수로 만들수도있다.

 <%! int count =0; %>
//퍼센트 뒤에 ! 를 붙이면된다
//표현식이아니므로 세미콜론을 붙인다.

<%! 와 %> 안에 들어가는 문장은 서비스 메소드 바깥으로 빠진다. 따라서 정적인 변수나 메소드 또는 인스턴스 변수나 메소드들
모두 여기에 코딩할수 있다.

JSP선언문을 기술하면 클래스 내부에, 서비스 메소드나 여타 메소드의 바깥 쪽에 위치하게 된다. 여기에 간단한 정적인 변수나 메소드
아니면 인스턴스 변수나 메소드를 만들수있다.

컨테이너가 JSP를 어떻게 바꾸는가...

JSP 컨테이너가 결국 서블릿으로 변환시킨다 이때 각각이 서블릿 코드로 어떻게 매핑되는지 알면 JSP 구조를 이해하는 데 도움이된다.

▶ 먼저 지시자(directives)가 있는지 보고선, 변환 작업할때 필요한 정보를 읽는다.

▶HttpServlet의 하위 클래스를 생성

▶import 속성을 가진 page 지시자가 있으면, 클래스 파일의 정의 위에, 패키지 선언 아래에 import문을 넣는다

▶선언문이 있으면, 클래스 파일안에, 서비스 메소드위에, 서블릿 선언 아래에 코딩한다.

▶service()메소드를 만든다. 서비스 메소드의 실제 이름은 _jspService()이다.
   이메소드는 서블릿의 부모 클래스에 정의된 service() 메소드를 이녀석이 호출한다.
   물론 매개변수 HttpServletRequest와 HttpServletResponse를 받는다. 서비스 메소드 처리를 위임받았다고 생각하면된다
   바로밑에 모든 내장객체를 선언하고, 초기화 하는 문장이나온다(밑에 내장객체설명)

▶템플릿 텍스트라고 불리는 HTML과, 스크립틀릿, 표현식을 서비스 메소드 안에 차례대로 Response객체의 출력 스트림인
    PrintWriter의 출력 형식에 맞게 코딩한다.


내장객체


컨테이너가 JSP를 서블릿으로 변환하는 과정 중, 서비스 메소드 선언 다음에 한 묶음의 내장 객체를 선언하고 값을 할당하는 부분이 있다.

JSP를 작성하면서 JSP가 서블릿이 된다는 것을 알기 떄문에, 내장객체를 사용할수있는것이다. 개발자가 서블릿 객체를 직접 코딩하진 않지만,

서블릿이 가지고 있는 특징, 즉 서블릿적인 것(Servletness)을 사용 할수 있다는 말이다.

모든 내장 객체들은 서블릿/JSP API에 일대일로 매핑된다.

예를들면 내장 객체인 request는 컨테이너가 서비스 메소드 매개변수로 넘겨준 HttpServletRequest 객체에 매핑된다.

                API                                         내장객체

                JspWriter    -----------------             out        
     HttpServletRequest   ---------------          request
     HttpServletResponse --------------          response
             HttpSession     ---------------          session
        ServletContext     ----------------        application
        JspException     ----------------         exception //이 내장객체는 "오류 페이지"에 쓸 요량으로만든것이다 (나중설명)
          PageContext    ----------------          pageContext
              //PageContext는 다른 내장 객체들을 포함(은닉)하고 있기떄문에 도우미 클래스로 PageContext만 넘겨도
                 필요한 다른 내장 객체 및 모든 생존범위 속성을 사용할수 있다.

                Object       ----------------          page

'공부 > Sevlets&JSP' 카테고리의 다른 글

JSP API 와 속성  (0) 2011.07.01
Session Listener(세션 리스너)  (0) 2011.06.30
세션(sisson) 관리  (0) 2011.06.29
RequestDispatcher  (0) 2011.06.29
동기화  (0) 2011.06.29


세션 생명주기 이벤트

 이정표  이벤트와 리스너 유형
 
생명주기

     -세션 생성
     컨테이너가 세션을 생셩했을 떄 이시점까지 새션은 여전히 새것(new)
     으로 간주된다(왜냐하면, 클라이언트가 세션ID를 가진 요청을 아직
     보내지 않았기 떄문이다).
     -세션 소멸
     컨테이너가 세션을 무효화했을 때(세션이 타임아웃 되었거나 또는
     다른 애플리케이션에서 invalidate()메소드를 호출했을 경우)
 HttpSessionEvent

 HttpSessionListener
 
속성

    -속성 추가
    세션의 setAttribute()를 호출했을때.
    -속성 제거
    세션의 removeAttribute()를 호출했을때.
    -속성 대체
    세션의 setAttribute()를 호출했을때. 동일 속성 이름이 이미 존재하는
    경우에.
 HttpSessionBindingEvent

 HttpSessionAttributeListener
 

 이동

    - 세션이 비활성화(passivate)되려고 할떄
    컨테이너가 세션을 다른VM으로 옮기려고 할 때. 세션이 옮겨지기 바로
    전에 호출되어, 세션이 가지고 있는 속성들도 옮길 준비를 함
    -세션이 활성화 될때
    컨테이너가 세션을 다른 VM으로 옮기고 난 다음. 세션의 getAttribut()
    를 호출하기 바로 직전에 호출되어 속성들이 리턴할 준비를 함.
 HttpSessionEvent

 HttpSessionActivationListener


HttpSessionBindingListener

위에 나와있는 이벤트는 세션의 일생중 중요한 순간들이다

HttpSessionBindingListener는 세션이 아닌 세션 속성의 중요 순간들에 대하여 리스닝한다.

속성이 세션에 추가될 떄 속성의 정보를 데이터베이스에서 읽어 온다든지,

아니면 세션에서 제거될 떄 속성의 정보로 데이터베이스를 업데이트한다든지 할 떄 사용 한다.

코드를 보면

package com.example;

import javax.servlet.http.*;

public class Dog implements HttpSessionBindingListener {
//Dog라는 속성 클래스는 HttpSessionBindingListener이기도 하다. Dog객체가 세션에 추가되거나 제거될 떄를 리스닝 하고있다.
        private String breed;

        public Dog(String breed){
               this.breed=breed;
        }

        public String getBreed() {
              return breed;
        }

         public void valueBound(HttpSessionBindingEvent event) { //"Bound"라는 말은 이 속성을 세션에 추가했다는걸 의미
         //세션에 추가 되었을 때 실행될 코드
         }

         public void valueUnbound(HttpSessionBindingEvent event){ //속성을 세션에서 제거했다는걸 의미
         //세션에서 제거되었을 떄 실행될 코드
         }
}

*세션 바인딩 리스너는 DD에서 설정하지 않는다.
Dog와 같은 속성 클래스가 HttpSessionBindingListener를 구현하면, 컨테이너는 이 객체가 세션에 추가되거나 제거될떄
관련 콜백 메소드(valueBound(), valueUnBound())를 호출한다. 이걸로 끝이다
하지만 HttpSessionListenner, HttpSessionActivationListener는 DD에 등록해야한다
왜냐하면 이들은 세션 안에 추가되는 개별 속성들이 아니라 세션 그 자체에 관련된 것이기 떄문이다.


세션 이동

클러스트링 환경 하에서, 컨테이너는 클라이언트의 요청을 몇몇의 JVM으로 분산하여 넘기는 로드밸런싱 환경을 구현한다

그림으로 간단하게 보면




세션 이동 및 직렬화

컨테이너는 직렬화가 구현된 속성은 별다른 코딩을 하지않더라도 옮길수 있어야 한다.
(속성에 있는 모든 인스턴스는 직렬화되거나 아니면 null이어야한다는 말이다)

그렇다고 해서 컨테이너가 HttpSession 객체를 옮기기 위하여 꼭 직렬화를 요구하는것은 아니다.

이게무슨말이냐하면 속성 클래스를 직렬화 하라는 뜻이다.

직렬화가 되있지않았다면(전부다가 아니라도, 속성 인스턴스 변수중 하나라도 직렬화 되지 않았을 경우에도)

속성 객체를 HttpSessionActivationListener 로 구현한수 활성화(activation)/비활성화(passivation) 콜백 메소드를 가지고 이동할수 있게하면 된다.

 

*리스너종류와 메소드 가궁금하면 API를 찾아 보자

'공부 > Sevlets&JSP' 카테고리의 다른 글

JSP API 와 속성  (0) 2011.07.01
JSP 기초  (0) 2011.07.01
세션(sisson) 관리  (0) 2011.06.29
RequestDispatcher  (0) 2011.06.29
동기화  (0) 2011.06.29

웹 서버에는 메모리가 없어서 응답을 보낸 다음에는 당신이 누구였는지 조차 잊어버린다.

다음번에 다시요청을해도 그가 이전의 당신이었다는 것을 모른다는 것이다.

즉 웹서버는 당신이 이전에 요청했다는 사실을 기억하지 못하며, 당신에게 응답을 보냈다는 것도 기억하지 못한다.

그러나 프로그램을 하다보면 여러 번의 요청으로 오고 간 클라이언트와 대화 내용(state)을 기억할 필요가 있다 예를들어

고객이 상품을 장바구니에 넣고, 결제하는 동작을 하나의 요청으로 처리할 수는 없지 않은가?

서블릿 API에 이를 해결할 아주 단순한 방법이 있다.

HttpSession을 사용하는 방법이다.

다중 요청간 대화 정보를 유지 하기 위하여 httpSession객체를 사용할수 있다.

즉 특정 사용자의 전체 세션 동안의 정보를 유지할 수 있다는 말인데

클라이언트가 세션이 유지되는 동안 모든 보낸 요청으로부터 얻은 정보를 여기에 저장할 수 있다.

Http 프로토콜은 무상태(stateless)연결이다. 클라이언트인 브라우저는 서버에 연결을 맺고, 요청을 보낸뒤, 응답을 받는다.

그후 연결을 끊는데 연결이라고 하는것은  한번의 요청과 응답을 위해 존재한다고 말할 수 있다.

지속적인 연결이 아니기 떄문에, 클라이언트가 맺는 두번쨰 요청이 똑같은 클라이언트로부터 온 것이라고 할지라도

컨테이너는 이를 모른다. 컨테이너는 단지 각각의 요청이 새로운 클라이언트로부터 왔다고 생각할 뿐이다.

이문제를 해결하는방법은 간단하다.

클라이언트가 제일 처음 요청을 보낼 떄, 컨테이너는 클라이언트의 유일한 세션 ID를 생성 하는 것이다.
그리고 이값을 Response에 넣어 클라이언트로 돌려보내는 것이다. 그 다음부터 클라이언트가 요청을 보낼 떄는
이 세션ID를 함꼐 보내는 것이다. 그러면 컨테이너는 ID를 받아보고 일치하는 세션을 찾아 세션과 연결을 요청한다.


어떻게 클라이언트와 컨테이너는 세션 ID 정보를 공유하는가?

컨테이너는 클라이언트에 Response의 일부로 세션 ID를보낸다.
그러면 클라이언트는 다음 요청부터 Request의 일부로 세션ID을 돌려보낸다.
세션ID정보를 교환하는 가장 간단하며, 일반적인 방법은 쿠키를 이용하는 것이다.


"Set-Cookie"는 Response에 있는 헤더 중 하나이다.

 

"Cookie"는 Request에 있는 헤더 중 하나이다.


컨테이너가 거의 모든 쿠키 관련 작업을 한다.

먼저 컨테이너에게 세션을 만들어 사용하고 싶다고 말하면 컨테이너가 세션 ID를 생성하고 새로운 Cookie객체를 만든다.

그러면 컨테이너는 쿠키 안에 세션 ID 값을 채우고, Response에 쿠키를 설정한다.

그다음 번 클라이언트 요청부터는, 컨테이너는 Request 객체에서 쿠키를 찾아서 세션 ID가 무엇인지 확인한다.

현재 존재하는 세션 가운데에서 세션 ID를 가진놈을 찾아서, 세션과 요청을 연결한다.



Response 객체에 세션 쿠키 보내기

 HttpSession session = request.getSession();

Request 객체로부터 세션 ID 가져오기

HttpSession session = request.getSession();


세션ID를 생성할 떄와, Request에 쿠키를 설정할떄 쓴 코드는 같다.

Request안에 세션ID 쿠키가 들어있으면

ID에 맞는 세션을 찾으면 되고,

그렇지 않고 세션ID쿠키가 없거나 세션 ID에 일치하는 세션이없으면

새로운 세션을 만들면 된다.

모든 쿠키 관련 작업은 내부에서 일어난다.

세션 종료

세션이 종료되는 세가지 이유

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

1.DD에서 세션 타임아웃을 설정하기
DD에서 설정하는 타임아웃은 생성되는 모든 세션에 setMaxInactiveInterval()메소드를 호출하는 것과도 같다.

 <web-app ...>
       <servlet>
        ...
       </servlet>
      <session-config>
            <ssesion-timeout>15</ssession-timeout>
            //15분을의미하며 클라이언트가 15분동안 요청이없으면 세션을  제거하라는 의미이다.
       </session-config>
</web-app>


2.특정 세션만 타임아웃 설정하기
특정 세션 인스턴스만 세션 타임아웃 값을 변경할 수 있다.(다른 세션 타임아웃 값은 바뀌지않는다.)

session.setMaxInactiveInterval(20*60);


*DD에 있는 타임아웃의 단위는 분이고 프로그램적으로 한세션에 설정하는 값은 초단위이다.

'공부 > Sevlets&JSP' 카테고리의 다른 글

JSP 기초  (0) 2011.07.01
Session Listener(세션 리스너)  (0) 2011.06.30
RequestDispatcher  (0) 2011.06.29
동기화  (0) 2011.06.29
Attribute(속성)  (0) 2011.06.28

RequestDispatcher 에는 두개의 메소드, forward()와 include()만 있는데

둘다 Request와 Response 객체를 인자로 한다.(작업을 받은 컴포넌트와 작업을 하려면 이 두 객체가 필요하기떄문).

RequestDispatcher를 얻는 방법은 두가지가 있는 데 첫 번째가 Request고 다른하나는 컨텍스트이다.

둘중 어느 객체로부터 리턴을 받든지 간에 Request를 넘길 웹 컴포넌트가 무엇이다라는 것을 알려주어야 한다.


ServletRequest로부터 RequestDispatcher를 리턴받는경우

RequestDispatcher view = request. getRequestDispatcher("result.jsp");

ServletRequest의 getRequestDispatcher()메소드는 Request를 넘길(foward) 자원에 대한 경로(String)를

인자로 한다. 경로가 /로 시작하는 경우 컨테이너는 "웹 애플리케이션의 루트로 시작하는군" 이라고 생각하며,

/로 시작하지 않으면 "원래 Request의 경로에  상대경로로 시작하는 군" 이라고 생각한다.

또한 현재 웹 애플리케이션의 루트 경로보다 상위 경로로 빠져 나가 다른 곳으로 경로를 지정할수 없다


ServletContext로부터 RequestDispatcher를 리턴받는경우

RequestDispatcher view = getServletContext().getRequestDispatcher("/result.jsp");    
//SerbletContext의 getRequestDispatcher() 메소드에서는 반드시 /가 제일 앞에 와야한다
ServletRequest와 마찬가지로, getRequestDispatcher() 메소드도 Request를 넘길(foward) 자원에 대한 경로(String)를

인자로한다 다른 점이 있다면 상대경로를 사용할 수 없다는 것이다. 즉  반드시 /를 시작으로 절대 경로를 명시하여야한다.

RequestDispatcher의 foward() 메서드 호출하기

view.forward(request, response);

Request로부터 리턴받았든, 컨텍스트로부터 리턴받았든지간에 RequestDispatcher는 Request를 넘길 자원이 무엇인지

이미 알고있다. 이미 getRequestDispatcher() 메소드의 인자로 이를 넘겼기떄문이다.

그렇기떄문에 단지 forward()에 request와 response를 넣어 명시한 컴포넌트로 넘기기만 하면 된다.



*RequestDispatcher의 include() 메서드
include() 메소드는 어떤 작업을 처리하기 위해 다른 곳으로(보통 다른 서블릿) 요청을 넘겼다가, 작업이 완료되면

다시 요청을 받는다. 즉 include() 메소드 요청을 처리하기 위해 도움을 청하는 것이지, 완전히 일을 끝내고 손을 떼는것이 아니다.

forward()는 "이게 다야 더이상 request와 response에 대해 할일이 없다" 라는 것이면

include()는 "request와 response에 대해 이일 좀해줘 근데 일이 끝나면 request와 response에대한 마무리 작업은 내가 할게,
(문론 바로 안끝내고 또 다른 include()나 forward() 작업을 할수도 있다)
그러니 다시 나에게 넘져줘"

라고 볼수있다.


*xx.flush();
클라이언트에게 응답을 보내는 메서드이다. 여기서 응답은 이미 보내졌고, 종료되고, 끝이났다는 말이다

그러므로 이뒤에는 request를 다른곳으로 넘길수없다. forward() 할수없다는뜻이다.

'공부 > Sevlets&JSP' 카테고리의 다른 글

Session Listener(세션 리스너)  (0) 2011.06.30
세션(sisson) 관리  (0) 2011.06.29
동기화  (0) 2011.06.29
Attribute(속성)  (0) 2011.06.28
ServletContextListener  (0) 2011.06.27

동기화

공부/Sevlets&JSP2011. 6. 29. 10:32
컨텍스트 속성 애플리케이션에 있는 누구든지 접근할수 있다는 것을 잊으면안된다.

다양한 서블릿들과 하나의 서블릿이 멀티스레드로 실행되고 있는 환경에서

Context속성에 들어온 요청이 동일한 서블릿으로 온것인지 다른서블릿으로 온것인지

컨테이너는 구분하지 못한다.

어떤 한 서블릿이 Context속성의 값을 변경/사용 하고있더라도

다른 서블릿이 속성 값을 마음대로 변경/사용 할수있는 것이다.

컨테스트에 락을 걸자!

컨텍스트 속성을 보호하는 가장 전형적인 방법은 컨텍스트 객체 자체를 동기화(lock)하는 방법이다.

컨텍스트에 가장 먼저 접근한 객체가 컨텍스트에 락을 건다.

이렇게 하는것은 특정 시점에서 오직 하나의 스레드만이 컨텍스트 속성을 설정하거나 값을 읽는 것을 보장한다는 의미이다.

그러나 여기에도 조건은 있다.

동일 컨텍스트 속성을 다루는 모든 코드들이 마찬가지로 ServletContext에 대하여 락을 걸어야 이것이 작동한다는 것이다.

만약 어떤 코드는 락을 요청하지 않았다면, 여전히 컨텍스트 속성에 자유롭게 접근할수 있기떄문이다.

이를 방지하기위해 웹 애플리ㅔ이션 설계 시 모든 개발자들이 속성에 접근하기 전에 강제적으로 락을 걸도록 만들어야 한다.

밑에 소스를 보면

public void doGet(HttpServletRequest request, Http ServletResponse response)
                                                                    throws IOException, ServletException){
             response.setContentType("Text/html");
             printWriter out = response.getWriter();

             out.println("test context attributes<br>");

        synchronized(getServletContext()){
         //컨텍스트 속성을 보호하기위해 컨텍스트 자체에 락을 걸었다


                    getServletContext().setAttribute("foo", "22");
                    getServletContext().setAttribute("bar", "42");

                    out.println(getServletContext().getAttribute("foo"));
                    out.println(getServletContext().getAttribute("foo"));
        }
}

컨텍스트에 락을 걸었기 떄문에 동기화 코드 블럭 안에서는(빠져나가기전까지는) 컨텍스트 속성이 다른 스레드로부터 안전하다는것을 의미한다. "안전하다"라는 말은 "ServletContext에 대한 동기화를 걸어 둔 다른 코드로부터 안전하다"를 의미하지
그렇지 않은 코드에 대해서는 안전하지 못하다

그나마 이 방법이 컨텍스트 속성을 스레드 - 안전하게 만드는 우리가 할수있는 최선이다.

세션(Session) 속성은 스레드 - 안전한가?

Http세션은 뒤에서 자세히 설명하겠지만 간단하게 설명하면

세션은 클라이언트와 대화 상태(Conversational state)를 유지하기 위하여 사용하는 객체이다.

하나의 클라이언트가 어느 정도 시간 간격으로 보내는 여러 번의 요청에도 세션은 유지된다.(하나의 클라이언트라는 말이 중요)

클라이언트 당 세션은 하나이니 어차피 어느 특정 시점에서는 한번에 하나의 요청만 들어오므로 자동적으로

세션이 스레드-안전하다고 생각할수도 있다. 하지만 클라이언트가 하나 이상의 브라우저를 열 겨우 서로 다른 브라우저로부터

온 요청이지만, 컨테이너는 동일한 세션을 사용할 것이다. 그렇게떄문에 세션 속성도 스레드 -안전하지 못하므로 보호되어야한다.

컨텍스트에 락을 걸었던것처럼 세션에도 락을걸면된다.

public void doGet(HttpServletRequest request, Http ServletResponse response)
                                                               throws IOException, ServletException){
                  response.setContentType("Text/html");
                  printWriter out = response.getWriter();

                  out.println("test context attributes<br>");
                  HttpSession session = request.getSession();
            synchronized(session){
//세션 속성을 보호하기위해 HttpSession객체에 락을 걸었다


                          session.setAttribute("foo", "22");
                          session.setAttribute("bar", "42");

                          out.println(session.getAttribute("foo"));
                          out.println(session.getAttribute("foo"));
            }
}

Request속성

단지 Request속성과 지역 변수만이 스레드 안전하다.(메소드 파라미터도 지역 변수에 포함)

이를 제외한 나머지는 멀티스레딩을 중지하지 않는 한, 멀티 스레딩 에 안전하지못하다

Request 속성은 애플리케이션의 다른 컴포넌트가 Request 또는 Request의 일부를 넘겨받기 위해 사용한다.

단순한 MVC 애플리케이션을 보면, 대부분 서블릿 컨트롤러로부터 시작해서 JSP 뷰료 끝이 난다는 것을 알 수 있다.

컨트롤러는 모델과 커뮤니케이션하여 Response를 만들기 위하여 뷰에게 데이터를 넘겨준다. 이떄 데이터를 컨텍스트나 세션 속성

넣을 필요까지 없다. 단지 이번 요청에 대해서만 사용할 데이터니깐 Request에 넣어 두는 것이 낫기 때문이다.

다른 컴퓨넌트에 Request 를 넘기는 방법은 RequestDispatcher 을 사용하면된다.

//doGet()의 일부
BeerExpert be = new BeerExpert();
ArrayList result = be.getBrands(c);

request.setAttribute("styles", result);       //모델 데이터를 request에 넣어둔다
     RequestDispatcher view = request.getRequestDispatcher("result.jsp");
     //JSP 뷰를 위한 디스패처를 리턴 받는다.
view.porward(request, response);
//JSP에게 "Request를 넘겨 받아라" 라고 말하는 것.

'공부 > Sevlets&JSP' 카테고리의 다른 글

세션(sisson) 관리  (0) 2011.06.29
RequestDispatcher  (0) 2011.06.29
Attribute(속성)  (0) 2011.06.28
ServletContextListener  (0) 2011.06.27
ServletConfig 와 ServletContext  (0) 2011.06.27

속성이라는 것은 3개의 서블릿 API객체 즉

ServletContext, HttpServletRequest(또는 ServletRequest), HttpSession 객체 중 하나에 설정해놓는(바인딩(binding)라고함)

객체를 말한다.

간단히 이를 Map 인스턴스(java.util.Map)에 이름/값의 쌍으로 저장하는 것이라고 생각해도 무방하다(이름은 String/ 값 Object)

사실 내부적으로 이것이 어떻게 구현되어 있는지 신경쓸필요없다 .단지 속성이 생존하는 범위(scope)이 중요하다.

속성은 게시판에 핀으로 고정시킨 게시물과 같다.

누군가 게시판에 다른 사람들이 읽으라고 붙여놓은 것이다
여기서 의문을 가져야할 사항은
누가 게시물을 등록하는가?
게시물의 게시기간은 얼마나 되는가?
개발자적인 용어로 바꾸면 속성의 생존범위(scope)는 어떻게 되는가? 이다

서블릿에 입문한지 얼마되지 않았다면, 속성과 파라미터의 차이에대해 고민을 꽤 시간을 낭비했을 것이다
밑에 표로 파라미터와 속성의 차이를 알아보자

속성 파라미터
타입 Application/context
Request
Session
Application/context 초기화 파라미터
Request 파라미터
Servlet 초기화 파라미터
설정 메소드 setAttribute(String name, Object value) 애플리케이션과 서블릿의 초기화 파라미터 값은 런타임 시 설정할 수 업다. 오로지 DD에서 초기화 설정때만 가능하다(Request 파라미터를 가지고, 좀어렵긴하지만 쿼리스트링을 설정 할수있다)
리턴 타입 Object String
참조 메서드 getAttribute(String name)
*속성은 리턴될떄 Object이므로
캐스트(cast)해야한다
getInitParameter(String name)


세 가지 생존 범위 : context, Request, Session

context 속성 : 애플리 케이션에 있는 것이라면 누구나 접근할 수 있다.(get/set)
Session 속성 : 특정 HttpSession에 접근 권한을 가진 녀석만 접근할 수 있다.(get/set)
REQUEST 속성 : 특정 ServletRequest에 접근 권한을 가진 녀석만 접근할 수 있다.(get/set)



속성들의 API를 살펴보면

모든 인터페이스에서 속성의 API 메소드는 동일한 것을 볼수있다.

속성범위

   접근(누가볼수있는가) 생존범위
(얼마나 생존해 있는가) 
 이곳이 가장 적당한 곳
 Context

스레드-안전(x)
웹 애플리케이션에 있는것은
어떤 것이든. 서블릿,JSP,
ServletContextListener,
servletContextAttribute,
Listener
 애플리케이션 생존시간과 동일
서버나 애플리케이션이 내려가면 컨텍스트도 소멸
 전체 애플리케이션에서 공유하고자하는 자원.
데이터베이서Connection,
JNDI검색명(lookup name),
이메일 주소 등.
 HttpSession

스레드-안전(x)
특정 세션에 접근할 수 있는
어떤 서블릿이나 JSP 모두.
세션은 여러개의 요청에 대하여 정보를 간직할 수 있다.
한 서블릿뿐만아니라 여러 서블릿에 대해서도 가능하다. 
 세션의 생존시간, 세션을 프로그램적으로 소멸시킬수 있으며, 간단히 시간이 만료될 수도 있다.  하나의 Request에만 관련된 것이 아니라 클라이언트 세션에 관련된 데이터와 자원.
클라이언트와 지속적인 대화를 유지하고 싶은것들. 장바구니가 가장 좋은 예.
 Request

스레드-안전(o)
 애플리케이션 내에서 Request객체에 직접 접근이 가능한것 모두. RequestDispatcher를 사용하여 요청을 처리할 수 있는 서블릿이나 JSP를 대부분 의미. 문론 Request관련 리스너포함  Request의 생존시간. 서블릿의 서비스 메소드가 끝날 떄까지이다. 즉 스래드가 Request를 핸들링 할때까지만 살아있는것이다  모델 정보를 컨트롤러에서 뷰로 넘길떄, 또는 특정 요청에만 관련된 데이터 등.



'공부 > Sevlets&JSP' 카테고리의 다른 글

RequestDispatcher  (0) 2011.06.29
동기화  (0) 2011.06.29
ServletContextListener  (0) 2011.06.27
ServletConfig 와 ServletContext  (0) 2011.06.27
Request, Response  (0) 2011.06.27


컨텍스트 파라미터에는 String 밖에 저장할 수 없다. 객체를 XML 배포 서술자에 넣을 수 없다

예를들어 애플리케이션에 있는 모든 서블릿이 데이터베이서 Connection객체를 공유하고 싶을 떄는 어떻게할까?

오늘날 컨텍스트 파라미터를 이용한 가장 일반적인 방법은 컨텍스트 파라미터에
 
DataSource 검색명(lookup name)을 저장하는 것이다.

그런다음 누가 String인 검색명을 실제 DataSource 객체로 바꾸면 되는데 이것을 누가 하느냐가 문제이다.

서블릿안에 넣자니 어떤 서블릿이 가장 먼저 호출된지 알수없다. 만약 가장먼저 호출되지않으면 그보다 호출이 먼저된

서블릿은 DataSource 객체를 공유받지 못할것이다.

방법은 컨텍스트 초기화 이벤트에 리스닝 하는 것이다. 이를 이용하면 컨텍스트 초기화 파라미터를 읽은 다음

애플리케이션이 클라이언트에게 서비스하기 전에 특정 코드를 실행할 수 있다.

하지만 이방법을 누가 하느냐가 문제인데 서블릿도 JSP도 아닌 클래스가 필요하다

이클래스는 다음의 두가지 ServletContext이벤트(초기화(생성)와 소멸)에 귀 기울이고 있어야한다.

즉 다음의 기능을 가진 클래스여야한다

 - 컨텍스트가 초기화(애플리케이션 배포)되는 걸 알아차릴수 있어야한다
ServletContext로부터 컨텍스트 초기화 파라미터를 읽는다.
데이터베이스를 연결하기 위하여 초기화 파라미터 검색명(lookup name)을 사용한다
데이터베이스 Connection 객체를 속성(Attribute)에 저장한다.
-컨텍스트가 종료(애플리케이션 서비스가 내려가는)되는 걸 알아차릴수있어야한다
데이터베이스 연결을 닫는다.
 ServletContextListener 클래스

import javax.servlet.*;

public class MyServletContextListener implementes ServletcontextListener
                                                                    //컨텍스트 리스너는 ServletContextListener만 구현하면된다
       public void contextInitialized(ServletContextEvent event){
              //여기에 데이터베이스 연결을 초기화 하는 코딩을한다.
              //그리고 이를 컨텍스트 속성에 저장한다.
       }

       public void contextDestroyed(ServletContextEvent event){
            //여기에 데이터베이스 연결을 닫는 코딩을 한다.
      }
}

리스너 작성후 컨테이너에게 우리가 리스너를 만들었음을 알려주기위해

DD(web.xml)에 <listener>요소에 클래스 이름만 기재하면 된다.

<servlet> 
        <servlet-name>xxx</servlet-name>
        <servlet-class>xxx</servlet-class>
</servlet>

<Context-param>
      <param-name>adminEmail</param-name>
      <param-value>abc@daum.com</param-value>
</Context-param>

<listener>
      <listener-class>
            com.example.MyServletContextListener
      </listener-class>
</listener>




전체적인 그림을 보면
애플리케이션 시작(초기화)에서부터 마지막(서블릿 실행) 까지 한번보면


1. 컨테이너는 DD를 읽는다. 물론<listener> 요소와 <context-param> 요소도 읽는다.
2. 컨테이너는 ServletContext 객체를 생성한다. 애플리케이션에서 이객체를 공유한다.
3. 컨테이너는 컨텍스트 초기화 파라미터의 이름/값 쌍(String 쌍)을만든다.(여기선하나만있다고가정)




4. 컨테이너는 생성한 컨텍스트 초기화 파라미터의 String 쌍을 ServletContext 객체에 설정한다.
5. 컨테이너는 MyServletContextListener 클래스 인스턴스를 만든다.
6. 컨테이너는 리스너의 contextInitialized() 메소드를 호출합니다. 인자로 ServletContextEvent를 넘긴다.
   이 이벤트 객체를 가지고 ServletContext에 접근한다. 코드에서는 ServletContextEvent로 접근한
   ServletContect로 컨텍스트 초기화 파라미터 값을 읽는다.



7. 리스너가 ServletContextEvent에게 ServletContext에 대한 참조를 요청한다..
8. 리스너가 ServletContext에게 컨텍스트 초기화 파라미터 breed에 대한 값을 요청한다..
9. 리스너는 초기화 파라미터를 가지고 Dog객체를 생성한다.
10. 리스너는 ServletContext의 속성으로 Dog를 설정한다.


11. 컨테이너는 새로운 서블릿을 생성한다( 풀어서 말하면 초기화 파라미터로 ServletConfig를 생성하고,
      여기에 ServletContext에 대한 참조를 설정한 다음,
      서블릿 init() 메소드를 호출한다).
12. 서블릿은 요청을 받고는, ServletContext에게 dog속성에 매핑된 객체 인스턴스를 요청한다.
13. 서블릿은 Dog객체의 getBreed()메소드를 호출한다. (그다음 HttpResponse에 이내용을 쓴다).

'공부 > Sevlets&JSP' 카테고리의 다른 글

동기화  (0) 2011.06.29
Attribute(속성)  (0) 2011.06.28
ServletConfig 와 ServletContext  (0) 2011.06.27
Request, Response  (0) 2011.06.27
서블릿 생명주기와 API  (0) 2011.06.24

ServletConfig

서블릿에 이렇게 하드코딩하는것보다

printWriter out = response.getWriter();
out.println(abc@daum.com);

이메일주소를 배포서술자안에 넣은후 서블릿이 DD에서 이메일 주소를 읽어오게하는 방법이
나중에 web.xml 만 수정하면되니까 서블릿을 손 끝하나 대지않아도 원하는것을 할수있다.

DD(web.xml) 파일에서

 <servlet>
<servlet-name>xxx</servlet-name>
<servlet-class>xxx</servlet-class>

<init-param>
                <param-name>adminEmail</param-name>
                <param-value>abc@daum.com</param-value>
          </init-param>


</servlet>
//servlet 항목안에 설정해준다


서블릿 코드에서

out.println(getServletConfig().getInitParameter("adminEmail");
//모든 서블릿에는 상속받은 getServletConfig()가 있다.



서블릿에는 상속받은 getServletConfig() 메소드가 있다.

컨테이너가 서블릿을 만들떄, DD를 읽어 이름/값의 쌍으로 ServletConfig를 생성한다.
컨테이너는 이 초기화 파라미터를 두번 다시 읽지 않는다. 이름/값 쌍이 ServletConfig 안에 기록이 되면,
서블릿이 다시 배포 되지 않는 한 DD를 수정한다고 바뀌지 않는다.


ServletConfig는 말 그대로 서블릿 설정이다. DD에 있는 서블릿 초기화 파라미터 정보를  웹 애플리케이션의
다른 컴포넌트와 공유하려면, 몇 가지 작업을 해야한다.

 //doPost() 메소드안
String color = request.getPrameter("color"); //Request 객체에서 클라이언트가 선택한 색정보를 읽어온다

BeerExpert be = newBeerExpert();
List rusult = be.getBrands(color); // 그런다음 모델을 인스턴스와하고 뷰에필요한 정보 설정

request.setAttribute("styles", result);
// Request 객체의 속성의 결과를 설정하고, Request 객체를 JSP가 처리하도록 넘김(forward)

Request 객체는 속성을 설정하는 메소드를 제공하는데(setAttribute()) 여기서 값은 어떤 객체든지 가능하다

ServletContext

컨텍스트(Context) 초기화 파라미터의 작동방식은 서블릿 초기화 파라미터와 동일하다.
그러나 컨텍스트(Context) 초기화 파라미터는 특정 하나의 서블릿만 사용하는 것이 아니라
모든 웹 애플리케이션에서 이용할 수 있다는 차이가 있다.
웹 애플리케이션에 있는 모든 JSP 서블릿에서 별다른 코딩없이도 컨텍스트 초기화 파라미터 정보에 접근할수 있으며, 그렇다고 모든 서블릿의 DD를 수정하지 않아도 된다. 또한 그 값을 수정하는 경우도 DD만 수정하면 다른곳도 자동으로 반영되니 편하다.

DD(web.xml) 파일에서

<servlet>
           <servlet-name>xxx</servlet-name>
           <servlet-class>xxx</servlet-class>
</servlet>
//<servlet> 항목 안에 있던 <init-param>을 모두 들어내고
<Context-param>
                <param-name>adminEmail</param-name>
                <param-value>abc@daum.com</param-value>
          </init-param>

//<Context-param>은 전체 애플리케이션을 위한 항목이다. 따라서 <servlet>항목안에 들어가지 않는다
<web-app> 항목에 포함시시키되 <servlet>항목안에 두지 않는다



서블릿 코드에서

out.println(getServletContext().getInitParameter("adminEmail"));
//모든 서블릿에는 상속받은 getServletContext() 메소드가 있다.




ServletConfig는 서블릿 당 하나

ServletContext는 웹 애플리케이션 당 하나

웹 애플리케이션은 오직 하나의 ServletContext으로 전체 웹 애플리케이션에서 정보를 공유한다. 하지만 웹 애플리케이션 안에 있는 서블릿은 자민만의 ServletConfig를 가진다!

또한 둘은 초기화 시켜주는 목적이다. 초기화 파라미터를 배포시 정해진 상수라고 생각하고
실행 시에 이 값을 읽을 수는 있지만, 수정할수는 없다. getInitParameter 있지만 setInitParameter() 는 없다!!!!



'공부 > Sevlets&JSP' 카테고리의 다른 글

Attribute(속성)  (0) 2011.06.28
ServletContextListener  (0) 2011.06.27
Request, Response  (0) 2011.06.27
서블릿 생명주기와 API  (0) 2011.06.24
MVC 패턴  (0) 2011.06.24

HttpServletRequest

HttpServlet의 service() 메소드는 HttpServletRequest와 HttpServletResponse를 인자로 한다.
service(HttpServletRequest,HttpServletResponse)

service() 메소드는 HTTP Request의 HTTP 메소드(GET,POST 등)에 따라 doGet()을 호출할지, 아니면 doPost()를 호출할지 결정
HTTP Request 메소드는 GET,POST,HEAD,TRACE,PUT,DELETE,OPTION,CONNECT 총 8가지가 있다.

Post 요청에는 몸체가 있다. GET 요청에는 몸체가 없다. GET파라미터는 URL의 실제 주소 뒤에 연결된다. 보통 이를 쿼리스트링 이라고 부른다.

HTML 폼에 "method=POST" 를 코딩하지 않았다면  이 요청은 POST가 아니라 GET이다.
즉 디폴트는 HTTP GET이다

Request 객체에서 파라미터를 뽑아내기 위하여 getParameter("파라메터이름") 메소드를 호출한다
리턴값은 언제나 String이다

이외에 Request 객체에서 헤더 정보, 쿠키정보, 세션정보, 쿼리 스트링, 입력스트림 관련 메소드를 사용할수있다.
이메소드에관한건 뒤에 서서히 살펴보자!

HttpServletResponse

클라이언트로 데이터를 보내기 위하여 Response 객체를 사용한다.

Response 객체(HttpServletResponse)에서 가장 많이 사용하는 메소드는 setContentType()과 getWriter()이다.

많은 개발자들이 착각하고 있는 것중 하나가 GetPrintWriter()이라고 생각하는데 getWriter()이 맞다.

getWriter()메소드로 HTML을 작성하는 것과 같은 문자 I/O작업을 한다.

Response 객체로 헤더를 설정하고, 오류를 전송하며 쿠키도 추가할수 있다.

실제 프로젝트에서 HTML응답을 보내기위해 JSP를 사용하지만 JAR파일 같은 바이너리를 전송하기 위해 Response 스트림을 사용한다.

Response에서 바이너리 스트림을 리턴받는 메소드는 getOutputStream이다.

브라우저가 응답으로 들어오는 데이터를 어떻게 핸들링 할지 알려주는 메소드는 setContentType()이다.
일반적으로 컨텐츠 타입은 text/html, application/pdf, image/jpeg 등이 있다.


요청에응답하지 않고, 요청을 다른 URL로 리다이렉트 할수 있다.
이경우 브라우저는 서버에서 정한 URL을 받아 새로운 요청을 보낸다.

리다이렉트와 디스패치는 다르다. 요청을 디스패치하는것은 서버에서 일어나는거고 리다이렉트는 클라이언트에서 일어난다.
디스패치 작업은 서버상에있는 다른 컴포넌트로 작업을 넘기는것이라면 리다이렉트는 완전히 다른 URL로 가라고 브라우저에게 지시하는 것이다


'공부 > Sevlets&JSP' 카테고리의 다른 글

ServletContextListener  (0) 2011.06.27
ServletConfig 와 ServletContext  (0) 2011.06.27
서블릿 생명주기와 API  (0) 2011.06.24
MVC 패턴  (0) 2011.06.24
서블릿 매핑, 배포 서술자(DD, Deployment Descriptor)  (0) 2011.06.23