spring

day4 class02 어노테이션으로 게시판 프로그램 구현하기

일상다반ㅅㅏ 2019. 2. 9. 21:50

어노테이션 적용 및 컨트롤러 통합

- 어노테이션을 이용하여 간단하게 구현된 컨트롤러를 하나의 파일러 합하여 편하게 관리한다.


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<StringString> searchConditionMap() {
        Map<StringString> conditionMap = new HashMap<StringString>();
        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=falseString condition,
                            @RequestParam(value="searchKeyword", defaultValue="", required=falseString 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

 

1
2
3
4
5
6
7
@RequestMapping(value="/login.do", method=RequestMethod.GET)
public String loginView(@ModelAttribute("user") UserVO vo) {
    System.out.println("로그인 화면으로 이동");
    vo.setId("test");
    vo.setPassword("test123");
    return "login.jsp";
}
cs

 login.jsp

 

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="${user.id }"/></td>
</tr>
<tr>
    <td bgcolor="orange">비밀번호</td>
    <td><input type="password" name="password" value="${user.password }"/></td>
</tr>
<tr>
    <td colspan="2" align="center">
        <input type="submit" value="로그인"/>
    </td>
</tr>
cs


2-3. Servlet API 사용

- 스프링 MVC에서는 컨트롤러 메소드 매개변수로 다양한 Servlet API를 사용할 수 있도록 지원한다.

1
2
<h1>글 목록</h1>
<h3>${userName } 님 환엽합니다...<a href="logout.do">Log-out</a></h3>
cs