2013년 9월 7일 토요일

[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()호출하기 전에 호출하됨. 모두 끝...

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

Chapter.04 서블릿은 평생을 서비스 클라이언트로 삶니다.

서블릿의 일생 (Web Container에 의해서)
  • Class Loading : class 찾아서 class loading 한다.
  • Servlet Instance : 서블릿의 생성자 실행(디폴트 생성자 실행)
  • init() : 전체 일생에서 단 한번만 실행됨. 반드시 service() 이전에 실행 되어야 함.
  • service() : 대부분의 시간을 보냄, 클라이어느 요청을 핸들링함. (doGet(), doPost() 실행하고
    요청이 들어 올때 마다 새로운 쓰레드에서 실행됨.
  • destory() : 죽기전에 모든 자원 해지 할 수 있는 기회를 줌.
Servlet 관련 주요 인터페이스 , 클래스
  • Servlet Interface (javax.servlet) : 생명주기 관련 메소드가 선언되어 있다.
    • service(ServletRequest,ServletResponse)
    • init(ServletConfig)
    • destory()
    • getServletConfig()
    • getServletInfo()
  • GenericServlet Class (java.servlet) : 추상화 클래스, 대부분의 서블릿 행위가 이 클래스에서 구현 되었다.
    • service(ServletRequest,ServletResponse)
    • init(ServletConfig)
    • init()
    • destory()
    • getServletConfig()
    • getServletInfo()
    • getInitParameter(String)
    • getInitParameterNames()
    • getServletContext()
    • log(String)
    • log(String,Throwable)
  • HttpServlet Class (javax.servlet.http) : 추상화 클래스, HTTP 관련 해서 service() 재정의 함.
    HttpServletRequest(Response) 만 파라미터로 받는 새로운 service()메소드를 구현함.
    • service(HttpServletRequest,HttpServletResponse)
    • service(ServletRequest,ServletResponse)
    • doGet(HttpServletRequest,HttpServletResponse)
    • doPost(HttpServletRequest,HttpServletResponse)
    • doHead(HttpServletRequest,HttpServletResponse)
    • doOptions(HttpServletRequest,HttpServletResponse)
    • doPut(HttpServletRequest,HttpServletResponse)
    • doTrace(HttpServletRequest,HttpServletResponse)
    • doDelete(HttpServletRequest,HttpServletResponse)
    • getLastModified(HttpServletRequest)
  • MyServlet : 여러분이 작성은 HTTP 관련 메소드만을 구현 하면 된다.
서블릿 Life Cycle 3 KEY Point
  • init() : 클라인언트의 요청을 처리하기 전에 서블릿을 초기화할 기회를 줌
    • 재정의 여부 : 초기화할 코드가 있는 초기화 함. (예, DB접속)
  • service() : 클라이언트의 HTTP 메소드를 참조 하여 doGet()을 호출하지 doPost() 호출할지 판단합니다.
    • 재정의 여부 : 거의 재정의 하지 않는다.
  • doGet() / doPost() : 웹 어플리케이션 실제 작업을 하는 곳
    • 재정의 여부 : 둘 중 하나는 반드시 재정의 해야 함.
컨테이너 - 서블릿 하나에 대한 다수의 요청을 처리하기 위해 다수의 스레드를 실행하지 다수의 인스턴스를 만들지 말아야 합니다.
  • 서블릿 초기화 시점 - 컨테이너 시작 할때(tomcat) , 관련 클래스를 찾아서 로딩 시킴.
  • 클래스 로딩 방법
  • - class finding & loading
  • - Just-In-Time (즉, 실행시 로딩하기
객체가 서블릿이 된다는 것은 :: 서블릿에 따라오는 고유한 권한을 가진다는 것을 의미합니다.

ServletConfig 객체
  • 서블릿당 ServletConfig 객체 하나
  • 배포시 설정된 정보를 서블릿에게 넘겨 주기 위해서(DB 나 EJB 참조)
  • ServletContext에 접근하기
  • 파라미터값은 배포 서술자(DD)에서 설정 가능
  • 서블릿이 배포하는 동안 수정되지 않는다. 만약 변경 되면 서블릿을 다시 배포 해야 한다.
ServletContext 객체
  • 웹 어플리케이션 당 하나
  • 웹 어플리케이션의 파라미터 정보를 읽어 오기 위하여 사용합니다.(DD 안에 설정됨)
  • 일종의 어플리케이션용 게시판이며 여기에 기록하면 다른 객체에서 참조 가능하다.
  • 서버 정보를 파악하기 위해 사용, 예) 컨테이너 이름 및 버젼, 지원하는 API 버젼등

Request / Response 주요 클래스 및 인터페이스
  • ServletRequest (javax.servlet) Interface :
    • getAttribute(String)
    • getContentLength()
    • getInputStream()
    • getLocalPort()
    • getParameter()
    • getParameterNames()
  • HttpServletRequest (javax.servlet.http) Interface : HTTP 관련 서비스를 제공 합니다.
    • getContextPath()
    • getCookies()
    • getHeader(String)
    • getQueryString()
    • getSession()
    • getMethod()
  • ServletResponse (javax.servlet) Interface :
    • getBufferSize()
    • setContentType()
    • getOutputStream()
    • getWriter()
    • getContentType()
  • HttpServletResponse (javax.servlet.http) Interface :
    • addCookie()
    • addHeader()
    • encodeRedirectURL()
    • sendError()
    • setStatus()

- HttpServletRequest  와 HttpServletResponse 는 누가 구현 하는가 - 컨테이너 , API로 구현된 클래스가 없음.
- GenerlcServlet 과 ServletRequest  와 ServletResponse  있는 이유는 HTTP 이외 사용될것 가정하여 설계 하였기 때문에 있음.

HTTP 메소드
  1. GET - URL로 자원 또는 파일 달라고 요청함.
  2. POST - 요청한 URL로 이 정보를 넘겨 주라고 요청함. 부가 정보를 가진 GET 이라고도 함.
  3. HEAD - 헤더 정보만 요청함. 이는 Response 몸체 정보가 없다는 것 빼고 GET과 동일함.
  4. TRACE - 요청한 메시지의 loopback 테스트를 요청함. 서버쪽에서 무엇을 받았는지 알고 싶을 때 하는 테스트
    테스트 목적혹은 문제 해결을 위해 사용함.
  5. PUT - 동봉한 몸체 정보를 요청한 URL로 올리기 위해 사용함.
  6. DELETE - 요청한 URL에 있는 자원이나 파일을 삭제하기 위해 사용
  7. OPTIONS - 요청한 URL이 응답할 수 있는 HTTP 메소드가 무엇인지 요청함.
  8. CONNECT - 터널링의 목적으로 연결을 요청함.

- 요청 멱등(Idempotent) 이란 - 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미
동일한 작업을 한 번이고 두 번이고 계속 해서 할 수 있습니다. 어떤 부작용도 없이

- method의 기본값 : 만약 <form>에서 method 속성을 생략할 경우는 기본적인 값을 “GET” 임.
- doGet() 과 doPost() 모든 지원 방안
public void doPost(...) throws{
  doGet(request,response);
}

- 파라미터 정보 얻는 메소드
  • 주어진 paraName에 대한 단일 값인 경우 : getParameter()
  • 주어진 paraName에 대한 여러 값인 경우 : getParameterValues() , 배열로 리턴함.

- Request 객체에 얻을 수 있는 정보
  • 클라이언트 플랫폼 정보 및 브라우저 정보 :getHeader(“User-Agent”)
    • getIntHeader() : 요청 정보의 응답값이 정수형인 경우를 보장한다.
  • 요청에 관련된 쿠기 정보 :getCookies();
  • 클라이언트의 세션 정보 : getSession();
  • Request의 HTTP 메소드 : getMethod();
  • Request의 입력 스트림 : getInputStream();
  • getRemotePort() : 요청을 보낸 클라이언트의 포트
  • getServerPort() : Request가 들어오는 포트 번호
  • getLocalPort() : 스레드를 처리 위한 포트
 
- Response 처리시 주의 사항
** setContentType를 설정 후 정보쓰기 작업을 수행 한다.

JAR를 내려받는 서블릿 코드 (잘 동작할까?)
doGet(...){
  response.setContentType(“application/jar”);
  ServletContext ctvx = getServletContext();
  inputStream is = ctx.getResourceAsStream(“/bookCode.jar”);
  int read = 0;
  byte[] bytes = new byte[1024];
  
  OutputStream os = response.getOutputStream();
  while((read = is.read(bytes) != -1){
      os.write(bytes,0,read);
  }
  os.flush();
  os.close();   

일반적인 MIME 타입
  • text/html
  • application/pdf
  • video/quicktime
  • application/java
  • image/jpeg
  • application/jar
  • application/octect-stream
  • application/x-zip

다른 URL로 이동 시키기

  • 서블릿 Redirect
    • 요청을 완전히 다른 URL로 방향을 바꾸는 것
    • 클라이언트에서 일어남.
    • 관련메소드 : response.sendRedirect(URLString);
    • 상대경로 사용가능
  • Request Dispatch
    • 다른 컴포넌트에게 위임을 하는 것
    • 서버에서 일어남
    • 관련코드 : request.getRequestDispathcher(“xxx.jsp”).forward(request,response);