finerss's world!


컨텍스트 파라미터에는 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

컨테이너는 클라이언트가 날린 요청에 들어 있는 URL을 가지고 어떤 서블릿인지 찾아낸다.
URL과 서블릿을 매핑하는 방법은 개발자가 이를 어떻게 설정하는가에 따라 달라진다.


서블릿은 세가지 이름을 가질수있는데

1. classes/registration/SignUpServlet.class 처럼 파일 위치를 알려주는 이름인 파일 위치명(file path name)

2. 서블릿 배포명 - 이이름은 내부적으로만 사용되는 이름이며, 클래스 이름이나 파일 이름과 같을 필요는 없다.

3. URL 이름 - 공공의(public) 이름으로 누구나 다알아도 되는이름이다. 이이름은 HTML 코드 안에 코딩하는 이름이며, 사용자가 클릭해서 서블릿을 호출할 때 사용하는 이름이다. 이 URL 이름이 HTTP 요청 안에 포함되어 서버로 전송되는 이름이다.

본래에 파일위치명 을 놔두고 다름이름을 만들어서 헷갈리게 하는이유는
서블릿 이름을 다른 이름으로 매핑하면, 애플리케이션의 유연성, 보안성이 좋아지기 떄문이다.

가령 JSP나 HTML 안에 서블릿의 실제 경로와 파일 이름을 하드 코딩한다고 해보자
만약 그서블릿을 담고있는 디렉토리 구조를 바꿔야 하는 상황이 벌어졌다면, 개발자는 파일이란 파일은 다 검색해서 하드코딩된 부분을 찾아 수정해야 하는 번거러움이 있다.

하지만 DD에 매핑을 하게되면 실제 파일명을 하드코딩하는 것이 아니라 DD에 매핑된 URL 이름만 명시 해놓기 떄문에
디렉토리 구조가 변경되었다하더라도 파일은 수정할필요없이 DD만 수정하면 되는 것이다.

보안문제를 보면 라이언트가 파일 위치명을 알게된다면, 실제 경로를 알수 있다는 말인데 이는 직접 브라우저 주소란에 이정보를 입력하여 접근 할수 있다는 것이다. 클라이언트가 여러분의 서버 디렉토리 구조랑 파일이름들을 모두 알수있다는 뜻이며 여러분이 설정한 방식으로 폼이나 페이지에 접근하지 않고, 클라이언트가 직접 접근하게 되기때문에 보안상 문제가 발생할수있는것이다.


배포 서술자(DD, Deployment Descriptor)에에서
URL을 서블릿에 매핑하기

웹컨테이너도 서블릿을 배포하려면, 배포서술자(이하 DD) 라는 XML 파일을 먼저 만들어야 한다(있다면 수정하면 된다).
DD 파일에는 서블릿과 JSP를 어떻게 실행하느냐에 관한 많은 정보들이 들어 있는데 우선 URL과 서블릿 매핑에 대해 알아보자.
매핑을 하려면 두 가지 작업을 해야 하는데, 먼저 URL 이름을 내부에서만 사용하는 이름으로 매핑하고, 그다음 내부 이름을 실제 클래스 이름으로 매핑하면 작업 끝이다.

URL 매핑을 위한 두 가지 항목

1. <servlet>
      내부에서만 사용하는 이름과 완전한(패키지 이름까지 포함하여) 클래스명과 서로 매핑한다.
2. <servlet-mapping>
      내부에서 사용하는 이름과 URL 이름을 서로 매핑한다.

DD형식을 보면

 <web-app ...>
   
    <servlet>
          <servlet-name>Internal name 1</servlet-name>
          <servlet-class>foo.Servlet1</servlet-class>
    </servlet>

    <servlet>
          <servlet-name>Internal name 2</servlet-name>
          <servlet-class>foo.Servlet2</servlet-class>
    </servlet>
..............................................
.............................................

     <servlet-mapping>
           <servlet-name>Internal name 1</servlet-name>
           <url-pattern>/public1</url-pattern>
      </servlet-mapping>

      <servlet-mapping>
           <servlet-name>Inrernal name 2</servlet-name>
           <url-pattern>/public2</url-pattern>
       </servlet-mapping>

</web-app>

각각을 살펴보면




클라이언트로부터 요청이 들어오면 컨테이너는 DD에서 위에 순서대로(1->2->3->4) 서블릿을 검색한다
/public2 라는 URL 이름으로 요청이들어왔다면 DD내에서 매핑된이름인 Internal name2로 실제 서블릿 명(실제위치)을 찾게 되는 것이다.

URL명과 실제 서블릿 명을 서로 매핑하는 일 말고도 DD에서 할수 있는 일은 많다.
보안역활(Security Role) 설정, 오류페이지 설정, 항목 라이브러리, 초기화 구성 및 관련 정보 설정 등 무척 많다.
그리고 서버가 J2EE의 모든 규격을 구현한 서버라면 EJB 선언 및 접근에 관련된 내용도 여기서 설정한다.



DD의 이점

- 이미 테스트된 소스 코드의 대한 수정 최소화
- 소스 코드가 없더라도, 애플리케이션을 목적에 맞게 수정할 수 있다.
- 코드 변경이나 컴파일을 다시 하지 않아도 서버 자원(예를 들면 데이터베이스 연결)을 바꿀수 있다.
- 접근 제어 목록(ACL, Access Control List), 보안 역활(Security Role)과 같은 보안에 관련된 업무도 쉽게 관리할 수 있다.
-프로그래머가 아닌 사람이 웹 애플리케이션을 배포하고 설정을 수정하는데 수월하다.










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

서블릿 생명주기와 API  (0) 2011.06.24
MVC 패턴  (0) 2011.06.24
서블릿 컨테이너(Servlet Container)  (1) 2011.06.22
CGI 와 Servlet 의차이  (0) 2011.06.22
CGI(Common Gateway Interface)  (0) 2011.06.22

서블릿에 요청이 들어오면, 누군가 서블릿을 초기화해서, 요청을 처리한 새로운 스레드를 만들어야한다.
그러면 서블렛은 doPost() 또는 doGet()메서드를 호출하며 여기에 두메소드에 인자로들어가는
 HTTP Request 와 HTTP Resopnse 객체를 누군가 생성해서 서블릿으로 넘겨줘야한다.
또한 서블릿이 생성, 소멸하는 시점에서 자원 관리도해야하는데 이것들을 하는것이 바로 컨테이너이다.

웹서버가 사용자로부터 서블릿에 대한 요청을 받으면 , 서블릿을 바로호출하는 것이 아니라, 서블릿을 관리하고 있는 컨테이너에게 이 요청을 넘깁니다. 여기서 컨테이너란 물론 서블릿이 배포(deploy)된 컨테이너를 말한다. 요청을 넘겨받은 컨테이너는 HTTP Request와 HTTP Response 객체를 만들어, 이를 인자로 서블릿 doPost()나 doGet() 메소드중 하나를 호출한다.


컨테이너가 하는일


 통신(Communication) 지원
-컨테이너는 서블릿과 웹서버가 서로 통신할 수 있는 손쉬운 방법을 제공한다. 다시말해, 서버와 대화하기위해 개발자가 직접 ServerSocket을 만들고, 특정 포트에 리스닝하고, 연결요청이 들어오면 스트림을 생성하는 등 이런 복잡한 일련의 일을 할필요가 없다는 것이다. 컨테이너는 이런 통신 기능을 API로 제공하고 있다. 따라서 웹 서버와 서블릿이 서로 통신하기위한 통로인 통신 API에 대해 개발자가 고민할 필요가없다.
생명주기(LifeCycle) 관리
-개발자 관점에서 서블릿 클래스를 로딩하여 인스턴스화하고, 초기화 메서드를 호출하고, 요청이 들어오면 적절한 서블릿 메소드를 호출하는 작업을 컨테이너가 한다. 또한 서블릿이 생명을 다한 순간에는 적절하게 가비지 컬렉션을 진행한다. 즉 서블릿의 탄생과 죽음을 관리한다.
멀티스레딩 지원
-컨테이너는 요청이 들어올 떄마다 새로운 자바 스레드를 하나 만듭니다. 클라이언트의 요청에 따라 적절한 HTTP 서비스 메소드를 실행하면 그걸로 스레딩 작업은 끝이 난다(스레드가 죽는다.). 스레드 안전성에 대해선 서버가 다중 요청에 대한 스레드 생성 및 운영에 대해서 알아서 해주니 걱정 할 필요없다.
선언적인 보안관리
-컨테이너를 사용하면 보안에 관련된 내용을 서블릿 또는 자바클래스 코드 안에 하드코딩 할 필요가 없다. 컨테이너가 있는 환경이라면 보안관리는 XML 배포 서술자에 기록하면되는데 이말은 보안에 대해 뭔가 수정할 일이 생기더라도 자바 소스 코드를 수정하여 다시 컴파일하지 않아도 보안관리가 가능하다는 말이다.
JSP 지원


컨테이너가 요청에 응답하는 것을 그림으로 보면


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

MVC 패턴  (0) 2011.06.24
서블릿 매핑, 배포 서술자(DD, Deployment Descriptor)  (0) 2011.06.23
CGI 와 Servlet 의차이  (0) 2011.06.22
CGI(Common Gateway Interface)  (0) 2011.06.22
웹 서버에 응답과 요청  (0) 2011.06.22

서블릿은 서버에서 실행되는 프로그램이다.
그리고, 서블릿의 모태는 CGI라고 할수 있다.

기존의 HTML은 정적인 페이지만을 서비스 할수 있었지만,
CGI는 요청페이지내에 서버용 프로그램을 삽입하여,
서버에서 처리한 결과를 서비스 할수 있다.


CGI는 사용자의 요청이 있을때마다 프로세스를 하나씩
생성한다. 이로인한 단점은 서버의 부하인데
이러한 단점을 극복한 한단계 업그레이드된 버전이
바로 servlet과 jsp이다.

servlet과 jsp는 인-프로세스방식을 사용하는데,
이는 메모리에 라이브러리를 로드시킨뒤 한번 로드된 라이브러리
(프로세스 라고도 함)를 여러 요청에 이용할수 있는 방식이다.
(서버에 부하가 작아짐)
또 하나의 차이점은 servlet과 jsp는 자바의 모든 성질을 그대로
가지고 있기 때문에 스레드 처리도 가능하다는 것이다.

 즉 GI가 클라이언트 프로세스로 처리하는데 반해 서블릿은 클라이언트를 쓰레드로 처리한다. 그래서 많은 클라이언트의 요구를 효과적으로 처리할 수 있다. 서블릿 객체는 쓰레드가 여러 개 돌아가면서 처리하기 때문에 서블릿 메소드들은 반드시 멀티쓰레드에 대한 고려를 해야한다.





웹 서버는 정적인 페이지 서비스만 제공한다.
정적인페이지란 디렉토리에 있는파일 그대로를 말하는데 서버는 단지 클라이언트가 요청한 파일을 찾아서 그대로 클라이언트에게 넘겨줄 뿐이다. 즉 모든 클라이언트가 동일한 결과를 본다는 뜻이다.

웹서버 혼자서 할 수 없는 두가지
1. 동적인 컨텐츠 생성
 앞에서 말했듯이 웹 서버는 단지 정적인 페이지만을 제공할 뿐이다. 그러나 도우미(Helper)애플리케이션이 웹 서버와 협력해서
동적이고, 실시간으로 작성한 페이지를 제공할 수 있다. 예로 이미지 디렉토리에서 임의로 그림을 하나 골라 제공하는 페이지 같은 것을 말한다

2. 서버상에 데이터 저장하기
 
사용자가 폼에 데이터를 입력하고 전송 버튼을 눌렀을경우 웹서버는 혼자 파일이나 데이터베이스에 데이터를 저장할수 없다.
이 경우 웹 서버는 자신을 도와줄 애플리케이션에게 SOS요청을 하는데 웹서버는 파라미터를 애플리케이션에 넘겨주고 응답하도록 부탁한다.

이런 도우미 애플리케이션을 CGI(Common Gateway Interface) 라고 부르며 대부분의 CGI 프로그램은 펄(Perl) 스크립트로 작성한다. 물론 펄 말고도 C, 파이썬, PHP 같은 언어도 있다.

CGI를 가지고 현재시간(동적)을 클라이언트에게 제공하는 것을 살펴보면

 

 


1. 사용자는 정적인 페이지가 아닌 CGI 프로그램에 대한 URL을 클릭한다.


2. 웹 서버는 들어온 요청이 도우미 프로그램을 호출하는 것임을 간파하고는, 해당 프로그램을 실행한다. 물론 GET 또는 POST로 넘어온 파라미터를 그대로 넘겨준다


3. 도우미 프로그램은 현재 시간이 들어간 페이지를 만들어(동적으로) 서버에 HTML 형식으로 넘겨준다. 이시점에서 웹 서버가 도우미 프로그램으로부터 받는 페이지는 정적인 페이지이다.


4. 도우미 프로그램은 페이지를 장사를 끝내고 셔터 문을 내린다. 클라이언트는 정적인 페이지가 된 HTML 페이지를 서버로부터 받는다.