SpringFramework/BASIC

Controller에서 view로 데이터 전송요청 Model / @ModelAttribute/ ModelAndView / redirectAttribute

유혁스쿨 2020. 8. 30. 01:24
728x90
반응형

Controller에서 view로 데이터 전송요청

1. Model 2. @ModelAttribute 3. ModelAndView 4. redirectAttribute  - 

u-it.tistory.com/2

Model

1.Model타입을 메서드의 파라미터로 주입하게 되면 'view'로 전달하는 데이터를 담아서 보낼 수 있습니다.

2.request.setAttribute()와 유사한 역할을 합니다.
3. Http header에 객체를 담아 객체를 통으로 전송시킵니다

ex) 메서드(Model model)

ex) addAttribute()

 

@ModelAttribute

커맨드객체를 통해 파라미터를 객체화하여 통으로 받을때 주로 사용합니다.
이때 객체의 이름을 받을때와 보낼때 각각 다르게 구분지어야할 때 사용합니다.
전달받은 파라미터를 Model에 담아서 화면까지 전달하려 할 때 사용되는 어노테이션입니다.
Http header에 객체를 실어 객체를 통으로 전송시킵니다.
@RequestMapping과 매우 흡사합니다.

ex)@ModelAttribute("받을값") 사용할 변수

 

ModelAndView

페이지와, 데이터를 동시 지정해줍니다.

ModelAndView의 addObject메서드는 Model의 addAttribute와 비슷한기능이지만
단순히 Model의 기능과는 다르게 Object를 key,value로 넘겨줍니다.
ㄴ이때 ?key=value 형식으로 객체를 파라미터로 넘겨줍니다.

파라미터 변수로 넘겨줄때 redirect를 해도 넘어가게되므로 redirect할때 만약 RedirectAttribure의 addFlashAttribute()메서드를 사용하지않고 파라미터를 통해 보내도 상관없다면 이런때에 맞게 유용하게 사용할 수 있습니다.

ex)addObject("변수명","값"); 

ex)setViewName("페이지명");

 

ex) new연산자로 객체를 생성하여 생성자를 통해 한번에 데이터를 담는 방법
ㄴreturn new ModelAndView("페이지명","변수명","값");

ㄴreturn new ModelAndView("페이지명",Map<String,?>)

→ new 객체를 사용할때 전달하려는 데이터가 많다면 Map을 사용합니다.

 

RedirectAttribute

 

addFlashAttribute("변수명","값");
redirect시 값을 변수명에 담아 객체화 한 후에 해당 객체를 서버에 저장후 꺼내서 쓸수있으며 사용후에는 소멸됩니다.
이것은 session과 비슷하지만 범위에대한 차이가 있습니다.
ㄴ 서버저장영역, 사용후유지
https://u-it.tistory.com/22

 

 

컨트롤러는 자기 처리가 다 끝나고 화면으로 가기 전에 사용자의 화면에 데이터를 동적으로 뿌려줄 수 있어야 합니다.

 

예를들어 컨트롤러가 글 목록을 보여주는 처리를 해줘야 합니다.

/list요청에 "글목록을 보여주겠다." 라고 하면 컨트롤러의 매핑메서드에 /list라는 uri를 매핑해놓고

게시글 목록을 select 하는 작업을 할것입니다.

게시글 목록들을 페이징 처리 한다면 제한해서 몇개만 가져오거나 전체글을 불러온다면 select * from board 등으로 resultSet으로 반복문으로 막 읽게됩니다.

읽은 후 list에 담아서 dao가 컨트롤러로 보내줍니다.

그럼 그것을 jsp파일로 보내서 거기서 또 반복문으로 화면에 출력합니다.

이런 처리를 할때 우리가 기존에는 requst나 session이나 application에 setAttribute를 해서

화면쪽으로 보내게 되고 화면쪽 즉, jsp쪽에서는 el표현식으로 키이름을 참조하여 데이터를 받고 처리를 했었습니다.

 

스프링에서도 동일하게 해도 됩니다.

실제로도 세션에 담고 로그인할때도 똑같습니다.

 

 

우리가 스프링에서는 이렇게 순간적으로 request로 담아서 보내는 데이터는 Model 이라는 객체에 담아서 전송합니다

 

Model객체는 HttpServletRequest와 비슷하다고 보셔도 무방합니다.

Model전달자 라고 부르는 애는 '컨트롤러가 모든 백엔드 처리가 끝난 다음 데이터를 들고 돌아왔을 때, 화면으로 가기 전, 그 화면에 보내줄 데이터를 담아줄 수 있는 객체다.' 라고 보시면 될거같습니다.

 

컨트롤러에서 view(화면)로 Response하기 전에 이런 처리들이 들어갑니다.

 

 

Controller패키지에 새로운클래스 ResponseController 라고 만듭니다.

rex-ex01.jsp파일을 만듭니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>Model객체에 대해 알아보기</h2>
	<a href="<c:url value='/test'/>">테스트1 페이지로~</a>
</body>
</html>

 

response폴더를 새로 만들고 res-ex01.jsp파일을 만듭니다.

@Controller("resCon") 
public class ResponseController { 
	
	@GetMapping("/res-ex01")
	public void resEx01() {}
}

 

test.jsp파일을 만듭니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>test.jsp 페이지 입니다.</h2>
	<p> 지정된 별명은 ${nick} 입니다. 그리고 나이는 ${age} 세입니다.</p>
</body>
</html>

 

test.jsp파일을 띄워줄 메서드를 작성합니다.

 

 

 

1. Model객체를 사용하여 화면에 데이터 전송하기.

 

Model model객체를 메서드에 지정해주고 키 값을 담아 addAttribute로 넘깁니다.

@Controller("resCon") 
public class ResponseController { 
	
	@GetMapping("/res-ex01")
	public void resEx01() {}

	@GetMapping("/test")
	public void test(Model model) {
		model.addAttribute("nick","뽀삐"); 
	}    
}

 

<a href="<c:url value='/test' />">테스트1 페이지로~</a>를 누릅니다.

[뷰페이지 출력 확인]

 

이번엔 파라미터에 age파라미터변수에 30을 넣어 주겠습니다.

jsp파일에서 하이퍼링크 주소에 ?age=30를 선언합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>Model객체에 대해 알아보기</h2>
	<a href="<c:url value='/test?age=30' />">테스트1 페이지로~</a>
</body>
</html>

 

get방식으로 넘기는 주소창에 파라미터와 변수가 적용 시킨것 입니다.

 

 

이 파라미터를 test.jsp파일에서 el ${age}을 써서 읽고싶다면 컨트롤러에서 파라미터 값을 읽어들여아합니다.

@Controller("resCon") 
public class ResponseController { 
	
	@GetMapping("/res-ex01")
	public void resEx01() {}

	@GetMapping("/test")
	public void test(Model model, @RequestParam("age") int age) {
		model.addAttribute("nick","뽀삐"); //test.jsp파일에 nick이라는 데이터를 들고갑니다.
		System.out.println(age);
		model.addAttribute("age",age);
	}    
}

혹은

@Controller("resCon") 
public class ResponseController { 
	
	@GetMapping("/res-ex01")
	public void resEx01() {}

	@GetMapping("/test")
	public String test(Model model, @RequestParam("age") int age) {
		model.addAttribute("nick","뽀삐"); //test.jsp파일에 nick이라는 데이터를 들고갑니다.
		System.out.println(age);
		model.addAttribute("age",age);
        	return "/test";
	}    
}

nick이라는 데이터는 String 뽀삐가 담겨있습니다.

jsp단에서는 EL표현식을 사용하여 받습니다 -> ${nick}

 

@RequestParam("age") int age

테스트1 페이지로~ 버튼클릭

[뷰페이지 출력 확인 ]

 

http://localhost:xxxx/'contextPath'/test?age=30

링크에 의해서 30이 파라미터로 전달이 되는것을 주소창을 통해 확인할 수 있습니다.

 

메서드에서는 그 파라미터를 캐치해내 값을 받은다음 Model객체를 통해 키,값 쌍으로 메서드가 요청할 페이지로

넘겨줍니다. 그것을 EL로 ${age}로 받습니다.

 

주소창의 ?age=44 로 입력 변경하면 el로 받은 ${age}값이44로바뀔것입니다.


2. @ModelAttribute를 사용한 화면에 데이터 전송하기

@Controller("resCon") 
public class ResponseController { 
	
	@GetMapping("/res-ex01")
	public void resEx01() {}

	@GetMapping("/test")
	public void test(Model model, @ModelAttribute("age") int age) {
		model.addAttribute("nick","뽀삐"); 
		System.out.println(age);
	}   
}

혹은

@Controller("resCon") 
public class ResponseController { 
	
	@GetMapping("/res-ex01")
	public void resEx01() {}

	@GetMapping("/test")
	public String test(@ModelAttribute("age") int age) {
		model.addAttribute("nick","뽀삐"); 
		System.out.println(age);
        	return "/test";
	}   
}

@ModelAttribute는 @RequestParam + Model.addAttribute가 포함 되 있는것입니다.

@RequestParam을 통해서 "age"라는 파라미터를 읽어들인 후 int age변수에 담고

model.addAttribute("age",age)를 해줍니다. 이때에 넘어갈 Key는 어노테이션의 "" 매개값과 같게 적용됩니다.

value는 변수가 됩니다.

편하게 쓰는 경우는 페이지에서 목록을 가져오기위해 3번 페이지를 눌렀을때

컨트롤러한테 페이지 눌른 현재 정보인 3을 보내줍니다.

그럼 컨트롤러는 그것을 가지고 DB에서 3페이지 게시물들을 가져올 수 있습니다.

좀 더 확실히 얘기하자면 아주 빠른속도로 페이지가 넘어가는 이 때에 파라미터는 서버에 존재하게 됩니다.

그리고 서버에 저장된값을 컨트롤러의 메서드에서 불러오는것이죠.

파라미터로 받아서 바로 모델이 실어보내야할 경우에 사용합니다.


3. ModelAndView객체를 활용한 처리

 

ModelAndView라고하니까 모델과 뷰(화면)를 같이 사용하는거 같습니다.

Model 에도 데이터를 담고싶고 안내할 View페이지도 따로 지정하고 싶을때 씁니다.

이때 ModelAndViewModel에 담은 객체를 주소창의 파라미터에 받아 넘깁니다.

?key=value 이렇게넘겨줍니다!

 

ModelAndView방법을 사용해보도록 하겠습니다.

 

res-ex01.jsp파일에서 하이퍼링크를 하나 더 만듭니다.

<body>
	<h2>Model객체에 대해 알아보기</h2>
	<a href="<c:url value='/test?age=30' />">테스트1 페이지로~</a>
	<a href="<c:url value='/test2' />">테스트2 페이지로~</a>
</body>
</html>

 

 

test2.jsp파일을 만듭니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>test2.jsp페이지 입니다.</h2>
	<p>컨트롤러가 전달한 데이터 : ${userName}</p>
</body>
</html>

 

 

 

ModelAndView 1번째 방식.

@Controller("resCon") 
public class ResponseController { 
	
	@GetMapping("/res-ex01")
	public void resEx01() {}

	@GetMapping("/test2")
	public ModelAndView test2() { 
		ModelAndView mv = new ModelAndView();//1.ModelAndView객체 생성
		mv.addObject("userName","박영희");//박영희"를 userName에 실어보내고 싶습니다.
		mv.setViewName("/test2"); //response폴더안에있는 test2 jsp파일을 보여주고싶다. 
		return mv;
	}  
}

 

void String 그리고 세번째 리턴타입인 ModelAndView가 되겠습니다.

ModelAndView라고하니까 모델과 뷰(화면)를 같이 사용하는거 같습니다.

Model애도 데이터를 담고싶고 안내할 페이지도 따로지정하고싶을때 씁니다.

 

 

ModelAndView 2번째 방식.

@Controller("resCon") 
public class ResponseController { 
	
	@GetMapping("/res-ex01")
	public void resEx01() {}

	@GetMapping("/test2")
	public ModelAndView test2() { 
		ModelAndView mv = new ModelAndView("/test2");
		mv.addObject("userName","박영희");
		return mv;
	}  
}

 

굳이 매개변수에 Model을 받지 않아도, 뷰리졸버 설정을 String으로 하지 않아도 두개를 동시에 처리합니다.

 

이렇게보면 Model과 무슨차이가 있느냐 생각할 수 있지만, 나중에 RestAPI라고 해서 항상 컨트롤러가 실시간으로 페이지가 넘어가면서 작동하지 않고, 비동기로 바로바로 통신 해야 할 수가 있습니다.

이때 String으로 반환하면 뷰리졸브로 반환이 안되는 케이스가 있습니다.

그때 ModelAndView를 사용하게 될겁니다.

 

그리고 앞서말했듯 Model은 key와 value를 객체에 담고 그 객체를 header를 통해 통으로 넘기지만

ModelAndView는 key와 value를 객체에 담고 그 객체를 파라미터로 받아 넘깁니다

 

 

불편하다면 String과 Model, 혹은 @ModelAttribute를 사용하여도 무관하지만 나중에 RestAPI를 사용하여 구축하게 될 때는 이 방식이 다시 나온다는것을 생각하시고 알아만 두시면 됩니다.

 

 

ModelAndView 3번째 방식.

@Controller("resCon") 
public class ResponseController { 
	
	@GetMapping("/res-ex01")
	public void resEx01() {}

	@GetMapping("/test2")
	public ModelAndView test2() {
		ModelAndView mv = new ModelAndView()
		return new ModelAndView("/test2","userName","박영희");
	}  
}

 

첫번째는 viewResolver를 제외한 jsp 파일의 경로와, 두번째는 키, 세번째는 값을 매개값으로 넣어줍니다

담을 데이터가 많으면 Map<String,?>을 사용해서 넣어줍니다.

 

스프링 같은경우엔 담을 데이터가 많으면 두가지 방식이 존재합니다.

 

첫번째방식 : 담을 데이터들 간에 연관관계가 있으면 클래스를 선언하여서 클래스에다 객체로 포장해서 담거나

두번째 방식 : 연관관계가 없으면 데이터간의 상관성이 없으면 맵을 사용합니다. 맵에 키를 부여하여 세팅해서 담습니다.

!!!!주의

ModelAndView의 Model과 비슷한 역할을 해주는 addObject는 Model의 addAttribute와 다릅니다!!!

 

@ModelAttribute에서 Attribute로 값을 담아 전송시켜 주는 기능은 Model의 addAttribute와 같을진 모르지만

ModelAndView의 addObject는 Model의 addAttribute와 비슷한기능을 할뿐 완벽하게 같은 기능이라고 볼수 없습니다.

  메서드 기능정의
Model addAttribute("키","값"); 키 이름에 값을 담아 Attribute로 넘겨줍니다
ModelAndView addObject("키","값"); 키 이름에 값을담아 Object로 넘겨주는데 Object는 물론, 파라미터로 값을 넘겨줄 수 잇습니다.

ModeladdAttribute는 일반적으로 파라미터값으로 넘겨줄 수 없습니다.

하지만 ModelAndView addObject는 포워딩은 물론 놀랍게도, redirect할때도 주소창에 파라미터값으로 넘겨줍니다.

 

 

재밌네요!!!!!!!

728x90
반응형