romworld

Spring 28 - adminlte3을 사용한 CRUD [setInterval(), datatables 사용법, ID 자동완성] 본문

Spring

Spring 28 - adminlte3을 사용한 CRUD [setInterval(), datatables 사용법, ID 자동완성]

inderrom 2023. 2. 16. 17:40

현재시각 출력

  • 비동기방식(json)
  • ajax(Acynchronous Javascript And XML)
  • setInterval() 함수 사용

 

setInterval()
-  웹페이지의 특정 부분을 주기적으로 업데이트해줘야 하거나 어떤 API로부터 변경된 데이터를 주기적으로 받아와야       하는 경우 사용
- 어떤 코드를 일정한 시간 간격을 두고 반복해서 실행하고 싶을 때 사용
-  setTimeout()함수와 대동소이.
- 첫번째 인자로 실행할 코드를 담고 있는 함수를 받음
- 두번째 인자로 반복 주기를 밀리초(ms) 단위로 받음 

 

 

<WelcomeController.java>

package kr.or.ddit.controller;

import java.util.Date;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class WelcomeController {
	
	// 요청URI : /home
	@GetMapping("/home")
	public String home(Model model) {
		String CT = getCurrentTime();
		
		model.addAttribute("greeting", "Welcome to BookMarket");
		model.addAttribute("strapline", "Welcome to Web Shopping Mall!");
		model.addAttribute("CT", CT);
		
		//forwarding
		// Views/welcome.jsp
		return "welcome";
	}
	
	
	/*
	 
	  
	 */
	//현재시각을 json 데이터로 리턴
	@ResponseBody
	@GetMapping("/getCurrentTime")
	public String getCurrentTime() {
	Date day = new Date();
		
		String am_pm;
		
		int hour = day.getHours();
		int minute = day.getMinutes();
		int second = day.getSeconds();
		
		if(hour / 12 == 0) {
			am_pm = "AM";
		}else {
			am_pm = "PM";
			hour = hour - 12;
		}
		
		String CT = hour + " : " + minute + " : " +second + " " + am_pm;
		
		return CT;
	}
	
}

 

<welcome.jsp>

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript">
/* setInterval()
- 웹페이지의 특정 부분을 주기적으로 업데이트해줘야 하거나
   어떤 API로부터 변경된 데이터를 주기적으로 받아와야 하는 경우 사용
- 어떤 코드를 일정한 시간 간격을 두고 반복해서 실행하고 싶을 때 사용
- setTimeout()함수와 대동소이.
- 첫번째 인자로 실행할 코드를 담고 있는 함수를 받음
- 두번째 인자로 반복 주기를 밀리초(ms) 단위로 받음
*/

//	setInterval(()=>console.log(new Date()),1000);
	
	//0과 9 사이의 수를 무작위로 생성하여 3초마다 출력(floor : 소수부는 버림)
//	let intervalId = 
//		setInterval(()=>console.log(Math.floor(Math.random()*10)),3000);
	//메모리 누수 방지
//	clearInterval(intervalId);
$(function(){
// 1초에 한 번씩 pCt요소의 text를 현재시각으로 변경해보자
// ajax(Acynchronous Javascript And XML)
// processType:false, : let f = new FormData();
// contentType : 보내는 타입
// data : 보내는 데이터
// dataType : "json" 응답데이터타입 (Controller에서 String에서 리턴 시 생략)  
	setInterval(function(){
		$.ajax({
			url:"/getCurrentTime",
			type:"get",
			success:function(res){
				console.log(" 보낸당")
				//.html() : 새로고침 
				$("#pCt").html(res);
			}
		});	
	}, 1000)
});
	
</script>
<title>도서관리시스템</title>
</head>
<body>
	<h1>${greeting}</h1>
	<p>${strapline}</p>
	<p id="pCt">${CT}</p>
</body>
</html>

1초마다 바뀐다

 

 


PRODUCT 테이블 생성

 

*SQL DEVELOPER

CREATE TABLE PRODUCT(
     PRODUCT_ID VARCHAR2(10),
    PNAME VARCHAR2(150),
    UNIT_PRICE NUMBER,
    DESCRIPTION VARCHAR2(4000),
    MANUFACTURER VARCHAR2(60),
    CATEGORY VARCHAR2(60),
    UNITS_IN_STOCK NUMBER,
    CONDITION VARCHAR2(60),
    FILENAME VARCHAR2(1000),
    QUANTITY NUMBER,
     CONSTRAINT PK_PRODUCT PRIMARY KEY(PRODUCT_ID)
);

 

<ProductVO.java>

package kr.or.ddit.vo;

import lombok.Data;

@Data
public class ProductVO {
	private String productId;
	private String pname;
	private int unitPrice;
	private String description;
	private String manufacturer;
	private String category;
	private int unitsInStock;
	private String condition;
	private String filename;
	private int quantity;
}

 

데이터 INSERT

 

 

<product._SQL.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">
 <!-- namespace : xml 파일이 여러개일 수 있으므로
 		이를 구별하기 위한 식별 용도로 사용 -->
<mapper namespace="kr.or.ddit.mapper.ProductMapper">
	
	<!-- 
	 제품 목록
	 파라미터타입 : x
	 리턴타입 : productVO
	-->
	<select id="list" resultType="productVO">
		SELECT PRODUCT_ID, PNAME, UNIT_PRICE, DESCRIPTION, MANUFACTURER
   				 , CATEGORY, UNITS_IN_STOCK, CONDITION, FILENAME, QUANTITY
		FROM PRODUCT
		ORDER BY PRODUCT_ID
	</select>
	
</mapper>

 

<ProductMapper.java>

package kr.or.ddit.mapper;

import java.util.List;

import kr.or.ddit.vo.ProductVO;

public interface ProductMapper {
	
	// 제품 목록
	public List<ProductVO> list();
	
}

 

<mybatisAlias.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>
   <!-- 
   [마이바티스] 스프링에서 "_"를 사용한 컬럼명을 사용 시(BOOK 테이블의 BOOK_ID)
   카멜케이스로 읽어줌(bookId)
   ex) 테이블 컬럼명이 member_id인 경우 jsp화면단에서 이 값을 사용 시 memberId로 사용
   -->
   <settings>
      <setting name="mapUnderscoreToCamelCase" value="true"/>
   </settings>
   <!-- 자주 사용하는 타입의 별칭을 세팅 -->
   <typeAliases>
      <typeAlias type="kr.or.ddit.vo.ProductVO" alias="productVO" />      
      
   </typeAliases>
</configuration>

 

<ProductService.java>

package kr.or.ddit.service;

import java.util.List;
import kr.or.ddit.vo.ProductVO;

public interface ProductService {
	// 제품목록
	public List<ProductVO> list();
}

 

<ProductServiceImpl.java>

package kr.or.ddit.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import kr.or.ddit.mapper.ProductMapper;
import kr.or.ddit.service.ProductService;
import kr.or.ddit.vo.ProductVO;

@Service
public class ProductServiceImpl implements ProductService {
	
	@Autowired
	ProductMapper productMapper;
	
	// 제품목록
	@Override
	public List<ProductVO> list() {
		return productMapper.list();
	}

}

 

<ProductController.java>

package kr.or.ddit.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import kr.or.ddit.service.ProductService;
import kr.or.ddit.vo.ProductVO;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RequestMapping("/product")
@Controller
public class ProductController {
	@Autowired
	ProductService productService;
	
	@GetMapping("/list")
	public String list(Model model){
		List<ProductVO> productVOList = this.productService.list();
		
		log.info("productVOList : " + productVOList);
		
		model.addAttribute("pvo", productVOList);
		
		//forwarding. product폴더의 list.jsp를 리턴
		return "product/list";
	}
}

list

 

부트스트랩을 가져오자!

PDF 파일저장 기능을 다 사용하려면

tiles도 수정해주자

datatables 사용하기

 

 

 
1. tiles의 index.jsp의 상단에 추가함(css)
<!-- DataTables -->
<link rel="stylesheet" href="/resources/AdminLTE/plugins/datatables-bs4/css/dataTables.bootstrap4.min.css">
<link rel="stylesheet" href="/resources/AdminLTE/plugins/datatables-responsive/css/responsive.bootstrap4.min.css">
<link rel="stylesheet" href="/resources/AdminLTE/plugins/datatables-buttons/css/buttons.bootstrap4.min.css">
 
 
2. tiles의 index.jsp의 하단에 추가함(js)
<!-- DataTables & Plugins -->
<script src="/resources/AdminLTE/plugins/datatables/jquery.dataTables.min.js"></script>
<script src="/resources/AdminLTE/plugins/datatables-bs4/js/dataTables.bootstrap4.min.js"></script>
<script src="/resources/AdminLTE/plugins/datatables-responsive/js/dataTables.responsive.min.js"></script>
<script src="/resources/AdminLTE/plugins/datatables-responsive/js/responsive.bootstrap4.min.js"></script>
<script src="/resources/AdminLTE/plugins/datatables-buttons/js/dataTables.buttons.min.js"></script>
<script src="/resources/AdminLTE/plugins/datatables-buttons/js/buttons.bootstrap4.min.js"></script>
<script src="/resources/AdminLTE/plugins/jszip/jszip.min.js"></script>
<script src="/resources/AdminLTE/plugins/pdfmake/pdfmake.min.js"></script>
<script src="/resources/AdminLTE/plugins/pdfmake/vfs_fonts.js"></script>
<script src="/resources/AdminLTE/plugins/datatables-buttons/js/buttons.html5.min.js"></script>
<script src="/resources/AdminLTE/plugins/datatables-buttons/js/buttons.print.min.js"></script>
<script src="/resources/AdminLTE/plugins/datatables-buttons/js/buttons.colVis.min.js"></script>
 
3. list.jsp에 추가함
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
 
<!-- jQuery -->
<script src="/resources/js/jquery-3.6.0.js"></script>
<script src="/resources/js/jquery-3.6.3.min.js"></script>
 
<div class="card">
<div class="card-header">
<h3 class="card-title">목록</h3>
</div>
 
<div class="card-body">
<div id="example1_wrapper" class="dataTables_wrapper dt-bootstrap4">
<div class="row">
<div class="col-sm-12">
<table id="example1" class="table table-bordered table-striped dataTable dtr-inline" aria-describedby="example1_info">
<thead>
<tr>
<th onclick="event.cancelBubble=true">상품번호</th>
<th onclick="event.cancelBubble=true">카테고리</th>
<th onclick="event.cancelBubble=true">상품명</th>
<th onclick="event.cancelBubble=true">제조사</th>
<th onclick="event.cancelBubble=true">가격</th>
<th onclick="event.cancelBubble=true">상태</th>
<th onclick="event.cancelBubble=true">재고</th>
</tr>
</thead>
<tbody>
<c:forEach var="pvo" items="${pvo}" varStatus="stat">
<tr>
<td>${pvo.productId}</td>
<td>${pvo.category}</td>
<td>${pvo.pname}</td>
<td>${pvo.manufacturer}</td>
<td style="text-align: right;"><fmt:formatNumber type="number" maxFractionDigits="3" value="${pvo.unitPrice}" />원</td>
<td>${pvo.condition}</td>
<td>${pvo.unitsInStock}</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
 
</div>
</div>
</div>
 
<script>
$(function () {
$("#example1").DataTable({
"responsive": true, "lengthChange": false, "autoWidth": false,
"buttons": ["copy", "csv", "excel", "pdf", "print", "colvis"]
}).buttons().container().appendTo('#example1_wrapper .col-md-6:eq(0)');
 
});
</script>

 

tiles 의 <index.jsp> 

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
<!DOCTYPE html>
<html class>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>AdminLTE 3 | Dashboard</title>

  <!-- Google Font: Source Sans Pro -->
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback">
  <!-- Font Awesome -->
  <link rel="stylesheet" href="/resources/adminlte3/plugins/fontawesome-free/css/all.min.css">
  <!-- Ionicons -->
  <link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
  <!-- Tempusdominus Bootstrap 4 -->
  <link rel="stylesheet" href="/resources/adminlte3/plugins/tempusdominus-bootstrap-4/css/tempusdominus-bootstrap-4.min.css">
  <!-- iCheck -->
  <link rel="stylesheet" href="/resources/adminlte3/plugins/icheck-bootstrap/icheck-bootstrap.min.css">
  <!-- JQVMap -->
  <link rel="stylesheet" href="/resources/adminlte3/plugins/jqvmap/jqvmap.min.css">
  <!-- Theme style -->
  <link rel="stylesheet" href="/resources/adminlte3/dist/css/adminlte.min.css">
  <!-- overlayScrollbars -->
  <link rel="stylesheet" href="/resources/adminlte3/plugins/overlayScrollbars/css/OverlayScrollbars.min.css">
  <!-- Daterange picker -->
  <link rel="stylesheet" href="/resources/adminlte3/plugins/daterangepicker/daterangepicker.css">
  <!-- summernote -->
  <link rel="stylesheet" href="/resources/adminlte3/plugins/summernote/summernote-bs4.min.css">
<!-- DataTables -->
<link rel="stylesheet" href="/resources/adminlte3/plugins/datatables-bs4/css/dataTables.bootstrap4.min.css">
<link rel="stylesheet" href="/resources/adminlte3/plugins/datatables-responsive/css/responsive.bootstrap4.min.css">
<link rel="stylesheet" href="/resources/adminlte3/plugins/datatables-buttons/css/buttons.bootstrap4.min.css">

<!-- jQuery -->
<script src="/resources/js/jquery-3.6.0.js"></script>

</head>
<body class="hold-transition sidebar-mini layout-fixed">
<div class="wrapper">

  <!-- Preloader -->
  <div class="preloader flex-column justify-content-center align-items-center">
    <img class="animation__shake" src="/resources/adminlte3/dist/img/AdminLTELogo.png" alt="AdminLTELogo" height="60" width="60">
  </div>

  <!---------------- Navbar header.jsp 시작 -------------->
   <tiles:insertAttribute name="header" />
  <!---------------- /.navbar header.jsp 끝 -------------->

  <!-- Main Sidebar Container aside.jsp 시작 -->
  <tiles:insertAttribute name="aside" />
  <!-- Main Sidebar Container aside.jsp 끝 -->
  

  <!-- Content Wrapper. Contains page content -->
  <div class="content-wrapper">
    <!-- Content Header (Page header) -->
    <div class="content-header">
      <div class="container-fluid">
        <div class="row mb-2">
          <div class="col-sm-6">
            <h1 class="m-0">Dashboard</h1>
          </div><!-- /.col -->
          <div class="col-sm-6">
            <ol class="breadcrumb float-sm-right">
              <li class="breadcrumb-item"><a href="#">Home</a></li>
              <li class="breadcrumb-item active">Dashboard v1</li>
            </ol>
          </div><!-- /.col -->
        </div><!-- /.row -->
      </div><!-- /.container-fluid -->
    </div>
    <!-- /.content-header -->

    <!-- Main content -->
    <section class="content">
      <div class="container-fluid">
          <!-- body 시작 -->
          <tiles:insertAttribute name="body" />
          <!-- body 끝 -->
        <!-- /.row (main row) -->
      </div><!-- /.container-fluid -->
    </section>
    <!-- /.content -->
  </div>
  <!-- /.content-wrapper -->
 
 <!------------- footer.jsp 시작 ------------->
 <tiles:insertAttribute name="footer" />
 <!------------- footer.jsp 끝 ------------->

  <!-- Control Sidebar -->
  <aside class="control-sidebar control-sidebar-dark">
    <!-- Control sidebar content goes here -->
  </aside>
  <!-- /.control-sidebar -->
</div>
<!-- ./wrapper -->

<!-- jQuery -->
<script src="/resources/adminlte3/plugins/jquery/jquery.min.js"></script>
<!-- jQuery UI 1.11.4 -->
<script src="/resources/adminlte3/plugins/jquery-ui/jquery-ui.min.js"></script>
<!-- Resolve conflict in jQuery UI tooltip with Bootstrap tooltip -->
<script>
  $.widget.bridge('uibutton', $.ui.button)
</script>
<!-- Bootstrap 4 -->
<script src="/resources/adminlte3/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- ChartJS -->
<script src="/resources/adminlte3/plugins/chart.js/Chart.min.js"></script>
<!-- Sparkline -->
<script src="/resources/adminlte3/plugins/sparklines/sparkline.js"></script>
<!-- JQVMap -->
<script src="/resources/adminlte3/plugins/jqvmap/jquery.vmap.min.js"></script>
<script src="/resources/adminlte3/plugins/jqvmap/maps/jquery.vmap.usa.js"></script>
<!-- jQuery Knob Chart -->
<script src="/resources/adminlte3/plugins/jquery-knob/jquery.knob.min.js"></script>
<!-- daterangepicker -->
<script src="/resources/adminlte3/plugins/moment/moment.min.js"></script>
<script src="/resources/adminlte3/plugins/daterangepicker/daterangepicker.js"></script>
<!-- Tempusdominus Bootstrap 4 -->
<script src="/resources/adminlte3/plugins/tempusdominus-bootstrap-4/js/tempusdominus-bootstrap-4.min.js"></script>
<!-- Summernote -->
<script src="/resources/adminlte3/plugins/summernote/summernote-bs4.min.js"></script>
<!-- overlayScrollbars -->
<script src="/resources/adminlte3/plugins/overlayScrollbars/js/jquery.overlayScrollbars.min.js"></script>
<!-- AdminLTE App -->
<script src="/resources/adminlte3/dist/js/adminlte.js"></script>
<!-- AdminLTE for demo purposes -->
<script src="/resources/adminlte3/dist/js/demo.js"></script>
<!-- AdminLTE dashboard demo (This is only for demo purposes) -->
<script src="/resources/adminlte3/dist/js/pages/dashboard.js"></script>
  <!-- DataTables  & Plugins -->
<script src="/resources/adminlte3/plugins/datatables/jquery.dataTables.min.js"></script>
<script src="/resources/adminlte3/plugins/datatables-bs4/js/dataTables.bootstrap4.min.js"></script>
<script src="/resources/adminlte3/plugins/datatables-responsive/js/dataTables.responsive.min.js"></script>
<script src="/resources/adminlte3/plugins/datatables-responsive/js/responsive.bootstrap4.min.js"></script>
<script src="/resources/adminlte3/plugins/datatables-buttons/js/dataTables.buttons.min.js"></script>
<script src="/resources/adminlte3/plugins/datatables-buttons/js/buttons.bootstrap4.min.js"></script>
<script src="/resources/adminlte3/plugins/jszip/jszip.min.js"></script>
<script src="/resources/adminlte3/plugins/pdfmake/pdfmake.min.js"></script>
<script src="/resources/adminlte3/plugins/pdfmake/vfs_fonts.js"></script>
<script src="/resources/adminlte3/plugins/datatables-buttons/js/buttons.html5.min.js"></script>
<script src="/resources/adminlte3/plugins/datatables-buttons/js/buttons.print.min.js"></script>
<script src="/resources/adminlte3/plugins/datatables-buttons/js/buttons.colVis.min.js"></script>
</body>
</html>

 

 

 

<list.jsp>

  • product폴더를 만들고 list 생성

테이블 표 가져오기

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="sec"   uri="http://www.springframework.org/security/tags"%>

<!-- jQuery -->
<script src="/resources/js/jquery-3.6.0.js"></script>
<script src="/resources/js/jquery-3.6.3.min.js"></script>

<div class="card">
   <div class="card-header">
      <h3 class="card-title">목록</h3>
   </div>

   <div class="card-body">
      <div id="example1_wrapper" class="dataTables_wrapper dt-bootstrap4">
         <div class="row">
            <div class="col-sm-12">
               <table id="example1" class="table table-bordered table-striped dataTable dtr-inline" aria-describedby="example1_info">
                  <thead>
                     <tr>
                        <th onclick="event.cancelBubble=true">상품번호</th>
                        <th onclick="event.cancelBubble=true">카테고리</th>
                        <th onclick="event.cancelBubble=true">상품명</th>
                        <th onclick="event.cancelBubble=true">제조사</th>
                        <th onclick="event.cancelBubble=true">가격</th>
                        <th onclick="event.cancelBubble=true">상태</th>
                        <th onclick="event.cancelBubble=true">재고</th>
                     </tr>
                  </thead>
                  <tbody>
                     <c:forEach var="pvo" items="${pvo}" varStatus="stat">
                        <tr>
                           <td>${pvo.productId}</td>
                           <td>${pvo.category}</td>
                           <td>${pvo.pname}</td>
                           <td>${pvo.manufacturer}</td>
                           <td style="text-align: right;"><fmt:formatNumber type="number" maxFractionDigits="3" value="${pvo.unitPrice}" />원</td>
                           <td>${pvo.condition}</td>
                           <td>${pvo.unitsInStock}</td>
                        </tr>
                     </c:forEach>
                  </tbody>
               </table>
            </div>
         </div>

      </div>
   </div>
</div>

<script>
  $(function () {
    $("#example1").DataTable({
      "responsive": true, "lengthChange": false, "autoWidth": false,
      "buttons": ["copy", "csv", "excel", "pdf", "print", "colvis"]
    }).buttons().container().appendTo('#example1_wrapper .col-md-6:eq(0)');

  });
</script>

 

 


CREATE

<ProductCotroller.java>

package kr.or.ddit.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import kr.or.ddit.service.ProductService;
import kr.or.ddit.vo.ProductVO;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RequestMapping("/product")
@Controller
public class ProductController {
	@Autowired
	ProductService productService;
	
	@GetMapping("/list")
	public String list(Model model){
		List<ProductVO> productVOList = this.productService.list();
		
		log.info("productVOList : " + productVOList);
		
		model.addAttribute("pvo", productVOList);
		
		//forwarding. product폴더의 list.jsp를 리턴
		return "product/list";
	}
	
	// 요청 URI : /product/create
	//요청방식 : get
	@GetMapping("/create")
	public String create() {
		
		//forwarding
		return "product/create";
	}
	
}

 

<list.jsp>

  • <a href="/product/create" class="btn btn-primary" style="float:right;">등록</a>
  • 클래스가 버튼 타입이라 a링크 줘도 된다.
  •  
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="sec"   uri="http://www.springframework.org/security/tags"%>

<!-- jQuery -->
<script src="/resources/js/jquery-3.6.0.js"></script>
<script src="/resources/js/jquery-3.6.3.min.js"></script>

<div class="card">
	<div class="card-header" style="width:100%;">
		<div style="width:30%;float:left;">
			<h3 class="card-title">목록</h3>
		</div>
		<div style="width:70%;float:right;">
			<!-- 등록 버튼 클릭 시 /product/create를 get방식으로 요청
				product폴더의 create.jsp를 forwarding처리해보자
				create.jsp는 https://adminlte.io/themes/v3/pages/forms/advanced.html를 활용해보자
			 -->
			<a href="/product/create" class="btn btn-primary" style="float:right;">등록</a>
		</div>
	</div>

   <div class="card-body">
      <div id="example1_wrapper" class="dataTables_wrapper dt-bootstrap4">
         <div class="row">
            <div class="col-sm-12">
               <table id="example1" class="table table-bordered table-striped dataTable dtr-inline" aria-describedby="example1_info">
                  <thead>
                     <tr>
                        <th onclick="event.cancelBubble=true">상품번호</th>
                        <th onclick="event.cancelBubble=true">카테고리</th>
                        <th onclick="event.cancelBubble=true">상품명</th>
                        <th onclick="event.cancelBubble=true">제조사</th>
                        <th onclick="event.cancelBubble=true">가격</th>
                        <th onclick="event.cancelBubble=true">상태</th>
                        <th onclick="event.cancelBubble=true">재고</th>
                     </tr>
                  </thead>
                  <tbody>
                     <c:forEach var="pvo" items="${pvo}" varStatus="stat">
                        <tr>
                           <td>${pvo.productId}</td>
                           <td>${pvo.category}</td>
                           <td>${pvo.pname}</td>
                           <td>${pvo.manufacturer}</td>
                           <td style="text-align: right;"><fmt:formatNumber type="number" maxFractionDigits="3" value="${pvo.unitPrice}" />원</td>
                           <td>${pvo.condition}</td>
                           <td>${pvo.unitsInStock}</td>
                        </tr>
                     </c:forEach>
                  </tbody>
               </table>
            </div>
         </div>

      </div>
   </div>
</div>

<script>
  $(function () {
	  // Datatables 설정
    $("#example1").DataTable({
      "responsive": true, "lengthChange": false, "autoWidth": false,
      "buttons": ["copy", "csv", "excel", "pdf", "print", "colvis"]
    }).buttons().container().appendTo('#example1_wrapper .col-md-6:eq(0)');

    
    // 동록 버튼 눌렀을 때
    
  });
</script>

 

<create.jsp>

  • product폴더에 추가
  • ckeditor 이용함
  •  
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
<script type="text/javascript" src="/resources/ckeditor/ckeditor.js"></script>
<div class="card card-primary">
	<div class="card-header">
		<h3 class="card-title">상품 등록</h3>
	</div>
	<!-- 
	요청URI : /product/create
	요청방식 : post
	메소드명 : createPost
	PRODUCT 테이블에 입력해보자
	 -->
	<form name="frm" action="/product/create" method="post">
		<div class="card-body">
			<div class="form-group">
				<label for="productId">상품아이디</label> <input
					type="text" name="productId" class="form-control" id="productId"
					placeholder="상품아이디를 입력해주세요" required />
			</div>
			<div class="form-group">
				<label for="pname">상품명</label> <input
					type="text" name="pname" class="form-control" id="pname"
					placeholder="상품명을 입력해주세요" required />
			</div>
			<div class="form-group">
				<label for="unitPrice">판매 가격</label> <input
					type="number" name="unitPrice" class="form-control" id="unitPrice"
					placeholder="판매 가격을 입력해주세요" required />
			</div>
			<div class="form-group">
				<label for="description">상품 설명</label> 
					<textarea cols="30" rows="5" name="description" class="form-control" id="description"
					placeholder="판매 가격을 입력해주세요"></textarea>
			</div>
			<div class="form-group">
				<label for="manufacturer">제조사</label> <input
					type="text" name="manufacturer" class="form-control" id="manufacturer"
					placeholder="제조사를 입력해주세요" required />
			</div>
			<div class="form-group">
				<label for="category">카테고리</label> <input
					type="text" name="category" class="form-control" id="category"
					placeholder="카테고리를 입력해주세요" required />
			</div>
			<div class="form-group">
				<label for="unitsInStock">재고수</label> <input
					type="number" name="unitsInStock" class="form-control" id="unitsInStock"
					placeholder="재고수를 입력해주세요" value="0" />
			</div>
			<div class="form-group">
				<label for="category">상태</label> 
				<div class="col-sm-6">
					<div class="form-group">
						<select id="condition" name="condition" class="form-control">
							<option value="New">New</option>
							<option value="Old">Old</option>
							<option value="Refurbished">Refurbished</option>
						</select>
					</div>
				</div>
			</div>
		</div>
		
		<div class="card-footer">
			<button type="submit" class="btn btn-primary">등록</button>
		</div>
		<!-- Cross Site Request Forgery -->
		<sec:csrfInput/>
	</form>
</div>
<script type="text/javascript">
CKEDITOR.replace("description");
</script>

 

 

<ProductCotroller.java>

  • createPost 매서드생성
package kr.or.ddit.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import kr.or.ddit.service.ProductService;
import kr.or.ddit.vo.ProductVO;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RequestMapping("/product")
@Controller
public class ProductController {
	@Autowired
	ProductService productService;
	
	@GetMapping("/list")
	public String list(Model model){
		List<ProductVO> productVOList = this.productService.list();
		
		log.info("productVOList : " + productVOList);
		
		model.addAttribute("pvo", productVOList);
		
		//forwarding. product폴더의 list.jsp를 리턴
		return "product/list";
	}
	
	//요청URI : /product/create
		//요청방식 : get
		@GetMapping("/create")
		public String create() {
			
			//fowarding
			//product폴더의 create.jsp를 forwarding
			return "product/create";
		}
		
	@PostMapping("/create")
	public String createPost(@ModelAttribute ProductVO productVO) {
		/*
		 productVO : ProductVO(productId=P1237, pname=Galaxy Note 20, unitPrice=1000
		 , description=<p>상품 설명</p>
		, manufacturer=Samsung, category=Smart Phone, unitsInStock=1000, condition=New
		, filename=null, quantity=0, productImage=null)
		 */
		log.info("productVO : " + productVO);
		
		int result = this.productService.createPost(productVO);
		log.info("result : " + result);
		
		if(result > 0) { // 등록 성공
			//redirect : URI 재요청
			return "redirect:/product/list";
		}else { //등록 실패
			return "redirect:/product/create";
		}
		
	}
	
}

 

<product_SQL.xml>

	
	<!-- 상품 등록 
	productVO
	생략(int)
	-->
	<insert id="createPost" parameterType="productVO">
		<selectKey resultType="String" order="BEFORE" keyProperty="productId">
			SELECT SUBSTR(MAX(PRODUCT_ID),1,1)
			     || (SUBSTR(MAX(PRODUCT_ID),2) + 1)
			FROM   PRODUCT
		</selectKey>
	
		INSERT INTO PRODUCT(PRODUCT_ID, PNAME, UNIT_PRICE, DESCRIPTION, MANUFACTURER
		, CATEGORY, UNITS_IN_STOCK, CONDITION) 
		VALUES(#{productId},#{pname},#{unitPrice},#{description},#{manufacturer}
		,#{category},#{unitsInStock},#{condition})
	</insert>

 

<ProductMapper.xml>

// 제품 등록. insert, update, delete 당연히 int로 리턴
	public int createPost(ProductVO productVO);

 

<ProductService.java>

	//제품 등록
	public int createPost(ProductVO productVO);

 

<ProductServiceImpl.java>

	// 제품 등록
	@Override
	public int createPost(ProductVO productVO) {
		return this.productMapper.createPost(productVO);

등록을 누르고 입력하면

                 

목록으로 잘 넘어감

                                                                                                                            

 


상품아이디 자동생성, readonly

 

<ProductController.java>

// 상품아이디 자동생성
	//json으로 응답 시 ResponseBody
	//1)String
	//2)List<..VO>, ..VO, Map<String,String>,List<Map<String,String>> : dataType="json"
	@ResponseBody
	@PostMapping("/getproductId")
	public String getproductId() {
		
		String productId = this.productService.getproductId();
		//dataType="json" 생략
		//List<..VO> =>$.each(result,function(index,data)
		//result : List<ProductVO>
		//data : ProductVO
		//index : 0부터1씩 증가
		return productId;
	}

 

<product_SQL.xml>

	<!-- 상품아이디 자동 생성 -->
	<select id="getproductId" resultType="String">
		SELECT SUBSTR(MAX(PRODUCT_ID),1,1)
			     || (SUBSTR(MAX(PRODUCT_ID),2) + 1)
		FROM   PRODUCT
	</select>

 

<ProductService.java>

	// 상품아이디 자동생성
	public String getproductId();

<ProductServiceImpl.java>

	// 상품 아이디 자동 생성
	@Override
	public String getproductId() {
		return this.productMapper.getproductId();
	}

 

<create.jsp>

  • ajax를 써줄 때 안에 꼭 같이 써주자!
beforeSend : function(xhr) { // 데이터 전송 전 헤더에 csrf값 설정
xhr.setRequestHeader("${_csrf.headerName}", "${_csrf.token}");
},
  • 아이디 자동생성 
  • readonly
  • button 태그 사용
  • 제이쿼리를 쓰는 경우에 꼭 스크립트 등록

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
<script type="text/javascript" src="/resources/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<script type="text/javascript">
$(function(){
	$("#btnAuto").on("click",function(){
		$.ajax({
			url:"/product/getproductId",
			type:"post",
			beforeSend : function(xhr) {   // 데이터 전송 전  헤더에 csrf값 설정
                xhr.setRequestHeader("${_csrf.headerName}", "${_csrf.token}");
			},
			success:function(res){
				$("input[name='productId']").val(res);
			}
		});
	});
})
</script>

<div class="card card-primary">
	<div class="card-header">
		<h3 class="card-title">상품 등록</h3>
	</div>
	<!-- 
	요청URI : /product/create
	요청방식 : post
	메소드명 : createPost
	PRODUCT 테이블에 입력해보자
	 -->
	<form name="frm" action="/product/create" method="post">
		<div class="card-body">
			<div class="form-group">
				<label for="productId">상품아이디</label> <input
					type="text" name="productId" class="form-control" id="productId"
					placeholder="상품아이디를 입력해주세요" required  readonly />
				<button type="button" id="btnAuto" class="btn bg-gradient-primary">자동생성</button>
			</div>

			<div class="form-group">
				<label for="pname">상품명</label> <input
					type="text" name="pname" class="form-control" id="pname"
					placeholder="상품명을 입력해주세요" required />
			</div>
			<div class="form-group">
				<label for="unitPrice">판매 가격</label> <input
					type="number" name="unitPrice" class="form-control" id="unitPrice"
					placeholder="판매 가격을 입력해주세요" required />
			</div>
			<div class="form-group">
				<label for="description">상품 설명</label> 
					<textarea cols="30" rows="5" name="description" class="form-control" id="description"
					placeholder="판매 가격을 입력해주세요"></textarea>
			</div>
			<div class="form-group">
				<label for="manufacturer">제조사</label> <input
					type="text" name="manufacturer" class="form-control" id="manufacturer"
					placeholder="제조사를 입력해주세요" required />
			</div>
			<div class="form-group">
				<label for="category">카테고리</label> <input
					type="text" name="category" class="form-control" id="category"
					placeholder="카테고리를 입력해주세요" required />
			</div>
			<div class="form-group">
				<label for="unitsInStock">재고수</label> <input
					type="number" name="unitsInStock" class="form-control" id="unitsInStock"
					placeholder="재고수를 입력해주세요" value="0" />
			</div>
			<div class="form-group">
				<label for="category">상태</label> 
				<div class="col-sm-6">
					<div class="form-group">
						<select id="condition" name="condition" class="form-control">
							<option value="New">New</option>
							<option value="Old">Old</option>
							<option value="Refurbished">Refurbished</option>
						</select>
					</div>
				</div>
			</div>
		</div>
		
		<div class="card-footer">
			<button type="submit" class="btn btn-primary">등록</button>
		</div>
		<!-- Cross Site Request Forgery -->
		<sec:csrfInput/>
	</form>
</div>
<script type="text/javascript">
CKEDITOR.replace("description");
</script>

 

자동생성 버튼을 누르면 아이디 자동생성됨

Comments