framework/spring mvc

[springMVC] 4. 스키마 기반의 SPRING MVC

jeri 2024. 8. 3. 02:42
반응형
  • Spring 프레임워크에서는 Spring Container가 DispatcherServlet, HandlerMapping, ViewResolver을 만들어 제공해줌
  • 하지만 사용하기 위해서는 몇 가지 설정이 필요함
  • web.xml : DispatcherServlet 서블릿 웹프로그램으로 등록
  • Spring Bean Configuration File.xml : HandlerMapping , ViewResolver Spring Bean으로 등록

 

Model(요청 처리 메소드) 역할을 하는 Controller클래스의 종류



01. Spring프레임워크에서 MVC 패턴 만드는 단계

1) 문제점 - 스키마 기반의 SpringMVC 

  • Command 패턴을 이용함 : 하나의 요청에 대한 하나의 처리 객체
  • 클라이언트의 요청이 많아질수록 요청을 처리하는 클래스(Controller를 상속받은 Model 클래스) 도 많아져야함
  • 스프링 빈도 너무 많아짐
  • URL 주소도 많이 매핑시켜야함
  • 유지보수의 큰 문제가 발생할 수 있음

2) 해결법 - 어노테이션 기반의 SpringMVC

  • 하나의 객체 내 다수의 메소드로 작성 (하나의 요청에 대한 하나의 메소드) 가능
  • 어노테이션을 통해 수동 매핑을 이용함

 

 

 

02. 스프링빈 환경설정파일(Spring Bean Configuration File)

💖 [root-context.xml]
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="<http://www.springframework.org/schema/beans>"
	xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>"
	xmlns:tx="<http://www.springframework.org/schema/tx>"
	xsi:schemaLocation="<http://www.springframework.org/schema/beans> <https://www.springframework.org/schema/beans/spring-beans.xsd>
		<http://www.springframework.org/schema/tx> <http://www.springframework.org/schema/tx/spring-tx.xsd>">
        
        
	<!-- Root Context: defines shared resources visible to all other web components -->
	<!-- root-context.xml : 모든 Front Controller에서 객체로 사용될 클래스를 Spring Bean으로
	등록하기 위한 Spring Bean Configuration File -->
	<!-- => DAO 클래스 작성에 필요한 클래스를 Spring Bean으로 등록 -->
	<!-- => DataSource, SqlSessionFactory, SqlSession, TransactionManager 등 -->
    



	<!-- DataSource 관련 클래스를 Spring Bean으로 등록 - DBCP(DataBase Connection Pool) -->
	<!-- => DataSource 객체 필드에 Connection 객체 생성에 필요한 값을 인젝션 처리 -->
	<!--
	<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
		<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
		<property name="username" value="scott"/>
		<property name="password" value="tiger"/>
	</bean>
	-->
	<!-- 퍼시스턴스 프레임워크(Persistence Framework)에서 발생되는 로그 이벤트를 전달받아
	Spring Framework에서 처리하기 위해 driverClassName 필드값과 url 필드값을 log4jdbc-log4j2-jdbc4
	라이브러리에서 제공하는 값으로 변경 -->
	<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
		<property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"/>
		<property name="url" value="jdbc:log4jdbc:oracle:thin:@localhost:1521:xe"/>
		<property name="username" value="scott"/>
		<property name="password" value="tiger"/>
	</bean>




	<!-- SqlSessionFactory 관련 클래스를 Spring Bean으로 등록 -->
	<!-- => SqlSessionFactoryBean 객체 필드에 객체 생성에 필요한 값을 인젝션 처리 -->
	<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactoryBean">
		<!-- configLocation 필드에 Mybatis Framework의 환경설정파일의 경로가 저장되도록 인젝션 처리 -->
		<!-- => SpringMVC Framework에서 사용하는 스프링 컨테이너(WebApplicationContext 객체)는
		[src/main/webapp] 폴더를 웹자원의 최상위 폴더로 처리하여 환경설정파일의 경로를 제공 -->
		<!-- <property name="configLocation" value="/WEB-INF/spring/mybatis-config.xml"/> -->
		<!-- [src/main/java] 폴더 또는 [src/main/resources] 폴더에 환경설정파일을 작성한 경우
		classpath 접두사를 사용하면 스프링 컨테이너(WebApplicationContext 객체)로 접근 가능 -->
		<!-- => 폴더의 패키지에 작성된 환경설정파일은 파일 시스템 형식으로 경로를 표현하여 접근 가능 -->
		<!-- <property name="configLocation" value="classpath:xyz/itwill/config/mybatis-config.xml"/> -->
		<property name="configLocation" value="classpath:mybatis-config.xml"/>

		<!-- dataSource 필드에 DataSource 관련 클래스의 Spring Bean이 저장되도록 인젝션 처리 - DI -->
		<!-- => Mybatis 환경설정파일에서 environment 엘리먼트와 유사한 기능 제공 -->
		<property name="dataSource" ref="dataSource"/>

		<!-- typeAliasesPackage 필드에 DTO 클래스를 작성한 패키지가 저장되도록 인젝션 처리 -->
		<!-- => XML 기반의 매퍼파일(MapperFile)에서 Java 자료형 대신 사용할 별칭을 제공하기 위한 기능 -->
		<!-- => Mybatis 환경설정파일에서 typeAliases 엘리먼트의 package 엘리먼트와 유사한 기능 제공 -->
		<property name="typeAliasesPackage" value="xyz.itwill10.dto"/>

		<!-- mapperLocations 필드에 List 객체를 생성하여 저장되도록 인젝션 처리 -->
		<!-- => List 객체에는 XML 기반의 매퍼 파일의 경로가 요소값으로 저장되도록 추가 - 매퍼 등록 -->
		<!-- => Mybatis 환경설정파일에서 mappers 엘리먼트의 package 엘리먼트와 유사한 기능 제공 -->
		<property name="mapperLocations">
			<list>
				<!-- [src/main/java] 폴더의 패키지에 매퍼 파일을 작성하기 위한 classpath 접두사 사용  -->
				<value>classpath:xyz/itwill10/mapper/*.xml</value>
			</list>
		</property>
	</bean>
    




	<!-- SqlSession 관련 클래스를 Spring Bean으로 등록 -->
	<!-- => SqlSessionTemplate 클래스로 객체를 생성하기 위한 생성자 매개변수에 SqlSessionFactoryBean
	객체를 전달하여 필드 초기화 처리 - DI -->
	<!-- destroy-method 속성을 사용하여 Spring Bean 소멸전 clearCache 메소드가 자동 호출되도록 설정  -->
	<!-- => clearCache 메소드는 SqlSessionTemplate 객체 소멸전 SqlSessionTemplate 객체에 의해
	사용된 JDBC 관련 객체를 정리하는 메소드 -->
	<!-- => DAO 클래스의 메소드에서 SqlSession 객체 사용후 close() 메소드를 호출하지 않도록 설정 -->
	<bean class="org.mybatis.spring.SqlSessionTemplate" id="sqlSession" destroy-method="clearCache">
		<constructor-arg ref="sqlSessionFactoryBean"/>
	</bean>
    
    
    

	<!-- TransactionManager 관련 클래스를 Spring Bean으로 등록 -->
	<!-- => Spring Bean의 식별자(beanName)을 반드시 [transactionManager]로 설정 -->
	<!-- => dataSource 필드에 DataSource 관련 클래스의 Spring Bean을 인젝션 처리  -->
	<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>
    
    
    
    

	<!-- annotation-driven : @Transactional 어노테이션을 사용하여 TransactionManager 객체로
	트렌젝션 처리 기능을 제공하기 위한 엘리먼트 -->
	<!-- => tx 네임스페이스로 spring-tx.xsd 파일을 제공받아 엘리먼트 작성 -->
	<tx:annotation-driven/>
</beans>
💖mvc-context1.xml (HandlerMapping등록)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="<http://www.springframework.org/schema/beans>"
	xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>"
	xsi:schemaLocation="<http://www.springframework.org/schema/beans> <http://www.springframework.org/schema/beans/spring-beans.xsd>">
    
    
	
	<!--1. Model객체 Spring Bean으로 등록-->
	<!-- Spring Framework 라이브러리 Controller 인터페이스를 상속받은 자식클래스를 Spring Bean으로 등록 -->
	<bean class="xyz.itwill09.spring.ListController" id="listController"/>
	<bean class="xyz.itwill09.spring.ViewController" id="viewController"/>
    
    
    <!--2.HandlerMapping객체 Spring Bean으로 등록-->
	<!-- Spring Framework 라이브러리의 SimpleUrlHandlerMapping 클래스를 Spring Bean으로 등록 -->
	<!-- => SimpleUrlHandlerMapping 객체 : 컨트롤러(DispatcherServlet)에게 클라이언트의 요구사항을
	전달받아 요청 처리 클래스의 객체(Spring Bean)를 반환하는 기능 제공 -->
	<!-- => mappings 필드에 Map 객체를 저장하여 엔트리(Entry) 추가 -->
	<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<!--  맵키(MapKey)는 클라이언트의 요구사항(String)을 전달하고 맵값(MapValue)은
		요청 처리 클래스에 Spring Bean에 대한 beanName(String)을 전달하여 Map 객체의
		엔트리로 추가 - map 엘리먼트 대신 props 엘리먼트 사용 -->
		<property name="mappings">
			<props>
				<prop key="/list.do">listController</prop>
				<prop key="/view.do">viewController</prop>
			</props>
		</property>
	</bean>
</beans>
💖mvc-context2.xml (ViewResolver등록)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="<http://www.springframework.org/schema/beans>"
	xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>"
	xsi:schemaLocation="<http://www.springframework.org/schema/beans> <http://www.springframework.org/schema/beans/spring-beans.xsd>">
    
   
    <!--1.ViewResolver객체 Spring Bean으로 등록-->
	<!-- Spring Framework 라이브러리 InternalResourceViewResolver 클래스를 Spring Bean으로 등록 -->
	<!-- InternalResourceViewResolver 객체 : 뷰이름(ViewName)을 전달받아 JSP 문서로 변환하여
	반환하는 기능을 제공하는 객체 -->
	<!-- => prefix 필드와 suffix 필드에 JSP 문서로 변환하기 위한 정보를 저장 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- prefix 필드 : 뷰이름 앞부분에 추가될 문자열 - 디렉토리  -->
		<property name="prefix" value="/WEB-INF/mvc/"/>
		<!-- suffix 필드 : 뷰이름 뒷부분에 추가될 문자열 - 확장자  -->
		<property name="suffix" value=".jsp"/>
	</bean>
</beans>

03. [DTO]

Product.java
package xyz.itwill09.spring;

import lombok.AllArgsConstructor;
import lombok.Data;

@AllArgsConstructor
@Data
public class Product {
	private int num;
	private String name;
}

04. [🖤Model]

ListController.java - Command 패턴
package xyz.itwill09.spring;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

//Model 역할을 제공하기 위한 클래스 - 요청 처리 클래스
//=> Spring Framework 라이브러리의 Controller 인터페이스를 상속받아 작성
//=> 클라이언트가 [/list.do]의 URL 주소로 요청한 경우 컨트롤러에 의해 동작될 요청 처리 클래스
public class ListController implements Controller{
	//요청 처리 메소드 - 클라이언트 요청에 의해 컨트롤러에 자동 호출
	// => ModelAndView 객체에 응답 관련 정보를 저장하여 반환
	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {

		//ModelAndView 객체 : 처리결과 및 이동 관련 정보를 저장하기 위한 객체
		ModelAndView modelAndView = new ModelAndView();

		//데이타 처리
		List<Product> productList = new ArrayList<Product>();
		productList.add(new Product(1000, "컴퓨터"));
		productList.add(new Product(2000, "노트북"));
		productList.add(new Product(3000, "핸드폰"));

		//요청에 대한 처리결과를 ModelAndView 객체의 속성값으로 저장
		//ModelAndView.addObject(String attributeName, Object attributeValue) :
		// => ModelAndView 객체에 처리결과를 속성값으로 저장하는 메소드 - Request Scope
		// => request.setAttribute()의 메소드와 유사한 기능 제공
		modelAndView.addObject("productList",productList);

		//응답에 대한 이동 관련 정보(View)를 ModelAndView 객체 필드에 저장
		//ModelAndView.setViewName(String viewName) : 뷰이름(ViewName)을 변경하는 메소드
		// => 컨트롤러에 의해 뷰이름(ViewName)은 JSP 문서로 변경되어 포워드 이동 - 응답
		modelAndView.setViewName("product_list");

		return modelAndView;
	}
}
ViewController.java - Command 패턴
package xyz.itwill09.spring;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

//Model 역활을 제공하기 위한 클래스 - 요청 처리 클래스
//=> 클라이언트가 [/view.do]의 URL 주소로 요청한 경우 컨트롤러에 의해 동작될 요청 처리 클래스
public class ViewController implements Controller{
	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {

		ModelAndView modelAndView = new ModelAndView();
		modelAndView.addObject("product",new Product(4000,"프린트"));
		modelAndView.setViewName("product_view");

		return modelAndView;
	}
}

05. [🖤View]

WEB-INF > mvc > product_list.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@taglib prefix="c" uri="<http://java.sun.com/jsp/jstl/core>" %>
//<%-- 회원목록을 제공받아 출력하는 JSP 문서 --%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SPRING</title>
</head>
<body>
	<h1>제품목록</h1>
	<hr>
	<c:forEach var="product" items="${productList}">
		<p>제품번호 = ${product.num }, 제품이름 = ${product.name }</p>
	</c:forEach>
</body>
</html>
WEB-INF > mvc >product_view.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<%@taglib prefix="c" uri="<http://java.sun.com/jsp/jstl/core>" %>
//<%-- 회원정보를 제공받아 출력하는 JSP 문서 --%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SPRING</title>
</head>
<body>
	<h1>제품정보</h1>
	<hr>
	<p>제품번호 = ${product.num }, 제품이름 = ${product.name }</p>
</body>
</html>
반응형