패키지명
com.koreait.app 까지는 똑같은데,
클라이언트/사용자에게 뭔갈 제공하는 역할을 한다면? view가 붙는다. (물론 회사마다 다르다)
DispatcherServlet
먼저 com.koreait.app.view.controller 패키지에
FrontController (Servlet파일)를 만들어준다.
여태까지는 FrontController(FC) 라고 불렀는데,
Spring에서는 얘를 DispatcherServlet 라고 부른다.
하지만 개념적으로 FC 라는 것은 동일하다!
이 파일이 서블릿이기 때문에 일반 컨테이너를 생성할 수 없다.
(일반 컨테이너는 POJO만 관리함, 서블릿은 not POJO)
그래서 서블릿 컨테이너인 톰캣을 사용해야 하고 톰캣은 web.xml을 바라본다.
서블릿 파일 생성 후 web.xml에 가면 무언가 추가가 돼있는 것을 볼 수 있다.
web.xml 태그에 과도한 설정이 싫어서 @ 어노테이션 방식을 사용한다.
그러기 위해 web.xml 내용은 지워준다.
Servlet 파일에는 기본적으로 doGet과 doPost 메서드가 존재한다.
그러나 Get, Post 어떤 방식으로 요청이 올지 모르기 때문에 doAction이라는 메서드를 만들어서
Get이나 Post 요청 어떤게 오더라도 다 doAction으로 갈 수 있도록 코드를 작성해 준다.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doACtion(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doACtion(request, response);
}
// 모든 요청을 받는 메서드
private void doACtion(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Action에서 진행되는 순서는
1. 클라이언트 요청을 추출한다
2. 그 요청에 맞는 Controller를 달라고 핸들러맵핑이라는 팩토리 패턴을 활용하는 객체에게 요청을 한다.
3. 요청에 대한 반환으로 액션 포워드를 반환한다.
인데,
Spring에서는 액션 포워드를 반환하지 않는다.
왜냐하면 무겁다고 느끼기 때문이다!
Sptring에서는 어디로 보내야 할지 판단을 해주는 객체를 사용한다.
이를 View Resolver라고 부른다.
DS에서 사용하는 HandlerMapping과 ViewResolver는 스프링 프레임워크에서 불러온다!
기존의 Action Forward는 어디로 갈지, 어떻게 갈지 두 가지를 다 보내야 하므로 객체로 만들어 줬는데,
현재 ViewResolver가 포워드/리다이렉트 구분을 해주기 때문에 경로만 보내면 된다!!
따라서 객체가 아닌 String 타입의 path만 보내주면 된다.
// DispatcherServlet
package com.koreait.app.view.controller;
import java.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet("*.do")
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private HandlerMapping handlerMapping;
private ViewResolver viewResolver; // 리다이렉트인지 포워드인지 스스로 판단해서 전달해주는 객체
public DispatcherServlet() {
super();
}
public void init() {
this.handlerMapping = new HandlerMapping();
this.viewResolver = new ViewResolver();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doACtion(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doACtion(request, response);
}
private void doACtion(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 사용자(클라이언트,브라우저)의 요청을 추출
String uri=request.getRequestURI();
// 요청을 잘라주는 코드, 어디까지 자를거니? >> 마지막 / 까지
String command=uri.substring(uri.lastIndexOf("/"));
// 2. 요청에 해당하는 Controller 기능을 수행
Controller controller=this.handlerMapping.getController(command);
// 이때 핸들러 맵핑은 팩토리 패턴을 활용하는 hanlerMapping
// 기존에는 요청에 대한 반환으로 액션 포워드를 반환받음
//ActionForward forward = controller.execute(request,response);
// Spring은 액션 포워드를 반환하지 않음. (viewResolver가 포워드/리다이렉트 방식을 판단해주기 때문)
// 따라서 경로 (path)만 보내주면 된다.
String path = controller.execute(request,response);
// 3. 응답 (페이지 이동)
// viewResolver 를 통해 나중에 수행할 것임..!!!
}
}
}
@WebServlet("*.do")
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private HandlerMapping handlerMapping;
private ViewResolver viewResolver; // 리다이렉트인지 포워드인지 스스로 판단해서 전달해주는 객체
DispatcherServlet에서는 의존성을 2개 가지고 있다.
바로 HandlerMapping과 ViewResolver이다.
의존성을 갖고 있기 때문에 DI (의존주입) 해줘야 한다.
DS는 서블릿 파일이기 때문에 독특한 의존 주입이 필요한데,
바로 init() 함수를 사용한 생성자 주입 방식이다.
public void init() {
this.handlerMapping = new HandlerMapping();
this.viewResolver = new ViewResolver();
}
// HandlerMapping.java
package com.koreait.app.view.controller;
import java.util.HashMap;
import java.util.Map;
import com.koreait.app.view.member.LoginController;
import com.koreait.app.view.member.MainController;
public class HandlerMapping {
private Map<String, Controller> mappings;
public HandlerMapping() {
this.mappings=new HashMap<String, Controller>();
this.mappings.put("/login.do", new LoginController()); // 로그인
}
public Controller getController(String command) {
return mappings.get(command);
}
}
그리고 기존 Action 대신 Controller 파일이 필요하다.
이는 메서드 시그니쳐 강제가 필요하니까, 인터페이스 파일로 만들어준다.
package com.koreait.app.view.controller;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
//기존 Action과 구조가 동일함. Action 표현은 소규모 플젝이나, JSP 기반
public interface Controller {
String execute(HttpServletRequest request, HttpServletResponse response); // path!!
}
// 메서드 오버라이딩 강제
// == 메서드 시그니쳐 강제
🍀 정리!
- FrontController는 오늘부터 DispatcherServlet이다.
- 서블릿 파일을 생성했기 때문에 기존 컨테이너로는 얘를 new 할 수 없어서, 서블릿 컨테이너인 톰캣을 사용한다.
- 컨테이너 1개 : xml 1개
- Action은 오늘부터 Controller
- 이때 handlerMapping가 팩토리 패턴을 활용한다.
- web.xml 설정 과도하니까 @ 어노테이션을 사용
- do 요청 3단계
- 응답 객체 ViewResolver 가 생겼기 때문에 객체로 대답하지 않고 String으로 가볍게 응답한다.
- DS 파일의 멤버변수 2개(HandlerMapping과 ViewResolver) == init 생성자 함수로 의존 주입을 한다!
'Spring' 카테고리의 다른 글
[Spring] Spring에서 제공하는 DispatcherServlet과 Controller (7) | 2024.10.08 |
---|---|
[Spring] ViewResolver (0) | 2024.10.07 |
[Spring] Spring의 구조와 Service (0) | 2024.10.06 |
[Spring] @ 어노테이션 설정 (6) | 2024.10.06 |
[Spring] Spring 내용 정리 (0) | 2024.10.06 |