일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 인텔리제이
- MVC2
- DDL
- MVC
- Join
- 코딩테스트
- 메이븐
- SQL
- 프로그래머스
- 서블릿
- toUpperCase
- Model2
- 코테
- @Controller
- 스프링
- 인프런
- select
- 서브쿼리
- 세션
- 기술 대비
- Model1
- STS
- 프레임워크
- 김영한
- @RestController
- order by
- 자바
- AOP
- JSP
- 뉴렉처
- Today
- Total
Heestory
03.Spring-MVC)MVC 프레임워크 만들기 본문
프레임워크 점진적인 발전 요약
v1 : 프론트 컨트롤러 도입
- 기존 구조를 최대한 유지하면서 프론트 컨트롤러를 도입
v2: VIew 분류
- 단순 반복 되는 뷰 로직 분리
v3 : Model 추가
- 서블릿 종속성 제거
- 뷰 이름 중복 제거
v4 : 단순하고 실용적인 컨트롤러
- v3과 구조 거의 비슷
- 구현 입장에서 ModelView를 직접 생성해서 반환하지 않도록 편리한 인터페이스 제공
v5 : 유연한 컨트롤러
- 어댑터 도입
- 어댑터를 추가해서 프레임워크를 유연하고 확장성 있게 설계
FrontController : 서브릿 하나로 클라이언트의 요청을 받아 맞는 컨트롤러를 찾아 호출
→ DispathcherServlet이 FrontController 패턴으로 구현되어 있다.
프론트 컨트롤러 도입 - v1
View 분리 - v2
String viewPath = "/WEB-INF/views/new-form.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
v1에서 모든 컨트롤러에서 뷰로 이동하는 부분의 중복이 있어 리펙토링
다른 패키지에서 쓴다면 클래스 위치 주의, MyView 클래스
public class MyView {
private String viewPath;
public MyView(String viewPath){
this.viewPath = viewPath;
}
public void render(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
public void render(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
modelToRequestAttribute(model, request);
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
Controlle의 반환 타입을 MyView로 해두어 공통 기능을 쓸 수 있게 한다
public interface ControllerV2 {
MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
→ dispatcher.forward()를 직접 생성해서 호출하지 않고 MyView 객체를 생성한 후 뷰 이름만 넣고 반환하면 된다
return new MyView("/WEB-INF/views/new-form.jsp");
MyView view = controller.process(request, response);
view.render(request, response);
Controller의 반환 타입이 MyView이기 때문에 FrontController의 반환 타입도 MyView 객체 생성해서 반환
render에(위의 코드참고) 호출하여 forward 로직 수행
Model 추가 - v3
서블릿 종속성 제거
: 컨트롤러 입장에서 HttpServletRequest 등은 곡 필요하지 않다. 요청 파라미터 정보를 자바의 Map으로 대신 넘기도록 함녀 지금 구조에서는 컨트롤러가 서블릿의 기술을 몰라도 동작할 수 있다.
request 객체를 Model로 사용하는 대신에 별도의 Model 객체를 만들어서 반환하면 된다.
→ 구현 코드도 매우 단순해지고, 테스트 코드 작성이 쉽다
뷰 이름 중복 제거
:컨트롤러는 뷰의 논리 이름을 반환하고 실제 물리 위치의 이름은 프론트 컨트롤러에서 처리하도록 단순화 하자
→ 뷰의 폴더 위치가 함께 이동해도 프론트 컨트롤러만 고치면 된다
ModelView
: Model을 직접 만들고, 추가로 View 이름가지 전달하는 객체용
public class ModelView {
private String viewname;
private Map<String,Object> model = new HashMap<>();
//setter,getter 생략
}
뷰의 이름과 뷰를 런더링 할 때 필요한 model 객체를 가지고 있다.
ControllerV3
public interface ControllerV3 {
ModelView process(Map<String, String> paramMap);
}
서블릿 구조 사용하지 않음
HttpServletRequest가 제공하는 파라미터는 프론트 컨트롤러가 paramMap에 담아서 호출
응답 결과로 뷰 이름과 뷰에 전달할 Model데이터를 포함하는 ModelView객체를 반환
return new ModelView("new-form");
view의 논리적 이름만 사용하고 , 실제 물리적이름은 프론트 컨트롤러에서 처리
이후 프론트 컨트롤러에서 뷰 리졸버를 이용하여 반환한 논리 뷰 이름을 실제 물리 뷰 경로로 변경한다.
또한 JSP는 request.setAttribute(), request.getAttribute()를 이용하기 때문에 model에 담아둔 내용을 변경한다.
단순하고 실용적인 컨트롤러 -v4
ModelView 객체를 생성하고 반환해야 하는 부분이 번거로워 ModelView를 반환하지 않고 viewName만 반환하도록
컨트롤러에서 model을 파라미터로 전달하기 때문에 뷰 이름만 반환
//ControllerV4
public interface ControllerV4 {
/**
*
* @param paramMap
* @param model
* @return
*/
String process(Map<String,String> paramMap, Map<String, Object> model);
}
public String process(Map<String, String> paramMap, Map<String, Object> model) {
//v3와 비교했을때 modelview가 필요 없음
return "new-form";
}
이후 프론트 컨트롤러에선 paramMap과 model 객체를 생성한다.
유연한 컨트롤러1 - v5
어댑터 패턴
: ControllerV3, ControllerV4 는 완전히 다른 인터페이스이다. 이런 호환이 필요할 대 어댑터
- 핸들러 어댑터 : 어댑터, 다양한 종류의 컨트롤러 호출
- 핸들러 : 컴트롤러의 이름을 더 넓은 범위의 핸들러로 변경
//어댑터를 이렇게 구현해야 한다는 어댑터용 인터페이스
public interface MyHandlerAdapter {
//어댑터가 해당 컨트롤러를 처리할 수 있는지 판단하는 메서드
boolean supports(Object handler);
//실제 컨트롤러를 호출하고 그 결과로 ModelVeiw를 반환
ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException;
}
public class FrontControllerServletV5 extends HttpServlet {
// private Map<String, ControllerV4> controllerMap = new HashMap<>();
private final Map<String, Object> handlerMappingMap = new HashMap<>(); //핸들러매핑 정보 담겨있음, Object - Controller 종류 무관하게 담기 위해
private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>(); //List 어댑터가 여러개 담겨있어 여기에 정보 담는다
//생성자는 핸들러 매핑과 어댑터를 초기화(등록)한다
public FrontControllerServletV5() {
initHandlerMappingMap(); //핸들러 매핑 초기화
initHandlerAdapters(); //어댑터 초기화
}
private void initHandlerMappingMap() {
handlerMappingMap.put("/front-controller/v5/v3/members/new-form", new MemberFormControllerV3());
handlerMappingMap.put("/front-controller/v5/v3/members/save", new MemberSaveControllerV3());
handlerMappingMap.put("/front-controller/v5/v3/members", new MemberListControllerV3());
handlerMappingMap.put("/front-controller/v5/v4/members/new-form", new MemberFormControllerV4());
handlerMappingMap.put("/front-controller/v5/v4/members/save", new MemberSaveControllerV4());
handlerMappingMap.put("/front-controller/v5/v4/members", new MemberListControllerV4());
}
private void initHandlerAdapters() {
handlerAdapters.add(new ControllerV3HandlerAdapter());
handlerAdapters.add(new ControllerV4HandlerAdapter());
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//URI를 통해 핸들러를 찾는다. 핸들러 매핑
Object handler = getHandler(request); //핸들러 찾아와
if (handler == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
//어댑터 찾기, 핸들러를 처리할 수 있는 어댑터 조회
MyHandlerAdapter adapter = getHandlerAdapter(handler); //어댑터 찾아와
//어댑터 호출
ModelView mv = adapter.handle(request, response, handler);
String viewName = mv.getViewname();
MyView view = veiwResolver(viewName);
view.render(mv.getModel(),request,response);
}
'개발(~국비) > Spring' 카테고리의 다른 글
05.Spring-MVC)기본 기능 (0) | 2022.11.05 |
---|---|
04.Spring-MVC)MVC 구조의 이해 (0) | 2022.11.04 |
02.Spring MVC)서블릿,JSP,MVC 패턴 (0) | 2022.11.01 |
01.Spring MVC)서블릿 (0) | 2022.10.28 |
09. 스프링)빈 스코프 (0) | 2022.10.27 |