kr.spring.util
생성하고 새 클래스 PagingUtil
생성package kr.spring.util;
public class PagingUtil {
private int startCount; // 한 페이지에서 보여줄 게시글의 시작 번호
private int endCount; // 한 페이지에서 보여줄 게시글의 끝 번호
private StringBuffer pagingHtml;// 페이지 표시 문자열
/**
* currentPage : 현재페이지
* totalCount : 전체 게시물 수
* rowCount : 한 페이지의 게시물의 수
* pageCount : 한 화면에 보여줄 페이지 수
* pageUrl : 호출 페이지 url
* addKey : 부가적인 key 없을 때는 null 처리 (&num=23형식으로 전달할 것)
* */
public PagingUtil(int currentPage, int totalCount, int rowCount,
int pageCount, String pageUrl) {
this(null,null,currentPage,totalCount,rowCount,pageCount,pageUrl,null);
}
public PagingUtil(int currentPage, int totalCount, int rowCount,
int pageCount, String pageUrl, String addKey) {
this(null,null,currentPage,totalCount,rowCount,pageCount,pageUrl,addKey);
}
public PagingUtil(String keyfield, String keyword, int currentPage, int totalCount, int rowCount,
int pageCount,String pageUrl) {
this(keyfield,keyword,currentPage,totalCount,rowCount,pageCount,pageUrl,null);
}
public PagingUtil(String keyfield, String keyword, int currentPage, int totalCount, int rowCount,
int pageCount,String pageUrl,String addKey) {
String sub_url = "";
if(keyword != null) sub_url = "&keyfield="+keyfield+"&keyword="+keyword;
if(addKey != null) sub_url += addKey;
// 전체 페이지 수
int totalPage = (int) Math.ceil((double) totalCount / rowCount);
if (totalPage == 0) {
totalPage = 1;
}
// 현재 페이지가 전체 페이지 수보다 크면 전체 페이지 수로 설정
if (currentPage > totalPage) {
currentPage = totalPage;
}
// 현재 페이지의 처음과 마지막 글의 번호 가져오기.
startCount = (currentPage - 1) * rowCount + 1;
endCount = currentPage * rowCount;
// 시작 페이지와 마지막 페이지 값 구하기.
int startPage = (int) ((currentPage - 1) / pageCount) * pageCount + 1;
int endPage = startPage + pageCount - 1;
// 마지막 페이지가 전체 페이지 수보다 크면 전체 페이지 수로 설정
if (endPage > totalPage) {
endPage = totalPage;
}
// 이전 block 페이지
pagingHtml = new StringBuffer();
if (currentPage > pageCount) {
pagingHtml.append("<a href="+pageUrl+"?pageNum="+ (startPage - 1) + sub_url +">");
pagingHtml.append("[이전]");
pagingHtml.append("</a>");
}
//페이지 번호.현재 페이지는 빨간색으로 강조하고 링크를 제거.
for (int i = startPage; i <= endPage; i++) {
if (i > totalPage) {
break;
}
if (i == currentPage) {
pagingHtml.append(" <b><span style='color:red;'>");
pagingHtml.append(i);
pagingHtml.append("</span></b>");
} else {
pagingHtml.append(" <a href='"+pageUrl+"?pageNum=");
pagingHtml.append(i);
pagingHtml.append(sub_url+"'>");
pagingHtml.append(i);
pagingHtml.append("</a>");
}
pagingHtml.append(" ");
}
// 다음 block 페이지
if (totalPage - startPage >= pageCount) {
pagingHtml.append("<a href="+pageUrl+"?pageNum="+ (endPage + 1) + sub_url +">");
pagingHtml.append("[다음]");
pagingHtml.append("</a>");
}
}
public StringBuffer getPagingHtml() {
return pagingHtml;
}
public int getStartCount() {
return startCount;
}
public int getEndCount() {
return endCount;
}
}
views
폴더에 새 JSP 파일 selectDetail.jsp
생성<%@ 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}/resources/css/style.css">
</head>
<body>
<div class="page-main">
<h2>${board.title}</h2>
<p>
글 번호 : ${board.num}<br>
작성자 : ${board.name}<br>
작성일 : ${board.reg_date}
</p>
<hr width="100%" size="1" noshade>
<p>
${board.content}
</p>
<hr width="100%" size="1" noshade>
<div class="align-center">
<input type="button" value="수정" onclick="location.href = 'update.do?num=${board.num}';">
<input type="button" value="삭제" onclick="location.href = 'delete.do?num=${board.num}';">
<input type="button" value="목록" onclick="location.href = 'list.do';">
</div>
</div>
</body>
</html>
views
폴더에 새 JSP 파일 updateForm.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>수정 폼</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/style.css">
</head>
<body>
<div class="page-main">
<h2>글 수정 폼</h2>
<form:form modelAttribute="boardVO">
<ul>
<li>
<form:label path="name">작성자</form:label>
<form:input path="name"/>
<form:errors path="name" cssClass="error-color"/>
</li>
<li>
<form:label path="title">제목</form:label>
<form:input path="title"/>
<form:errors path="title" cssClass="error-color"/>
</li>
<li>
<form:label path="passwd">비밀번호</form:label>
<form:password path="passwd"/>
<form:errors path="passwd" cssClass="error-color"/>
</li>
<li>
<form:label path="content">내용</form:label>
<form:textarea path="content"/>
<form:errors path="content" cssClass="error-color"/>
</li>
</ul>
<div class="align-center">
<form:button>수정</form:button>
<input type="button" value="홈으로" onclick="location.href = 'list.do';"/>
</div>
</form:form>
</div>
</body>
</html>
views
폴더에 새 JSP 파일 deleteForm.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글 삭제 폼</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/style.css">
</head>
<body>
<div class="page-main">
<h2>글 삭제 폼</h2>
<form:form action="delete.do" modelAttribute="boardVO">
<form:hidden path="num"/>
<ul>
<li>
<form:label path="passwd">비밀번호</form:label>
<form:password path="passwd"/>
<form:errors path="passwd" cssClass="error-color"/>
</li>
</ul>
<div class="align-center">
<form:button>삭제</form:button>
<input type="button" value="홈으로" onclick="location.href = 'list.do';">
</div>
</form:form>
</div>
</body>
</html>
src/main/resources
폴더에서 log4j.xml
오른쪽 클릭하고 Open With-XML Editor 선택해서 다음의 내용을 수정 <!-- Application Loggers -->
<logger name="kr.spring">
<level value="info" />
</logger>
BoardController
클래스에 다음의 프로퍼티를 추가 // 로그 처리(로그 대상 지정)
private static final Logger logger = LoggerFactory.getLogger(BoardController.class);
BoardController
클래스의 process()
메서드를 다음처럼 수정 // 목록
@RequestMapping("/list.do")
public ModelAndView process(@RequestParam(value="pageNum", defaultValue="1") int currentPage) {
int count = boardService.getBoardCount();
logger.info("pageNum : " + currentPage);
logger.info("count : " + count);
// 페이지 처리
PagingUtil page = new PagingUtil(currentPage, count, 10, 10, "/list.do");
List<BoardVO> list = null;
if(count>0) {
list = boardService.getBoardList(page.getStartCount(), page.getEndCount());
}
ModelAndView mav = new ModelAndView();
mav.setViewName("selectList");
mav.addObject("count", count);
mav.addObject("list", list);
mav.addObject("pagingHtml", page.getPagingHtml());
return mav;
}
BoardVO
클래스에서 toString()
메서드를 재정의 @Override
public String toString() {
return "BoardVO [num=" + num + ", name=" + name + ", title=" + title + ", passwd=" + passwd + ", content="
+ content + ", reg_date=" + reg_date + "]";
}
BoardController
클래스의 submit()
메서드를 다음처럼 수정 // 글쓰기 폼에서 전송된 데이터 처리
@PostMapping("/insert.do")
public String submit(BoardVO boardVO, BindingResult result) {
logger.info("BoardVO : " + boardVO);
// 유효성 검증
new BoardValidator().validate(boardVO, result);
// 유효성 검증 결과 오류가 있으면 폼 호출
if(result.hasErrors()) {
return form();
}
// 글 등록
boardService.insertBoard(boardVO);
return "redirect:/list.do";
}
BoardController
클래스의 submitUpdate()
메서드를 다음처럼 수정 // 수정 폼에서 전송된 데이터 처리
@PostMapping("/update.do")
public String submitUpdate(BoardVO boardVO, BindingResult result) {
logger.info("BoardVO : " + boardVO);
// 유효성 검증
new BoardValidator().validate(boardVO, result);
// 유효성 검증 결과 오류가 있으면 수정 폼 호출
if(result.hasErrors()) {
return "updateForm";
}
// DB에 저장된 비밀번호 구하기
BoardVO db_board = boardService.getBoard(boardVO.getNum());
// 비밀번호 검증
if(!db_board.getPasswd().equals(boardVO.getPasswd())) { // DB에 저장된 비밀번호와 사용자가 입력한 비밀번호가 불일치하면
result.rejectValue("passwd", "invalidPassword");
return "updateForm";
}
// 글 수정
boardService.updateBoard(boardVO);
return "redirect:/list.do";
}
INFO
로 지정하면 FATAL
, ERROR
, WARN
, INFO
레벨의 로그가 모두 출력됨로그 레벨 | 의미 |
---|---|
FATAL |
가장 심각한 오류 |
ERROR |
일반적인 오류 |
WARN |
주의를 요하는 경우 |
INFO |
런타임시 관심 있는 내용 |
DEBUG |
시스템 흐름과 관련된 상세 정보 |
TRACE |
가장 상세한 정보 |
pom.xml
에서 <dependencies>
태그 사이에 다음의 내용을 추가 <dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions</artifactId>
<version>3.9.3</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
root-context.xml
에서 <beans>
태그 사이에 다음의 내용을 추가 <!-- JDBC 기반 트랜잭션 관리자 설정 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"/>
root-context.xml
에서 <beans>
태그 사이에 다음의 내용을 추가 <!-- 선언적 트랜잭션 처리 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="update*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(public * kr.spring.board..*ServiceImpl.*(..))" id="servicePublicMethod"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="servicePublicMethod"/>
</aop:config>
BoardServiceImpl
클래스에서 updateBoard()
메서드 하단에 boardDAO.insertBoard(board);
를 추가하고, BoardDAOImpl
클래스에서 INSERT_SQL
을 임의로 오류 발생하도록 변경root-context.xml
에서 <tx:advice>
태그와 <aop:config>
태그를 주석 처리root-context.xml
에서 <beans>
태그 사이에 다음의 내용을 추가 <!-- 어노테이션 방식으로 처리할 때 반드시 명시 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional
BoardServiceImpl
클래스에서 updateBoard()
메서드에 @Transactional
어노테이션 적용BoardServiceImpl
클래스에서 updateBoard()
메서드 하단에 boardDAO.insertBoard(board);
를 추가하고, BoardDAOImpl
클래스에서 INSERT_SQL
을 임의로 오류 발생하도록 변경ch06MybatisSqlSession
, 최상위 패키지명을 kr.spring.mybatis
로 지정하고 Spring MVC Project 선택pom.xml
에서 <properties>
태그 사이의 내용을 다음처럼 변경 <java-version>1.8</java-version>
<org.springframework-version>5.0.20.RELEASE</org.springframework-version>
pom.xml
에서 <properties>
태그 종료 이후, <dependencies>
태그 시작 이전에 다음의 내용을 추가 <!-- Oracle 드라이버 설정 시작 -->
<repositories>
<repository>
<id>oracle</id>
<name>ORACLE JDBC Repository</name>
<url>https://code.lds.org/nexus/content/groups/main-repo</url>
</repository>
</repositories>
<!-- Oracle 드라이버 설정 끝 -->
pom.xml
에서 <dependencies>
태그 사이에 다음의 내용을 추가 <!-- 라이브러리 추가 시작 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.20.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.7.0.0</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions</artifactId>
<version>3.9.3</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.18.Final</version>
</dependency>
<!-- 라이브러리 추가 끝 -->
src/main/webapp/WEB-INF
의 web.xml
열고 <web-app>
태그 사이에 다음의 내용을 추가 <filter> <!-- POST 방식 전송시 인코딩 처리를 위해 내장된 필터를 사용; 필터는 요청이 DispatcherServlet에 의해 다뤄지기 전,후에 동작 -->
<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> <!-- 컨텍스트 루트 하위의 모든 요청(*.do뿐만 아니라 *.jsp 등 확장자가 다른 경우까지 포함)에 대해 인코딩 필터 처리하도록 설정 -->
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
src/main/webapp/WEB-INF/spring/appServlet
에서 servlet-context.xml
열고 <context:component-scan>
태그를 다음처럼 수정 <context:component-scan base-package="kr.spring.board.controller" />
servlet-context.xml
의 <beans:beans>
태그 사이에 다음의 내용을 추가 <!-- messageSource 지정 -->
<beans:bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<beans:property name="basenames">
<beans:list>
<beans:value>messages.validation</beans:value>
</beans:list>
</beans:property>
</beans:bean>
src/main/webapp/WEB-INF/spring
에서 root-context.xml
열고 <beans>
태그를 다음처럼 수정<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
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-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!--
bean 자동 스캔 : servlet-context.xml에서 Controller를 자동 스캔 설정하였으므로 root-context.xml에서는 Controller 자동 스캔 제외(이중 스캔 방지)
-->
<context:component-scan base-package="kr.spring.board">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- jdbc.properties 등록 -->
<context:property-placeholder location="classpath:config/jdbc.properties"/>
<!-- 커넥션 풀을 이용한 DataSource 설정 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 최대 커넥션 개수 -->
<property name="maxActive" value="50"/>
<!-- 접속이 없을 경우 최대 유지 커넥션 개수 -->
<property name="maxIdle" value="30"/>
<!-- 접속이 없을 경우 최소 유지 커넥션 개수 -->
<property name="minIdle" value="20"/>
<!-- 최대 대기 시간(초 단위) : 초과시 연결 실패 오류 발생 -->
<property name="maxWait" value="5"/>
</bean>
<!-- JDBC 기반 트랜잭션 관리자 설정 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"/>
<!-- 어노테이션 방식으로 처리할 때 반드시 명시 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
src/main/resources
에 새 폴더 config
생성하고 새 파일 jdbc.properties
생성jdbc.driverClassName=oracle.jdbc.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:xe
jdbc.username=scott
jdbc.password=tiger
src/main/resources
에 새 폴더 messages
생성하고 새 파일 validation.properties
생성# 어노테이션
NotEmpty.name=작성자는 필수 항목
NotEmpty.title=제목은 필수 항목
NotEmpty.passwd=비밀번호는 필수 항목
NotEmpty.content=내용은 필수 항목
# 직접 reject
invalidPassword=비밀번호 불일치
src/main/resources
폴더에서 log4j.xml
오른쪽 클릭하고 Open With-XML Editor 선택해서 다음의 내용을 수정 <!-- Application Loggers -->
<logger name="kr.spring">
<level value="info" />
</logger>
webapp
폴더에 하위 폴더로 sql
생성하고 ch05JDBC
프로젝트에서 같은 위치의 table.sql
복사해서 붙여넣기ch05JDBC
프로젝트의 webapp/resources
에서 css
폴더를 복사해서 ch06MybatisSqlSession
프로젝트의 같은 위치에 붙여넣기webapp
폴더 오른쪽 클릭하고 새 JSP 파일 index.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
response.sendRedirect(request.getContextPath() + "/list.do");
%>
kr.spring.mybatis
패키지 삭제kr.spring.board.vo
생성하고 새 클래스 BoardVO
생성package kr.spring.board.vo;
import java.sql.Date;
import javax.validation.constraints.NotEmpty;
public class BoardVO {
private int num;
@NotEmpty
private String name;
@NotEmpty
private String title;
@NotEmpty
private String passwd;
@NotEmpty
private String content;
private Date reg_date;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getReg_date() {
return reg_date;
}
public void setReg_date(Date reg_date) {
this.reg_date = reg_date;
}
@Override
public String toString() {
return "BoardVO [num=" + num + ", name=" + name + ", title=" + title + ", passwd=" + passwd + ", content="
+ content + ", reg_date=" + reg_date + "]";
}
}
kr.spring.board.dao
생성하고 새 XML 파일 BoardMapper.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="BoardDAO">
</mapper>
config
폴더에 새 XML 파일 SqlMapConfig.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 alias="boardVO" type="kr.spring.board.vo.BoardVO"/> <!-- XML에서는 패키지명까지 포함한 전체 이름을 호출해야 자바빈 정보를 읽어올 수 있는데, alias를 부여하면 alias로 자바빈 정보를 읽어올 수 있음 -->
</typeAliases>
<mappers>
<mapper resource="kr/spring/board/dao/BoardMapper.xml"/>
</mappers>
</configuration>
root-context.xml
에서 <beans>
태그 사이에 다음의 내용을 추가 <!-- MyBatis 설정 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:config/SqlMapConfig.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory"/>
</bean>
kr.spring.board.dao
패키지에 새 인터페이스 BoardDAO
생성package kr.spring.board.dao;
import java.util.List;
import java.util.Map;
import kr.spring.board.vo.BoardVO;
public interface BoardDAO {
public void insertBoard(BoardVO board);
public int getBoardCount();
public List<BoardVO> getBoardList(Map<String, Object> map); // MyBatis에서는 메서드에 인자를 하나만 명시하므로 여러 개를 전달해야 할 때는 Map 객체 이용
public BoardVO getBoard(int num);
public void updateBoard(BoardVO board);
public void deleteBoard(int num);
}
BoardDAOImpl
생성package kr.spring.board.dao;
import java.util.List;
import java.util.Map;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import kr.spring.board.vo.BoardVO;
@Repository // 자동 스캔 처리
public class BoardDAOImpl implements BoardDAO {
@Autowired
private SqlSessionTemplate sqlSession;
@Override
public void insertBoard(BoardVO board) {
sqlSession.insert("insertBoard", board);
}
@Override
public int getBoardCount() {
Integer count = sqlSession.selectOne("getBoardCount");
return count;
}
@Override
public List<BoardVO> getBoardList(Map<String, Object> map) {
return sqlSession.selectList("getBoardList", map); // 인자로 XML에 포함된 SQL문 호출에 사용할 식별자와 ?에 바인딩할 데이터가 담긴 Map 객체 전달
}
@Override
public BoardVO getBoard(int num) {
return sqlSession.selectOne("getBoard", num); // 자바빈 또는 Map 객체가 아니라 값 하나만 전달시, 해당 값이 담긴 변수명 num이 데이터 바인딩시의 식별자로 사용됨
}
@Override
public void updateBoard(BoardVO board) {
sqlSession.update("updateBoard", board);
}
@Override
public void deleteBoard(int num) {
sqlSession.delete("deleteBoard", num);
}
}
BoardMapper.xml
의 <mapper>
태그 사이에 다음의 내용을 추가 <!-- 목록 -->
<select id="getBoardList" resultType="boardVO" parameterType="map"> <!-- java.util.Map의 alias가 map -->
SELECT
*
FROM (SELECT
a.*, ROWNUM AS rnum
FROM (
SELECT
*
FROM tboard
ORDER BY num DESC) a)
<![CDATA[
WHERE rnum >= #{start} AND rnum <= #{end}
]]> <!-- <는 XML에서 태그를 시작하는 기호라 문법 검사시 에러가 발생하므로, CDATA를 이용하여 문법 검사를 건너뛰도록 처리; SQL문에 Map 객체의 데이터를 바인딩시, #{key} 형식으로 key의 값을 호출 -->
</select>
kr.spring.board.service
생성하고 새 인터페이스 BoardService
생성package kr.spring.board.service;
import java.util.List;
import java.util.Map;
import kr.spring.board.vo.BoardVO;
public interface BoardService {
public void insertBoard(BoardVO board);
public int getBoardCount();
public List<BoardVO> getBoardList(Map<String, Object> map); // MyBatis에서는 메서드에 인자를 하나만 명시하므로 여러 개를 전달해야 할 때는 Map 객체 이용
public BoardVO getBoard(int num);
public void updateBoard(BoardVO board);
public void deleteBoard(int num);
}
BoardServiceImpl
생성package kr.spring.board.service;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import kr.spring.board.dao.BoardDAO;
import kr.spring.board.vo.BoardVO;
@Service // 자동 스캔 처리
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardDAO boardDAO;
@Override
public void insertBoard(BoardVO board) {
boardDAO.insertBoard(board);
}
@Override
public int getBoardCount() {
return boardDAO.getBoardCount();
}
@Override
public List<BoardVO> getBoardList(Map<String, Object> map) {
return boardDAO.getBoardList(map);
}
@Override
public BoardVO getBoard(int num) {
return boardDAO.getBoard(num);
}
@Override
public void updateBoard(BoardVO board) {
boardDAO.updateBoard(board);
}
@Override
public void deleteBoard(int num) {
boardDAO.deleteBoard(num);
}
}
kr.spring.board.controller
생성하고 새 클래스 BoardController
생성package kr.spring.board.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import kr.spring.board.service.BoardService;
import kr.spring.board.vo.BoardVO;
import kr.spring.util.PagingUtil;
@Controller
public class BoardController {
@Autowired
private BoardService boardService;
// 로그 처리(로그 대상 지정)
private static final Logger logger = LoggerFactory.getLogger(BoardController.class);
// 목록
@RequestMapping("/list.do")
public ModelAndView getList(@RequestParam(value="pageNum", defaultValue="1") int currentPage) {
// 총 레코드 수
int count = boardService.getBoardCount();
// 페이지 처리
PagingUtil page = new PagingUtil(currentPage, count, 10, 10, "list.do");
// 목록 호출
List<BoardVO> list = null;
if(count>0) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("start", page.getStartCount());
map.put("end", page.getEndCount());
list = boardService.getBoardList(map);
}
ModelAndView mav = new ModelAndView();
// view 이름 지정
mav.setViewName("selectList");
// 데이터 저장
mav.addObject("list", list);
mav.addObject("count", count);
mav.addObject("pagingHtml", page.getPagingHtml());
return mav;
}
}
views
폴더에서 home.jsp
삭제하고 새 JSP 파일 selectList.jsp
생성<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시판 목록</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/style.css">
</head>
<body>
<div class="page-main">
<h2>게시판 목록</h2>
<div class="align-right">
<input type="button" value="글쓰기" onclick="location.href = 'insert.do';">
</div>
<c:if test="${count==0}">
<div class="result-display">
표시할 내용이 없습니다.
</div>
</c:if>
<c:if test="${count>0}">
<table>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>작성일</th>
</tr>
<c:forEach var="board" items="${list}">
<tr>
<td>${board.num}</td>
<td><a href="detail.do?num=${board.num}">${board.title}</a></td>
<td>${board.name}</td>
<td>${board.reg_date}</td>
</tr>
</c:forEach>
</table>
<div class="align-center">${pagingHtml}</div>
</c:if>
</div>
</body>
</html>