서블릿은 기본적으로 상태를 유지하지 않는다. 상태를 유지해줘야 하는 경우에 사용한다.
도메인 중심 프로그래밍 모델과 상태 유지를 위한 세션 도입의 필요성ex) 수정 페이지의 처리 방법
- hidden 필드 사용시 단점
- 데이타 보안의 문제.
- 사용자 정보에 새로운 필드가 추가되거나 수정되었을 때 실수 우려.
- DB 재조회
- 계층 사이의 강한 결합
- 각 계층이 도메인 모델을 따라 만든 도메인 오브젝트에만 의존하도록 만들면 각 계층 사이에 의존성과 결합도를 대폭 줄일 수 있다.
- 모든 계층의 코드가 서로 영향을 주지 않고 독립적으로 확장하거나 변경할 수 있고, 여러 개의 로직에서 공유할 수 있다.
- 수정할 필요가 있는 필드가 어떤 것인지 모든 계층의 메소드가 다 알고 있게 하는 방식이다. 하지만 다음과 같은 단점이 존재한다.
- 애플리케이션이 복잡해질 경우 코드의 중복이 늘어난다.
- 한쪽을 수정하면 연관된 코드도 다 함께 수정해줘야 한다.
- 테스트가 힘들어 지고 테스트 코드에도 중복이 일어난다.
==> 그래서 해결책은 ???
@SessionAttributes
- 컨트롤러 메소드가 생성하는 모델 정보 중에서 @SessionAttributes에 지정한 이름과 동일한 것이 있다면 이를 세션에 저장해준다.
- ==> 뷰가 이 모델을 참조해서 기존 사용자 정보를 폼에 뿌려줄 수 있게 하기 위함.
- @ModelAttribute가 지정된 파라미터가 있을 때 이 파라미터에 전달해줄 오브젝트를 세션에서 가져온다.
- ==> 파라미터에 @ModelAttribute가 있으면 해당 타입의 새 오브젝트를 생성한 후에 요청 파라미터 값을 프로퍼티에 바인딩해준다.
- ==> 하지만 @SeesionAttributes에 선언된 이름과 @ModelAttribute의 모델 이름이 동일하면,
- 세션에 같은 이름의 오브젝트가 존재하는지 확인
- 존재한다면 세션에 있는 오브젝트를 가져와 @ModelAttribute파라미터로 전달해줄 오브젝트로 사용한다
- 존재하지 않는 다면 오브젝트를 새로 만들어서 오브젝트로 사용한다.
@Controller
@SessionAttributes("user")
public class UserController {
...
@RequestMapping(value="/user/edit", method=RequestMethod.GET)
public String form(@RequestParam int id, Model model) {
model.addAttribute("user", userService.getUser(id));
return "user/edit";
}
@RequestMapping(value="/user/edit", method=RequestMethod.POST)
public String submit(@ModelAttribute User user) { ... }
}
a. form() : DB에서 user 오브젝트를 생성해서 폼으로 넘긴다.
b. 폼에서는 user 오브젝트를 참조해서 정보를 뿌려준다.
c. 폼에서 사용자 입력 값을 submit() 으로 전송한다.
d. submit() : 폼에서 전송해준 파라미터만 바인딩한 뒤에 컨트롤러의 user 파라미터로 넘겨
e. 만약 검증 오류가 발생하면 다시 사용자 폼을 띄워준다.
- 하나 이상의 모델을 세션에 저장하도록 지정할 수 있다.
- @SessionAttributes의 설정은 클래스의 모든 메소드에 적용된다.
- 컨트롤러 메소드에 의해 생성되는 모든 종류의 모델 오브젝트는 @SessionAttributes에 저장될 이름을 갖고 있는지 확인된다.
- 여러대로 구성된 서버의 경우는 어떻게 처리해야 하나?????
SessionStatus
- @SessionAttributes를 사용할 때는 더 이상 필요 없는 세션 애트리뷰트를 코드로 제거해줘야 한다.
- SessionStatus는 컨트롤러 메소드의 파라미터로 사용할 수 있는 스프링 내장 타입이다.
@RequestMapping(value="/user/edit", method=RequestMethod.POST)
public String submit(@ModelAttribute User user, SessionStatus sessionStatus) {
this.userService.updateUser(user);
sessionStatus.setComplet(); // 세센에 저장된 정보를 모두 제거한다.
return "user/editsuccess";
}
등록 폼을 위한 @SessionAttributes 사용- 등록 폼에서도 @SessionAttributes를 사용하자.
- 더 강력한 상태유지 방식의 애플리케이션을 만들려면 스프링의 포트폴리오 프로젝트인 SWF(Spring Web Flow)를 검토해 보자.
스프링 목 오부젝트와 AbstractDispacherServletTest를 이용해 세션 테스트 만들기준비중