티스토리 뷰

MVC패턴

컨트롤러(CONTROLLER) : 클라이언트(http)의 요청을 받아서 파라미터를 검증, 비지니스 로직을 실행한다. 그리고 뷰에 전달할 결과 데이터를 조회해서 모델에 담는다

 

모델(MODEL) : 뷰에 출력할 데이터를 담아둔다. 뷰가 필요한 데이터를 모두 모델에 담아 전달해주는 덕분에 뷰는 비지니스 로직이나 데이터 접근을 몰라도 되고 화면을 렌더링 하는 일에 집중할 수 있다

 

뷰(VIEW) : 모델에 담겨있는 데이터를 사용하여 화면을 그림

 

출처 : www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., 원

www.inflearn.com

 

 

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

- 공통 처리가 어렵다

 

↓↓↓

 

이를 해결하기 위해서 컨트롤러로 넘어가기전에 먼저 공통 기능을 처리해야함

결론 : 프론트 컨트롤러로 구현해보기

 

댓글
최근에 올라온 글
최근에 달린 댓글
링크
Total
Today
Yesterday