day4 class02 어노테이션으로 게시판 프로그램 구현하기
어노테이션 적용 및 컨트롤러 통합
- 어노테이션을 이용하여 간단하게 구현된 컨트롤러를 하나의 파일러 합하여 편하게 관리한다.
1. BoardController
- 기존에 구현했던 나머지 컨트롤러 파일들은 삭제한다.
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 67 68 69 70 71 72 73 74 | package com.springbook.view.board; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.SessionAttributes; import com.springbook.biz.board.BoardVO; import com.springbook.biz.board.impl.BoardDAO; @Controller @SessionAttributes("board") public class BoardController { // 글 등록 @RequestMapping(value="/insertBoard.do") public String insertBoard(BoardVO vo, BoardDAO boardDAO) { // System.out.println("글 등록 처리"); boardDAO.insertBoard(vo); return "getBoardList.do"; } // 글 수정 @RequestMapping("/updateBoard.do") public String updateBoard(@ModelAttribute("board") BoardVO vo, BoardDAO boardDAO) { // System.out.println("글 수정 처리"); System.out.println("번호 : " + vo.getSeq()); System.out.println("제목 : " + vo.getTitle()); System.out.println("작성자 : " + vo.getWriter()); System.out.println("내용 : " + vo.getContent()); System.out.println("등록일 : " + vo.getRegDate()); System.out.println("조회수 : " + vo.getCnt()); boardDAO.updateBoard(vo); return "getBoardList.do"; } // 글 삭제 @RequestMapping("/deleteBoard.do") public String deleteBoard(BoardVO vo, BoardDAO boardDAO) { // System.out.println("글 삭제 처리"); boardDAO.deleteBoard(vo); return "getBoardList.do"; } // 글 상세 조회 @RequestMapping("/getBoard.do") public String getBoard(BoardVO vo, BoardDAO boardDAO, Model model) { // System.out.println("글 상세조회 처리"); model.addAttribute("board", boardDAO.getBoard(vo)); return "getBoard.jsp"; } // 검색 조건 목록 설정 @ModelAttribute("conditionMap") public Map<String, String> searchConditionMap() { Map<String, String> conditionMap = new HashMap<String, String>(); conditionMap.put("제목", "TITLE"); conditionMap.put("내용", "CONTENT"); return conditionMap; } // 글 목록 검색 @RequestMapping("/getBoardList.do") public String getBoardList(BoardVO vo, BoardDAO boardDAO, Model model) { // System.out.println("글 목록 검색 처리"); model.addAttribute("boardList", boardDAO.getBoardList(vo)); // Model 정보 저장 return "getBoardList.jsp"; } } | cs |
1-1. Controller 리턴타입
- 리턴타입은 개발자 마음대로 결정할 수 있지만 대부분 프로젝트는 리턴타입을 통일하며 String을 많이 사용한다.
- ModelAndView 대신 Model을 사용하면 String이 리턴타입이여도 JSP화면에 전달할 데이터를 사용할 수 있다.
1-2. @RequestParam 사용하기
- Command 객체를 이용하면 클라이언트에서 넘겨준 요청 파라미터 정보를 받아낼 수 있다. 하지만 이를 위해서는 반드시 요청 파라미터와 매핑될 변수와 Setter 메소드가 Command 클래스에 선언되어 있어야 한다.
- 그래서 Command 클래스에 없는 파라미터 정보를 추출할 수 있는 @RequestParam을 사용하면 된다.
- 하지만 교재에서는 BoardVO에 변수와 Getter/Setter 메소드를 생성하여 사용했다. (Getter/Setter 단축키 : shift + alt + s)
- 아직 검색 기능도 안된다...
1 2 3 4 5 6 7 8 | @RequestMapping("/getBoardList.do") public String getBoardList(@RequestParam(value="searchCondition", defaultValue="TITLE", required=false) String condition, @RequestParam(value="searchKeyword", defaultValue="", required=false) String keyword, BoardVO vo, BoardDAO boardDAO, Model model) { // System.out.println("글 목록 검색 처리"); model.addAttribute("boardList", boardDAO.getBoardList(vo)); // Model 정보 저장 return "getBoardList.jsp"; } | cs |
1-3. @ModelAttribute 사용하기
- 2-2에서 Command 객체의 이름을 변경할 때 사용하기도 했지만 View(JSP)에서 사용할 데이터를 설정하는 용도로도 사용할 수 있다.
- 클라이언트가 "/getBoardList.do"요청을 하면 searchConditionMap() 메소드 위에 @ModelAttribute가 선언되었으므로 getBoardList() 메소드가 실행되기 전에 먼저 실행된다.
- getBoardList() 메소드가 리턴한 getBoardList.jsp에서는 Model에 저장된 검색 목록(conditionMap)과 글 목록(boardList)을 모두 사용할 수 있다.
- hashmap 특성 상 입력한 것과 출력한 결과의 순서가 다를 수 있다. (그래도 대학 다녔다고 이건 기억이 나네ㅎㅎ 아는게 있긴 했구나아)
1 2 3 4 5 | <select name="searchCondition"> <c:forEach items="${conditionMap }" var="option"> <option value="${option.value }">${option.key }</option> </c:forEach> </select> | cs |
1-4. @SessionAttributes 사용하기
- 수정 작업을 처리할 때 유용하게 사용할 수 있는 어노테이션이다.
- 현재는 글 번호, 제목, 내용만을 수정 요청을 보내지만, 수정 시에 BoardVO에는 작성자를 보내지 않고 update 쿼리문만 작성자까지 포함되는 것으로 변경된다면 작성자는 null로 수정된다.
- 이를 방지하기 위해 @SessionAttributes를 사용한다.
- 사용자가 상세 화면을 요청하면 getBoard()메소드는 검색 결과인 BoardVO 객체를 board라는 이름으로 Model에 저장한다. 그리고 @SessionAttributes는 Model에 "board"라는 이름으로 저장되는 데이터가 있다면 그 데이터를 세션(HttpSession)에도 자동으로 저장하라는 설정이다.
- 따라서 getBoard) 메소드가 실행되어 상세 화면이 출력되면 일차적으로 Model에 board라는 이름으로 BoardVO 객체가 저장되고, 세션에도 board라는 이름으로 BoardVO 객체가 저장된다. 이 객체에는 상세 화면에 출력된 모든 정보(번호, 제목, 작성자, 내용, 등록일자, 조회수)가 저장되어 있다.
2. LoginController
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 | package com.springbook.view.user; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.springbook.biz.user.UserVO; import com.springbook.biz.user.impl.UserDAO; @Controller public class LoginController { @RequestMapping(value="/login.do", method=RequestMethod.GET) public String loginView(UserVO vo) { System.out.println("로그인 화면으로 이동"); vo.setId("test"); vo.setPassword("test123"); return "login.jsp"; } @RequestMapping(value="/login.do", method=RequestMethod.POST) public String login(UserVO vo, UserDAO userDAO, HttpSession session) { System.out.println("로그인 처리..."); UserVO user = userDAO.getUser(vo); if(userDAO.getUser(vo) != null) { session.setAttribute("userName", user.getName()); return "redirect:getBoardList.do"; } else { return "login.jsp"; } } } | cs |
2-1. method 속성
- @RequestMapping을 이용하면 Servlet처럼 클라이언트의 요청 방식(GET/POST)에 따라 수행될 메소드를 설정할 수 있다.
- loginView()메소드의 매개변수 UserVO 객체와 같은 Command 객체에 적절한 데이터를 설정하면 리던된 JSP 파일에서 이 데이터를 사용할 수 있다.
- 클라이언트가 직접 URL을 입력하거나 하이퍼링크를 클릭하여 요청하면 기본이 GET방식이다. 로그인 링크를 클릭하면 "login.do"가 요청된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <tr> <td bgcolor="orange">아이디</td> <td><input type="text" name="id" value="${userVO.id }"/></td> </tr> <tr> <td bgcolor="orange">비밀번호</td> <td><input type="password" name="password" value="${userVO.password }"/></td> </tr> <tr> <td colspan="2" align="center"> <input type="submit" value="로그인"/> </td> </tr> | cs |
2-2. @ModelAttribute 사용
- 스프링 컨테이너가 생성하는 Command 객체의 이름은 클래스 이름의 첫 글자를 소문자로 변경한 이름이 자동으로 설정된다. 따라서 login.jsp에서 userVO로 접근이 가능했다.
LoginController |
|
|||
login.jsp |
|
2-3. Servlet API 사용
- 스프링 MVC에서는 컨트롤러 메소드 매개변수로 다양한 Servlet API를 사용할 수 있도록 지원한다.
1 2 | <h1>글 목록</h1> <h3>${userName } 님 환엽합니다...<a href="logout.do">Log-out</a></h3> | cs |