[스프링 MVC 1편] 4 - (4) 프론트 컨트롤러 - v4
* 스프링 입문 = window, 스프링 MVC 1편 = Mac 으로 진행합니다
* 진도 : 섹션4 - (5)
* : 자바 클래스명, : 코드, : 단축키
1. 프론트 컨트롤러_구현 4단계
- ModelView 를 없애보자! Map 으로 별도 설정
1) 인터페이스
[ src - java - hello.servlet - web - frontcontroller .v4 - ControllerV4 ]
public interface ControllerV4 {
String process(Map<String, String> paramMap,Map<String, Object> model);
}
- ModelView없이 진행
- 서블릿과 앞부분 이름 차이
protected void service → String process
- 서블릿과 앞부분 이름 차이
- Map<> paramMap / model 맵 2개 추가
- 프론트 컨트롤러는 이 인터페이스를 호출해서 로직의 일관성을 가져갈 수 있다
인터페이스는 어딘가에 상속 혹은 종속 되어있지 않아서 extend나 implements 사용 X
< 기존의 ControllerV3 인터페이스에서 삭제한 코드 >
- ModelView
public interface ControllerV3 {
ModelView process(Map<String, String> paramMap);
3) 회원 등록
[ src - java - hello .servlet - web - frontcontroller .v4 - controller - MemberFormControllerV4 ]
public class MemberFormControllerV4 implements ControllerV4 {
@Override
public String process(Map<String, String> paramMap, Map<String, Object> model) {
return "new-form";
}
}
- 상속 implements ControllerV4 ~ @Override (option + enter)
- 이제는 HttpServlet Re~ 코드가 아닌 맵이 자동으로 생성이 된다
- 이제는 HttpServlet Re~ 코드가 아닌 맵이 자동으로 생성이 된다
- 뷰 영역 return "// 논리적 이름 //"
- 논리적 이름 = "new-form"
- 논리적 이름 = "new-form"
< 기존의 MemberSaveControllerV3 클래스에서 삭제한 코드 >
- ModelView 부분
public class MemberFormControllerV3 implements ControllerV3 {
@Override
public ModelView process(Map<String, String> paramMap) {
return new ModelView("new-form");
}
}
4) 회원 저장
[ src - java - hello .servlet - web - frontcontroller .v4 - controller - MemberSaveControllerV4 ]
public class MemberSaveControllerV4 implements ControllerV4 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
public String process(Map<String, String> paramMap, Map<String, Object> model) {
String username = paramMap.get("username");
int age = Integer.parseInt(paramMap.get("age"));
Member member = new Member(username, age);
memberRepository.save(member);
model.put("member", member);
return "save-result";
}
}
- 상속 implements ControllerV4 ~ @Override (option + enter)
- 이제는 HttpServlet Re~ 코드가 아닌 맵이 자동으로 생성이 된다
- 이제는 HttpServlet Re~ 코드가 아닌 맵이 자동으로 생성이 된다
- 리포지토리 가져오기 private MemberRepository.getInstance (서블릿 방식 때랑 같음)
- form data 값 읽어오기 paramMap.get() (command + option + v)
( age만 int로 추가 변경 )
- 파라미터에서 값(username, age) 꺼내오기
- 파라미터에서 값(username, age) 꺼내오기
- Member 객체 생성 및 저장 (서블릿 방식 때랑 같음)
- Map model에 값 넣기 model.put("member", member)
- 출력 return "save-result"
< 기존의 MemberSaveControllerV3 클래스에서 삭제한 코드 >
- ModelView 부분
- ModelView mv = new ModelView()
- mv.getModel().put()
- return mv
public class MemberSaveControllerV3 implements ControllerV3 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
public ModelView process(Map<String, String> paramMap) {
String username = paramMap.get("username");
int age = Integer.parseInt(paramMap.get("age"));
Member member = new Member(username, age);
memberRepository.save(member);
ModelView mv = new ModelView("save-result");
mv.getModel().put("member", member);
return mv;
}
}
5) 회원 목록
[ src - java - hello .servlet - web - frontcontroller .v4 - controller - MemberListControllerV4 ]
public class MemberListControllerV4 implements ControllerV4 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
public String process(Map<String, String> paramMap, Map<String, Object> model) {
List<Member> members = memberRepository.findAll();
model.put("members", members);
return "members";
}
}
- 상속 implements ControllerV4 ~ @Override (option + enter)
- 이제는 HttpServlet Re~ 코드가 아닌 맵이 자동으로 생성이 된다
- 이제는 HttpServlet Re~ 코드가 아닌 맵이 자동으로 생성이 된다
- 리포지토리 가져오기private MemberRepository.getInstance(서블릿 방식 때랑 같음)
- 데이터 조회 memberRepository.findAll() (option + command + v) (서블릿 방식 때랑 같음)
- Map model에 값 넣기 model.put("member", member)
- 출력 return "members"
< 기존의 MemberSaveControllerV3 클래스에서 삭제한 코드 >
- ModelView 부분
- ModelView mv = new ModelView()
- mv.getModel().put()
- return mv
public class MemberListControllerV3 implements ControllerV3{
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
public ModelView process(Map<String, String> paramMap) {
List<Member> members = memberRepository.findAll();
ModelView mv = new ModelView("members");
mv.getModel().put("members", members);
return mv;
}
}
5) 프론트 컨트롤러
[ src - java - hello.servlet - web - frontcontroller. v4 - FrontControllerServletV4 ]
@WebServlet(name = "frontControllerServiceV4", urlPatterns = "/front-controller/v4/*")
public class FrontControllerServiceV4 extends HttpServlet {
private Map<String, ControllerV4> controllerMap = new HashMap<>();
public FrontControllerServiceV4() {
controllerMap.put("/front-controller/v4/members/new-form", new MemberFormControllerV4());
controllerMap.put("/front-controller/v4/members/save", new MemberSaveControllerV4());
controllerMap.put("/front-controller/v4/members", new MemberListControllerV4());
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String requestURI = request.getRequestURI();
ControllerV4 controller = controllerMap.get(requestURI);
if(controller==null){
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
Map<String, String> paramMap = createParamMap(request);
Map<String, Object> model = new HashMap<>();
String viewName = controller.process(paramMap, model);
MyView view = viewResolver(viewName);
view.render(model, request, response);
}
private static MyView viewResolver(String viewName) {
return new MyView("/WEB-INF/views/" + viewName + ".jsp");
}
private static 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;
}
}
- 프론트 컨트롤러는 꼭 서블릿으로 작성한다!
1. 상속 extends HttpServlet
2. 서블릿 생성@WebServlet
3. 서비스 생성 protected service
4. 맵 생성 private Map
- key = url, value = ControllerV4
- 매핑 정보 담을 공간 = controllerMap
5. 매핑 정보 public FrontControllerServiceV4()
- command + n 하고 constructor 클릭 → Select None 클릭
- 매핑정보를 담기!
- key 값이 요청되면 value를 실행하게끔 설정
6. URI 주소 가져오기 request.getRequestURI (option + command + v)
7. 맵에서 URI 찾아 컨트롤러 반환 controllerMap.get(requestURI)(option + command + v)
- 예외처리는 404 출력 SC_NOT_FOUND
8. 인터페이스, 회원 등록/저장/목록 컨트롤러에서 사용한 맵 2개 등록
- Map<String, String> paraMap = new HashMap<>()
- Map<String, Object> model = new HashMap<>()
9. 파라미터네임 꺼내기 request.getParameterName
- request.getParameter() : ("파라미터 이름")을 작성하면 값을 꺼낼 수 있다
- asIterator() : iterator 인터페이스형으로 바꿔서 반환
- Iterator.forEachRemaining() : Iterator의 forEachRemaining() 메서드를 사용하여 키-값 쌍을 콘솔에 출력
- paramName -> parammap.put(paramName, request.getParameter(paramName))
- key = paraName, value = request.getParameter(paramName)
★★ 너무 길어서 따로 메서드로 뽑는게 좋다!
Map<String, String> paraMap부터 request.getParameterName 까지 드래그 후
option + command + m하고 createParamMap 입력하기 ★★
10. 파라미터 받기 controller.process(paramMap) (option + command + v)
11. 뷰 설정 (프론트컨트롤러v3 랑 같음)
- new MyView("/WEB-INF/views/" + viewName + ".jsp") (option + command + v) 하고
★★ option + command + m 해서 viewResolver(viewName) 입력하기 ★★- 컨트롤러가 반환한 논리 뷰 이름을 실제 물리 뷰 경로로 변경, 실제 물리 경로가 있는 MyView 객체를 반환
논리 뷰 이름: members
물리 뷰 경로: /WEB-INF/views/members.jsp
- 컨트롤러가 반환한 논리 뷰 이름을 실제 물리 뷰 경로로 변경, 실제 물리 경로가 있는 MyView 객체를 반환
- 렌더 호출 view.render(model, request, respontse)
< 기존의 FrontControllerService3 클래스에서 삭제한 코드 >
@WebServlet(name = "frontControllerServiceV3", urlPatterns = "/front-controller/v3/*")
public class FrontControllerServiceV3 extends HttpServlet {
private Map<String, ControllerV3> controllerMap = new HashMap<>();
public FrontControllerServiceV3() {
controllerMap.put("/front-controller/v3/members/new-form", new MemberFormControllerV3());
controllerMap.put("/front-controller/v3/members/save", new MemberSaveControllerV3());
controllerMap.put("/front-controller/v3/members", new MemberListControllerV3());
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String requestURI = request.getRequestURI();
ControllerV3 controller = controllerMap.get(requestURI);
if(controller==null){
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
Map<String, String> paramMap = createParamMap(request);
ModelView mv = controller.process(paramMap);
String viewName = mv.getViewName();
MyView view = viewResolver(viewName);
view.render(mv.getModel(), request, response);
}
private static MyView viewResolver(String viewName) {
return new MyView("/WEB-INF/views/" + viewName + ".jsp");
}
private static 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;
}
}
[출처] 김영한 강사님 인프런 스프링 mvc1
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의
웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., 원
www.inflearn.com