본문 바로가기
Spring/Spring Muzi

Spring MVC패턴 흐름

by 미눅스[멘토] 2023. 7. 19.
728x90

 

 

 

1.웹 브라우저 (클라이언트)에서 URL을 요청하면 가장 먼저 디스패처 스블릿에 전달됨.

 

2.URL 요청을 받은 디스패치 서블릿은 어느 컨트롤러에서 요청을 처리할지 결정하려고 핸들러 매핑으로 적합한 컨트롤러를 검색한다.

 

3.핸들러 매핑은 클라이언트 요청을 처리할 컨트롤러를 결정하여 디스패처 서블릿에 반환한다.

 

4.컨트롤러는 해당 클라이언트 요청을 전달받는다. GET또는 POST방식을 기반으로 적합한 메서드를 호출한다.

 

5.호출된 메서드는 정의된 비즈니스 로직으로 모델 데이터를 설정하고 뷰 이름을 디스패처 서블릿에 반환한다.

 

6.디스패서 서블릿은 웹 브라우저에서 들어온 요청을 처리한 결과를 보여 주려고 뷰 리졸버에 도움을 요청하여 응답 결과를 생성할 뷰 객체를 검색한다.

 

7.뷰 리졸버는 적절한 뷰를 결정하여 디스패처 서블릿에 뷰를 반환한다.

 

8.디스패처 서블릿은 데이터가 담긴 모델을 뷰로 보내면 클라리언트 요청에 대한 응답 작업을 완료한다.

 

9.뷰는 클라이언트 요청에 대한 응답 작업이 완료하여 처리 결과르르 디스패처 서블릿에 반환한다.

 

10.마지막으로 클라이언트 화면에 응답 결과를 출력한다. 사용자는 웹 브라우저 화면에서 그 결과를 볼 수 있다.

 

 

 

 


 

 

 

 

흐름

create.jsp →BookController→BookService→BookServiceImpl→BookDao→book_SQL.xml→BookVO

 

 

 

 

create.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<h1>책 등록</h1>
<!-- 뷰(View) : 화면을 담당
Client -> 요청(/create) -> Server(create()메소드와 매핑. View에 create.jsp를 포워딩)
	   <- 응답(create_jsp.java, create_jsp.class, HTML**) <-
웹 브라우저(크롬)에서 HTML을 렌더링 : 브라우저가 읽어서 해석
 -->
 <!-- 
 요청URL : /create
 요청파라미터 : {title=이순신의 모험, categoty=소설, price=35000}
 요청방식 : post
  -->
 <form action="/create" method="post">
 	<!-- 폼 데이터 -->
 	<p>제목 : <input type="text" name="title" required></p>
 	<p>카테고리 : <input type="text" name="category" required></p>
 	<p>가격 : <input type="number" name="price" maxlength="10" 
 				required></p>
 	<p>설명 : <textarea rows="" cols="30" name="content"></textarea>
 	<p>
 		<input type="submit" value="저장" />
 		<input type="button" value="목록" />
 	</p>
 </form>
</body>
</html>

 

사용자에게  폼 데이터를 받아온다.

 

 

 

 

BookController

 

package kr.or.ddit.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import kr.or.ddit.service.BookService;
import kr.or.ddit.vo.BookVO;
import lombok.extern.slf4j.Slf4j;

/* Controller 어노테이션
 스프링 프레임워크에게 "이 클래스는 웹 브라우저의 요정(equest)를
 방아들이는 컨트롤러야"라고 알려주는 것임 
 스프링은 servlet-context.xml의 context:component-scan의 설정에 의해
 이 클래스를 자바빈 객체로 등록(메모리에 바인딩)
 */
@Slf4j
@Controller
public class BookController {
	
	//DI, IoC(의존성 주입,역흐름 제어)
	@Autowired
	BookService BookService;
	
	/*
	  요청URL : /create
	  요청파라미터 : 없음
	  요청방식 : get
	  
	 BookVO [bookId=0, title=이순신의 모험, category=소설, price=10000, content=null, insert_Date=null]
	 */
	@RequestMapping(value="/create", method=RequestMethod.GET)
	public ModelAndView create() {
		/*
		 ModelAndView
		 1) Model : Controller가 반환할 데이터(String, int, List, Map, VO..)를 담당
		 2) View : 화면을 담당(뷰(View : JSP)의 경로) 
		 */
		ModelAndView mav = new ModelAndView();
		
		//forwarding : JSP를 처리, 컴파일하여 HTML로 만들어 리턴
		//prefix : /WEB-INF/views/
		mav.setViewName("book/create");//book=폴더, creqate=파일
		//suffix : .jsp
		//조립되면 : /WEB-INF/views/book/create.jsp
		
		return mav;
	}
	
	
	/*
	 요청URL : /create
	 요청파라미터 : {title=이순신의 모험, categoty=소설, price=35000}
	 요청방식 : post
	*/
	@RequestMapping(value="/create", method = RequestMethod.POST)
	public ModelAndView createPost(HttpServletRequest requeset
			, ModelAndView mav, BookVO bookVO) {
		String title = requeset.getParameter("title");
		String category = requeset.getParameter("category");
		String price = requeset.getParameter("price");
		
		log.info("title : " + title + ", category : " + category + 
		 "price : " + price);
		
		
		log.info("bookVO : " + bookVO);
		
		int result = this.BookService.insert(bookVO);
		log.info("result : " + result);
		
		//forwarding
		mav.setViewName("book/detail");
		
		return mav; 
	}
	
	//책 상세보기
	//요청URI : /detail?bookId=1
	//요청URL : /detail
	//요청파라미터 : bookId=1
	//BookVO [bookId=1, title=null, category=null, price=0
	//, content=null, insertDate= null]
	@RequestMapping(value="/detail", method = RequestMethod.GET)
	public ModelAndView detail(ModelAndView mav, BookVO bookVO) {
		
		
		log.info("detail -> bookVO(전) :" + bookVO);
		
		bookVO = this.BookService.detail(bookVO);
		
		log.info("detail-> bookVO(후) : " + bookVO);
		
		mav.setViewName("book/detail");
		
		return mav;
	}
	
	
}

 

BookService

package kr.or.ddit.service;

import kr.or.ddit.vo.BookVO;

//서비스 interface : 비즈니스 로직
public interface BookService {
	//메소드 시그니처
	//책 등록하기
	public int insert(BookVO bookVO);
	
	
	//책 상세 보기
	public BookVO detail(BookVO bookVO);
	
}

 

 

BookServiceImpl

package kr.or.ddit.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import kr.or.ddit.dao.BookDao;
import kr.or.ddit.service.BookService;
import kr.or.ddit.vo.BookVO;

// 서비스 클래스 : 비즈니스 로직(기능 수행)
// 스프링 MVC 구조에서 Controller와 DAO를 연결하는 역할
/*
 스프링 프레임워크는 직접 클래스를 호출하는 것을 지양하고,
 인터페이스를 호출하는 것을 좋아함.
 인텊이스를 통해서 접근하는 것을 권장하고 있기 떄문에.(확장성)
 
 Impl : implment의 약어
 */
//"스프링아 이 클래스는 서비스 클래스야"라고 알려주면, 프링이가 자바비능로 등록해줌
@Service
public class BookServiceImpl implements BookService {
	
	//DI(의존성 주입)
	//IoC(제어의 역전)
	@Autowired
	BookDao bookDao;
	
	//Override 어노테이션 : 메소드를 재정의
	@Override
	public int insert(BookVO bookVO) {
		return this.bookDao.insert(bookVO);
	}

	
	//책 상세
	@Override
	public BookVO detail(BookVO bookVO) {
		return this.bookDao.detail(bookVO);
	}

}

 

 

BookDao

package kr.or.ddit.dao;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import kr.or.ddit.vo.BookVO;
import lombok.extern.slf4j.Slf4j;

//DAO(Data Access Object) 클래스
// 매퍼xml(book_SQL.xml)을 실행함
// Repository 어노테이션 : 데이터에 접근하는 클래스라고
//	스프링에게 알려줌. 스프링이 자바빈으로 등록해서 관리함 
@Slf4j
@Repository
public class BookDao {
	
	//DI(Dependency Injection) : 의존성 주입
	//(sqlSessionTemplate 타입 객체를 BookDao 객체에 주입함)
	//Ioc(Inversion of Control) : 제어의 역전(new 키워드를 통해 개발자가 직접 객체를 생성하지 않고 스프링이 미리 만들어 놓음)
	@Autowired
	SqlSessionTemplate sqlSessionTemplate;
	
	//<insert id="insert" parameterType="bookVO">s
	public int insert(BookVO bookVO) {
		//book_SQL.xml 파일의 namespace가 book이고, id가 insert인
		//태그를 찾아서 그 안에 들어잇는 sql을 실행함
		//.insert("namespace.id",파라미터)
		//book.insert 실행전
		log.info("bookVO(전) : " + bookVO);
		int result = sqlSessionTemplate.insert("book.insert",bookVO);
		//book.insert 실행후
		log.info("bookVO(후) : " + bookVO);
		log.info("result : " + result);
		return result;
	}
	
	//책 상세보기(p.71)
	//<select id="detail" parameterType="bookVO" resultType="bookVO">
	public BookVO detail(BookVO bookVO) {
		//sqlSessionTemplate : 쿼리를 실행해주는 객체.(root_context.xml에서 bean으로 생성되어 있음)
		// .selectOne() 메소드 : 1행을 가져올 때 사용. / .selectList() 메소드 : 결과 집합 목록 반환(다중행)
		//만약, 결과 행 수가 0일떄? null을 반환
		//	     결과 행 수가 2 이상일 때 ? TooManyResultsException 예외 발생
		// .selectOne("namespace.id" 파라미터)
		return this.sqlSessionTemplate.selectOne("book.detail",bookVO);
	}
	
}

 

 

book_SQK.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace : 매퍼xml 파일이 여러개일 수 있음
	이를 구별하기 위한 식별 용도로 사용
 -->
<mapper namespace="book">
	<!-- MyBatis에서 제공해주는 데이터 입력을 나타내는 태그
	1) 들어옴 : Dao 객체가 던진 파라미터
		- parametertype(o) : String, int, hashMap, VO, List
		- parameterMap(x)
	2) 나감 : Dao 객체의 메소드 쪽으로 리턴
		- resulttype : String, int ,hashMap, VO
		- resultMap : MyBatis의 resultMap 태그를 사용
	 -->
	 
	<insert id ="insert" parameterType="bookVO">
		<selectKey resultType="int" order="BEFORE" keyProperty="bookId">
			SELECT NVL(MAX(BOOK_ID),0) +1 FROM BOOK
		</selectKey>
		INSERT INTO BOOK(BOOK_ID, TITLE, CATEGORY, PRICE, CONTENT, INSERT_DATE)
		VALUES(#{bookId},#{title},#{category},#{price},#{content},SYSDATE)
	</insert>
	
	<!-- P.71  -->
	<!-- 책 상세보기
		MyBatis의  select 태그는 조회(select) 쿼리를 실행하기 위한 태그
		parameterType(DAO -> XML) : bookVO타입.{bookId=1, title=null, category=null...}
		resultType(XML -> DAO) : bookVO타입{bookId=1, title=검은태양,category=드라마...}
	 -->
	 <select id="detail" parameterType="bookVO" resultType="bookVO">
		select BOOK_ID, TITLE, CATEGORY, PRICE, CONTENT, INSERT_DATE
		from book
		where book_id = #{bookId}
	 </select>
	 
</mapper>

 

 

BookVO

package kr.or.ddit.vo;

import java.util.Date;

//자바빈 클래스
//1) 멤버변수 2)기본 생성자 3) getter/setter메소드
public class BookVO {
	
	//멤버변수
	private int bookId;
	private String title;
	private String category;
	private int price;
	private String content;
	private Date insert_Date;
	
	//기본 생성자
	public BookVO() {
	}

	
	//getter/setter
	public int getBookId() {
		return bookId;
	}

	public void setBookId(int bookId) {
		this.bookId = bookId;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getCategory() {
		return category;
	}

	public void setCategory(String category) {
		this.category = category;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public Date getInsert_Date() {
		return insert_Date;
	}

	public void setInsert_Date(Date insert_Date) {
		this.insert_Date = insert_Date;
	}


	@Override
	public String toString() {
		return "BookVO [bookId=" + bookId + ", title=" + title + ", category=" + 				category + ", price=" + price
				+ ", content=" + content + ", insert_Date=" + insert_Date + "]";
	}
	
	
	
}

'Spring > Spring Muzi' 카테고리의 다른 글

동기,비동기  (0) 2023.07.25
그냥 수업 필기..  (0) 2023.07.25
AJAX, XML, JSON, CSV 수업...그냥..필기...  (0) 2023.07.24
수업시간에 그냥 필기...  (0) 2023.07.21
무지  (0) 2023.07.19