실습 코드 참조
moonhy7/SpringFramework: Spring Framework 실습 코드 정리 (github.com)
6.1절 Spring MVC 적용 준비 ( _055_BoardWeb_Spring_MVC )
1) Controller 관련 파일 삭제
- Spring MVC를 적용하기에 앞서 직접 개발했던 Controller 관련 파일들은 모두 삭제한다.
- 삭제된 클래스들을 스프링에서 제공하는 클래스로 교체하면서 Spring MVC를 적용할 것이다.
- 첫 번째로 com.springbook.view.controller 패키지를 삭제한다.
2) String타입을 ModelAndView로 변경
- 그 후 기존에 사용하던 모든 Controller 클래스들은 스프링에서 제공하는 Contoller 인터페이스로 구현한다.
- 스프링에서 제공하는 Controller 인터페이스도 우리가 만들었던 Controller와 크게 다르지 않지만 handleRequest() 메소드의 리턴 타입이 String이 아닌 ModelAndView라는 점만 다르다.
6.2절 로그인 기능 구현
1. LoginController 구현
- 기존에 사용하던 LoginController 클래스에서 handleRequest() 메소드의 리턴 타입을 ModelAndView로 수정한다.
- 또한 화면 내비게이션에서 로그인 성공과 실패일 때 각 화면 정보를 ModelAndView 객체에 저장하여 리턴한다.
package com.springbook.view.user;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import com.springbook.biz.user.UserVO;
import com.springbook.biz.user.impl.UserDAO;
//SpringFramework에서 제공하는 Controller, interface의 handleRequest메소드는 리턴 타입 ModelAndView
public class LoginController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
System.out.println("로그인 처리");
//1. 사용자 입력 정보 추출(login.jsp에서 전송한 id, password 받기)
String id = request.getParameter("id");
String password = request.getParameter("password");
//2. DB연동 처리(UserDAO의 메소드 호출)
UserVO vo = new UserVO();
vo.setId(id);
vo.setPassword(password);
UserDAO userDAO = new UserDAO();
UserVO user = userDAO.getUser(vo);
//3. 화면 네비게이션(로그인 후 화면 이동 처리)
//DB 연동 후 리턴받은 데이터와 View를 모두 담을 수 있는 객체
ModelAndView mav = new ModelAndView();
//로그인 성공 시 게시판 목록 조회 화면으로 이동
if(user != null) {
//redirect : viewResolver를 무시하고 바로 리다이렉트
mav.setViewName("redirect:getBoardList.do");
//로그인 실패 시 다시 로그인 화면으로 이동
} else {
mav.setViewName("redirect:login.jsp");
}
return mav;
}
}
2. HandlerMapping 등록
- 작성된 LoginController가 클라이언트의 /login.do 요청에 대해서 동작하게 하려면 스프링 설정 파일인 presentation-layer.xml에 HandlerMapping과 LoginController를 <bean> 등록해야 한다.
- SimpleUrlHandlerMapping 객체는 Setter 인젝션을 통해 Properties 타입의 컬렉션 객체를 의존성 주입하고 있음
- 의존성 주입된 Properties 컬렉션에는 /login.do 경로 요청에 대해 아이디가 login인 객체가 매핑되어 있다.
- LoginController 클래스를 <bean> 등록할 때 반드시 SimpleUrlHandlerMapping에서 /login.do 키 값으로 매핑한 값과 같은 아이디로 등록해야 함
<!-- HandlerMapping 등록 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/login.do">login</prop>
</props>
</property>
</bean>
<!-- Controller 등록 -->
<bean id="login" class="com.springbook.view.user.LoginController"></bean>
6.3절 글 목록 검색 기능 구현
1. GetBoardListController 구현
- 검색 결과를 세션이 아닌 ModelAndView 객체에 저장하고 있다.
- 세션은 클라이언트 부라우저 하나당 하나씩 서버 메모리에 생성되어 서버에 부담을 준다.
- 그래서 검색 결과를 세션이 아닌 HttpServletRequest 객체에 저장하는 것이 낫다.
- 하지만 GetBoardListController는 검색 결과를 HttpSession도 아니고 HttpServletRequest도 아닌 ModelAndView에 저장하고 있다.
- DispatcherServlet은 Controller가 리턴한 ModelAndView 객체에서 Model 정보를 추출한 다음 HttpServletRequest 객체에 검색 결과에 해당하는 Model 정보를 저장하여 JSP로 포워딩함
package com.springbook.view.board;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
public class GetBoardListController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
System.out.println("글 목록 검색 처리");
//1. 사용자 입력정보 추출(검색기능 나중에 구현)
//2. DB 연동 처리(BoardDAO의 메소드 호출)
BoardVO vo = new BoardVO();
BoardDAO boardDAO = new BoardDAO();
List<BoardVO> boardList = boardDAO.getBoardList(vo);
//3. 검색 결과를 세션에 저장하고 목록 화면으로 이동한다.
ModelAndView mav = new ModelAndView();
//ModelAndView 객체에 데이터 담기
mav.addObject("boardList", boardList);
//ModelAndView 객체에 View 담기
mav.setViewName("getBoardList");
return mav;
}
}
2. HandlerMapping 등록
- GetBoardListController 객체가 /getBoardList.do 요청에 동작할 수 있도록 SimpleUrlHandlerMapping에 매핑 정보 추가
3. 게시글 목록 검색 과정
① 클라이언트로부터 /getBoardList.do 요청을 전송하면 DispatcherServlet이 요청을 받고
② SimpleUrlHAndlerMapping을 통해 요청을 처리할 GetBoardListController를 검색한다.
③ DispatcherServlet은 검색된 GetBoardListController를 실행하여 요청을 처리한다.
④ GetBoardListController는 검색 결과인 List<BoardVO>와 getBoardList.jsp 이름을 ModelAndView 객체에 저장하여 리턴한다.
⑤ DispatcherServlet은 ModelAndView로부터 View 정보를 추출하고 ViewResolver를 이용하여 응답으로 사용할 getBoardList.jsp를 검색한다.
⑥ DispatcherServlet은 getBoardList.jsp를 실행하여 글 목록 화면을 전송한다.
6.4절 글 상세 조회 기능 구현
1. GetBoardController 구현
- GetBoardController는 GetBoardListController와 기능이 같다.
- 따라서 검색 결과로 얻어낸 Model과 View 정보를 ModelAndView 객체에 저장하여 리턴하도록 구현한다
package com.springbook.view.board;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
public class GetBoardController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
System.out.println("글 상세 조회 처리");
//1. 상세 조회할 게시글 번호 추출
String seq = request.getParameter("seq");
//2. DB 연동 처리(BoardDAO의 메소드 호출)
BoardVO vo = new BoardVO();
vo.setSeq(Integer.parseInt(seq));
BoardDAO boardDAO = new BoardDAO();
BoardVO board = boardDAO.getBoard(vo);
//3. 검색 결과를 세션에 저장하고 목록 화면으로 이동한다.
ModelAndView mav = new ModelAndView();
mav.addObject("board", board); //Model 정보 저장
mav.setViewName("getBoard"); //View 정보 저장
return mav;
}
}
2. HandlerMapping 등록
- GetBoardController 객체가 /getBoard.do 요청에 동작할 수 있도록 SimpleUrlHAndlerMapping에 매핑 정보를 추가한다.
3. 실행 화면
6.5절 글 등록 기능 구현하기
1. InsertBoardController 구현
- 글 등록 기능을 처리하고 나면 반드시 ModelAndView 객체를 리턴해야 한다.
- 따라서 글 등록 후 글 목록 화면으로 이동하기 위해 ModelAndView 객체에 getBoardList.do를 View 이름으로 설정하고 리턴한다.
- 그리고 사용자가 입력한 한글은 web.xml 파일에 ChararcterEncodingFilter가 등록되었으므로 깨지지 않고 잘 처리된다.
package com.springbook.view.board;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
public class InsertBoardController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
System.out.println("글 등록 처리");
//1. 사용자 입력정보 추출(insertBoard.jsp에서 전송된 정보 추출)
String title = request.getParameter("title");
String writer = request.getParameter("writer");
String content = request.getParameter("content");
//2. DB 연동 처리(BoardDAO의 메소드 호출)
BoardVO vo = new BoardVO();
vo.setTitle(title);
vo.setWriter(writer);
vo.setContent(content);
BoardDAO boardDAO = new BoardDAO();
boardDAO.insertBoard(vo);
//3. 화면 네비게이션
//글 등록 처리 후 글 목록 페이지로 이동
ModelAndView mav = new ModelAndView();
mav.setViewName("redirect:getBoardList.do");
return mav;
}
}
2. HandlerMapping 등록
- InsertBoardController가 /getBoard.do 요청에 동작할 수 있도록 SimpleUrlHAndlerMapping에 매핑 정보를 추가한다.
- 이후에 추가될 글 수정, 글 삭제, 로그아웃 관련 설정도 함께 처리한다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 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="/updateBoard.do">updateBoard</prop>
<prop key="/deleteBoard.do">deleteBoard</prop>
<prop key="/logout.do">logout</prop>
</props>
</property>
</bean>
<!-- Controller 등록 -->
<bean id="login" class="com.springbook.view.user.LoginController"></bean>
<bean id="getBoardList" class="com.springbook.view.board.GetBoardListController"></bean>
<bean id="getBoard" class="com.springbook.view.board.GetBoardController"></bean>
<bean id="insertBoard" class="com.springbook.view.board.InsertBoardController"></bean>
<bean id="updateBoard" class="com.springbook.view.board.UpdateBoardController"></bean>
<bean id="deleteBoard" class="com.springbook.view.board.DeleteBoardController"></bean>
<bean id="logout" class="com.springbook.view.user.LogoutController"></bean>
</beans>
6.6절 글 수정 기능 구현하기
1. UpdateBoardController 구현
package com.springbook.view.board;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
public class UpdateBoardController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
System.out.println("글 수정 처리");
//1. 사용자 입력정보 추출(getBoard.jsp에서 전송된 정보 추출)
String seq = request.getParameter("seq");
String title = request.getParameter("title");
String content = request.getParameter("content");
//2. DB 연동 처리(BoardDAO의 메소드 호출)
BoardVO vo = new BoardVO();
vo.setSeq(Integer.parseInt(seq));
vo.setTitle(title);
vo.setContent(content);
BoardDAO boardDAO = new BoardDAO();
boardDAO.updateBoard(vo);
//3. 화면 네비게이션
//수정처리 후 글 목록 화면으로 이동
ModelAndView mav = new ModelAndView();
mav.setViewName("redirect:getBoardList.do");
return mav;
}
}
6.7절 글 삭제 기능 구현하기
1. DeleteBoardController 구현
package com.springbook.view.board;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
public class DeleteBoardController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
System.out.println("글 삭제 처리");
//1.사용자 입력정보 추출(getBoard.jsp에서 전송된 정보 추출)
String seq = request.getParameter("seq");
//2. DB 연동 처리(BoardDAO의 메소드 호출)
BoardVO vo = new BoardVO();
vo.setSeq(Integer.parseInt(seq));
BoardDAO boardDAO = new BoardDAO();
boardDAO.deleteBoard(vo);
//3. 화면 네비게이션
//글 삭제 처리 후 글 목록 화면으로 이동
ModelAndView mav = new ModelAndView();
mav.setViewName("redirect:getBoardList.do");
return mav;
}
}
6.8절 로그아웃 기능 구현하기
1. LogoutController 구현
package com.springbook.view.user;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class LogoutController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
System.out.println("로그아웃 처리");
//1. 브라우저와 연결된 세션 객체를 강제 종료한다.
HttpSession session = request.getSession();
session.invalidate();
//2. 세션 종료 후, 로그인 화면으로 이동
ModelAndView mav = new ModelAndView();
mav.setViewName("redirect:login.jsp");
return mav;
}
}
6.9절 ViewResolver 활용하기
1. ViewResolver 적용하는 이유
- ViewResolver는 아직 스프링 설정 파일에 적용하지 않은 요소이다.
- ViewResolver를 이용하면 클라이언트로부터의 직접적인 JSP 호출을 차단할 수 있어 대부분의 웹 프로젝트에서 ViewResolver 사용은 거의 필수이다.
- ViewResolver는 JSP를 View로 사용하는 경우에는 InternalResourceViewResolver를 사용한다.
- getBoardList.jsp 파일을 브라우저에서 직접 호출하면 아래와 같이 아무 데이터도 출력되지 않는다.
- 게시글 목록을 검색하는 GetBoardListController가 실행되지 않았기 때문이다.
- GetBoardListController부터 실행될 수 있도록 적절히 제어하는 역할을 ViewResolver가 해준다.
2. ViewResolver 적용하기
- WEB-INF 폴더는 절대 브라우저에서 접근할 수 없으므로 WEB-INF 폴더로 이동한 JSP 파일들은 절대 클라이언트 브라우저에서 접근할 수 없다.
- 하지만 InternalResourceViewResolver를 아래와 같이 설정하면 WEB-INF 폴더에 있는 JSP 파일을 View 화면으로 사용할 수 있음
- 결과적으로 직접적인 JSP 호출을 차단하게 된다.
<!-- 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>
3. Controller 수정
1) LoginController
- ViewResolver를 적용했을 때 ModelAndView 객체에 저장되는 View 이름은 ViewResolver 설정을 고려하여 등록한다.
- 로그인에 성공하거나 실패했을 떄 View 이름 앞에 redirect:을 붙여서 ViewResolver가 설정되더라도 이를 무시하고 리다이렉트하도록 한다.
//3. 화면 네비게이션(로그인 후 화면 이동 처리)
//DB 연동 후 리턴받은 데이터와 View를 모두 담을 수 있는 객체
ModelAndView mav = new ModelAndView();
//로그인 성공 시 게시판 목록 조회 화면으로 이동
if(user != null) {
//redirect : viewResolver를 무시하고 바로 리다이렉트
mav.setViewName("redirect:getBoardList.do");
//로그인 실패 시 다시 로그인 화면으로 이동
} else {
mav.setViewName("redirect:login.jsp");
}
return mav;
}
}
2) GetBoardListController
- GetBoardListController에서 확장자 .jsp를 생략하여 접두사와 접미사를 할당하여 파일을 실행한다.
//3. 검색 결과를 세션에 저장하고 목록 화면으로 이동한다.
ModelAndView mav = new ModelAndView();
//ModelAndView 객체에 데이터 담기
mav.addObject("boardList", boardList);
//ModelAndView 객체에 View 담기
mav.setViewName("getBoardList");
return mav;
3) 그 외 컨트롤러들
- Insert, Update, Delete 컨트롤러 클래스에 모두 redirect:getBoard.do를 View 이름으로 설정한다.
//3. 화면 네비게이션
ModelAndView mav = new ModelAndView();
mav.setViewName("redirect:getBoardList.do");
return mav;
4) LogoutController
- 로그아웃 처리 후 로그인 화면으로 이동할 수 있도록 login.jsp 화면으로 넘긴다.
//2. 세션 종료 후, 로그인 화면으로 이동
ModelAndView mav = new ModelAndView();
mav.setViewName("redirect:login.jsp");
return mav;
댓글