본문 바로가기
Java/Servlet & JSP

JSP) Servlet 템플릿 이용하여 Servlet 생성, @WebServlet 이노테이션, Servlet 생명주기

by 박채니 2022. 6. 16.

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

 

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.


Servlet 템플릿 이용하여 Servlet 생성하기

 

ctrl+N - Servlet 

Servlet 요청 URL을 별칭으로 변경해주었습니다. (클라이언트 쪽에 서버단의 구조를 노출하는 것을 방지)

 

오버라이드 할 메소드를 제공해주고, 기본으로 doGet, doPost 메소드가 체크 되어있습니다.

저는 init, destroy 메소드를 추가하고 Finish

 

@WebServlet("URL") 어노테이션

- web.xml에 url-parttern과 servlet 클래스를 바인딩하는 것과 동일한 작업

@WebServlet("/servlet/lifeCycle.do")
public class ServletLifeCycleTest extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ServletLifeCycleTest() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Servlet#init(ServletConfig)
	 */
	public void init(ServletConfig config) throws ServletException {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Servlet#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

위와 같이 HttpServlet을 상속하는 클래스가 생성되었습니다.


Servlet

  - GenericServlet 추상 클래스 : Servlet 인터페이스를 구현

    - HttpServlet 추상 클래스

       - ServletLifeCycle의 상속 구조를 갖고 있습니다.

 

* 사용자 요청이 접수되면 HttpServlet#service 메소드가 호출되고, 그 안에서 전송방식에 따라 doGet, doPost 호출 처리

(HttpServlet#service 메소드를 보고 싶다면 HttpServlet을 ctrl + 클릭한 후 Attach Source에 다운받았던 src.zip 파일 등록)

 

service 메소드를 확인해보겠습니다.

tomcat 안에 생성한 프로젝트(web2)가 있고, tomcat은 사용자 요청이 들어오면 요청 정보를 분석하여 request 객체와 response 객체를 미리 생성!

생성된 request, response 객체를 생성한 프로젝트(web2)의 servlet에 전달하면서 호출하는데, 맨 처음 service 메소드를 호출하고, 그 안에서 doGet/doPost 메소드가 호출!

doGet/doPost 등 분기처리하는 service 메소드

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;
                try {
                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                } catch (IllegalArgumentException iae) {
                    // Invalid date header - proceed as if none was set
                    ifModifiedSince = -1;
                }
                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);
        }
    }

 

* Servlet은 tomcat(WAS/Web Container)에 의해 Singletone패턴으로 관리됨

   (프로그램 운영 중에 단 하나의 객체만 만들어서 운영)

* 사용자 요청 당 하나의 쓰레드가 생성되어 처리 (응답성 향상)

 

* Servlet LifeCycle

① 생성자 호출 (실제 요청 처리될 작업 등)

② init 호출 (실제 요청 처리될 작업 등)

③ service - doGet/doPost

④ destroy 호출 (Servlet에서 사용한 자원 반납처리 등)

 

생명주기 확인하기

<li><a href="/web2/servlet/lifeCycle.do">Servlet 생명주기</a></li>

 

@WebServlet("/servlet/lifeCycle.do")
public class ServletLifeCycleTest extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ServletLifeCycleTest() {
        System.out.println("[ServletLifeCycleTest 생성자 호출]");
    }

	/**
	 * @see Servlet#init(ServletConfig)
	 */
	public void init(ServletConfig config) throws ServletException {
		System.out.println("[init 호출]");
	}

	/**
	 * @see Servlet#destroy()
	 */
	public void destroy() {
		System.out.println("[destroy 호출]");
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("[GET /servlet/lifeCycle.do 호출!]");
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}
}

 

@콘솔출력값

서버 접속 시

[ServletLifeCycleTest 생성자 호출]
[init 호출]
[GET /servlet/lifeCycle.do 호출!]

만일, 매 요청마다 Servlet객체가 생성된다면 위 출력값이 똑같이 호출될 것입니다.

하지만 Singletone패턴으로 관리되므로, 그렇지 않습니다.

 

새로고침

[ServletLifeCycleTest 생성자 호출]
[init 호출]
[GET /servlet/lifeCycle.do 호출!]
[GET /servlet/lifeCycle.do 호출!]
[GET /servlet/lifeCycle.do 호출!]

service(doGet/doPost)만 호출이 되는 것을 확인할 수 있습니다.

 

서버 종료 시

[destroy 호출]