BoostCource/Back-end

#05. BE - Spring MVC에서 Session 사용하기

칸타탓 2018. 11. 21. 14:31

<5. Spring MVC에서 Session 사용하기>

참고: [boostcourse full-stack] http://www.edwith.org/boostcourse-web



* @SessionAttributes / @ModelAttribute

@SessionAttributes 파라미터로 지정된 이름과 같은 이름이 @ModelAttribute에 지정되어 있을 경우 메소드가 반환되는 값은 세션에 저장된다.


- 세션에 값을 초기화하기

@SessionAttributes("user")
public class LoginController {
  @ModelAttribute("user")
  public User setUpUserForm() {
  return new User();
  }
}


@SessionAttributes의 파라미터와 같은 이름이 @ModelAttribute에 있을 경우

세션에 있는 객체를 가져온 후, 클라이언트로 전송받은 값을 설정한다.

@Controller
@SessionAttributes("user")
public class LoginController {
......
  @PostMapping("/dologin")
  public String doLogin(@ModelAttribute("user") User user, Model model) {
......
  }
}

 

- @SessionAttribute

메소드에 @SessionAttribute가 있을 경우 파라미터로 지정된 이름으로 등록된 세션 정보를 읽어와서 변수에 할당한다.

@GetMapping("/info")
public String userInfo(@SessionAttribute("user") User user) {
//...
//...
return "user";
}


 

* SessionStatus

SessionStatus 는 컨트롤러 메소드의 파라미터로 사용할 수 있는 스프링 내장 타입이다.

현재 컨트롤러의 @SessionAttributes에 의해 저장된 오브젝트를 제거할 수 있다.

@Controller
@SessionAttributes("user")
public class UserController {
...... 
    @RequestMapping(value = "/user/add", method = RequestMethod.POST)
    public String submit(@ModelAttribute("user") User user, SessionStatus sessionStatus) {
  ......
  sessionStatus.setComplete();
                                   ......

   }
 }

 


* Spring MVC - form tag 라이브러리

modelAttribute속성으로 지정된 이름의 객체를 세션에서 읽어와서 form태그로 설정된 태그에 값을 설정한다.

<form:form action="login" method="post" modelAttribute="user">
Email : <form:input path="email" /><br>
Password : <form:password path="password" /><br>
<button type="submit">Login</button>
</form:form>






관리자는 /loginform에서 암호를 입력해 로그인을 한다.

관리자가 암호를 맞게 입력할 경우 세션에 로그인 정보가 저장된다.

세션에 로그인 정보가 있을 경우 방명록에는 "삭제" 링크가 보여진다.

삭제 링크를 누르면 삭제가 된다. 삭제 작업에서도 로그인 정보가 있는지를 검사해야 한다.

 


GuestbookAdminController.java


package kr.or.connect.guestbook.controller;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Controller
public class GuestbookAdminController {
@GetMapping(path="/loginform") //loginform이라는 요청이 들어오면
public String loginform() {
return "loginform"; //해당 요청을 받아서 loginform.jsp 수행
}
//해당 요청을 받아서 처리할 수 있는 컨트롤러
@PostMapping(path="/login")
//name="passwd"는 input의 name과 일치해야 한다
public String login(@RequestParam(name="passwd", required=true) String passwd,
HttpSession session,
RedirectAttributes redirectAttr) {
if("1234".equals(passwd)) {
session.setAttribute("isAdmin", "true"); //세션의 이름과 값 설정
} else {
redirectAttr.addFlashAttribute("errorMessage", "암호가 틀렸습니다.");
return "redirect:/loginform";
}
return "redirect:/list";
}
@GetMapping(path="/logout")
public String login(HttpSession session) {
session.removeAttribute("isAdmin");
return "redirect:/list";
}
}

 


loginform.jsp (view)


<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>loginform</title>
</head>
<body>
<h1>관리자 로그인</h1>
<br><br>
${errorMessage}<br>
<form method="post" action="login">
암호 : <input type="password" name="passwd"><br>
<input type="submit">
</form>
</body>
</html>


 

GuestbookController.java

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package kr.or.connect.guestbook.controller;
 
import java.util.ArrayList;
import java.util.List;
 
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttribute;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 
import kr.or.connect.guestbook.dto.Guestbook;
import kr.or.connect.guestbook.service.GuestbookService;
 
@Controller
public class GuestbookController {
    @Autowired
    GuestbookService guestbookService;
 
    @GetMapping(path="/list")
    public String list(@RequestParam(name="start", required=false, defaultValue="0"int start,
                       ModelMap model, @CookieValue(value="count", defaultValue="1", required=trueString value,
                       HttpServletResponse response) {
        
        try {
            int i = Integer.parseInt(value);
            value = Integer.toString(++i);
        }catch(Exception ex){
            value = "1";
        }
        
        Cookie cookie = new Cookie("count", value);
        cookie.setMaxAge(60 * 60 * 24 * 365); // 1년 동안 유지.
        cookie.setPath("/"); // / 경로 이하에 모두 쿠키 적용. 
        response.addCookie(cookie);
        
        List<Guestbook> list = guestbookService.getGuestbooks(start);
        
        int count = guestbookService.getCount();
        int pageCount = count / GuestbookService.LIMIT;
        if(count % GuestbookService.LIMIT > 0)
            pageCount++;
        
        List<Integer> pageStartList = new ArrayList<>();
        for(int i = 0; i < pageCount; i++) {
            pageStartList.add(i * GuestbookService.LIMIT);
        }
        
        model.addAttribute("list", list);
        model.addAttribute("count", count);
        model.addAttribute("pageStartList", pageStartList);
        model.addAttribute("cookieCount", value);
        
        return "list";
    }
    
    @PostMapping(path="/write")
    public String write(@ModelAttribute Guestbook guestbook,
                        HttpServletRequest request) {
        String clientIp = request.getRemoteAddr();
        System.out.println("clientIp : " + clientIp);
        guestbookService.addGuestbook(guestbook, clientIp);
        return "redirect:list";
    }
    
   //삭제 추가히기 - url로 요청을 받아오는 것: getMapping
    @GetMapping(path="/delete")
    public String delete(@RequestParam(name="id", required=true) Long id, 
                         @SessionAttribute("isAdmin"String isAdmin,
                         HttpServletRequest request,
                         RedirectAttributes redirectAttr) {
        if(isAdmin == null || !"true".equals(isAdmin)) { // 세션값이 true가 아닐 경우
            redirectAttr.addFlashAttribute("errorMessage""로그인을 하지 않았습니다.");
            return "redirect:loginform";
        }
        String clientIp = request.getRemoteAddr();
        guestbookService.deleteGuestbook(id, clientIp);
        return "redirect:list";        
    }
}
cs




<%@ 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 PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>방명록 목록</title>
</head>
<body>
<h1>방명록</h1>
<br>
방명록 전체 수 : ${count }, 방문한 수 : ${cookieCount }<br><br>
<c:forEach items="${list}" var="guestbook">
${guestbook.id }<br>
${guestbook.name }<br>
${guestbook.content }<br>
${guestbook.regdate }<br>
<!-- 삭제 링크 걸기 -->
<c:if test="${sessionScope.isAdmin == 'true'}"><a href="delete?id=${guestbook.id}">삭제</a><br><br></c:if>
</c:forEach>
<br>
<c:forEach items="${pageStartList}" var="pageIndex" varStatus="status">
<a href="list?start=${pageIndex}">${status.index +1 }</a>&nbsp; &nbsp;
</c:forEach>
<br><br>
<form method="post" action="write">
name : <input type="text" name="name"><br>
<textarea name="content" cols="60" rows="6"></textarea><br>
<input type="submit" value="등록">
</form>
</body>
</html>