model1, 2는 기존에 해왔던 실습 예제와 똑같은 방식이다.
간단한 게시판 만들기 코드를
model1으로 시작해서 그 코드를 가지고 model2로 바꿔본 후에 Spring 이 어떤식으로 구동하는지 알기 위하여
필요한 클래스를 직접 만들어서 그 구조를 익혀보자.
먼저 클라이언트가 요청을 하게 되면 그 요청을 DispatcherServlet에서 받게 된다.
DispatcherServlet은 다시 Controller에게 요청을 하는데 이때 HandlerMapping에 클라이언트가 요청을 처리할 Controller를 매핑하고 ViewResolver 클래스를 통하여 JSP경로를 완성시킨다.
DispatcherServlet
@WebServlet(name = "action", urlPatterns = { "/*do" })
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);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
process(request, response);
}
private void process(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 클라이언트 요청 path(경로) 정보 추출
String uri = request.getRequestURI();
String path = uri.substring(uri.lastIndexOf("/"));
// lastIndexOf("/") => 지정한 "/" 중, 맨 마지막 "/" 의 인덱스 부터 맨마지막 까지 값을 꺼냄
//핸들러를 통해 paht에 해당하는 controller 검샥
Controller ctrl = handlerMapping.getController(path);
//검색된 컨트롤러 실행
String viewName = ctrl.handleRequest(request, response);
// 클라이언트 요청 path에 따라 적절히 분기 처리
//viewResolver를 통하여 해당 화면 검색
String view = null;
if (!viewName.contains(".do")) {
view = viewResolver.getView(viewName);
} else {
view = viewName;
}
response.sendRedirect(view);
}
~~Controller 클래스가 생성될 때마다 HandlerMapping에 등록 시켜줘야하며
~~Controller 클래스들은 Controller 인터페이스를 구현 받는다.
Controller 인터페이스
public interface Controller {
String handleRequest(HttpServletRequest request, HttpServletResponse response);
}
경로를 설정하기 위해
ViewResolver 클래스
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;
}
}
최종적인 HandlerMapping 클래스는 이러한 구조가 된다.
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);
}
}
model2에서는 DispatcherServlet 클래스에서
모든 일처리(if(command.equals("login"){ } 이러한 구조)를 했다면
MVC 구조에서는 각각의 컨트롤러에서 해당하는 일들을 처리한다.
ex) 게시글 등록 컨트롤러
public class InsertBoardController implements Controller {
@Override
public String handleRequest(HttpServletRequest request, HttpServletResponse response) {
System.out.println("게시글 등록");
//request.setCharacterEncoding("UTF-8");
String title = request.getParameter("title");
String content = request.getParameter("content");
String writer = request.getParameter("writer");
BoardVO vo = new BoardVO();
vo.setTitle(title);
vo.setWriter(writer);
vo.setContent(content);
BoardDAO dao = new BoardDAO();
int result = dao.insertBoard(vo);
if(result == 1){
return "getBoardList.do";
} else {
return "error";
}
}
}
model2에서는 경로 설정을 위하여 response.redirect를 사용하여 페이지 이동이 이루어졌다면
MVC에서는 ViewResolver 클래스의 값설정과 web.xml에 등록되었있는 Servlet 매핑의 경로
를 통하여 페이지 전환이 이루어지게된다.
web.xml
<servlet>
<description>DispatcherServlet.java</description>
<display-name>action</display-name>
<servlet-name>action</servlet-name>
<servlet-class>com.jdh.spring.view.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
DispathcerServlet -> Controller -> 이때 반환 타입이 String 타입 -> DispathcerServlet
DispathcerServlet에서의 init() 메서드가 실행되어 경로를 완성 시킨다.
MVC 아키텍처 -> Spring이 제공하는 MVC
MVC아키텍처에서는 경로값을 String타입으로 반환받았는데 Spring에서는 ModelAndView를 통하여 반환 받는다.
MVC 아키텍처 구조를 알아보기 위해서 DispathcerServlet 클래시를 직접 만들어서 사용해봤다.
이번에는 Springframework이 제공하는 DispathcerServlet 를 사용한다.
먼저 web.xml 수정이 필요하다.
<filter>
<filter-name>characterEncoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncoding</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/presentation-layer.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
servlet-class의 경로를 스프링경로로 변경!!
WEB-INF 폴더 안에 config폴더를 만든후에 xml파일 추가
이 xml문서에서는 HandlerMapping, controller, ViewResolver을 설정한다.
(기존에 직접 만들어서 사용했던 클래스를 이번엔 spring에서 제공해주는 클래스를 사용한다.)
최종 XML 문서는 이렇게 되어있다.
<!-- HandlerMapping 등록 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/login.do">login</prop>
<prop key="/getBoardList.do">getBoardList</prop>
<prop key="/getBoard.do">getBoard</prop>
<prop key="/insertBoard.do">insertBoard</prop>
<prop key="/upateBoard.do">updateBoard</prop>
<prop key="/deleteBoard.do">deleteBoard</prop>
<prop key="/logout.do">logout</prop>
</props>
</property>
</bean>
<!-- Controller 등록 -->
<bean id="login" class="com.jdh.spring.view.user.LoginController" />
<bean id="getBoardList" class="com.jdh.spring.board.controller.GetBoardListController" />
<bean id="getBoard" class="com.jdh.spring.board.controller.GetBoardController" />
<bean id="insertBoard" class="com.jdh.spring.board.controller.InsertBoardController" />
<bean id="updateBoard" class="com.jdh.spring.board.controller.UpdateBoardController" />
<bean id="deleteBoard" class="com.jdh.spring.board.controller.DeleteBoardController" />
<bean id="logout" class="com.jdh.spring.view.user.LogoutController" />
<!-- ViewResolver 등록 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/board/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
**
HandlerMapping의 property name="mappings" <--- 유일값
HandlerMapping의 prop값은 Controller의 id값과 동일하게 설정
<property name="prefix" value="/WEB-INF/board/"></property>
<property name="suffix" value=".jsp"></property>
ViewResolver에 경로와 확장자를 설정해놨다.
WEB-INF 안에 board 디렉토리 내부의 파일을 실행하게 설정했고,(그러므로 폴더를 만들어줘야한다.)
컨트롤러에서의 경로를 수정해줘야한다.
ex) 게시글 목록불러오기 컨트롤러
import org.springframework.web.servlet.mvc.Controller;
public class GetBoardListController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("게시글 불러오기");
ModelAndView mav = new ModelAndView();
BoardVO vo = new BoardVO();
BoardDAO dao = new BoardDAO();
List<BoardVO> board = dao.getBoardList(vo);
mav.addObject("board",board); // 정보 저장
mav.setViewName("getBoardList"); //view정보 저장
return mav;
}
}
구현 받은 Controller를 보면 스프링이 제공해주는 클래스임을 알 수 있다.
게시글 목록부분에서 페이지 전환에 .jsp가 빠진것을 알 수 있다.
하지만 데이터를 처리하는 다른 클래스의 경우 ex)삭제, 수정 등 의 경우는 경로가 다르게 설정되었다.
ex) 게시글 수정
public class UpdateBoardController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
int seq = Integer.parseInt(request.getParameter("seq"));
String title = request.getParameter("title");
String content = request.getParameter("content");
BoardVO vo = new BoardVO();
vo.setSeq(seq);
vo.setTitle(title);
vo.setContent(content);
BoardDAO dao = new BoardDAO();
dao.updateBoard(vo);
ModelAndView mav = new ModelAndView();
mav.setViewName("redirect:getBoardList.do");
return mav;
}
}
redirect: <- 를 통하여 xml문서에서 설정해놓은 값을 무시하고 현재 컨트롤러에서 설정한 값을 그대로 사용할 수 있다.
만약 redirect: 라는 접두사를 사용하지 않는다면 board/getBoardList.do.jsp라는 url형식으로 넘어가기 때문에 404에러
'Learn > KH정보교육원' 카테고리의 다른 글
[KH정보교육원 당산] 73일 (Spring - 파일업로드, 다국어처리, 데이터 변환) (0) | 2021.06.29 |
---|---|
[KH정보교육원 당산] 72일 ( 어노테이션 방식) (0) | 2021.06.23 |
[KH정보교육원 당산] 70일(Spring - 트랜잭션, Model1 -> model2 -> Spring MVC) (0) | 2021.06.21 |
[KH정보교육원 당산] 68일 (Spring - JDBC / AOP ) (0) | 2021.06.17 |
[KH정보교육원 당산] 연습문제 8(요구사항확인) (0) | 2021.06.17 |