Goal

  • Web Service의 기본적인 동작 과정을 이해한다
  • Servlet을 이해한다

Servlet이란

Servlet의 개념

웹 기반의 요청에 대한 동적인 처리가 가능한 하나의 클래스

  • Server Side에서 돌아가는 Java Program
  • 개발자가 작성하는 부분

Servlet의 기본적인 동작과정

스크린샷 2020-11-10 오전 10 49 45

  1. Web Server는 HTTP Request를 Web Container(Servlet Container)에게 위임한다
    1. web.xml설정에서 어떤 URL과 매핑되어 있는지 확인
    2. 클라이언트(browser)의 요청 URL을 보고 적절한 Servlet을 실행
  2. Web Container는 service() 메소드를 호출하기 전에 Servlet객체를 메모리에 올린다
    1. Web Container는 적절한 Servlet 파일을 컴파일(.class 파일 생성)한다
    2. .class 파일을 메모리에 올려 Servlet 객체를 만든다
    3. 메모리에 로드될 때 Servlet객체를 초기화하는 init()메소드가 실행된다
  3. Web Container는 Request가 올 때 마다 thread를 생성하여 처리한다.
    • 각 thread는 Servlet의 단일 객체에 대한 service() 메소드를 실행한다
  • Servlet Program에서 Thread의 역할
    • Thread의 역할: Servlet의 doGet()또는 doPost()를 호출
    • Web Container(Servlet Container)는 thread의 생성과 제거를 담당한다
      • 하지만 thread의 생성과 제거의 반복은 큰 오버헤드를 만든다
      • 이를 위해서 Tomcat(WAS)는 “Thread Pool”이라는 적절한 매커니즘을 사용해서 오버해드를 줄인다
    • 즉, WAS는 Servlet의 Life cycle을 담당한다
      • 웹 브라우저 클라이언트의 요청이 들어왔을때 Servlet 객체의 생성은 WAS가 알아서 처리한다
      • WAS 위에서 Servlet이 돌아다니고 개발자는 이 Servlet을 만들어야한다

Servlet Life Cycle

스크린샷 2020-11-10 오전 11 18 28

  • 클라이언트에 요청이 들어오면 WAS는 해당 요청에 맞는 Servlet이 메모리에 있는지 확인한다

    • 만약 메모리에 없다면 해당 Servlet Class를 메모리에 올린 후(Servlet 객체 생성)
      • init() 메소드 실행 후 service() 메소드를 실행
    • 메모리에 있다면 바로 service 메소드 실행
      1
      2
      3
      4
      5
      if(메모리에 없음) {
      // 해당 서블릿 클래스를 메모리에 올림
      // init() 메소드를 실행
      }
      // service() 메소드를 실행
  • init()

    • 한 번만 수행된다
    • 클라이언트의 요청에 따라 적절한 Servlet이 생성되고
      이 Servlet이 메모리에 로드될 때 init() 메소드가 실행된다
    • 역할: Servlet 객체를 초기화
  • service()

    • 응답에 대한 모든 내용은 service()메소드에 구현해야한다
    • Servlet이 수신한 모든 request에 대해 service() 메소드가 호출된다
      • HttpServlet을 상속받은 Servlet클래스에서 service()메서드를 오버라이드하지 않았다면, 그 부모인 HttpServlet의 service()가 호출된다
      • HttpServlet의 service()메소드는 템플릿 메소드 패턴으로 구현되었다
      • service()메소드는 request의 type(HTTP Method: GET, POST, PUT, DELETE)에 따라 적절한 메소드(doGet, doPost, doPut, doDelete)를 호출한다
      • 즉, 하위 클래스에서 doGet, doPost등의 메소드를 오버라이드 해두면 HttpServlet의 service()메소드가 요청에 맞는 메소드를 알아서 호출할 수 있게 된다
    • 메소드가 return하면 thread는 종료된다
  • destory()

    • 한 번만 수행된다
    • Web Application이 갱신되거나 WAS를 종료할 때 호출된다
    • 역할: Servlet 객체를 메모리에서 제거

Servlet 메서드 구현 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    // `javax.servlet.http.HttpServlet`를 상속받은 Servlet 클래스
public class LoginServlet extends HttpServlet {
// doPost()를 재정의
protected void doPost(HttpServletRequest request, HttpServletResponse response throws ServletException, IOException {
// read form fields
String username = request.getParameter("username");
String password = request.getParameter("password");

// get response writer
PrintWriter writer = response.getWriter();

/* 여기서 -> DB 접근 등 Business Logic 부분을 처리 */

// build HTML code (view 생성 부분)
String htmlResponse = "<html>";
htmlResponse += "<h2>Your username is: " + username + "<br/>";
htmlResponse += "Your password is: " + password + "</h2>";
htmlResponse += "</html>";

// return response
writer.println(htmlResponse);
}
}
  • WAS는 웹 브라우저로부터 요청을 받으면

    1. 요청할 때 가지고 있는 정보를 HttpServletRequest객체를 생성하여 저장한다
    2. 웹 브라우저에게 응답을 보낼 때, 사용하기 위한 HttpServletResponse 객체를 생성한다
    3. 생성된 HttpServletRequest, HttpServletResponse 객체를 Servlet에게 전달한다
  • 일반적으로 javax.servlet.http.HttpServlet를 상속받은 Servlet클래스를 작성한다

    1. HttpServletRequest request 파라미터를 통해서 사용자가 입력한 data를 읽는다
    2. HttpServletResponse 파라지터를 통해서 출력/결과를 생성한다
  • Servlet 클래스에 doGet() 또는 doPost()중 적어도 하나를 재정의하여 작성한다

    • protected doGet()(HttpServletRequest request, HttpServletResponse response){}
    • protected doPost()(HttpServletRequest request, HttpServletResponse response){}
  • HttpServletRequest request 객체

    • 사용자가 입력한 내용을 request 객체에 받아온다

      • Http 프로토콜의 Request정보를 Servlet에 전달
    • 헤더 정보, 파라미터, 쿠키, URI, URL, Body의 Stream등을 읽어 들이는 메소드가 있다.

    • getHeader(“원하는 헤더 이름”)

      • 원하는 헤더 정보를 확인할 수 있다
    • getParameter()

      • 이 메소드를 호출하여 parameter값을 가져온다
        • parameter값은 URL또는 form의 input tag를 통해서 넘어올 수 있다
      • Ex.
        1
        2
        String name = request.getParameter("firstname");
        int year = Integer.parseInt (request.getParameter("year"));
    • getParameterValues()

      • parameter가 여러 개의 값을 반환할 때 이 메소드를 호출한다. (Ex. checkbox)
        1
        String languages[] = request.getParameterValues("language");

Servlet Concurrency

스크린샷 2020-11-10 오후 1 35 15

  • Java 서블릿 컨테니어/ 웹 서버는 일반적으로 멀티 쓰레드 환경이다.

    • 같은 Servlet에 대한 여러 개의 요청이 동시에 실행될 수 있어 runtime에 따라 결과가 달라질 수 있다
    • 즉, Servlet은 메모리에 한 번 올라오고 멀티 쓰레드 환경에서 여러 thread는 하나의 Servlet을 공유하기 대문에 Concurrency Control가 필요하다
  • Servlet의 service() 메소드 안의 변수

    • 정적 변수, 맴버 변수: 공유하는 자원이므로 상호 배제가 필요
    • 지역 변수: thread마다 독립적으로 생성

Servlet Annotation

스크린샷 2020-11-10 오후 1 44 53

  • Servlet API 3.0은 javax.servlet.annotation이라는 새로운 패키지를 도입했다.
    • Tomcat 7이상에서 사용가능
  • Annotation은 Web Deployment Descriptor파일(web.xml)의 XML 설정을 대체할 수 있다
  • Annotation Type
    • @WebServlet: 서블릿 선언
    • @WebInitParam: 초기화 매개 변수 지정
  • Ex)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @WebServlet(value = "/Simple", 
    initParams = {@WebInitParam(name="foo", value="Hello "),
    @WebInitParam(name="bar", value=" World!")})
    public class Simple extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setContentType("text/html");
    PrintWriter out=response.getWriter();

    out.print("<html><body>");
    out.print("<h3>Hello Servlet</h3>");
    out.println(getInitParameter("foo"));
    out.println(getInitParameter("bar"));
    out.print("</body></html>");
    }
    }