MVC2의 과정을 Spring 스타일로 제작
★동작 순서★
사용자의 요청 --*.do --> DS -> HM -> C호출 -> 경로정보를 반환 -> VR -> 사용자에게 화면을 제공
1. Dispatcher Servlet(DS)
- 기존 FrontController 역할을 하는 서블릿을 Dispatcher Servlet라고 부름
- URL Mapping은 *.do로 생성
- 서블릿 파일 생성과 동시에 web.xml에 매핑이 됨
- web.xml 에서 매핑이 완료되었기 때문에
2. Controller
2-1) interface 생성
- controller 파일들의 메서드를 강제하기 위해서 interface를 생성
- 기존에 Action Forward로 페이지 이동 처리 했던 것과 달리 이제는 경로만 VeiwResolver에 Stirng 값으로 전달
package com.kim.biz.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//기존 Action 역할
public interface Controller {
String handleRequest(HttpServletRequest request, HttpServletResponse response);
// 기존에는 AF execute -> VR 경로만 String으로 전달
}
2-2) 각종 Controller 생성
- 각 기능마다 생성되는 Controller 들은 interface를 implements 함
- ViewResolver에서 처리해주기 때문에 경로인 "login"만 반환
package com.kim.biz.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.kim.biz.member.MemberVO;
import com.kim.biz.member.impl.MemberDAO;
public class LoginController implements Controller {
@Override
public String handleRequest(HttpServletRequest request, HttpServletResponse response) {
String mid=request.getParameter("mid");
String mpw=request.getParameter("mpw");
MemberVO mVO=new MemberVO();
mVO.setMid(mid);
mVO.setMpw(mpw);
MemberDAO mDAO=new MemberDAO();
mVO=mDAO.selectOneMember(mVO);
if(mVO==null) {
return "login"; // VR가 .jsp를 추가하기때문에 생략해서 반환
}
else {
return "main.do";
}
}
}
3. HandlerMapping
- client의 request URL에 매핑되는 Controller를 찾아 DispatcherServelt에 반환 - Mappings에 생성자 주입 - private를 붙여 싱글톤 패턴이 유지되게 하는데 이는 객체의 무분별한 생성으로 인하여 메모리가 낭비되는걸 막기 위함!
싱글톤 패턴이란?
- 클래스의 인스턴스가 1개만 생성되는 것을 보장하는 디자인 패턴
- 2개 이상의 객체가 만들어지지 않게 함!
- 간단하게 생각하면 private를 이용해서 new로 생성하지 못하게 할 수 있음
package com.kim.biz.controller;
import java.util.HashMap;
import java.util.Map;
public class HandlerMapping { // 싱글톤 패턴이 유지됨 -> 객체의 무분별한 생성을 막기위해
//input : 어떤 요청에 대해 == String
//output : 무슨 Controller 객체를 제공해야하는지 == Controller
private Map<String, Controller> mappings; //의존 관계 -> DI => 생성자 주입
public HandlerMapping() {
mappings=new HashMap<String,Controller>();
mappings.put("/login.do", new LoginController());
}
public Controller getController(String command) {
return mappings.get(command);
}
}
4. ViewResolver
- Controller가 반환한 View Name을 기반으로 View Name에 맞는 View를 찾아 Dispatcher Servelt에 리턴
- 어디로 가야하는지 경로를 만들어 줌
package com.kim.biz.controller;
public class ViewResolver {
public String prefix; //의존 관계 -> DI => setter 주입
public String suffix; //의존 관계 -> DI => setter 주입
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public String getView(String viewName) { //경로를 만들어줌
return prefix+viewName+suffix;
}
}
DS를 최종적으로 종합해보자면,
HM, VR 의존 관계로 DI
HM은 생성자 주입-> new
VR은 setter 주입 -> set 해줌
package com.kim.biz.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//의존관계
private HandlerMapping handlerMapping;
private ViewResolver viewResolver;
//init() 통해서 DI
public void init() throws ServletException{
handlerMapping=new HandlerMapping(); //생성자 주입 -> new하면 됨
viewResolver=new ViewResolver(); // setter 주입이기 때문에 => set 해주어야 함
viewResolver.setPrefix("./");
viewResolver.setSuffix(".jsp");
}
public DispatcherServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doAction(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8"); //필터가 없기 때문에 인코딩을 이렇게 해줌
doAction(request,response);
}
private void doAction(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String command=request.getRequestURI();
command=command.substring(command.lastIndexOf("/"));
System.out.println(command);
//HM에서 요청에 맞는 controller를 가져옴
Controller ctrl=handlerMapping.getController(command);
// controller가 로직 수행 하고 경로를 반환
String viewName=ctrl.handleRequest(request, response);
String view=null;
if(viewName.contains(".do")) {
view=viewName;
}else {
view=viewResolver.getView(viewName);
}
response.sendRedirect(view);
}
}
구성요소 | 설명 |
DispatcherServlet | 클라이언트의 요청을 전달받아 요청에 맞는 컨트롤러가 리턴한 결과값을 View에 전달 |
HandlerMapping | 클라이언트의 요청(URL)을 어떤 컨트롤러가 처리할지 결정 |
Controller | 클라이언트의 요청을 처리한 뒤, 결과를 DispatcherServlet에 전달 |
ViewResolver | 컨트롤러의 처리결과를 생성할 뷰 결정 |
Spring MVC2 패턴2 장점
※ 메모리를 불필요하게 사용하던 객체들이 현저히 줄어듦
※ 하드코딩 X (코드의 불필요한 반복패턴이 줄어듦) => 코드가 간결해짐
※ 결합도가 낮아짐 / 응집도가 높아짐
'Spring' 카테고리의 다른 글
[Spring] XML파일 대신 Java 클래스 파일 @로 변경 (0) | 2022.09.22 |
---|---|
[Spring] MVC2 패턴 동작과정2 - Spring framework 클래스 적용 (1) | 2022.09.20 |
[Spring] JDBC Template 사용 (0) | 2022.09.18 |
[Spring] AOP 설정 변환 (xml -> @) (0) | 2022.09.18 |
[Spring] Joinpoint, 바인드 변수 (0) | 2022.09.16 |