DevLog ๐ถ
[Spring] MVC ํจํด์ด๋, V1~V5๋ก MVC ํ๋ ์์ํฌ ๋ง๋ค๊ธฐ ๋ณธ๋ฌธ
[Spring] MVC ํจํด์ด๋, V1~V5๋ก MVC ํ๋ ์์ํฌ ๋ง๋ค๊ธฐ
dolmeng2 2022. 8. 16. 15:44- ๊น์ํ ๋์ '์คํ๋ง MVC 1ํธ - ๋ฐฑ์๋ ์น ๊ฐ๋ฐ ํต์ฌ ๊ธฐ์ '์ ๋ณด๊ณ ์ ๋ฆฌํ ๊ธ์ ๋๋ค ๐
- ์ง๋ ํฌ์คํ ๊ณผ ์ด์ด์ง๋๋ค :D
- ๊ฐ๋จํ๊ฒ ํ์ ๊ด๋ฆฌ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค์ด๋ณด์.
[SMember.java]
@Getter @Setter
@NoArgsConstructor
public class SMember {
private Long id;
private String username;
private int age;
public SMember(String username, int age) {
this.username = username;
this.age = age;
}
}
- ์ด์ ์ ์คํ๋ง ํต์ฌ์๋ฆฌ ๊ฐ์์ ๋์ผํ ํ๋ก์ ํธ๋ฅผ ์ฌ์ฉํ๊ณ ์์ด์ ๋๋ฉ์ธ ์ด๋ฆ์ ๋ณ๊ฒฝํ์๋ค. Member๋ผ๊ณ ํด๋ ๋ฌด๋ฐฉํ๋ค.
[SMemberRepository.java]
public class SMemberRepository {
private static Map<Long, SMember> store = new ConcurrentHashMap<>();
private static AtomicLong sequence = new AtomicLong(0L);
private static final SMemberRepository repository
= new SMemberRepository();
private SMemberRepository() {
}
public static SMemberRepository getRepository() {
return repository;
}
public SMember save(SMember member) {
member.setId(sequence.incrementAndGet()); // ++sequence์ ๋์ผํ ์๋ฏธ
store.put(member.getId(), member);
return member;
}
public SMember findById(Long id) {
return store.get(id);
}
public List<SMember> findAll() {
return new ArrayList<>(store.values());
}
public void clearStore() {
store.clear();
}
}
- ์ ๋ฐ์ ์ผ๋ก ์ฑ๊ธํค ํจํด์ ์ฌ์ฉํ์๋ค. ์์ฑ์๋ฅผ private๋ก ๋ง์๊ณ , repository ์ญ์ getRepository()๋ก๋ง ๊ฐ์ ธ์ฌ ์ ์๋ค.
- ์ฑ๊ธํค์ด๋ค ๋ณด๋๊น ๋์์ฑ ์ด์ ๋๋ฌธ์ ConcurrentHashMap๊ณผ AtomicLong์ ์ฌ์ฉํด์ฃผ์๋ค. ์์ ์์๋ ์ฌ์ฉํ์ง ์์๋ ๋ฌด๋ฐฉํ๋ค.
- static์ผ๋ก๋ ๊ด๋ฆฌํ ํ์๋ ์๋ค. static์ ๊ณต์ ๋ณ์๋ก ์ฌ์ฉํ ๋ ์ฐ์ด์ง๋ง, ์ฑ๊ธํค์ด๋ฉด ์ด์ฐจํผ ์ด์ ๋ํด์ ๋ณด์ฅ๋ฐ๊ธฐ ๋๋ฌธ์ด๋ค.
- ์ถ๊ฐ์ ์ผ๋ก, findAll()์ ๊ฒฝ์ฐ new ArrayList<>()๋ก store.values()์ ๊ฐ์ ๋ณต์ฌํด์ ์ ๋ฌํ๋ ๊ฑธ ๋ณผ ์ ์๋๋ฐ, ์ด๋ ์๋ฐ์ ๋ ํผ๋ฐ์ค ์ฐธ์กฐ๋ก ์ธํด์ store ์์ฒด๋ฅผ ๋๊ฒจ๋ฒ๋ฆฌ๋ฉด store์ ๊ฐ์ด ๋ณ๊ฒฝ๋ ์ ์๋ ๋ฌธ์ ๋๋ฌธ์ ์์ ๊ฐ์ด ์ ์ธํ์๋ค.
โ Test
class SMemberRepositoryTest {
SMemberRepository repository = SMemberRepository.getRepository();
@AfterEach
void afterEach() {
repository.clearStore();
}
@Test
public void save() throws Exception {
// given
SMember member = new SMember("hi", 22);
// when
SMember savedMember = repository.save(member);
// then
SMember findMember = repository.findById(savedMember.getId());
assertThat(findMember).isEqualTo(member);
}
@Test
public void findAll() throws Exception {
// given
SMember member1 = new SMember("hi", 22);
SMember member2 = new SMember("hihi", 22);
repository.save(member1);
repository.save(member2);
// when
List<SMember> all = repository.findAll();
// then
assertThat(all.size()).isEqualTo(2);
assertThat(all).contains(member1, member2);
}
}
- ๊ฐ๋จํ ํ ์คํธ ์ฝ๋์ด๋ค. ๋ ๋ค ์ ๋์๊ฐ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
- ์ด์ , ๋ทฐ ํ๋ฉด์ ๊ตฌ์ฑํ๊ธฐ ์ํด์ JSP, ํ์๋ฆฌํ๋ฅผ ์ด์ฉํด์ ์งํ์ ํด๋ณด์.
- ๋จ์ ์๋ธ๋ฆฟ๊ณผ ์๋ฐ ์ฝ๋๋ก๋ ๊ตฌ์ฑํ ์ ์์ง๋ง, ์์ฒญ๋ ํ๋์ฝ๋ฉ์ด ํ์ํ๊ณ ์ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ ์๋ตํ๊ฒ ๋ค.
- ๋จ์ JSP๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ทฐ์ ์๋ฐ ์ฝ๋๊ฐ ๋ค์ด๊ฐ๊ธฐ ๋๋ฌธ์ ๊ต์ฅํ ๋ณต์กํ๋ค. ๋ง์ด ์ฌ์ฉํ๋ MVC ํจํด์ ์ฌ์ฉํด๋ณด์.
| MVC ํจํด์ด๋?
- JSP์ ๊ฒฝ์ฐ ๋น์ฆ๋์ค ๋ก์ง, ๋ทฐ ๋ ๋๋ง๊น์ง ๋ค์ด๊ฐ๊ธฐ ๋๋ฌธ์ ์ ์ง๋ณด์ ๊ด์ ์์ ๋งค์ฐ ์ข์ง ์๋ค.
- MVC๋ ๋ชจ๋ธ - ๋ทฐ - ์ปจํธ๋กค๋ฌ๋ฅผ ํตํด์ ๊ฐ๊ฐ์ ์ญํ ์ ๋ ์ง์คํ ์ ์๋๋ก ๋์์ค๋ค.
โ ๋ชจ๋ธ (Model)
- ๋ทฐ์ ์ถ๋ ฅํ ๋ฐ์ดํฐ๋ฅผ ๋ด๋ ์ญํ ๋ก, ๋ชจ๋ธ์ ํตํด ๋ทฐ์๊ฒ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ค๊ณ ๋ณด๋ฉด ๋๋ค.
โ ๋ทฐ (View)
- ๋ชจ๋ธ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ์ด์ฉํ์ฌ ํ๋ฉด์ ๊ตฌ์ฑํ๋ค. HTML์ ํตํด ๋ทฐ๋ฅผ ๋ง๋ค์ด์ฃผ๋ ์์ ์ ์งํํ๋ค.
โ ์ปจํธ๋กค๋ฌ (Controller)
- HTTP ์์ฒญ์ ๋ฐ์์ ๊ฒ์ฆ ๋ฐ ๋น์ฆ๋์ค ๋ก์ง์ ์คํํ๋ ๋ถ๋ถ์ด๋ค. ๋ทฐ์ ์ ๋ฌํ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ธ์ ๋ด์์ฃผ๋ ์ญํ ์ ํ๋ค.
- ๋ณดํต ๋น์ฆ๋์ค ๋ก์ง์ ๊ฒฝ์ฐ ๋ณ๋์ Service ๋ ์ด์ด๋ฅผ ํตํด์ ์คํํ๋ค.
- ๊ฐ์ธ์ ์ธ ๊ฒฝํ์ผ๋ก๋ entity - repository - service - controller ๊ตฌ์กฐ๋ฅผ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๊ฒ ๊ฐ๋ค.
- ์ด ๊ทธ๋ฆผ์ด ๊ฐ์ฅ ์ ํํ๊ฒ ๋ก์ง์ ์ค๋ช ํด์ฃผ๋ ๊ฒ ๊ฐ๋ค :D
- ์ด์ , ์ค์ ์ฝ๋์ ์ ์ฉํด๋ณด์.
- build.gradle์ ๋ค์์ ์ถ๊ฐํด์ฃผ์. (JSP)
implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
implementation 'javax.servlet:jstl'
[new-form.jsp]
- main/webapp/WEB-INF/views ๋ฐ์ ์ค์ ํด๋์๋ค.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="save" method="post">
username: <input type="text" name="username">
age: <input type="text" name="age">
<button type="submit">์ ์กํ๊ธฐ</button>
</form>
</body>
- ๊ฐ๋จํ๊ฒ ์ด๋ฆ๊ณผ ๋์ด๋ฅผ ์ ๋ ฅ๋ฐ์ post ๋ฐฉ์์ผ๋ก ์ ์กํ ์ ์๋๋ก ๊ตฌ์ฑํ์๋ค.
- ํ์ฌ์ ๊ณ์ธต ๊ฒฝ๋ก + /save (action์ ์ง์ ํด์ค ๊ฒฝ๋ก)๊ฐ ํธ์ถ๋๋ค.
[save-result.jsp]
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
์ฑ๊ณต!
<ul>
<li>id=${member.id}</li>
<li>username=${member.username}</li>
<li>age=${member.age}</li>
</ul>
</body>
- ํ์ ์ ์ฅ ๊ฒฐ๊ณผ๋ฅผ ๋์์ฃผ๋ ๋ทฐ์ด๋ค.
[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>
<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>
- jsp์์ ์ ๊ณตํ๋ taglib ๊ธฐ๋ฅ์ ํตํด ํธ๋ฆฌํ๊ฒ ๋ฐ๋ณต๋ฌธ์ ์ฒ๋ฆฌํ์๋ค.
- items = {members}์ ๋ด๊ธด ์ ๋ค์ 'item'์ด๋ผ๋ ์ด๋ฆ์ผ๋ก ์ ๊ทผํ๋ฉฐ ๊ฐ ์์๋ค์ ์ถ๋ ฅํด์ฃผ๋ ๊ฒ์ด๋ค.
- thead์ tbody์ ๊ฒฝ์ฐ ํ ์ด๋ธ์ ํค๋์ ๋ด์ฉ์ ์์ฑํ๋ ๋ถ๋ถ์ด๋ฉฐ, ๊ทธ๋ฅ ์น์ ์ ๋๋๋ ์ฉ๋๋ผ๊ณ ๋ณด๋ฉด ๋๋ค.
- th๋ ํ์ ์ ๋ชฉ, tr์ ์ผ์ข ์ ๊ฐ๋ก์ค, td๋ ๊ฐ๊ฐ์ ์ ๋ด์ฉ์ ์์ฑํด์ฃผ๋ ๋ฌธ๋ฒ์ด๋ค.
- ์ด์ , ๋ณธ๊ฒฉ์ ์ธ MVC ํ๋ ์์ํฌ๋ฅผ ์ ์ํ์!
| MVC ํ๋ ์์ํฌ
- MVC ํ๋ ์์ํฌ์ ํต์ฌ์ 'ํ๋ก ํธ ์ปจํธ๋กค๋ฌ(Front Controller)'์ด๋ค!
- ํ๋ก ํธ ์ปจํธ๋กค๋ฌ๋ ์๋จ์์ ์๋ธ๋ฆฟ ํ๋๋ก ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ๋ฐ์ผ๋ฉฐ, ์์ฒญ์ ๋ง๋ ์ปจํธ๋กค๋ฌ๋ฅผ ํธ์ถํด์ฃผ๋ ์ญํ ์ ํ๋ค.
- ๊ณตํต์ฒ๋ฆฌ๋ ๊ฐ๋ฅํ๋ฉฐ, ํ๋ก ํธ ์ปจํธ๋กค๋ฌ๋ฅผ ์ ์ธํ ๋๋จธ์ง๋ ์๋ธ๋ฆฟ์ ์ฌ์ฉํ ํ์๊ฐ ์๋ค.
- ๊ทธ๋ ๊ธฐ ๋๋ฌธ์, ๊ธฐ์กด์๋ ์๋ธ๋ฆฟ์ 3๊ฐ๋ก ๊ด๋ฆฌํ์๋ค๋ฉด ์ด์ ๋ 1๊ฐ๋ง ๊ด๋ฆฌํด๋ ๋๋ค๋ ๊ฒ์ด๋ค.
- ์คํ๋ง์์๋ DispatcherServlet์ด FrontController์ ์ญํ ์ ํด์ค๋ค!
- ๋จ๊ณ์ ์ผ๋ก ํ๋์ฉ ์ง์ ๊ตฌํํด๋๊ฐ๋ฉฐ FrontController ํจํด์ ์ตํ๋ณด์.
โ V1 - ์ปจํธ๋กค๋ฌ ์ธํฐํ์ด์ค ๋์ ํ๊ธฐ
[SMemberController.java]
public interface SMemberController {
void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
- ์ธํฐํ์ด์ค๋ก ์ ์ธํ์ฌ ํด๋น ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ์ปจํธ๋กค๋ฌ๋ค์ ๋ง๋ค์ด๋ณด์.
[MemberFormController.java] - ํ์ ๋ฑ๋ก ์ปจํธ๋กค๋ฌ
public class MemberFormController implements SMemberController{
@Override
public void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String viewPath = "/WEB-INF/views/new-form.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
[MemberSaveController.java] - ํ์ ์ ์ฅ ์ปจํธ๋กค๋ฌ
public class MemberSaveController implements SMemberController{
private final SMemberRepository repository
= SMemberRepository.getRepository();
@Override
public void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
SMember member = new SMember(username, age);
repository.save(member);
// JSP์๊ฒ ๋ฐ์ดํฐ ์ ๋ฌํ๊ธฐ ์ํด์ ์ฌ์ฉ
request.setAttribute("member", member);
String viewPath = "/WEB-INF/views/save-result.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
HttpServletRequest๋ฅผ ์ผ์ข ์ Model๋ก ์ฌ์ฉํ๋ค. setAttribute๋ฅผ ์ด์ฉํด request์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๊ดํ์ฌ ๋ทฐ์ ์ ๋ฌํ๋ค.
์๊น, view ๊ตฌ์ฑํ ๋ ์ฌ์ฉํ ${} ๋ฌธ๋ฒ์ด ์ผ์ข ์ getAttribute์ ๋์ผํ ์ญํ ์ด๋ผ๊ณ ๋ณด๋ฉด ๋๋ค :D
์ฌ๊ธฐ์ RequestDispatcher๋ ํด๋ผ์ด์ธํธ์ ์์ฒญ์ JSP๋ก ๋๊ฒจ์ฃผ๋ ์ญํ ์ ํ๋ค๊ณ ๋ณผ ์ ์๋ค.
๐ฉ ์ด๋, HttpServletResponse์ sendRedirect()๋ฅผ ์ด์ฉํ๋ฉด ์ํ๋ ๊ฒฝ๋ก๋ก ์ด๋์ ํ ์ ์์ง๋ง, HTTP์ ๋ฆฌ๋ค์ด๋ ์ ์ ์ด์ฉํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋ธ๋ผ์ฐ์ ์๊ฒ ์ง์ ์ ์ธ response๋ฅผ ์ค ๋ค์. ๋ธ๋ผ์ฐ์ ์์ ์ง์ ๋ฐ์ ์์ฒญ ๊ฒฝ๋ก๋ก ๋ ๋ค์ ์ฌ์์ฒญ์ ํ๊ฒ ๋์ด์ 2๋ฒ์ ์ฐ์ฐ์ด ๋ฐ์ํ๊ฒ ๋๋ค.
: ์ฆ, ์ ๋ฐฉ๋ฒ์ ํด๋ผ์ด์ธํธ๊ฐ ์ธ์งํ๊ธฐ ๋๋ฌธ์ ์ค์ URL ๊ฒฝ๋ก๊น์ง ๋ณ๊ฒฝ๋๋ค.
๋ํ, ์ต์ด ์์ฒญ์ ์ฒ๋ฆฌํ ๋ด์ฉ์ ๋ฆฌ๋ค์ด๋ ํธ ๋ ์์ฒญ์์ ๊ณต์ ๊ฐ ์ ๋๊ธฐ ๋๋ฌธ์ (์ด๋ฏธ ํด๋ผ์ด์ธํธ์๊ฒ ์ ๋ฌ) ์ฟ ํค๋ ์ธ์ ๊ฐ์ ๋ณ๋์ ์ํ๋ฅผ ๋ด์๋๋ ๋ณด๊ด์๊ฐ ํ์ํ๊ฒ ๋๋ค. ๊ทธ๋ฌ๋, ์ด๋ cost ์ ์ผ๋ก ์๊ฐํด๋ณด์์ ๋ ๋งค์ฐ ๋ญ๋น์ด๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์, requestDispatcher์ forward ๋ฐฉ์์ ์ด์ฉํ๋ฉด ์๋ฒ ๋ด๋ถ์์ ํธ์ถํ ์ ์๋ค.
์ด๋ ํ์ฌ ์์ฒญ์ ์ฒ๋ฆฌ ์ค์ธ ์๋ธ๋ฆฟ์ด ์ํด์๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ๋ฒ์ ๋ด์์ ๋ฒ์๋ฅผ ์กฐ์ ํ ์ ์๋ค!
์ฆ, 1๋ฒ์ HTTP ์์ฒญ ๋ด์์ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํด์ง๋ค.
๐ ํด๋ผ์ด์ธํธ๊ฐ a.jsp ์์ฒญ -> ์๋ฒ ๋ด๋ถ์์ forward๋ฅผ ํตํด b.jsp ํธ์ถ -> ํด๋ผ์ด์ธํธ์๊ฒ b.jsp ๊ฒฐ๊ณผ ์๋ต.
[MemberListController.java] - ํ์ ๋ชฉ๋ก ์ปจํธ๋กค๋ฌ
public class MemberListController implements SMemberController{
private final SMemberRepository repository
= SMemberRepository.getRepository();
@Override
public void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<SMember> members = repository.findAll();
request.setAttribute("members", members);
String viewPath = "/WEB-INF/views/members.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
[FrontController.java] - ํ๋ก ํธ ์ปจํธ๋กค๋ฌ
@WebServlet(name = "frontController", urlPatterns = "/front-controller/*")
public class FrontController extends HttpServlet {
private Map<String, SMemberController> controllerMap
= new HashMap<>();
public FrontController() {
controllerMap.put("/front-controller/members/new-form", new
MemberFormController());
controllerMap.put("/front-controller/members/save", new
MemberSaveController());
controllerMap.put("/front-controller/members", new
MemberListController());
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("FrontController.service");
String requestURI = req.getRequestURI();
SMemberController controller = controllerMap.get(requestURI);
if(controller == null) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
controller.process(req, resp);
}
}
- ControllerMap์ ๋์๋ค. key๋ ๋งคํ URL์, value๋ ํธ์ถ๋ ์ปจํธ๋กค๋ฌ๋ฅผ ์๋ฏธํ๋ค.
- controller๊ฐ ์๋ ๊ฒฝ์ฐ 404, ์๋ค๋ฉด process๋ฅผ ํตํด ์ปจํธ๋กค๋ฌ๋ฅผ ์คํํด์ฃผ์๋ค.
๐ฉ ์ฐธ๊ณ ๋ก, FrontController์ ๊ฒฝ์ฐ ์๋ธ๋ฆฟ ์ปจํ ์ด๋์ ๋ฑ๋ก๋ ๋ ์์ฑ์๊ฐ ํธ์ถ๋์ด ๊ฐ์ฒด๊ฐ ๋ง๋ค์ด์ง๋ค๊ณ ์ดํดํ๋ฉด ๋๋ค :)
/front-controller/members/new-form
/front-controller/members/save
/front-controller/members
- ๋ชจ๋ ๋ค ์ ๋์ํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค. (์ค์๋ก 2๋ฒ ๋ฑ๋กํด์ ๊ฐ์ ๊ฒ 2๋ฒ์ฉ ๋ค์ด๊ฐ๋ค...ใ ใ )
โ V2 - View ์ด๋ ๋ถ๋ฆฌํ๊ธฐ
- ์ด์ ์ V1 ๊ฐ์ ๊ฒฝ์ฐ viewPath๋ฅผ ์ง์ ํ์ฌ RequestDispatcher๋ฅผ ํ์ฉํด ๋ทฐ๋ก ์ด๋์์ผฐ๋ค.- ๋ค๋ง, ์ฝ๋๊ฐ ๋ค ์ค๋ณต๋๋ ๋ถ๋ถ์ด๊ธฐ ๋๋ฌธ์ ์๋นํ ๋ถํธํ๋ค. ์ด์ ๋ํด ๋ฐ๋ก ์ฒ๋ฆฌํ๋ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด๋ณด์!
[MyView.java]
public class MyView {
private String viewPath;
public MyView(String viewPath) {
this.viewPath = viewPath;
}
public void render(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
- render()๋ผ๋ ํจ์๋ฅผ ๋ฐ๋ก ๋ง๋ค์ด์ ๊ณตํต์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๊ฒ ๋์๋ค.
[SMemberController.java] - ์์
public interface SMemberController {
MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
[MemberFormController.java] - ์์
public class MemberFormController implements SMemberController{
@Override
public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
return new MyView("/WEB-INF/views/new-form.jsp");
}
}
- viewPath๋ฅผ ๋๊ฒจ์ฃผ๋ MyView ๊ฐ์ฒด๋ฅผ ์๋กญ๊ฒ ์์ฑํ์๋ค. frontController์์ ํด๋น myView ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ์ฌ render๋ฅผ ์คํํ ์์ ์ด๋ค.
- ๋ง์ฐฌ๊ฐ์ง๋ก ๋จ์ ํ์ผ๋ค๋ ์์ ํด๋ณด์.
[MemberSaveController.java] - ์์
public class MemberSaveController implements SMemberController {
private final SMemberRepository repository
= SMemberRepository.getRepository();
@Override
public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
SMember member = new SMember(username, age);
repository.save(member);
request.setAttribute("member", member);
return new MyView("/WEB-INF/views/save-result.jsp");
}
}
[MemberListController.java] - ์์
public class MemberListController implements SMemberController {
private final SMemberRepository repository
= SMemberRepository.getRepository();
@Override
public MyView process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<SMember> members = repository.findAll();
request.setAttribute("members", members);
return new MyView("/WEB-INF/views/members.jsp");
}
}
[FrontController.java] - ์์
@WebServlet(name = "frontController", urlPatterns = "/front-controller/*")
public class FrontController extends HttpServlet {
private Map<String, SMemberController> controllerMap
= new HashMap<>();
public FrontController() {
controllerMap.put("/front-controller/members/new-form", new
MemberFormController());
controllerMap.put("/front-controller/members/save", new
MemberSaveController());
controllerMap.put("/front-controller/members", new
MemberListController());
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("FrontController.service");
String requestURI = req.getRequestURI();
SMemberController controller = controllerMap.get(requestURI);
if(controller == null) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
MyView view = controller.process(req, resp);
view.render(req, resp);
}
}
- controller.process()๋ฅผ ํตํด service() ํจ์๋ก ๋ฆฌํด๋ฐ์ MyView ๊ฐ์ฒด๋ฅผ ์ด์ฉํ์ฌ .render()๋ฅผ ํธ์ถํด ๋ทฐ๋ฅผ ๊ทธ๋ ค์ฃผ์๋ค.
- ๋ง์ฐฌ๊ฐ์ง๋ก ์คํํด๋ณด๋ฉด ์ ๋์ํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
โ V3 - Model ์ถ๊ฐํ๊ธฐ
- V2์์ ์ค๋ณต์ ์ ๊ฑฐํด์ ๊ฐ ์ปจํธ๋กค๋ฌ์ ์ฝ๋๊ฐ ์๋นํ ๊น๋ํด์ก๋ค.
- ํ์ง๋ง, HttpServletRequest / Response๋ฅผ ๋ด๋ถ์ ์ผ๋ก ๊ผญ ์ฌ์ฉ์ ํด์ผ ํ ๊น?
- ๋ฌผ๋ก , ํ์ํ ๊ฒฝ์ฐ๊ฐ ์์ ์ ์๊ฒ ์ง๋ง, ์ ํํ๊ฒ๋ ํ๋ผ๋ฏธํฐ ์ ๋ณด๊ฐ ํ์ํ ๊ฒ์ด์ง, req/resp๊ฐ ํ์ํ ๊ฒ์ ์๋๋ค.
- req ๊ฐ์ฒด๋ฅผ Model๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ์๋๋ผ, ๋ณ๋์ Model ๊ฐ์ฒด๋ฅผ ์์ฑํด์ ๋ฐํํด๋ณด์.
- ์ด๋ ๊ฒ ํ๋ฉด ์ปจํธ๋กค๋ฌ๊ฐ ์๋ธ๋ฆฟ์ ์ข ์์ ์ด์ง ์์๋ ๋๊ธฐ ๋๋ฌธ์ ์ฝ๋๊ฐ ๋ ๋จ์ํด์ง๋ค.
- ์ถ๊ฐ์ ์ผ๋ก, View์ ์ด๋ฆ์ด ์ค๋ณต๋๋ ๋ถ๋ถ์ด ์๊ธฐ ๋๋ฌธ์ (/WEB-INF/views) ๋ทฐ์ ๋ ผ๋ฆฌ ์ด๋ฆ์ ๋ฐํํ๋๋ก ํด๋ณด์.
[ModelView.java]
@Getter @Setter
public class ModelView {
private String viewName;
private Map<String, Object> model = new HashMap<>();
public ModelView(String viewName) {
this.viewName = viewName;
}
}
- ๋ทฐ์ ์ด๋ฆ๊ณผ ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ํจ๊ป ๊ฐ์ง๊ณ ์๋ค๋ ์๋ฏธ๋ก ModelView๋ผ๋ ์ด๋ฆ์ ์ง์๋ค.
- ๋ชจ๋ธ์ ๋ฐ์ดํฐ๋ ํ๋ผ๋ฏธํฐ ๋ค์ - ์ค์ ๊ฐ ํํ๋ก map์ ์ ์ฅํด์ฃผ๋ฉด ๋๋ค.
[SMemberController.java] - ์์
public interface SMemberController {
ModelView process(Map<String, String> paramMap);
}
- ์ด๋ฒ์๋ ModelView๋ฅผ ๋ฆฌํดํ๋๋ก ๋ณ๊ฒฝํ์๋ค. ๋ํ, ํ๋ผ๋ฏธํฐ๋ก ๋ ์ด์ ์๋ธ๋ฆฟ ๊ธฐ์ ์ ์ฌ์ฉํ์ง ์๋๋ค!
- HttpServletRequest๋ฅผ model๋ก ์ฌ์ฉํ์ง ์๊ณ , paramMap์ ์ด์ฉํด์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ฌํด์ฃผ์.
[MemberFormController.java] - ์์
public class MemberFormController implements SMemberController{
@Override
public ModelView process(Map<String, String> paramMap) {
return new ModelView("new-form");
}
}
- ์ด๋ฐ ์์ผ๋ก view์ ๋ ผ๋ฆฌ์ ์ธ ์ด๋ฆ์ ๋ฆฌํดํ๋๋ก ๋ณ๊ฒฝํ์๋ค.
[MemberSaveController.java] - ์์
public class MemberSaveController implements SMemberController {
private final SMemberRepository repository
= SMemberRepository.getRepository();
@Override
public ModelView process(Map<String, String> paramMap) {
String username = paramMap.get("username");
int age = Integer.parseInt(paramMap.get("age"));
SMember member = new SMember(username, age);
repository.save(member);
ModelView mv = new ModelView("save-result");
mv.getModel().put("member", member);
return mv;
}
}
- ํ๋ผ๋ฏธํฐ ์ ๋ณด๋ฅผ map์์ ๊บผ๋ด์ ์ฌ์ฉํ ์ ์๋ค.
- ๋ทฐ์๊ฒ ํ์ํ ์ ๋ณด๋ฅผ ์ ๋ฌํด์ฃผ๊ธฐ ์ํด ModelView์ model ํ๋์ put์ ํตํด ์ง์ด๋ฃ๋ ์์ผ๋ก ์งํํ์๋ค.
[MemberListController.java] - ์์
public class MemberListController implements SMemberController {
private final SMemberRepository repository
= SMemberRepository.getRepository();
@Override
public ModelView process(Map<String, String> paramMap) {
List<SMember> members = repository.findAll();
ModelView mv = new ModelView("members");
mv.getModel().put("members", members);
return mv;
}
}
[FrontController.java] - ์์
@WebServlet(name = "frontController", urlPatterns = "/front-controller/*")
public class FrontController extends HttpServlet {
private Map<String, SMemberController> controllerMap
= new HashMap<>();
public FrontController() {
controllerMap.put("/front-controller/members/new-form", new
MemberFormController());
controllerMap.put("/front-controller/members/save", new
MemberSaveController());
controllerMap.put("/front-controller/members", new
MemberListController());
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("FrontController.service");
String requestURI = req.getRequestURI();
SMemberController controller = controllerMap.get(requestURI);
if(controller == null) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
Map<String, String> paramMap = createParamMap(req);
ModelView mv = controller.process(paramMap);
String viewName = mv.getViewName();
MyView view = viewResolver(viewName);
view.render(mv.getModel(), req, resp);
}
private Map<String, String> createParamMap(HttpServletRequest req) {
Map<String, String> paramMap = new HashMap<>();
req.getParameterNames().asIterator()
.forEachRemaining(paramName -> {
paramMap.put(paramName, req.getParameter(paramName))
});
return paramMap;
}
private MyView viewResolver(String viewName) {
MyView view = new MyView("/WEB-INF/views/" + viewName + ".jsp");
return view;
}
}
createParamMap์ด๋ผ๋ ํจ์๋ฅผ ๋ฐ๋ก ๋์ด์ HttpServletRequest์ ์๋ ํ๋ผ๋ฏธํฐ ์ ๋ณด๋ฅผ ๊บผ๋ด ๋งต์ ๋ด์๋ค.
์ฆ, ํด๋ผ์ด์ธํธ์ ์์ฒญ URL๊ณผ ํ๋ผ๋ฏธํฐ๊ฐ request์ ๋ด๊ฒจ์๋๋ฐ, ์ด๋ฅผ ๊บผ๋ด์ ์ด๋ค๋ ๊ฒ!
: ์ฐธ๊ณ ๋ก, asIterator().forEachRemaining()์ ์ฐ๋ ์ด์ ๋ req.getParameterNames()๋ฅผ ํ์ ๋ ๋์ค๋ ํ์ ์ด Enumerationํ์ด์ด์ ๊ทธ๋ ๋ค.
๋ง๋ ๋งต์ controller.process()๋ฅผ ์ด์ฉํด์ ์ ๋ฌํ์์ผ๋ฉฐ, ๋ฐํ ๊ฒฐ๊ณผ๋ก ๋์จ ModelView ๊ฐ์ฒด์์ ๋ ผ๋ฆฌ viewName์ ๊บผ๋ด์ค๋ค.
์ดํ, ๊บผ๋ธ viewName์ ์ถ๊ฐ์ ์ผ๋ก ๋ฌผ๋ฆฌ ๊ฒฝ๋ก๋ฅผ ์ค์ ํด์ฃผ์์ผ๋ฉฐ, ์ด๋ฅผ viewResolver๋ผ๋ ์ด๋ฆ์ผ๋ก ์ง์๋ค!
[MyView.java] - ์์
public class MyView {
private String viewPath;
public MyView(String viewPath) {
this.viewPath = viewPath;
}
public void render(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// model.forEach((key, value) -> request.setAttribute(key, value));
model.forEach(request::setAttribute);
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
๋ค์๊ณผ ๊ฐ์ด model์ ๋ด๊ธด ํ๋ผ๋ฏธํฐ๋ฅผ request์ setAttribute๋ฅผ ํตํด view์๊ฒ ๋๊ฒจ์ค๋ค.
์ด๋, ๋๋ค์์ ์ฌ์ฉํด์ฃผ๋ฉด ๋ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ค. - ๋ง์ฐฌ๊ฐ์ง๋ก ๋์ผํ๊ฒ ๊ฒฐ๊ณผ๊ฐ ๋์ค๋ ๊ฑธ ๋ณผ ์ ์๋ค!
โ V4 - ๋จ์ํ ๊ฒ ์ข์!
- V3 ๋ฒ์ ์ ๊ฒฝ์ฐ ์ค๊ณ๊ฐ ์ ๋์ด ์๋ค. ๋ค๋ง, ์ฝ๋๊ฐ ๋น๊ต์ ๋ณต์กํ๊ณ ModelView๋ฅผ ๊ฐ๋ฐ์๊ฐ ๊ณ์ ๋ง๋ค์ด์ค์ผ ํ๋ค๋ ์ ์ด ๋จ์ ์ด๋ค.
- ๊ทธ๋ ๊ธฐ ๋๋ฌธ์, ์ฐ๋ฆฌ๋ ์ ์ฝ๋๋ฅผ ์กฐ๊ธ ๋ ๋จ์ํ์์ผ๋ณด์.
- ModelView ๋์ ViewName๋ง ๋ฐํํ๋๋ก ์ค๊ณํ ๊ฒ์ด๋ค.
[SMemberController.java] - ์์
public interface SMemberController {
String process(Map<String, String> paramMap, Map<String, Object> model);
}
- ๋ฐํํ์ String์ผ๋ก ๋ฐ๊พธ์์ผ๋ฉฐ, model ๊ฐ์ฒด๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ๋๋ก ๋ณ๊ฒฝํ์๋ค.
[MemberFormController.java] - ์์
public class MemberFormController implements SMemberController{
@Override
public String process(Map<String, String> paramMap, Map<String, Object> model) {
return "new-form";
}
}
- new-form์ด๋ผ๋ ๋ ผ๋ฆฌ ์ด๋ฆ๋ง ๋ฐํํ๋๋ก ๋ณ๊ฒฝํ์๋ค.
[MemberSaveController.java] - ์์
public class MemberSaveController implements SMemberController {
private final SMemberRepository repository
= SMemberRepository.getRepository();
@Override
public String process(Map<String, String> paramMap, Map<String, Object> model) {
String username = paramMap.get("username");
int age = Integer.parseInt(paramMap.get("age"));
SMember member = new SMember(username, age);
repository.save(member);
model.put("member", member);
return "save-result";
}
}
- ๊ธฐ์กด์๋ ModelView ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ๊ทธ ๋ด๋ถ์ ์๋ model ๊ฐ์ ๋ฃ์ด์ฃผ๋ ์์ผ๋ก ์งํํ์๋ค๋ฉด, ์ด์ ๋ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ๋ฐ์ model์ ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค. ๋ํ, ๋ง์ฐฌ๊ฐ์ง๋ก ๋ทฐ์ ๋ ผ๋ฆฌ ์ด๋ฆ๋ง ๋ฐํํด์ฃผ์๋ค.
[MemberListController.java] - ์์
public class MemberListController implements SMemberController {
private final SMemberRepository repository
= SMemberRepository.getRepository();
@Override
public String process(Map<String, String> paramMap, Map<String, Object> model) {
List<SMember> members = repository.findAll();
model.put("members", members);
return "members";
}
}
[FrontController.java] - ์์
@WebServlet(name = "frontController", urlPatterns = "/front-controller/*")
public class FrontController extends HttpServlet {
private Map<String, SMemberController> controllerMap
= new HashMap<>();
public FrontController() {
controllerMap.put("/front-controller/members/new-form", new
MemberFormController());
controllerMap.put("/front-controller/members/save", new
MemberSaveController());
controllerMap.put("/front-controller/members", new
MemberListController());
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("FrontController.service");
String requestURI = req.getRequestURI();
SMemberController controller = controllerMap.get(requestURI);
if(controller == null) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
Map<String, String> paramMap = createParamMap(req);
Map<String, Object> model = new HashMap<>();
String viewName = controller.process(paramMap, model);
MyView view = viewResolver(viewName);
view.render(model, req, resp);
}
private Map<String, String> createParamMap(HttpServletRequest req) {
Map<String, String> paramMap = new HashMap<>();
req.getParameterNames().asIterator()
.forEachRemaining(paramName -> {
paramMap.put(paramName, req.getParameter(paramName));
});
return paramMap;
}
private MyView viewResolver(String viewName) {
return new MyView("/WEB-INF/views/" + viewName + ".jsp");
}
}
- ์ด์ ๊ณผ ๋ฌ๋ผ์ง ์ ์ model ๊ฐ์ฒด๋ฅผ ์ฌ๊ธฐ์์ ๋ง๋ค์ด์ ๋๊ฒจ์ค๋ค๋ ์ ๊ณผ,
์ปจํธ๋กค๋ฌ์ ์คํ๊ฒฐ๊ณผ๋ก ๋ฆฌํด๋ฐ์ viewName์(๋ ผ๋ฆฌ ์ด๋ฆ) viewResolver์ ์ ๋ฌํด์ค๋ค๋ ์ ์ด๋ค.
- ๋ง์ฐฌ๊ฐ์ง๋ก ์ด์ ๊ณผ ๋์ผํ๊ฒ ์ ์คํ๋๋ค :D
โ V5 - ์ฌ๋ฌ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์ ์๋๋ก ๋ง๋ค๊ธฐ
- ์ฐ๋ฆฌ๊ฐ ์ง๊ธ๊น์ง ๊ฐ๋ฐํ๋ ๋ฐฉ๋ฒ์ ํผ์ฉํ๊ณ ์ถ๋ค๋ฉด ์ด๋ป๊ฒ ํ๋ฉด ์ข์๊น?
- "์ด๋ํฐ ํจํด"์ ํ์ฉํ์ฌ ๋ค์ํ ๋ฐฉ์์ ์ปจํธ๋กค๋ฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค!
- ์ค๊ฐ์ ํธ๋ค๋ฌ ์ด๋ํฐ๋ฅผ ๋์ด ๋ค์ํ ์ข ๋ฅ์ ์ปจํธ๋กค๋ฌ๋ฅผ ํธ์ถํ ์ ์๋๋ก ํ๊ณ , ์ฐ๋ฆฌ๊ฐ ์ง๊ธ๊น์ง ๊ฐ๋ฐํ์๋ ์ปจํธ๋กค๋ฌ๋ฅผ ์ผ์ข ์ 'ํธ๋ค๋ฌ'๋ผ๊ณ ์๊ฐํ์.
[MyHandlerAdapter.java]
public interface MyHandlerAdapter {
boolean supports(Object handler);
ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws ServletException, IOException;
}
- supports() ๋ฉ์๋๋ฅผ ๋์ด์ ํ๋ผ๋ฏธํฐ๋ก ํธ๋ค๋ฌ๋ฅผ ๋ฐ์๋ค.
- ์ด๋, ์ด๋ํฐ๊ฐ ํด๋น ์ปจํธ๋กค๋ฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋์ง ํ๋จํ๋ ๋ฉ์๋์ด๋ค.
- ์ด๋ํฐ๋ ์ค์ ์ปจํธ๋กค๋ฌ๋ฅผ ํธ์ถ ํ ๊ฒฐ๊ณผ๋ก ModelView๋ฅผ ๋ฐํํ๋ค. ์ปจํธ๋กค๋ฌ๊ฐ ๋ฐํํ์ง ๋ชปํ๋ฉด ์ด๋ํฐ๊ฐ ์ง์ ์์ฑํด์ ๋ฐํํ๋ค.
- ์ด์ ์๋ ํ๋ก ํธ ์ปจํธ๋กค๋ฌ๊ฐ ์ค์ ์ปจํธ๋กค๋ฌ๋ฅผ ํธ์ถํ์ง๋ง, ์ด์ ๋ ์ด๋ํฐ๋ฅผ ํตํด ์ปจํธ๋กค๋ฌ๋ฅผ ํธ์ถํ๋ค.
[ControllerV3HandlerAdapter.java]
public class ControllerV3HandlerAdapter implements MyHandlerAdapter{
@Override
public boolean supports(Object handler) {
return (handler instanceof ControllerV3); // ์ด๋ฐ ์์ผ๋ก!
}
@Override
public ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
SMemberController controller = (SMemberController) handler;
Map<String, String> paramMap = createParamMap(request);
ModelView mv = controller.process(paramMap);
return mv;
}
private Map<String, String> createParamMap(HttpServletRequest request) {
Map<String, String> paramMap = new HashMap<>();
request.getParameterNames().asIterator()
.forEachRemaining(paramName -> paramMap.put(paramName,
request.getParameter(paramName)));
return paramMap;
}
}
- ์ด๋ฐ ์์ผ๋ก ์ํ๋ Controller์ ๋ง์ถฐ์ ์ฒ๋ฆฌํ๋๋ก ๋๊ฒจ์ฃผ๋ฉด ๋๋ค.
(V3, V4์ ๋ง๋๋ก ๊ฐ์๋ผ์ด๋ค๊ณ ์๊ฐํด์ฃผ๋ฉด ๋ ๊ฒ ๊ฐ๋ค)
[ControllerV4HandlerAdapter.java]
public class ControllerV4HandlerAdapter implements MyHandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof ControllerV4);
}
@Override
public ModelView handle(HttpServletRequest request, HttpServletResponse
response, Object handler) {
ControllerV4 controller = (ControllerV4) handler;
Map<String, String> paramMap = createParamMap(request);
Map<String, Object> model = new HashMap<>();
String viewName = controller.process(paramMap, model);
ModelView mv = new ModelView(viewName);
mv.setModel(model);
return mv;
}
private Map<String, String> createParamMap(HttpServletRequest request) {
Map<String, String> paramMap = new HashMap<>();
request.getParameterNames().asIterator()
.forEachRemaining(paramName -> paramMap.put(paramName,
request.getParameter(paramName)));
return paramMap;
}
}
- ์ฌ๊ธฐ์ ์ค์ํ ์ ์, ๊ธฐ์กด์ viewName๋ง ๋ฐํํ๋ V4์ ํน์ง์ ์ํด์ '์ด๋ํฐ'์์ ModelView ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ๋ฐํํ๋ค๋ ์ ์ด๋ค.
- ํธ๋ค๋ฌ๊ฐ ์๋, ์ด๋ํฐ์์ ModelView๋ฅผ ๋ง๋ค๊ณ setModel์ ํตํด ๋ชจ๋ธ์ ๋ฃ์ด์ฃผ๋ ์ญํ ๊น์ง ํด์ค๋ค.
- ์ฆ, ์ด๋ํฐ๊ฐ ํ์์ ๋ง์ถฐ์ ๋ฐํํด์ฃผ๋ ์ญํ ์ ํ๋ ๊ฒ์ด๋ค!!
[FrontController.java] - ์์
@WebServlet(name = "frontController", urlPatterns = "/front-controller/*")
public class FrontController extends HttpServlet {
private Map<String, SMemberController> handlerMappingMap
= new HashMap<>();
private List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();
public FrontController() {
initHandlerMapping();
initHandlerAdapters();
}
private void initHandlerAdapters() {
handlerAdapters.add(new ControllerV3HandlerAdapter());
handlerAdapters.add(new ControllerV4HandlerAdapter());
}
private void initHandlerMapping() {
// V3
handlerMappingMap.put("/front-controller/members/new-form", new
MemberFormController());
handlerMappingMap.put("/front-controller/members/save", new
MemberSaveController());
handlerMappingMap.put("/front-controller/members", new
MemberListController());
// V4
handlerMappingMap.put("/front-controller/v5/v4/members/new-form", new
MemberFormControllerV4());
handlerMappingMap.put("/front-controller/v5/v4/members/save", new
MemberSaveControllerV4());
handlerMappingMap.put("/front-controller/v5/v4/members", new
MemberListControllerV4());
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object handler = getHandler(req);
if(handler == null) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
MyHandlerAdapter adapter = getHandlerAdapter(handler);
ModelView mv = adapter.handle(req, resp, handler);
MyView view = viewResolver(mv.getViewName());
view.render(mv.getModel(), req, resp);
}
private Object getHandler(HttpServletRequest request) {
String requestURI = request.getRequestURI();
return handlerMappingMap.get(requestURI);
}
private MyHandlerAdapter getHandlerAdapter(Object handler) {
for (MyHandlerAdapter adapter : handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
throw new IllegalArgumentException("handler adapter๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. handler=" + handler);
}
private MyView viewResolver(String viewName) {
return new MyView("/WEB-INF/views/" + viewName + ".jsp");
}
}
- handlerMappingMap์ URI๊ณผ ๋งคํ๋ ํธ๋ค๋ฌ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ๊ณ ์๋ค.
- getHandler๋ฅผ ํตํด์ ํธ๋ค๋ฌ ๋งคํ ์ ๋ณด์ธ handlerMappingMap์์ URI์ ๋งคํ๋ ํธ๋ค๋ฌ๋ฅผ ์ฐพ์์ ๋ฐํํ๋ค.
- getHandlerAdapter์์ support ๋ฉ์๋๋ก ํด๋น ํธ๋ค๋ฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ ์ด๋ํฐ๋ฅผ ์ฐพ๋๋ค.
- ๋ฐํ๋ฐ์ ์ด๋ํฐ๋ฅผ ์ด์ฉํด handle ๋ฉ์๋๋ก ์ค์ ํธ๋ค๋ฌ๊ฐ ํธ์ถ๋๊ณ , ํ๋ก์ธ์ค๋ฅผ ์ฒ๋ฆฌํ ๊ฒฐ๊ณผ์ธ ModelView๋ฅผ ๋ฐํ๋ฐ๋๋ค.
- ์ฐ๋ฆฌ๋ V1~V5๊น์ง ์ ์ง์ ์ผ๋ก ๋ฐ์ ์์ผ๋๊ฐ๋ฉฐ MVC ๊ตฌ์กฐ๋ฅผ ์ตํ๋ค.
- ์ฌ๊ธฐ์ ๋๋ถ์ด์, ์ด๋ ธํ ์ด์ ์ ํ์ฉํ๋ฉด ์ปจํธ๋กค๋ฌ๋ฅผ ๋ ๋ฐ์ ์ํฌ ์ ์๋ค!
- ์ด์ ์คํ๋ง์์ MVC๋ฅผ ์ด๋ป๊ฒ ์ง์ํ๋์ง ํ์ธํด๋ณด์.