Spring MVC5 @SessionAttributes 개요, @SessionAttributes, @ModelAttribute 미니 장바구니 예제, @SessionAttributes vs @SessionAttribute 비교
http://ojc.asia/bbs/board.php?bo_table=LecSpring&wr_id=857
ojc.asia
n @SessionAttributes는 주로 @Controller에서 사용되며, 지정한 모델 객체를 세션레벨에서 저장하고 관리한다는 것을 알리는 어노테이션으로, @SessionAttributes 어노테이션을 컨트롤러 클래스 위에 붙이고 모델 이름을 인자로 준다.
컨트롤러의 다른 메소드에 대한 요청이 들어 오면 Spring이 가장 먼저 할 일은 @SessionAttributes ( 'emp')를 알아 채고 세션에서 'emp' 모델을 찾는다. 값을 찾지 못하면 이름이 'emp'인 @ModelAttribute가있는 메서드 getEmp() 메소드가 호출되고, 메서드에서 반환 된 값은 'emp'라는 이름으로 세션에 저장된다.
@Controller
@SessionAttributes("emp")
public class EmpController {
// 다른 컨트롤러 메소드의 요청이 오면 그보다 먼저 아래 메소드가 실행되어 리턴되는 객체를 emp 라는 이름으로 세션에 저장한다.
@ModelAttribute("emp")
public Emp getEmp (....) {
return new Emp(....);
}
………………..
}
n 어노테이션에서 지정한 모델 객체를 세션에 저장하고 이후부터 해당 모델 객체가 사용되면 세션에서 불러와서 사용하고 이를 뷰에서 이름으로 접근이 가능하도록 한다.
n 컨트롤러의 메소드가 만드는 모델 정보 중에 이름이 같은 것이 있으면 세션에도 저장하고 컨트롤러 메소드의 @ModelAttribute 인자를 HTTP 요청(Request)이 아니라 먼저 세션에서 검색하여 사용한다.
n @SessionAttributes를 사용하면 @ModelAttribute또는 model.addAttribute()를 사용해서 객체를 저장할 경우 세션에 저장된다.
n @SessionAttributes로 세션에서 사용 완료된 객체는 사용 후 SessionStatus.setComplete() 메소드로 제거 해야 한다.
@SessionAttribute vs @SessionAttributes
@SessionAttributes는 지정한 모델 객체를 세션에 저장하고 관리한다는 의미이지만 @SessionAttribute는 세션에 저장되어 있는 값(속성)을 컨트롤러의 메소드에 매핑 시켜주는 어노테이션 이다.
1. 스프링 인터셉터에서
public class HelloInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
System.out.println("preHandle~~~");
HttpSession session = request.getSession();
session.setAttribute(“msg”, “Hello~”);
return true;
}
2. 컨트롤러 메소드에서
@Controller
public class EmpController {
@RequestMapping(value = "/getEmp", method = RequestMethod.POST)
public Emp getEmp(@SessionAttribute(“msg”) String msg, ……) {
}
}
활용사례
n 지속적으로 사용자의 입력 값을 세션에 유지시키기를 원하거나 여러 단계에 걸쳐 Submit 되면서 완성되는 폼을 구성하는 경우에 적합하다.
n 회원정보 입력화면에서 한번 입력 후 입력 값이 잘못 입력되어 경고 창을 띄우고 다시 페이지를 그린다고 생각할 때 최초 입력한 정보를 세션에 두고 이를 바탕으로 입력 화면을 다시 그려준다면 좋을 것 이다. 이때 @SessionAttributes를 사용하면 된다.
n 회원정보 입력 화면이 여러 페이지에 걸쳐 입력되는 경우 @SessionAttributes를 사용한다면 미리 모델 객체를 생성하여 첫번째 입력 화면의 내용을 세션에 객체로 저장해 두고, 다음 사용자 입력화면에서 나머지 회원정보를 입력하고 세션에 있는 객체에 추가로 저장하면 된다. 물론 이 경우 데이터 입력 값 검증 시 에도 유용하다.
n 장바구니 / 쇼핑카트
Spring WEB MVC 미니 쇼핑카트(@SessionAttibutes, @ModelAttribute)
n Spring WEB MVC를 이용하여 간단하게 장바구니를 구현하자.
ü 장바구니에 담길 상품항목은 name, price, cnt 정도로 하자
1. STS에서
File à New à Spring Legacy Project
Project Name : cart2
Spring MVC Project 선택
Spring Legacy Project가 안보이시는 분은 help à Eclipse MarketPlace에서 “sts”
로 검색 후 Spring Tools 3 Add-On Spring Tools 4 3.9.14.CI 를 Install 하자.
다음 화면의 top level package에서 a.b.cart 입력
전체 프로젝트 구성은 아래 그림과 같다.

2. pom.xml]
스프링 버전만 수정!
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>a.b</groupId>
<artifactId>cart</artifactId>
<name>cart2</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.6</java-version>
<org.springframework-version>5.2.3.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
3. 쇼핑몰에 담길 상품(Goods.java)
package a.b.cart;
public class Goods {
private String name; //상품명
private int cnt; //개수
private int price; //가격
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCnt() {
return cnt;
}
public void setCnt(int cnt) {
this.cnt = cnt;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
4. 컨트롤러[HomeController.java]
package a.b.cart;
import java.util.ArrayList;
import java.util.List;
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.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
@Controller
@RequestMapping("/")
// cart라는 이름의 Model은 세션에서 관리되는 Attribute이다.
@SessionAttributes({"cart"})
public class HomeController {
@RequestMapping(method = RequestMethod.GET)
public String getCart(Model model) {
if (!model.containsAttribute("cart")) {
// 빈 리스트가 cart라는 모델로 만들어지고 @SessionAttributes에 의해
// 세션에 저장되고 JSP에서 ${cart}로 참조가능
model.addAttribute("cart", new ArrayList<Goods>());
}
// home.jsp를 호출, cart라는 이름의 Model을 JSP가 참조가능
// 디스패처 서블릿의 설정파일 servlet-context.xml의 ViewResolver 참조
return "home";
}
@RequestMapping(value="add", method = RequestMethod.POST)
public String add(
//입력 파라미터인 name, price, cnt가 goods에 일괄 바인딩 됨
//goods라는 이름의 Model로 저장(Request Scope)
@ModelAttribute Goods goods,
//세션에서 cart라는 이름의 Model을 가져와 cart에 할당
@ModelAttribute("cart") List<Goods> cart) {
// cart라는 Model(ArrayList)에 사용자가 입력한 항목들을 가진 goods 객체를 Add
cart.add(goods);
//localhost:8080/cart로 요청을 보냄
return "redirect:/";
}
}
5. /WEB-INF/views/home.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>OracleJava Community Spring4 MVC Cart</title>
</head>
<body>
<h1>
Spring5 MVC Cart
</h1>
<c:forEach var="goods" items="${cart}" >
Name : ${goods.name}, Price : ${goods.price}, Cnt : ${goods.cnt }
<br/>
</c:forEach>
<br><br>
<h1>Add Cart...</h1>
<form method="post" action="add">
Name : <input type="text" name="name"><br>
Price : <input type="text" name="price"><br>
Cnt : <input type="text" name="cnt"> <br><br>
<button>Add Goods...</button>
</form>
</body>
</html>
8. 실행

#스프링강좌, #스프링강의, #스프링교육, #스프링동영상, #Spring동영상, #SessionAttribute, #ModelAttribute, #스프링장바구니, #스프링Cart, #스프링세션
댓글 없음:
댓글 쓰기