본문 바로가기

학원/복기

[Spring] Session Scope / @SessionAttributes

예제1)

 

전달값(로그인정보)를 제공받아 인증 처리 후 권한 정보를 Session Scope 속성값으로 저장하여 로그인 성공 메세지를 출력하는 JSP 문서의 뷰이름을 반환하는 요청 처리 메소드를 선언해보자

  • 전달값을 String 자료형의 매개변수에 하나씩 제공받아 사용할 것이다.
  • Session Scope 속성값을 저장하기 위해서는 매개변수로 HttpSession 객체를 제공받아 사용해야 한다.

Request Scope는 현재 요청 처리 메소드와 포워드 이동 되는 뷰(JSP) 에서만 속성값을 제공받아 사용 가능하지만,

Session Scope는 동일한 세션을 사용하는(=클라이언트가 같은) 모든 요청 처리 메소드와 뷰에서 속성값을 제공받아 사용 가능하다.

 

 

LoginController

@Controller
public class LoginController {
	@RequestMapping(value= "/login", method=RequestMethod.GET)
	public String login() {
		return "login_form";//포워드 이동 
	}
	
	//전달값(로그인정보)를 제공받아 인증 처리 후 권한 정보를 Session Scope 속성값으로 저장 후 
	//로그인 성공 메세지를 출력하는 JSP 문서의 뷰이름을 반환하는 요청 처리 메소드
	@RequestMapping(value= "/login", method=RequestMethod.POST)
	public String login(@RequestParam String id, @RequestParam String passwd
			,HttpSession session, Model model) {
		if(!id.equals("abc123") || !passwd.equals("123456")) {//인증 실패
			//인증 실패 관련 정보를 Request Scope 속성값으로 저장 - 입력페이지(JSP)에서 출력 가능
			model.addAttribute("message", "아이디 또는 비밀번호를 잘못 입력 하였습니다.");
			model.addAttribute("id", id);
			return "login_form";//입력페이지로 이동 
		}
		
		//인증 성공 - 권한 관련 정보를 Session Scope 속성값으로 저장
		session.setAttribute("loginId", id);
		
		return "login_display";
	}
}

 

login_form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>로그인</h1>
	<hr>
	<form action="login" method="post">
	<table>
		<tr>
			<td>아이디</td>
			<td><input type="text" name="id" value="${id }"></td>
		</tr>
			<tr>
			<td>비밀번호</td>
			<td><input type="password" name="passwd"></td>
		</tr>
		<tr>
			<td colspan="2"><button type="submit">로그인</button></td>
		</tr>
	</table>
	</form>
	<p style="color: red;">${message }</p>
</body>
</html>

 

login_display.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>로그인 성공</h1>
	<hr>
	<h2>${loginId }님, 환영합니다.</h2>
</body>
</html>

 

 

아이디 또는 비밀번호를 잘못 입력한 경우

 

 

로그아웃 페이지를 만들어보자

 

LoginController

@RequestMapping("/logout")
public String logout(HttpSession session) {
	//session.removeAttribute("loginId");
	session.invalidate();//현재 세션을 무효화하여 세션에 저장된 모든 데이터를 삭제
	return "logout_display";
}

 

logout_display.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>로그아웃</h1>
	<h2>로그아웃 처리 되었습니다.</h2>
	<a href="login">로그인</a>
</body>
</html>

 

 

로그인, 비로그인 사용자의 권한에 따른 요청 처리를 해보자 

 

@RequestMapping("/login_display")
public String login(HttpSession session, Model model) { 
	if(session.getAttribute("loginId")==null) {
		model.addAttribute("message", "로그인 사용자만 접근 가능합니다.");//비로그인 사용자가 요청했을 경우 
		return "login_form";
	}
		return "login_display";//로그인 성공했을 때만 해당 페이지 출력
}

 

 

 

모든 전달값을 Member 클래스의 매개변수의 필드값으로 제공받아 사용하는 것도 가능하다.

 

 

Member

@Data
public class Member {
	private String id;
	private String passwd;
	private String name;
	private String email;
}

 

LoginController

@RequestMapping(value= "/login", method=RequestMethod.POST)
public String login(@ModelAttribute Member member, HttpSession session, Model model) {
	if(!member.getId().equals("abc123") || !member.getPasswd().equals("123456")) {//인증 실패
		//인증 실패 관련 정보를 Request Scope 속성값으로 저장 - 입력페이지(JSP)에서 출력 가능
		model.addAttribute("message", "아이디 또는 비밀번호를 잘못 입력 하였습니다.");
		return "login_form";//입력페이지로 이동 
	}
		
	//인증 성공 - 권한 관련 정보를 Session Scope 속성값으로 저장
	session.setAttribute("loginId", member.getId());
		
	return "login_display";
}

 

login_form.jsp 수정

<td><input type="text" name="id" value="${member.id }"></td>

 


예제2)

 

 

Hewon

@Data
public class Hewon {
	private String id;
	private String name;
	private String email;
}

 

SessionController

@Controller
public class SessionController {
	//아이디를 전달받아 회원정보를 검색하여 반환하는 메소드 - Service 클래스의 메소드
	private Hewon getHewon(String id) {
		Hewon hewon=new Hewon();
		hewon.setId(id);
		hewon.setName("홍길동");
		hewon.setEmail("abc@itwill.xyz");
		return hewon;
	}
	
	//아이디를 전달받아 아이디의 회원정보를 검색하여 뷰에게 제공하기 위한 요청 처리 메소드
	// => 요청 처리 메소드에서 검색된 회원정보를 속성값으로 저장하여 뷰(JSP)에서 HTML 태그를 사용하여 출력되도록 응답 처리
	@RequestMapping("/hewon_view")
	public String view(@RequestParam(defaultValue = "abc123") String id, Model model) {
		//Service 클래스의 메소드를 호출하여 매개변수에 전달된 아이디의 회원정보를 검색하여 반환받아 저장
		Hewon hewon=getHewon(id);
		
		//Model 객체를 사용하여 검색된 회원정보를 속성값으로 저장하여 뷰에게 제공
		// => 현재 요청 처리 메소드의 뷰에게만 속성값을 제공하여 응답 처리 - Request Scope
		//model.addAttribute("hewon", hewon);
		//속성명을 생략하면 속성값으로 저장된 객체의 자료형(클래스)의 이름을 속성명으로 자동 설정
		// => 속성명은 클래스 이름의 첫문자는 소문자로 자동 변환
		model.addAttribute(hewon);//속성명 생략 가능
		
		return "hewon_view";
	}
}

 

hewon_view.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>회원정보</h1>
	<hr>
	<ul>
		<li>아이디 = ${hewon.id }</li>
		<li>이름 = ${hewon.name }</li>
		<li>이메일 = ${hewon.email }</li>
	</ul>
	<!-- 회원정보 변경페이지를 요청할 수 있는 링크 제공 - 아이디 전달 -->	
	<button type="button" onclick="location.href='hewon_update?id=${hewon.id}';">회원정보변경</button>
</body>
</html>

 

 

 

 

 

update 페이지를 만들어 보자

//아이디를 전달받아 아이디의 회원정보를 검색하여 뷰에게 제공하기 위한 요청 처리 메소드
// => 요청 처리 메소드에서 검색된 회원정보를 속성값으로 저장하여 뷰(JSP)에서 입력 태그의 초기값으로 사용되도록 응답 처리
@RequestMapping(value = "/hewon_update", method = RequestMethod.GET)
public String update(@RequestParam(defaultValue = "abc123") String id, Model model) {
	Hewon hewon=getHewon(id);
	model.addAttribute(hewon);//입력태그의 초기값으로 사용할 것임
	return "hewon_update";
}

 

hewon_update.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>회원정보변경</h1>
	<hr>
	<form action="hewon_update" method="post">
	<!-- 회원정보를 변경하기 위해 hidden 타입의 입력태그로 아이디 전달 -->
	<!-- => 아이디를 입력태그의 초기값으로 설정하여 read-only 속성을 사용하여 전달 가능 -->
	<input type="hidden" name="id" value="${hewon.id }">
	<table>
		<tr>
			<td>아이디</td>
			<!-- <td><input type="text" name="id" value="${hewon.id }" readonly="readonly"></td> -->
			<td>${hewon.id }</td>
		</tr>
		<tr>
			<td>이름</td>
			<td><input type="text" name="name" value="${hewon.name }"></td>
		</tr>
		<tr>
			<td>이메일</td>
			<td><input type="text" name="email" value="${hewon.email }"></td>
		</tr>
		<tr>
			<td colspan="2"><button type="submit">회원변경</button></td>
		</tr>
	</table>
	</form>
	<p style="color: red;">${message }</p>	
</body>
</html>

 

 

 

 

회원정보를 전달받아 변경된 회원정보를 뷰에게 제공하는 요청 처리 메소드를 선언해보자

@RequestMapping(value = "/hewon_update", method = RequestMethod.POST)
public String update(@ModelAttribute Hewon hewon) {
	return "hewon_result";
}

 

hewon_result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
	<h1>회원정보 변경 확인</h1>
	<hr>
	<ul>
		<li>아이디 = ${hewon.id }</li>
		<li>이름 = ${hewon.name }</li>
		<li>이메일 = ${hewon.email }</li>		
	</ul>
</body>
</html>

 


 

 

@SessionAttributes를 사용하면 model 객체를 이용해 Session Scope처럼 사용할 수 있다.

 

@Controller
@SessionAttributes
public class SessionController {
    ...
    ...
}

 

@SessionAttributes

@SessionAttributes는 Model 객체를 사용하여 저장되는 속성값을 현재 요청 처리 클래스(Controller 클래스)에 있는 모든 요청 처리 메소드와 뷰에게 제공하기 위한 어노테이션이다. (변경 처리할 때만 사용)

  • Model 객체를 사용하여 저장되는 속성값을 Request Scope 속성값이 아닌 제한적인 Session Scope 속성값으로 변환하여 사용되도록 제공한다.
  • 변경 처리시 호출되는 요청 처리 메소드에서 변경할 객체를 따로 검색하지 않고, 뷰에서는 값을 전달하지 않도록 제한적인 Session Scope 속성값을 제공한다. 

@SessionAttributes에는 value 속성을 반드시 써주어야 한다.

  • 제한적인 Session Scope 속성값으로 변환하기 위한 속성명을 속성값으로 설정한다.
  • 다른 속성값이 없는 경우 속성값만 설정 가능하다.
@Controller
@SessionAttributes("hewon")
public class SessionController {
    ...
    ...
}

 

@SessionAttributes에 의해 Model 객체로 저장된 속성값은 제한적인 Session Scope 속성값으로 변환되어 현재 요청 처리 클래스의 모든 요청 처리 메소드와 뷰에게 속성값을 제공해준다.

//@SessionAttributes에 의해 Session Scope의 속성값으로 변환
model.addAttribute(hewon);

 

@SessionAttributes에 의해 제공된 회원정보 요청 처리 메소드와 뷰에서 사용할 수 있다.

따라서 아이디를 전달받아 회원정보를 검색하는 명령과 뷰에게 속성값을 저장하여 제공하는 명령이 불필요하다.

//아이디를 전달받아 아이디의 회원정보를 검색하여 뷰에게 제공하기 위한 요청 처리 메소드
// => 요청 처리 메소드에서 검색된 회원정보를 속성값으로 저장하여 뷰(JSP)에서 입력 태그의 초기값으로 사용되도록 응답 처리
/*
@RequestMapping(value = "/hewon_update", method = RequestMethod.GET)
public String update(@RequestParam(defaultValue = "abc123") String id, Model model) {
	Hewon hewon=getHewon(id);
	model.addAttribute(hewon);
	return "hewon_update";
}
*/

@RequestMapping(value = "/hewon_update", method = RequestMethod.GET)
public String update() {
	return "hewon_update";
}

 

 

 

@SessionAttributes 어노테이션을 사용하면 아이디를 전달하지 않아도 회원정보 변경페이지에서 회원정보가 저장된 속성값을 제공받아 사용가능하므로 아이디 전달이 불필요하다.

 

hewon_view

<!-- <button type="button" onclick="location.href='hewon_update?id=${hewon.id}';">회원정보변경</button> -->

<button type="button" onclick="location.href='hewon_update?id=';">회원정보변경</button>

 

 

요청 처리 메소드의 매개변수에는 Command 객체로 @SessionAttributes 어노테이션에 의해 제공된 회원정보를 전달받아 저장하고 변경값으로  Command 객체의 필드값만 변경 처리한다.

  • SessionStatus 인터페이스로 매개변수를 작성하여 SessionStatus 객체를 제공받아 저장해야 한다.
    • SessionStatus 객체 : @SessionAttributes 어노테이션에 의해 제공된 제한적인 Session Scope 속성값의 상태정보를 저장하기 위한 객체
    • SessionStatus.setComplete() : @SessionAttributes 어노테이션에 의해 제공된 제한적인 Session Scope 속성값을 제거하는 메소드
//회원정보를 전달받아 변경된 회원정보를 뷰에게 제공하는 요청 처리 메소드
/*
@RequestMapping(value = "/hewon_update", method = RequestMethod.POST)
public String update(@ModelAttribute Hewon hewon) {
	return "hewon_result";
}
*/

@RequestMapping(value = "/hewon_update", method = RequestMethod.POST)
public String update(@ModelAttribute Hewon hewon, SessionStatus sessionStatus) {
	sessionStatus.setComplete();
	return "hewon_result";
}

 

hewon_update.jsp에서 아이디를 전달하지 않아도 된다.

<!-- <input type="hidden" name="id" value="${hewon.id }"> -->