** Spring MVC Project 설정
1. Spring MVC Project를 생성
=> 기본 패키지 이름을 3 level 이상으로 설정 - kr.co.pk
=> 3번째 패키지 이름이 application의 ContextPath(URL 기본 경로) : Tomcat에서 수정 가능
실제 도메인 연결할 때는 없어질 것이고 포트번호도 생략하고자 하면 http는 80번 https는 443번 사용
![]() |
2. 애플리케이션 실행 Run as Run on Server
=> url - http://localhost:8080/pk/
3. 포트번호를 생략하게 해보자.
=> server.xml에서 tomcat의 port를 80번으로 변경
<Connector connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="8443"/>
4. ContextPath를 제거
=> ContextPath를 / 로 변경
1) Tomcat 설정을 수정
=> [Servers] 탭에서 Tomcat을 더블클릭
![]() |
=> [Module]탭에서 실행하고자 하는 프로젝트 선택하고 [Edit] 버튼을 누른후 path를 / 로 설정
![]() |
2) 재실행
![]() |
3) 다른 컴퓨터의 브라우저에서는 http://IP 주소만 입력하면 접속이 된다.
5. Java, Spring, JUnit, Servlet, JSP 버전을 변경
=> pom.xml 파일에서 수행
1) Java와 Spring 버전변경은 properties에서 한다.
<properties>
<java-version>1.8</java-version>
<org.springframework-version>5.0.7.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
=> java는 람다와 스트림을 사용할 거라면 1.8이상
=> spring은 4.0.0 이상을 사용
2) dependecies 태그 안에서 servlet과 jsp의 dependency를 수정
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
=> scope 태그를 남겨두어야 한다.
scope가 있으면 현재 프로젝트의 라이브러리를 가져가지 않고 실행되는 곳의 라이브러리를 사용
servlet과 jsp는 java에 있는 것을 사용하는 것이 아니고 WAS의 것을 사용한다.
3) JUnit - dependencies 안에서 수정 : 4.12로 변경, Spring5.0 이상은 4.12부터 테스트 가능
=> 단위(클래스나 메소드) 테스트 라이브러리
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
=> scope를 남겨두는데 이 scope는 테스트할 때 사용이 되고 배포를 할 때는 삭제가 되는 라이브러리 설정
4) servlet 버전을 변경한 경우 web.xml 파일의 DTD 수정
=> 이 작업은 하지 않아도 실행에는 문제가 없지만 이 프로젝트를 다른 환경으로 가져가면 에러가 발생
=> 구글에 web.xml 서블릿 버전으로 검색하면 DTD가 검색된다.
<?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">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
6. 기본 설정이 끝나면 재실행 - 실행이 잘 됐으니 Git에다가 올려두자.
7. 여러 명이 하는 프로젝트라면 여기까지는 일반적으로 Project Manager가 결정
** 오라클의 데이터를 MyBatis(SQL Mapper : SQL과 프로그래밍 언어의 코드를 분리)를 이용해서 읽어오기
=> CRUD(Create, Read, Update, Delete)를 위한 프로젝트 구조
Controller <- Service <- Repository <- MyBatis Session(xml, interface) -둘중에 하나만 공부하고 반대쪽은 특징을 기억하는 방식으로 공부하자)
=> ItemController를 생성해서 사용
DTO
Interceptor, AOP Class
Error Page 설정
1. pom.xml 파일에 필요한 의존성 설정
=> oracle, spring-jdbc, mybatis, spring-mybatis : 필수
=> Test를 하고자 하면 spring-test : 거의 필수
=> DTO 클래스를 편리하게 만들고자 하면 lombok : 최근에 많이 사용
=> 데이터베이스 연동할 때 로그를 출력하고자 하면 log4jdbc : 개발할 때만 사용
1) Oracle의 Repository 설정 : Oracle의 경우는 Maven 중앙저장소에 없어서 설정
<repositories>
<repository>
<id>oracle</id>
<name>ORACLE JDBC Repository</name>
<url>http://maven.jahia.org/maven2</url>
</repository>
</repositories>
2) dependencies에 나머지 의존성을 설정
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc7</artifactId>
<version>12.1.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
<dependency>
<groupId>org.bgee.log4jdbc-log4j2</groupId>
<artifactId>log4jdbc-log4j2-jdbc4</artifactId>
<version>1.16</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework-version}</version>
</dependency>
3) pom.xml을 수정한 후 저장하고 잠시 기다렸다가 재실행
=> 실행이 안되면 라이브러리를 다운로드 받지 못한 것이나 설정 실패
2. 필요한 클래스를 생성
=> MyBatis를 xml로 사용
1) DTO 클래스 생성 : kr.co.pk.item.domain
=> 자료형과 이름을 정확하게 기재
package kr.co.pk.item.domain;
public class Item {
private Integer itemid;
private String itemname;
//숫자 데이터의 경우 null이 될 가능성이 있는 경우는 Wrapper 클래스 사용
private Integer price;
private String description;
private String pictureurl;
public Integer getItemid() {
return itemid;
}
public void setItemid(Integer itemid) {
this.itemid = itemid;
}
public String getItemname() {
return itemname;
}
public void setItemname(String itemname) {
this.itemname = itemname;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPictureurl() {
return pictureurl;
}
public void setPictureurl(String pictureurl) {
this.pictureurl = pictureurl;
}
@Override
public String toString() {
return "Item [itemid=" + itemid + ", itemname=" + itemname + ", price=" + price + ", description=" + description
+ ", pictureurl=" + pictureurl + "]";
}
}
2) DAO 클래스 생성 : kr.co.pk.item.dao.ItemDAO
=> 사용할 데이터베이스 프레임워크 클래스의 의존성을 설정
package kr.co.pk.item.dao;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class ItemDAO {
@Autowired
//MyBatis를 xml로 이용할 때 사용하는 클래스
private SqlSession sqlSession;
}
3) Service 인터페이스 생성 : kr.co.pk.item.service.ItemService
package kr.co.pk.item.service;
public interface ItemService {
}
4) Service 인터페이스의 내용을 구현할 ServiceImpl 클래스를 생성 : kr.co.pk.item.service.ItemServiceImpl
=> DAO를 주입받는다.
package kr.co.pk.item.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import kr.co.pk.item.dao.ItemDAO;
@Service
public interface ItemServiceImpl extends ItemService {
@Autowired
private ItemDAO itemDao;
}
5) Controller 클래스를 생성: kr.co.pk.item.controller.ItemController
=> Service 를 주입 받는다.
package kr.co.pk.item.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import kr.co.pk.item.service.ItemService;
@Controller
public class ItemController {
@Autowired
private ItemService itemService;
}
3. 데이터베이스 프레임워크 설정(Oracle + MyBatis)
1) 데이터베이스 접속 정보를 저장
=> root-context.xml 파일에 작성
=> 데이터베이스는 모든서비스에 이용될 가능성이 높기 때문에 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 모든 곳에서 사용할 Bean을 생성 -->
<!-- 데이터베이스 접속 정보를 저장하는 bean을 생성 데이터베이스 종류별로 설정 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@192.168.0.200:1521:xe</value>
</property>
<property name="username">
<value>user05</value>
</property>
<property name="password">
<value>user05</value>
</property>
</bean>
</beans>
2) Test 클래스를 만들어서 테스트 - 에러
=> src/test/java 디렉토리에 생성
3) XML을 이용해서 MyBatis를 연동할 때 사용할 매퍼 파일을 생성
=> src/resources 디렉토리에 별도의 디렉토리(mappers)를 생성해서 만드는 것이 일반적
=> mappers/item.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">
<mapper namespace="item">
</mapper>
4) root-context.xml 파일에 xml을 이용해서 MyBatis를 사용할 수 있도록 해주는 bean 생성코드를 작성
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 모든 곳에서 사용할 Bean을 생성 -->
<!-- 데이터베이스 접속 정보를 저장하는 bean을 생성 데이터베이스 종류별로 설정 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@192.168.0.200:1521:xe</value>
</property>
<property name="username">
<value>user05</value>
</property>
<property name="password">
<value>user05</value>
</property>
</bean>
<!-- XML을 이용한 MyBatis 사용 설정 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- mappers 디렉토리 안에 있는 모든 xml을 mapper로 사용 다른 용도의 xml 파일이 있으면 에러 -->
<property name="mapperLocations" value="classpath:mappers/**/*.xml" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
</beans>
5) Test 클래스에 MyBatis 설정을 확인하기 위한 코드를 추가하고 실행
package kr.co.pk;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//설정 파일을 읽어오는 코드
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"file:src/main/webapp/WEB-INF/spring/root-context.xml"})
public class ItemTest {
//데이터베이스 접속 정보를 주입
@Autowired
private DataSource dataSource;
//MyBatis 사용 클래스를 주입
@Autowired
private SqlSession sqlSession;
//MyBatis 설정 정보를 테스트
@Test
public void mybatisTest() {
System.out.println(sqlSession);
}
//데이터베이스 연결을 테스트
@Test
public void connectTest() {
try {
System.out.println(dataSource.getConnection());
}catch(Exception e) {
System.out.println(e.getLocalizedMessage());
e.printStackTrace();
}
}
}
=> mapper 파일(item.xml)에 sql이 하나도없어서 에러발생해야하는데 난 왜 에러가 안났나...- spq을 작성하고 다시 테스트
4. 웹 애플리케이션이 시작될 때 Item 테이블의 전체 데이터를 가져와서 출력하기
1)sql 매퍼 파일에 필요한 SQL을 생성
<?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">
<mapper namespace="item">
<!-- Item 테이블의 데이터를 전부 가져오는 SQL -->
<select id=""
resultType="kr.co.pk.item.domain.Item">
select itemid, itemname, price, description, pictureurl
from item
</select>
</mapper>
2) ItemDAO 클래스에 전체 데이터를 가져오는 메소드를 생성
public List<Item> allitem() {
return sqlSession.selectList("item.allitem")"
}
package kr.co.pk.item.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import kr.co.pk.item.domain.Item;
@Repository
public class ItemDAO {
@Autowired
//MyBatis를 xml로 이용할 때 사용하는 클래스
private SqlSession sqlSession;
//Item 테이블의 전체 데이터를 가져오는 메소드
public List<Item> allitem() {
return sqlSession.selectList("item.allitem");
}
}
3) ItemService 인터페이스에 전체 데이터를 가져오는 메소드를 선언 (이부분이 어려움)
4) ItemServiceImpl 클래스에 전체 데이터를 가져오는 메소드를 구현
package kr.co.pk.item.service;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import kr.co.pk.item.dao.ItemDAO;
import kr.co.pk.item.domain.Item;
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private ItemDAO itemDao;
@Override
public void allitem(HttpServletRequest request, HttpServletResponse response) {
//1.파라미터 읽기
//2.필요한 처리 수행
//3.DAO 메소드의 매개변수 생성
//4.DAO 메소드를 호출
List<Item> list = itemDao.allitem();
//5.결과를 가공
//6.결과를 저장 - REST API Server의 경우는 request에 저장
request.setAttribute("list", list);
}
}
5) ItemController 클래스에 시작 요청을 처리하는 메소드를 수정
=> 단순한 웹 애플리케이션을 만들 때와 웹 서버를 만들 때는 Controller가 조금씩 수정
=> 기존 HomeController의 내용은 삭제
package kr.co.pk.item.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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 kr.co.pk.item.service.ItemService;
@Controller
public class ItemController {
@Autowired
private ItemService itemService;
@RequestMapping(value = {"/", "index.html"}, method = RequestMethod.GET)
public String home(HttpServletRequest request, HttpServletResponse response) {
//서비스의 메소드를 호출
itemService.allitem(request, response);
return "home";
}
}
6) 기본의 home.jsp 파일을 삭제하고 새로 생성한 후 작성
출력되는지 먼저 테스트 해보고
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ITEM</title>
</head>
<body>
${list}
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- jsp 를 이용해서 데이터를 출력할 때는 이 코드는 거의 필수 -->
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ITEM</title>
</head>
<body>
<div align="center">
<h2>상품 목록</h2>
<table border="1">
<tr>
<th width="80">상품 ID</th>
<th width="300">상품 이름</th>
<th width="300">상품 가격</th>
</tr>
<c:forEach var="item" items="${list}">
<tr>
<td width="80">${item.itemid}</td>
<td width="300">${item.itemname}</td>
<td width="100" align="right">
${item.price}원</td>
</tr>
</c:forEach>
</table>
</div>
</body>
</html>
7) webapp 디렉토리에 css 디렉토리를 만들고 home.css 파일을 만들고 작성
div.body{
overflow-y:auto;
margin-top:50px;
margin-bottom:50px;
}
tr.header{
background:#c9bfed;
}
tr.record{
background:#ededed;
}
8) home.jsp 파일에 home.css를 적용하기 위한 코드를 작성
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/home.css">
9) servlet-context.xml 파일에 추가
<!-- Controller가 처리하지 못하는 URL은 WAS가 처리하도록 하는 설정 -->
<default-servlet-handler/>
10) 다시 실행
5. 상세보기 구현
=> 목록보기에서 하나를 골라서 그 하나를 자세히 보는 기능
=> 목록보기에서 목록을 클릭하면 클릭한 목록을 자세히 보여주는 형태로 구현
클릭할 때 하나의 데이터를 찾아올 수 있도록 기본키 값을 어떻게 넘겨줄 것인지를 고려
웹에서는 url 뒤에 파라미터로 넘겨주던가 /값을 작성하는 형태를 이용
=> 최근에는 파라미터로 넘기는 경우보다는 URL에 변수를 추가하는 형태로 많이 구현
1) home.jsp 파일에 제목을 출력하는 부분을 수정
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- jsp를 이용해서 데이터를 출력할 때는 이 코드는 거의 필수 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ITEM</title>
<link rel="stylesheet"
href="${pageContext.request.contextPath}/css/home.css">
</head>
<body>
<div align="center" class="body">
<h2>상품 목록</h2>
<table border="1">
<tr class="header">
<th width="80">상품 ID</th>
<th width="300">상품 이름</th>
<th width="100">상품 가격</th>
</tr>
<c:forEach var="item" items="${list}">
<tr class="record">
<td width="80">${item.itemid}</td>
<td width="300">
<a href="detail/${item.itemid}">${item.itemname}</a>
<td width="100" align="right">
${item.price}원</td>
</tr>
</c:forEach>
</table>
</div>
</body>
</html>
2)
<?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">
<mapper namespace="item">
<!-- Item 테이블의 데이터를 전부 가져오는 SQL -->
<select id="allitem"
resultType="kr.co.pk.item.domain.Item">
select itemid, itemname, price, description, pictureurl
from item
</select>
<!-- Item 테이블에서 데이터 1개를 가져오는 SQL -->
<select id="detailitem"
parameterType="java.lang.Integer"
resultType="kr.co.pk.item.domain.Item">
select itemid, itemname, price, description, pictureurl
from item
where itemid = #{itemid}
</select>
</mapper>
3) mapper 테스트 :
package kr.co.pk;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//설정 파일을 읽어오는 코드
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"file:src/main/webapp/WEB-INF/spring/root-context.xml"})
public class ItemTest {
//데이터베이스 접속 정보를 주입
@Autowired
private DataSource dataSource;
//MyBatis 사용 클래스를 주입
@Autowired
private SqlSession sqlSession;
//MyBatis 설정 정보를 테스트
@Test
public void mybatisTest() {
System.out.println(sqlSession);
}
@Test
public void detailitem() {
System.out.println(sqlSession.selectOne("item.detailitem", 1));
}
//데이터베이스 연결을 테스트
@Test
public void connectTest() {
try {
System.out.println(dataSource.getConnection());
}catch(Exception e) {
System.out.println(e.getLocalizedMessage());
e.printStackTrace();
}
}
}
4) ItemDAO에 상세보기를 위한 메소드를 작성
package kr.co.pk.item.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import kr.co.pk.item.domain.Item;
@Repository
public class ItemDAO {
@Autowired
//MyBatis를 xml로 이용할 때 사용하는 클래스
private SqlSession sqlSession;
//Item 테이블의 전체 데이터를 가져오는 메소드
public List<Item> allitem(){
return sqlSession.selectList("item.allitem");
}
//Item 테이블에서 1개의 데이터를 가져오는메소드
public Item detailitem(Integer itemid) {
return sqlSession.selectOne("item.detailitem", itemid);
}
}
5) ItemService 인터페이스에 상세보기를 위한 메소드를 선언
package kr.co.pk.item.service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//서비스의 메소드는 매개변수를 다양하게 만들 수 있습니다.
//모든 곳에서 사용가능하도록 만들고자 하면
//HttpServletRequest 와 HttpServletResponse를 갖도록 하면 되고
//상황에 따라 다르게 만들 수 도 있습니다.
public interface ItemService {
//전체 데이터를 가져오는 메소드
public void allitem(HttpServletRequest request, HttpServletResponse response);
//상세보기를 위한 메소드
public void detailitem(HttpServletRequest request, HttpServletResponse response);
}
6) ItemServiceImpl 클래스에 상세보기를 위한 메소드를 구현
![]() |
7) ItemController 클래스에 상세보기를 위한 메소드를 구현
package kr.co.pk.item.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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 kr.co.pk.item.service.ItemService;
@Controller
public class ItemController {
@Autowired
private ItemService itemService;
@RequestMapping(value = {"/", "index.html"}, method = RequestMethod.GET)
public String home(HttpServletRequest request, HttpServletResponse response) {
//서비스의 메소드를 호출
itemService.allitem(request, response);
return "home";
}
@RequestMapping(value = {"detail/{itemid}"}, method = RequestMethod.GET)
public String detail(HttpServletRequest request, HttpServletResponse response) {
//서비스의 메소드를 호출
itemService.detailitem(request, response);
return "detail";
}
}
8) 이미지를 프로젝트 내에 복사
=>webapp 디렉토리에 img 디렉토리를 배치
9)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상세보기</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css">
</head>
<body>
<div align="center" class="body">
<h2>상품 상세 화면</h2>
<table border="1">
<tr class="header">
<td>
<img src="${pageContext.request.contextPath}/img/${item.pictureurl}"/>
<td>
<td>
<table>
<tr height="50">
<td width="80">상품명</td>
<td width="160">${item.itemname}</td>
</tr>
<tr height="50">
<td width="80">가격</td>
<td width="160">${item.price}원</td>
</tr>
<tr height="50">
<td width="80">비고</td>
<td width="160">${item.description}</td>
</tr>
<tr>
<td colspan="2" align="center" width="240">
<a href="${pageCOntext.request.contextPath}/">
■목록으로 돌아가기
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</body>
</html>
6. MySQL로 변환
1) pom.xml 파일에 mysql 의존성을 추가
<!-- MySQL 의존성 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
MySQL에 테이블 생성
-- 테이블이 존재하면 삭제
drop table item;
-- 테이블 생성
-- 데이터를 삽입하고 삭제하고 갱신하는 일이 빈번하면 innodb
-- 주로하는 일이 조회라면 MyISAM(Indexed Sequential Access Media) 으로 설정
-- 한글이 있으면 인코딩 설정을 해주어야 한다.
CREATE TABLE ITEM(
itemid int,
itemname VARCHAR(20),
price int,
description VARCHAR(50),
pictureurl VARCHAR(20),
PRIMARY KEY (itemid)
)engine=innodb default charset=utf8;
insert into item values(1, 'Lemon', 500, 'Vitamin-A', 'lemon.jpg');
insert into item values(2, 'Orange', 1500, 'Vitamin-B', 'orange.jpg');
insert into item values(3, 'Kiwi', 2000, 'Vitamin-C', 'kiwi.jpg');
insert into item values(4, 'Grape', 1000, 'Vitamin-D', 'grape.jpg');
insert into item values(5, 'Strawberry', 2000, 'Vitamin-E', 'strawberry.jpg');
insert into item values(6, 'Mandarin', 300, 'Vitamin-F', 'mandarin.jpg');
commit;
select * from ITEM;
2) 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 모든 곳에서 사용할 Bean을 생성 -->
<!-- 데이터베이스 접속 정보를 저장하는 bean을 생성 데이터베이스 종류별로 설정 -->
<!--
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@192.168.0.200:1521:xe</value>
</property>
<property name="username">
<value>user05</value>
</property>
<property name="password">
<value>user05</value>
</property>
</bean>
-->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://192.168.0.200:3306/sample?useUnicode=yes&characterEncoding=UTF-8</value>
</property>
<property name="username">
<value>user05</value>
</property>
<property name="password">
<value>user05</value>
</property>
</bean>
<!-- XML을 이용한 MyBatis 사용 설정 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- mappers 디렉토리 안에 있는 모든 xml을 mapper로 사용 다른 용도의 xml 파일이 있으면 에러 -->
<property name="mapperLocations" value="classpath:mappers/**/*.xml" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
</beans>
7. Mapper 인터페이스를 이용한 MyBatis 사용
=> Mapper 인터페이스를 이용하면 xml 파일을 만들 필요없고 DAO도 만들 필요가 없다.
1) Mapper 로 사용할 인터페이스를 생성하고 테이블의 전체 데이터를 가져오는 메소드와 itemid를 이용해서 1개를 찾아오는 메소드를 생성
=> kr.co.pk.item.dao.ItemMapper
package kr.co.pk.item.dao;
import java.util.List;
import org.apache.ibatis.annotations.Select;
import kr.co.pk.item.domain.Item;
public interface ItemMapper {
@Select("select itemid, itemname, price, description, pictureurl from item")
public List<Item> allitem();
@Select("select itemid, itemname, price, description, pictureurl from item where itemid = {itemid}")
public Item detailitem(Integer itemid);
}
2) root-context.xml 파일에 MapperFactoryBean 생성
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 모든 곳에서 사용할 Bean을 생성 -->
<!-- 데이터베이스 접속 정보를 저장하는 bean을 생성 데이터베이스 종류별로 설정 -->
<!--
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@192.168.0.200:1521:xe</value>
</property>
<property name="username">
<value>user05</value>
</property>
<property name="password">
<value>user05</value>
</property>
</bean>
-->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://192.168.0.200:3306/sample?useUnicode=yes&characterEncoding=UTF-8</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>asdqwe123</value>
</property>
</bean>
<!-- XML을 이용한 MyBatis 사용 설정 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- mappers 디렉토리 안에 있는 모든 xml을 mapper로 사용 다른 용도의 xml 파일이 있으면 에러 -->
<property name="mapperLocations" value="classpath:mappers/**/*.xml" />
</bean>
<!-- XML을 이용해서 MyBatis를 사용할 때 생성 -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
<!-- 인터페이스를 이용해서 MyBatis를 이용할 때 생성 -->
<bean id="goodMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
<property name="mapperInterface" value="kr.co.pk.item.dao.ItemMapper"/>
</bean>
</beans>
3) ServiceImpl 클래스에서 GoodMapper를 주입받아서 사용하면 된다.
package kr.co.pk.item.service;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import kr.co.pk.item.dao.ItemDAO;
import kr.co.pk.item.dao.ItemMapper;
import kr.co.pk.item.domain.Item;
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
//private ItemDAO itemDao;
private ItemMapper itemDao;
@Override
public void allitem(HttpServletRequest request, HttpServletResponse response) {
//1.파라미터 읽기
//2.필요한 처리 수행
//3.DAO 메소드의 매개변수 생성
//4.DAO 메소드를 호출
List<Item> list = itemDao.allitem();
//5.결과를 가공
//6.결과를 저장 - REST API Server의 경우는 request에 저장
request.setAttribute("list", list);
}
@Override
public void detailitem(HttpServletRequest request, HttpServletResponse response) {
//요청 주소의 마지막 부분을 가져오기
//localhost/detail/itemid
String requestURI = request.getRequestURI();
String [] ar = requestURI.split("/");
String itemid = ar[ar.length-1];
//DAO의 메소드를 호출
Item item = itemDao.detailitem(Integer.parseInt(itemid));
//결과를 저장
request.setAttribute("item", item);
}
}
4) 전자 정부 프레임 워크나 기업에서 만든 프레임워크들은 샘플 프로젝트에서 xml을 이용하는 방식을 채택
8. hibernate로 변환
=> DTO 클래스를 확인 : 자료형을 확인
1) pom.xml 파일에 hibernate와 spring-orm의 의존성을 설정
<!-- hibernate 의존성 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework-version}</version>
</dependency>
2) Item 클래스와 Item 테이블을 매핑하기 위한 하이버네이트 설정 파일을 작성
=> kr.co.pk.item.dao 패키지에서 item.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="kr.co.pk.item.domain">
<class name="Item" table="ITEM">
<id name="itemid" column="itemid"/>
<property name="itemname" column="itemname"/>
<property name="price" column="price"/>
<property name="description" column="description"/>
<property name="pictureurl" column="pictureurl"/>
</class>
</hibernate-mapping>
3) root-context.xml 파일에 hibernate bean을 추가
=> 하이버네이트는 트랜잭션이 필수라서 tx 네임스페이스 추가
![]() |
<!-- 하이버네이트 설정 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>kr/co/pk/item/dao/item.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>hibernate.dialect=org.hibernate.dialect.MySQLDialect</value>
</property>
</bean>
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
4) ItemDAO 클래스에 Hibernate의 SessionFactory를 주입하고 메소드 코드를 수정
package kr.co.pk.item.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import kr.co.pk.item.domain.Item;
@Repository
public class ItemDAO {
@Autowired
//MyBatis를 xml로 이용할 때 사용하는 클래스
private SqlSession sqlSession;
@Autowired
//Hibernate는 SessionFactory
private SessionFactory sessionFactory;
//Item 테이블의 전체 데이터를 가져오는 메소드
public List<Item> allitem(){
//return sqlSession.selectList("item.allitem");
return sessionFactory.getCurrentSession().createCriteria(Item.class).list();
}
//Item 테이블에서 1개의 데이터를 가져오는메소드
public Item detailitem(Integer itemid) {
//return sqlSession.selectOne("item.detailitem", itemid);
return sessionFactory.getCurrentSession().get(Item.class, itemid);
}
}
5) ItemServiceImpl의 메소드위에 @Transactional추가
package kr.co.pk.item.service;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import kr.co.pk.item.dao.ItemDAO;
import kr.co.pk.item.dao.ItemMapper;
import kr.co.pk.item.domain.Item;
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
//private ItemDAO itemDao;
private ItemMapper itemDao;
@Override
@Transactional
public void allitem(HttpServletRequest request, HttpServletResponse response) {
//1.파라미터 읽기
//2.필요한 처리 수행
//3.DAO 메소드의 매개변수 생성
//4.DAO 메소드를 호출
List<Item> list = itemDao.allitem();
//5.결과를 가공
//6.결과를 저장 - REST API Server의 경우는 request에 저장
request.setAttribute("list", list);
}
@Override
@Transactional
public void detailitem(HttpServletRequest request, HttpServletResponse response) {
//요청 주소의 마지막 부분을 가져오기
//localhost/detail/itemid
String requestURI = request.getRequestURI();
String [] ar = requestURI.split("/");
String itemid = ar[ar.length-1];
//DAO의 메소드를 호출
Item item = itemDao.detailitem(Integer.parseInt(itemid));
//결과를 저장
request.setAttribute("item", item);
}
}
실행
** XML
=> Hyper Text Markup Language : Tag를 브라우저가 해석해서 랜더링
=> eXtensible Markup Language : 확장 마크업 언어
XML은 태그의 의미를 DTD에 설정한 곳이나 개발자가 해석
HTML이 구조적이지 못해서 데이터를 표현하는데 한계가 있어서 만들어 낸 데이터 표현 포맷
프로젝트 설정이나 Open API에 많이 이용
프로젝트 설정 파일로 사용되는 경우에는 우리가 해석할 수 없고 해석을 대신해주는 DTD를 상단에 선언해 주어야 한다.
** Spring MVC Project에서 사용되는 XML
=> server.xml : Tomcat의 설정파일이다.
=> pom.xml : Maven의 설정파일 (Maven은 빌드도구)
=> web.xml : Web Application의 설정 파일
여기까지는 이름이 고정
applicationContext.xml : Spring MVC 전체에서 사용되는 설정 파일
dispatcher-servlet.xml : URL 패턴에 해당하는 요청에만 사용하는 설정 파일
mybatis의 환경설정 파일과 매퍼 파일 - 대신 인터페이스를 사용할 수 있다.
hibernate의 경우는 매퍼 파일이 XML로 되어 있다.
** 개발 환경
Operating System : Windows10
Database : Oracle
Programming Language : Java
IDE : Eclipse
WAS: Apache Tomcat 9.0
Build Tool : Maven
Unit Test : JUnit
SCM(Software Configuration Management - 형상관리) : Git Hub
Framework. : Spring 5.0, MyBatis
jQuery는 안쓰는게 좋고, 뷰 나 react는 쓰는게 좋다.
** pom.xml 파일의 주요 태그
1. properties
=> 아래에서 많이 사용할 문자열을 태그로 만들어두는 것
2. repositories
=> 기본적으로 Maven 중장 저장소에서 다운로드를 받는데 다른 곳에서 다운로드 받고자 할 때 다운로드 받을 위치를 설정
3. dependencies
=> 사용할 외부 라이브러리
** Spring MVC Project 구조
1. 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">
<!-- 애플리케이션이 시작될 때나 종료될 대 또는 세션이 만들어질 때 세션이 소멸 될 때 등의 이벤트가 발생하면 호출되는객체의 클래스를 설정하는 태그가 listener
WEB-INF 디렉토르에 applicationContext.xml 파일이 있어야 한다. -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- applicationContext.xml 파일의 경로를 수정하는 설정 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- URL 패턴에 ㄸ라서 사용할 스프링 설정 파일을 지정하는 태그 -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<!-- /는 .jsp를 제외한 모든 요청에 응답 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2. root-context.xml
=> 모든곳에서 사용할 bean을 설정하는 파일
=> 데이터베이스 접속 정보를 생성
3. servlet-context.xml
=> web.xml 파일에 설정한 url 패턴에 해당하는 요청이 왔을 때 사용할 bean을 설정하는 파일
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Spring MVC Profect에서 사용하는 50여 가지의 어노테이션을 사용할 수 있도록 해주는 설정 -->
<annotation-driven />
<!-- 변화가 거의 없는 파일들을 저장해 두면 캐싱을 해서 이용할 수 있도록 해주는 설정
기본은 root(webapp, WebContent) 디렉토리의 resources 캐싱 시간을 설정하는 것도 가능-->
<resources mapping="/resources/**" location="/resources/" />
<!-- Controller에서 forwarding 하는 view이름을 넘겨주었을 때 실제 사용할 View를 결정짓는 설정 -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<!-- bean을 자동 생성해주는 root 패키지 설정
클래스를 만들 때는 이 패키지 안에 만드는 것을 권장, 다른 패키지에 만들었다면 다른 패키지도 추가해주면 된다. -->
<context:component-scan base-package="kr.co.pk" />
</beans:beans>
4. kr.co.pk 패키지에 가면 HomeController가 생성되어 있음
// 시작 요청이 오면 home으로 포워딩 :
servlet-context.xml 파일의 ViewResolver와 결합해서 실제 출력할 View를 결정한다.
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
return "home";
}
** 하나의 서비스 구현 절차
=> 어디에서 요청을 할 것인지 그리고 어떤 요청을 할 것인지 결정
시작하자마자는 /
=> 대부분의 서비스는 2가지 형태
바로 데이터를 요청해서 출력하는 서비스 : 목록보기나 상세보기
요청 -> Controller -> Service -> DAO -> 저장소 -> DAO -> Service -> Controller -> View
입력화면을 이용해서 파라미터를 입력받고 요청을 해서 출력 : 삽입, 수정, 삭제, 로그인, 검색
요청 -> Controller -> View -> Controller -> Service -> DAO -> 저장소 -> DAO -> Service -> Controller -> View : 삽입
요청 -> Controller -> Service -> DAO -> 저장소 -> DAO -> Service -> Controller -> View -> 요청 -> Controller -> Service -> DAO -> 저장소 -> DAO -> Service -> Controller -> View : 수정
** url 패턴을 / 나 /* 을 사용했을 때의 문제점
/ : .jsp를 제외한 모든 요청을 처리
/* : 모든 요청을 처리
=> css 나 js 처럼 확장자가 jsp가 아니면 Controller가 처리할려고 하고 Controller에 처리하는 코드가 없으면 404에러가 발생
=> servlet-context.xml파일에 Controller가 처리하지 않으면 WAS가 처리하도록 해주는 설정을 추가해 주어야 한다.
** 집에 있는 PC를 고정된 IP를 갖도록 할 수 있다.
=> IP 공유기를 사용하시는 분들은 자신의 IP 공유기 제조회사와 포트 포워딩을 검색
** Oracle과 MySQL의 차이
1. 테이블을 생성할 때 자료형의 차이
오라클은 숫자를 number로 만들지만 MySQL은 int, float으로 생성
오라클은 문자열을 char, varchar2, clob 로 표현하지만 MySQL은 char, varchar, text로 표현
오라클은 sequence로 일련번호를 만들지만 MySQL은 auto_increment로 생성
2. 조회에서의 차이
오라클은 페이징(나누어서 가져오기)을 할 대 인라인 뷰를 사용하지만 MySQL은 limit 구문 이용
오라클은 인코딩 설정을 하지 않아도 되지만 MySQL은 반드시 인코딩 설정을 해주어야 한다.
** hibernate
=> ORM : Object Relation Mapper - 객체와 데이터베이스 테이블의 데이터를 매핑시키는 프레임워크
최근에 등장하는 데이터베이스 연동 프레임워크는 거의 대부분은 ORM이다.