일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 파생상품평가
- 마이페이지
- 이미지 업로드
- 달력 라이브러리
- 밸류즈
- 관리자페이지
- 밸류즈 홈페이지
- RCPS
- 배포
- Ajax
- register
- stock option
- Token
- 회원가입로직
- react
- MRC
- 인증처리
- 로그인
- jsonwebtoken
- Typesciprt
- Styled Components
- Update
- mypage
- 빌드 및 배포
- 로그인 로직
- ui탬플릿
- 공통메서드
- 캘린더 라이브러리
- 스프링시큐리티
- userManagement
- Today
- Total
I T H
[프로젝트] 16. 관리자 회원관리페이지 - 그리드 / 엑셀 (Week 4) 본문
관리자 전용 화면 중
회원관리 페이지를 개발 진행함
해당 화면은 무료로 제공하는 그리드 API를 활용하여
테이블 태그 대신 자바스크립트에서 화면에 데이터를 출력해보고자 함.
라이브러리 사용을 위해 아래 사이트에서 참고.
TOAST UI :: Make Your Web Delicious!
TOAST UI is an open-source JavaScript UI library maintained by NHN Cloud.
ui.toast.com
관련 라이브러리를 프로젝트에 임포트하여 사용.
<!-- tui grid -->
<link rel="stylesheet" href="https://uicdn.toast.com/grid/latest/tui-grid.css" />
...
<!-- tui grid -->
<script src="https://uicdn.toast.com/grid/latest/tui-grid.js"></script>
페이지 구현 및 컨트롤러 작성을 통해
회원관리 페이지 개발 및
기능 중 회원 리스트 조회만 먼저 처리해 보자.
먼저 템플릿 버튼 모양이 너무 커서
살짝 커스터마이징을 진행한 스타일시트 파일을 작성.
[ custom.css ]
.amado-btn-custS {
display: inline-block;
min-width: 60px;
height: 30px;
color: #ffffff !important;
border: none;
border-radius: 0;
padding: 0 7px;
font-size: 11px;
line-height: 30px;
background-color: #fbb710;
font-weight: 400;
margin-bottom: 5px;
}
.amado-btn-custR {
display: inline-block;
min-width: 60px;
height: 30px;
color: #ffffff !important;
border: none;
border-radius: 0;
padding: 0 7px;
font-size: 11px;
line-height: 30px;
background-color: #dc3545;
font-weight: 400;
margin-bottom: 5px;
}
.amado-btn-custI {
display: inline-block;
min-width: 60px;
height: 30px;
color: #ffffff !important;
border: none;
border-radius: 0;
padding: 0 7px;
font-size: 11px;
line-height: 30px;
background-color: #17a2b8;
font-weight: 400;
margin-bottom: 5px;
}
.amado-btn-custE {
display: inline-block;
min-width: 60px;
height: 30px;
color: #ffffff !important;
border: none;
border-radius: 0;
padding: 0 7px;
font-size: 11px;
line-height: 30px;
background-color: #175625;
font-weight: 400;
margin-bottom: 5px;
}
[ userAdm.jsp ]
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="kr">
<head>
<meta charset="UTF-8">
<meta name="description" content="">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- The above 4 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<!-- Title -->
<title>ART - [관리자] 회원관리</title>
<!-- import CSS -->
<%@include file="/resources/inc/incCss.jsp"%>
<!-- jQuery modal 팝업창 사용 CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.css" />
</head>
<body>
<!-- ##### Main Content Wrapper Start ##### -->
<div class="main-content-wrapper d-flex clearfix">
<!-- import Header -->
<%@include file="/resources/inc/incHeader.jsp"%>
<div class="products-catagories-area section-padding-100">
<div class="container-fluid">
<div class="row">
<div class="col-12 col-lg-12">
<div class="checkout_details_area mt-50 clearfix">
<div class="cart-title">
<h4>[관리자] 회원관리</h4>
</div>
</div>
</div>
<!-- 조회 조건 -->
<div class="col-md-3 mb-3">
<small>사용자 아이디</small>
<input type="text" class="form-control" id="txtId" value="" placeholder="" required>
</div>
<div class="col-md-3 mb-3">
<small>성명</small>
<input type="text" class="form-control" id="txtName" value="" placeholder="" required>
</div>
<div class="col-md-3 mb-3">
<small>권한</small>
<select class="w-100" id="cmbAuth">
<option value="">전체</option>
<option value="1">일반사용자</option>
<option value="2">관리자</option>
</select>
</div>
<!-- 버튼 -->
<div class="col-12 col-lg-12" style="text-align: right;">
<a id="btnSearch" class="btn amado-btn-custS w-10">조회</a>
<a id="btnRemove" class="btn amado-btn-custR w-10">삭제</a>
<a id="btnSave" class="btn amado-btn-custI w-10">추가</a>
<a id="btnExcel" class="btn amado-btn-custE w-10">엑셀</a>
</div>
</div>
<div id="grid"></div>
</div>
</div>
<div id="ex1" class="modal">
<p>신규 사용자 등록</p>
<div class="row">
<div class="col-md-6 mb-3">
<small>아이디</small>
<!-- 한 페이지에 id가 겹치면 안되므로 팝업창에서 작성한 컴포넌트들의 id는 *Pop* 키워드를 붙여주기로 함 (아이디~이메일 모두) 예)txtPopId, txtPopPwd -->
<input type="text" class="form-control popTxt" id="txtPopId" value="" placeholder="아이디 입력" required>
</div>
<div class="col-md-6 mb-3">
<small>비밀번호</small>
<input type="password" class="form-control popTxt" id="txtPopPwd" value="" placeholder="비밀번호 입력" required>
</div>
<div class="col-md-6 mb-3">
<small>사용자 권한</small>
<select class="w-100" id="cmbAuthType">
<option value="1">일반사용자</option>
<option value="2">관리자</option>
</select>
</div>
<div class="col-md-6 mb-3">
<small>사용자명</small>
<input type="text" class="form-control popTxt" id="txtPopName" value="" placeholder="사용자명 입력">
</div>
<div class="col-md-6 mb-3">
<small>성별</small>
<select class="w-100" id="cmbSex">
<option value="1">남자</option>
<option value="2">여자</option>
</select>
</div>
<div class="col-md-6 mb-3">
<small>전화번호</small>
<input type="number" class="form-control popTxt" id="txtPopTel" min="0" placeholder="전화번호 입력" value="">
</div>
<div class="col-md-6 mb-3">
<small>이메일</small>
<input type="email" class="form-control popTxt" id="txtPopMail" placeholder="이메일 입력" value="">
</div>
</div>
<hr>
<a id="btnSaveUser" class="btn amado-btn-custS w-10">저장</a>
<a id="btnModifyUser" class="btn amado-btn-custS w-10" style="display: none;">수정</a>
<a href="#" class="btn amado-btn-custE w-10" rel="modal:close">닫기</a>
</div>
</div>
<!-- ##### Main Content Wrapper End ##### -->
<!-- import Footer -->
<%@include file="/resources/inc/incFooter.jsp"%>
<!-- import JS -->
<%@include file="/resources/inc/incJs.jsp"%>
<!-- jQuery modal 팝업창 사용 라이브러리 -->
<!-- https://github.com/kylefox/jquery-modal -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.js"></script>
<!-- page script -->
<script src="/resources/views/userAdm.js"></script>
</body>
</html>
[ userAdm.js ]
/*******************************************************************************
* userAdm.js
* @author thkim
* @since 2022
* @DESC 관리자 - 회원관리 화면 스크립트
******************************************************************************/
(function() {
function UserAdm() {
/*
* private variables
*/
var grid = null; // 그리드 객체를 담기위한 변수
/*
* 초기화 메소드
*/
function _init() {
// 이벤트 처리 함수 호출
bindEvent();
// 등록된 사용자 리스트 조회
findUserInfo();
}
function bindEvent() {
// 조회 버튼 클릭 이벤트
$("#btnSearch").on("click", function() {
findUserInfo();
});
// 삭제 버튼 클릭 이벤트 - 체크박스에 체크한 항목의 사용자를 삭제할 수 있도록 한다.
$("#btnRemove").on("click", function() {
var checkedRow = grid.getCheckedRows();
if(checkedRow.length <= 0) {
alert("삭제할 항목을 선택하시기 바랍니다.");
return;
}
saveUserInfoRemove(checkedRow);
});
// 추가 버튼 클릭 이벤트 - 팝업창을 오픈하여 사용자를 추가하거나 수정할 수 있도록 한다.
$("#btnSave").on("click", function() {
$("#ex1").modal(); // 모달(팝업) 창 오픈
$("#btnModifyUser").hide();
$("#btnSaveUser").show();
$("#txtPopId").attr("readOnly", false); // 편집 가능하도록
// 이미 입력된 정보가 있을 수 있으므로
// 각 항목을 초기화
$(".popTxt").val("");
});
// 사용자 등록 버튼 클릭 이벤트
$("#btnSaveUser").on("click", function() {
saveUserInfo();
});
// 엑셀 버튼 클릭 이벤트
$("#btnExcel").on("click", function() {
var obj = {
userId: $("#txtId").val(),
userName: $("#txtName").val(),
userAuth: $("#cmbAuth").val()
};
cfCustomExcelDownloadDyn("/userAdm/findExcel", obj);
});
// 팝업창 내에서 수정 버튼 클릭 이벤트
$("#btnModifyUser").on("click", function() {
saveModifyUserInfo();
});
}
/*
* 등록된 사용자 리스트 조회
*/
function findUserInfo() {
var obj = {
userId: $("#txtId").val(),
userName: $("#txtName").val(),
userAuth: $("#cmbAuth").val()
};
cfFind("/userAdm/findUserInfo", obj, function(data) {
if (data.length > 0) {
setGrid(data);
}
}, true, "POST");
}
/*
* 체크한 사용자 정보 삭제
*/
function saveUserInfoRemove(obj) {
var result = confirm('삭제하시겠습니까?'); // confirm message : 예/아니오 응답을 받기위한 메시지창
if(result) {
cfSave("/userAdm/saveUserInfoRemove", obj, function(data) {
if(data.success) {
alert("사용자 정보가 삭제되었습니다.");
findUserInfo(); // 사용자 정보 재조회
} else {
alert("사용자 정보 삭제 실패하였습니다. 확인 후 다시 등록하시기 바랍니다.");
}
});
}
}
/*
* 신규 입력한 사용자 정보 저장
*/
function saveUserInfo() {
var obj = setParam();
var result = confirm('저장하시겠습니까?'); // confirm message : 예/아니오 응답을 받기위한 메시지창
if(result) {
cfSave("/userAdm/saveUserInfo", obj, function(data) {
if(data.success) {
alert("사용자 정보가 등록되었습니다.");
// 각 항목을 초기화
$(".popTxt").val("");
// modal 팝업창 닫기
$.modal.close();
// 사용자 정보 재조회
findUserInfo();
} else {
alert("사용자 정보 등록 실패하였습니다. 확인 후 다시 등록하시기 바랍니다.");
}
});
}
}
/*
* grid setting
*/
function setGrid(data) {
// 이미 그리드가 그려져 있으면
if(grid != null) {
grid.destroy(); // 초기화하기 위해 사용
}
// 그리드 컬럼 정보 세팅
var columns = [{
header: '사용자 아이디',
name: 'USER_ID'
}, {
header: '성명',
name: 'USER_NAME'
}, {
header: '권한',
name: 'AUTH_TYPE'
}, {
header: '성별',
name: 'USER_SEX'
}, {
header: '전화번호',
name: 'USER_PHONE'
}, {
header: '이메일',
name: 'USER_EMAIL'
}, {
header: '주소',
name: 'USER_ADDR'
}, {
header: '우편번호',
name: 'ZIP_CODE'
}, {
header: '탈퇴여부',
name: 'OUT_YN'
}, {
header: '등록일자',
name: 'INPUT_DATETIME'
}];
// 그리드 옵션 설정 및 그리드 생성
grid = new tui.Grid({
el: document.getElementById('grid'),
columns: columns,
columnOptions: {
resizable: true // 컬럼 사이즈 조정
},
rowHeaders: ['checkbox'] // 채크박스
});
grid.resetData(data); // 그리드 데이터 세팅
tui.Grid.applyTheme('striped'); // 줄무늬 스타일 적용
// 그리드 더블클릭 이벤트
// 1개의 행을 더블클릭할 경우 수정할 수 있도록 팝업이 오픈된다.
grid.on("dblclick", function(selected) {
var rowIdx = selected.rowKey; // 선택한 행의 인덱스
var item = grid.getRow(rowIdx);
setModifyPop(item);
});
}
/**
* 수정 팝업
*/
function setModifyPop(item) {
// 클릭한 사용자 정보 팝업창에 세팅
$("#txtPopId").val(item.USER_ID);
$("#txtPopPwd").val("");
$("#cmbAuthType").val((item.AUTH_TYPE == "관리자" ? "2" : "1")).niceSelect('update');;
$("#txtPopName").val(item.USER_NAME);
$("#cmbSex").val((item.USER_SEX == "남자" ? "1" : "2")).niceSelect('update');;
var userPhone = item.USER_PHONE;
userPhone = userPhone.replace("-", "").replace("-", "");
$("#txtPopTel").val(userPhone);
$("#txtPopMail").val(item.USER_EMAIL);
$("#ex1").modal(); // 모달 팝업창 오픈
$("#btnSaveUser").hide(); // 저장 버튼은 숨김
$("#btnModifyUser").show(); // 수정 버튼은 노출
$("#txtPopId").attr("readOnly", true); // 사용자 아이디는 키이므로 수정 금지
}
/**
* 수정 팝업창에서 수정 버튼 클릭한 경우
* 입력한 정보로 데이터를 업데이트 한다.
*/
function saveModifyUserInfo() {
var obj = setParam();
var result = confirm('사용자 정보를 수정하시겠습니까?'); // confirm message : 예/아니오 응답을 받기위한 메시지창
if(result) {
cfSave("/userAdm/saveModifyUserInfo", obj, function(data) {
if(data.success) {
alert("사용자 정보가 수정되었습니다.");
// 각 항목을 초기화
$(".popTxt").val("");
// modal 팝업창 닫기
$.modal.close();
// 사용자 정보 재조회
findUserInfo();
} else {
alert("사용자 정보 수정 실패하였습니다. 확인 후 다시 수정하시기 바랍니다.");
}
});
}
}
/**
* 저장 시 사용될 파라미터 정보를 세팅
*/
function setParam() {
var userId = $("#txtPopId").val();
var userPw = $("#txtPopPwd").val();
var authType = $("#cmbAuthType").val();
var userName = $("#txtPopName").val();
var userSex = $("#cmbSex").val();
var userPhone = $("#txtPopTel").val();
var userEmail = $("#txtPopMail").val();
if(userId == null || userId == "") { // 사용자 아이디가 입력되지 않은 경우
alert("사용자 아이디를 입력하시기 바랍니다.");
return;
}
if(userPw == null || userPw == "") { // 사용자 비밀번호가 입력되지 않은 경우
alert("사용자 비밀번호를 입력하시기 바랍니다.");
return;
}
var obj = {
userId: userId,
userPw: userPw,
authType: authType,
userName: userName,
userSex: userSex,
userPhone: userPhone,
userEmail: userEmail
}
return obj;
}
function _finalize() {
}
return {
init: _init,
finalize: _finalize
};
};
var userAdm = new UserAdm();
userAdm.init();
})();
//# sourceURL=userAdm.js
[ util.js ] - 하단에 내용 추가
/******************************************************************************
*
* cfCustomExcelDownloadDyn
* 엑셀 다운로드 (동적 파라미터 형태)
*
******************************************************************************/
function cfCustomExcelDownloadDyn(url, obj, method) {
var keys = Object.keys(obj);
var form = "<form action='" + url + "' method='" + (method ? method : 'POST') + "'>";
for(var i = 0; i < keys.length; i++) {
form += "<input type='hidden' name='" + keys[i] + "' value='" + obj[keys[i]] + "' />";
}
form += "</form>";
$(form).appendTo("body").submit().remove();
}
[ UserAdmController.java ]
package kr.co.art.biz.userAdm.web;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import kr.co.art.biz.userAdm.persistence.UserAdmMapper;
import kr.co.art.biz.userAdm.service.UserAdmService;
@Controller
@RequestMapping("/userAdm")
public class UserAdmController {
@Autowired
private UserAdmMapper userAdmMapper;
@Autowired
private UserAdmService userAdmService;
@RequestMapping("")
public String main() {
return "userAdm";
}
/**
* 등록된 사용자 리스트 조회
* (/userAdm/findUserInfo)
* @return
*/
@RequestMapping("/findUserInfo")
@ResponseBody
public List<Map<String, Object>> findUserInfo(@RequestBody Map<String, Object> param) {
List<Map<String, Object>> list = userAdmMapper.findUserInfo(param);
return list;
}
/**
* 등록된 사용자 삭제
* (/userAdm/saveUserInfoRemove)
* @return
*/
@RequestMapping("/saveUserInfoRemove")
@ResponseBody
public Map<String, Object> saveUserInfoRemove(@RequestBody List<Map<String, Object>> param) {
Map<String, Object> result = new HashMap<String, Object>();
userAdmService.saveUserInfoRemove(param);
result.put("success", true);
return result;
}
/**
* 신규 사용자 등록
* (/userAdm/saveUserInfo)
* @return
*/
@RequestMapping("/saveUserInfo")
@ResponseBody
public Map<String, Object> saveUserInfo(@RequestBody Map<String, Object> param) {
Map<String, Object> result = new HashMap<String, Object>();
userAdmService.saveUserInfo(param);
result.put("success", true);
return result;
}
/**
* 사용자 정보 수정
* (/userAdm/saveModifyUserInfo)
* @return
*/
@RequestMapping("/saveModifyUserInfo")
@ResponseBody
public Map<String, Object> saveModifyUserInfo(@RequestBody Map<String, Object> param) {
Map<String, Object> result = new HashMap<String, Object>();
userAdmService.saveModifyUserInfo(param);
result.put("success", true);
return result;
}
/**
* 엑셀 다운로드
* (/userAdm/findExcel)
* @return
*/
@RequestMapping("/findExcel")
public String findExcel(@RequestParam Map<String, Object> param, ModelMap map) {
List<Map<String, Object>> list = userAdmMapper.findUserInfo(param);
map.put("list", list);
map.put("excelFile", "userInfo.xlsx");
return "excelView";
}
}
[ UserAdmService.java ]
package kr.co.art.biz.userAdm.service;
import java.util.List;
import java.util.Map;
public interface UserAdmService {
// 등록된 사용자 정보 삭제
void saveUserInfoRemove(List<Map<String, Object>> list);
// 신규 사용자 등록
void saveUserInfo(Map<String, Object> map);
// 사용자 정보 수정
void saveModifyUserInfo(Map<String, Object> map);
}
[ UserAdmServiceImpl.java ]
package kr.co.art.biz.userAdm.service;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import kr.co.art.biz.userAdm.persistence.UserAdmMapper;
@Service
public class UserAdmServiceImpl implements UserAdmService {
@Autowired
private UserAdmMapper userAdmMapper;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public void saveUserInfoRemove(List<Map<String, Object>> list) {
// 체크한 항목이 여러개일 수 있으므로
// 리스트로 전달받고 for문 돌려서 1개씩 삭제
for(Map<String, Object> map : list) {
userAdmMapper.saveUserInfoRemove(map);
}
}
@Override
public void saveUserInfo(Map<String, Object> map) {
String orgPassword = (String) map.get("userPw");
String userId = (String) map.get("userId");
String encPassword = initUserPassword(orgPassword, userId);
map.put("userPw", encPassword); // 암호화한 비밀번호로 다시 세팅
userAdmMapper.saveUserInfo(map);
}
@Override
public void saveModifyUserInfo(Map<String, Object> map) {
String orgPassword = (String) map.get("userPw");
String userId = (String) map.get("userId");
String encPassword = initUserPassword(orgPassword, userId);
map.put("userPw", encPassword); // 암호화한 비밀번호로 다시 세팅
userAdmMapper.saveModifyUserInfo(map);
}
private String initUserPassword(String orgPassword, String userId) {
return passwordEncoder.encode(orgPassword);
}
}
[ UserAdmMapper.java ]
package kr.co.art.biz.userAdm.persistence;
import java.util.List;
import java.util.Map;
public interface UserAdmMapper {
// 등록된 사용자 리스트 조회
List<Map<String, Object>> findUserInfo(Map<String, Object> params);
// 사용자 정보 삭제
void saveUserInfoRemove(Map<String, Object> params);
// 사용자 정보 등록
void saveUserInfo(Map<String, Object> params);
// 사용자 정보 수정
void saveModifyUserInfo(Map<String, Object> params);
}
[ UserAdmMapper.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="kr.co.art.biz.userAdm.persistence.UserAdmMapper">
<select id="findUserInfo" resultType="hashmap" parameterType="hashmap">
SELECT USER_ID
, USER_NAME
, CASE WHEN AUTH_TYPE = '1' THEN '일반 사용자' ELSE '관리자' END AUTH_TYPE
, CASE WHEN USER_SEX = '1' THEN '남자' ELSE '여자' END USER_SEX
, CONCAT(SUBSTR(USER_PHONE, 1, 3), '-', SUBSTR(USER_PHONE, 4, 4), '-', SUBSTR(USER_PHONE, 8, 4)) USER_PHONE
, USER_EMAIL
, USER_ADDR
, ZIP_CODE
, OUT_YN
, DATE_FORMAT(INPUT_DATETIME, '%Y-%m-%d') INPUT_DATETIME
FROM ART.ART_USER
WHERE 1=1
<if test="!''.equals(userId)">
AND USER_ID LIKE CONCAT('%', #{userId}, '%')
</if>
<if test="!''.equals(userName)">
AND USER_NAME LIKE CONCAT('%', #{userName}, '%')
</if>
<if test="!''.equals(userAuth)">
AND AUTH_TYPE = #{userAuth}
</if>
</select>
<delete id="saveUserInfoRemove" parameterType="hashmap">
DELETE FROM ART.ART_USER
WHERE 1=1
AND USER_ID = #{USER_ID}
</delete>
<insert id="saveUserInfo" parameterType="hashmap">
INSERT INTO ART.ART_USER (
USER_ID
, AUTH_TYPE
, USER_PW
, USER_NAME
, USER_SEX
, USER_PHONE
, USER_EMAIL
, OUT_YN
, INPUT_DATETIME
)
VALUES (
#{userId}
, #{authType}
, #{userPw}
, #{userName}
, #{userSex}
, #{userPhone}
, #{userEmail}
, 'N' -- default
, NOW()
)
</insert>
<update id="saveModifyUserInfo" parameterType="hashmap">
UPDATE ART.ART_USER
SET USER_NAME = #{userName}
, USER_SEX = #{userSex}
, USER_PHONE = #{userPhone}
, USER_EMAIL = #{userEmail}
, USER_PW = #{userPw}
WHERE 1=1
AND USER_ID = #{userId}
</update>
</mapper>
그리드를 활용하니 스타일을 따로 주거나 할 필요가 없어서 편함.

데이터 조회, 삭제, 추가, 엑셀 기능이 포함됨

사용자 신규등록, 더블클릭 후 수정 시 사용될 모달 팝업창
[ 엑셀 다운로드 기능 ]
Apache Poi 활용 - 엑셀 다운로드 기능을 구현하기 위해
pom.xml 파일에 라이브러리 의존성 추가
<!-- Excel POI -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.13</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.13</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.13</version>
</dependency>
<!-- Apache POI CSV -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.5</version>
</dependency>
<!-- jxls (with poi - custview) -->
<dependency>
<groupId>net.sf.jxls</groupId>
<artifactId>jxls-core</artifactId>
<version>1.0.6</version>
</dependency>
[ CustomExcelView.java ]
package kr.co.art.sys.framework.ui;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.jxls.transformer.XLSTransformer;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.view.document.AbstractExcelView;
public class CustomExcelView extends AbstractExcelView {
@Autowired
private ServletContext servletContext;
@Override
protected void buildExcelDocument(Map<String, Object> model,
HSSFWorkbook workbook, HttpServletRequest request, HttpServletResponse response)
throws Exception {
XLSTransformer transformer = new XLSTransformer();
String excelFileName = (String) model.get("excelFile");
String saveExcelName = (String) model.get("saveName");
if(!"".equals(saveExcelName) && saveExcelName != null) {
saveExcelName = new String(saveExcelName.getBytes("UTF-8"), "ISO-8859-1");
}
// markAsFixedSizeCollection 설정
String[] array = (String[]) model.get("fixedSizeCollections");
if(array != null) {
for(int i = 0; i < array.length; i++) {
transformer.markAsFixedSizeCollection(array[i]);
}
}
String path = servletContext.getRealPath("/WEB-INF/readExcel/");
String templateFileName = path + "/" + excelFileName;
Workbook resultWorkbook = transformer.transformXLS(new FileInputStream(templateFileName), model);
StringBuffer contentDisposition = new StringBuffer();
contentDisposition.append("attachment;fileName=\"");
if(!"".equals(saveExcelName) && saveExcelName != null) {
contentDisposition.append(saveExcelName);
} else {
contentDisposition.append(excelFileName);
}
contentDisposition.append("\";");
response.setHeader("Content-Disposition", contentDisposition.toString());
response.setContentType("application/vnd.ms-excel");
resultWorkbook.write(response.getOutputStream());
}
}
[ excel 템플릿 파일 생성 및 프로젝트 삽입 ]
- /WEB-INF/readExcel 폴더 생성 후 아래에 엑셀 템플릿 파일 위치함
[ dispatcher-servlet.xml ] - 파일 수정 : 아래 내용 추가
<!-- excel view --> <bean id="excelView" class="kr.co.art.sys.framework.ui.CustomExcelView"/>
'Spring ArtGallery Project' 카테고리의 다른 글
[프로젝트] 18. 상품페이지 - 장바구니 담기 (Week 4) (0) | 2024.01.24 |
---|---|
[프로젝트] 17. 상품상세 페이지 - 슬라이드 이미지 (Week 4) (0) | 2024.01.24 |
[프로젝트] 15. 메인페이지 꾸미기 (Week 3) (1) | 2024.01.23 |
[프로젝트] 14. 시큐리티 tag 라이브러리 - 관리자 메뉴 처리 (Week 3) (0) | 2024.01.23 |
[프로젝트] 13. 관리자 - 상품등록 구현 (Week 3) (0) | 2024.01.23 |