사용하면서 정리한 몇가지 옵션이다.

주로 사용자가 다운로드받은 엑셀의 프린트출력을 바로 할수 있도록 하기 위한 내용 중심이다.

HSSF보다는 최근의 excel은 대부분 xlsx를 사용하므로 XSSF를 사용.

 

/*
 * POI Library 용어 정리
	HSSF : 엑셀 파일을 다루는데 사용 (엑셀 97 이후~)
	XSSF : 엑셀 2007 이후의 xlsx 파일을 다루는데 사용
	HPSF : 오피스 파일의 문서요약 정보를 다루는데 사용
	HWPF : 워드 파일을 다루는데 사용
	HSLF : 파워포인트 파일을 다루는데 사용
	HDGF : 비지오 파일을 다루는데 사용
	HPBF : 퍼블리셔 파일을 다루는데 사용
	HSMF : 아웃룻의 *.msg 파일을 다루는데 사용
	DDF : 아웃룩의 이미지 파일을 다루는데 사용
 */
package com.test.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HeaderFooter;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Footer;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFPrintSetup;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;


/**
 *
 *  상세내용 엑셀 변환용 
 * 1. 타이틀은 회색, 페이지별로 반복
 * 2. 좌우여백 : 0.5 inch
 * 3. 페이지 레이아웃 : 가로는 1페이지로, 세로는 자동으로
 * 4. font size : 10, 타이틀은 11
 * 5. footer 중앙에 페이지번호 추가
 * 6. footer 좌우에 내용추가
 * 7. Horizontal center 정렬
 * 8. 각 컬럼사이즈는 고정으로 처리 (내용에 따라 일부 변경 필요)
 * 9. cell 정렬은 Vertical은 Center
 * 10. Cell내용은 줄바뀜 제거 ( wordWrap )
 */
@SpringBootTest
public class TestWriteExcel {

	@Test
	public void mainTest() {
		TestWriteExcel rww = new TestWriteExcel();

		try {

			rww.createExcel();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	void createExcel() {

		XSSFWorkbook xlsxWB = new XSSFWorkbook();

		// Sheet 이름 설정하기
		XSSFSheet sheet1 = xlsxWB.createSheet("202103_상세내역");
		sheet1.setFitToPage(true);
		sheet1.setAutobreaks(true);
			
//		double leftMarginInches = sheet.getMargin(Sheet.LeftMargin);
		sheet1.setMargin(Sheet.LeftMargin, 0.5 /* inches */ );
		sheet1.setMargin(Sheet.RightMargin, 0.5 /* inches */ );
		sheet1.setRepeatingRows(CellRangeAddress.valueOf("1"));
		
//		Header header = sheet1.getHeader();
		
		//page 번호 추가
		Footer footer = sheet1.getFooter();
        footer.setCenter( HeaderFooter.page() + "/" + HeaderFooter.numPages() );  
        footer.setLeft("회사명or 프로젝트명");
        footer.setRight("202103_상세내역");
		       
		
		XSSFPrintSetup ps = sheet1.getPrintSetup();
		ps.setPaperSize(XSSFPrintSetup.A4_PAPERSIZE);
		
		//확대/축소비율
//		ps.setScale((short)90); // 아래옵션이 있다면 설정 필요없음.
		ps.setFitWidth((short)1);  //가로는 1페이지에
		ps.setFitHeight((short)0); //세로는 자동으로
		
		sheet1.setHorizontallyCenter(true); //출력시 가로정렬 Center로
		
		// 컬럼의 너비 설정
//		sheet1.autoSizeColumn(1); // 행 번호
		
		//타이틀 Cell 스타일
		XSSFCellStyle cellStyle = xlsxWB.createCellStyle();
		cellStyle.setBorderBottom(BorderStyle.THIN);
		cellStyle.setBorderTop(BorderStyle.THIN);
		cellStyle.setBorderRight(BorderStyle.THIN);
		cellStyle.setBorderLeft(BorderStyle.THIN);

		//타이틀 Cell 색상
		cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); // 밝은 Grey
		cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); 
		
		cellStyle.setWrapText(true); //줄바뀜처리
		cellStyle.setAlignment(HorizontalAlignment.CENTER);  //가로정렬
		cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //세로정렬


		//내용 Cell 스타일
		XSSFCellStyle cellStyle2 = xlsxWB.createCellStyle();
		cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //세로정렬
		
		cellStyle2.setBorderBottom(BorderStyle.THIN);
		cellStyle2.setBorderTop(BorderStyle.THIN);
		cellStyle2.setBorderRight(BorderStyle.THIN);
		cellStyle2.setBorderLeft(BorderStyle.THIN);
		
        //내용은 크기에 따른 줄 바꿈 필요없음.(Default)
		//cellStyle2.setWrapText(true);
		Font font = xlsxWB.createFont();
		font.setFontHeightInPoints((short) 10);
		cellStyle2.setFont(font);
		

		XSSFRow row = null;
		XSSFCell cell = null;
		String[] titles = {
				"학교명", 
				"ID",
				"이름",
				"등록일시",
				"출석\n일시",
				"비고",
				"검사명",
				"담당자"
				};
		
		int i = 0;
		
        //각 컬럼별 사이즈 지정
		sheet1.setColumnWidth(i++, 3300);//
		sheet1.setColumnWidth(i++, 1700);//
		sheet1.setColumnWidth(i++, 2500);// 이름
		sheet1.setColumnWidth(i++, 3200);// 등록일시
		sheet1.setColumnWidth(i++, 3200);// 출석일시
		sheet1.setColumnWidth(i++, 3000);// 비고
		sheet1.setColumnWidth(i++, 3000);// 검사명
		sheet1.setColumnWidth(i++, 2200);// 담당자

		// 첫 행 만들기
		row = sheet1.createRow(0);
		
		int j=0;
		for (String string : titles) {			
			cell = row.createCell(j++);
			cell.setCellValue(string);
			cell.setCellStyle(cellStyle);
		}		

		String[] cellValues = {
				"데이터제목", 
				"A234567890",
				"홍길동입니다",
				"2020-12-23 14:55",
				"2020-12-25 14:55",
				"Test",
				"신장, 몸무게",
				"김선생"
				};
		
		CellType[] cellTypes = {
				CellType.STRING,
				CellType.STRING,
				CellType.STRING,
				CellType.STRING,
				CellType.STRING,
				CellType.STRING,
				CellType.STRING,
				CellType.STRING
		};
		
        //100개의 Row를 테스트로 입력하여 페이지 넘어가는 것 확인
		for(int l=1;l<100;l++) {
			// 두번째 행부터 내용입력됨
			row = sheet1.createRow(l);
			
			for (int k=0;k < cellValues.length;k++) {
				
				String string = cellValues[k];
				cell = row.createCell(k);
				cell.setCellValue(string);
				cell.setCellStyle(cellStyle2);
				cell.setCellType(cellTypes[k]);
			}			
		}
	
		// 파일저장
		String filename = "sample_" + Calendar.getInstance().getTimeInMillis() + ".xlsx";
		try {
			File xlsFile = new File("d:\\" + filename);
			FileOutputStream fileOut = new FileOutputStream(xlsFile);
			xlsxWB.write(fileOut);
			
			System.out.println(filename + " is created");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


OAuth2등을 위해서 java http 통신상에서 remote server가  https를 사용하는 경우 서버상에 해당 인증서 정보를 등록하지 않으면 아래와 같은 오류가 발생한다.

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
java.lang.NullPointerException

핵심은 브라우져가 아닌 java상에서 호출하기 때문이다.

java는 이를 위해  /jre/lib/security/cacerts 파일에 인증서 정보를 등록해서 사용한다.

cacerts파일은 handling은 %java_home%/bin/keytool 명령어를 통해서 관리한다. 

 

1. 현재 서버에 등록된 인증서 정보 조회
keytool -list -v -keystore java_home/jre/lib/security/cacerts

 

2. 인증서의 keystore정보에서 인증서를 파일로 추출
keytool -exportcert -keystore "keystore파일" -storepass "keystore파일의 비밀번호" -file xxx.cert -alias "alias name"

 

3. 앞에서 추출한 파일정보를 cacerts에 추가한다. (cacerts의 default 비밀번호는 changeit 임)
keytool -importcert -keystore ${JAVA_HOME}/jre/lib/security/cacerts -storepass changeit -file xxx.cert -alias "alias name"

 

인증서정보 추가결과

위와 같이 하면 오류가 없어짐.

 

java.security.KeyStore class에 대한 사용

 

KeyStore 파일에서 로딩하려면 저장된 keystore파일 경로와 비밀번호, 그리고 keystore저장시 지정된 alias이름을 알아야함.
KeyStore의 Instance생성은 KeyStore keystore = KeyStore.getInstance("jks"); 와 같은 형태임.
getInstance파라메터에는 keytype이 들어가야함. default는 "jks" 임.

 

keystore.load(new FileInputStream("keystore 파일 경로"), keystorepasswd);

로딩한 keystore파일정보를 조회

Certificate cf = keystore.getCertificate("alias Name");

위의 certificate정보를 출력해서 정상적으로 로딩되었는지 확인 가능.

 

이렇게 로딩된 keystore파일을 이용해서 ssl 통신에서 사용.

아래의 소스는 unirest lib를 이용한 호출시 적용예

public void setKeyStore() throws Exception {
		
//  ClassPathResource keyResource = new ClassPathResource(keyStorePath);
    FileInputStream fIn = new FileInputStream("/home/user/test.keystore");

    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());		
    keyStore.load(fIn, keyPass.toCharArray());

    //alias 포함여부 확인
    System.out.println("alias exist>>" + keyStore.containsAlias("alias name"));
    //alias를 통한 certificate 정보 조회
    System.out.println("cert info>>" + keyStore.getCertificate("alias name"));
        
    //SSL 통신을 하기 위해 Unirest정보에 cert정보 로딩.
    //여기서 인증서 정보가 cacerts에 등록되지 않으면 오류발생함.
    Unirest.config().clientCertificateStore(keyStore, keyPass);
}

 

 

참고 : www.lesstif.com/system-admin/java-validatorexception-keystore-ssl-tls-import-12451848.html

 

 



DBeaver workspace 변경

Posted 2021. 4. 13. 17:12

사용하던 Windows PC가 느려지거나 오동작한 경우 종종 PC를 초기화하여 사용하게 된다.

백업을 열심히 받고, 빠진게 없나 살펴보았지만 꼭 설치하고나면 빠진게 있어 멘붕이 오곤한다.

 

개발관련 프로그램이나 자료는 대부분  D드라이브에 위치하기 때문에 백업에서 자유롭긴한데, 그래도 빠지는것들이 발생한다.

Eclipse기반의 DBeaver를 사용중인데, 자주 빼먹는 백업요소중 하나이기도 하다. 

설치후 Default로 사용하게 되는 dbeaver의 workspace는 c:\Users\{사용자}\ 이하 디렉토리이다.

정확한 경로는 

공식문서를 찾아보니 CLI를 이용한 -data 옵션으로 실행하면 가능하다고 되어있다. 

command line에서 실행할때 파라메터로 -data 를 이용해서 workspace를 추가하면 된다는 내용인듯.

설치디렉토리에 가보니 dbeaver.exe 외에 dbeaver-cli.exe도 있다. 실행해보니 잘되긴 하는데... 문제는 로그가 foreground로 올라온다.  이건 아니다 싶어 혹시나하고 dbeaver.exe에도 동일한 옵션을 붙여서 해보니 동일하게 잘 된다. 뭐지?

( 설치디렉토리의 readme.txt를 보니 꼭 cli.exe라고 한정하지 않고 있다. )

 

바로가기를 만들고 대상입력란에 -data 옵션추가해서 사용하면 끝.

 

또다른 방법으로 Symbolic Link를 활용

또는 mklink명령어 사용

출처 : https://zetawiki.com/wiki/%EC%9C%88%EB%8F%84%EC%9A%B0_%EC%8B%AC%EB%B3%BC%EB%A6%AD_%EB%A7%81%ED%81%AC_%EC%83%9D%EC%84%B1

 

이렇게 해놓으면 다음부턴 굳이 백업을 받지 않아도 됨.

 



« PREV : 1 : 2 : 3 : 4 : 5 : ··· : 61 : NEXT »