Adapter ํจํด
by rlaehddnd0422"์ด๋ํฐ ํจํด"์ ์ฌ์ฉํ๋ฉด ControllerV1 ~ ControllerV4๊น์ง, ์ฌ๋ฌ ๋ฒ์ ์ ์ปจํธ๋กค๋ฌ๋ฅผ ๊ฐ์๋ผ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด๋ํฐ ํจํด์ ์ฌ์ฉํด์ Front-Controller๊ฐ ๋ค์ํ ๋ฐฉ์์ ์ปจํธ๋กค๋ฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋๋ก ํด๋ณด๊ฒ ์ต๋๋ค.
๊ทธ๋ฆผ ๊ตฌ์กฐ๋ก ํ์ธํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
ํธ๋ค๋ฌ : ์ปจํธ๋กค๋ฌ์ ๋์ ๋ฒ์์ ์ด๋ฆ์ผ๋ก, ๊ทธ๋ฅ ์ปจํธ๋กค๋ฌ๋ก ์ดํดํ์ ๋ ๋ฉ๋๋ค.
ํธ๋ค๋ฌ-์ด๋ํฐ : ํธ๋ค๋ฌ(์ปจํธ๋กค๋ฌ)์ ์ด๋ํฐ๋ก ๋ค์ํ ์ข ๋ฅ์ ํธ๋ค๋ฌ(์ปจํธ๋กค๋ฌ)๋ฅผ ํธ์ถํ ์ ์๊ฒ ํด์ค. ์์ธํ ์ค๋ช ์ ์ฝ๋๋ฅผ ํตํด ์งํํ๊ฒ ์ต๋๋ค.
0. Client์์ HTTP์์ฒญ์ ๋ณด๋ ๋๋ค.
1. ์์ฒญ URL Pattern๊ณผ ๋งคํ๋ FrontController์์ ํธ๋ค๋ฌ-๋งคํ ์ ๋ณด๋ฅผ ์กฐํํฉ๋๋ค.
2. ํธ๋ค๋ฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ ์ด๋ํฐ๊ฐ ์๋์ง ์กฐํํฉ๋๋ค.
3. ์กฐํํ ์ด๋ํฐ์์ handle(handler) ๋ฉ์๋๋ฅผ ํตํด ํธ๋ค๋ฌ(์ปจํธ๋กค๋ฌ)๋ฅผ ํธ์ถํด ์ปจํธ๋กค๋ฌ ๋ก์ง ์คํ ํ ModelView๋ฅผ ๋ฆฌํดํฉ๋๋ค.
4. Front-Controller์์ ๋ฆฌํด๋ ModelView์ viewName์ ํตํด viewResolverํด์ viewPath๋ฅผ ์ป์ด๋ ๋๋ค.
5. viewPath๋ฅผ ํตํด MyView์์ JSP๋ก forward ํด์ค๋๋ค.
์์๊ณผ์ ์ ์ฝ์ด๋ด๋ ํ ๋ฒ์ ์๋ฟ์ง ์์ ์ฝ๋๋ฅผ ํตํด ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ฐ์ FrontController๊ฐ ModelView๋ฅผ ๋ฆฌํด๋ฐ๊ธฐ ์ ๊ณผ ํ๋ก ๋๋ ์ ์ค๋ช ํ๊ฒ ์ต๋๋ค.
์ฐ์ FrontController ์ ์ฒด ์ฝ๋์ ๋๋ค.
package hello.servlet.web.frontcontroller.v5;
import hello.servlet.web.frontcontroller.ModelView;
import hello.servlet.web.frontcontroller.MyView;
import hello.servlet.web.frontcontroller.v3.controller.MemberFormControllerV3;
import hello.servlet.web.frontcontroller.v3.controller.MemberListControllerV3;
import hello.servlet.web.frontcontroller.v3.controller.MemberSaveControllerV3;
import hello.servlet.web.frontcontroller.v4.controller.MemberFormControllerV4;
import hello.servlet.web.frontcontroller.v4.controller.MemberListControllerV4;
import hello.servlet.web.frontcontroller.v4.controller.MemberSaveControllerV4;
import hello.servlet.web.frontcontroller.v5.adapter.ControllerV3HandlerAdapter;
import hello.servlet.web.frontcontroller.v5.adapter.ControllerV4HandlerAdapter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@WebServlet(name = "frontControllerServletV5", urlPatterns = "/front-controller/v5/*")
public class FrontControllerServletV5 extends HttpServlet {
private final Map<String, Object> handlerMappingMap = new HashMap<>();
private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();
FrontControllerServletV5()
{
initHandlerMappingMap();
initHandlerAdapters();
}
private void initHandlerAdapters()
{
handlerAdapters.add(new ControllerV3HandlerAdapter());
handlerAdapters.add(new ControllerV4HandlerAdapter());
}
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());
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object handler = getHandler(request);
if(handler==null)
{
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
System.out.println("handler = " + handler);
MyHandlerAdapter adapter = getHandlerAdapter(handler);
ModelView mv = adapter.handle(request, response, handler);
String viewPath = viewResolver(mv.getViewName());
System.out.println("viewPath = " + viewPath);
MyView view = new MyView(viewPath);
view.render(mv.getModel(),request,response);
}
private Object getHandler(HttpServletRequest request) {
String requestURI = request.getRequestURI();
Object handler = handlerMappingMap.get(requestURI);
return handler;
}
private MyHandlerAdapter getHandlerAdapter(Object handler)
{
for (MyHandlerAdapter adapter : handlerAdapters) {
if(adapter.supports(handler))
{
return adapter;
}
}
throw new IllegalArgumentException(
"handler adapter๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค." + " handler = " + handler);
}
private String viewResolver(String viewName) {
return "/WEB-INF/views/" + viewName + ".jsp";
}
}
ModelView ๋ฆฌํด ๋ฐ๊ธฐ ์ ์ Front-Controller Logic
1. ์์ฒญ URI - ์ปจํธ๋กค๋ฌ ๋งคํ
private final Map<String, Object> handlerMappingMap = new HashMap<>();
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());
}
HashMap์ ์ด์ฉํด URI-Handler(์ปจํธ๋กค๋ฌ) ๋งคํ์ ํตํด config
2. Handler-Adapter ์ถ๊ฐ
private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();
FrontControllerServletV5()
{
initHandlerMappingMap(); // URI - Handler
initHandlerAdapters(); // Handler - Adapter
}
private void initHandlerAdapters()
{
handlerAdapters.add(new ControllerV3HandlerAdapter());
handlerAdapters.add(new ControllerV4HandlerAdapter());
}
์ฌ๊ธฐ์ MyHandlerAdapter๋ ํธ๋ค๋ฌ-์ด๋ํฐ์ ์ธํฐํ์ด์ค์ ๋๋ค.
๋คํ์ฑ์ ์ด์ฉํ๊ธฐ ์ํด ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ์ต๋๋ค.
public interface MyHandlerAdapter {
boolean supports(Object handler);
ModelView handle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws ServletException, IOException;
}
์ด๋ํฐ์์๋ ๋ ๊ฐ์ง ๋ฉ์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- boolean supports(Object handler) : ์ด๋ํฐ๊ฐ ์ด ํธ๋ค๋ฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋์ง์ ๋ํ ์ฌ๋ถ
- ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException : ์ด๋ํฐ๊ฐ ์ค์ ํธ๋ค๋ฌ๋ฅผ ํธ์ถํ๊ณ ModelView๋ฅผ ๋ฐํ. ์ด์ ์๋ ํ๋ก ํธ์ปจํธ๋กค๋ฌ๊ฐ ์ค์ ์ปจํธ๋กค๋ฌ๋ฅผ ํธ์ถํ์ง๋ง ์ด์ ๋ ์ด ์ด๋ํฐ๋ฅผ ํตํด์ ์ค์ ์ปจํธ๋กค๋ฌ๊ฐ ํธ์ถ๋ฉ๋๋ค.
์ฐ์ ์ค์ ์ด๋ํฐ๋ฅผ ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค.
ControllerV3 ์ด๋ํฐ ์ ๋๋ค.
public class ControllerV3HandlerAdapter implements MyHandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof ControllerV3);
}
@Override
public ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
ControllerV3 controller = (ControllerV3) handler;
Map<String,String> paramMap = createParamMap(request);
ModelView mv = controller.process(paramMap);
return mv;
}
private Map<String, String> createParamMap(HttpServletRequest request) {
Map<String,String> paramMap = new HashMap<>();
request.getParameterNames().asIterator()
.forEachRemaining(paramName -> paramMap.put(paramName, request.getParameter(paramName)));
return paramMap;
}
}
- supports : ์ด ํธ๋ค๋ฌ(์ปจํธ๋กค๋ฌ)๊ฐ ControllerV3์ ์ธ์คํด์ค์ธ์ง์ ๋ํ ์ฌ๋ถ ๋ฆฌํด
- handle : ํธ๋ค๋ฌ๋ฅผ ControllerV3๋ก Object->ControllerV3๋ก ํ์ ๋ณํ โถ๏ธ request๋ฅผ ํตํด ์ ๋ฌ๋ ํ๋ผ๋ฏธํฐ๋ก paramMap์ ์ป์ โถ๏ธ ์ปจํธ๋กค๋ฌ๋ฅผ ํธ์ถํด process(ํ๋ผ๋ฏธํฐ ํ ๋น, JSP ๋์ ๋ฆฌ์์ค ๋ชจ๋ธ์ put ๋ฑ ) ํ ํ ์์ฑ๋ ModelView๋ฅผ ๋ฆฌํด
์ฆ ์ด๋ํฐ์์ ํธ๋ค๋ฌ(์ปจํธ๋กค๋ฌ)๊ฐ ํธ์ถ๋๊ณ ModelView๋ฅผ ๋ฆฌํดํฉ๋๋ค.
๋ค์์ ControllerV4 ์ด๋ํฐ์ ๋๋ค.
package hello.servlet.web.frontcontroller.v5.adapter;
import hello.servlet.web.frontcontroller.ModelView;
import hello.servlet.web.frontcontroller.MyView;
import hello.servlet.web.frontcontroller.v3.ControllerV3;
import hello.servlet.web.frontcontroller.v4.ControllerV4;
import hello.servlet.web.frontcontroller.v5.MyHandlerAdapter;
import org.springframework.ui.Model;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class ControllerV4HandlerAdapter implements MyHandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof ControllerV4);
}
@Override
public ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
ControllerV4 controller = (ControllerV4) handler;
Map<String,String> paramMap = createParamMap(request);
Map<String,Object> model = new HashMap<>();
String viewName = controller.process(paramMap, model);
ModelView mv = new ModelView(viewName);
mv.setModel(model);
return mv;
}
private Map<String, String> createParamMap(HttpServletRequest request) {
Map<String,String> paramMap = new HashMap<>();
request.getParameterNames().asIterator()
.forEachRemaining(paramName -> paramMap.put(paramName, request.getParameter(paramName)));
return paramMap;
}
private String viewResolver(String viewName) {
return "/WEB-INF/views/" + viewName + ".jsp";
}
}
- supports : ์ด ํธ๋ค๋ฌ(์ปจํธ๋กค๋ฌ)๊ฐ ControllerV3์ ์ธ์คํด์ค์ธ์ง์ ๋ํ ์ฌ๋ถ ๋ฆฌํด
- handle : ControllerV4์์๋ model๊ณผ paramMap์ process์ ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ์ฃผ๊ณ viewName์ ๋ฆฌํด๋ฐ๊ธฐ ๋๋ฌธ์ ์์ ๊ฐ์ด ๊ตฌํ ํ์ต๋๋ค. viewName์ ์ฃผ์ ๋ฐ์ ModelView์ ๋ฆฌํดํ๊ณ process๋ฅผ ํตํด ์ ๋ฐ์ดํธ๋ model์ setํด์ค ModelView๋ฅผ ๋ฆฌํดํฉ๋๋ค.
3. ์์ฒญ URI์ ๋ง๋ ํธ๋ค๋ฌ(์ปจํธ๋กค๋ฌ)์ ์ด๋ํฐ ๊ฐ์ ธ์ค๊ธฐ
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object handler = getHandler(request);
if(handler==null)
{
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
MyHandlerAdapter adapter = getHandlerAdapter(handler);
...
}
private Object getHandler(HttpServletRequest request) {
String requestURI = request.getRequestURI();
Object handler = handlerMappingMap.get(requestURI);
return handler;
}
private MyHandlerAdapter getHandlerAdapter(Object handler)
{
for (MyHandlerAdapter adapter : handlerAdapters) {
if(adapter.supports(handler))
{
return adapter;
}
}
throw new IllegalArgumentException(
"handler adapter๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค." + " handler = " + handler);
}
- getHandler(request) : ์์ฒญ URI๋ฅผ ํตํด ํธ๋ค๋ฌ๋งต์ ๋งคํํ์ฌ ํธ๋ค๋ฌ(์ปจํธ๋กค๋ฌ)๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
- getHandlerAdapter(getHandler๋ฅผ ํตํด ์ป์ handler) : List๋ฅผ iteratorํ๊ฒ ์ดํด๋ณด๊ณ supports ๋ฉ์๋๋ฅผ ์ด์ฉํด ํด๋น ํธ๋ค๋ฌ์ ํธํ๋๋ ์ด๋ํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
ModelView๋ฅผ ๋ฆฌํด๋ฐ์ ํ์ Front-Controller Logic
package hello.servlet.web.frontcontroller.v5;
import hello.servlet.web.frontcontroller.ModelView;
import hello.servlet.web.frontcontroller.MyView;
import hello.servlet.web.frontcontroller.v3.controller.MemberFormControllerV3;
import hello.servlet.web.frontcontroller.v3.controller.MemberListControllerV3;
import hello.servlet.web.frontcontroller.v3.controller.MemberSaveControllerV3;
import hello.servlet.web.frontcontroller.v4.controller.MemberFormControllerV4;
import hello.servlet.web.frontcontroller.v4.controller.MemberListControllerV4;
import hello.servlet.web.frontcontroller.v4.controller.MemberSaveControllerV4;
import hello.servlet.web.frontcontroller.v5.adapter.ControllerV3HandlerAdapter;
import hello.servlet.web.frontcontroller.v5.adapter.ControllerV4HandlerAdapter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@WebServlet(name = "frontControllerServletV5", urlPatterns = "/front-controller/v5/*")
public class FrontControllerServletV5 extends HttpServlet {
private final Map<String, Object> handlerMappingMap = new HashMap<>();
private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();
FrontControllerServletV5()
{
initHandlerMappingMap();
initHandlerAdapters();
}
private void initHandlerAdapters()
{
handlerAdapters.add(new ControllerV3HandlerAdapter());
handlerAdapters.add(new ControllerV4HandlerAdapter());
}
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());
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
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 viewPath = viewResolver(mv.getViewName());
MyView view = new MyView(viewPath);
view.render(mv.getModel(),request,response);
}
private Object getHandler(HttpServletRequest request) {
String requestURI = request.getRequestURI();
Object handler = handlerMappingMap.get(requestURI);
return handler;
}
private MyHandlerAdapter getHandlerAdapter(Object handler)
{
for (MyHandlerAdapter adapter : handlerAdapters) {
if(adapter.supports(handler))
{
return adapter;
}
}
throw new IllegalArgumentException(
"handler adapter๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค." + " handler = " + handler);
}
private String viewResolver(String viewName) {
return "/WEB-INF/views/" + viewName + ".jsp";
}
}
adapter์ handle์ ํตํด ๋ฆฌํด๋ ModelView์์ viewName(๋ทฐ ๋ ผ๋ฆฌ ์ด๋ฆ)ํ๋๋ฅผ ViewResolver ๋ฉ์๋๋ฅผ ์ฌ์ฉํด ์ค์ viewPath๋ฅผ ๊ฐ์ง๊ณ MyView ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด JSP๋ก forwardํฉ๋๋ค.
<์ ๋ฆฌ>
1. ์ด๋ํฐ๋ฅผ ๋์ ํด์ ํ๋ ์์ํฌ๋ฅผ ํ์ฅ์ฑ์๊ฒ ์ค๊ณ ํด๋ณด์์ต๋๋ค.
2. ๋คํ์ฑ์ ์ด์ฉํ ์ด๋ํฐ ๋๋ถ์ ๊ธฐ์กด ๊ตฌ์กฐ๋ฅผ ์ ์งํ๋ฉด์ ํ๋ ์์ํฌ์ ๊ธฐ๋ฅ์ ํ์ฅํ ์ ์์์ต๋๋ค.
์ฌ๊ธฐ์ ์ด๋ ธํ ์ด์ ์ ์ง์ํ๋ ์ด๋ํฐ๋ฅผ ์ฌ์ฉํด์ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ ํธ๋ฆฌํ๊ฒ ๋ฐ์ ์ํฌ ์๋ ์์ต๋๋ค.
์ด์ ํฌ์คํ ๊ณผ ์ด๋ฒ ํฌ์คํ ์์๋ ์ฌ๋ฌ๊ฐ์ง MVC ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด๋ณด๊ณ ํ์ฅํด๋ณด์์ต๋๋ค.
๋ค์ ํฌ์คํ ์์๋ ์คํ๋ง ๋ถํธ๋ฅผ ์ด์ฉํ MVC ๊ตฌ์กฐ๋ฅผ ์์๋ณด๊ฒ ์ต๋๋ค.
<์ฐธ๊ณ ์๋ฃ>
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
https://chinggin.tistory.com/586
'๐ Backend > MVC Pattern' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ค์ํ ๋ฐฉ์์ HandlerMapping, HandlerAdapter, ViewResolver (0) | 2023.03.03 |
---|---|
Spring MVC ๊ตฌ์กฐ (0) | 2023.03.03 |
Front-Controller ํจํด (0) | 2023.02.27 |
Spring / MVC ํจํด (0) | 2023.02.24 |
Spring / ์์ Servlet ํจํด, JSP ํจํด (0) | 2023.02.23 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
Study Repository
rlaehddnd0422