1. Servlet Class Diagram
서블릿 컨테이너에서 사용되는 클래스들의 관계를 나타낸 클래스 다이어그램
큰 그림으로 이해하면 Servlet 인터페이스를 추상 클래스인 GenericServlet 이 구현,
그리고 이 GenericServlet 을 HttpServlet 이 상속하고 있다.
GenericServlet 의 메소드 Service()는 ServletRequest, ServletResponse 객체를 인자로 받고 있고,
HttpServlet 의 메소드 Service()는 HttpServletRequest, HttpServletResponse 객체를 인자로 받고 있다.
HttpServletRequest 는 ServletRequest 를 상속,
HttpServletResponse 는 ServletResponse 를 상속.
이것이 무엇을 의미하는가 생각해 볼 필요가 있다.
우리가 지금 쓰고 있는 브라우저 앞에는 http 또는 https 가 붙어 있는데,
이것은 통신규약(프로토콜) 중 하나를 의미한다.
http는 응용계층의 프로토콜로 사용자(클라이어트)의 요청을 서버에서 적절히 처리하여 응답한다.
클라이언트가 http에 요청을 하면 요청 정보는 HttpServletRequest, HttpServletRespose 객체를 가지고
서블릿 컨테이너로 들어가서 HttpServlet 클래스의 메소드들을 이용하여 처리된다.
그럼 httpServlet 클래스만 작성해 두면 될 것을, 왜 GenericServlet 추상 클래스를 만들어 두었을까?
여기서부터는 나만의 상상으로 적는 글이므로 사실이 아닐 수도 있겠지만.. 적어 보도록 하겠다.
만약 http 보다 뛰어난 프로토콜이 등장한다고 가정해 보자.
그 프로토콜의 이름을 superHttp라고 하면,
SuperHttpServletRequest, SuperHttpServletResponse 객체를 가지고
SuprerHttpServlet 클래스의 메소드들을 가지고 요청을 처리해야 할 것이다.
객체지향 개념의 다형성을 생각해 보자.
프로토콜이 바뀌어도 GenericServlet 추상클래스를 상속하는 클래스로 만들면
서블릿 컨테이너 세상을 움직이고 있는 코드의 수정이 거의 일어나지 않을 것이다.
그래서 아마 자바 세상에서 이렇게 클래스 다이어그램을 만들어 두지 않았을까 조심스럽게 생각해 본다.
2. 클라이언트 요청을 처리하는 HttpServlet 클래스의 메소드들
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; try { request = (HttpServletRequest) req; response = (HttpServletResponse) res; } catch (ClassCastException e) { throw new ServletException("non-HTTP request or response"); } service(request, response); } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic doGet(req, resp); } else { long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); if (ifModifiedSince < (lastModified / 1000 * 1000)) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { // // Note that this means NO servlet supports whatever // method was requested, anywhere on this server. // String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } } | cs |
댓글