Servlet이 doGet(), doPost()을 바로 호출하지 않고 service()을 호출하는 이유

yunu·2022년 8월 25일
0
post-thumbnail

서블릿 컨테이너가 HttpServletResponseHttpServletRequest를 생성 후 service()를 하는 이유에 대해 왜 이미 http 헤더를 분석하여 원하는 서블릿이 무엇인지 아는 시점에서 doGet(), doPost()를 바로 하지 않고 service()를 호출했는지에 대해 궁금함이 생겨 조사해보았다.

public abstract class HttpServlet extends GenericServlet {
	...
  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) {
                      // 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);
          }
      }
    ...
}

위의 코드는 HttpServlet 추상클래스의 service() 메서드에 대해 가져온 것이다. 보시면 service() 메서드 내부에서 해당하는 메서드에 맞게 조건을 달아놓은 것을 볼 수 있다. 서블릿 컨테이너에서는 서블릿이 어떤 http 메서드인지 알 필요없이 service() 해주면 되기 때문에 코드가 더 간결해지는 것 같다. 처음엔 서블릿 구현체가 아예없는 추상클래스인 줄 알고 service() 내부에 구현되어 있는 것이 없는 줄 알았다. 하지만 구현체가 있는 메서드여서 바로 이해할 수 있었다.
service()를 오버라이딩하여 사용하는 경우는 어떤 http 메서드 간에 공통적인 것을 처리하는 경우이다.(하지만 이런 경우는 오버라이딩한 서블릿 클래스를 다시 상속받아 사용해야할 것 같다). 일반적으로는 서블릿에서 doGet(), doPost() 같은 메서드만 오버라이딩하여 로직을 구현하면 된다.

profile
rip

0개의 댓글