자바 개발을 한다면 한번쯤은 들어봤을 것이다. 웹 서버 개발자라면 필히 알고있어야지!!
책과 인터넷을 뒤져보다 제일 이해하기 쉬운 블로그의 글을 가져와서 조금 수정했다.
1. 서블릿이란 무엇인가?
먼저 서블릿이라는 개념을 잘 이해하는 것이 중요하다고 생각한다. 개념을 이해하지 못한다면 뒤로 갈수록 동작 여부에만 만족하는 싸구려 개발자가 될 가능성이 크다. 하지만 이 서블릿이라는 놈은 개념 잡기가 매우 힘들었다. 자바의 어떤 한 기술을 말하는건지, 자바 클래스를 말하는건지 아니면 어떤 클래스를 상속 받아서 구현된 자바 프로그램들을 말하는건지... 즉, 어떤 기술을 서블릿이라고 부르는건지, 어떤 규칙을 지킨 하나의 웹 어플리케이션을 말하는건지 너무 햇갈렸다. 내 성격상 일단 받아들이고 천천히 이해하려는 성격은 아닌지라... 꽤 고생했다.
서블릿의 용어는 Server program + let (웹 서버에서 실행되는 작은 프로그램 단위) 의 합성어라고 하는 사람들도 있고 Server + Applet 이라는 사람들도 있다. 뭔가 더 햇갈리는 느낌이 강하게 나지만 결국 "클라이언트 요청을 처리하고 그 결과를 다시 클라이언트에게 전송하는 Servlet 클래스의 구현 규칙을 지킨 자바 프로그램" (클라이언트의 HTTP 요청에 대해 특정 기능을 수행, HTML문서를 생성등의 응답을 하는 인터넷 서버 프로그램) 이라고 이해하면 될 것 같다. 그렇게 타협했다. 물론 자바와 관련이 있으므로 당연히 JDK 가 필요하다. 즉 자바 API 와 이를 동작시키는 JVM 이 필요하다는 소리이다.
2. 서블릿 컨테이너
그렇다면 서블릿이라는 놈을 관리해주는 놈이 있어야 하지 않을까? 그냥 서버에 서블릿 만들어서 위치해 둔다고 클라이언트의 Request/Response 를 처리해줄리가 없다. 결론적으로 서블릿을 관리해주는 놈을 서블릿 컨테이너라고 한다. 서블릿 컨테이너는 서블릿의 생명주기를 관리하고 요청에 따른 스레드를 생성해준다. 또, 클라이언트의 Request 를 받아주고 Response 를 보낼 수 있게 웹 서버와 소켓을 만들어서 통신을 해준다. 자세한 서블릿 컨테이너의 역할은 아래와 같다.
- 통신 지원
서블릿과 웹 서버가 통신할 수 있는 손쉬운 방법을 제공한다. 우리가 통신을 한다고 생각할 때 소켓을 만들고, 특정 포트를 리스닝하고, 연결 요청이 들어오면 스트림을 생성해서 요청을 받는다고 알고있는데 이 과정을 서블릿 컨테이너가 대신 해주는 것이다. 서블릿 컨테이너는 이런 통신 과정을 API 로 제공하고 있기 때문에 우리가 쉽게 사용할 수 있다. - 생명주기 관리
서블릿 컨테이너가 기동되는 순간 서블릿 클래스를 로딩해서 인스턴스화하고, 초기화 메서드를 호출하고, 요청이 들어오면 적절한 서블릿 메소드를 찾아서 호출한다. 만약 서블릿의 생명이 다하는 순간 가비지 컬렉션을 진행한다. - 멀티스레딩 관리
서블릿 컨테이너는 해당 서블릿의 요청이 들어오면 스레드를 생성해서 작업을 수행한다. 즉 동시의 여러 요청이 들어온다면 멀티스레딩 환경으로 동시다발적인 작업을 관리한다. - 선언적인 보안관리
서블릿 컨테이너는 보안 관련된 기능을 지원한다. 따라서 서블릿 코드 안에 보안 관련된 메소드를 구현하지 않아도 된다. - JSP 지원
3. 톰캣
톰캣이라면 프로그래밍을 하는 사람들은 다 들어봤을 이름이다. 하지만 솔직하게 말해서 나는 톰캣을 "오픈소스 웹 서버 아니야? 그거 돌리면 고양이 웹 페이지 뜨던데" 정도로 알고 있었다. 뭐... 어찌됐든 톰캣은 서블릿 컨테이너이다. 톰캣은 웹 서버와 연동하여 실행할 수 있는 자바 환경을 제공하여 자바 서버 페이지(JSP)와 자바 서블릿이 실행할 수 있는 환경을 제공하고 있다. 톰캣은 관리툴을 통해 설정을 변경할 수 있지만, XML 파일을 편집하여 설정할 수도 있다. 그리고, 톰캣은 HTTP 서버도 자체 내장하기도 한다. 보통 톰캣은 WAS 의 기능을 수행한다라고 말한다. 요즘 톰캣의 버젼이 올라가면서 웹 서버의 기능도 충분히 잘 수행하기 때문에 굳이 웹 서버와 WAS 를 나눠서 생각하지 않아도 되지만... 정확한 개념을 필요하는 사람은 여기를 참고하면 되겠다. (http://blog.naver.com/PostView.nhn?blogId=ssohyuny2000&logNo=155249496)
--------------------------------------------------------------------------------------------------------------------------
서블릿 프로그램.
간단한 서블릿 프로그램 구현을 해본다면 뭔가 딱 감이온다.
servlet 3.0 미만
public class DefaultServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public DefaultServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>TestWeb2</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description></description>
<display-name>DefaultServlet</display-name>
<servlet-name>DefaultServlet</servlet-name>
<servlet-class>com.js.DefaultServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DefaultServlet</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
</web-app>
servlet 3.0이상 에서는 서블릿 맵핑을 어노테이션 기능을 이용해도 된다.
@WebServlet("/test")
public class DefaultServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public DefaultServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see Servlet#init(ServletConfig)
*/
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
}
/**
* @see Servlet#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
/**
* @see HttpServlet#doPut(HttpServletRequest, HttpServletResponse)
*/
protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
/**
* @see HttpServlet#doDelete(HttpServletRequest, HttpServletResponse)
*/
protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>TestWEb1</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
일반적으로 사용자가 만드는 서블릿은 javax.servlet.HTTP.HTTPServlet을 상속받아 구현한다.
프로그래머가 작성하는 서블릿 클래스는 추상 클래스 HttpServlet에 있는 메소드 중 클라이언트 사용자가 요청한 정보에 따라 처리해야 할 메소드를 오버라이딩 해서 구현한다.
doGet() : 클라이언트 HTTP GET 요청에 대해 처리.
doPost() : 클라이언트 HTTP POST 요청에 대해 처리.
doPut() : 클라이언트 HTTP PUT 요청에 대해 처리.
doDelete() : 클라이언트 HTTP DELETE 요청에 대해 처리.
init() : 서블릿의 생명주기 처리로 가장처음에 실행.
destory() : 서블릿의 생명주기 처리로 서블릿 객체를 메모리에서 제거할때 마지막으로 실행.
서블릿 생명주기 (servlet Life Cycle)
서블릿 생성 -> init() -> { service() -> doXxx() } -> destory() -> 서블릿 종료 ( {} 반복 )
서블릿 클래스 객체가 생성되면 가장 처음에 메소드 init()이 실행되며, 클라이언트의 요청이 들어 올 때마다 service() 메소드가 실행되어 요청에 맞는 메소드 doXxx()를 생행한다. 마지막으로 서버가 종료되거나 서블릿을 더 이상 사용할 필요가 없어 서블릿 객체를 메모리에서 제거할 때, 마지막으로 메소드 destory()가 실행되어 사용하던 자원을 정리하고 종료된다.
init()과 destory()는 서블릿의 생서오가 종료시 단 한번이 실행되며 service() 메소드는 사용자의 요청이 있을 때마다 반복적으로 실행된다.
참고.
'일하다가??' 카테고리의 다른 글
OSX : NFS Mount (NFS 마운트) (0) | 2016.10.31 |
---|---|
해시값의 복호화 ?? (18) | 2016.10.08 |
암호화 알고리즘 종류 (1) | 2016.10.08 |
자바 어노테이션 (Java Annotation) (0) | 2016.04.30 |
java volatile 키워드 (7) | 2016.04.30 |
댓글