서블릿 개발하기 연재목록

#1 개발환경 구축 (https://opensrc.tistory.com/180?category=475522)

#2 프로잭트 생성 (https://opensrc.tistory.com/181?category=475522)

#3 첫번째 JSP 파일 만들기 (https://opensrc.tistory.com/182?category=475522)

#4 첫번째 서블릿 만들기 (https://opensrc.tistory.com/183?category=475522)

#5 포스트 요청을 처리하는 서블릿 만들기 (https://opensrc.tistory.com/203?category=475522)

#6 GET/POST 요청과 함께 파라메터 전달 하기 (https://opensrc.tistory.com/204?category=475522)

#7 Servlet 들여다 보기 (https://opensrc.tistory.com/206?category=475522)

===========================================================

 

이 포스트를 처음 시작한 이유는 요즘 Java Web Application 개발을 가르치는 서적이나 교육기관들을 보면 Java Web Application 의 기본인 Servlet 을 가르치지 않고 처음부터 Spring 같은 잘 만들어진 프레임워크를 이용하여 시작합니다.

실제 현장에서 개발을 할 때도 프레임워크를 사용하지 않고 HttpServlet 을 상속받아서 사용하는 일은 거의 없습니다. 물론 그래도 상관 없을 만큼 국내 Java 기반의 프로잭트의 대부분은 Spring 기반으로 되어 있습니다. 심지어 공공에서 많이 쓰이는 전자정부 프레임워크 조차 Spring기반입니다.

사실 기본적인 Servlet 형태를 모르고 Spring만 잘 해도 개발 하는데 문제가 없겠지만 가끔 Spring Application 은 어떻게 동작 할까... 하는 생각이 들 때가 있을 것 같아서 기본적인 HttpServlet 을 확장해서 Spring MVC Application 과 비슷한 형태로 만들어 보는 것이 목적입니다. 물론 Spring 처럼 수많은 사람들에 의해서 만들어 지고 검증된 프레임워크 처럼 편하고 뛰어난 기능을 모두 갖추기는 어렵지만 Spring은 물론 Java MVC Web Application이 어떻게 동작하는지 이해하는데 도움이 되었으면 좋겠다는 생각에 시작했습니다.

사설이 길었습니다.

 

[서블릿 개발하기] #7 Servlet 들여다 보기

이전 시간까지 우리가 만든 HelloWorldServlet은 javax.servlet.http.HttpServlet을 상속받았습니다.

HttpServlet 의 소스코드는

https://github.com/javaee/servlet-spec/blob/master/src/main/java/javax/servlet/http/HttpServlet.java

 

javaee/servlet-spec

The API and Issue Tracker for the JCP Standard Java Servlet Specification - javaee/servlet-spec

github.com

이곳에서 보실 수 있습니다.

 

HttpServlet 클래스 선언부에 보면 javax.servlet.GenericServlet 을 상속 받은것을 알 수 있습니다.  GenericServlet 의 소스는 이곳에서 살펴 보실 수 있습니다.

https://github.com/javaee/servlet-spec/blob/master/src/main/java/javax/servlet/GenericServlet.java

 

javaee/servlet-spec

The API and Issue Tracker for the JCP Standard Java Servlet Specification - javaee/servlet-spec

github.com

GenericServlet 은 javax.servlet.Servlet, javax.servlet.ServletConfig, java.io.Serializable 의 구현체 이네요 관심있으신 분은 소스를 더 살펴보셔도 좋습니다. 이 포스트에서는 HttpServlet까지만 살펴보겠습니다.

 

 

우리가 만든 HelloWorldServlet 의 GET Request와 POST 요청을 처리하는 goGet(), doPost() 메소드는 상속받은 HttpServlet 의 doGet과 doPost를 각각 재정의(Override)한 것입니다. HttpServlet.java 소스에 각 메소드의 원형을 살펴보면

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException

이렇게 생겼습니다.

사용자로부터 들어오는 요청에 대한 정보는 HttpServletRequest  req 에 담아서 전달 됩니다.

사용자에게 응답해야 하는 정보는 HttpServletResponse resp 에 담아주면 됩니다.

우리가 만든 doGet, doPoat는 이것을 재정의 한 것 입니다. 꼭 있어야 하는 것은 아니지만 우리가 만든 HelloWordServlet.java가 컴파일 될 때 부모 클래스의 기능을 Override 한 것이라고 표시를 해주면 좋을 것 같습니다.

	@Override 
	public void doGet(HttpServletRequest request, HttpServletResponse response)
    	throws ServletException, IOException {

		...

	}
    
 	@Override 
	public void doPost(HttpServletRequest request, HttpServletResponse response)
    	throws ServletException, IOException {

		...

	}  

이렇게 어노테이션을 붙혀주면 더 보기좋네요.

다시 위에 HttpServlet.java 소스를 살펴보면 GET과 POST 외에도 PUT, DELETE 같은 요청을 처리하는 doPut, doDelete 같은 메소드도 있습니다. 전에 말씀드린 대로 POST 요청에 대해 잘 이해를 하신다면 PUT과 DELETE를 사용하시는 데도 문제가 없을 것 같습니다.

다른 것들은 건너 뛰고 좀 더 살펴보면 service 라는 메소드가 보입니다.

    protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
        ...
    }

이렇게 생겼네요 설명을 보면 

Receives standard HTTP requests from the public service method and dispatches them to the doXXX methods defined in this class...

아마도 doGet, doPost 같은 요청을 이 매소드가 대신 처리 해준다는 소리 같습니다.

소스를 조금 살펴 보면

    protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String method = req.getMethod();

        if (method.equals(METHOD_GET)) {
        ... 생략...
        	doGet(req, resp);
        ... 생략...
        } else if (method.equals(METHOD_HEAD)) {
        ... 생략...
            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 {
        ... 생략...
            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }

request 의 메소드를 확인해서 각각을 처리 하는게 보입니다.

정말 그렇게 되는가 우리가 만든 HelloWorldServlet 에 적용해 보도록 하겠습니다.

service 메소드가 작동 하려면 기존에 있던 doGet, doPost 는 삭제 해야 합니다.

package com.tistory.opensrc.basicservlet.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 첫번째 hello, world 서블릿
 * @author cloud
 *
 */
public class HelloWorldServlet extends HttpServlet {

	/**
	 * serial version id
	 */
	private static final long serialVersionUID = 701289870660846795L;

	/**
	 * 사용자 요청을 처리
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	@Override
	public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		response.setContentType("text/html"); // text html 형태로 출력 하겠다고 지정함
		PrintWriter out = response.getWriter(); // response로 부터 출력 장치를 확보
		
		String yourName = request.getParameter("your_name"); // request에서 화면으로 부터 넘어온 파라메터의 값을 추출 합니다. 
		
		// html 내용을 출력
		out.println("<html>");
		out.println("hello, world<br/>");
		out.println("method : " + request.getMethod() + "<br/>");
		out.println("You'r name is " + yourName);
		out.println("</html>");
	}
}

이렇게 바꿔봤습니다.

GET Request

POST Request

네 잘 동작 합니다.

특별히 GET, POST 중 어느 한가지만 처리 하려는 목적이 아니라면 service 를 사용하면 둘다 하나의 로직으로 처리 할 수 있어서 로직을 추가 하기 용이하고 혹시 GET이나 POST 같은 특정 요청만 처리 하겠다고 한다면 위의 소스에서 처럼 request.getMethod()를 받아서 분기 처리 해주시면 될 것 같습니다.

다음 시간에는 Java Web Application에서 한글 처리에 대해 이야기 해보도록 하겠습니다.

+ Recent posts