본문 바로가기
Spring

Spring #6 : 스프링-마이바티스 연동(230119)

by haheehee 2023. 1. 20.

새 프로젝트 prosp04를 Dynamic Web Project로 만들고

필요한 스프링 라이브러리를 복사하여 lib폴더에 넣기

 


다 약속된 폴더

WEB-INF 폴더에 action-servlet.xml을 추가하고, web.xml은 프로젝트 생성할때 체크박스 표시로 나타내기

WEB-INF 폴더에 config폴더 생성.(이름정확히해야함!)

그리고 config폴더에 action-mybatis.xml과 action-service.xml추가

 

jdbc.driverClassName=org.mariadb.jdbc.Driver
jdbc.url=jdbc:mariadb://localhost:3306/membertable
jdbc.username=root
jdbc.password=1234

jdbc.properties

- mariadb로 만들어진 membertable 데이터베이스를 사용

 

<?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">
	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>  
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/config/action-mybatis.xml
			/WEB-INF/config/action-service.xml
		</param-value>
	</context-param>
	
	<servlet>
		<servlet-name>action</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>action</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
</web-app>

web.xml

- /WEB-INF/config/action-mybatis.xml : 마이바티스 설정 파일 읽어들이기

 

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
		<property name="prefix" value="/WEB-INF/views/member/" />
		<property name="suffix" value=".jsp" />
	</bean>
	<bean id="memberController"
		class="com.spring.member.controller.MemberControllerImpl">
		<property name="methodNameResolver">
			<ref local="memberMethodResolver" />
		</property>
		<property name="memberService" ref="memberService" />
	</bean>
	<bean id="memberMethodResolver"
		class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
		<property name="mappings">
			<props>
				<prop key="/member/listMembers.do">listMembers</prop>
				<prop key="/member/addMember.do">addMember</prop>
				<prop key="/member/removeMember.do">removeMember</prop>
				<prop key="/member/memberForm.do">form</prop>
			</props>
		</property>
	</bean>
	<bean id="memberUrlMapping"
		class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<props>
				<prop key="/member/*.do">memberController</prop>
			</props>
		</property>
	</bean>
</beans>

action-servlet.xml

1. @WebServlet("/mem.do")
와 RequestDispatcher dispatch = request.getRequestDispatcher(nextPage);
dispatch.forward(request, response);
==> action-servlet.xml 이 그 역할을 대신함

2. <property>태그의 prefix와 suffix가 JSP파일명인셈.(경로와 더불어)

prefix는 JSP파일의 위치를 지정해줌.

 

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<bean id="propertyPlaceholderConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<value>/WEB-INF/config/jdbc.properties</value>
		</property>
	</bean>
	<bean id="dataSource"
		class="org.apache.ibatis.datasource.pooled.PooledDataSource">
		<property name="driver" value="${jdbc.driverClassName}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>
	<bean id="sqlSessionFactory"
		class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="classpath:mybatis/model/modelConfig.xml" />
		<property name="mapperLocations" value="classpath:mybatis/mappers/*.xml" />
	</bean>
	<bean id="sqlSession"
		class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
	</bean>
	<bean id="memberDAO"
		class="com.spring.member.dao.MemberDAOImpl">
		<property name="sqlSession" ref="sqlSession"></property>
	</bean>
</beans>

action-mybatis.xml

<bean>태그 : 객체생성하는 것과 같다.

1. propertyPlaceholderConfigurer :

PropertyPlaceholderConfigurer 클래스를 이용해

데이터베이스 설정 관련 정보를 jdbc.properties파일에서 읽어오는 것

2. dataSource : 

마이바티스에서 제공하는 PooledDataSource클래스를 이용해

dataSource 빈을 생성

3. sqlSessionFactory : 

SqlSessionFactoryBean클래스로 dataSource속성에 빈을 설정

4. sqlSession : SqlSession 빈 생성

5. memberDAO : sqlSession 빈을 memberDAO 빈 속성에 주입

 

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<bean id="memberService"
		class="com.spring.member.service.MemberServiceImpl">
		<property name="memberDAO" ref="memberDAO" />
	</bean>
</beans>

action-service.xml

- memberDAO빈을 memberService 빈의 속성에 주입

 

 

==>다 이렇게 쪼개는 이유 : 유지보수에 용이


 

mybatis패키지

 

member.xml은 그대로!

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
	<typeAliases>
		<typeAlias type="com.spring.member.vo.MemberVO" alias="memberVO" />
	</typeAliases>
</configuration>

modelConfig.xml

<tyleAliases>태그로 마이바티스에서 데이터 전달에 사용될 memberVO 빈 설정

mybatisConfig.xml -> 연동부분


 

package com.spring.member.controller;

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

import org.springframework.web.servlet.ModelAndView;

public interface MemberController {
	public ModelAndView listMembers(HttpServletRequest request, HttpServletResponse response) throws Exception;
	public ModelAndView addMember(HttpServletRequest request, HttpServletResponse response) throws Exception;
	public ModelAndView removeMember(HttpServletRequest request, HttpServletResponse response) throws Exception;
}

MemberController.java

 

package com.spring.member.controller;

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.multiaction.MultiActionController;

import com.spring.member.service.MemberService;
import com.spring.member.service.MemberServiceImpl;
import com.spring.member.vo.MemberVO;


public class MemberControllerImpl extends MultiActionController implements MemberController {
	private MemberService memberService;
	
	public void setMemberService(MemberServiceImpl memberService) {
		this.memberService = memberService;
	}
	
	@Override
	public ModelAndView listMembers(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String viewName = getViewName(request);
		List membersList = memberService.listMembers();
		ModelAndView mav = new ModelAndView(viewName);
		mav.addObject("membersList", membersList);
		return mav;
	}
	
	@Override
	public ModelAndView addMember(HttpServletRequest request, HttpServletResponse response) throws Exception {
		request.setCharacterEncoding("utf-8");
		MemberVO memberVO = new MemberVO();
		
		bind(request, memberVO);
		int result = 0;
		result = memberService.addMember(memberVO);
		ModelAndView mav = new ModelAndView("redirect:/member/listMembers.do");
		return mav;
	}
	
	@Override
	public ModelAndView removeMember(HttpServletRequest request, HttpServletResponse response) throws Exception {
		request.setCharacterEncoding("utf-8");
		String id = request.getParameter("id");
		memberService.removeMember(id);
		ModelAndView mav = new ModelAndView("redirect:/member/listMembers.do");
		return mav;
	}
	
	public ModelAndView form(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String viewName = getViewName(request);
		ModelAndView mav = new ModelAndView();
		mav.setViewName(viewName);
		return mav;
	}
	
	private String getViewName(HttpServletRequest request) throws Exception {
		String contextPath = request.getContextPath();
		String uri = (String) request.getAttribute("javax.servlet.include.request_uri");
		if(uri == null || uri.trim().equals("")) {
			uri = request.getRequestURI();
		}
		int begin = 0;
		if(!((contextPath==null)||("".equals(contextPath)))) {
			begin = contextPath.length();
		}
		int end;
		if(uri.indexOf(";")!=-1) {
			end = uri.indexOf(";");
		} else if(uri.indexOf("?")!=-1) {
			end = uri.indexOf("?");
		} else {
			end = uri.length();
		}
		
		String fileName = uri.substring(begin, end);
		if(fileName.indexOf(".")!=-1) {
			fileName = fileName.substring(0, fileName.lastIndexOf("."));
		}
		if(fileName.lastIndexOf("/")!=-1) {
			fileName = fileName.substring(fileName.lastIndexOf("/"), fileName.length());
		}
		return fileName;
	}
}

MemberControllerImpl.java

1. setMemberService() :memberService 빈을 주입하기 위한 setter

2. mav.addObject("membersList", membersList); : 조회한 회원 정보를 ModelAndView의 addObject()메소드로 바인딩

3. bind(request, memberVO); : 회원가입창에서 전송된 정보를 memberVO 해당 속성에 자동으로 설정

4. form() : 데이터베이스 연동 작업이 없는 입력창 요청 시 뷰이름만 ModelAndView로 반환

 

package com.spring.member.service;

import java.util.List;

import org.springframework.dao.DataAccessException;
import com.spring.member.vo.MemberVO;

public interface MemberService {
	public List listMembers() throws DataAccessException;
	public int addMember(MemberVO memberVO) throws DataAccessException;
	public int removeMember(String id) throws DataAccessException;
}

MemberService.java

 

package com.spring.member.service;

import java.util.List;

import org.springframework.dao.DataAccessException;

import com.spring.member.vo.MemberVO;
import com.spring.member.dao.MemberDAO;

public class MemberServiceImpl implements MemberService {
	private MemberDAO memberDAO;
	public void setMemberDAO(MemberDAO memberDAO) {
		this.memberDAO = memberDAO;
	}
	
	@Override
	public List listMembers() throws DataAccessException {
		List membersList = null;
		membersList = memberDAO.selectAllMemberList();
		return membersList;
	}
	
	@Override
	public int addMember(MemberVO memberVO) throws DataAccessException {
		return memberDAO.insertMember(memberVO);
	}
	
	@Override
	public int removeMember(String id) throws DataAccessException {
		return memberDAO.deleteMember(id);
	}
}

MemberServiceImpl.java

1. setMemberDAO() : 속성 memberDAO에 memberDAO 빈을 주입하기 위한 setter

 

package com.spring.member.dao;

import java.util.List;

import org.springframework.dao.DataAccessException;
import com.spring.member.vo.MemberVO;

public interface MemberDAO {
	public List selectAllMemberList() throws DataAccessException;
	public int insertMember(MemberVO memberVO) throws DataAccessException;
	public int deleteMember(String id) throws DataAccessException;
}

MemberDAO.java

 

package com.spring.member.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.springframework.dao.DataAccessException;
import com.spring.member.vo.MemberVO;

public class MemberDAOImpl implements MemberDAO {
	private SqlSession sqlSession;
	
	public void setSqlSession(SqlSession sqlSession) {
		this.sqlSession = sqlSession;
	}
	
	@Override
	public List selectAllMemberList() throws DataAccessException {
		List<MemberVO> membersList = null;
		membersList = sqlSession.selectList("mapper.member.selectAllMemberList");
		return membersList;
	}
	
	@Override
	public int insertMember(MemberVO memberVO) throws DataAccessException {
		int result = sqlSession.insert("mapper.member.insertMember", memberVO);
		return result;
	}
	
	@Override
	public int deleteMember(String id) throws DataAccessException {
		int result = sqlSession.delete("mapper.member.deleteMember", id);
		return result;
	}
}

MemberDAOImpl.java

DAO가 모델

SqlSession을 setter형태로 의존성 주입
1. action-mybatis.xml의 <bean id="memberDAO"...>태그에서 <property name="sqlSession"> 은 
MemberDAOImpl클래스의 sqlSession 필드가 아닌 setSqlSession()의 sqlSession을 의미하는 것.
2. 또한 <bean id="sqlSession" ...>태그는 생성자가 꼭 필요!
하지만 라이브러리에서 sqlSessionFactory를 받는 생성자를 제공해주어 저절로 생성됨.

 

반드시 dispatcherServlet은 .do로 끝나게하기.

 


 

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" isELIgnored="false"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<% request.setCharacterEncoding("utf-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>회원정보 출력창</title>
<style type="text/css">
.cls1 {
	font-size: 40px;
	text-align: center;
}

.cls2 {
	text-align: center;
}
</style>
</head>
<body>
	<table align="center" width="80%" border="1">
		<tr align="center" bgcolor="lightblue">
			<td>ID</td>
			<td>PASSWORD</td>
			<td>NAME</td>
			<td>EMAIL</td>
			<td>JOINDATE</td>
			<td>삭제</td>
		</tr>
		<c:choose>
			<c:when test="${membersList == null}">
				<tr align="center">
					<td colspan="7"><b>등록된 회원이 없습니다.</b></td>
				</tr>
			</c:when>
			<c:when test="${membersList != null}">
				<c:forEach var="member" items="${membersList}">
					<tr align="center">
						<td>${member.id}</td>
						<td>${member.pwd}</td>
						<td>${member.name}</td>
						<td>${member.email}</td>
						<td>${member.joinDate}</td>
						<td><a href="${contextPath}/member/removeMember.do?id=${member.id}">삭제</a></td>
					</tr>
				</c:forEach>
			</c:when>
		</c:choose>
		
	</table>
	<table align="center" width="40%" border="0">
		<tr style="text-align: center">
			<td height="50px"><a href="${contextPath}/member/memberForm.do"><b>회원가입</b></a></td>
		</tr>
	</table>
</body>
</html>

listMembers.jsp

 

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" isELIgnored="false"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<% request.setCharacterEncoding("utf-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>회원가입 창</title>
</head>
<body>
	<form method="post" action="${contextPath}/member/addMember.do"> 
		<h1 style="text-align: center">회원가입창</h1>
		<table align="center">
			<tr>
				<td width="200"><p align="right">아이디</p></td>
				<td width="400"><input type="text" name="id"></td>
			</tr>
			<tr>
				<td width="200"><p align="right">비밀번호</p></td>
				<td width="400"><input type="password" name="pwd"></td>
			</tr>
			<tr>
				<td width="200"><p align="right">이름</p>	</td>
				<td width="400"><input type="text" name="name"></td>
			</tr>
			<tr>
				<td width="200"><p align="right">이메일</p></td>
				<td width="400"><input type="text" name="email"></td>
			</tr>
			<tr>
				<td width="200"></td>
				<td width="80">
					<input type="submit" value="가입하기">
					<input type="reset" value="다시입력">
				</td>
			</tr>
		</table>
	</form>
</body>
</html>

memberForm.jsp

 


-- 결과 --

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

댓글