본문 바로가기
Java Web Programming/6. Spring | MyBatis

[SpringMVC/MyBatis] Spring 설정 파일을 분리하여 적용해보기 + DB Sequence

by 파프리카_ 2020. 11. 10.
728x90
반응형

진행 과정

1. <serlvet>태그 내에 <init-param> tag가 없다면 (null이라면)

      DispatcherServlet의 servlet-name에 의거해 스프링 설정 파일 로딩 ([serlvetname]-serlvet.xml)

2. <serlvet>태그 내에 <init-param> tag가 있다면 (null이 아니면) 이를 통해 설정 파일을 찾는다.

     ⇒ DispathcerSerlvet의 init-param에 contextConfigLocation을 이용해, 

           다수의 스프링 설정 파일 로딩

     * Spring에서 제공하는 DispatcherSerlvet은 자신의 SerlvetConfig에 init-param으로

        contextConfigLocation이 제공되면 서블릿 이름으로 자신의 설정파일을 찾지 않고,

        두 번째 설정 방식에 의해 자신의 설정 파일을 찾는다.


문제

 

1번. 전체 회원 수 조회

2번. item_no로 ItemVO 검색

3번. 아이템 등록 후 spring_item table의 정보가 insert되고,

        등록된 item 정보가 등록결과 화면에 시퀀스(item_no) 포함해서 제공하기 (redirect 방식)

         + 등록된 아이템 정보를 모두 보여준다.


Maven pom 설정 

 

/pom.xml

<dependencies>
  <!-- Spring-Web MVC Framework (SpringMVC, IOC, DI/DL) -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.14.RELEASE</version>
  </dependency>

  <!-- Ajax JSON Library (jackson-databind) -->
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.5</version>
  </dependency>
  
  <!-- MyBatis Framework -->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.0</version>
  </dependency>

  <!-- Spring과 MyBatis 연동 Framework -->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.0</version>
  </dependency>

  <!-- DBCP ver.2 -->
  <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.1.1</version>
  </dependency>

  <!-- JDBC(*Spring ver과 같아야한다) -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>4.3.14.RELEASE</version>
  </dependency>
  
  <!-- JSTL Library-->
  <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
  </dependency>

</dependencies>

DD (Deploytment Descriptor) 설정 - init-param tag 추가

 

/WEB_INF/web.xml 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>SpringMVC6-item</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- init-param 태그 추가
    	 : Spring 설정 파일이 다수일 경우, 
    	   SerlvetConfig init param을 전달하여,
    	   Spring 설정을 로딩하게 한다.
     -->
    <init-param>
    	<param-name>contextConfigLocation</param-name>
    	<param-value>/WEB-INF/spring-*.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  
  <!-- request에 대한 한글처리 -->
  <filter>
    <filter-name>EncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>utf-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>EncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

Spring configure 설정 - spring 설정이 여러개 !

 

spring설정을 model과 web으로 구분하여 분리

 

* namespace에서 'context' 체크

/WEB_INF/spring-model.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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
	<!-- 1. DBCP 설정 -->
	<bean id="dbcp" class="org.apache.commons.dbcp2.BasicDataSource">
		<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
		<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:xe"/>
		<property name="username" value="scott"/>
		<property name="password" value="tiger"/>
	</bean>
	
	<!--2. SqlSessionFactory 설정 -->
	<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- DBCP(datebase connection pool) 주입 -->
		<property name="dataSource" ref="dbcp"/>
		<!-- MyBatis에서 쓸 mapper loation(path) 주입 -->
		<property name="mapperLocations" value="classpath:/mybatis/config/*.xml"/>
		<!-- Package에 별칭주기 -->
		<property name="typeAliasesPackage" value="org.kosta.model"/>
		<!-- underScore 표기법을 Camel 표기법으로 mapping(변환)해주는 설정 -->
		<property name="configuration">
			<bean class="org.apache.ibatis.session.Configuration">
				<property name="mapUnderscoreToCamelCase" value="true"></property>
			</bean>
		</property>
	</bean>

	<!--3. SqlSessionTemplate설정 : 트랜잭션 제어를 지원-->
	<bean id="SqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg ref="sqlSessionFactoryBean"/>
	</bean>
	
	<!--4. IOC 설정 : <context:component-scan> :  IOC, DI, DL에 대한 설정-->
	<context:component-scan base-package="org.kosta"></context:component-scan>


</beans>

 

* namespace에서 'mvc' 체크

/WEB_INF/spring-web.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:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!--5. SpringMVC 설정-->
	<mvc:annotation-driven/>

	<!--6. ViewResolver 설정 : client에게 응답하는 view에 대한 설정 -->
	<bean id="ViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/views/"/>
		<property name="suffix" value=".jsp"/>
	</bean>

</beans>

MyBatis 설정 - mapper (/mybatis.config)

 

src/mybatis/config/item.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- Sql Mapper -->
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="item">

	<!-- 1. 전체 회원 수 조회 -->
 	<select id="getItemCount" resultType="int">
 		SELECT COUNT(*)
 		FROM   spring_item
 	</select>
 	
	<!-- 2. item_no로 ItemVO 조회 -->
	<select id="findItemByNo" resultType="itemVO">
		SELECT item_no, item_name, maker, price
		FROM   spring_item
		WHERE  item_no=#{value}
	</select>
	
	<!-- 3. 아이템 등록 후, 등록된 ItemVO 조회 -->
	<insert id="registerItem" parameterType="itemVO">
		<!-- itemVO 객체의 itemNo에 nextval을 할당해준다. -->
		<selectKey keyProperty="itemNo" resultType="string" order="BEFORE">
			SELECT spring_item_seq.nextval
			FROM   dual
		</selectKey> 
		INSERT INTO spring_item (item_no, item_name, maker, price)
		VALUES (#{itemNo}, #{itemName}, #{maker}, #{price})
	</insert>
</mapper>

SQL

 

1. 테이블 생성 및 값 입력

CREATE TABLE spring_item(
    item_no    NUMBER        PRIMARY KEY,
    item_name  VARCHAR2(100) NOT NULL,
    maker      VARCHAR2(100) NOT NULL,
    price      NUMBER        NOT NULL
)

CREATE SEQUENCE spring_item_seq;
INSERT INTO spring_item VALUES(spring_item_seq.nextval, '아이폰9', '애플', 1000);

2. spring_item 테이블


Model

 

/org.kosta.model

 

/ItemVO.java 

package org.kosta.model;

public class ItemVO {
	private String itemNo;
	private String itemName;
	private String maker;
	private int price;
	
	public ItemVO() {
		super();
	}

	public ItemVO(String itemNo, String itemName, String maker, int price) {
		super();
		this.itemNo = itemNo;
		this.itemName = itemName;
		this.maker = maker;
		this.price = price;
	}

	public String getItemNo() {
		return itemNo;
	}

	public void setItemNo(String itemNo) {
		this.itemNo = itemNo;
	}

	public String getItemName() {
		return itemName;
	}

	public void setItemName(String itemName) {
		this.itemName = itemName;
	}

	public String getMaker() {
		return maker;
	}

	public void setMaker(String maker) {
		this.maker = maker;
	}

	public int getPrice() {
		return price;
	}

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

	@Override
	public String toString() {
		return "ItemVO [itemNo=" + itemNo + ", itemName=" + itemName + ", maker=" + maker + ", price=" + price + "]";
	}
	
}

/ItemDAO.java <<interface>>

package org.kosta.model;

public interface ItemDAO {

	int getItemCount();

	ItemVO findItemByNo(String itemNo);

	void registerItem(ItemVO vo);

}

 

/ItemDAOImpl.java

-- annotation --

@Repository - class위

@Resource - instance 변수 위 (SqlSesssionTemplate)

package org.kosta.model;

import javax.annotation.Resource;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class ItemDAOImpl implements ItemDAO {
	@Resource
	private SqlSessionTemplate template;

	public ItemDAOImpl(SqlSessionTemplate template) {
		super();
		this.template = template;
	}
	
	// 1. 전체 회원 수 조회
	@Override
	public int getItemCount() {
		return template.selectOne("item.getItemCount");
	}
	
	// 2. item_no로 ItemVO 조회
	@Override
	public ItemVO findItemByNo(String itemNo) {
		return template.selectOne("item.findItemByNo", itemNo);
	}
	
	// 3. 아이템 등록
	@Override
	public void registerItem(ItemVO vo) {
		template.insert("item.registerItem", vo);
	}

}

View

 

/index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HOME</title>
</head>
<body>
	<h3>SpringMVC item 관리</h3>
	<strong>DB Sequence, spring 설정파일 분리</strong>
	<br><br>
	<!-- 1. 전체 회원 수 조회 -->
	<a href="getItemCount.do">전체 아이템 수 보기</a>
	<hr>

	<!-- 2. item_no로 ItemVO 조회 -->
	<form action="findItemByNo.do">
		아이템 번호 <input type="number" name="itemNo">
		<input type="submit" value="검색">
	</form>
	<hr>

	<!-- 3. 아이템 등록 후, 등록된 ItemVO 조회 -->
	<form action="registerItem.do" method="POST">
		상품명 <input type="text" name="itemName" required="required"><br>
		제조사 <input type="text" name="maker" required="required"><br>
		가격 <input type="number" name="price" required="required"><br>
		<input type="submit" value="등록하기">
	</form>	
</body>
</html>

/views

 

/item_count.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>아이템 수</title>
</head>
<body>
	아이템은 총 ${requestScope.totalCount}개 있습니다.
</body>
</html>

 

/find_item_result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>등록 결과 화면</title>
</head>
<body>
	<h4>${requestScope.ivo.itemName}이 등록 완료되었습니다!</h4>
		id : ${requestScope.ivo.itemNo}<br>
		name : ${requestScope.ivo.itemName}<br>
		maker : ${requestScope.ivo.maker}<br>
		price : ${requestScope.ivo.price}
</body>
</html>

Controller

 

/org.kosta.Controller

 

** redirect방식으로 보내면 request가 유지되지 않기 때문에,

${param.} ${requestScope}로 받아올 수 없다. 만약 유지시키고 싶다면 session에 담아 보내야한다. (${sessionScope.})

하지만 계속 유지되기 때문에 좋은 방법이 아니다.

이를 해결하기 위해서, 새로 Controller를 만들어서 이를 이용하는 것이 적합하다.

 

/ItemController.java

-- annotation --

@Controller - class 위

@Resource - instance변수 위 (CustomerDAO)

@RequestMapping - method 위

package org.kosta.controller;

import javax.annotation.Resource;

import org.kosta.model.ItemDAO;
import org.kosta.model.ItemVO;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller //Component 계열 - 객체 생성
public class ItemController {
	@Resource //DI 계열 - 주입받기
	private ItemDAO itemDAO;
	
	// 1. 전체 회원 수 조회
	@RequestMapping("getItemCount.do")
	public String getItemCount(Model model) {
		int totalCount = itemDAO.getItemCount();
		model.addAttribute("totalCount", totalCount);
		return "item_count";
	}
	
	// 2. item_no로 ItemVO 조회
	@RequestMapping("findItemByNo.do")
	public ModelAndView findItemByNo(String itemNo) {
		ItemVO vo = itemDAO.findItemByNo(itemNo);
		return new ModelAndView("find_item_result", "ivo", vo);
	}
	
	// 3. 아이템 등록
	@PostMapping("registerItem.do")
	public String registerItem(Model model, ItemVO vo) {
		String viewName = "";
		itemDAO.registerItem(vo);	
		viewName = "redirect:registerItemResult.do?itemNo="+ vo.getItemNo();
		return viewName;
	}
	
	// 3_1. 아이템 등록 시, 번호 보내기
	@RequestMapping("registerItemResult.do")
	public ModelAndView registerItemResult(String itemNo) {
		ItemVO ivo = itemDAO.findItemByNo(itemNo);
		return new ModelAndView("register_item_result",
				"ivo", ivo);
	}
}

[ 결과 ]

 

> 홈화면 (index.jsp)

 

> '전체 아이템 수 보기'링크를 클릭하면, item_count.jsp가 작동된다.

 

>  아이템 번호로 검색하면, find_item_result.jsp가 작동된다.

 

>  아이템을 등록하면, register_item_result.jsp가 작동된다.

728x90
반응형