-
ModelAndViewJAVA 2021. 7. 25. 14:37
DispatcherServlet
Spring 에서는 FrontController 를 DispatcherServlet 이라는 클래스로 정의해놓았다.
dispatcher : 배달 보내는 사람, 운행 관리원Servlet 처음 할 때 사용한 MVC 모델 순서
1. 요청이 옴 2. FrontContoller 가 먼저 요청을 받는다. 3. 요청사항(요청명) 에 따라 control 을 짝 지어 요청(request)을 넘긴다. (control 의 메서드에 매개변수로 넘긴다.)
(control 들이 공통 구현한 인터페이스 하나로 다향성을 이용하자)4. 짝 지어진 control 이 요청에 맞는 업무 즉, model 을 사용한다.(등록폼관련 control은 model 사용안할 수도 있다.)
그리고 매개변수로 받은 요청에 값을 저장해준다.
또한 이 작업한 model 값이 나타날 view 를 지정해 FrontController 에 return 한다.5. model 값은 request 로 저장했고, view 이름도 받은 FrontController 가 해당 view 로 forward 한다. 6. view 에서 값을 받아 인터페이스(화면)를 구현한다. 7. view 에서 다른 view 로(등록폼도 포함) 가는 경우에도 control을 거쳐야 하므로 다시 1번부터 반복한다. 위의 문제점은 FrontController 가 control 들에게 request를 통째로 준다는 점이다.
필요한 control 도 있겠지만 필요한 값이 몇개 정해진 control 들도 있는데 정보를 통째로 주면
데이터를 잘못 건드리거나, request, response 의 이해도가 낮은 사람들에게 어려움을 준다.
Spring 에서 사용할 MVC 모델
1. ModelAndView
전제사항: ModelAndView 라는 클래스를 만든다.
역할은 데이터를 전송시킬 수 있는 리턴 타입 자리를 맡는다.
ModelAndView 클래스
멤버변수 : viewName, HashMap<String, Object>
메서드 : setViewName(), getViewName(), addObject(key, value)2. 진행 순서
1. 요청이 옴 2. FrontController 가 먼저 요청을 받는다. 3. 요청사항(요청명) 에 따라 control 을 짝 지어 요청(request)을 넘긴다. (control 의 메서드에 매개변수로 넘긴다.)
(control 들이 공통 구현한 인터페이스 하나로 다향성을 이용하자)4. control 인 메서드의 반환값은 ModelAndView 클래스로,
객체 생성한 후 위에 정리한 메서드를 사용하여 멤버변수에 값을 저장하고 리턴한다.5. FrontController 에 반환된 ModelAndView 클래스로 저장한 viewName 을 꺼내고 map 을 EntrySet(위 EntrySet 참고) 으로 만들어
값을 request 에게 set시킨다.6. 반환된 viewName 을 이용해 view로 request 를 forward 시킨다. 7. view 에서 값을 받아 인터페이스(화면)를 구현한다. 8. view 에서 다른 view 로(등록폼도 포함) 가는 경우에도 control을 거쳐야 하므로 다시 1번부터 반복한다.
MVC 실습 (직접 ModelAndView 만들어보기)
>> ModelAndView.java
public class ModelAndView { // 같은 패키지안의 controller 들이 사용하기 때문에 get 없이 바로 멤버변수로 참고하자. String viewName = null; // 마찬가지로 직접 멤버변수를 참고하여 entry - Set을 만들 것이다. HashMap<String, Object> model = new HashMap<String, Object>(); public void setViewName(String viewName) { this.viewName = viewName; } public void addObject(String key , Object val) { model.put(key, val); } }
>> IControl.java (control 들의 다형성을 위한 인터페이스)
public interface IControl { // view 이름 요청처리 // 입력: 일단 넓게 일반적으로 요청객체로 대신 ModelAndView process(HttpServletRequest request, HttpServletResponse response); }
>> 게시물등록준비.java
public class 게시물등록준비 implements IControl{ public ModelAndView process(HttpServletRequest request, HttpServletResponse response) { // 요청 // 업무 // 경로 지정 ModelAndView mv = new ModelAndView(); mv.setViewName("게시물등록창"); return mv; } }
>> 게시물등록.java (control 임!)
public class 게시물등록 implements IControl { //@Autowired-DI IBoardDAO boardDAO = new BoardDAO(); //@RuquestMapping("add_board") 스프링. 아래처럼 가능해진다. // public ModelAndView process(String 제목, String 내용){} public ModelAndView process(HttpServletRequest request, HttpServletResponse response) { // 요청 String 제목 = request.getParameter("title"); String 내용 = request.getParameter("contents"); Board board = new Board(); board.setTitle(제목); board.setContents(내용); ModelAndView mv = new ModelAndView(); // 업무 HttpSession session = request.getSession(false);//없으면 null 값을 준다. boolean 로그인 = true; if (!(session != null && session.getAttribute("no") != null)) { 로그인 = false; //test - 추후 삭제 session = request.getSession(); session.setAttribute("no", 1); 로그인 = true; }; if(!로그인) { mv.setViewName("forward:/로그인준비"); mv.addObject("msg", "로그인 후 세개시물 작성 가능합니다."); return mv; } int 로그인한회원번호 = (Integer)session.getAttribute("no"); Member 작성한회원 = new Member(); 작성한회원.setNo(로그인한회원번호); board.setWriter(작성한회원); boardDAO.save(board); // 경로지정 mv.addObject("board", board); mv.setViewName("게시물등록결과통보"); return mv; } }
>> ControlProvider.java ( control 을 FrontController 에서 생성하지 않고 이 클래스를 통해 얻어낸다.)
1. 요청명을 key 로 , 요청명의 Control 을 value 로 HashMap 을 만든다. (생성시 별도의 메서드 사용없이 들어가 있도록 생성자에 넣기)
2. 해당 HashMap 을 요청명 (key) 값으로 Control 을 얻는 getControl(String work) 메서드를 만든다.
3. getControl() 메서드를 객체 생성 후 써야하면 복잡하니까(생성자에 put되있으니 static선언해서 사용하면 값이 없다.)
이 클래스를 static 멤버변수로 만들어 객체를 생성하고 이 객체를 꺼낼 static 메서드를 만든다.
class BasicControlProvider { HashMap<String, IControl> controls = new HashMap<String, IControl>(); BasicControlProvider(){ controls.put("prepare_board", new 게시물등록준비()); controls.put("add_board", new 게시물등록()); } public IControl getControl(String work) { return controls.get(work); } } public class ControlProvider { static BasicControlProvider controlProvider = new BasicControlProvider(); public static BasicControlProvider getControlProvider() { return controlProvider; } }
>> FrontController.java
//FrontController @WebServlet("/") // 이 웹서버에 아무거나 요청해도 이 Servlet 이 반환. public class ForntController extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 요청과 컨트롤 객체 매핑 String 요청작업 = request.getRequestURI().substring("/AboutSerlvet/".length()); IControl control = ControlProvider.getControlProvider().getControl(요청작업); // 해당 컨르롤 요청처리 ModelAndView 모델과지정된뷰명 = control.process(request,response); Set<Entry<String, Object>> entry들 = 모델과지정된뷰명.model.entrySet(); for (Entry<String, Object> entry : entry들) { request.setAttribute(entry.getKey(), entry.getValue()); } // forward RequestDispatcher rd = request.getRequestDispatcher(ViewResolver.getJspViewName(모델과지정된뷰명.viewName)); rd.forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
'JAVA' 카테고리의 다른 글
JSP: FrontController 직접 구현해보기 (0) 2021.07.26 이미지업로드: inputStream,outputStream, cos.jar-MultipartRequest (0) 2021.07.25 MVC 3 Tier,인터페이스정의서,AJAX-JSON사용,BLOB(image) (0) 2021.07.25 Servlet, 과도기 MVC (0) 2021.07.25 MVC모델2, JSTL (0) 2021.07.25