03. Standalone 서블릿 어플리케이션

컨테이너리스 개발 준비

Spring Boot는 서블릿 컨테이너 관련 작업을 수행하므로 개발자는 BEAN 구축에만 집중할 수 있습니다.


컨테이너를 설치 및 배포하지 않고 서블릿 컨테이너가 코드에서 작동하는 방식 구현해보자.

빈 main() 메서드만 남기고 Spring Boot가 사용 중인 것으로 보이는 다음 두 줄을 삭제합니다.

@SpringBootApplication
springApplication.run(HellobootApplication, args);


서블릿 컨테이너 시작


서블릿 컨테이너를 직접 설치하는 대신 독립 실행형 프로그램을 만들어 서블릿 컨테이너를 시작합니다.

Spring Boot 프로젝트 생성 시 웹 모듈을 선택하면 아래와 같은 내장 tomcat 라이브러리(서블릿 컨테이너 제품)가 추가된다.


임베디드 Tomcat의 초기화 및 손쉬운 구성을 지원하기 위해 Spring Boot TomcatServletWebServerFactoryTomcat 웹 서버(서블릿 컨테이너)를 실행하는 코드를 생성할 수 있습니다.

public static void main(String() args) {
	ServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
	WebServer webServer = serverFactory.getWebServer();
	webServer.start();
}
  • TomcatServletWebServerFactory: Tomcat의 서블릿 웹 서버를 생성하는 팩토리 클래스입니다.
  • getWebServer: 실제 웹 서버(서블릿 컨테이너)를 생성하는 생성 함수.

메인 메서드가 실행 중일 때 Tomcat 서버가 포트 8080에서 실행 중인지 확인할 수 있습니다(http 요청을 전송하여 확인할 수 있음).


서블릿 등록

서블릿 컨테이너에 서블릿(웹 구성 요소) 추가.


서블릿을 등록하려면 서블릿 컨텍스트서블릿 등록과 같은 초기화 작업을 수행할 때 ServletWebServerFactory의 getWebServer() 메서드에 ServletContextInitializer를 구현하는 객체를 전달합니다.

ServletContextInitializer @FunctionalInterface그래서 람다 식으로 바꿔서 사용하면 편리합니다. (하나의 기능을 가진 인터페이스)

@FunctionalInterface
public interface ServletContextInitializer {
	void onStartup(ServletContext servletContext) throws ServletException;
}

서블릿은 HttpServlet 클래스를 상속하고 필요한 메서드를 재정의하여 만들 수 있습니다.

https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html

HttpServlet(Java(TM) EE 7 사양 API)

서블릿이 PUT 요청을 처리할 수 있도록 서버에서 호출합니다(서비스 메소드를 통해). PUT 작업을 통해 클라이언트는 파일을 서버에 배치할 수 있으며 FTP를 통해 파일을 보내는 것과 유사합니다. 이 메서드를 재정의할 때 모든 콘텐츠 헤더를 그대로 둡니다.

docs.oracle.com

서블릿을 등록할 때 서블릿 이름과 서블릿 객체를 사용합니다. 매핑할 URL 정보는 서블릿 등록 정보에 지정되어 있습니다.

서블릿에서 Http서블릿 요청다음을 사용하여 요청 정보 추출 HttpServlet 응답다음으로 답변 생성

– 3가지 요소(상태 코드, 헤더, 본문)로 웹 요청을 생성합니다.

public static void main(String() args) {
    ServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
    WebServer webServer = serverFactory.getWebServer(servletContext -> {
        servletContext.addServlet("hello", new HttpServlet() {
            @Override
            protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
                res.setStatus(HttpStatus.OK.value());
                res.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE);
                res.getWriter().println("Hello Servlet");
            }
        }).addMapping("/hello");
    });
    webServer.start();
}


(미리 적어두었다가 다음 강의에 활용합시다.)

프런트 컨트롤러는 처리할 요청을 분류하기 위해 요청을 구문 분석한 후 요청을 처리하는 핸들러(컨트롤러 메서드)로 전달합니다.
핸들러가 반환한 반환 값을 해석하여 웹 요청을 구성합니다.

전면 컨트롤러의 두 가지 주요 기능은 다음과 같습니다. 연결 및 바인딩.

세부 규칙을 지정하면 공통 코드를 사용하여 매핑 및 바인딩을 처리할 수 있습니다.

  • 매핑: HTTP 요청을 처리하기 위한 핸들러 식별 및 연결
  • 바인딩: 웹 요청 정보를 추출하여 의미 있는 개체로 처리기에 전달하는 프로세스입니다.
if (req.getRequestURI().equals("/hello") && req.getMethod().equals(HttpMethod.GET.name())) { 
    String name = req.getParameter("name");
	String ret = helloController.hello(name);
	
    resp.setStatus(HttpStatus.OK.value()); 
    resp.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE); 
    resp.getWriter().println(ret);
}