쌓고 쌓다
서블릿, JSP로 MVC 패턴 만들기 본문
서블릿은 Controller로, JSP는 View로 사용한다.
Model은 HttpServletRequest 객체를 사용한다.
회원 저장
formController
@WebServlet(name="mvcMemberFormServlet", urlPatterns = "/servlet-mvc/members/new-form")
public class MvcMemberFormServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String viewPath = "/WEB-INF/views/new-form.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
*WEB-INF에 있는것은 Controller를 통해서만 접근이 가능하다. URL로 접근 안된다.
forward
서버 내부에서 다시 호출하기 때문에 클라이언트는 인식할 수 없고 URL도 변경되지 않는다. 호출이 1번 일어남.
redirect
응답이 클라이언트에게 갔다가, 클라이언트가 다시 redirect 경로로 요청을 보낸다. 호출이 2번 일어남.
클라이언트가 인식할 수 있고 URL 또한 변경된다.
new-form.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!-- 상대경로 사용, [현재 URL이 속한 계층 경로 + /save] -->
<form action="save" method="post">
username: <input type="text" name="username" />
age: <input type="text" name="age" />
<button type="submit">전송</button>
</form>
</body>
</html>
action 경로가 save이다.
이것은 상대경로 위치로 현재 URL 경로에서 save를 호출한다. (현재 경로: /servlet-mvc/memvers/)
만약 상대 경로라면 action 경로를 "/servlet-mvc/members/save"로 지정한다.
saveController
@WebServlet(name = "mvcMemberSaveServlet", urlPatterns = "/servlet-mvc/members/save")
public class MvcMemberSaveServlet extends HttpServlet {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age")); // request.getParameter의 반환은 문자열이다. 변환 필요.
Member member = new Member(username, age);
memberRepository.save(member);
request.setAttribute("member", member);
String viewPath = "/WEB-INF/views/save-result.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
form 데이터로 넘어온 POST 요청을 getParameter로 꺼낸다. URL 쿼리 파라미터와 형식이 같기에 getParameter로 꺼낼 수 있다.
받은 데이터를 Repository에 저장하고 Model에 담아 save-result.jsp로 응답한다.
Model은 HttpServletRequest 객체를 사용하며 아래의 방법으로 데이터를 저장하고 꺼낸다.
- request.setAttribute() : 데이터 저장
- request.getAttribute() : 데이터 조회
save-result.jsp
<%@ page import="hello.servlet.domain.member.Member" %> <!-- 프로퍼티 접근법 사용시 import 필요 없음 -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<ul>
<li>id = <%=((Member) request.getAttribute("member")).getId()%>
</li>
<li>username = <%=((Member) request.getAttribute("member")).getUsername()%>
</li>
<li>age = <%=((Member) request.getAttribute("member")).getAge()%>
</li>
<!-- 프로퍼티 접근법 또한 가능 -->
<li>id = ${member.id}</li>
<li>username = ${member.username}</li>
<li>age = ${member.age}</li>
</ul>
<a href="/index.html">메인</a>
</body>
</html>
Model에 담긴 데이터는 프로퍼티 접근법으로 ${member.id}처럼 접근하자. JSP가 ${} 문법을 제공하는 것이다.
회원 목록
memberListController
@WebServlet(name = "mvcMemberListServlet", urlPatterns = "/servlet-mvc/members")
public class MvcMemberListServlet extends HttpServlet {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Member> members = memberRepository.findAll();
request.setAttribute("members", members);
String viewPath = "/WEB-INF/views/members.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
멤버 목록 또한 마찬가지로 List<Member>를 request를 통해 Model에 담아주면 된다.
members.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!-- JSP가 태그를 생성해줌 -->
<html>
<head>
<title>Title</title>
</head>
<body>
<table>
<thead>
<th>id</th>
<th>username</th>
<th>age</th>
</thead>
<tbody>
<c:forEach var="item" items="${members}">
<tr>
<td>${item.id}</td>
<td>${item.username}</td>
<td>${item.age}</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>
JSP가 제공하는 JSTL로 HTML 표준 태그를 생성할 수 있다.
<c:forEach> 기능으로 members에 담긴 데이터를 하나씩 뽑아 태그를 생성.
사용시 아래의 선언이 필요하다.
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
MVC 패턴 한계
MVC 패턴에서 각 요청마다 각 Controller가 담당한다.
즉, 모든 컨트롤러에서 공통 처리하는 기능을 만들기가 어렵다.
프론트 컨트롤러로 컨트롤러 호출전에 공통 기능을 처리할 수 있다.
'프로그래밍 > JSP & Servlet' 카테고리의 다른 글
프론트 컨트롤러 개념과 구현 (0) | 2023.07.30 |
---|---|
JSP 애플리케이션과 MVC 패턴 (0) | 2023.07.25 |
서블릿 애플리케이션과 템플릿 엔진 (0) | 2023.07.24 |
HTTP 응답 데이터 (0) | 2023.07.22 |
HTTP 요청 데이터 (0) | 2023.07.20 |