Goal
- Web Service의 기본적인 동작 과정을 이해한다
- Servlet을 이해한다
Servlet이란
Servlet의 개념
웹 기반의 요청에 대한 동적인 처리가 가능한 하나의 클래스
- Server Side에서 돌아가는 Java Program
- 개발자가 작성하는 부분
Servlet의 기본적인 동작과정
- Web Server는 HTTP Request를 Web Container(Servlet Container)에게 위임한다
- web.xml설정에서 어떤 URL과 매핑되어 있는지 확인
- 클라이언트(browser)의 요청 URL을 보고 적절한 Servlet을 실행
- Web Container는 service() 메소드를 호출하기 전에 Servlet객체를 메모리에 올린다
- Web Container는 적절한 Servlet 파일을 컴파일(.class 파일 생성)한다
- .class 파일을 메모리에 올려 Servlet 객체를 만든다
- 메모리에 로드될 때 Servlet객체를 초기화하는 init()메소드가 실행된다
- 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
클라이언트에 요청이 들어오면 WAS는 해당 요청에 맞는 Servlet이 메모리에 있는지 확인한다
- 만약 메모리에 없다면 해당 Servlet Class를 메모리에 올린 후(Servlet 객체 생성)
- init() 메소드 실행 후 service() 메소드를 실행
- 메모리에 있다면 바로 service 메소드 실행
1
2
3
4
5if(메모리에 없음) {
// 해당 서블릿 클래스를 메모리에 올림
// init() 메소드를 실행
}
// service() 메소드를 실행
- 만약 메모리에 없다면 해당 Servlet Class를 메모리에 올린 후(Servlet 객체 생성)
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 | // `javax.servlet.http.HttpServlet`를 상속받은 Servlet 클래스 |
WAS는 웹 브라우저로부터 요청을 받으면
- 요청할 때 가지고 있는 정보를 HttpServletRequest객체를 생성하여 저장한다
- 웹 브라우저에게 응답을 보낼 때, 사용하기 위한 HttpServletResponse 객체를 생성한다
- 생성된 HttpServletRequest, HttpServletResponse 객체를 Servlet에게 전달한다
일반적으로 javax.servlet.http.HttpServlet를 상속받은 Servlet클래스를 작성한다
- HttpServletRequest request 파라미터를 통해서 사용자가 입력한 data를 읽는다
- 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
2String name = request.getParameter("firstname");
int year = Integer.parseInt (request.getParameter("year"));
- 이 메소드를 호출하여 parameter값을 가져온다
getParameterValues()
- parameter가 여러 개의 값을 반환할 때 이 메소드를 호출한다. (Ex. checkbox)
1
String languages[] = request.getParameterValues("language");
- parameter가 여러 개의 값을 반환할 때 이 메소드를 호출한다. (Ex. checkbox)
Servlet Concurrency
Java 서블릿 컨테니어/ 웹 서버는 일반적으로 멀티 쓰레드 환경이다.
- 같은 Servlet에 대한 여러 개의 요청이 동시에 실행될 수 있어 runtime에 따라 결과가 달라질 수 있다
- 즉, Servlet은 메모리에 한 번 올라오고 멀티 쓰레드 환경에서 여러 thread는 하나의 Servlet을 공유하기 대문에 Concurrency Control가 필요하다
Servlet의 service() 메소드 안의 변수
- 정적 변수, 맴버 변수: 공유하는 자원이므로 상호 배제가 필요
- 지역 변수: thread마다 독립적으로 생성
Servlet Annotation
- 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
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>");
}
}