티스토리 뷰

spring

day3 class04 MVC 프레임워크 개발

일상다반ㅅㅏ 2019. 1. 27. 17:28

이전까진 DispatcherServlet클래스 하나로 Controller 기능을 구현했다. 하지만 이렇게 하나의 서블릿으로 컨트롤러를 구현하면 개발과 유지보수가 어려워진다.


1. MVC 프레임워크 구조


클래스 

기능 

 DispatcherServlet

유일한 서블릿 클래스로서 모든 클라이언트의 요청을 가장 먼저 처리하는 Front Controller 

 HandlerMapping 

클라이언트의 요청을 처리할 Controller 매핑 

 Controller 

실질적인 클라이언트의 요청 처리 

 ViewResolver 

Controller가 리턴한 View 이름으로 실행될 JSP 경로 완성 



2. Controller 인터페이스 작성

- 구체적인 컨트롤러 구현에 앞서 모든 컨트롤러를 같은 타입으로 관리하기 위한 인터페이스를 만든다.

1
2
3
4
5
6
7
8
9
package com.springbook.view.controller;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public interface Controller {
 
    String handleRequest(HttpServletRequest request, HttpServletResponse response);
}
cs



3. ViewResolver 클래스 작성

- Controller가 리턴한 View 이름에 접두사와 접미사를 결합하여 최종으로 실행될 View 경로와 파일명을 완성한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.springbook.view.controller;
 
public class ViewResolver {
 
    public String prefix;
    public String suffix;
    
    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }
    
    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
    
    public String getView(String viewName) {
        return prefix + viewName + suffix;
    }
}
cs



4. DispatcherServler 수정

- init() 메소드를 재정의 하여 서블릿 객체가 생성된 후에 멤버변수를 초기화하기 위해 자동으로 실행된다.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.springbook.view.controller;
 
import java.io.IOException;
import java.util.List;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
import com.springbook.biz.user.UserVO;
import com.springbook.biz.user.impl.UserDAO;
 
/**
 * Servlet implementation class DispatcherServlet
 */
public class DispatcherServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private HandlerMapping handlerMapping;
    private ViewResolver viewResolver;
    
    public void init() throws ServletException {
        handlerMapping = new HandlerMapping();
        viewResolver = new ViewResolver();
        viewResolver.setPrefix("./");
        viewResolver.setSuffix(".jsp");
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        process(request, response);
    }
 
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("EUC-KR");
        process(request, response);
    }
 
    private void process(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 1. 클라이언트의 요청 path정보를 추출한다.
        String uri = request.getRequestURI();
        String path = uri.substring(uri.lastIndexOf("/"));
        
        // 2. HandlerMapping을 통해 path에 해당하는 Controller를 검색한다.
        Controller ctrl = handlerMapping.getController(path);
        
        // 3. 검색된 Controller를 실행한다.
        String viewName = ctrl.handleRequest(request, response);
        
        // 4. ViewResolver를 통해 viewName에 해당하는 화면을 검색한다.
        String view = null;
        if(!viewName.contains(".do")) {
            view = viewResolver.getView(viewName);
        } else {
            view = viewName;
        }
        
        // 5. 검색된 화면으로 이동한다.
        response.sendRedirect(view);
    }
}
cs



5. 상세 Controller 구현

- 비즈니스 로직을 수행할 소스를 해당 컨트롤러 클래스에 입력한다.

- 보통의 페이지들은 ViewResolver를 이용하여 나중에 .jsp가 입력된다.

- "*.do"로 리턴하는 것은 리턴 된 후 글 목록을 다시 검색하기 위해 사용한다.

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
32
33
34
35
36
37
38
39
40
41
42
43
public class GetBoardListController implements Controller {
 
    @Override
    public String handleRequest(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("글 목록 검색 처리");
        
        // 1. 사용자 입력 정보 추출(검색 기능은 추후 구현)
        // 2. DB 연동 처리
        BoardVO vo = new BoardVO();
        BoardDAO boardDAO = new BoardDAO();
        List<BoardVO> boardList = boardDAO.getBoardList(vo);
        
        // 3. 응답 화면 구성
        HttpSession session = request.getSession();
        session.setAttribute("boardList", boardList);
        return "getBoardList";
    }
}
 
public class InsertBoardController implements Controller {
 
    @Override
    public String handleRequest(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("글 등록 처리");
        
        // 1. 사용자 입력 정보 추출
        String title = request.getParameter("title");
        String writer = request.getParameter("writer");
        String content = request.getParameter("content");
        
        // 2. DB 연동 처리
        BoardVO vo = new BoardVO();
        vo.setTitle(title);
        vo.setWriter(writer);
        vo.setContent(content);
        
        BoardDAO boardDAO = new BoardDAO();
        boardDAO.insertBoard(vo);
        
        // 3. 화면 네비게이션
        return "getBoardList.do";
    }
}
cs



6. HandlerMapping 클랙스 작성

- 모든 컨트롤러 객체들을 저장하고 있다가, 클라이언트의 요청이 들어오면 요청을 처리할 특정 컨트롤러를 검색하는 기능을 제공한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class HandlerMapping {
 
    private Map<String, Controller> mappings;
    
    public HandlerMapping() {
        mappings = new HashMap<String, Controller>();
        mappings.put("/login.do"new LoginController());
        mappings.put("/getBoardList.do"new GetBoardListController());
        mappings.put("/getBoard.do"new GetBoardController());
        mappings.put("/insertBoard.do"new InsertBoardController());
        mappings.put("/updateBoard.do"new UpdateBoardController());
        mappings.put("/deleteBoard.do"new DeleteBoardController());
        mappings.put("/logout.do"new LogoutController());
    }
    
    public Controller getController(String path) {
        return mappings.get(path);
    }
}
cs