본문 바로가기
코딩도전기/MVC

CODO Day17_JAVA_MVC(Model2/상속*)

by 코도꼬마 2023. 2. 23.

디자인 패턴

  • 설계문제에 대한 해답을 문서화하기 위해 고안된 방법
  • 소프트웨어 개발과정에서 자주 나타나는 과제를 해결하기 위한 방법
  • 패턴은 특정한 상황에서 구조적인 문제를 해결하는 방식을 설명해 줌

 

주의사항

  • 디자인패턴은 일반적으로 대규모 프로그램 개발에 적합
  • 패턴은 절대적이지 않기 때문에 각 디자인 패턴이 유용한 상황을 알아야 함(상황에 맞게 변형 가능)
  • 패턴의 틀에 갇힌 사고방식은 효율성이 낮은 프로그램을 생산
  • 패턴은 사용하는 것보다 차용 한다고 생각해야 함

 

 

Model 2

  • Java Logic과 JSP를 분리
  • 출력부분만 JSP로 다룸
  • 나머지 데이터 저장 및 JAVA LOGIC부분은 java(class)로 다룸

 

 

MVC(Model View Controller) 패턴(Model 2의 기본적인 디자인 패턴*)

  • 애플리케이션을 세 가지의 역할로 구분
  • 각 파트는 자신이 맡은 역할을 수행
View 유저가 요청하거나 요청한 결과를 보여주는 화면 HTML & JSP
Controller 요청한 내용을 확인하여 해당 업무를 수행할 Model에게 전달 JAVA
Model Controller에서 받은 요청처리반환

 

  • 실생활 예제

 

 

JSP와 MVC 비교

  • JSP

 

  • MVC

 

 

Basic MVC Pattern

  • 기본적인 MVC구조로 jsp와 Java 분리
  • 우선 View(jsp)에서 보내는 내용을 Controller(java)에서 받을 수 있는 기능이 필요
  • Jsp에서 하던 서버의 기능을 JAVA에서 해야 하기 때문에 많은 코드가 필요
  • 많은 기능들을 다 만들어서 사용하기 힘들기 때문에 이미 만들어진 기능들을 상속받아 사용

Package 이름은 사이트 이름으로 지정

 

    # @WebServlet("/")
        - controller class 생성 시 클래스 선언 위치 위쪽에 자동완성으로 선언(자동으로 import됨)
        - web.xml에서 welcome file list에 파일(ex) index.jsp)이 없으면 이쪽으로 와라
        - 해당 class가 controller 역할을 할 것임을 명시
        - ("/") : 'http://localhost:8080/01_controller/'의 마지막 / >> 서버에 접근하면 이 클래스로 와라

    # HttpServlet class(부모 클래스)
    - http(sever)와 java가 RequestResponse를 주고 받을 수 있도록 구현해둔 class
    - JSP에서 사용했던 Request, Response 객체를 java에서 사용할 수 있도록 구현해둔 class

  • MainController.java
package kr.co.web.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/")  

public class MainController extends HttpServlet {
//jsp에서 form태그 작성 시 method값을 post로 지정하지 않으면 get으로 접근함

	//get방식으로 들어오면 이 메서드가 실행
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
		System.out.println("Get으로 접근!");
	}

	//post방식으로 들어오면 이 메서드가 실행
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
		
	}

}

 

 

상속(inherit)* - OOP 4대 특징 중 하나

  • 부모 class를 자신의 class처럼 사용하는 것
  • 이미 만들어진 기능을 상속해서 내 것처럼 쓸 수 있음
  • 상속을 하는 이유
    1. Code의 중복을 피할 수 있음
    2. 내 능력으로는 만들지 못하는 기술을 사용할 수 있음
  • 상속을 위해서는 extends 키워드를 사용
  • 부모클래스에서 private 접근 제한자를 갖는 멤버는 상속 불가능
  • 1개의 클래스만 상속 받을 수 있음(다중상속x)
  • 여러개의 class를 상속받고 싶은 경우 차례대로 하나씩 상속받아 누적시킨 후 하나의 클래스로 합침

 

 

객체화와 상속의 차이점

 

 

  • index.jsp 

        -  index.jsp가 있으면 Controller보다 우선 실행 / index가 없으면 클래스파일로 감

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="./calc" method="post">
		<input type="text" name="su1"/>
		<select name="oper">
			<option value="+">+</option>
			<option value="-">-</option>
			<option value="*">*</option>
			<option value="/">/</option>
		</select>
		<input type="text" name="su2"/>
		<button>계산</button>
	</form>
</body>
</html>

 

  • MainController.java
package kr.co.web.controller;

import java.io.IOException;

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 kr.co.web.model.Calculator;  //model package에 있는 Calculator를 객체화하기 위해 import함

@WebServlet("/calc")  //해당 class가 controller 역할을 할 것임을 명시
public class MainController extends HttpServlet {

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
		
		String su1 = req.getParameter("su1");
		String su2 = req.getParameter("su2");
		String oper = req.getParameter("oper");
		System.out.println(su1 + " " + oper + " " + su2);
		
		//Calculator 객체화
		Calculator cal = new Calculator();
		int result = cal.calculation(Integer.parseInt(su1), Integer.parseInt(su2), oper);
		System.out.println("결과값 : " + result);
	}
}

 

  • Calculator.java   >> Operator2,3,4를 상속받은 Operator를 객체화하여 사용

       -  상속받은 클래스의 멤버는 따로 객체화하지 않고 사용 가능
       -  사용자 입장에서는 각 기능을 쓰기 위해 어떤 클래스들을 객체화해야 하는지 다 알 필요가 없음
       -  상속을 받아도 부모 클래스 객체화 가능

package kr.co.web.model;

public class Calculator {

	public int calculation(int su1, int su2, String oper) {

		int result = 0;

		Operator op = new Operator();
		
		switch (oper) { 
		case "+":
		    //일반적인 객체화를 활용한 방법
//			Operator op = new Operator();
//			result = op.plus(su1, su2);
			result = op.plus(su1, su2);
			break;

		case "-":
//			Operator2 op2 = new Operator2();
//			result = op2.minus(su1, su2);
			result = op.minus(su1, su2);
			break;

		case "*":
//			Operator3 op3 = new Operator3();
//			result = op3.multi(su1, su2);
			result = op.multi(su1, su2);
			break;

		case "/":
//			Operator4 op4 = new Operator4();
//			result = op4.devide(su1, su2);
			result = op.devide(su1, su2);
			break;

		}

		return result;
	}

}

 

  • Operator.java
package kr.co.web.model;

public class Operator extends Operator2{
	
	int plus(int a, int b) {
		return a+b;
	}
}

 

  • Operator2.java
package kr.co.web.model;

public class Operator2 extends Operator3{

	int minus(int a, int b) {
		return a-b;
	}
}

 

  • Operator3.java
package kr.co.web.model;

public class Operator3 extends Operator4{

	int multi(int a, int b) {
		return a*b;
	}
}

 

  • Operator4.java
package kr.co.web.model;

public class Operator4 {

	int devide(int a, int b) {
		return a/b;
	}
}

 

 

 

 

Override*

  • 부모로부터 물려 받은 method를 변경하여 사용할 수 있음
  • final{readOnly} 키워드가 있는 메서드는 불가능

  • index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="./car" method="get">
		자동차를
			<select name="action">
				<option value="start">시동건다</option>
				<option value="stop">멈춘다</option>
				<option value="run">달린다</option>
				<option value="turbo">터보를 사용한다</option>
				<option value="test">정비한다</option>
			</select>
			<button>실행</button>
	</form>
	${result} <!-- server에서 보낸 내용 출력 -->
</body>
</html>

 

  • MainController.java
package kr.co.web.controller;

import java.io.IOException;

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 kr.co.web.model.MyCar;

@WebServlet("/car")
public class MainController extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
		//부모가 준 기능을 버리고 내가 스스로 만들 것이다
		//확인사항 1.View에서 오는 파라메터 확인(콘솔로)
		String action = req.getParameter("action");
		System.out.println("action 파라메터 : " + action);

		String result = "";
		MyCar car = new MyCar();

		switch (action) {
		case "start":
			result = car.start();
			break;

		case "stop":
			result = car.stop();
			break;

		case "run":
			result = car.run();
			break;

		case "turbo":
			car.turbo = true;
			result = car.run();
			break;

		case "test":
			result = car.test();
			break;
		} 
		
		//result변수에 담긴 값을 View에 전송하기		
		System.out.println(result);
		
		//response는 값을 담아보낼 수 없고, request는 값을 담아보낼 수 있음*
		//그래서 view에 응답(response)과 request를 같이 보냄*
		req.setAttribute("result", result);
		RequestDispatcher dis = req.getRequestDispatcher("index.jsp");
		dis.forward(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {

		super.doPost(req, resp); //super == 부모객체
		//이대로 사용하면 부모의 doPost 메서드를 사용하는 것임 / override하는 의미가 없음
        //메소드를 오버라이드해서 사용할 경우 부모객체 삭제
	}
}

 

java logic을 jsp를 통해 client에게 request를 받고 response 하는 방법

1. View에서 오는 파라메터 확인(콘솔로)하고
2. result변수에 담긴 값을 View에 전송
3. response는 값을 담아보낼 수 없고, request는 값을 담아보낼 수 있기 때문에*
4. view에 응답(response)과 request를 붙여서 같이 보냄*

 

  • ParentCar.java
package kr.co.web.model;

public class ParentCar {
	
	public String start() {
		return "시동이 걸렸다";
	}
	
	public String run() {
		return "시속 50km로 달린다";
	}
	
	public String stop() {
		return "멈춘다";
	}
	
	public final String test() { //read only
		return "자체 정비 실행";
	}
}

 

# @Override

  • alt + shift + S  >>  Override/Implement methods... 선택  :  Override 메소드를 선택하면 자동으로 선언해줌
  • super.run()  :  부모메서드  >>  오버라이드 할 경우 삭제하고 변경
  • final method(test())는 readOnly(읽기전용)이기 때문에 수정이 불가능하여 override도 불가능

 

  • MyCar.java
package kr.co.web.model;

public class MyCar extends ParentCar {

	//부모의 메서드는 50km밖에 안되서 맘에 들지 않아 내가 바꿔 쓴다(override)
	
	public boolean turbo = false;
	
	@Override
	public String run() {		
		
		if (turbo == true) {
			return "시속 150km로 달린다";
		}else {
			return super.run();  //부모의 메서드를 그대로 활용할 수 있음
		}	
	}
	//final은 readOnly이기 때문에 수정이 불가능하여 override도 불가능
}