본문 바로가기
Programming/Spring

Spring MVC (annotation 기반)

by TinKerBellBass 2017. 8. 8.
728x90
반응형
참고 도서
스프링 퀵 스타트
국내도서
저자 : 채규태
출판 : 루비페이퍼 2016.06.30
상세보기



1. Controller 클래스의 bean 객체 자동 생성 설정

1
2
3
4
5
6
<!-- controller 가 모여 있는 패키지, com.neverland.view -->
<!-- HandlerMapping, Controller, ViewResolver 정의한 XML 파일에 설정
<!-- DispatchetServlet 객체가 생성되면 XmlWebApplicationContext 가 호출하는 XML -->
<!-- bean 객체 생성을 위한 context:component-scan 설정, 네임스페이스 context 추가 -->
<!-- 호출되면 com.neverland.view 패키지 안의 @Controller 클래스의 객체 생성 -->
<context:component-scan base-package="com.neverland.view">
</context:component-scan>
cs


2. XML 기반을 Annotation 기반으로 변경해 나가기 

(1) @Controller 와 @RequestMapping

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
// XML 기반
package com.neverland.view.board;
// 스프링의 Controller 인터페이스 구현, handleRequest() 메소드 재정의
// HandlerMapping, Controller, ViewResolver 는 XML에 설정
public class GetBoardListController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response){
        BoardVO vo = new BoardVO();
        BoardDAO = new BoardDAO();
        List<BoardVO> boardList = boardDAO.getBoardList(vo);
 
        ModelAndView mav = new ModelAndView();
        mav.addObject("boardList", boardList);
        mav.setViewName("getBoardList.jsp");
        return mav;        
    }
}
 
 
// annotation 기반 
// 클라이언트 요청이 들어오면 bean 객체 자동 생성, XML의 Controller bean 객체 생성 기능
@Controller
public class GetBoardListController{
    // 클라이언트의 요청이 /getBoardList.do 로 매칭되면 메소드 실행, XML의 HandlerMapping 기능
    // handleRequest() 메소드 재정의 불필요 -> getBoardList() 로 메소드 명 
    @RequestMapping("/getBoardList.do")        
    public ModelAndView getBoardList(HttpServletRequest request, HttpServletResponse response){
        BoardVO vo = new BoardVO();
        BoardDAO = new BoardDAO();
        List<BoardVO> boardList = boardDAO.getBoardList(vo);
        ModelAndView mav = new ModelAndView();
        mav.addObject("boardList", boardList); // Model 정보 저장 
        mav.setViewName("getBoardList.jsp"); // View 정보 저장 
        return mav;        
    }
}
cs

(2) Command 객체와 @RequestMapping 메소드의 매개변수

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
/*
(1)
@RequestMapping("/getBoardList.do")
public ModelAndView getBoardList(BoardVO){
}
클라이언트의 요청이 발생하면 DispatcherServlet 이 생성되고,
스프링 컨테이너는 XmlWebApplicationContext 객체가 
호출하는 XML의 component-scan에 설정된 패키지에서
@Controller 클래스를 찾고 @RequestMapping 으로 요청을 매칭
이 때 매칭되는 클래스의 매개변수(BoardVO)를 
스프링 컨테이너는 생성하여 전달
 
(2)
Command 객체 - HTTP 요청 파라미터를 값을 전달 받을 때 사용되는 객체
ex)
HTTP에서 클라이언트 요청 발생
서블릿 컨테이너는 HttpServletRequest 객체를 생성하고,
클라이언트 요청 정보를 추출해서 HttpServletRequest 객체에 담아서 service()메소드 호출

POST 방식의 경우라면, 
HTTP 바디에 title=값&content=값 으로 매핑된 값이 HttpServletRequest에 담김
(참고: GET 방식의 경우는 HTTP 바디가 생성되지 않고, HTTP 헤더의 URL 정보 뒤에
URL?title=값&content=값 (스트링 쿼리)으로 매핑된다)
<input type="text" name="title">
<input type="text" name="content">

스프링 컨테이너는 HttpServletRequest 객체에 담긴 요청 파라미터를 커맨드 객체에 세팅
커맨드 객체를 생성하는 클래스에는 
반드시 HTTP에서 넘어오는 name 값이 setter로 설정되어 있어야 함
public class BoardVO{
    private String title;
    private String content;
    public void setTitle(String title){
        this.title = title;
    }
    public void setContent(String content){
        this.content = content;
    }
}

즉 스프링 컨테이너는 
request.getParameter("title") 값을 setTitle() 메소드의 매개변수로, 
request.getParameter("content") 값을 setContent() 메소드의 매개변수로 넣어서
객체에 HTTP 요청 파라미터를 세팅하고 BoardVO 객체(커맨드 객체) 생성
(1)(2) 두 과정에 의해 요청을 처리하기 위해 매칭된 
@Controller 클래스의 @RequestMapping 메소드의 매개변수로 설정된
BoardVO 객체는 스프링 컨테이너에 의해 생성되고, 
HTTP 요청 파라미터가 세팅되어 메소드로 들어온다 
=> Command 객체의 핵심 기능, HttpServletRequest 대신 HTTP 요청 파라미터 처리
*/
 

@Controller
public class GetBoardListController{
    // BoardDAO, ModelAndView 는 커맨드 객체는 아니지만, 
    // @RequestMapping 메소드의 매개변수로 설정되어 있으므로
    // 메소드가 실행 될 때 스프링 컨테이너에 의해 객체가 생성
    @RequestMapping("/getBoardList.do")            
    public ModelAndView getBoardList(BoardVO, BoardDAO, ModelAndView mav){
        mav.addObject("boardList", boardDAO.getBoardList(vo)); // Model 정보 저장
        mav.setViewName("getBoardList.jsp"); // View 정보 저장
        return mav;        
    }
}
cs

(3) @RequestMapping 메소드의 반환 타입


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
// 반환 타입을 String 으로 하여, View 이름만 문자열로 리턴
// ModelAndView 객체 대신 Model 객체를 매개변수로 넣어 Model 정보 저장
// Model 정보가 필요없이 View 정보만 필요한 요청 처리가 있을 수 있어서 String으로 통일
@Controller
public class GetBoardListController{
    
    @RequestMapping("/getBoardList.do")            
    public String getBoardList(BoardVO, BoardDAO, Model model){
        // Model 정보 저장
        model.setAttribute("boardList", boardDAO.getBoardList(vo));         
        return "getBoardList.jsp"// View 이름 리턴        
    }
}
 
/*
forwarding 과 redirect 
return "getBoardList.jsp" 로 반환하면 기본적으로 포워딩 방식으로 처리
포워딩 방식은 URL 변경 없음
예를 들어 insertBoard.do 요청을 받아 요청이 처리되고 
getBoardList.jsp 로 포워딩 되면 URL이 그대로 inserBoard.do 로 변경 없음
포워딩 방식은 요청이 클라이언트로 넘어가지 않고 
다음 URL로 지정된 곳에 그냥 넘어가기만 함, 새로운 요청이 들어오면 URL 변경됨

return "redirect:getBoardList.do" 로 반환하면 리다이렉트 방식으로 처리
URL이 getBoardList.do 로 변경됨
리다이렉트 방식은 요청이 처리되고 난 후,
getBoardList.do 를 요청하라고 클라이언트에 응답함
클라이언트는 응답을 받고 다시 getBoardList.do 를 HTTP에 요청함
*/
cs


(4) 어노테이션 방식의 장점

어노테이션 방식은 코드가 상당히 줄기 때문에, XML 에서 나누어 만들었던 Controller 클래스를 

하나의 클래스로 통합할 수 있음


3. method 속성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 같은 요청에 대해 
// View 화면만 보여줄 때는 GET,
// 요청을 적절히 처리할 때는 POST
 
@Controller
public class LoginController{
 
    @RequestMapping(value="/login.do", method=RequestMethod.GET)
    public String loginView(UserVO vo){
vo.setId("tinkerbell");
        return "login.jsp"
    }
// 응답하는 View 에서 커맨드 객체 사용
// ${userVO.id} 객체 이름 앞 대문자를 소문자로 바꿔서 사용
 
    @RequestMapping(value="/login.do", method=RequestMethod.POST)
    public String login(UserVO vo, UserDAO userDAO){
        if(userDAO.getUser(vo) != nullreturn "getBoardList.do";
        else return "login.jsp";
    }    
}
// GET 요청 방식은 쿼리스트링으로 요청이 넘어오거나, 직접 URL을 입력하여 View 를 실행할 때
// POST 요청 방식은 form 태그 method 가 POST, submit 버튼 클릭을 통해 실행할 때
// 로그인 화면을 보여 줄 때와, 로그인 처리할 때를 구분하여 처리하는 것이 

c


4. Servlet API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 스프링 MVC 는 HttServlerRequest 객체가 제공하는 다양한 메소드를 이용하기 위해
// Servlet API 를 매개변수로 사용할 수 있게 지원
// 대표적으로 HttpSession 객체는 HttpServletRequest 객체를 통해 얻을 수 있음
 
@Controller
public class LoginController{
 
    @RequestMapping(value="/login.do", method=RequestMethod.GET)
    public String loginView(){
        return "login.jsp"
    }
 
    @RequestMapping(value="/login.do", method=RequestMethod.POST)
    public String login(UserVO vo, UserDAO userDAO, HttpSession session){
        UserVO user = userDAO.getUser(vo);
        if(user != null) {
            // 로그인에 성공하면 userName 을 세션에 
            session.setAttribute("userName", user.getName());
            return "getBoardList.do";
        }else return "login.jsp";
    }    
}
cs

 

5. 그 외 어노테이션

(1) @RequestParam 과 @ModelAttribute

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
/*
Command 객체에 없는(setter로 설정되어 있지 않은) 파라미터를 
Controller 클래스에 사용하기 위해
@RequestParam 어노테이션 사용
@RequestParam 은 HTTP 요청 파라미터 정보를 추출
<input name="searchKeyword" type="text"/>
@RequestParam을 사용해 Command 객체에 없는 파라미터인
searchKeyword 요청 파라미터를 추출
*/
 
@Controller
public class BoardController{
    @RequestMapping("/getBoardList.do")
    public String getBoardList(@RequestParam(value="searchKeyword", defaultValue="", required=falseString keyword, BoardDAO boardDAO, Model model){
        System.out.println("검색 단어: " + keyword);
        model.addAttribute("boardList", boardDAO.getBoardList(vo));
        return "getBoardList.jsp";
    }
}
// value - 화면으로부터 전달되는 파라미터 이름
// default - 화면으로부터 전달되는 파라미터 정보가 없을 때 설정되는 기본값
// required - 파라미터의 생략 여부
// 메소드 매개변수가 지저분해서 싫으면 커맨드 객체에 setter 로 설정해도 됨
 
 
 
/* 
@ModelAttribute 어노테이션은 View 에서 사용할 데이터를 설정하기 위해 사용
@ModelAttribute 로 설정된 메소드는 @RequestMapping 로 설정된 메소드보다 먼저 호출
@ModelAttribute 메소드 실행 결과로 리턴된 객체는 자동으로 Model 에 저장
@RequestMapping 메소드 실행 결과로 리턴되는 Model 과 
@ModelAttribute 메소드 실행 결과로 리턴된 Model 은 컬렉션으로 저장됨
*/
 
@Controller
public class BoardController{
    @ModelAttribute("searchKeywordUse")
    public String searchKeyword(){
        String searchKeyword = "냥냥";
        return searchKeyword;
    }
 
    @RequestMapping("/getBoardList.do")
    public String getBoardList(BoardVO vo, BoardDAO boardDAO, Model model){
        model.addAttribute("boardList", boardDAO.getBoardList(vo));
        return "getBoardList.jsp";
    }
}
/* 
"/getBoardList.do" 요청 발생 
-> @ModelAttribute 메소드 실행, Model에 반환 값 저장 
-> @RequestMapping 메소드 실행, Model에 값 저장
최종적으로 Model 에는
searchKeywordUse : String searchKeyword
boardList : boardDAO.getBoardList(vo)
두 값이 컬렉션으로 저장됨
Model에 저장된 이 두 값을 응답하는 View 에서 사용할 수 있다
*/
 
 
// @ModelAttribute 의 또 다른 사용법
// 응답하는 View 에서 사용될 커맨드 객체의 이름 변경
@RequestMapping(value="/login.do", method=RequestMethod.GET)
public String loginView(@ModelAttribute("user") UserVO vo){
    vo.setId("tinkerbell");
}
// 응답하는 View 에서 사용할 때 userVO 가 아니라 user 로 사용
// ${userVO.id} => ${user.id}
cs


(2) @SessionAttribute


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
/*
@SessionAttribute 는 HttpSession 객체에 값을 저장하기 위한 어노테이션
@SessionAttribute("board") 
-> Model 에 "board"라는 이름으로 저장되는 데이터가 있다면,
   그 데이터를 HttpSession 객체에 자동으로 저장
public String updateBoard(@ModelAttribute("board") BoardVO vo){
}
-> updateBoard() 메소드가 호출되면,
스프링 컨테이너는 먼저 @ModelAttribute("board") 설정을 해석하여
세션에 board 라는 이름으로 저장된 데이터가 있으면
해당 객체를 세션에서 꺼내서 매개변수로 선언된 BoardVO 객체에 할당
그리고 클라이언트 요청에서 넘어온 파라미터 값이 있다면,
클라이언트 요청 파라미터 값을 BoardVO 객체에 새롭게 할당
예를 들어, BoardVO 객체가 가지는 값이 title, content, writer 라고 가정 하에
HttpSession 객체에 board 라는 세션 값이 저장되어 있고,
여기에는 BoardVO 객체가 가지는 writer, title 값이 들어 있다.
그럼 먼저 BoardVO 객체에 writer, title 값이 할당된다.
그리고 클라이어트 요청에서 넘어온 파라미터 값이 title, content 라면,
BoardVO 객체에는 새롭게 title, content 값이 할당된다.
사용법: update SQL 사용할 때 null 값을 방지하기 위해 사용
*/
 
// getBoard() 메소드 실행 후 updateBoard() 메소드가 실행된다고 가정
@Controller
@SessionAttribute("board")       // board 이름으로 model 에 저장되는 데이터를 
public class BoardController{    // HttpSession 객체에 저장
    @RequestMapping("/getBoard.do")
    public String getBoard(BoardVO vo, BoardDAO boardDAO, Model model){
        // model 에 board 이름으로 데이터 저장 
        // -> @SessionAttribute에 의해 HttpSession 객체에 저장 됨
        model.addAttribute("board", boardDAO.getBoard(vo));
        return "getBoard.jsp";
    }
 
    // 세션에 board 이름으로 저장된 데이터가 있는지 확인
    // -> 클라이언트 요청 파라미터 값 중 BoardVO 객체에 관련된 값이 있으면 그 값으로 새롭게 할당
    @RequestMapping  
    public String upadateBoard(@ModelAttribute("board") BoardVO vo, BoardDAO boardDAO){
        boardDAO.updateBoard(vo);
        return "getBoardList.do";
    }
}
cs


728x90
반응형

'Programming > Spring' 카테고리의 다른 글

Mybatis  (0) 2017.08.13
Spring Layered Architecture  (0) 2017.08.09
Spring MVC (XML 설정 기반)  (0) 2017.08.08
Spring JDBC (JdbcTemplate class)  (0) 2017.08.05
AOP(Aspect Oriented Programming)  (0) 2017.08.02

댓글