프론트 컨트롤러
servlet이 여러개로 늘어나고
모든 서블릿이 container로 부터 요청을 직접받아 수행하고 return하는 방식으로 코드를 만드니까
대부분 서블릿에서 공통으로 하는 일들도 중복되는 코드로 나타났다.
서블릿은 웹 요청과 응답을 직접적으로 다뤄줘야 하기 때문에 자연스럽지 않다
그래서 서블릿만 가지고 기능을 개발하는데에는 한계가 있다.
이를 개선하기 위한 첫번째 시도는 frontController이다.
원래의 서블릿은 url에 맞게 mapping해서
각기 다른 서블릿이 각기 다른 url을 맡아서 처리하는 방식으로 동작을 해야 했는데
그렇게 하지 말고 모든 서블릿에 공통적으로 등작하는 처리하는 코드를
중앙화된 제일 앞단에 존재하는 컨트롤러라고 이름을 붙이고 공통적인 작업을 처리하고
요청에 따라 로직을 처리하는 곳에 위임하는 방식으로
애플리 케이션이 돌아가게 만드는 것이다.
"공통적인 로직을 앞단 또는 뒷단에서 처리하게 하는 것이 포인트이다."
서블릿을 이용해서 프론트컨트롤러를 만드는 개발방식이 많이 사용되어짐
인증, 보안, 다국어처리 모든 웹 요청에 대해서 공통적으로 처리해야 하는 작업들은 프론트 컨트롤러가 처리하도록 하는 것이다.
프론트 컨트롤러를 직접 만들어보자.
package com.example.tobyboot;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class TobybootApplication {
public static void main(String[] args) {
TomcatServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
// TomcatServletWebServerFactory serverFactory = new JettyServletWebServerFactory();
WebServer webServer = serverFactory.getWebServer(servletContext -> {
servletContext.addServlet("frontcontrller", new HttpServlet() {
HelloController helloController = new HelloController();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 인증, 보안, 다국어, 공통으로 처리해야 하는 기능이 구현되어 있다고 하자
// uri == hello, method == get
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);
} else if (req.getRequestURI().equals("/user")) {
//
} else {
resp.setStatus(HttpStatus.NOT_FOUND.value());
}
}
// / 밑으로 들어오는 모든 요청을 처리하겠다. (front controller 책임을 맡게 된다.)
}).addMapping("/*");
});
// 톰캣 서블릿 컨테이너가 동작한다.
webServer.start();
System.out.println("Hello containerless Standalone Application");
}
}
package com.example.tobyboot;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
public String hello(String name) {
return "Hello " + name;
}
}
spring container를 설명 (Spring 공식문서)
비지니스 로직을 담고있는 비지니스 오브젝트임 pojo가 필요하다. (어떤 클래스도 상속받지 않는 클래스)
이렇게 만들어진 코드를 어떻게 구성할지 정보를 담고 있는 Configuration metadata 를 Spring container가 조합해서
완전히 구성된 시스템을 만든다.
스프링 컨테이너를 대표하는 이름이 있다.
application context
application context , 어떤 빈이 들어갈지, 리소스가 접근하는 방법, 내부에 이벤트를 전달하고 구독하는 방법들, 이런 기능들을 담고 있는 것이 application context고, 이것에 스프링 컨테이너다.
코드로 손쉽게 만들 수 있는 application context 가 있는데 GenericApplicationContext이다.
GenericApplicationContext applicationContext = new GenericApplicationContext();
서블릿은 직접 addServlet을 통해서 binding을 진행하였다
스프링 같은 경우에는 object를 직접 만들어서 넣는 방법도 가능하지만
일반적으로 어떤 클래스를 이용하여 bean object를 생성할 것인가 meta 정보를 넣어주는 방식으로 구성
applicationContext.registerBean(HelloController.class);
빈 등록이 끝난것이다.
container를 초기화 하는 작업, bean object를 만들어 주는 작업을 실행한다.
applicationContext.refresh();
applicationContext에서 bean 이름, class type으로 등록되어있는 bean 객체를 받아올 수 있다.
'강의 > 토비의 스프링부트' 카테고리의 다른 글
자바코드 구성 정보 사용 (0) | 2023.02.21 |
---|---|
di 적용 (0) | 2023.02.20 |
Dependency injection (0) | 2023.02.20 |
dsf (0) | 2023.02.19 |
토비의 스프링부트 (0) | 2023.02.19 |