티스토리 뷰
MVC패턴
컨트롤러(CONTROLLER) : 클라이언트(http)의 요청을 받아서 파라미터를 검증, 비지니스 로직을 실행한다. 그리고 뷰에 전달할 결과 데이터를 조회해서 모델에 담는다
모델(MODEL) : 뷰에 출력할 데이터를 담아둔다. 뷰가 필요한 데이터를 모두 모델에 담아 전달해주는 덕분에 뷰는 비지니스 로직이나 데이터 접근을 몰라도 되고 화면을 렌더링 하는 일에 집중할 수 있다
뷰(VIEW) : 모델에 담겨있는 데이터를 사용하여 화면을 그림
출처 : www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
member.java
package hello.servlet.domain.member;
import lombok.Getter;
import lombok.Setter;
@Getter @Setter
public class Member {
private Long id;
private String username;
private int age;
public Member(){
}
public Member( String username, int age) {
this.username = username;
this.age = age;
}
}
- 간단하게 id, username, age만 사용
- @Getter, @Setter : lombok 사용
MemberRepository.java
package hello.servlet.domain.member;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MemberRepository {
private static Map<Long,Member> store = new HashMap<>();
private static long sequence = 0L;
private static final MemberRepository instance = new MemberRepository();
public static MemberRepository getInstance(){
return instance;
}
private MemberRepository(){
}
public Member save(Member member){
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}
public Member findById(Long id){
return store.get(id);
}
public List<Member> findAll(){
return new ArrayList<>(store.values());
}
}
- 구현할 기능은 등록(save), 한개만 조회(findById), 모두조회(findAll)
index.html
<!DOCTYPE html>
<html><head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
<li><a href="basic.html">서블릿 basic</a></li>
<li>서블릿
<ul>
<li><a href="/servlet/members/new-form">회원가입</a></li>
<li><a href="/servlet/members">회원목록</a></li>
</ul>
</li>
<li>JSP
<ul>
<li><a href="/jsp/members/new-form.jsp">회원가입</a></li>
<li><a href="/jsp/members.jsp">회원목록</a></li>
</ul>
</li>
<li>서블릿 MVC
<ul>
<li><a href="/servlet-mvc/members/new-form">회원가입</a></li>
<li><a href="/servlet-mvc/members">회원목록</a></li>
</ul>
</li>
</ul>
</body>
</html>
노란 표시된곳을 클릭했을때 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
MvcMemberFormServlet.java / 회원등록폼 불러오는 컨트롤러(즉, 서블릿이 컨트롤러 역할을 함)
package hello.servlet.web.servletmvc;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@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); //서블릿에서 jsp호출
/////// 외부에서 호출되고 싶지 않을때 WEB-INF 사용
}
}
- /WEB-INF : 이 경로안에 JSP가 있으면 외부에서 직접 JSP를 호출 x
- getRequestDispatcher("경로") : 컨트롤러에서 뷰로 이동할때 사용
- dispatcher.forward() : 다른 서블릿이나 JSP로 이동할때 사용. 서버 내부에서 다시 호출
new-form.jsp / 회원등록폼 뷰
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta charset="UTF-8">
<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>
MvcMemberSaveServlet.java / 회원등록하는 컨트롤러
package hello.servlet.web.servletmvc;
import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@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"));
Member member = new Member(username, age);
memberRepository.save(member);
//model에 데이터를 보관
request.setAttribute("member", member); /// request 내부에 map같은 저장소가 잇음
String viewPath="/WEB-INF/views/save-result.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
- HttpServletRequest를 Model로 사용
- setAttribute() : request 객체에 데이터를 보관해서 뷰에 전달(뷰에서 request.getAttribute() 로 꺼내면 됨)
save-result.jsp / ↑ 전송버튼 눌렀을때 뷰
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
성공
<ul>
<li>id=${member.id}</li>
<li>username=${member.username}</li>
<li>age=${member.age}</li>
</ul>
<a href="/index.html">메인</a>
</body>
</html>
- 원래라면 값을 object로 받아와 <%= ((Member)request.getAttribute("member")).getId%> 처럼 써야되는데
JSP는 ${} 문법을 제공해서 간단하게 조회할수 있음
노란색으로 표시한 회원목록 눌렀을 때
MvcMemberListServlet.java / 등록된 모든 멤버 조회하는 컨트롤러
package hello.servlet.web.servletmvc;
import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@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);
}
}
- request 객체로 등록한 멤버들을 model에 보관
members.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/index.html">메인</a>
<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가 뷰 역할을 함)
- View로 이동하는 코드가 항상 중복 호출되어야 함
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
- 사용하지 않는 코드들 존재한다. 특히 response는 현재 코드에서 사용 x
- 공통 처리가 어렵다
↓↓↓
이를 해결하기 위해서 컨트롤러로 넘어가기전에 먼저 공통 기능을 처리해야함
결론 : 프론트 컨트롤러로 구현해보기
'JSP' 카테고리의 다른 글
[JSP] JDBC (0) | 2018.07.18 |
---|---|
[JSP] Scope 간단예제 - 상품선택, 내가선택한 품목보기 (0) | 2018.07.13 |
[JSP] 자바빈 JavaBean (0) | 2018.07.13 |
[JSP] 쿠키(Cooki), 세션(Session) (0) | 2018.07.11 |
[JSP] Request, Response 간단한 메뉴계산 예제 (0) | 2018.07.10 |
- Total
- Today
- Yesterday