반응형

maven 을 사용하다 보면 자주 사용되지만 공개 repository에서 관리되지 않는 라이브러리들이 종종 있습니다.


대표적으로 mssql jdbc 가 있습니다.


이런 경우 mssql jdbc만 다른 방식으로 관리하고 컴파일 및 빌드를 한다는게 정말 불편하고 일관되지 않아서 어려움이 많습니다.


그래서 maven에서 이런 라이브러들까지 관리할 수 있도록 local 라이브러리 관리 기능을 제공하고 있습니다.




1. pom.xml 에서 아래처럼 repository 를 설정합니다. ${basedir}은 프로젝트 루트 디렉토리 입니다.


1
2
3
4
5
6
7
8
9
  <repositories>
    <repository>
      <!-- DO NOT set id to "local" because it is reserved by Maven -->
      <id>local-lib</id>
      <name>In Project Repo</name>
      <url>file://${basedir}/lib</url>
      <layout>default</layout>
    </repository>
  </repositories>



2. mssql jdbc를 예로 <dependecies>에서는 아래 처럼 설정합니다.


1
2
3
4
5
6
    <!-- MSSQL -->
    <dependency>
      <groupId>com.microsoft.sqlserver</groupId>
      <artifactId>sqljdbc4</artifactId>
      <version>4.2</version>
    </dependency>




3. 다운로드 받은 실제 mssql 라이브러리를 아래 폴더 형식으로 넣어둡니다. 


[프로젝트홈] \lib\com\microsoft\sqlserver\sqljdbc4\4.2\sqljdbc4-4.2.jar


위 폴더 구조는 "groupId" / "artifactId" / "version" / "artifactId"-"version".jar 이런 규칙으로 생성됩니다. 




반응형
반응형

apache poi 로 엑셀작업을 하다보면 셀(Cell) 크기 문제로 어려움을 겪는 경우가 많이 있습니다.


Cell 세로 높이에 대해서 알아보겠습니다.


가로 크기를 자동으로 해놓으면 내용에 따라 가로 넓이가 계속 늘어나기 때문에 세로 높이를 신경쓸 필요가 없습니다.

하지만 내용이 많은 경우 자동 줄 바꿈 옵션(셀객체.getCellStyle().setWrapText(true))을 통해 보여주어야 합니다. 


보통은 wrapText를 하면 세로 높이 역시 자동으로 조정 됩니다.

문제는 병합된 셀들의 경우 자동으로 높이가 조절되지 않습니다.


이런 경우 해당 셀의 텍스트를 분석해서 셀의 높이를 계산해 높이를 수동으로 설정하는 방법이 있습니다.

아래 예제 소스를 보시면 특이하게 java.awt.Font 를 사용하고 있습니다.

일종의 편법의 awt Font를 이용해서 세로 높이를 계산해 내는 겁니다.


참고로, 병합된 셀의 세로 높이가 자동으로 잡히지 않는 문제는 poi 의 영역이 아니라 엑셀 자체의 문제라고 합니다.


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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
 
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.io.IOException;
import java.io.OutputStream;
import java.text.AttributedString;
import java.util.List;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.ShapeTypes;
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.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFSimpleShape;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;


...........................중략........................

/**
   * ROW 높이 자동 조절
   * 
   * @param rownum
   * @param cellValue
   */
  public void setAutoRowFit(int cellnum, int rownum) {
    XSSFRow row = sheet.getRow(rownum);
    XSSFCell cell = row.getCell(cellnum);
    XSSFFont cellFont = cell.getCellStyle().getFont();
    int fontStyle = java.awt.Font.PLAIN;
    if (cellFont.getBold())
      fontStyle = java.awt.Font.BOLD;
    if (cellFont.getItalic())
      fontStyle = java.awt.Font.ITALIC;
    java.awt.Font currFont = new java.awt.Font(cellFont.getFontName(), fontStyle,
        cellFont.getFontHeightInPoints());
    String cellText = cell.getStringCellValue();
    AttributedString attrStr = new AttributedString(cellText);
    attrStr.addAttribute(TextAttribute.FONT, currFont);
    // Use LineBreakMeasurer to count number of lines needed for the text
    //
    FontRenderContext frc = new FontRenderContext(nulltruetrue);
    LineBreakMeasurer measurer = new LineBreakMeasurer(attrStr.getIterator(), frc);
    int nextPos = 0;
    int lineCnt = 1;
    float columnWidthInPx = sheet.getColumnWidthInPixels(cellnum);
    while (measurer.getPosition() < cellText.length()) {
      nextPos = measurer.nextOffset(columnWidthInPx);
      lineCnt++;
      measurer.setPosition(nextPos);
    }
    System.out.println("lineCnt:" + lineCnt);
    if (lineCnt > 1) {
      row.setHeightInPoints(
          sheet.getDefaultRowHeightInPoints() * lineCnt * /* fudge factor */ 1f);
    }
  }
cs


반응형
반응형

웹 개발을 하다 보면 언제나 마주치는 것들 중에 하나가 바로 파일 다운로드 입니다.


파일을 다운로드 받기 위한 방법은 여러가지가 있습니다.


iframe을 이용한 방법, 새창을 이용한 방법, 자기 자신의 페이지에 바로 다운 받는 방법 등등 이 있습니다.



이번에 설명하려고 하는 것은 파일을 다운로드를 받는 방법과 무관하게 

다운로드 받을 파일을 생성하는 동안 로딩 표시나 프로그레스 바를 보여줄 수 있는 방법입니다.


용량이 작은 파일은 상관없지만 용량이 큰 파일은 생성하는데 시간이 오래 걸리기 때문에, 파일 다운로드 받기를 시도하고 있다는 사실을 사용자가 인지하지 못할 수 있습니다. 그렇게 되면 파일이 다운로드되지 않는다고 느껴 다른 페이지로 이동하거나 파일다운로드를 재시도하게 됩니다.


사용자 입장에서나 시스템 입장에서 모두 불편해지는 상황이 됩니다.


이런 상황을 해소하고자 하는게 이번 글의 목적 입니다.


간단하게 다운로드 할 파일을 생성하는 동안 화면에 뭔까 띄우기를 시작해 보겠습니다.


다운로드 할 파일을 생성하는 흔한 경우가 바로 엑셀 파일입니다.

엑셀 파일을 다운로드 하는 자바스크립트 코드입니다. (jquery 쿠키 플러그인을 이용하고 있습니다. https://plugins.jquery.com/cookie/)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 엑셀 다운로드 받기
function goExcelDownload() {
    $('#searchForm').submit(); // 다운로드 요청 !!
 
    fullSpinOn(); // spin 화면에 띄우기
 
 
    // 0.5 초마다 fileDownloadToken 라는 쿠키가 있는지 체크합니다.
    // 해당 쿠키가 있으면 spin을 끄고 fileDownloadToken 쿠키를 지운 후 Interval 을 종료 합니다.
    FILEDOWNLOAD_INTERVAL = setInterval(function() {
      if ($.cookie("fileDownloadToken"!= null) {
        $.cookie('fileDownloadToken'null, {
          expires : 0,
          path : location.pathname
        });
        clearInterval(FILEDOWNLOAD_INTERVAL);
        fullSpinOff();// 끄기
      }
    }, 500);
  }
cs


세상 간단합니다.

이해가 안되면 무슨 코드인가 싶겠지만 간단한 트릭정도로 생각하시면 됩니다.


1. 엑셀 다운로드를 서버에 요청한다. 

2. 바로 화면에 뭔가(로딩,프로그레스,스핀 등등)를 띄운다.

3. 서버에서 쿠키를 응답할 때까지 쭈욱 기다린다.

4. 서버에서는 파일 생성이 완료되면 다운로드 파일을 포함한 응답을 준다.

5. 응답 헤더에 쿠키가 포함되어 있어 파일다운로드가 시작되면 화면에서는 뭔가를 끈다.

6. 파일 다운로드가 시작된다. !!


JAVA 기준의 서버 쪽 소스를 보면 아래 처럼 간단하게 응답헤더에 쿠키만 넣어주면 끝입니다.


1
2
3
4
5
6
7
8
9
10
11
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
 
... 중략
 
 
// 엑셀 다운로드 요청을 처리하는 곳에서
// 응답 헤더에 fileDownloadToken 쿠키를 넣어줌.
 
Cookie cookie = new Cookie("fileDownloadToken""TRUE");
response.addCookie(cookie);
cs


대용량 파일 생성 후 다운로드 하는 서비스에는 필수 입니다.

고고~


반응형
반응형
1
2
3
4
5
    int lineCnt = 0;
    int fromIndex = -1;
    while ((fromIndex = cellText.indexOf("\n", fromIndex + 1)) >= 0) {
      lineCnt++;
    }
cs



개행문자를 예시로 썼습니다.


세상 간단합니다.

반응형
반응형

List 객체를 문자열로 붙여서 변환하고 싶을 경우,

String 객체의 join 메서드를 사용하면 됩니다.


String.join("이어줄문자열', list); 이런식으로 사용하시면 됩니다.

java 1.8 부터 생겨난 기능입니다.



String.join 메서드의 설명 입니다.

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
Open Declaration String java.lang.String.join(CharSequence delimiter, Iterable<extends CharSequence> elements)
 
 
Returns a new String composed of copies of the CharSequence elements joined together with a copy of the specified delimiter. 
 
For example, 
List<String> strings = new LinkedList<>();
     strings.add("Java");strings.add("is");
     strings.add("cool");
     String message = String.join(" ", strings);
     //message returned is: "Java is cool"
 
     Set<String> strings = new LinkedHashSet<>();
     strings.add("Java"); strings.add("is");
     strings.add("very"); strings.add("cool");
     String message = String.join("-", strings);
     //message returned is: "Java-is-very-cool"
Note that if an individual element is null, then "null" is added.
Parameters:
delimiter a sequence of characters that is used to separate each of the elements in the resulting String
elements an Iterable that will have its elements joined together.
Returns:
new String that is composed from the elements argument
Throws:
NullPointerException - If delimiter or elements is null
Since:
1.8
See Also:
join(CharSequence, CharSequence)
java.util.StringJoiner
cs


반응형
반응형

String.format("%d%%", 5);


==> 5%


이런식으로 %% 두번 쓰면 됩니다.

반응형
반응형

꿩 먹고 알 먹고 !!


개발 로그도 쌓고 !! 돈도 벌고 !! 


블로그에 광고를 붙여서 야금야금 용돈이라도 벌고싶습니다. 여러분 같이 해봅시다.



Step 1. 일단 광고를 붙일 수 있는 블로그를 하나 장만한다.


 - 저는 여기 티스토리에 장만했습니다.

 - 네이버 블로그는 광고 못 붙이는걸로 알고 있습니다.





Step 2. 어떤 광고를 붙일지 알아봅니다.


 - 티스토리는 두둥! 플러그인에서 다 제공해줍니다!!

 - 저는 그래도 제일 눈에 익은 구글 애드센스!!




Step 3. 광고를 붙여 봅시다.


https://www.google.com/adsense 에 가입하고 goni9071.tistory.com 으로 신청했는데 사이트 검토 결과가 두둥...

아무나 받아주지 않습니다. ㅜㅜ


컨텐츠 불충분!!! 

컨텐츠가 몇 개면 받아줄까요? 일단 50글을 목표로하고 50글 작성후에 다시 도전해 보겠습니다. ㅜㅜ




==============================================

두둥 아직  목표한 50글을 한참 못 채운 21 글 상태에서 아래와 같은 메일이 구글에서 왔습니다.


이제 광고글 게재할 준비가 되었냐고 친절하게 메일까지 보내주시다니요. ㅜㅜ


그래서 팔랑귀를 가진 저는 한번더 도전!! 을 했습니다만은.... 


결곽는 역시나 동일하게 컨텐츠 불충분 입니다. ㅜㅜ 돈벌기 쉽지 않네요. 흑흑.



==============================================

2017년 8월 20일 목표한 50글을 채워서 다시 신청했습니다.


하하하. 이게 뭐라고 승인되니 기분 좋네요. 드디어 저도 광고수익을 얻을 수 있습니다.~










===============================================


Step 4. 통계화면을 봅니다.


Step 5. 머라도 열심히 써봅니다.


 - 목표는 1일 1글 입니다.

 


Step 6. 강태공처럼 기다려 봅니다.

반응형
반응형

리눅스의 ln 링크처럼 윈도우에도 링크를 만들 수 있습니다.

 

만드는 방법은 아래와 같습니다.

 

mklink 링크주소 원본주소

 

 


/d 는 폴더 옵션.

반응형
반응형

html 파일을 서버에 올리지 않고 로컬의 파일을 바로 크롬에서 테스트 하는 경우,


Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.


위와 같은 오류가 발생한다.


이런 경우 열려있는 모든 크롬창을 완전히 닫은 후에,



위  이미지 처럼 'Chrome 개발용' 이란 이름으로 바로가기를 하나 만든 후에


 --disable-web-security --user-data-dir 을 chrome.exe 뒤에 복사한 후 "확인" 을 누른다.


그리고 새로만든 바로가기 아이콘으로 크롬을 실행하면 로컬파일에서도 ajax 테스트가 가능하다.



** 가끔 크롬을 모두 끄고 다시 시작해도 동일하게 오류가 발생할 때가 있다. 이럴땐 작업관리자에서 백그라운드로 크롬에 실행되고 있는 것이다. 백그라운드 프로세스도 모두 죽이고 다시하면된다.

** 정상적으로 개발용으로 크롬이 열리면 "지원되지 않는 명령줄 플래그(--disable-web-security)를 사용 중이므로 안정성과 보안에 문제가 발생합니다." 라는 경고가 뜬다.


반응형

+ Recent posts