Day49

2020. 12. 9. 11:22교육과정/KOSMO

키워드 : MVC 실습(1) / MVC 실습(2) 

 

 

****

 

※ MVC를 사용하는 이유 : url을 통해 파일 경로를 추적하지 못하게 하면서, 리소스는 제공하기 위함

※ MVC패턴에서는 자바빈즈 사용 불가! (<jsp:useBean> 사용하여 데이터 넘기지 못한다.)

 

<<< MVC 실습 (1) >>>

0. 화면이 될 start.jsp 파일을 만들고 화면에 띄울 내용 작성

<a href='simpleView.jsp'>기존방식</a><br/>
<a href='/JSP/05_mvc_class/1_mvcSimple/simpleView.jsp'>기존방식</a><br/>

 


1. src에 mvc.simple 패키지를 만들면서 SimpleControl.java 라는 이름의 서블릿 파일 생성 

   → 서블릿파일은 Controller 역할을 한다.

   (헷갈리지 않도록 주석은 모두 지운다. )

 

 


2. SimpleControl.java 서블릿 파일에서 메소드를 작성

   (1) doPost( ) 메소드를 복사하여 아래에 붙여넣은 뒤 메소드 명을 processRequest( ) 메소드로 변경한다. 

protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
}

   (2) 이후 doGet( ) 메소드와 doPost( ) 메소드 모두 processRequest( ) 메소드를 호출하도록 메소드 내용을 수정한다.

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    processRequest(request, response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    processRequest(request, response);
}

 


3. WEB-INF 폴더 내의 web.xml 파일에서 작업

   (1) 서블릿 클래스 동륵에 관한 스크립트를 복사하여 2 에서 작성한 서블릿의 정보로 수정하여 작성 후 저장한다. 

<servlet>
    <servlet-name>SimpleControl</servlet-name>   <!-- 3 -->
    <servlet-class>mvc.simple.SimpleControl</servlet-class>   <!--4 -->
</servlet>
<servlet-mapping>
    <servlet-name>SimpleControl</servlet-name>   <!-- 1 -->
    <url-pattern>/simple</url-pattern>   <!-- 2 -->
</servlet-mapping>

   (2) 결국, simple 이라는 이름을 통해 SimpleControl이라는 이름의 서블릿을 찾고,

       해당 서블릿이 SimpleControl.java 파일을 수행하게 된다. 

 

 


4. SimpleControl.java 파일에서 processRequest( ) 메소드를 작성

   (1) 사용자로부터 요청값 얻어오기

String type = request.getParameter("type");

 

   (2) 사용자 요청값에 따라 알맞은 기능을 수행

String value = "";
if (type == null) value = "안녕하세요";
else if (type.equals("first")) value = "반갑습니다";

 

   (3) 처리 결과를 request나 session에 저장

request.setAttribute("param", value);

 

   (4) 결과 페이지(뷰페이지)로 포워딩

       → 아래의 스크립트는 자바빈즈의 포워딩 액션태그 <jsp:forward page='simplevVew.jsp'>와 동일한 역할을 한다. 

RequestDispatcher dispatcher = request.getRequestDispatcher(jspDir + "simpleView.jsp");
dispatcher.forward(request, response);

 

   (5) start.jsp 파일 내에 MVC 방식으로 페이지를 여는 <a> 태그를 작성한다. 

<a href='/JSP/simple'>MVC 방식</a><br/>

 

 

 


5. web.xml에서 url 방식을 추가하면서 확장자명을 지정할 수 있다. 

   (1) 새로운 url패턴을 만들어준다. 

<servlet-mapping>
    <servlet-name>SimpleControl</servlet-name>   <!-- 1 -->
    <url-pattern>/simple</url-pattern>   <!-- 2 -->
    <url-pattern>*.jung</url-pattern>
</servlet-mapping>

 

   (2) start.jsp 에서 새로운 방식으로 페이지를 열기 위한 스크립트를 작성한다. 

<a href='/JSP/123.jung'>MVC 방식2</a><br/>

 

 


6. 파일을 바꾸지 않더라도 쿼리스트링의 type값에 따라 화면의 출력내용을 바꿀 수 있다. 

<a href='/JSP/simple'>MVC 방식1</a><br/>
<a href='/JSP/simple?type=first'>MVC 방식2</a><br/>
<a href='/JSP/simple?type=second'>MVC 방식3</a><br/><hr/>

<a href='/JSP/123.jung'>MVC 방식11</a><br/>
<a href='/JSP/123.jung?type=first'>MVC 방식12</a><br/>
<a href='/JSP/123.jung?type=second'>MVC 방식13</a><br/><hr/>

 

String type = request.getParameter("type");

if (type == null) value = "안녕하세요";
else if (type.equals("first")) value = "반갑습니다";

 

 

 


7. request.getParameter() / request.getAttribute() 구별하기

 

getParameter( ) - String 타입 리턴
- 웹 브라우저에서 전송받은 request 영역의 값(파라미터)를 얻어옴

getAttribute( ) - Object 타입 리턴
- setAttribute( ) 속성을 통한 설정이 없으면 무조건 null 값 리턴

 

   (1) start.jsp 에서 파라미터가 지정됨

<a href='/JSP/simple'>MVC 방식1</a><br/>
<a href='/JSP/simple?type=first'>MVC 방식2</a><br/>
<a href='/JSP/simple?type=second'>MVC 방식3</a><br/><hr/>

 

   (2) Simplecontrol.java에서 파라미터(type)에 따라 Attribute(param)가 지정됨

String type = request.getParameter("type");
String value = "";
if (type == null) value = "안녕하세요";
else if (type.equals("first")) value = "반갑습니다";
request.setAttribute("param", value);

 

   (3) simpleView.jsp 에서 getAttribute( ) 값인 param과 getParameter( ) 값인 type을 각각 확인할 수 있음

<%
    Object obj = request.getAttribute("param");
    String str = request.getParameter("type");
%>

 

<body>
	
    <%= str %> || <%= obj %> <br/>

 

 

 




<<< MVC 실습 (2) >>>

 

 

8. Message.java 파일과 MessageDao.java 파일을 확인해보면

   이전에 작성한 GuestTB 을 활용하는 것임을 알 수 있다. 

   DB 드라이버 연결을 위해 IP 정보를 알맞게 수정한다. 

 


9. GuestControl.java 파일에서 확인 가능한 사항

   (1) 생성자함수에서 iniCommant( ) 메소드를 호출하여 Key값에 따라 객체를 생성하여 HashMap에 담아둠

       → 추후 페이지 이동시 Controller에 어떤 Key값을 입력하느냐에 따라 해당되는 객체가 생성되고

           객체에서 DB와 연동되는 Dao의 내부 함수가 실행된다. 

public GuestControl() {
    super();       
    initCommand();
}

private void initCommand(){
    commandMap = new HashMap();

    // Key값에 따라 객체 생성
    commandMap.put("main-page",	new CommandNull("main.jsp") );
    commandMap.put("list-page",	new CommandList("listMessage.jsp") );		
		
}

 

   (2) processRequest( ) 메소드에서는 이전 화면에서 파라미터로 넘어오는 값을

       변수 cmdKey에 저장 후 그 값의 null 여부에 따라 Key값을 새롭게 부여함

        (→ cmd에 대한 입력값이 없을 경우 기본값을 설정해주기 위한 목적으로 생각됨)

String nextPage = "";
String cmdKey	= request.getParameter("cmd");
if( cmdKey == null ){
    cmdKey = "main-page";
}

 

   (3) HashMap 안에 cmdKey와 동일한 값이 있을 경우, 해당 되는 해쉬맵을 가져오도록 get( ) 메소드 수행

       → 가져온 해쉬맵을 Command타입으로 형 변환하여 변수 cmd에 담는다. 

       → cmd에 해당하는 execute( ) 메소드를 호출하고 그 결과를 nextPage라는 String타입 변수에 담는다. 

Command cmd = null;

    try{
			
    if( commandMap.containsKey( cmdKey ) ){
        // 부모변수에 자식객체 넣는것이라 가능함
        cmd = (Command)commandMap.get( cmdKey );
    }else{
        throw new CommandException("지정할 명령어가 존재하지 않음");
    }
    
    // cmd에 해당하는 execute 함수 호출
    nextPage = cmd.execute( request, response  );

 


10. execute( ) 메소드에 관하여

 

   (1) execute( ) 메소드는 인터페이스인 Command.java 파일에서 정의되었으며

      오버라이딩을 위해 메소드 내에서 수행하는 내용이 없는 함수이다. 

      → cmd의 Key값에 따라 각기 다른 역할을 수행하면서 함수명은 동일하게 execeute( )로 사용하기 위함

public interface Command {
    public String execute( HttpServletRequest request, HttpServletResponse response  ) throws CommandException;
}

 

   (2) CommandNull.java  / CommandList.java / CommandInput.java / CommandDelete.java에서

       인터페이스인 Command.java파일을 상속한다. 

 

   (3) (2)의 java파일들마다 각기 다른 작업을 수행하는 execute( ) 메소드를 오버라이딩하여 정의한다. 

// CommandNull.java에서
return next;

// CommandList.java에서
MessageDao.getInstance().selectList();

// CommandInput.java에서
MessageDao.getInstance().insert(msg);

// CommandDelete.java에서
MessageDao.getInstance().delete(messageId, password);

 

   (4) 결과적으로 Controller에서 execute( ) 메소드 하나만 호출해도 다양한 작업을 수행하는 구조를 만들 수 있게 된다.

        → 코드가 심플해짐!

 

 


11. web.xml 파일에서 서블릿 클래스를 등록

    ① 서블릿 클래스의 별칭(alias)을 설정한다. 

    ② URL에 서블릿의 이름을 연결(매핑)한다. 

    ③ 서블릿 클래스의 별칭에 해당되는 서블릿 파일 (Controller)의 경로를 지정한다. 

<servlet>
    <servlet-name>GuestControl</servlet-name>                       <!-- 3 -->
    <servlet-class>mvc.guest.control.GuestControl</servlet-class>   <!-- 4 -->
</servlet>
<servlet-mapping>
    <servlet-name>GuestControl</servlet-name>                       <!-- 1 -->
    <url-pattern>*.do</url-pattern>
    <url-pattern>/GuestControl</url-pattern>                        <!-- 2 -->
</servlet-mapping>

 


12. 메인화면(main.jsp)에서 목록보기 페이지(listMessage.jsp)로 이동하기

 

(1) "방명록"이라는 텍스트는 <a> 태그로 하이퍼링크가 생성되어있다. 

<% String projectName = "/JSP"; %>    
...
<body>
<a href="<%= projectName %>/GuestControl?cmd=list-page"> 방명록 </a>

<a> 태그에서 완성되는 하이퍼링크 주소 : href="/JSP/GuestControl?cmd=list-page" 

→ 컨트롤러를 거쳐서 페이지를 이동하게 된다. 

 

(2) 메인화면을 거치지 않고 목록보기 페이지를 바로 실행할 경우,

    컨트롤러를 통해 불러와야 하는 데이터가 없으므로 목록이 출력되지 않는다. 

    즉, MVC구조를 사용하면 메인 화면을 거치지 않고 접속했을 때(개발자가 지정한 경로를 벗어난 경우) 

    화면 출력이 되지 않도록 만들 수 있다. 

<%
    List <Message> mList = (List <Message>)request.getAttribute("param");  
%>
...
<body>
<% if( mList == null ) { %>
    남겨진 메세지가 하나도~~없습니다. <br>
<% } %>

 

(3) 메인화면에서 "방명록" 하이퍼링크를 클릭하면 cmd=list-page라는 key=value를 가지고 컨트롤러로 넘어가서

<a href="<%= projectName %>/GuestControl?cmd=list-page"> 방명록 </a>

    CommandList.java 객체를 생성하면서 다음페이지가 될 파일명을 인자로 가져간다. 

private void iniCommand(){
    ....
    commandMap.put("list-page",	new CommandList("listMessage.jsp") );
}

    key값이 null이 아니므로, key값에 해당되는 CommandList.java 파일의 execute( ) 메소드를 호출한다. 

private void processRequest( ....
    ....
    cmd = (Command)commandMap.get( cmdKey);
    ....
    nextPage = cmd.execute( request, response  );

 

(4) 서블릿의 내장객체인 RequestDispatcher를 사용하여 다음 페이지로 포워딩 해준다. 

    ※ RequestDisparcher 클래스

     : 클라이언트로부터 최초에 들어온 요청을 JSP/Servlet 내에서 원하는 자원으로 보내는 역할을 수행하거나,

       특정 자원에 처리를 요청하고 처리 결과를 얻어오는 기능을 수행하는 클래스

RequestDispatcher reqDp = getServletContext().getRequestDispatcher( jspDir + nextPage );
reqDp.forward( request, response );

 

(5) CommandList.java 파일의 execute( ) 메소드에서는 MessageDao.java의 selectList( ) 메소드를 호출하고

    그 결과를 List타입 변수 mList에 지정한다. 

    mList에 담긴 데이터는 "param"이라는 이름으로 setAttribute 하여 ListMessage.jsp 페이지로 전달한다. 

public String execute(...) {
    ....
    List <Message> mList = MessageDao.getInstance().selectList();
    request.setAttribute("param", mList );

 

<%
    List <Message> mList = (List <Message>)request.getAttribute("param"); 
%>

 

(6) MessageDao.java의 selectList( ) 메소드는 DB에서 게시글 번호의 역순으로 목록 정보를 가져와서 mList에 지정한다. 

public List<Message> selectList() throws MessageException {
    ....
    boolean isEmpty = true;
    ....
    String sql = "SELECT * FROM guestTB order by message_id desc";
    while( rs.next()) {
        isEmpty = false;
        int message_id = rs.getInt("message_id");
        String guest_name = rs.getString("guest_name");
        String password = rs.getString("password");
        String message = rs.getString("message");
        
        Message m = new Message(message_id, guest_name, password, message );
        mList.add(m);
    }
    
    if( isEmpty ) return Collections.emptyList();
    
    return mList;
}

 

(7) ListMessage.jsp 페이지에서는 데이터가 들어있는 mList로부터 목록정보를 화면에 출력한다. 

<%
    List <Message> mList = (List <Message>)request.getAttribute("param"); 
%>
....
<body>
....
<table border="1">
    <% for( Message msg : mList ) { %>
    <tr>	
        <td> <%= msg.getId() %> </td> 
        <td> <%= msg.getGuestName() %></td> 
        <td> <a href="GuestControl?cmd=delete-form&messageId=<%= msg.getId() %>"> [ 삭제하기 ]</a> </td>			
    </tr>
    <tr>
        <td colspan='3'> 
            <textarea cols=35 rows=3><%= msg.getMessage() %>
            </textarea>
        </td>
    </tr>
    <% } %>
</table>

 

(결과)

 

 

 


13. 목록보기 페이지(listMessage.jsp)에서 방명록 남기기 페이지(insertMessage.jsp)로 이동하기

 

(1) "방명록 남기기" 텍스트에 <a> 태그를 사용하여

     cmd=input-form이라는 key=value를 가지고 컨트롤러로 넘어가도록 작성

<a href="GuestControl?cmd=input-form">방명록 남기기 </a>

 

(2) 컨트롤러 서블릿 파일에서 해쉬맵에 "input-form"이라는 키에

     CommandNull 객체가 생성되면서 인자로 "insertMessage.jsp"를 가져가도록 작성

commandMap.put("input-form", new CommandNull("insertMessage.jsp") );

 

(3) 컨트롤러에서 "input-form"이라는 파라미터로 CommandNull 객체의 execute( ) 메소드를 호출하여

    다음 화면인 "insertMessage.jsp" 페이지로 이동시킨다. 

String cmdKey	= request.getParameter("cmd");
....
nextPage = cmd.execute( request, response  );
....
RequestDispatcher reqDp = getServletContext().getRequestDispatcher( jspDir + nextPage );
reqDp.forward( request, response );

 

(결과)

 


14. 방명록 남기기 페이지(insertMessage.jsp) 의 사용자 입력값을 DB에 입력하기

 

(1) "insertMessage.jsp"의 버튼 클릭 이벤트에서 cmd=input-save라는 key=value로

    <form>의 입력값을 가지고 컨트롤러로 이동한다.

function checkFields(){
    ....
    frmObj.action = "GuestControl?cmd=input-save";
    ....
}
....
<body>
    <form name="frm" method="post">
        이름 : <input type="text" name="guestName"/><br/><br/>
        암호 : <input type="password" name="password"/><br/><br/>
        메세지 : <textarea name="message" rows="3" cols="30"></textarea><br/><br/>
        <input type="button" value="메세지 남기기" onclick="Javascript:checkFields()">
    </form>

 

(2) 컨트롤러의 initCommand( ) 메소드에서 해쉬맵에 "input-form"이라는 키를 가지면서

     CommandNull 객체가 생성될 때 인자로 "insertMessage.jsp"를 가져가도록 작성

commandMap.put("input-save", new CommandInput("saveMessage.jsp") );

 

(3) 컨트롤러에서 "input-save"라는 파라미터로 CommandInput 객체의 execute( ) 메소드를 호출하여

    다음 화면인 "saveMessage.jsp" 페이지로 이동시킨다. 

String cmdKey	= request.getParameter("cmd");
....
nextPage = cmd.execute( request, response  );
....
RequestDispatcher reqDp = getServletContext().getRequestDispatcher( jspDir + nextPage );
reqDp.forward( request, response );

 

(4) CommandInput.java 파일에서 execute( ) 메소드 수행시 사용자 입력값을 Message 객체 msg에 지정하고,  

     MessageDao.java의 insert( ) 메소드의 인자로 넣어 호출한다. 

public String execute( ... ) {
    ....
    Message msg = new Message();
    msg.setGuestName( request.getParameter("guestName"));
    msg.setPassword(request.getParameter("password"));
    msg.setMessage( request.getParameter("message"));
    ....
    MessageDao.getInstance().insert(msg);

 

(5) MessageDao.java 파일에서 insert( ) 메소드를 수행하여 DB에 사용자 입력값을 등록한다. 

public int insert(Message rec) throws MessageException {
    ....
    String sql = "INSERT INTO guestTB VALUES(seq_guestTb_messageId.nextval,?,?,?)"; 
    ....
    ps.setString	( 1, rec.getGuestName()	);
    ps.setString	( 2, rec.getPassword()	);
    ps.setString	( 3, rec.getMessage()	);
    
    ps.executeUpdate();

 

(결과)

 

 


15. "saveMessage.jsp" 페이지에서 목록보기 페이지로 이동하기

 

(1) "saveMessage.jsp" 파일의 "목록보기" 텍스트에 <a>태그를 사용하여

     컨트롤러로 이동시 cmd=list-page라는 파라미터 값을 가져가는 하이퍼링크를 작성

<a href="GuestControl?cmd=list-page"> [ 목록보기 ]</a>

 

(결과)

 

 


16. 삭제하기 차례다~~!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 



사용자가 요청하면 controller(서블릿으로 만듦)가 작동한다.  이후 포워딩 되어 jsp파일이 View단으로 사용자에게 응답가게 된다. 


게시판 MVC 패턴 만들기
- 패키지나 폴더 구조 먼저 새롭게 만들기
- 복사파일 (View / Model)
- 새롭게 만들 부분 - Control (Servelet)
- 수정 부분 (Service -> Command)

1. 주제 선정
- 배경
- 벤치마킹
-Lean Canvas

 

 

 

 

 

 

 

 

반응형

'교육과정 > KOSMO' 카테고리의 다른 글

Day51  (0) 2020.12.11
Day50  (0) 2020.12.10
Day48  (1) 2020.12.08
Day47  (0) 2020.12.07
Day46  (0) 2020.12.04