Jsp-mybatis

이현주·2023년 10월 2일
0

JSP

목록 보기
10/11

1. JUnit4 단위 테스트 수행 방법

1) JUnit Test Case 파일 추가
2) @Test 애너테이션이 추가된 테스트 메소드 작성
3) [Run As] - [JUnit Test]

2. JUnit4 단위 테스트 주요 애너테이션

1) @Test : 실제 테스트 수행
2) @Before : @Test 이전에 수행
3) @BeforeAll : JUnit Test Case(BookUnitTest.java) 수행 이전, static 필수
4) @After : @Test 이후에 수행
5) @AfterAll : JUnit Test Case(BookUnitTest.java) 수행 이후, static 필수

3. JUnit4 단위 테스트 주의사항

1) 영속 계층(Dao)을 테스트 한다.
2) WAS(Tomcat)의 개입이 없으므로 WAS가 필요한 코드는 테스트 불가하다.
3) 메소드 이름을 한글로 작성해도 상관없다.

테스트 성공시 녹색바 , 실패시 적색바

테스트로 등록된 정보

필요한것

*lib
hamcrest-core-1.3.jar
junit-4.13.2.jar
lombok.jar
mybatis-3.5.13.jar
ojdbc8.jar
taglibs 2종

*sql
[book.sql]

DROP TABLE BOOK_T;
CREATE TABLE BOOK_T (
  BOOK_NO NUMBER             NOT NULL,
  TITLE   VARCHAR2(100 BYTE) NOT NULL,
  AUTHOR  VARCHAR2(100 BYTE),
  PRICE   NUMBER,
  PUBDATE DATE,
  CONSTRAINT PK_BOOK PRIMARY KEY(BOOK_NO)
);

DROP SEQUENCE BOOK_SEQ;
CREATE SEQUENCE BOOK_SEQ NOCACHE;

mybatis.config

쿼리문을 저장하는 장소, 설정 등
[mybatis-config.xml]

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">
  
  <configuration>
  
    <!--설정 -->
  <settings>
  <setting name="mapUnderscoreToCamelCase" value="true"/>
  </settings>
  
  
  <!--환경 설정(Transaction,Connection Pool)-->
  <environments default="development">
  <environment id="development">
    <transactionManager type="JDBC"/>
    <dataSource type="POOLED">
      <property name="driver" value="oracle.jdbc.OracleDriver"/>
      <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
      <property name="username" value="GD"/>
      <property name="password" value="1111"/>
    </dataSource>
  </environment>
  </environments>
  
  <!--매퍼 설정(매퍼의 위치와 이름) -->
  <!--매퍼는 쿼리문을 저장하는 장소 (매퍼의 파일 이름을 통상적으로 테이블의 이름을 따라서 지음)  -->
  <mappers>
    <mapper resource="mybatis/mapper/book.xml"/>
  </mappers>
  

  </configuration>

junit

[BookUnitTest.java]

package junit;

import static org.junit.Assert.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Test;

import domain.BookDto;
import repository.BookDao;

/*
 
 */

public class BookUnitTest {

  // Dao
  private BookDao dao = BookDao.getDao();
  
  // @Test
  public void 책_등록_테스트() {
    
    // 등록할 BookDto 생성
    BookDto dto = BookDto.builder()
                    .title("테스트제목")
                    .author("테스트저자")
                    .price(999999)
                    .build();
    
    // BookDto 등록
    int addResult = dao.bookAdd(dto);
    
    // 등록 결과 확인
    assertEquals(1, addResult);
    
  }

  // @Test
  public void 책_조회_테스트() {
    
    // 조회할 책 번호
    int bookNo = 1;
    
    // 조회
    BookDto dto = dao.bookDetail(bookNo);
    
    // 조회 결과 확인
    assertNotNull(dto);
    
  }
  
  // @Test
  public void 책_목록_테스트() {
    
    // begin, end를 가진 Map 생성
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("begin", 1);
    map.put("end", 20);
    
    // 목록 가져오기
    List<BookDto> list = dao.bookList(map);
    
    // 결과 확인
    assertEquals(1, list.size());
    
  }
  
  // @Test
  public void 책_수정_테스트() {
    
    // 수정할 BookDto 생성
    BookDto dto = BookDto.builder()
                    .bookNo(1)
                    .title("[수정]제목")
                    .author("[수정]저자")
                    .price(-999999)
                    .build();
    
    // 수정
    int modifyResult = dao.bookModify(dto);
    
    // 결과 확인
    assertEquals(1, modifyResult);
    
  }
  
  @Test
  public void 책_삭제_테스트() {
    
    // 삭제할 책 번호
    int bookNo = 1;
    
    // 삭제
    int deleteResult = dao.bookDelete(bookNo);
    
    // 결과 확인
    assertEquals(1, deleteResult);
    
  }
  
}

mybatis.mapper

테스트를 위한 쿼리문(테스트지만 실제 db에 저장된다.)
[book.xml]

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
  
  <mapper namespace="mybatis.mapper.book" >
  
  <select id="bookCount" resultType="int">
    SELECT COUNT(*)
      FROM BOOK_T
  </select>
  
  
  <!--BookDao의  bookList메소드에서 에서 bookList라는 select태그를 호출 그래서 아이디 필요-->
    <select id="bookList" parameterType="Map" resultType="domain.BookDto">
      SELECT A.BOOK_NO, A.TITLE, A.AUTHOR, A.PRICE, A.PUBDATE
        FROM(SELECT BOOK_NO, TITLE, AUTHOR, PRICE, PUBDATE, ROW_NUMBER() OVER(ORDER BY BOOK_NO DESC)AS RN
                FROM BOOK_T)A
        WHERE A.RN BETWEEN #{begin} AND #{end}
    </select>
    
    <select id="bookDetail" parameterType="int" resultType="domain.BookDto">
      SELECT BOOK_NO, TITLE, AUTHOR, PRICE, PUBDATE
      FROM BOOK_T
      WHERE BOOK_NO = #{bookNo}
    </select>
    
    <insert id="bookAdd" parameterType="domain.BookDto" >
      INSERT INTO BOOK_T(
          BOOK_NO
          ,TITLE
          ,AUTHOR
          ,PRICE
          ,PUBDATE     
      )VALUES(
        BOOK_SEQ.NEXTVAL
        ,#{title}
        ,#{author}
        ,#{price}
        ,SYSDATE
      )
    </insert>
    
    <update id="bookModify" parameterType="domain.BookDto">
    UPDATE BOOK_T
       SET TITLE = #{title}
         , AUTHOR= #{author}
         , PRICE= #{price}
      WHERE BOOK_NO= #{bookNo}
    
    </update>
    
    <delete id="bookDelete" parameterType="domain.BookDto">
     DELETE FROM BOOK_T
      WHERE BOOK_NO = #{bookNo}
    </delete>
    
  </mapper>

[index.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="contextPath" value="<%=request.getContextPath()%>" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
</head>
<body>

  <div>
    <a href="${contextPath}/book/list.do">도서목록</a>
  </div>

</body>
</html>

[BookDto]

package domain;

import java.sql.Date;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class BookDto {
  private int bookNo;
  private String title;
  private String author;
  private int price;
  private Date pubdate;
}

[BookDao]

package repository;

import java.io.InputStream;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import domain.BookDto;

public class BookDao {

  // mybatis의 SqlSession을 만들 수 있는 SqlSessionFactory 선언
  private SqlSessionFactory factory;
  
  // Singleton Pattern
  private static BookDao dao = new BookDao();
  private BookDao() {
    // SqlSessionFactory 생성
    try {
      String resource = "mybatis/config/mybatis-config.xml";
      InputStream in = Resources.getResourceAsStream(resource);
      factory = new SqlSessionFactoryBuilder().build(in);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  public static BookDao getDao() {
    return dao;
  }
  
  // 매퍼의 namespace
  private final String NS = "mybatis.mapper.book.";
  
  // 전체 개수 반환 메소드
  public int bookCount() {
    SqlSession ss = factory.openSession();
    int count = ss.selectOne(NS + "bookCount");
    ss.close();
    return count;
  }
  
  // 목록 반환 메소드
  public List<BookDto> bookList(Map<String, Object> map) {
    SqlSession ss = factory.openSession();
    List<BookDto> list = ss.selectList(NS + "bookList", map);
    ss.close();
    return list;
  }
  
  // 상세 반환 메소드
  public BookDto bookDetail(int bookNo) {
    SqlSession ss = factory.openSession();
    BookDto dto = ss.selectOne(NS + "bookDetail", bookNo);
    ss.close();
    return dto;
  }
  
  // 등록 메소드
  public int bookAdd(BookDto dto) {
    SqlSession ss = factory.openSession(false);  // false : 내가 커밋하겠다.
    int addResult = ss.insert(NS + "bookAdd", dto);
    if(addResult == 1) {
      ss.commit();
    }
    ss.close();
    return addResult;
  }
  
  // 수정 메소드
  public int bookModify(BookDto dto) {
    SqlSession ss = factory.openSession(false);
    int modifyResult = ss.update(NS + "bookModify", dto);
    if(modifyResult == 1) {
      ss.commit();
    }
    ss.close();
    return modifyResult;
  }
  
  // 삭제 메소드
  public int bookDelete(int bookNo) {
    SqlSession ss = factory.openSession(false);
    int deleteResult = ss.delete(NS + "bookDelete", bookNo);
    if(deleteResult == 1) {
      ss.commit();
    }
    ss.close();
    return deleteResult;
  }
  
}

[PageVo.java]

package util;

import lombok.Data;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@Data
public class PageVo {

  private int page;     // 현재 페이지 번호(요청 파라미터로 받는다.)
  private int total;    // 전체 항목의 개수(DB에서 구한 뒤 받는다.)
  private int display;  // 한 페이지에 표시할 항목의 개수(요청 파라미터로 받는다.)
  private int begin;    // 한 페이지에 표시되는 항목의 시작 번호(계산한다.)
  private int end;      // 한 페이지에 표시되는 항목의 종료 번호(계산한다.)
  
  private int totalPage;        // 전체 페이지의 개수(계산한다.)
  private int pagePerBlock = 2; // 한 블록에 표시되는 페이지의 개수(임의로 정한다.)
  private int beginPage;        // 한 블록에 표시되는 페이지의 시작 번호(계산한다.)
  private int endPage;          // 한 블록에 표시되는 페이지의 종료 번호(계산한다.)
  
  public void setPaging(int page, int total, int display) {
    
    /* 한 페이지를 나타낼 때 필요한 정보 */
    
    // 받은 정보 저장
    this.page = page;
    this.total = total;
    this.display = display;
    
    // 계산한 정보 저장
    begin = (page - 1) * display + 1;
    end = begin + display - 1;
    if(end > total) {
      end = total;
    }
    
    /* 전체 페이지를 나타낼 때 필요한 정보 */
    
    // 전체 페이지 계산
    totalPage = (int)Math.ceil((double)total / display);
    
    // 각 블록의 시작 페이지와 종료 페이지 계산
    beginPage = ((page - 1) / pagePerBlock) * pagePerBlock + 1;
    endPage = beginPage + pagePerBlock - 1;
    if(endPage > totalPage) {
      endPage = totalPage;
    }
    
  }
  
  public String getPaging(String url) {
    
    StringBuilder sb = new StringBuilder();
    
    sb.append("<div>");
    
    // 이전 블록
    if(beginPage == 1) {
      sb.append("<span>이전</span>");
    } else {
      sb.append("<a href=\"" + url + "?page=" + (beginPage - 1) + "\">이전</a>");
    }
    
    // 페이지 번호
    for(int p = beginPage; p <= endPage; p++) {
      if(p == page) {
        sb.append("<span>" + p + "</span>");
      } else {
        sb.append("<a href=\"" + url + "?page=" + p + "\">" + p + "</a>");
      }
    }
    
    // 다음 블록
    if(endPage == totalPage) {
      sb.append("<span>다음</span>");
    } else {
      sb.append("<a href=\"" + url + "?page=" + (endPage + 1) + "\">다음</a>");
    }
    
    sb.append("</div>");
    
    return sb.toString();
    
  }
  
}

[BookFilter.java]

package filter;

import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet Filter implementation class BookFilter
 */
@WebFilter("*.do")
public class BookFilter extends HttpFilter implements Filter {
       
  /**
   * @see HttpFilter#HttpFilter()
   */
  public BookFilter() {
    super();
    // TODO Auto-generated constructor stub
  }

  /**
   * @see Filter#destroy()
   */
  public void destroy() {
    // TODO Auto-generated method stub
  }

  /**
   * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
   */
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
    // 컨트롤러가 실행되기 이전에 처리되는 코드
    
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;
    
    // 요청 인코딩
    req.setCharacterEncoding("UTF-8");
    
    // 요청 주소 확인
    System.out.println(req.getRequestURI());
    
    // 요청 파라미터 확인
    Map<String, String[]> map = req.getParameterMap();
    for(Entry<String, String[]> entry : map.entrySet()) {
      System.out.println(entry.getKey() + ":" + Arrays.toString(entry.getValue()));
    }

    // pass the request along the filter chain
    chain.doFilter(request, response);
    
  }

  /**
   * @see Filter#init(FilterConfig)
   */
  public void init(FilterConfig fConfig) throws ServletException {
    // TODO Auto-generated method stub
  }

}

[BookController.java]

package controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import common.ActionForward;
import service.BookService;
import service.BookServiceImpl;

/**
 * Servlet implementation class BookController
 */
@WebServlet("*.do")
public class BookController extends HttpServlet {
  private static final long serialVersionUID = 1L;
  
  private BookService bookService = new BookServiceImpl();
  
  /**
   * @see HttpServlet#HttpServlet()
   */
  public BookController() {
    super();
    // TODO Auto-generated constructor stub
  }

  /**
   * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
   */
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    // BookFilter 실행 후 Controller 실행
    
    // 요청 인코딩(BookFilter가 수행함) + 응답 타입과 인코딩
    // request.setCharacterEncoding("UTF-8");
    response.setContentType("text/html; charset=UTF-8");
    
    // 요청 주소 확인
    String requestURI = request.getRequestURI();
    String contextPath = request.getContextPath();
    String urlMapping = requestURI.substring(contextPath.length());
    
    // 어디로 어떻게 이동할 것인지 알고 있는 ActionForward 객체
    ActionForward af = null;
    
    // 요청에 따른 처리
    switch(urlMapping) {
    // 단순 이동 (forward 처리)
    case "/book/write.do":
      af = new ActionForward("/book/write.jsp", false);
      break;
    case "/index.do":
      af = new ActionForward("/index.jsp", false);
      break;
    // 서비스 처리
    case "/book/add.do":
      af = bookService.bookAdd(request);
      break;
    case "/book/list.do":
      af = bookService.bookList(request);
      break;
    case "/book/detail.do":
      af = bookService.bookDetail(request);
      break;
    case "/book/edit.do":
      af = bookService.bookEdit(request);
      break;
    case "/book/modify.do":
      af = bookService.bookModify(request);
      break;
    case "/book/delete.do":
      af = bookService.bookDelete(request);
      break;
    }
    
    // 이동
    if(af != null) {
      if(af.isRedirect()) {
        response.sendRedirect(af.getPath());
      } else {
        request.getRequestDispatcher(af.getPath()).forward(request, response);
      }
    }
    
  }

  /**
   * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
   */
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub
    doGet(request, response);
  }

}

[BookService.java]

package service;

import javax.servlet.http.HttpServletRequest;

import common.ActionForward;

public interface BookService {
   public ActionForward bookList(HttpServletRequest request);
   public ActionForward bookDetail(HttpServletRequest request);
   public ActionForward bookAdd(HttpServletRequest request);
   public ActionForward bookEdit(HttpServletRequest request);
   public ActionForward bookModify(HttpServletRequest request);
   public ActionForward bookDelete(HttpServletRequest request);
}

[BookServiceImpl.java]

package service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;

import common.ActionForward;
import domain.BookDto;
import repository.BookDao;
import util.PageVo;

public class BookServiceImpl implements BookService {

  private BookDao dao = BookDao.getDao();
  private PageVo pageVo = new PageVo();
  
  @Override
  public ActionForward bookList(HttpServletRequest request) {
    Optional<String> opt = Optional.ofNullable(request.getParameter("page"));
    int page = Integer.parseInt(opt.orElse("1"));
    int total = dao.bookCount();
    int display = 10;
    pageVo.setPaging(page, total, display);
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("begin", pageVo.getBegin());
    map.put("end", pageVo.getEnd());
    List<BookDto> bookList = dao.bookList(map);
    request.setAttribute("bookList", bookList);
    request.setAttribute("paging", pageVo.getPaging(request.getContextPath() + "/book/list.do"));
    return new ActionForward("/book/list.jsp", false);
  }

  @Override
  public ActionForward bookDetail(HttpServletRequest request) {
    Optional<String> opt = Optional.ofNullable(request.getParameter("bookNo"));
    int bookNo = Integer.parseInt(opt.orElse("0"));
    BookDto book = dao.bookDetail(bookNo);
    request.setAttribute("book", book);
    return new ActionForward("/book/detail.jsp", false);
  }

  @Override
  public ActionForward bookAdd(HttpServletRequest request) {
    String title = request.getParameter("title");
    String author = request.getParameter("author");
    int price = Integer.parseInt(request.getParameter("price"));
    BookDto dto = BookDto.builder()
        .title(title)
        .author(author)
        .price(price)
        .build();
    int addResult = dao.bookAdd(dto);
    String path = null;
    switch(addResult) {
    case 0: path = request.getContextPath() + "/index.do"; break;
    case 1: path = request.getContextPath() + "/book/list.do"; break;    
    }
    return new ActionForward(path, true);
  }

  @Override
  public ActionForward bookEdit(HttpServletRequest request) {
    Optional<String> opt = Optional.ofNullable(request.getParameter("bookNo"));
    int bookNo = Integer.parseInt(opt.orElse("0"));
    BookDto book = dao.bookDetail(bookNo);
    request.setAttribute("book", book);
    return new ActionForward("/book/edit.jsp", false);
  }
  
  @Override
  public ActionForward bookModify(HttpServletRequest request) {
    int bookNo = Integer.parseInt(request.getParameter("bookNo"));
    String title = request.getParameter("title");
    String author = request.getParameter("author");
    int price = Integer.parseInt(request.getParameter("price"));
    BookDto dto = BookDto.builder()
                    .bookNo(bookNo)
                    .title(title)
                    .author(author)
                    .price(price)
                    .build();
    int modifyResult = dao.bookModify(dto);
    String path = null;
    switch(modifyResult) {
    case 0: path = request.getContextPath() + "/index.do"; break;
    case 1: path = request.getContextPath() + "/book/detail.do?bookNo=" + bookNo; break;    
    }
    return new ActionForward(path, true);
  }

  @Override
  public ActionForward bookDelete(HttpServletRequest request) {
    Optional<String> opt = Optional.ofNullable(request.getParameter("bookNo"));
    int bookNo = Integer.parseInt(opt.orElse("0"));
    int deleteResult = dao.bookDelete(bookNo);
    String path = null;
    switch(deleteResult) {
    case 0: path = request.getContextPath() + "/index.do"; break;
    case 1: path = request.getContextPath() + "/book/list.do"; break;    
    }
    return new ActionForward(path, true);
  }

}

[detail.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="contextPath" value="<%=request.getContextPath()%>" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<style>
  .link a {
    margin-right: 20px;
  }
</style>
<script>

  $(function(){
    fnDelete();
  })

  function fnDelete(){
    $('#delete_link').click(function(event){
      if(!confirm('도서 정보를 삭제할까요?')){
        event.preventDefault();
        return;
      }
    })
  }

</script>
</head>
<body>

  <div class="link">
    <a href="${contextPath}/book/write.do">작성하러가기</a>
    <a href="${contextPath}/book/list.do">목록으로이동</a>
    <a href="${contextPath}/book/edit.do?bookNo=${book.bookNo}">수정하러가기</a>
    <a id="delete_link" href="${contextPath}/book/delete.do?bookNo=${book.bookNo}">삭제하기</a>
  </div>

  <hr>
  
  <div>
    <div>책번호: ${book.bookNo}</div>
    <div>제목: ${book.title}</div>
    <div>저자: ${book.author}</div>
    <div>가격: ${book.price}</div>
    <div>출판일: ${book.pubdate}</div>
  </div>

</body>
</html>

[list.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="contextPath" value="<%=request.getContextPath()%>" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<style>
  .book_list table {
    border-collapse: collapse;
  }
  .book_list table td {
    border-top: 1px solid gray;
    border-bottom: 1px solid gray;
  }
</style>
<script>

  $(function(){
    fnEvent();
  })
  
  function fnEvent(){
    $('.btn_detail').click(function(){
      location.href = '${contextPath}/book/detail.do?bookNo=' + $(this).parent().data('book_no');
    })
    $('.btn_edit').click(function(){
      location.href = '${contextPath}/book/edit.do?bookNo=' + $(this).parent().data('book_no');
    })
    $('.btn_delete').click(function(){
      if(confirm('도서 정보를 삭제할까요?')){
        location.href = '${contextPath}/book/delete.do?bookNo=' + $(this).parent().data('book_no');
      }
    })
  }

</script>
</head>
<body>

  <div>
    <a href="${contextPath}/book/write.do">작성하러가기</a>
  </div>

  <hr>
  
  <div class="book_list">
    <table>
      <thead>
        <tr>
          <td>책번호</td>
          <td>제목</td>
          <td>저자</td>
          <td></td>
        </tr>
      </thead>
      <tbody>
        <c:forEach var="book" items="${bookList}">
          <tr>
            <td>${book.bookNo}</td>
            <td>${book.title}</td>
            <td>${book.author}</td>
            <td data-book_no="${book.bookNo}">
              <button type="button" class="btn_detail">상세조회</button>
              <button type="button" class="btn_edit">정보수정</button>
              <button type="button" class="btn_delete">정보삭제</button>
            </td>
          </tr>
        </c:forEach>
      </tbody>
    </table>
  </div>
  
  <div>${paging}</div>

</body>
</html>

[write.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="contextPath" value="<%=request.getContextPath()%>" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script>

  $(function(){
    fnList();
    fnAdd();
  })

  function fnList(){
    $('#btn_list').click(function(){  
      location.href = '${contextPath}/book/list.do';
    })
  }
  function fnAdd(){
    $('#frm_add').submit(function(event){
      if($('#title').val() === ''){
        alert('제목은 필수입니다.');
        $('#title').focus();
        event.preventDefault();
        return;
      }
    })
  }

</script>
</head>
<body>

<div>
  <form id="frm_add" method="post" action="${contextPath}/book/add.do">
    <div>
      <label for="title">제목</label>
      <input type="text" id="title" name="title">
    </div>
    <div>
      <label for="author">저자</label>
      <input type="text" id="author" name="author">
    </div>
    <div>
      <label for="price">가격</label>
      <input type="text" id="price" name="price">
    </div>
    <div>
      <button type="submit">작성완료</button>
      <button type="reset">작성초기화</button>
      <button type="button" id="btn_list">목록으로이동</button>
    </div>
  </form>
</div>

</body>
</html>

[edit.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="contextPath" value="<%=request.getContextPath()%>" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script>

  $(function(){
    fnList();
    fnModify();
  })

  function fnList(){
    $('#btn_list').click(function(){  
      location.href = '${contextPath}/book/list.do';
    })
  }
  function fnModify(){
    $('#frm_edit').submit(function(event){
      if($('#title').val() === ''){
        alert('제목은 필수입니다.');
        $('#title').focus();
        event.preventDefault();
        return;
      }
    })
  }

</script>
</head>
<body>

<div>
  <form id="frm_edit" method="post" action="${contextPath}/book/modify.do">
    <div>
      <label for="title">제목</label>
      <input type="text" id="title" name="title" value="${book.title}">
    </div>
    <div>
      <label for="author">저자</label>
      <input type="text" id="author" name="author" value="${book.author}">
    </div>
    <div>
      <label for="price">가격</label>
      <input type="text" id="price" name="price" value="${book.price}">
    </div>
    <div>
      <input type="hidden" name="bookNo" value="${book.bookNo}">
      <button type="submit">수정완료</button>
      <button type="reset">작성초기화</button>
      <button type="button" id="btn_list">목록으로이동</button>
    </div>
  </form>
</div>

</body>
</html>


profile
졸려요

0개의 댓글