서블릿실행순서(Q. 서블릿 클래스의 계층 구조는?/Q. 생명주기흐름은?)/HttpServletRequest/HttpServletResponse객체의 주요 메서드

굥굥이·2022년 5월 2일
0

✨ 서블릿 클래스 계층 구조

  • 서블릿 APIservlet과 servletConfig 인터페이스를 구현해 제공하여 GenericServlet 추상 클래스가 이 두 인터페이스의 추상 메서드를 구현한다. 그리고 이 GenericServlet을 다시 HttpServlet이 상속받는다.
    ( + GenericServlet 추상 클래스는 잘 쓰지 않는다. Http 프로토콜에 대응하는 전용 서블릿인 HttpServlet 추상클래스가 제공되기 때문.)
  • 기존의 Servlet인터페이스를 구현해야 했다면 해당 인터페이스의 메서드도 같이 구현해야 했다.
    (특히 라이프사이클 메서드라 불리는 init(), service(), destroy()를 일일이 구현해야 했다.)
    => 하지만 해당 추상 클래스(GenericServlet/HttpServlet)를 사용하면 service()만 구현하면 바로 서블릿을 사용할 수 있다.

> 서블릿의 API 기능

  • Servlet 인터페이스(javax.sevlet 패키지에 선언돼있음) : 모든 서블릿이 구현해야 하는 메서드를 정의하고 있는 인터페이스이다. 서블릿 패키지의 중심이라고 할 수 있는데, 서버가 서블릿을 관리할 수 있도록 서블릿의 생명주기에 필요한 라이프 사이클 메서드(init(), service(), destroy())를 제공하기 때문이다.
    • 주요 메서드
      init() : 서블릿 컨테이너가 서블릿을 초기화하기 위해 호출하는 메서드.(단 한번만 실행됨. 이 과정이 성공적으로 끝나야 service()메서드가 이용가능하다.)
                참고로 초기화할 때 init()은 서블릿 초기화를 위한 정보를 가진 ServletConfig객체를 파라미터로 전달받아서 서블릿을 초기화한다.
      service() : 서블릿이 클라이언트 요청(requese)에 응답(response)할 수 있도록 하는 메서드.
                   컨테이너는 클라이언트 요청이 있을 때 해당 메서드를 실행한다. 그러면 service()메서드는 요청에 따른 메서드를 실행한다.(doGet, doPost, doPut, doDelete)
                   서블릿은 한 번 불러왔다면 초기화는 더이상 수행되지 않는데, 그렇기 때문에 사용자 요청이 있으면 웹 컨테이너는 사용자의 요청이 맞춰 스레드를 만든다. 그리고 그 스레드를 통해서 service메서드를 실행하고 이미 초기화가 끝나 대기중인 서블릿을 실행한다.
      destroy() : 서블릿이 더이상 사용되지 않을 때 일반적으로 개발자가 아닌 컨테이너에 의해 호출된다. (단 한번만 실행됨)서비스 메서드 내 모든 스레드가 종료되거나 제한 시간이 지나면 호출된다.
                   이 메서드를 실행함으로서 서블릿과 관련된 각종 리소스들이 종료된다.
      getServletConfig() : ServletConfig 객체값을 불러올 수 있도록 하는 메서드다.
                           init()메서드 호출 시, web.xml을 참고하여 서블릿 초기화에 관련된 정보를 저장하는 SservletConfig객체가 파라미터 값으로 전달되는데, 이때 객체값을 불러올 수 있는 메서드이다. 
      getServletInfo() : 서블릿과 관련된 다양한 정보(버전, 저작권자, 작성자)를 문자열로 반환해준다.
    • 내가 이해한 흐름 : init()메서드는 서블릿 초기화를 해주는데, 이 때 서블릿 초기화를 위한 정보를 가진 ServletConfig객체를 파라미터로 전달받아야 한다. 이 객체를 불러오려면 getServletContig()메서드를 호출하여야 한다. 그리하여 init()메서드가 성공적으로 끝이나면 service()메서드를 이용해 서블릿 이용(요청/응답)을 할 수 있다. 시간이 지나서 서버가 종료되거나 모든 스레드가 종료되면 destroy()메서드가 자동으로 실행되어, 서블릿이 종료된다.
  • Servlet Config 인터페이스(javax.sevlet 패키지에 선언돼있음) : 서블릿 컨테이너가 서블릿을 초기화 할 때 필요로 하는 정보를 전달해주기 위해 만든 인터페이스이다. 해당 인터페이스를 기반으로 만든 servletConfig객체는 배포서술자로도 불리는 web.xml을 참고하여 서블릿 초기화를 위한 정보를 저장한다.
  • GenericServlet 클래스(javax.sevlet 패키지에 선언돼있음) : 상위 두 인터페이스를 구현하여 일반적인 서블릿 기능을 구현한 클래스이다. Servlet의 라이프사이클 메서드 중 init(), destroy()를 간단하게 제공하므로, 즉 사용자는 service()만 구현하여 서블릿을 간편하게 실행할 수 있다.
  • HttpServlet 클래스(javax.servlet.http 패키지에 선언돼있음) : GenericServlet을 상속받아 HTTP 프로토콜을 사용하는 웹 브라우저에서 서블릿 기능을 수행하는 클래스이다. init(), destroy(), service()까지 구현돼 있다. service()가 호출되면서 요청 방식에 따라 doGet()이나 doPost()가 차례대로 호출된다.

> HttpServlet의 여러가지 메서드 기능

  • protected doGet(HttpServletRequest req, HttpServletResponse resp) : 서블릿이 GET request를 수행하기 위해 service()를 통해서 호출된다.
  • protected doPost(HttpServletRequest req, HttpServletResponse resp) : 서블릿이 POST request를 수행하기 위해 service()를 통해서 호출된다.
  • protected Service (HttpServletRequest req, HttpServletResponse resp) : 표준 HTTP request를 public service()에서 전달받아 doXXX() 메서드를 호출한다.
  • public service (HttpServletRequest req, HttpServletResponse resp) : 클라이언트의 request를 protected service()에게 전달한다.
  • 흐름정리 : 클라이언트 요청 시 public service()메서드를 먼저 호출한 후, 다시 protected service()메서드를 호출한다. 그런다음 다시 request 종류에 따라 doxxx()메서드를 호출하는 과정으로 실행된다.

🎨 그림으로 앞에서 배운 것들을 정리해보자

  • 먼저 Servlet 생명주기를 보자. 여기에서 꼭 알아둬야 할 부분은 Servlet 객체 생성과 init()호출은 단 한 번만 이뤄 진다는 것! destroy()또한 마찬가지!
    그렇다면 실행이 된 적이 있는 서블릿이라면, 생명주기에서는 계속 service()메서드만 호출되고 이 service()메서드에서 요청에 따른 메서드(doGet() 혹은 doPost()를 실행한다는 점을 알 수 있다.
  • 이제 Servlet 생명주기에서 더 나아가, 전체적인 흐름을 보도록 하자. (핑크색으로 칠해놓은 게, 무조건 서블릿 실행 시 실행되는 것들이다.)
    컨테이너가 HttpServletRequest, HttpServletResponse 두 객체를 생성한 후, Web.xml 문서에 따라 그에 맞는 서블릿을 찾았다면, 해당 서블릿 클래스를 로드하는데 이 때 서블릿에서 사용할 객체를 만들고 이 객체를 이용해 init()메서드를 호출한다.
    위에서 적은 클래스 로드, 서블릿 인스턴스 생성, init()은 서블릿 생명 주기에서 단 한번만 수행되는 것들이다.(=한 개의 서블릿이 처음 요청될 때만 수행됨)
    그리고 많은 요청이 다중으로 들어오면, 이 한 개의 인스턴스를 사용해서 새로운 스레드를 생성하여 service()메서드를 실행한다.
  • 처음 요청될 때가 아니라면 어떻게 실행되는지 흐름을 보도록 하자. 여기서 꼭 알아두어야 할 점은 서블릿에 대한 최초 요청이 있을 때만 서블릿을 초기화하는 작업을 하고, 그 뒤에는 최초에 만든 인스턴스 하나스레드를 이용service()메서드를 실행하여 처리한다는 점이다.
  • 요청을 실질적으로 처리하는 것은, service()메서드라는 것을 꼭 알아두자!!!(service()메서드가 요청에 따른 메서드를 실행하기 때문) 최초 실행이든 다음 실행이든 service()메서드는 무조건 실행된다.

✨ HttpServlet 추상클래스를 상속한 서블릿을 사용해보자

  1. HttpServlet 추상 클래스를 상속받는다.
    public class 서블릿명 extends HttpServlet {
  2. doGet() 혹은 doPost()메서드의 매개변수로 HttpServletRequest과 HttpServletResponse를 받아서 사용하면 된다. (굳이 service()메서드는 오버라이딩하여 사용하지 않음)
      // 'request.위에서 배운 메서드' 혹은 'response.위에서 배운 메서드'로, 요청을 추출 혹은 응답해주면 된다.
       doGet(HttpServletRequest request, HttpServletResponse response){}
       doPost(HttpServletRequest request, HttpServletResponse response){}

> HttpServletRequest 객체의 주요 메서드

  • HttpServletRequest : 클라이언트가 서버에 보내는 요청정보를 처리하는 객체
    • 클라이언트가 서버로 요청하는 정보로는 클라이언트의 IP주소, 포트번호 / 클라이언트가 전송한 요청 헤더 정보 / 요청 방식 / 질의(Query) 문자열 등이 있다. 위와 같은 정보를 아래 메서드들을 이용해 출력해보자.
    • ServletResquest 인터페이스 : 네트워크 기반에서 사용되는 기본적인 메소드들로만 구성되어 있음. 나머지는 HttpServletRequest 객체에서 확장 지원하고 있음.
      //주요 메소드
      Object getAttribute(String name) : ServletRequest 객체 안에 등록된 데이터를 추출하여 반환한다.
      Enumeration getAttributeNames() : ServletRequest 객체 안에 등록된 데이터들의 이름 전부를 하나의 Enumeration 객체에 담아서 반환한다.
      String getCharacterEncoding() : 클라이언트가 서버에 서비스를 요청할 때 사용한 문자들의 인코딩 문자셋을 반환한다.
      int getContentLength() : 서비스 요청 시 보낸 요청정보 몸체에 포함된 데이터의 길이를 반환한다. 만약 길이를 알 수 없을 때는 -1를 반환한다.
      ServletInputStream getInputStream() : 요청정보 몸체로부터 바이너리 데이터를 읽어들이기 위해 한 번에 한 줄씩 읽을 수 있는 ServletInputStream 객체를 반환한다.
      String getParameter(String name) : 클라이언트가 보낸 질의 문자열 중에서 인자로 지정된 name과 일치하는 것을 찾아 name의 value를 반환한다.
      Enumeration< String> getParameterNames() : 클라이언트가 서버로 보낸 질의 문자열들의 이름을 하나의 Enumeration 객체에 담아서 반환한다.
      String[] getParameterValues(String name) : 클라이언트가 서버로 보낸 질의 문자열 중에서 인자로 지정된 name과 일치하는 모든 값을 찾아 하나의 String 타입의 배열에 담아 반환한다.
      String getProtocol() : 클라이언트가 서버에 서비스를 요청하면서 사용한 프로토콜 정보를 반환한다.
      BufferedReader getReader() : 요청정보 몸체로부터 문자 인코딩에 따라 텍스트를 읽어들이기 위한 BufferedReader 객체를 반환한다.
      String getRemoteAddr() : 서버에 서비스를 요청한 클라이언트의 IP 주소를 반환한다.
      String getScheme() : 서비스 요청 시 사용한 http, https, 또는 ftp 등과 같은 프로토콜 이름을 반환한다.
      String getServerName() : 서비스를 요청받은 서버의 이름을 반환한다.
      int getServerPort() : 클라이언트의 서비스를 요청받은 서버 포트 번호를 반환한다.
      ServletContext getServletContext() : 서버가 시작될 때 웹 애플리케이션 단위로 생성된 ServletContext 객체의 주소를 추출하여 반환한다.
      void removeAttribute(String name) : ServletRequest 객체에 setAttribute(name) 메소드를 이용하여 등록된 데이터를 삭제한다.
      void setAttribute(String name, Object o) : 클라이언트의 또 다른 서비스 요청에서도 계속해서 사용하고 싶은 데이터는 서버에 저장해야 하는데 ServletRequest 객체 안에 저장(등록)해준다.
      void setCharacterEncoding(String env) : 클라이언트가 요청정보 몸체에 포함해서 보내는 문자열들을 지정된 문자셋을 이용해 인코딩해준다.
    • HttpServletResquest 인터페이스 : 프로토콜에 기반하는 세션이나 쿠키와 같은 정보들을 추출함.
      //주요 메소드
      String getHeader(String headerName) : HTTP 요청 헤더에 지정된 headerName의 값을 문자열로 반환한다. 만일 HTTP 요청 헤더에 headerName의 값이 없으면 null을 반환한다.
      Enumeration getHeaderNames() : HTTP 요청 헤더에 포함된 모든 헤더의 이름을 Enumeration으로 반환한다.
      Enumeration getHeaders(String headerName) : HTTP 요청 헤더에 포함된 headerName의 모든 값을 Enumeration으로 반환한다.
      int getIntHeader(String headerName) : HTTP 요청 헤더에 포함된 headerName의 값을 int로 반환한다. 지정된 headerName의 값을 int로 변환할 수 없을 때 NumberFormat Exception이 발생하고, headerName 헤더가 HTTP 요청 헤더에 없을 때 -1을 반환한다.
      long getDateHeader(String headerName) : HTTP 요청 헤더에 포함된 headerName의 값을 밀리초로 변환하여 long으로 반환한다. 지정된 header의 값을 int로 변환할 수 없을 때 IllegalArgumentException이 발생하고, headerName 헤더가 HTTP 요청 헤더에 없을 때 -1을 반환한다.
      String getPathInfo() : 클라이언트가 서비스 요청 시 보낸 요청 URL의 뒷부분에 있는 path 정보를 반환한다.
      HttpSession getSession() : 서비스를 요청한 클라이언트가 사용하는 HttpSession 객체를 반환한다. 만일 반환할 HttpSession 객체가 없으면 새로 생성하여 반환한다.
      HttpSession getSession(boolean create) : 서비스를 요청한 클라이언트가 사용하는 HttpSession 객체를 반환한다. 만일 반환한 HttpSession 객체가 없으면 getSession(true)이면 새로 생성하여 반환한다. 그러나 getSession(false)이면 HttpSession 객체를 새로 생성하지 않고 null을 반환한다.
      String getRequestedSessionId() : 서비스를 요청한 클라이언트가 사용하는 HttpSession의 ID를 반환한다.
      boolean isRequestedSessionIdValid() : 서비스를 요청한 클라이언트가 사용하는 HttpSession 객체가 유효한지를 판단한다.
      boolean isRequestedSessionIdFromCookie() : 서비스를 요청한 클라이언트가 사용하는 HttpSession의 ID가 쿠키로 전달되면 true, 그렇지 않다면 false를 반환한다.
      boolean isRequestedSessionIdFromURL() : 서비스를 요청한 클라이언트가 사용하는 HttpSession의 ID가 URL에 포함되면 true, 그렇지 않다면 false를 반환한다.
      Cookie[] getCookies() : 서비스를 요청받은 서버가 서비스를 요청한 클라이언트에게 이전에 보낸 모든 쿠키를 추출한다.
      String getRequestURI() : 클라이언트가 서비스 요청 시 보낸 URL에서 URI 부분만 반환한다.
      String getQueryString() : 클라이언트가 GET 방식으로 서버에 보낸 질의 문자열들을 모두 추출하여 반환한다.
      String getMethod() : 클라이언트가 서비스를 요청할 때 요청한 방식의 이름을 반환한다.
      String getPathTranslated() : 클라이언트가 서비스 요청 시 보낸 URL의 경로 정보를 절대경로(path)로 변경하여 반환한다.

> HttpServletResponse 객체의 주요 메서드

  • HttpServletResponse : 서버가 클라이언트로 보내는 응답정보를 처리하는 객체
    • ServletResponse 인터페이스 : 일반적인 네트워크 통신에서의 응답 관련 메소드 제공
      //주요 메소드
      PrintWriter getWriter() : 서비스를 요청한 클라이언트와 서버 간에 연결된 PrintWriter 객체를 생성하여 반환한다.
      void setBufferSize(int size) : 출력스트림의 버퍼 크기를 설정한다.
      void setCharacterEncoding(String charset) : 응답정보 인코딩에 사용할 문자를 설정한다.
      void setContentLength(int len) : 응답정보의 데이터 길이를 설정한다.
      void setContentType(String type) : 응답정보의 데이터 형식(MIME 타입)을 설정한다.
      void setLocale(Locale loc) : 클라이언트가 사용하는 언어, 국가코드 등 클라이언트의 환경을 설정한다.
    • HttpServletResponse 인터페이스 : HTTP 통신 기반의 응답 관련 메소드 확장 제공( ex : 쿠키 설정, HTTP 응답 헤더 설정 등)
      //주요 메소드
      void addCookie(Cookie cookie) : 인자값으로 주어진 쿠키를 응답정보의 헤더에 추가한다. 쿠키는 응답정보의 Set-Cookie 헤더의 값으로 추가되어 클라이언트로 전송된다.
      String encodeRedirectURL(String url) : 클라이언트와 서버 간 세션이 유지되는 상태에서 브라우저 쿠키를 지원하지 않을 때 주어진 URL 뒤에 세션 아이디를 추가하고 인코딩하여 요청을 재전송한다.
      String encodeURL(String url) : 주어진 URL에 세션 아이디를 추가하여 인코딩해서 반환한다.
      void sendRedirect(String location) : 응답을 클라이언트가 요청한 URL이 아니라 sendRedirect()에 주어진 URL로 재전송한다. 매개변수 location은 절대 URL이나 상대 URL로 지정한다. 이 메소드는 서버의 특정 자원이 다른 URL로 이동할 때 사용할 수 있는 메소드이다.
      public void setDateHeader(String name, long date) : 날짜를 밀리 초로 변환하여 주어진 이름과 날짜를 응답정보 헤더에 설정한다.
      public void setHeader(String name, String value) : 응답정보의 헤더에 주어진 이름과 값을 설정한다.
      public void setIntHeader(String name, int value) : 주어진 이름과 정수값을 갖도록 응답정보 헤더에 추가한다.
      public void setStatus(int sc) : 응답으로 전송될 HTTP 응답에 대한 상태코드를 설정한다.

+ DD(Deployment Descriptor : 배포서술자)설정 방법

  • DD설정(Web.xml) : Deploy(배포)할 때 Servlet의 정보를 설정해준다.
    브라우저가 Java Servlet에 접근하기 위해서는 WAS(ex : Tomcat)에 필요한 정보를 알려줘야, 해당하는 Servlet을 호출할 수 있다.
    • 정보 1 : 배보할 Servlet이 무엇인지 / 정보 2 : 해당 Servlet이 어떤 URL에 매핑되는지
      <web-app>
      		<!-- 1. aliases 설정 -->
      		<servlet>
      			<servlet-name>welcome</servlet-name> //2. 해당 클래스의 
      			<servlet-class>servlets.WelcomeServlet</servlet-class> //1. 실제 클래스 이름 설정. ex ) 패키지이름.클래스이름
      		</servlet>
      		<!-- 2. 매핑 -->
      		<servlet-mapping>
      			<servlet-name>welcome</servlet-name>
      			<url-pattern>/welcome</url-pattern>
      		</servlet-mapping>
      </web-app>

+ 참고

https://sgcomputer.tistory.com/226
https://loco-motive.tistory.com/2
https://kgvovc.tistory.com/31?category=957989
https://chicken-park.tistory.com/10
https://sgcomputer.tistory.com/232

profile
아자아자 파이띵굥!

0개의 댓글