서블릿 컨테이너(FrontController)를 직접 구현하면
URI 맵핑, 보안, 다국어, 바인딩 기능
을 개발자가 계속 처리해 주어야 합니다.
이것을 간편화 하기위해스프링
의DispatcherServlet
으로 전환해 보겠습니다.
이제 프론트컨트롤러 패턴을 직접 구현한게 아닌 Spring의 DispatcherServlet
을 사용하고 있습니다.
DispatcherServlet
이 작업을 위임할 applicationContext
를 등록하여 사용한 것을 확인 할 수 있습니다.
public static void main(String[] args) {
GenericWebApplicationContext applicationContext = new GenericWebApplicationContext(); // 스프링 컨테이너 생성
applicationContext.registerBean(HelloController.class); // 메타정보를 넣어 Bean을 생성
applicationContext.registerBean(SimpleHelloService.class);
applicationContext.refresh(); // Bean을 만드는 명령어
// 서블릿 펙토리 : 서블릿 컨테이너를 만드는 것을 쉽게 도와줍니다.
ServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
// serverFactory.getWebServer : 서블릿 컨테이너 생성하는 메소드입니다.
// 따라서 webServer 가 서블릿 컨테이너 입니다.
WebServer webServer = serverFactory.getWebServer(servletContext -> {
servletContext.addServlet("dispatcherServlet",
new DispatcherServlet(applicationContext) // DispatcherServlet이 작업을 위임할 applicationContext를 등록
).addMapping("/*"); // 모든 요청을 다 받는다.
});
webServer.start();
}
아직 중요한게 남아있습니다.
스프링 컨테이너가 갖고있는 오브젝트에게 위임을 요청해야하는데 어디로 요청해야하는지
에 대한 요청정보
가 없습니다.
즉, 서블릿 컨테이너 코드 대신 컨트롤러 클래스 안에 매핑정보를 넣어야 합니다.
@RequestMapping
public class HelloController {
// final은 처음 생성할때 꼭 필요하므로 생성자가 꼭! 있어야 합니다.
private final HelloService helloService;
public HelloController(HelloService helloService) {
this.helloService = helloService;
}
@GetMapping("/hello")
public String hello(String name){
// 컨트롤러의 중요한 역할인 유저의 요청사항을 검증하기
return helloService.sayHello(Objects.requireNonNull(name));
}
}
우선 DispatcherServlet
은 모든요청을 받고 그 후에 DispatcherServlet가URI
를 확인하여 주입받은 applicationContext
의 Bean
을 확인하고 일치하는 URI가 있는지 확인하고
servletContext.addServlet("dispatcherServlet",
new DispatcherServlet(applicationContext) // DispatcherServlet이 작업을 위임할 applicationContext를 등록
).addMapping("/*"); // 모든 요청을 다 받는다.
return타입이 String이라면 스프링은 기본적으로
dispatcherServlet
은 view라는 html템플릿을 찾아 view를 리턴해라! 라고 인식합니다.
지금은 html 파일이 없기때문에 에러가 발생한 것입니다.
@ResponseBody
를 붙이면 웹응답의 Body에값에 그대로 들어가게 됩니다.
그렇기에 HttpMessageConverter
가 내부적으로 Json으로 변환하여 전송합니다.
@GetMapping("/hello")
@ResponseBody
public String hello(String name){
// 컨트롤러의 중요한 역할인 유저의 요청사항을 검증하기
return helloService.sayHello(Objects.requireNonNull(name));
}