컨테이너의 역할

  • 커뮤니케이션 (통신) 지원
    • 통신 기능 관련한 API 를 지원한다.
  • 라이프 사이클 관리
    • 서블릿 클래스를 로딩, 인스턴스화, 초기화 메소드 호출, 서블릿 메소드 호출, 서블릿 소멸 등을 수행한다.
  • 멀티 스레딩 관리
    • 클라이언트로부터 요청이 들어올때마다 새로운 자바 스레드를 생성
    • HTTP 서비스 메소드를 실행하면 스레딩 작업은 종료된다.
    • 서버는 다중 요청에 대한 스레드 생성 및 운영에 대해서 자동으로 처리한다.
  • 보안 관리
  • JSP 지원

컨테이너의 판단

  • 컨테이너는 클라이언트의 요청에 대해서 서블릿이라는 것을 판단한다.
    • ServletRequest & ServletResponse 객체를 생성
    • 들어온 객체를 HttpServletRequest & HttpServletResponse 객체로 캐스팅
    • 메소드에 따라서 GET 또는 POST 인지 결정하고 Response 객체로 클라이언트에 실어보낸다.
    • 이후 스레드 작업이 완료되면, 객체는 소멸되며 GC 에 의해 처리가 된다.

 

HttpServlet 클래스의 Service Method

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    
    HttpServletRequest request;
    HttpServletResponse response;
    
    try {
    
    	request = (HttpServletRequest)req;
    	response = (HttpServletResponse)res;
        
    } catch (ClassCastException var6) {
    
    	throw new ServletException("non-HTTP request or response");
    
    }

	this.service(request, response);
}

 

method 무엇인지 판단, 분기처리를 수행

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader("If-Modified-Since");
                if (ifModifiedSince < lastModified) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } 

 

서블릿 라이프 사이클 

  • init()
  • service()
    • doGet() / doPost()
  • destroy()

이렇게 존재한다.

 

라이프 사이클을 확인하기 위해 HttpServlet 클래스를 상속받는 커스텀 서블릿을 만들었다. .

public class DemoServlet extends HttpServlet{

    private static final long serialVersionUID = 1L;

    public void init(ServletConfig config) throws ServletException{
        System.out.println("=====> 서블릿 init()");
        super.init();
    }

    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException{
        System.out.println("=====> 서블릿 service()");
        super.service(request, response);
    }

    public void destroy(){
        System.out.println("=====> 서블릿 destroy()");
    }
    
    /**
     * doGet() 또는 doPost() 오버라이딩 ...
    **/
    
}

톰캣을 실행시키고 서블릿에 매핑되는 URL 을 브라우저에 입력한다.

  • init() 과 service() 가 순서대로 실행
  • 새로고침을 수행하면 service() 만 실행
  • 톰캣을 종료하면 destroy() 가 실행

init()

  • 컨테이너가 서블릿 인스턴스를 생성한 이후에 수행하는 메소드이다.
  • 클라이언트의 요청을 처리하기 전에 서블릿을 초기화할 수 있는 기회를 주는 것이다.

 

service()

  • 최초 클라이언트의 요청을 받았을 때, 컨테이너는 새로운 스레드를 생성 또는 스레드 풀로부터 하나의 스레드를 가지고와서 해당 메소드를 수행한다.

 

클라이언트의 요청 & 서로 다른 스레드

  • 컨테이너는 하나의 서블릿으로 다수의 요청을 처리하려고 한다.
  • 이를 위해서 다수의 스레드를 생성한다.
  • 다수의 인스턴스는 생성하지 않는다.
  • 클라이언트 요청 당 하나씩 스레드가 생성된다.
  • 클라이언트로부터 들어오는 모든 요청은 자신만의 스레드/스택을 할당받는다.

 

reference

헤드퍼스트 디자인 패턴 : Servlet & JSP

Posted by doubler
,