<script type="text/javascript">
$(document).ready(function() {
	//임의 숫자 세팅
	$("input[name='ipt_calc']").each(function(){
		$(this).val((Math.random() * 100).toFixed());
	});
});

function fnCalc(targetNm){
	//최대값 구하기
	let maxValue = Math.max.apply(null, $("#" + targetNm + "Area input[type='number']").map(function (){return $(this).val();}).get());
	//0을 제외한 최소값 구하기
	let minValue = Math.min.apply(null, $("#" + targetNm + "Area input[type='number']").map(function (){return $(this).val() == 0 ? 99999 : $(this).val();}).get());

	$("#sp_area").text(targetNm);
	$("#sp_max").text(maxValue);
	$("#sp_min").text(minValue);
}
</script>

	<div>
		<div>area : <span id="sp_area"></span></div>
		<div>max : <span id="sp_max"></span></div>
		<div>min : <span id="sp_min"></span></div>
	</div>
	<br /><br />
	<div id="firstArea">
		<div>firstArea <button type="button" onclick="fnCalc('first');">calc</button></div>
		<div><input type="number" name="ipt_calc" value="" /></div>
		<div><input type="number" name="ipt_calc" value="" /></div>
		<div><input type="number" name="ipt_calc" value="" /></div>
		<div><input type="number" name="ipt_calc" value="" /></div>
		<div><input type="number" name="ipt_calc" value="" /></div>
		<div><input type="number" name="ipt_calc" value="" /></div>
	</div>
	<div id="secondArea">
		<div>secondArea <button type="button" onclick="fnCalc('second');">calc</button></div>
		<div><input type="number" name="ipt_calc" value="" /></div>
		<div><input type="number" name="ipt_calc" value="" /></div>
		<div><input type="number" name="ipt_calc" value="" /></div>
		<div><input type="number" name="ipt_calc" value="" /></div>
		<div><input type="number" name="ipt_calc" value="" /></div>
		<div><input type="number" name="ipt_calc" value="" /></div>
	</div>
반응형

스크립트로 엑셀 업로드가 가능하여 테스트해보고 스크립트로 Export도 가능할듯하여 테스트.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>엑셀 Export 테스트</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.16.9/xlsx.full.min.js"></script>
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js"></script>
<script>
	function upload(event) {
		var input = event.target;
		var reader = new FileReader();
		reader.onload = function() {
			var fdata = reader.result;
			var read_buffer = XLSX.read(fdata, {type : 'binary'});
			
			var xlsArea = document.getElementById("xlsArea");
			var tableStr = "<table id='tableData' style='border:1px solid;'>";
			
			read_buffer.SheetNames.forEach(function(sheetName) {
				var rowdata = XLSX.utils.sheet_to_json(read_buffer.Sheets[sheetName]);
				//console.log("[" + sheetName + "] 시트 데이터 : " + JSON.stringify(rowdata));
				
				$.each(rowdata, function(i, coldata){
					//console.log(rowdata);
					
					//엑셀 Header 세팅
					if(i == 0){
						tableStr += "<tr>";
						$.each(coldata, function(colHeader, colText){
							tableStr += "<th style='color:red;width:500px;border:1px solid;'>" + colHeader + "<th>";
						});
						tableStr += "</tr>";
					}
					
					//엑셀 내용 세팅
					tableStr += "<tr>";
					$.each(coldata, function(colHeader, colText){
						tableStr += "<td style='border:1px solid;'>" + colText + "<td>";
					});
					tableStr += "</tr>";
				});
			});
			
			tableStr += "</table>";
			xlsArea.innerHTML = tableStr;
			//console.log(tableStr);
		};
		reader.readAsBinaryString(input.files[0]);
	}
	
	var excelHandler = {
		getExcelFileName : function() {
			return 'table-test.xlsx';
		},
		getSheetName : function() {
			return 'Table Test Sheet';
		},
		getExcelData : function() {
			return document.getElementById('tableData');
		},
		getWorksheet : function() {
			return XLSX.utils.table_to_sheet(this.getExcelData());
		}
	};
	
	function s2ab(s) { 
		var buf = new ArrayBuffer(s.length); //convert s to arrayBuffer
		var view = new Uint8Array(buf);  //create uint8array as viewer
		for (var i=0; i<s.length; i++) view[i] = s.charCodeAt(i) & 0xFF; //convert to octet
		return buf;
	}
	
	function fnExport(){
		// step 1. workbook 생성
		var wb = XLSX.utils.book_new();
		
		// step 2. 시트 만들기 
		var newWorksheet = excelHandler.getWorksheet();
		
		// step 3. workbook에 새로만든 워크시트에 이름을 주고 붙인다.  
		XLSX.utils.book_append_sheet(wb, newWorksheet, excelHandler.getSheetName());
		
		// step 4. 엑셀 파일 만들기 
		var wbout = XLSX.write(wb, {bookType:'xlsx',  type: 'binary'});
		
		// step 5. 엑셀 파일 내보내기 
		saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), excelHandler.getExcelFileName());
	}
</script>

</head>
<body>
	<div style="float: left;">
		<input type="file" id="id_file_upload" onchange="upload(event)"/>
	</div>
	<div style="float: right;">
		<button type="button" id="btnExport" onclick="fnExport();">엑셀 내보내기</button>
	</div>
	<br /><br />
	<div id="xlsArea"></div>
</body>
반응형
    <script>
        $(function(){
            //datepicker
            $('.datepicker').not('.readonly').datepicker({
                format: 'dd-mm-yyyy',
                startDate: '+1d'
            }).on("blur", function(){
            	var dataRegexp = /[0-9]{4}-?(0[1-9]|1[012])-?(0[1-9]|[12][0-9]|3[01])/;
                if (!dataRegexp.test($(this).val()) ) {
                    $(this).val("");
                }
            });
            $.datepicker.setDefaults({
                dateFormat: 'yymmdd',
                prevText: '이전 달',
                nextText: '다음 달',
                monthNames: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
                monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],
                dayNames: ['일', '월', '화', '수', '목', '금', '토'],
                dayNamesShort: ['일', '월', '화', '수', '목', '금', '토'],
                dayNamesMin: ['일', '월', '화', '수', '목', '금', '토'],
                showMonthAfterYear: true,
                changeYear: true, //콤보박스에서 년 선택 가능
                changeMonth: true, //콤보박스에서 월 선택 가능
                yearRange: 'c-100:c+10'
            });
        });
    </script>
반응형

스크립트로 엑셀 업로드가 가능하여 테스트해봄.

 

case 1) 엑셀을 업로드하여 화면에 단순 표시

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>엑셀 업로드 테스트</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.16.9/xlsx.full.min.js"></script>
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script>
	function upload(event) {
		var input = event.target;
		var reader = new FileReader();
		reader.onload = function() {
			var fdata = reader.result;
			var read_buffer = XLSX.read(fdata, {type : 'binary'});
			
			var xlsArea = document.getElementById("xlsArea");
			var tableStr = "<table style='border:1px solid;'>";
			
			read_buffer.SheetNames.forEach(function(sheetName) {
				var rowdata = XLSX.utils.sheet_to_json(read_buffer.Sheets[sheetName]);
				//console.log("[" + sheetName + "] 시트 데이터 : " + JSON.stringify(rowdata));
				
				$.each(rowdata, function(i, coldata){
					//console.log(rowdata);
					
					//엑셀 Header 세팅
					if(i == 0){
						tableStr += "<tr>";
						$.each(coldata, function(colHeader, colText){
							tableStr += "<th style='color:red;width:500px;border:1px solid;'>" + colHeader + "<th>";
						});
						tableStr += "</tr>";
					}
					
					//엑셀 내용 세팅
					tableStr += "<tr>";
					$.each(coldata, function(colHeader, colText){
						tableStr += "<td style='border:1px solid;'>" + colText + "<td>";
					});
					tableStr += "</tr>";
				});
			});
			
			tableStr += "</table>";
			xlsArea.innerHTML = tableStr;
			//console.log(tableStr);
		};
		reader.readAsBinaryString(input.files[0]);
	}
</script>

</head>
<body>
	<input type="file" id="id_file_upload" onchange="upload(event)"/>
	<br /><br />
	<div id="xlsArea"></div>
</body>
</html>

 

case 2) 엑셀을 업로드하여 화면에서 수정 후 서버에 반영

(원래 엑셀을 서버로 업로드하는 부분과 export 하는 부분을 구현하려 하였으나 화면에 보여줄때 input 등으로 표시하고 수정하여 서버에 반영하면 필요없을 듯하여 수정)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>엑셀 업로드 테스트</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.16.9/xlsx.full.min.js"></script>
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script>
	function upload(event) {
		var input = event.target;
		var reader = new FileReader();
		reader.onload = function() {
			var fdata = reader.result;
			var read_buffer = XLSX.read(fdata, {type : 'binary'});
			
			var $xlsArea = $("#xlsArea");
			var $table = $("<table>", {style:"border:1px solid;"});
			
			read_buffer.SheetNames.forEach(function(sheetName) {
				var rowdata = XLSX.utils.sheet_to_json(read_buffer.Sheets[sheetName]);
				//console.log("[" + sheetName + "] 시트 데이터 : " + JSON.stringify(rowdata));
				
				$.each(rowdata, function(i, coldata){
					//console.log(rowdata);
					
					//엑셀 Header 세팅
					if(i == 0){
						var $headerTr = $("<tr>");
						$.each(coldata, function(colHeader, colText){
							var $th = $("<th>", {style : 'color:red;width:500px;border:1px solid;', text : colHeader});
							$headerTr.append($th);
						});
						$table.append($headerTr);
					}
					
					//엑셀 내용 세팅
					$tr = $("<tr>");
					$.each(coldata, function(colHeader, colText){
						var $td = $("<td>", {style : 'border:1px solid;'});
						var $ipt = $("<input>", {type : "input", value : colText, name : colHeader, style : "width:97%;"});
						$td.append($ipt);
						$tr.append($td);
					});
					$table.append($tr);
				});
			});
			
			$xlsArea.append($table);
			//console.log(tableStr);
		};
		reader.readAsBinaryString(input.files[0]);
	}
</script>

</head>
<body>
	<input type="file" id="id_file_upload" onchange="upload(event)"/>
	<br /><br />
	<div id="xlsArea"></div>
</body>
</html>

 

 

반응형

WebApplicationInitializer 인터페이스를 사용하면 web.xml에서 했던 서블릿, 필터, 리스너 설정 등을 java로 설정할 수 있다.
처음에 그것도 모르고 web.xml에 아무것도 없어 당황을....^^;

프로젝트를 하나 만들어 아래와 같이 간단히 등록하고 테스트를 해보니 정상 동작되는 것을 확인했다.

 

package testweb;
 
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
 
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;
 
public class Init implements WebApplicationInitializer {
 
	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		System.out.println("onStartup...");
		addListender(servletContext);
		addDispatcher(servletContext);
		addFilter(servletContext);
	}
 
	public void addListender(ServletContext servletContext) {
		System.out.println("addListender...");
		AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
		appContext.register(AppConfig.class);
		ContextLoaderListener listender = new ContextLoaderListener(appContext);
		servletContext.addListener(listender);
	}
 
	public void addDispatcher(ServletContext servletContext) {
		System.out.println("addDispatcher...");
		AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
		webContext.register(WebConfig.class);
		DispatcherServlet dispatcherServlet = new DispatcherServlet(webContext);
		ServletRegistration.Dynamic webServlet = servletContext.addServlet("webServlet", dispatcherServlet);
		webServlet.addMapping("/");
		webServlet.setLoadOnStartup(1);
	}
 
	public void addFilter(ServletContext servletContext) {
		System.out.println("addFilter...");
		CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter("UTF-8", true, true);
		FilterRegistration.Dynamic webEncodingFilter = servletContext.addFilter("webEncodingFilter", encodingFilter);
		webEncodingFilter.addMappingForUrlPatterns(null, false, "/*");
	}
}

 

반응형

input type이 number 경우 maxlength가 먹히지 않어 스크립트 제어가 필요해짐.

/* ********************************************************
 * 기타 class 이벤트 적용
 * vPoint12 : 정수 10자리 소수점 2자리 까지 입력되도록
 * vNum10 : 정수만 10자리 입력되도록
 ******************************************************** */
function fnEtcClassEvent(){
    $(".vPoint12").each(function(){
        // .(마침표)가 양끝에 있는 케이스를 처리
        $(this).off('blur').on('blur',function(e){
            var value = $(this).val();
            var regExp = /^\.|\.$/;
            if(regExp.test(this.value)){
                $(this).val(value.replace('.',''));
            }
        });
        
        // 소수점 둘째자리까지의 실수만 입력 허용
        $(this).off('input').on('input',function(e){
            var value = $(this).val();
            var regExp = /^\d{0,10}(\.\d{0,2})?$/;
            if(!regExp.test(this.value)){
                $(this).val(value.substring(0,value.length-1));
            }
        });
        
        // 숫자와 .(마침표)만 입력 허용
        $(this).off('keypress').on('keypress',function(e){
            e = e || window.event;
            var charCode = e.which || e.keyCode;
            if (!((charCode >= 48 && charCode <= 57) || charCode === 46)){
                return false;
            }
        });
    });
    
    $(".vNum10").each(function(){
        // 정수만 입력 허용
        $(this).off('input').on('input',function(e){
            var value = $(this).val();
            var regExp = /^\d{0,10}$/;
            if(!regExp.test(this.value)){
                $(this).val(value.substring(0,value.length-1));
            }
        });
        
        // 숫자만 입력 허용
        $(this).off('keypress').on('keypress',function(e){
            e = e || window.event;
            var charCode = e.which || e.keyCode;
            if (!((charCode >= 48 && charCode <= 57))){
                return false;
            }
        });
    });
}

반응형
/* ********************************************************
 * 기타 벨리데이션
 * vReq : 필수입력 체크(class)
 ******************************************************** */
function fnEtcValid(){
	var isPass = true;
	$.each($(".vReq"), function(idx, obj){
		if(obj.value == "" && isPass){
			var vId = obj.id;
			var vLabel = $("label[for='" + vId + "']").text() || $("#" + vId).attr("title");
			var vStr = vLabel == "" ? "" : "[ " + vLabel + " ] 항목은 ";
			isPass = false;
			alert(vStr + "필수입력 항목입니다.");
			obj.focus();
			return false;
		}
	});
	return isPass;
}
반응형
$(document).ready(function() {
    // validate 전화번호 형식 추가
    jQuery.validator.addMethod("phone", function(phone_number, element) {
        phone_number = phone_number.replace(/\s+/g, ""); 
        return this.optional(element) || phone_number.length > 9 && phone_number.match(/^(01[016789]{1}|02|0[3-9]{1}[0-9]{1})-?[0-9]{3,4}-?[0-9]{4}$/);
    }, "잘못된 입력 형식입니다");
    
    // validate date 형식 추가
    jQuery.validator.addMethod("date", function(value, element) {
        return this.optional(element) || value.match(/^(19|20)?\d{2}[/., -](0?[1-9]|1[0-2])[/., -](0?[1-9]|[12][0-9]|3[0-1])$/);
    }, "잘못된 입력 형식입니다");
});
반응형

이런 저런 이유(건강, 일없음.... ㅜ.ㅡ)로 쉬면서 웹사이트를 하나 만들다가 발견한 사이트.

 

무료로 텍스트 로고를 바로 제작해서 다운받아 사용할 수 있다.

 

사업용 같은 사이트를 만들려면 돈 좀 들여 로고 제작을 하겠지만... 취미나 간단한 웹사이트를 만들때는 유용할 듯하다. ^-^;

 

글자 이펙트나 색상 옵션 등 설정가능하고 다른유형의 로고를 덧붙여 만드는 등 여러 옵션기능 존재.

 

Link : Cool Text Graphics Generator

 

Cool Text Graphics Generator

 

반응형

'개발 > 참고사이트' 카테고리의 다른 글

부트스트랩 무료 템플릿 사이트  (1) 2020.08.11
무료 아이콘 사이트  (0) 2020.07.10
원격데스크탑 연결  (0) 2020.07.10
PPT 무료템플릿 모아놓은 사이트  (2) 2019.06.05
Mybatis 매퍼 설정관련  (0) 2019.02.07

1. 이클립스 가동 후 Server 탭에서 IBM 폴더의 Liberty 서버 생성

  -> 필요한 파일을 다운받느라 어느정도 시간이 걸리고 다 받은 후 이클립스 재시작 알림창으로 재시작


2. 아래 Url에서 WebSphere 파일 받은 후 적당한 위치에 압축 풀기

  -> https://developer.ibm.com/wasdev/downloads/#asset/runtimes-wlp-webProfile8


cf) Maven으로 받는 방법도 있음

<dependency>

  <groupId>com.ibm.websphere.appserver.runtime</groupId>

  <artifactId>wlp-webProfile8</artifactId>

  <version>20.0.0.8</version>

  <type>zip</type>

</dependency>


3. 이클립스 Server 탭에서 IBM 폴더의 Liberty 서버 다시 생성하기

  -> Runtime Environment에서 1.번에서 압축 풀은 폴더 지정하기


4. Server 탭에서 해당서버 컨텍스트 루트 및 인코딩 지정하고 서버 시작하여 확인


반응형

'개발 > 기타' 카테고리의 다른 글

JSP에 오늘 날짜 또는 시간 표시  (0) 2019.04.17
JSTL c:out 데이터 표시할때 태그 적용  (0) 2019.03.04

bootstrap template 및 예제, 설명 등


http://bootstrapk.com/getting-started/



해외 bootstrap template 제공 사이트


https://www.bootstrapzero.com/browse

반응형

* "ALL_" 대신에 "USER_"를 사용하고 OWNER 조건을 빼서 사용할 수도 있다.


--전체 계정 전체 테이블 조회

SELECT * FROM ALL_TABLES;


--사용자계정 전체 테이블 조회

SELECT * FROM ALL_TABLES WHERE OWNER = 'SUBINTO';

 

 --사용자계정 전체 테이블 커멘트 조회

 SELECT * FROM ALL_TAB_COMMENTS WHERE OWNER = 'SUBINTO';


--사용자계정 전체 컬럼 조회

 SELECT * FROM ALL_TAB_COLUMNS WHERE OWNER = 'SUBINTO';

 

 --사용자계정 전체 컬럼 커멘트 조회

 SELECT * FROM ALL_COL_COMMENTS WHERE OWNER = 'SUBINTO';


* 위 쿼리를 활용하여 쿼리 생성 쿼리를 만들수도 있다.(아래는 SELECT 쿼리를 생성하는 쿼리 참조)


--쿼리 생성 쿼리(SELECT)

SELECT DECODE(ROWNUM, 1, 'SELECT ' ||  CHR(13), ', ')

    || UPPER(COLUMN_NAME) || ' AS ' ||LOWER(SUBSTR(COLUMN_NAME, 1,1))||SUBSTR(REPLACE(INITCAP(LOWER(COLUMN_NAME)), '_',''), 2)    

    || DECODE(ROWNUM, (COUNT(1) OVER()), CHR(13) || '  FROM '|| TABLE_NAME ||';', '') AS "SELECT Query"

 FROM ALL_TAB_COLUMNS

WHERE OWNER = 'SUBINTO'

  AND TABLE_NAME = UPPER('TB_MENU');


반응형

* Tabulator Tree 세팅은 아래의 이전 글 참조


Tabulator Tree 데이터 세팅 및 노드 추가 처리 스크립트



1.Tabulator 생성시 columns에 아래 체크박스 컬럼 추가


            {

                title:"매핑여부",

                field:"mappingGubun",

                width:80,

                hozAlign:"center",

                download:false,

                vertAlign:"middle",

                editor:"tickCross",

                formatter:"tickCross",

                formatterParams: {

                    allowTruthy:true,

                    tickElement:"<input type='checkbox' checked>",

                    crossElement:"<input type='checkbox'>"

                },

                cellEdited:function(cell) { 

                    if (cell.getValue())

                        checkedTreeNode(menuMngSheet, cell, 1); //해당 체크 박스 및 하위 체크박스 체크

                    else

                        checkedTreeNode(menuMngSheet, cell, 0); //해당 체크 박스 및 하위 체크박스 체크해제

                },

                headerFilter:"tickCross",

                headerFilterEmptyCheck:function(value){

                    fnHeaderCheck(value); //체크박스 전체 체크

                    return true;

                }

            },


2. Tabulator Tree 체크박스 관련 함수 추가(3레벨 메뉴까지 있는 Tree를 기준으로 하였음. 상황에 맞게 수정)


//Tree 체크박스 체크시 하위 노드 체크기능

function checkedTreeNode(vSheet, cell, vCheckValue){

    var rows = vSheet.getRows();

    

    var row = cell.getRow();

    var sSeq = row.getData()["sSeq"];

    

    var isChecked = false;

    var isCheckedLvl = -1;

    var isPass = false;


    if(rows != null && rows.length > 0){

        //1레벨 확인

        for(var i = 0 ; i < rows.length ; i++){

            var lvl1Row = rows[i];

            var lvl1Children = rows[i].getTreeChildren();

            

            if(lvl1Row.getData()["sSeq"] == sSeq && !isPass){

                isChecked = true;

                isCheckedLvl = lvl1Row.getData()["menuLvl"];

                if(lvl1Row.getCell("mappingGubun")){

                    cellEditedCallback(lvl1Row.getCell("mappingGubun"), "U", vCheckValue);

                }

            }

            if(lvl1Children != undefined){

                //2레벨 확인

                for(var j = 0 ; j < lvl1Children.length ; j++){

                    var lvl2Row = lvl1Children[j];

                    var lvl2Children = lvl2Row.getTreeChildren();

                    

                    if((lvl2Row.getData()["sSeq"] == sSeq || (isChecked && isCheckedLvl != lvl2Row.getData()["menuLvl"])) && !isPass){

                        isChecked = true;

                        isCheckedLvl = isCheckedLvl == -1 ? lvl2Row.getData()["menuLvl"] : isCheckedLvl;

                        if(lvl2Row.getCell("mappingGubun")){

                            cellEditedCallback(lvl2Row.getCell("mappingGubun"), "U", vCheckValue);

                        }

                    }

                    if(lvl2Children != undefined){

                        //3레벨 확인

                        for(var k = 0 ; k < lvl2Children.length ; k++){

                            var lvl3Row = lvl2Children[k];

                            

                            if((lvl3Row.getData()["sSeq"] == sSeq || (isChecked && isCheckedLvl != lvl3Row.getData()["menuLvl"])) && !isPass){

                                isChecked = true;

                                isCheckedLvl = isCheckedLvl == -1 ? lvl3Row.getData()["menuLvl"] : isCheckedLvl;

                                if(lvl3Row.getCell("mappingGubun")){

                                    cellEditedCallback(lvl3Row.getCell("mappingGubun"), "U", vCheckValue);

                                }

                            }

                            if(isChecked && isCheckedLvl == lvl3Row.getData()["menuLvl"]) isPass = true;

                        }

                    }

                    if(isChecked && isCheckedLvl == lvl2Row.getData()["menuLvl"]) isPass = true;

                }

            }

            if(isChecked && isCheckedLvl == lvl1Row.getData()["menuLvl"]) isPass = true;

        }

    }

}


//Tree 전체 체크박스 체크시 하위 노드 체크기능

function checkedAllTreeNode(vSheet, vCheckValue){

    var treeData = vSheet.getData();

    

    if(treeData != null && treeData.length > 0){

        for(var i = 0 ; i < treeData.length ; i++){

            var menuLvl1Map = treeData[i];

            menuLvl1Map.mappingGubun = vCheckValue;

            menuLvl1Map.sStatus = "U";

            

            //1레벨 하위항목

            if(menuLvl1Map._children != undefined) {

                for(var j = 0 ; j < menuLvl1Map._children.length ; j++){

                    var menuLvl2Map = menuLvl1Map._children[j];

                    menuLvl2Map.mappingGubun = vCheckValue;

                    menuLvl2Map.sStatus = "U";

                    

                    //2레벨 하위항목

                    if(menuLvl2Map._children != undefined) {

                        for(var k = 0 ; k < menuLvl2Map._children.length ; k++){

                            var menuLvl3Map = menuLvl2Map._children[k];

                            menuLvl3Map.mappingGubun = vCheckValue;

                            menuLvl3Map.sStatus = "U";

                        }

                    }

                }

            }

        }    

    }

    vSheet.setData(treeData);

}



반응형

<style type="text/css">

// 미디어쿼리를 이용한 가로모드, 세로모드일때의 css 적용 방법

@media all and (orientation:portrait) {

// 세로모드일때의 css 적용

}

@media all and (orientation:landscape) {

// 가로모드일때의 css 적용

}

</style>


<script type="text/javascript">

$(document).ready(function() {

// matchMedia를 이용한 가로모드, 세로모드일때의 script 적용 방법

var media = window.matchMedia("(orientation: portrait)");

if (media.matches) {

// 세로모드일때의 script 적용

}

else{

// 가로모드일때의 script 적용

}

});

</script>


cf. 같은 내용으로 window.innerWidth와 window.innerHeight의 크기를 비교하여 가로모드인지 세로모드인지 판별할 수 있다.

반응형

무료 아이콘 사이트 / 유료도 있음


https://fontawesome.com/

반응형

여러곳의 원격데스크탑을 연결해야할때 보다 직관적이고 편함



https://mremoteng.org/download

반응형

'개발 > 참고사이트' 카테고리의 다른 글

부트스트랩 무료 템플릿 사이트  (1) 2020.08.11
무료 아이콘 사이트  (0) 2020.07.10
PPT 무료템플릿 모아놓은 사이트  (2) 2019.06.05
Mybatis 매퍼 설정관련  (0) 2019.02.07
jquery ztree  (0) 2018.11.02

* Maven dependency 추가


<dependency>

<groupId>org.java-websocket</groupId>

<artifactId>Java-WebSocket</artifactId>

<version>1.5.1</version>

</dependency>


1. TestEndpointServer.java (Websocket Server)


import javax.websocket.OnClose;

import javax.websocket.OnError;

import javax.websocket.OnMessage;

import javax.websocket.OnOpen;

import javax.websocket.server.ServerEndpoint;


/**

 * Websocket Test Server

 */

@ServerEndpoint("/websocket")

public class TestEndpointServer {

/**

* 웹 소켓이 연결되었을 때 호출(또는 URL 접근시 호출)

*/

@OnOpen

public void connectionOpen() {

System.out.println("################# client is connected!");

}


/**

* 웹 소켓에서 메시지가 날라왔을 때 호출

* cf) 메세지를 받기만 할 경우 return 값을 void로 설정

*/

@OnMessage

public String receiveMessage(String message) {

System.out.println("################# Message from the client : " + message);

String sendMessage = "return message " + message + " -> Lucky Number : " + Math.floor(Math.random() * 100);

System.out.println("################# Echo from the server : " + sendMessage);

return sendMessage;

}


/**

* 웹 소켓이 닫혔을 때 호출(또는 브라우저가 닫혔을 때 호출)

*/

@OnClose

public void connectionClose() {

System.out.println("################# client is disconnected!");

}


/**

* 웹 소켓이 에러가 났을 때 호출

* @param t

*/

@OnError

public void connectionError(Throwable t) {

t.printStackTrace();

}

}


2-1. TestEndpointClient.java (Websocket Client : java 테스트용 1. 서버를 띄운뒤 2-1, 2-2 같이 작성해서 돌려야됨)


import java.io.IOException;

import java.net.URI;


import javax.websocket.ClientEndpoint;

import javax.websocket.ContainerProvider;

import javax.websocket.OnOpen;

import javax.websocket.Session;

import javax.websocket.WebSocketContainer;


/**

 * Websocket Test Client

 */

@ClientEndpoint

public class TestEndpointClient {

public String SocketIp = "127.0.0.1";

public String SocketPort = "7200";

public String SocketPath = "/websocket";


Session userSession = null;


/**

* Websocket 연결

*/

public TestEndpointClient() {

try {

WebSocketContainer container = ContainerProvider.getWebSocketContainer();

container.connectToServer(this, new URI("ws://" + SocketIp + ":" + SocketPort + SocketPath));

} catch (Exception e) {

throw new RuntimeException(e);

}

}


/**

* 웹 소켓이 연결되었을 때 호출

*/

@OnOpen

public void onOpen(Session userSession) {

System.out.println("################# open Websocket");

this.userSession = userSession;

}


/**

* 웹 소켓 닫기

* @OnClose을 사용하였으나 연결이 끈기지 않어(왜?) 직접 연결끈기...ㅜ.ㅡ

*/

public void onClose() {

System.out.println("################# close Websocket");

try {

if(this.userSession != null) {

this.userSession.close();

}

} catch (IOException e) {

e.printStackTrace();

}

finally {

this.userSession = null;

}

}


/**

* 웹 소켓에 메시지 보내기

*/

public void sendMessage(String message) {

System.out.println("################# sendMessage : " + message);

this.userSession.getAsyncRemote().sendText(message);

}

}


2-2. TestEndpointJavaRun.java


public class TestEndpointJavaRun {


public static void main(String[] args) {

try {

// open websocket

TestEndpointClient clientEndPoint = new TestEndpointClient();

// send message

clientEndPoint.sendMessage("메세지를 첫번째로 보냅니다......");

clientEndPoint.sendMessage("메세지를 두번째로 보냅니다......");

clientEndPoint.sendMessage("메세지를 세번째로 보냅니다......");


// close websocket

clientEndPoint.onClose();


} catch (Exception e) {

e.getStackTrace();

}

}

}


3. TestEndpointJspRun.jsp (Websocket Client : jsp 테스트용 1. 서버를 띄운뒤 3. jsp에 접근해서 테스트)


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<title>Websocket Test</title>

</head>

<body>

<form>

<input id="message" type="text">

<input onclick="wsSendMessage();" value="Echo" type="button">

<input onclick="wsCloseConnection();" value="Disconnect" type="button">

</form>

<br>

<textarea id="echoText" rows="30" cols="100"></textarea>

<script type="text/javascript">

var webSocket = new WebSocket("ws://127.0.0.1:7200/websocket");

var echoText = document.getElementById("echoText");

echoText.value = "";

var message = document.getElementById("message");

webSocket.onopen = function(message){ wsOpen(message);};

webSocket.onmessage = function(message){ wsGetMessage(message);};

webSocket.onclose = function(message){ wsClose(message);};

webSocket.onerror = function(message){ wsError(message);};

function wsOpen(message){

echoText.value += "Connected ... \n";

}

function wsSendMessage(){

webSocket.send(message.value);

echoText.value += "Message sent to the server : " + message.value + "\n";

message.value = "";

}

function wsCloseConnection(){

webSocket.close();

}

function wsGetMessage(message){

echoText.value += "Message received from to the server : " + message.data + "\n";

}

function wsClose(message){

echoText.value += "Disconnect ... \n";

console.log("disconnect", message);

}


function wsError(message){

echoText.value += "Error \n";

console.log("error", message);

}

</script>

</body>

</html>






반응형

1. Tabulator Grid 객체 생성


cfgItemSheet = new Tabulator("#sheet-containerItem", {

    height:"750px", // virtualDom 사용위해 필수

        layout:"fitColumns",

    headerSort:false,

        selectable: 1,

        dataTree:true,

        dataTreeStartExpanded:true,

        rowClick:function(e, row){

        //selected Row 없어지는 것 방지

        var selectedData = cfgItemSheet.getSelectedData();

        if(selectedData == "") row.toggleSelect();

        },

        ajaxConfig: "POST",

        ajaxContentType:"json",

        ajaxResponse:function(url, params, response) {

    if (response.Message === "OK") {

$('#message').css("color", "#FFFFFF");

$('#message').html("* 조회 완료 : 총 " + response.Data.length + "건");

        return bindListToTree(response.Data);

} else {

$('#message').css("color", "#FF3A00");

$('#message').html("* " + response.Message);

return [];

}

        },

        columns:[

            {

            title:"항목관리",

            columns:[

            {

                    title:"번호",

                    field:"sSeq",

                    width:80,

                    minWidth:60,

                    hozAlign:"left"

            },

            {

                title:"상태",

                field:"sStatus",

                width:80,

                minWidth:60,

                hozAlign:"center",

                download:false,

                formatter: "lookup",

                formatterParams: {

                "D":"삭제", "I":"입력", "U":"수정", undefined:""

                }

            },

            {

            title: "항목명",

                    field: "itemNm",

                    hozAlign:"center",

editor:"input",

            cellEdited:function(cell) {

            var rowData = cell.getRow().getData();

            if (rowData.sStatus != "I")

            cellEditedCallback(cell, "U", 0);

            },

                    validator : ["maxLength:100"]

            },

            {

            title: "항목ID",

                    field: "itemId",

                    download: true,

                    hozAlign:"center",

                    visible : false

            },

            {

            title: "상위항목ID",

                    field: "itemTop",

                    hozAlign:"center",

                    download: true,

                    visible : false

            },

            {

            title: "레벨",

                    field: "itemLvl",

                    hozAlign:"center",

                    download: true,

                    visible : false

            },

            {

            title: "정렬순서",

                    field: "sortOrder",

                    hozAlign:"center",

editor:"input",

            cellEdited:function(cell) {

            var rowData = cell.getRow().getData();

            if (rowData.sStatus != "I")

            cellEditedCallback(cell, "U", 0);

            },

                    validator : ["integer", "maxLength:10"]

            },

        {

        title: "사용여부",

                field: "useYn",

                hozAlign:"center",

                editor:"select",

        formatter: "lookup",

        formatterParams: {"Y":"사용", "N":"미사용"},

        editorParams:{

        values:{"Y":"사용", "N":"미사용"}

        },

                    cellEdited:function(cell) {

                    var rowData = cell.getRow().getData();

                    if (rowData.sStatus != "I")

                    cellEditedCallback(cell, "U", 0);

                    }

        }

            ]

            }

        ]

    });


2. 노드 추가 관련 스크립트


//최상위 항목 등록

function addActionHandlerUp(ev) {

var newSSeq = searchTreeDataLength(cfgItemSheet) + 1;

cfgItemSheet.addRow({ "sStatus":"I", "sDelCheck":0, "sSeq":newSSeq, "itemLvl":"0", "itemId":"", "itemTop":vGrpId, "useYn":"Y"}, true);

//selected Row 체크

var rows = cfgItemSheet.getRows();

rows[0].toggleSelect();

}


//하위 항목 등록

function addActionHandlerDown(ev) {

var sheetData = cfgItemSheet.getData();

var selectedData = cfgItemSheet.getSelectedData()[0];


if(selectedData.sStatus == "I"){

$('#message').html("* 상위레벨을 먼저 저장해야 합니다.");

}

else if(parseInt(selectedData.itemLvl, 10) >= 2){

$('#message').html("* 3레벨까지만 생성이 가능합니다.");

}

else{

//Tree Data Row 추가

sheetData = addSelectedTreeDataRow(cfgItemSheet);


//Tree Data 세팅 및 세팅 후 selected Row 처리

cfgItemSheet.setData(sheetData).then(function(){

if(cfgItemSheet.getDataCount() > 0){

//신규 생성 Tree Data Row Selected

selectedTreeNewRow(cfgItemSheet);

}

});

}

}


3. 저장시 관련 스크립트


function saveActionHandler(ev) {

ev.preventDefault();


// 입력/수정/삭제 할 행

let rows = searchTreeData(cfgItemSheet, "sStatus", ["D", "I", "U"]);


//변경된 Row의 데이터를 JSON 형태로 받음.

//var jsonString = cfgItemSheet.GetSaveJson();

if(rows.length < 1) {

$('#message').html("* 저장할 데이터가 없습니다!");

return;

}

// 신호장치명, 장치코드, 정렬순서 공백 체크

let itemNmRows = searchTreeData(cfgItemSheet, "itemNm", [undefined, ""]);

if (itemNmRows.length > 0) {

alert("항목명을 확인해주십시오!");

return;

}

let sortOrderRows = searchTreeData(cfgItemSheet, "sortOrder", [undefined, ""]);

if (sortOrderRows.length > 0) {

alert("정렬순서를 확인해주십시오!");

return;

}

if(confirm("변경하신 항목관리 정보를 저장하시겠습니까?")) {

let obj = {

schGrpId : vGrpId,

data: rows

};


cfgItemSheet.setData("/cfgItemAction.do", obj, "POST").then(function(){

if(cfgItemSheet.getDataCount() > 0){

var rows = cfgItemSheet.getRows();

rows[0].toggleSelect();

}

});

}

}


4. Tree 관련 스크립트


//list데이터 구조를 Tree데이터 구조로 변환하여 리턴

function bindListToTree(listData){

var treeData = new Array();

var itemLvl1Cnt = 0;

var itemLvl2Cnt = 0;

if(listData != null && listData.length > 0){

for(var i = 0 ; i < listData.length ; i++){

var map = listData[i];

//1레벨 세팅

if(map.itemLvl == 0) {

treeData[itemLvl1Cnt++] = map;

itemLvl2Cnt = 0;

}

//2레벨 세팅

else if(map.itemLvl == 1) {

var lvl1Map = treeData[itemLvl1Cnt - 1];

var lvl1SubList = lvl1Map._children;

if(lvl1SubList == undefined) {

lvl1SubList = new Array();

}

lvl1SubList[lvl1SubList.length] = map;

lvl1Map._children = lvl1SubList;

treeData[itemLvl1Cnt - 1] =  lvl1Map;

itemLvl2Cnt++;

}

//3레벨 세팅

else if(map.itemLvl == 2) {

var lvl1Map = treeData[itemLvl1Cnt - 1];

var lvl1SubList = lvl1Map._children;

var lvl2Map = lvl1SubList[itemLvl2Cnt - 1];

var lvl2SubList = lvl2Map._children;

if(lvl2SubList == undefined) {

lvl2SubList = new Array();

}

lvl2SubList[lvl2SubList.length] = map;

lvl2Map._children = lvl2SubList;

lvl1SubList[itemLvl2Cnt - 1] = lvl2Map;

lvl1Map._children = lvl1SubList;

treeData[itemLvl1Cnt - 1] = lvl1Map;

}

}

}

return treeData;

}


//Tree데이터 구조를 list데이터 구조로 변환하여 리턴

function bindTreeToList(treeData){

var listData = new Array();

var listCnt = 0;

if(treeData != null && treeData.length > 0){

for(var i = 0 ; i < treeData.length ; i++){

var lvl1Map = treeData[i];

listData[listCnt++] = lvl1Map;

//1레벨 하위항목

if(lvl1Map._children != undefined) {

for(var j = 0 ; j < lvl1Map._children.length ; j++){

var lvl2Map = lvl1Map._children[j];

listData[listCnt++] = lvl2Map;

//2레벨 하위항목

if(lvl2Map._children != undefined) {

for(var k = 0 ; k < lvl2Map._children.length ; k++){

var lvl3Map = lvl2Map._children[k];

listData[listCnt++] = lvl3Map;

}

}

}

}

}

}

return listData;

}


//Tree데이터에서 조건에 맞는 데이터를 찾아 list데이터 구조로 변환하여 리턴

function searchTreeData(vSheet, vField, vParamArr){

var treeData = vSheet.getData();

var listData = bindTreeToList(treeData);

var searchData = new Array();

var searchCnt = 0;

if(listData != null && listData.length > 0){

for(var i = 0 ; i < listData.length ; i++){

var map = listData[i];

for(var j = 0 ; j < vParamArr.length ; j++){

if(map[vField] == vParamArr[j]){

searchData[searchCnt++] = map;

}

}

}

}

return searchData;

}


//Tree데이터의 총 length를 리턴

function searchTreeDataLength(vSheet){

var treeData = vSheet.getData();

var listData = bindTreeToList(treeData);

return listData.length;

}


//선택된 Tree Data Row 추가

function addSelectedTreeDataRow(vSheet){

var sheetData = vSheet.getData();

var selectedData = vSheet.getSelectedData()[0];

var itemLvl = parseInt(selectedData.itemLvl, 10) + 1;

var itemTop = selectedData.itemTop;

//Tree Data Row 추가

for(var i = 0 ; i < sheetData.length ; i++){

var lvl1Map = sheetData[i];

var newSSeq = searchTreeDataLength(vSheet) + 1;

//1레벨 항목 확인

if(lvl1Map.itemId == selectedData.itemId){

var newItemTop = "";

var newItemLvl = 0;

if(lvl1Map._children != undefined){

newItemTop = lvl1Map.itemId;

newItemLvl = parseInt(lvl1Map.itemLvl, 10) + 1;

}

else{

lvl1Map._children = new Array();

newItemTop = lvl1Map.itemId;

newItemLvl = parseInt(lvl1Map.itemLvl, 10) + 1;

}

lvl1Map._children[lvl1Map._children.length] = {"sStatus":"I", "sDelCheck":0, "sSeq":newSSeq, "itemLvl":newItemLvl, "itemId":"", "itemTop":newItemTop, "useYn":"Y"};

}

else if(lvl1Map._children != undefined) {

for(var j = 0 ; j < lvl1Map._children.length ; j++){

var lvl2Map = lvl1Map._children[j];

//2레벨 항목 확인

if(lvl2Map.itemId == selectedData.itemId){

var newItemTop = "";

var newItemLvl = 0;

if(lvl2Map._children != undefined){

newItemTop = lvl2Map.itemId;

newItemLvl = parseInt(lvl2Map.itemLvl, 10) + 1;

}

else{

lvl2Map._children = new Array();

newItemTop = lvl2Map.itemId;

newItemLvl = parseInt(lvl2Map.itemLvl, 10) + 1;

}

lvl2Map._children[lvl2Map._children.length] = {"sStatus":"I", "sDelCheck":0, "sSeq":newSSeq, "itemLvl":newItemLvl, "itemId":"", "itemTop":newItemTop, "useYn":"Y"};

}

}

}

}

return sheetData;

}


//신규 생성 Tree Data Row Selected

function selectedTreeNewRow(vSheet){

var treeDataLength = searchTreeDataLength(vSheet);

var rows = vSheet.getRows();

for(var i = 0 ; i < rows.length ; i++){

var row1 = rows[i];

//1레벨 selected

if(parseInt(row1.getData().sSeq, 10) == treeDataLength){

row1.select();

}

else if(row1.getTreeChildren().length != undefined){

for(var j = 0 ; j < row1.getTreeChildren().length ; j++){

var row2 = row1.getTreeChildren()[j];

//2레벨 selected

if(parseInt(row2.getData().sSeq, 10) == treeDataLength){

row2.select();

}

else if(row2.getTreeChildren().length != undefined){

for(var k = 0 ; k < row2.getTreeChildren().length ; k++){

var row3 = row2.getTreeChildren()[k];

//3레벨 selected

if(parseInt(row3.getData().sSeq, 10) == treeDataLength){

row3.select();

}

}

}

}

}

}

}



반응형

1. context-common.xml (bean 추가)


<!-- MultipartResolver 설정 -->

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<property name="maxUploadSize" value="100000000" />

<property name="maxInMemorySize" value="100000000" />

</bean>


2. ExcelUtil.java (공통 엑셀 유틸 추가)


package egovframework.cmn.cmn;


import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;


import org.apache.poi.hssf.usermodel.HSSFDateUtil;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import org.apache.poi.ss.usermodel.Cell;

import org.apache.poi.ss.usermodel.Row;

import org.apache.poi.ss.usermodel.Sheet;

import org.apache.poi.ss.usermodel.Workbook;

import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import org.springframework.web.multipart.commons.CommonsMultipartFile;


public class ExcelUtil {

/**

* 엑셀 파일 읽기

* @param file

* @param sheetNum

* @param strartRowNum

* @param startCelNum

* @return List<HashMap<Integer, String>>

* @throws Exception

*/

public List<HashMap<Integer, String>> excelReadSetValue(CommonsMultipartFile file, int sheetNum, int strartRowNum, int startCelNum) throws Exception {

List<HashMap<Integer, String>> resultList = new ArrayList<>();

SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

//xls, xlsx 구분

Workbook workbook = null;

if(file.getOriginalFilename().toUpperCase().endsWith("XLSX")) {

workbook = new XSSFWorkbook(file.getInputStream());

}

else {

workbook = new HSSFWorkbook(file.getInputStream());

}

//Sheet 수 확인

int sheetCnt = workbook.getNumberOfSheets();

int listNum = 0;


try {

if (sheetCnt > 0) {

//첫번째 Sheet 선택

Sheet sheet = workbook.getSheetAt(sheetNum);

//Sheet의 Row와 Cell 수 확인

int rows = sheet.getPhysicalNumberOfRows();

int cells = sheet.getRow(0).getPhysicalNumberOfCells();

HashMap<Integer, String> valueMap = null;

//Header Row 빼고 시작(0에서 시작)

for(int r = strartRowNum ; r < rows; r++) {

//String device_id = "";

valueMap = new HashMap<Integer, String>();

//한 줄씩 읽고 데이터 저장

Row row = sheet.getRow(r);

if (row != null) {

//Cell 기본값 빼고 시작(0에서 시작)

for(int c = startCelNum ; c < cells ; c++) {

Cell cell = row.getCell(c);

if (cell != null) {

String value = "";

switch(cell.getCellType()) {

case Cell.CELL_TYPE_BLANK :

value = "";

break;

case Cell.CELL_TYPE_BOOLEAN :

value = "" + cell.getBooleanCellValue();

break;

case Cell.CELL_TYPE_ERROR :

value = "" + cell.getErrorCellValue();

break;

case Cell.CELL_TYPE_FORMULA :

value = cell.getCellFormula();

break;

case Cell.CELL_TYPE_NUMERIC :

if(HSSFDateUtil.isInternalDateFormat(cell.getCellStyle().getDataFormat())) {

value = sdf.format(cell.getDateCellValue());

}

else {

cell.setCellType(Cell.CELL_TYPE_STRING ); 

value = cell.getStringCellValue(); 

}

break;

case Cell.CELL_TYPE_STRING :

value = cell.getStringCellValue();

break;

}

//공백과 트림 제거

value = value.trim().replaceAll(" ", "");

valueMap.put(c, value);

}

}//end col for

resultList.add(listNum++, valueMap);

}//end if

}//end row for

}

} catch(Exception e) {

e.getStackTrace();

}

return resultList;

}

}



3. XxxController.java


/**

* 엑셀 업로드 처리

* @param multiRequest

* @param request

* @return

* @throws Exception

*/

@RequestMapping("cfgUploadAction.do")

public String cfgUploadAction(HttpServletRequest request, RedirectAttributes redirectAttributes) throws Exception {

try {

cfgService.excelUpload(request);


redirectAttributes.addFlashAttribute("Code", 0);

redirectAttributes.addFlashAttribute("Message", egovMessageSource.getMessage("proc.success"));

} catch (Exception ex) {

redirectAttributes.addFlashAttribute("Code", 1);

redirectAttributes.addFlashAttribute("Message", "오류가 발생하였습니다. 엑셀양식을 확인해 주세요.");

}

return "redirect:/mng/fac/cfg/cfgUploadPop.do";

}


4. XxxServiceImpl.java


/**

* 엑셀 업로드 처리

* @param multiRequest

* @return String

* @throws Exception

*/

@SuppressWarnings("unchecked")

public void excelUpload(HttpServletRequest request) throws Exception{

MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request;

//파일 정보

CommonsMultipartFile file = (CommonsMultipartFile)multiRequest.getFile("excelFile");

//엑셀정보

ExcelUtil eu = new ExcelUtil();

int sheetNum = 0; //1번째 시트 읽음 

int strartRowNum = 1; //2번째 줄부터 읽음

int startCelNum = 2; //3번째 줄부터 읽음(지역ID)

List<HashMap<Integer, String>> excelList = eu.excelReadSetValue(file, sheetNum, strartRowNum, startCelNum);

//테이블 Key 정보

DeviceBaseVO deviceBaseVO = null;


//엑셀 Row 수 만큼 For문 조회 

for(Object obj : excelList) {

Map<Integer, String> mp = (Map<Integer, String>)obj;

Set<Integer> keySet = mp.keySet();

Iterator<Integer> iterator = keySet.iterator();

deviceBaseVO = new DeviceBaseVO();

while(iterator.hasNext()) {

int key = iterator.next();

String value = StringUtil.nullConvert(mp.get(key));

switch(key) {

case 2 :

deviceBaseVO.setAreaId(value);

break;

case 4 :

deviceBaseVO.setFacilityId(value);

break;

case 5 :

deviceBaseVO.setDeviceNm(value);

break;

case 6 :

deviceBaseVO.setDeviceId(value);

break;

case 7 :

deviceBaseVO.setInstDt(value);

break;

case 8 :

deviceBaseVO.setUseYn(value);

break;

}

}

if(!"".equals(deviceBaseVO.getAreaId()) && deviceBaseVO.getAreaId() != null) {

cfgMapper.updateCfgInfo(deviceBaseVO);

}

}

}


5. Xxx.jsp


<form name="popForm" method="post" action="${actionUrl}" enctype="multipart/form-data">

<table>

<caption>엑셀 업로드</caption>

<colgroup>

<col><col>

</colgroup>


<tbody>

<tr>

<th><label for="code2">파일찾기</label></th>

<td><input name="excelFile" id="excelFile" type="file" size="30"></td>

</tr>

</table>


<!-- 버튼 영역 -->

<div class="btn-area">

<a href="#" onclick="doSubmit();" class="btn btn-yellow btn-ok">업로드</a>

<a href="javascript:self.close();" class="btn btn-yellow btn-cancel">창닫기</a>

</div>

</form>


반응형

1. context-common.xml (bean 추가)


<bean id="excelView" class="egovframework.cmn.cmn.ExcelView" />


2. ExcelView.java (공통 엑셀다운로드)


package egovframework.cmn.cmn;


import java.net.URLEncoder;

import java.util.List;

import java.util.Map;


import javax.servlet.ServletOutputStream;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import org.apache.poi.hssf.usermodel.HSSFCellStyle;

import org.apache.poi.hssf.usermodel.HSSFFont;

import org.apache.poi.hssf.util.HSSFColor;

import org.apache.poi.ss.usermodel.CellStyle;

import org.apache.poi.ss.usermodel.Font;

import org.apache.poi.ss.util.CellRangeAddress;

import org.apache.poi.xssf.usermodel.XSSFCell;

import org.apache.poi.xssf.usermodel.XSSFRow;

import org.apache.poi.xssf.usermodel.XSSFSheet;

import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import org.springframework.web.servlet.view.AbstractView;


import egovframework.rte.psl.dataaccess.util.EgovMap;


public class ExcelView extends AbstractView {

    /** The content type for an Excel response */

     private static final String CONTENT_TYPE_XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";


    /**

     * Default Constructor. Sets the content type of the view for excel files.

     */

    public ExcelView() {

    }


    @Override

    protected boolean generatesDownloadContent() {

        return true;

    }


    /**

     * Renders the Excel view, given the specified model.

     */

    @Override

    protected final void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {


        XSSFWorkbook workbook = new XSSFWorkbook();


        setContentType(CONTENT_TYPE_XLSX);


        buildExcelDocument(model, workbook, request, response);

        

        // Set the filename

        String sFilename = "";

        if(model.get("filename") != null){

            sFilename = (String)model.get("filename");

        }else if(request.getAttribute("filename") != null){

            sFilename = (String)request.getAttribute("filename");

        }else{

            sFilename = getClass().getSimpleName();

         }


        response.setContentType(getContentType());

        

        String header = request.getHeader("User-Agent");

        sFilename = sFilename.replaceAll("\r","").replaceAll("\n","");

        if(header.contains("MSIE") || header.contains("Trident") || header.contains("Chrome")){

            sFilename = URLEncoder.encode(sFilename,"UTF-8").replaceAll("\\+","%20");

            response.setHeader("Content-Disposition","attachment;filename="+sFilename+".xlsx;");

        }else{

            sFilename = new String(sFilename.getBytes("UTF-8"),"ISO-8859-1");

            response.setHeader("Content-Disposition","attachment;filename=\""+sFilename + ".xlsx\"");

        }

        

        // Flush byte array to servlet output stream.

        ServletOutputStream out = response.getOutputStream();

        out.flush();

        workbook.write(out);

        out.flush();


        // Don't close the stream - we didn't open it, so let the container handle it.

        // http://stackoverflow.com/questions/1829784/should-i-close-the-servlet-outputstream

    }

    

    @SuppressWarnings("unchecked")

    protected void buildExcelDocument(Map<String, Object> model, XSSFWorkbook wb, HttpServletRequest req, HttpServletResponse resp) throws Exception {

    List<Map<String, Object>> dataMapList = (List<Map<String, Object>>) model.get("dataMapList");

   

    for(Map<String, Object> dataMap : dataMapList) {

            XSSFCell cell = null;

     

            String sheetNm = (String) dataMap.get("sheetNm"); // 엑셀 시트 이름

            

            String[] titleArr = (String[]) dataMap.get("titleArr"); // 각 컬럼 이름

            String[] fieldArr = (String[]) dataMap.get("fieldArr"); // 각 컬럼의 변수 이름

            

            List<EgovMap> dataList = (List<EgovMap>) dataMap.get("list"); // 데이터가 담긴 리스트 

            

            CellStyle cellStyle = wb.createCellStyle(); // 제목셀의 셀스타일

            cellStyle.setWrapText(true); // 줄 바꿈            

            cellStyle.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index); // 셀 색상

            cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); // 셀 색상 패턴

            cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 셀 가로 정렬

            cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // 셀 세로 정렬

            cellStyle.setDataFormat((short)0x31); // 셀 데이터 형식

            cellStyle.setBorderRight(HSSFCellStyle.BORDER_DOUBLE);

            cellStyle.setBorderLeft(HSSFCellStyle.BORDER_DOUBLE);

            cellStyle.setBorderTop(HSSFCellStyle.BORDER_DOUBLE);

            cellStyle.setBorderBottom(HSSFCellStyle.BORDER_DOUBLE);

            

            // 셀 폰트색상, bold처리

            Font font = wb.createFont();

            font.setColor(HSSFColor.WHITE.index);

            font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);

            cellStyle.setFont(font);

            

            CellStyle cellStyle2 = wb.createCellStyle(); // 데이터셀의 셀스타일

            cellStyle2.setWrapText(true); // 줄 바꿈           

            cellStyle2.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 셀 가로 정렬

            cellStyle2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // 셀 세로 정렬

            cellStyle2.setDataFormat((short)0x31); // 셀 데이터 형식

            cellStyle2.setBorderRight(HSSFCellStyle.BORDER_THIN);

            cellStyle2.setBorderLeft(HSSFCellStyle.BORDER_THIN);

            cellStyle2.setBorderTop(HSSFCellStyle.BORDER_THIN);

            cellStyle2.setBorderBottom(HSSFCellStyle.BORDER_THIN);

            

            XSSFSheet sheet = wb.createSheet(sheetNm);

            sheet.setDefaultColumnWidth(12);

            

            // 컬럼명 삽입

            for(int i=0; i<titleArr.length; i++){

                setText(getCell(sheet, 0, i), titleArr[i]);

                getCell(sheet, 0, i).setCellStyle(cellStyle);

                sheet.autoSizeColumn(i);

                int columnWidth = (sheet.getColumnWidth(i))*5;

                sheet.setColumnWidth(i, columnWidth);

                

                if(dataList.size() < 1){

                    cell = getCell(sheet, 1, i);

                    if(i==0){

                        setText(cell, "등록된 정보가 없습니다.");

                    }

                    cell.setCellStyle(cellStyle2);

                }

            }

            

            if(dataList.size() > 0){ // 저장된 데이터가 있을때

                // 리스트 데이터 삽입

                for (int i = 0; i<dataList.size(); i++) {

                    EgovMap dataEgovMap = dataList.get(i);

                    

                    // 맨 앞 컬럼인 "번호"는 idx라는 이름으로 여기서 생성하여 넣어준다.

                    dataEgovMap.put("idx", (i+1)+""); 


                    for(int j=0; j<fieldArr.length; j++){

                        String data = String.valueOf(dataEgovMap.get(fieldArr[j]));

                        cell = getCell(sheet, 1 + i, j);

                        setText(cell, data);

                        cell.setCellStyle(cellStyle2);

                    }

                }

            }else{ // 저장된 데이터가 없으면 셀 병합

                // 셀 병합(시작열, 종료열, 시작행, 종료행)

                sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, titleArr.length-1));

            }

    }

    }


    /**

     * Convenient method to obtain the cell in the given sheet, row and column.

     * 

     * <p>Creates the row and the cell if they still doesn't already exist.

     * Thus, the column can be passed as an int, the method making the needed downcasts.</p>

     * 

     * @param sheet a sheet object. The first sheet is usually obtained by workbook.getSheetAt(0)

     * @param row thr row number

     * @param col the column number

     * @return the XSSFCell

     */

    protected XSSFCell getCell(XSSFSheet sheet, int row, int col) {

        XSSFRow sheetRow = sheet.getRow(row);

        if (sheetRow == null) {

            sheetRow = sheet.createRow(row);

        }

        XSSFCell cell = sheetRow.getCell((short) col);

        if (cell == null) {

            cell = sheetRow.createCell((short) col);

        }

        return cell;

    }


    /**

     * Convenient method to set a String as text content in a cell.

     * 

     * @param cell the cell in which the text must be put

     * @param text the text to put in the cell

     */

    protected void setText(XSSFCell cell, String text) {

        cell.setCellType(XSSFCell.CELL_TYPE_STRING);

        cell.setCellValue(text);

    }            

}


3. SearchVO.java (VO 변수 추가)


private String schFileNm = ""; /** 엑셀다운로드 파일명 */

private String[] schSheetNmArr = null; /** 엑셀다운로드 시트명 배열 */

private String[][] schTitleArrArr = null; /** 엑셀다운로드 Title 배열 */

private String[][] schFieldArrArr = null; /** 엑셀다운로드 Field 배열 */


4. XxxController.java (Controller 엑셀다운로드 함수 추가)


@RequestMapping("disorderAllList.do")

public ModelAndView selectDisorderAllList(@ModelAttribute("searchVO") SearchVO searchVO, HttpServletRequest request, HttpServletResponse response, BindingResult bindingResult) throws Exception {

//코드관리 목록 조회

List<?> list = cfgService.selectDisorderList(searchVO);

//코드1관리 목록 조회

List<?> list1 = cfgService.selectCauseList(searchVO);

//코드2관리 목록 조회

List<?> list2 = cfgService.selectActionList(searchVO);

    ModelAndView mav = new ModelAndView("excelView");

    List<Map<String, Object>> dataMapList = new ArrayList<Map<String, Object>>();

    Map<String, Object> subMap = null;

    

    for(int i = 0 ; i < searchVO.getSchSheetNmArr().length ; i++) {

    subMap = new HashMap<String, Object>();

    subMap.put("titleArr", searchVO.getSchTitleArrArr()[i]);

    subMap.put("fieldArr", searchVO.getSchFieldArrArr()[i]);

    subMap.put("sheetNm", searchVO.getSchSheetNmArr()[i]);

    if(i == 0) subMap.put("list", list);

    else if(i == 1) subMap.put("list", list1);

    else if(i == 2) subMap.put("list", list2);

   

    dataMapList.add(i, subMap);

    }

    mav.addObject("dataMapList", dataMapList);

    mav.addObject("filename", searchVO.getSchFileNm());

    

    return mav;

}


5. common.js (공통 Tabulator 엑셀 다운로드 함수 추가)


//Tabulator 엑셀 다운로드

function downBaseExcelTabulator(vAction, vFileNm, vSheetNmArr, vSheetArr, vParams){

//action 정보 세팅

var vForm = document.createElement("FORM");

vForm.action = vAction;

vForm.method = "POST";


//파일명 세팅

appendMakeInput(vForm, "schFileNm", vFileNm);


//시트명 세팅

for(var i = 0 ; i < vSheetNmArr.length ; i++){

appendMakeInput(vForm, "schSheetNmArr[" + i + "]", vSheetNmArr[i]);

}

//sheet 컬럼 정보 세팅

for(var j = 0 ; j < vSheetArr.length ; j++){

var vColumns = vSheetArr[j];

for(var jj = 0 ; jj < vColumns.length ; jj++){

if(vColumns[jj].download != false){

appendMakeInput(vForm, "schTitleArrArr[" + j + "]", vColumns[jj].title);

appendMakeInput(vForm, "schFieldArrArr[" + j + "]", vColumns[jj].field);

}

}

}

//params 정보 세팅

if(vParams != null && vParams != ""){

for(var k = 0 ; k < vParams.length ; k++){

appendMakeInput(vForm, vParams[k].name, vParams[k].value);

}

}

window.document.body.appendChild(vForm);

vForm.submit();

}



//Tabulator 단일 시트 엑셀 다운로드

function downOneExcelTabulator(vAction, vFileNm, vSheetNm, vSheet, vParams){

var vSheetNmArr = [vSheetNm];

var vSheetArr = [vSheet.getColumnDefinitions()];

downBaseExcelTabulator(vAction, vFileNm, vSheetNmArr, vSheetArr, vParams);

}


//Tabulator 멀티 시트 엑셀 다운로드

function downMultiExcelTabulator(vAction, vFileNm, vSheetNmArr, vSheetArr, vParams){

var reSheetArr = new Array();

for(var i = 0 ; i < vSheetArr.length ; i++){

var tempArr = new Array();

for(var j = 0 ; j < vSheetArr[i].getColumns().length ; j++){

tempArr[j] = vSheetArr[i].getColumns()[j].getDefinition();

}

reSheetArr[i] = tempArr;

}

downBaseExcelTabulator(vAction, vFileNm, vSheetNmArr, reSheetArr, vParams);

}


//input hidden 객체 만들어 붙이기

function appendMakeInput(obj, nm, val){

var vInput = document.createElement("INPUT");

vInput.name = nm;

vInput.value = val;

vInput.type = "hidden";

obj.append(vInput);

}


6. Xxx.js (각 화면 엑셀 다운로드 함수 추가)


//엑셀 다운로드

function excelDown(opt){

if(opt == "ALL"){

var vAction = "/common/disorderAllList.do";

var vFileNm = "코드관리(전체)";

var vSheetNmArr = ["코드관리", "코드1관리", "코드2관리"];

var vSheetArr = [disorderSheet, causeSheet, actionSheet];

var vParams = null;

//Tabulator 엑셀 다운로드

downMultiExcelTabulator(vAction, vFileNm, vSheetNmArr, vSheetArr, vParams);

}

else{

var sheets = {

    "코드관리": true,

    "코드1관리": causeSheet,

    "코드2관리": actionSheet

};


disorderSheet.download("xlsx", "코드관리.xlsx", {sheets:sheets});

}

}



반응형

이클립스로 프로젝트를 돌리던 중 아무것도 수정한게 없는데 아래와 같은 에러가 오류가 떴다.


org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (IO 오류: The Network Adapter could not establish the connection)


오라클 리스너가 갑자기 실행이 되지 않아 나타나는 오류라서 윈도우 서비스를 실행하여 해당 서비스를 강제 실행을 하니 아래와 같은 메세지가 발생.


OracleOraDb11g_home1TNSListener 서비스가 로컬 컴퓨터에서 시작했다가 중지되었습니다


결과적으로 오라클 설치경로(ex : C:\app\subinto\product\11.2.0\dbhome_2\NETWORK\ADMIN)에서 sqlnet.ora, tnsnames.ora 이 두파일 을 열어보면 HOST가 내 컴퓨터 이름과 같지 않아서 발생하였다.(왜 바뀐거지??? =_=?)


아무튼 컴퓨터 이름으로 맞추고서 리스너 서비스를 다시 실행하니 정상 동작하였다.

반응형

1.메이븐을 사용한다면 pom.xml에 아래 dependency를 추가하고 메이븐을 사용하지 않는다면 아래 사이트에가서 필요한 jar를 다운 받는다.

(https://mvnrepository.com/artifact/org.apache.tiles)

 

  <!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-api -->
  <dependency>
      <groupId>org.apache.tiles</groupId>
      <artifactId>tiles-api</artifactId>
      <version>3.0.8</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-autotag-core -->
  <dependency>
      <groupId>org.apache.tiles</groupId>
      <artifactId>tiles-autotag-core</artifactId>
      <version>1.2</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-autotag-core-runtime -->
  <dependency>
      <groupId>org.apache.tiles</groupId>
      <artifactId>tiles-autotag-core-runtime</artifactId>
      <version>1.2</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-core -->
  <dependency>
      <groupId>org.apache.tiles</groupId>
      <artifactId>tiles-core</artifactId>
      <version>3.0.8</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-extras -->
  <dependency>
      <groupId>org.apache.tiles</groupId>
      <artifactId>tiles-extras</artifactId>
      <version>3.0.8</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-jsp -->
  <dependency>
      <groupId>org.apache.tiles</groupId>
      <artifactId>tiles-jsp</artifactId>
      <version>3.0.8</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-request-api -->
  <dependency>
      <groupId>org.apache.tiles</groupId>
      <artifactId>tiles-request-api</artifactId>
      <version>1.0.7</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-request-jsp -->
  <dependency>
      <groupId>org.apache.tiles</groupId>
      <artifactId>tiles-request-jsp</artifactId>
      <version>1.0.7</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-request-servlet -->
  <dependency>
      <groupId>org.apache.tiles</groupId>
      <artifactId>tiles-request-servlet</artifactId>
      <version>1.0.7</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-servlet -->
  <dependency>
      <groupId>org.apache.tiles</groupId>
      <artifactId>tiles-servlet</artifactId>
      <version>3.0.8</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/org.apache.tiles/tiles-template -->
  <dependency>
      <groupId>org.apache.tiles</groupId>
      <artifactId>tiles-template</artifactId>
      <version>3.0.8</version>
  </dependency>

 

 

2. web.xml 설정(중간에 타일즈를 추가하는 것이면 이미 설정 되어있을 것이다.)

 

<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/config/egovframework/springmvc/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

 

3. dispatcher-servlet.xml 설정(프로젝트마다 파일이름이 다를 수 있다.)

   기존 설정과 중복되는 부분은 주석처리 하거나 필요한 설정이라면 order 순서를 변경한다.

   org.springframework.web.servlet.view.tiles3.SimpleSpringPreparerFactory 부분은 동적메뉴 구성을 위해 추가하였다.(5-1번 참고)

 

    <!-- Ajax jsonView Return (ModelAndView) -->
    <bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"
     p:contentType="application/json;charset=UTF-8">
    </bean>
    <bean id="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"
     p:order="2">
    </bean>

 


 <!-- Tiles 추가로 인해 주석처리
    <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" p:order="2"
     p:viewClass="org.springframework.web.servlet.view.JstlView"
     p:prefix="/WEB-INF/jsp/egovframework/" p:suffix=".jsp" />
  -->
    
    <!-- Tiles 추가 -->
    <bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver"
        p:viewClass="org.springframework.web.servlet.view.tiles3.TilesView"
        p:order="1" />
    <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
            <property name="definitions">
                  <list>
                        <value>/WEB-INF/config/egovframework/tiles/tiles.xml</value>
                  </list>
            </property>
            <property name="preparerFactoryClass" value="org.springframework.web.servlet.view.tiles3.SimpleSpringPreparerFactory"></property>
    </bean>

 

4. tiles.xml 설정(definition의 name abc/**/*Viewdef/**/*ViewController의 리턴값과 매칭되어야 해당 Tiles Layout이 적용된다.)

  cf ex1) return "abc/aa/cc/dd/wowView";  cf ex2) return "def/a/goodView";

 

<!DOCTYPE tiles-definitions PUBLIC
  "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
  "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
 
<tiles-definitions>
  
    <!-- Tiles 적용 기본 Layout -->
    <definition name="base" template="/WEB-INF/jsp/egovframework/layout/TilesLayout.jsp" preparer="egovframework.cmn.MenuPreparer">
        <put-attribute name="header" value="/WEB-INF/jsp/egovframework/layout/Header.jsp" />
        <put-attribute name="menuLvl2" value="/WEB-INF/jsp/egovframework/layout/MenuLvl2.jsp" />
        <put-attribute name="menuLvl3" value="/WEB-INF/jsp/egovframework/layout/MenuLvl3.jsp" />
    </definition>
   
    <!-- Tiles 적용 팝업 Layout -->
    <definition name="baseEmpty" template="/WEB-INF/jsp/egovframework/layout/PopLayout.jsp">
    </definition>
    
    

    
 
    <!-- 기본 관리자 화면 - 첫번째관리 Layout -->
    <definition name="abc/**/*View" extends="base">
        <put-attribute name="body" value="/WEB-INF/jsp/egovframework/abc/{1}/{2}View.jsp" />
        <put-attribute name="curPath" value="abc/{1}/{2}View" cascade="true"/>
    </definition>
 
    <!-- 기본 관리자 화면 - 두번째관리 Layout -->
    <definition name="def/**/*View" extends="base">
        <put-attribute name="body" value="/WEB-INF/jsp/egovframework/def/{1}/{2}View.jsp" />
    </definition>
 



    
    <!-- 팝업 화면 Layout -->
    <definition name="**/*Pop" extends="baseEmpty">
        <put-attribute name="body" value="/WEB-INF/jsp/egovframework/{1}/{2}Pop.jsp" />
    </definition>
   
   
   
   
   
   
    <!-- 기타 Tiles 미적용 -->
    <definition name="cmn/*" template="/WEB-INF/jsp/egovframework/cmn/{1}.jsp"></definition>

  
</tiles-definitions>

 

5-1. 동적메뉴 구성을 위한 설정(MenuPreparer.java)

 

public class MenuPreparer implements ViewPreparer {

 /** SysadmService */
 @Resource(name="sysadmService")
 private SysadmService sysadmService;

 @Override
 public void execute(Request tilesRequest, AttributeContext attributeContext) throws PreparerException {
  List<?> menuList;
  try {
   Map<String, String> map = tilesRequest.getParam();
   SearchVO searchVO = new SearchVO();
   
   //로그인한 세션정보 가져오기
   HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
   HttpSession session = request.getSession();
   LoginVO loginVO = (LoginVO)session.getAttribute("loginVO");
   
   //접근사용자구분 세팅
   searchVO.setSchUserGubun(loginVO.getUserGubun());
   
   //관리자메뉴 세팅
   menuList = sysadmService.getSelectMngMenuList(searchVO);
   attributeContext.putAttribute("menuList", new Attribute(menuList), true);
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 

 

5-2. TilesLayout.jsp 설정

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib uri="http://tiles.apache.org/tags-tiles-extras" prefix="tilesx" %>

<!DOCTYPE html>
<html lang="ko">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">

<!-- Stylesheets ============================================= -->
<link rel="stylesheet" href="/css/bootstrap.css" type="text/css" />
<link rel="stylesheet" href="/css/style.css" type="text/css" />

 

<!-- External JavaScripts ============================================= -->
<script type="text/javascript" src="/js/jquery.js"></script>


 

<tilesx:useAttribute name="curPath" />
<script type="text/javascript" src="/script/${curPath}.js"></script>

 

<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>관리자페이지</title>
</head>

<body class="stretched">

<!-- Document Wrapper ============================================= -->
<div id="wrapper" class="clearfix">
 <!-- Header ============================================= -->
 <tiles:insertAttribute name="header"/>
 <!-- #header end -->

    <!-- Content ============================================= -->
    <section id="content" class="content-grid">
        <div class="content-wrap nopadding">
   <div class="container-fluid">
    <div id="tabs" class="card">
     <!-- 2depth 메뉴 -->
     <tiles:insertAttribute name="menuLvl2" />
     <!-- //2depth 메뉴 -->
     
     <div class="tab-content">
      <div class="tab-pane active" id="default">
       <div class="card-body">
        <!-- 3depth 메뉴 -->
        <tiles:insertAttribute name="menuLvl3" />
        <!-- //3depth 메뉴 -->
        
        <!-- bodyContent -->
        <tiles:insertAttribute name="body" />
        <!-- //bodyContent -->
       </div>
      </div>
     </div>
    </div>
   </div>
  </div>
    </section>
    <!-- #content end -->
</div>
<!-- #wrapper end -->
</body>
</html> 

 

 

 

5-3. MenuLvl2.jsp 설정(menuList 변수는 5-1에서 지정한 변수)

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<tiles:importAttribute name="menuList" />
<ul class="nav nav-tabs ui-sortable">
 <c:forEach var="result" items="${menuList}" varStatus="status">
  <c:if test="${result.lvl eq 2}">
   <li ${result.isActive eq 'Y' ? 'class="active"' : ''}><a href="${result.menuUrl }?menuId=${result.menuId}" ${result.popGubun eq 'Y' ? 'target="_blank"' : ''}>${result.menuNm }</a></li>
  </c:if>
 </c:forEach>
</ul> 

 

6. 만드는 것보다 글로 정리하는게 어렵네요... 로그인한 사용자에 대한 동적메뉴를 구성하는 부분에서 많이 막혔었네요.

구글 국내로 검색해도 마땅한 자료를 못찾아 많이 헤멧네요. 5-1 부분에 세션정보를 가져오는 부분이 국내에서 타일즈랑 묶어서 찾기가 참 힘들었네요

반응형

1. web.xml 설정(중간에 로그인 체크를 위한 인터셉터를 추가하는 것이면 이미 설정 되어있을 것이다.)

 

<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/config/egovframework/springmvc/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

 

2. dispatcher-servlet.xml 설정(프로젝트마다 파일이름이 다를 수 있다.)

 

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**/*View.do"/> <!-- 절대경로(/)부터 시작하면 중간경로가 있을 수 있기에 (**)으로 표시 -->
        <mvc:exclude-mapping path="/cmn/login/*.do"/> <!-- 예외 경로 지정 -->
        <mvc:exclude-mapping path="/mon/page/loginView.do"/> <!-- 예외 경로 지정(여러개일 수 있음으로...) -->
        <bean class="egovframework.cmn.cmn.AuthInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>

 

3. AuthInterceptor.java 설정

 

public class AuthInterceptor extends HandlerInterceptorAdapter {
    /**
     * 세션에 계정정보(LoginVO)가 있는지 여부로 인증 여부를 체크한다. 계정정보(LoginVO)가 없다면, 로그인 페이지로 이동한다.
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        LoginVO loginVO = null;
       
        try {
            loginVO = (LoginVO) request.getSession().getAttribute("loginVO");

            if (loginVO != null && loginVO.getUserId() != null) {
                return true;
            } else {
                ModelAndView modelAndView = new ModelAndView("forward:/loginView.do");
                modelAndView.addObject("message", "세션이 만료되어 로그아웃 되었습니다. 다시 로그인 해주세요.");
                throw new ModelAndViewDefiningException(modelAndView);
            }
        } catch (Exception e) {
            ModelAndView modelAndView = new ModelAndView("forward:/loginView.do");
            modelAndView.addObject("message", "세션이 만료되어 로그아웃 되었습니다. 다시 로그인 해주세요.");
            throw new ModelAndViewDefiningException(modelAndView);
        }
    }

    /**
     * 세션에 메뉴권한(LoginVO.userGubun)을 가지고 메뉴를 조회하여 권한 여부를 체크한다.
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        LoginVO loginVO = null;
        String requestURI = request.getRequestURI();
       
        try {
         if(!"/loginView.do".equals(requestURI)) {
          loginVO = (LoginVO) request.getSession().getAttribute("loginVO");
          if (loginVO != null && loginVO.getUserId() != null) {
           SearchVO searchVO = new SearchVO();
           searchVO.setSchMenuUrl(requestURI);
           searchVO.setSchUserGubun(loginVO.getUserGubun());
           List<?> resultList = sysadmService.getSelectRollMenuCheckList(searchVO);
           
           if(resultList == null || resultList.size() == 0) {
                     ModelAndView mav = new ModelAndView("forward:/monitorView.do"); 
                     mav.addObject("message", "권한이 없습니다.");
                     throw new ModelAndViewDefiningException(mav);
           }
           
          } else {
           ModelAndView mav = new ModelAndView("forward:/loginView.do");
           mav.addObject("message", "세션이 만료되어 로그아웃 되었습니다. 다시 로그인 해주세요.");
           throw new ModelAndViewDefiningException(mav);
          }
         }
        } catch (Exception e) {
            ModelAndView mav = new ModelAndView("forward:/monitorView.do"); 
            mav.addObject("message", "권한이 없습니다.");
            throw new ModelAndViewDefiningException(mav);
        }    }
}

 

4. 현재 진행 중인 프로젝트엔 세션 권한별 접근 메뉴 체크가 없기에 비워놈... 언젠가는 추가할지도??

5. 동일한 환경으로 새로운 프로젝트를 시작하여 권한도 추가하였다.

반응형

ResourceBundle 클래스를 사용하여 properties 파일 정보를 읽어올 수 있다.

 

다음과 같은 파일이 있다면

 

경로 : WEB-INF/classes/egovframework/egovProps/IpInfoSample.properties

 

IpInfoSample.properties 파일 내용

 

#소켓IP정보

SocketIp=127.0.0.1

 

#소켓포트정보

SocketPort=5001 

 

아래와 같이 사용하여 정보를 읽어올 수 있다.

 

ResourceBundle mainResource = ResourceBundle.getBundle("egovframework.egovProps.IpInfoSample");

String SocketIp = mainResource.getString("SocketIp");

String SocketPort = mainResource.getString("SocketPort");

 

System.out.println("[SocketIp] : " + SocketIp);

System.out.println("[SocketPort] : " + SocketPort);

 

결과 :

[SocketIp] : 127.0.0.1
[SocketPort] : 5001

 

properties 파일의 모든 정보를 읽어야 한다면 아래와 같이 사용할수도 있다.

 

ResourceBundle mainResource = ResourceBundle.getBundle("egovframework.egovProps.IpInfoSample");  

Enumeration enm = mainResource.getKeys();

 

while(enm.hasMoreElements()){
    String key = (String) enm.nextElement();
    String value = mainResource.getString(key);


    System.out.println("[" + key + "] : " + value);
}

 

결과 :

[SocketIp] : 127.0.0.1
[SocketPort] : 5001

 

반응형

GPKI 서버 인증서가 만료되어 GPKI를 신규로 발급받아 설치 시 표준API 라이센스 파일(gpkiapi.lic)의 내용을 복사하여

 

~(Web Root)/gpkisecureweb/client/var.js

 

위 파일에 아래 라이센스변수 내용을 수정하고 서버를 돌렸는데 계속 라이센스 만료에러가 발생하였다.

 

var.js

 

ServerCert = "MIID5 ...."

 

결론은 gpkiapi.lic 파일의 라이센스를 Base64Encode 값으로 변환하여 ServerCert 변수에 세팅해야된다. 

 

<%@ page import="com.gpki.gpkiapi.storage.Disk" %>
<%@ page import="com.gpki.gpkiapi.util.Base64" %>
<%@ page import="com.gpki.gpkiapi.cert.X509Certificate" %>
<%
String SERVER_KM_CERT_PATH = "서버인증서파일경로/서버인증서파일(SVR_env.cer)";
Base64 base64 = new Base64();
byte[] bBase64 = null;
String strBase64 = "";
X509Certificate srvCert = Disk.readCert(SERVER_KM_CERT_PATH);
bBase64 = srvCert.getCert();
strBase64 = new String(base64.encode(bBase64));
%>

 

위 내용은 표준API설치가이드에서 제공하는 Base64Encode로 변환하는 가이드인데 저대로 하면 에러가 발생한다.^^;

 

변환하기전에 아래 소스를 먼저 선언하고 돌려야한다. 참고로 가이드문서는 jsp로 되어있지만 java로 돌리면 훨신 간편하다. ^-^

 

GpkiApi.init("/subinto/conf/"); //gpkiapi.lic 가 있는 경로
반응형

java 1.7 버전과 톰캣 7, 스프링 프레임워크 3 버전대로 테스트하다가 몽고DB 4.0을 연결해서 테스트하다보니 오류가 발생.

몽고DB 4.0은 스프링 프레임워크 4 버전부터 사용가능하다고 해서 나는 오류.

스프링 버전 4.0으로 올리고 나서 해결됨.

 

cf) 스프링 버전 4.0으로 올리면서 java 버전은 1.8 과 톰캣 버전은 8로 같이 올려야됨...

반응형

Java에서 json 형태로 화면으로 떨구기

 

1. pom.xml 설정(Maven 설정)

        <!-- Ajax jQuery -->
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib-ext-spring</artifactId>
            <version>1.0.2</version>
            <exclusions>
                <exclusion>
                    <artifactId>servlet-api</artifactId>
                    <groupId>javax.servlet</groupId>
                </exclusion>
            </exclusions>
        </dependency>

 

2. action-servlet.xml 설정

    <!-- jsonView -->
    <bean id="jsonView" class="net.sf.json.spring.web.servlet.view.JsonView" >
        <property name="contentType" value="application/json;charset=UTF-8"></property>
    </bean>

 

3. Controller 설정

    @RequestMapping(value = "/biz/mkform/mkFormListJson.do")
    public ModelAndView selectMkFormListJson(CommandMap commandMap) throws Exception {
        ModelAndView mav = new ModelAndView("jsonView");
        Map<String,Object> resultMap = mkFormService.selectUserTableList(commandMap.getMap());
        mav.addObject("resultMap", resultMap);
       
        return mav;
    }

 

4. jsp 설정

 

        jQuery.ajax({
            type:'POST',
            url:'/biz/mkform/mkFormListJson.do',     
            data:'',
            async:false,
            dataType:'json',
            success:function(data){
                document.getElementById("wow").innerHTML = data.resultMap;
            }, 
            error:function(request,status,error){ 
                alert('[' + request.status + '] 에러가 발생하였습니다.');
            }
        });

 

※ 2. action-servlet.xml 설정에서 "net.sf.json.spring.web.servlet.view.JsonView" 대신 "org.springframework.web.servlet.view.json.MappingJacksonJsonView"를 사용해도 동일하게 동작된다.

차이점으로는 정렬순서와 null을 null로 처리할지 ""으로 처리할지 정도라는데 조금 더 자세한 사항은 검색!

반응형

https://www.free-powerpoint-templates-design.com/

반응형

'개발 > 참고사이트' 카테고리의 다른 글

부트스트랩 무료 템플릿 사이트  (1) 2020.08.11
무료 아이콘 사이트  (0) 2020.07.10
원격데스크탑 연결  (0) 2020.07.10
Mybatis 매퍼 설정관련  (0) 2019.02.07
jquery ztree  (0) 2018.11.02

jsoup lib를 이용하여 크롤링 연습하기

 

소스 다운 및 참고사이트 : https://jsoup.org/

 

public class CommonCrolling {
    private final static String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36";
   
    public static String getCurrentData(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
        return sdf.format(new Date());
    }
   
    public static void main(String[] args) {
        try {
            System.out.println("############################################## Start Time : " + getCurrentData());
            // 1. URL 선언
            String connUrl = "http://www.daum.net";
           
            // 2. HTML 가져오기
            Connection conn = Jsoup
                    .connect(connUrl)
                    .header("Content-Type", "application/json;charset=UTF-8")
                    .userAgent(USER_AGENT)
                    .method(Connection.Method.GET)
                    .ignoreContentType(true);
           
            Document doc = conn.get();
           
            // 3. 가져온 HTML Document 를 확인하기
            //System.out.println(doc.toString());
            System.out.println(doc.select(".list_stxt").toString());
           
        } catch (IOException e) {
            // Exp : Connection Fail
            e.printStackTrace();
        }
        System.out.println("############################################## End Time : " + getCurrentData());
    }
}

 

반응형

/* 뺑뺑이 만들기
    각 중학교 1차원 배열
 * 문제) 2009년도 대전 시내 초등학교 졸업생이 200명이다. (0~199번) 이 학생들을
        대전중학교에 45명, 한밭중학교에 40명, 갈마중학교에 30명, 둔산중학교에 50명,
        성모중학교에 35명을 배정하라. 그리고 위와 같이 학교별 배정 학생번호 리스트와
        학번별 학교배정 리스트를 출력하시오.
 */

 

public class HomeWork02 {
    public static void main(String[] args) {
        int[] 학번 = 학생번호(200);
        int[] 배당학교 = 뺑뺑이(학번);
        int num = 0;
        for(int i = 0 ; i < 중학교.length ; i++){
            HomeWork02 hw = new HomeWork02();
            System.out.println("============================================================================");
            System.out.println("학교명 : " + 중학교[i]);
            System.out.println("============================================================================");
            for(int j = 0 ; j < 학번.length ; j ++){
                if(배당학교[j] == i){
                    System.out.print(학번[j] + "\t");
                    num += 1;
                    if(num % 10 == 0) System.out.println(" ");
                }
            }
            System.out.println("학생수 : " + num);
            num = 0;
            System.out.println("============================================================================");
            System.out.println(" ");
            System.out.println(" ");
        }
        System.out.println("============================================================================");
        System.out.println("\t번호\t학교번호\t학교명\t누적학생수");
        System.out.println("============================================================================");
        int[] 누적학생수 = new int[중학교.length];   
        for(int i = 0 ; i < 학번.length ; i++){
            for(int j = 0 ; j < 중학교.length ; j++){
                if(j == 배당학교[i]){
                    누적학생수[j] += 1;
                    System.out.printf("%10d\t%8d\t%6s\t%6d\n", 학번[i], 배당학교[i], 중학교[j], 누적학생수[j]);          
                }else{
                  
                }
            }
        }
        System.out.println("============================================================================");     
    }
    static int[] 뺑뺑이(int[] a){                   
        int[] x = new int[a.length];                                // 학교배정 x
        int 대전중학생수 = 0, 한밭중학생수 = 0, 갈마중학생수 = 0,
                둔산중학생수 = 0, 성모중학생수 = 0;
        int total = 0;
        while(total < a.length){
     gogo : for(int i = 0 ; i < a.length ; i++){
                x[i] = (int)(Math.random()*5);
                if(x[i] == 0){
                    if(대전중학생수 >= 45){
                        i = i - 1;
                        continue gogo;
                    }else{
                        대전중학생수 += 1;
                    }
                }
                else if(x[i] == 1){
                    if(한밭중학생수 >= 40){
                        i = i - 1;
                        continue gogo;
                    }else{
                        한밭중학생수 += 1;
                    }
                }
                else if(x[i] == 2){
                    if(갈마중학생수 >= 30){
                        i = i - 1;
                        continue gogo;
                    }else{
                        갈마중학생수 += 1;
                    }
                }
                else if(x[i] == 3){
                    if(둔산중학생수 >= 50){
                        i = i - 1;
                        continue gogo;
                    }else{
                        둔산중학생수 += 1;
                    }
                }
                else{
                    if(성모중학생수 >= 35){
                        i = i - 1;
                        continue gogo;
                    }else{
                        성모중학생수 += 1;
                    }
                }
            }
                total = 대전중학생수 + 한밭중학생수 + 갈마중학생수 +
                    둔산중학생수 + 성모중학생수;   
        }
        return x;                            
    }
    static int[] 학생번호 (int a){
        int[] 번호 = new int[a];
        for(int i = 0 ; i < a ; i++){           // 학생번호 생성
            번호[i] = i;
        }
        return 번호;
    };
    static String[] 중학교 = new String[]{
        "대전중학교", "한밭중학교", "갈마중학교", "둔산중학교", "성모중학교"
    };
}

 

반응형

+ Recent posts