ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring MVC(세션 관리)
    웹개발/Spring 2020. 7. 28. 03:02

    이 내용은 인프런의 스프링 웹 MVC강좌를 참고하여 만들었습니다.

     

    세션 : 네트워크 환경에서 connectionless한 문제를 해결하기 위하여 존재

            일정시간동안 같은 사용자로부터 오는 요청을 하나의 상태로 저장

     

    Event class

    public class Event {
    
        interface ValidateLimit{}
        interface ValidateName{}
    
        private Integer id;
    
        @NotBlank(groups = ValidateName.class)
        private String name;
    
        @Min(value = 0, groups = ValidateLimit.class)
        private Integer limit;
    
        public Integer getLimit() {
            return limit;
        }
    
        public void setLimit(Integer limit) {
            this.limit = limit;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

     

    form.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Create New Event</title>
    </head>
    <body>
    <form action = "#" th:action="@{/events}" method="post" th:object="${event}">
        <p th:if="${#fields.hasErrors('limit')}" th:errors="*{limit}">Incorrect date</p>
        <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Incorrect date</p>
        <input type="text" title = "name" th:field="*{id}"/>
        <input type="text" title = "name" th:field="*{name}"/>
        <input type="text" title="limit" th:field="*{limit}">
        <input type="submit" value="Create"/>
    </form>
    
    </body>
    </html>

     

    1,기본적인 Session의 생성

    @Controller
    public class SampleController {
    
        @GetMapping("/events/form")
        public String eventsForm(Model model,HttpSession httpSession){
            Event newEvent = new Event();
            newEvent.setLimit(50);
            model.addAttribute("event",new Event());
            httpSession.setAttribute("event",newEvent);
            return "events/form";
        }
    }

    2, @SessionAttributes어노테이션을 이용하게 되면 model의 name과 세선의 name을 자동적으로 매칭을 시켜주워 Session을 저장시켜 줌

    @Controller
    @SessionAttributes({"event"})
    public class SampleController {
    
        @GetMapping("/events/form")
        public String eventsForm(Model model){
            Event newEvent = new Event();
            newEvent.setLimit(50);
            model.addAttribute("event",new Event());
            return "events/form";
        }
    
    }

    테스트 코드

    @RunWith(SpringRunner.class)
    @WebMvcTest
    public class SampleControllerTest {
    
        @Autowired
        MockMvc mockMvc;
    
        @Test
        public void testForm() throws Exception{
            ResultActions result  = mockMvc.perform(get("/events/form"))
                    .andDo(print())
                    .andExpect(view().name("events/form"))
                    .andExpect(model().attributeExists("event"))
                    .andExpect(request().sessionAttribute("event",notNullValue()))
                    .andExpect(status().isOk())
                    ;
        }
    }
       

    3, 세션의 종료는 SessionStatus를 통하여 종료시킬 수 있다.

    @Controller
    @SessionAttributes({"event"})
    public class SampleController {
    
        @GetMapping("/events/form")
        public String eventsForm(Model model){
            Event newEvent = new Event();
            newEvent.setLimit(50);
            model.addAttribute("event",new Event());
            return "events/form";
        }
    
        @PostMapping("/events")
        public String getEvent(SessionStatus sessionStatus) {
            sessionStatus.setComplete();
            return "events/form";
        }
    
    }

    또한, 세션의 시간을  applicaion.properties에 다음과 같은 구문을 추가하여 지속 시간을 설정 할 수 있다.

    server.servlet.session.timeout=60s

     

    4,위와 같은 방법을 사용하여 멀티 폼 서블릿을 통하여 세션을 응용 할 수 있다.

    form-name.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Create New Event</title>
    </head>
    <body>
    <form action = "#" th:action="@{/events/form/name}" method="post" th:object="${event}">
        <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Incorrect date</p>
        <input type="text" title = "name" th:field="*{name}"/>
        <input type="submit" value="Create"/>
    </form>
    
    </body>
    </html>

    form-limit.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Create New Event</title>
    </head>
    <body>
    <form action = "#" th:action="@{/events/form/limit}" method="post" th:object="${event}">
        <p th:if="${#fields.hasErrors('limit')}" th:errors="*{limit}">Incorrect date</p>
        <input type="text" title="limit" th:field="*{limit}">
        <input type="submit" value="Create"/>
    </form>
    
    </body>
    </html>

    finish.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Finish</title>
    </head>
    <body>
    <h1>Finish</h1>
    </body>
    </html>

     

    - model이 생성이 되면서 세션에 대한 내용이 바뀌는 것을 구현

     

    - name의 값이 들어간 event객체가 세션에 들어가고 limit 값이 들어간  event객체가 같은 이름의 세션에 들어갔을 때 대체가 됨을 확인 할 수 있다.

     

    @Controller
    @SessionAttributes({"event"})
    public class SampleController {
    
        @GetMapping("/events/form")
        public String eventsForm(Model model){
            model.addAttribute("event",new Event());
            return "events/form-name";
    
        }
    
        @PostMapping("/events/form/name")
        public String getEvent(@Valid @ModelAttribute Event event,
                               BindingResult bindingResult,
                               Model model,
                               HttpServletRequest request) {
    
            model.addAttribute("event",new Event()); //세션이 생성됨
    
            //세션이 만들어졌나 확인하는 작업
            HttpSession session = request.getSession();
            Event sessionCheck = (Event)session.getAttribute("event");
            System.out.println("세션의 name 확인 : " + sessionCheck.getName());
    
    
            if(bindingResult.hasErrors()){
                return "events/form-name";
            }
            return "redirect:/events/form/limit";
        }
    
        @GetMapping("/events/form/limit")
        public String eventsForm2(@ModelAttribute Event event, Model model){
            model.addAttribute("event",event);//세션의 생성
            return "events/form-limit";
    
        }
    
        @PostMapping("/events/form/limit")
        public String getEvent2(@Valid @ModelAttribute Event event,
                                BindingResult bindingResult,
                                Model model,
                                SessionStatus sessionStatus,
                                @SessionAttribute("event") Event eventSession) {
            if(bindingResult.hasErrors()){
                return "events/form-limit";
            }
    
            System.out.println("세션의 limit 확인 : " + eventSession.getLimit());
            sessionStatus.setComplete();//세션이 종료됨
            return "redirect:/events/list";
        }
    
        @GetMapping("/events/list")
        public String getEvents(){
            return "events/finish";
        }
    
    }

    5,Interceptor를 통하여 서블릿이 구동 준비 과정에서 세션을 생성하고 관리 할 수도 있다.

    public class VisitTimeSetter implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            HttpSession session = request.getSession();
            if(session.getAttribute("visitTime") == null){
                session.setAttribute("visitTime", LocalDateTime.now());
            }
    
            return true;
        }
    }
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new VisitTimeSetter());
        }
    
        @Override
        public void configurePathMatch(PathMatchConfigurer configurer) {
            UrlPathHelper urlPathHelper = new UrlPathHelper();
            urlPathHelper.setRemoveSemicolonContent(false);
            configurer.setUrlPathHelper(urlPathHelper);
        }
    }
Designed by Tistory.