@ModelAttribute 어놑ㅌ테이션의 기능과 커맨드 객체의 기능에 대해서 알아보겠습니다.
추가적으로 @RequestParam 어노테이션과 HttpServletRequest에 대해서도 추가적으로 다뤄보겠습니다.
순서는 HttpServletRequest > @RequestParam > 커맨드 객체 > @ModelAttribute 순서로 이해해야 세가지 개념에 대해서 확실하게 이해하실 수 있습니다.
Extends the ServletRequest interface to provide request information for HTTP servlets.
The servlet container create an HttpServletRequest object and passes it as an argument to the servlet's service methods(doGet, doPPost, etc).
docs.oracle.com 에서는 위와 같이 설명되어 있다.
HttpServletRequest는 Http Servlet에 대한 요청 정보를 제공하도록 ServletRequest를 확장한 인터페이스 입니다.
HttpServletRequest는 서블릿 컨테이너가 생성하며 서블릿의 service() 메서드의 매개변수로 보냅니다.
서블릿의 생명주기에 대해서 잠깐 다루고 가겠습니다.
서블릿의 생명주기(Life Cycle)
1. 서블릿의 컨테이너가 서블릿 인스터너스의 init() 메서드를 호출하여 초기화한다.
- 최초 요청시 한번만 초기화되며 그 이후로는 이 과정을 생략한다.
2. 서블릿이 초기화된 다음부터는 클라이언트가 요청을 처리할 수 있다. 각 요청은 별도의 스레드로 처리하고 이 때 서블릿의 service() 메서드를 호출한다.
- 이 안에서 HTTP 요청을 받고 클라이언트로 보낼 HTTP 응답을 만든다.
- service()는 Http Method에 따라 doGet() 또는 doPost() 등으로 위임하여 처리한다.
3. 서블릿 컨테이너 판단에 따라 서블릿을 메모리에서 내려야할 시점에 destroy()를 호출한다.
public class HelloServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("init");
}
@Override
public void deGet(HttpServletRequest req, HttpServletResponse res) throws ServletException {
System.out.println("doGet");
}
@Override
public void destory() {
System.out.println("destroy");
}
}
위 내용을 토대로 알 수 있는 HttpServletRequest의 핵심 기능은 HttpServlet의 요청을 받아서 꺼내서 쓸 수 있다는 것입니다.
그럼 이제 HttpServletRequest로 어떻게 컨트롤러에서 값을 꺼내는지 알아보겠습니다.
<form action="<c:url value="/user/ins"/>" method="post"/>
<input type="text" name="userName" value="JungHo" />
<input type="text" name="phone" value="010-1234-5678" />
</form>
위 처럼 JSP에서 사람 정보를 입력하고 POST로 넘기면 formData 형식 처럼 key와 value의 값으로 HttpServletRequest에 담아서 컨트롤러에 전달합니다.
GET의 경우 URL 뒤에 /user/ins?name=abc&phone=010-1234-5678 형식으로 전달되는데 물음표(?) 뒤의 문자열들을 쿼리스트링 또는 요청 파라미터라고 부릅니다.
GET 방식의 경우에도 ?key=value&key=value 형식으로 HttpServletRequest에 담아서 컨트롤러로 전달합니다.
@PostMapping("/ins")
public String ins(HttpServletRequeset request) {
String name = request.getParameter("name");
String name = request.getParameter("phone");
//만약에 JSP에서 설정한 name="userName" 이라는 키 값이 여러개인 경우에는
//getParameterValues() 메서드를 이용하여 배열로 받아올 수 있다.
String[] names = request.getParameterValues("name");
return REDIRECT_LIST;
}
컨트롤러에서 위 처럼 꺼내서 쓸 수 있습니다. 즉, 속성 하나당 변수 1개가 생성되는 1:1 방식이라고 할 수 있습니다.
@RequestParam
HttpServletRequest와 동일하게 @RequestParam은 1:1 방식입니다. 차이점은 HttpServletRequest 대신 @RequestParam이라는 어노테이션을 사용한다는 점입니다.
<form action="<c:url value="/user/ins"/>" method="post"/>
<input type="text" name="userName" value="JungHo" />
<input type="text" name="phone" value="010-1234-5678" />
</form>
JSP 예제는 HttpSerrrvletRequest 예제와 동일한 것으로 사용하겠습니다.
@PostMapping("/ins")
public String ins(@RequestParam String userName, @RequestParam String phone) {
//@RequestParam 뒤에 붙는 매개변수 변수명은 JSP 에서 설정한 name 의 key 값과 동일해야 한다.
return REDIRECT_LIST;
}
HttpServletRequest와 @RequestParam을 이용하여 받아오는 경우 요청 파라미터가 많아지면 많아질 수록 컨트롤러 내부코드나 매개변수가 증가하여 코드 가독성이 떨어지고, 작성되는 코드 양이 많아집니다. 이러한 문제를 해결하고자 나온 것이 커맨드 객체(Command Object) 입니다.
'spring' 카테고리의 다른 글
Spring MVC 구조 - (하) (0) | 2020.10.20 |
---|---|
IOC(Inversion of Control)컨테이너 - 서블릿 컨테이너 (0) | 2020.10.03 |
MVC 프레임워크 구현 - (중) (0) | 2020.10.03 |
@ModelAttribute와 커맨드 객체(2) (0) | 2020.09.06 |
web.xml - Element (0) | 2020.03.15 |