'Programming/Java'에 해당하는 글 56건

Apache POI 는 MS office 문서포맷을 Java 로 사용할 수 있는 API 를 제공한다.

보통 WorkBook 으로 문서를 만드는 예제나, 암호화된 문서의 암호를 삭제시킬 수 있는 예제들이 떠돌고 있다.

 

MultipartFile 로 엑셀파일 전달 받고, 해당 파일에 암호 설정해서 돌려주는 API 를 만들어 봤다.

 

 

 Gradle 

 

dependencies {
    implementation 'org.apache.poi:poi:5.2.2'
    implementation 'org.apache.poi:poi-ooxml:5.2.2'
}

 

 

 Java 

 

@PostMapping("/excel/encrypt")
public ResponseEntity<ByteArrayResource> excelEncrypt(@RequestParam MultipartFile file) {

    String[] extensionArr = {"xls", "xlsx"};  // 97~, 2007~
    String[] mimeTypeArr = {"application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"};
    // 파일검증 생략

    // apache poi 엑셀 암호화
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    try (POIFSFileSystem fs = new POIFSFileSystem()) {
        EncryptionInfo encryptionInfo = new EncryptionInfo(EncryptionMode.agile);

        Encryptor encryptor = encryptionInfo.getEncryptor();
        encryptor.confirmPassword("password!@#$");

        try (OPCPackage opc = OPCPackage.open(file.getInputStream());
             OutputStream outputStream = encryptor.getDataStream(fs)) {
            opc.save(outputStream);
        }
        fs.writeFilesystem(byteArrayOutputStream);
        byteArrayOutputStream.close();
    } catch (Exception e) {
        logger.info(e.getMessage());
    }

    HttpHeaders header = new HttpHeaders();
    String encFileName = URLEncoder.encode(file.getOriginalFilename(), StandardCharsets.UTF_8).replace("+", "%20");
    header.setContentType(MediaType.parseMediaType(file.getContentType())); // <- 지정하지 않아도 무관
    header.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=utf-8''enc_" + encFileName);

    return new ResponseEntity<>(new ByteArrayResource(byteArrayOutputStream.toByteArray()),
                    header, HttpStatus.OK);
}

 

POIFS (Poor Obfuscation Implementation File System)
 - MS Office 의 OLE 2 Compound document 파일 포맷을 읽고 쓰는 컴포넌트. 
 - 모든 오피스 파일 포맷은 OLE2 방식이므로 하위 모든 컴포넌트의 기반이 된다.
HSSF (Horrible SpreadSheet Format)
 - MS excel 97 이후로 현재까지의 엑셀파일들에 읽고 쓰기를 지원하는 컴포넌트.
XSSF (XML SpreadSheet Format)
 - MS excel 2007 이후의 오픈 XML 파일 포맷인 *.xlsx 파일을 읽고 쓰는 컴포넌트.

 

 

 

 

음~ 잘된당~

용량을 10M 정도 넘겨봤더니, 에러 발생. 늘려보려 했는데... 실패!

 

Tried to allocate an array of length 132,636,469, but the maximum length for this record type is 100,000,000.
If the file is not corrupt or large, please open an issue on bugzilla to request 
increasing the maximum allowable size for this record type.
As a temporary workaround, consider setting a higher override value with IOUtils.setByteArrayMaxOverride()

WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

 

그 동안의 무심함에 미안함을 조금 가지며 JAVA 근황을 좀 살펴 보았다. 보아하니 발전을 많이 했다기 보다 버전만 열심히들 올렸네. 8인가 열심히 쓰고 있었는데 16이라니... 앞으로 신규 프로젝트들은 뭘루 시작해야 하나. OpenJDK 8 과 11 사이에서 어떤 것이 현명한 선택인지 모르겠다.

 

 

OpenJDK

Download and install the open-source JDK for most popular Linux distributions. Oracle's free, GPL-licensed, production-ready OpenJDK JDK 16 binaries are at jdk.java.net/16; Oracle's commercially-licensed JDK 16 binaries for Linux, macOS, and Windows, bas

openjdk.java.net

 

AdoptOpenJDK

AdoptOpenJDK provides prebuilt OpenJDK binaries from a fully open source set of build scripts and infrastructure. Supported platforms include Linux, macOS, Windows, ARM, Solaris, and AIX.

adoptopenjdk.net

 

Java 버전 별 변경점들을 정리해 봤다.


Java SE 17 LTS (2021.09)

  • Java 8, 11 을 잇는 세번째 LTS 버전(3년마다 배포)
  • 애플릿 완전 제거

 

Java SE 16 (2021.03)

  • OpenJDK 버전관리가 Mercurial 에서 Git 으로 변경.
  • jpackage 명령어로 자바 프로그램 손쉽게 배포(pkg, deb, msi 등)
  • 패턴 매칭 정식 지원
  • Record 형식 정식 지원

 

Java SE 15 (2020.09)

  • EdDSA 암호화 알고리즘 추가
  • 다중 텍스트 블록 (""")

 

Java SE 14 (2020.03)

  • instanceof 패턴 매칭
  • record (data object) 선언 기능 추가

 

Java SE 13 (2019.06)

  • switch 문에 yield 예약어 추가

 

Java SE 12 (2019.03)

  • Switch 문의 확장 : case MONDAY, FRIDAY, SUNDAY -> System.out.println(6); 

 

Java SE 11 LTS (2018.09)

  • 일반 지원은 2023년 9월, 연장 지원은 2026년 9월에 종료될 예정
  • Oracle JDK 와 Open JDK 통합 (Oracle JDK는 구독형 유료 모델로 전환)
  • 이클립스 재단으로 넘어간 Java EE가 JDK에서 삭제되고, JavaFX도 JDK에서 분리되어 별도의 모듈로 제공. 
  • 람다 파라미터에 대한 지역변수 문법 변경: (var x, var y) -> x.process(y) => (x, y) -> x.process(y)
  • HTTP 클라이언트 표준화 기능 추가 (jdk.incubator.http 패키지가 표준화되어 java.net.http 패키지로 추가)
  • 엡실론(Epsilon) 가지비 컬렉터 : 오버헤드의 최저지연과 할당 제한이 가능한 완전한 수동 가비지 컬렉터 적용

 

Java SE 10 (2018.03)

  • var 키워드를 이용한 지역변수 선언 및 타입추론 가능
  • 병렬 처리 가비지 컬렉션 도입으로 인한 성능 향상
  • JVM 힙 영역을 시스템 메모리가 아닌 다른 종류의 메모리에도 할당 가능
  • 루트 CA 목록 추가
  • JDK의 Repository가 하나로 통합
  • Deprecated된 API는 Java SE 10에서 모두 삭제

 

Java SE 9 (2017.09)

  • Jigsaw 기반 런타임 모듈화(기존 jar 방식 개선)
  • JAVA 를 인터프리터 언어 쉘처럼 사용할 수 있는 JShell 추가
  • immutable collection / HTTP/2 / private 인터페이스 메소드 / HTML5 Javadoc / 프로퍼티 파일에 UTF-8 지원
  • 1.x 버전에서 9.0 으로 판올림이 일어나며, 6개월마다 새로운 버전 업데이트

 

Java SE 8 (2014.03)

  • Oracle JDK vs Open JDK (오라클 인수 후 첫번째 버전)
  • Lambda 표현식 및 함수형 프로그래밍
  • 날짜 및 시간 API(java.time 패키지)
  • Stream API 추가
  • JavaScript 엔진 Rhino -> Nashorn
  • 32비트를 지원하는 마지막 공식 Java 버전

 

Java SE 7 (2011.07)

  • Switch 문에서 문자열 사용 가능 : case "MON"
  • generics 타입 추론(생략 가능) : Map<String, Object> map = new HashMap<>();
  • try-with-resources 자동 리소스 해제(close) : try (SomeResource resource = getResource()) { ...
  • Diamond Operator <> 지원
  • 멀티프로세서 처리 : Fork/Join Framework
  • ECC 암호화 내장
  • 이진수 표현 (2진수는 0b, 8진수는 0, 16진수는 0x로 시작)

 

Java SE 6 (2006.12)

  • J2SE 에서 Java SE 로 표기가 바뀜.
  • JDBC 4.0, Java Compiler API, Pluggable Annotation 등이 추가
  • Rhino JavaScript 엔진이 기본으로 탑재

 

Java SE 5 (2004.09)

  • generics, annotation, enum, foreach, ...

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,



첨부파일의 타입을 체크해야 할 때 해당 파일의 MimeType 을 살펴보면 어떤 파일인지 알 수 있는데, png 이미지 파일의 MimeType 이 image/png 이 아닌 application/octet-stream 로 넘어오는 현상을 발견했다.


new MimetypesFileTypeMap().getContentType(filename);


위와 비슷하게 MimetypesFileTypeMap() 을 사용했는데 이 메소드는 주어진 파일의 확장자를 이용하여 MimeType 을 확인하기 위해 사용자 시스템에서 다음의 순서로 mime.types 파일을 찾는다.


  1. 프로그래밍 방식으로 MimetypesFileTypeMap 인스턴스에 항목 추가
  2. 사용자의 홈 디렉토리에 있는 .mime.types
  3. <java.home>/lib/mime.types
  4. META-INF/mime.types
  5. META-INF/mimetypes.default (일반적으로 activation.jar 파일에만 있다.)


이 과정에서 mime.types 파일을 찾지 못하면 MimeType 으로 application/octet-stream 를 반환한다. 이 메소드는 주어진 파일의 확장자만 이용하여 파일의 타입을 판단하기 때문에 처리 시간이 아주 짧지만 사용자 시스템의 환경에 따라 정확도는 떨어진다. 웹 서버에는 흔히 META-INF/mime.types 파일이 있지만 사용자 환경에서 개발시에는 결과값이 다를 수 있다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

DAO Pattern

Programming/Java 2018. 12. 7. 00:38

DAO(Data Access Object) 디자인 패턴은 비즈니스 계층에서 퍼시스턴스 계층을 분리하는데 사용되는 구조적 패턴이다. 

쉽게말해 퍼시스턴스(Persistence) 계층... DB 의 데이터 처리(CRUD) 부분을 분리하여 계층간에 복잡성을 숨기는데 필요하다.


이 때 필요한건 세가지 이다.


  • Model Object : DAO 클래스에서 검색된 데이터를 저장하는 get/set 메소드가 포함된 간단한 POJO 이다. (Damain Class / Value Object 라고도 함.)
  • DAO Interface : 모델 객체에서 수행할 표준 연산을 정의한다.
  • DAO Class : 인터페이스를 구현한 클래스로서 DataSource 에서 데이터를 가져와야 한다.


아래 예는 학번과 이름으로 학생들을 관리하는 프로그램 예제이다.



1. Model Object


Student.java


public class Student {
   private String name;
   private int rollNo;
 
   Student(String name, int rollNo){
      this.name = name;
      this.rollNo = rollNo;
   }
 
   public String getName() {
      return name;
   }
 
   public void setName(String name) {
      this.name = name;
   }
 
   public int getRollNo() {
      return rollNo;
   }
 
   public void setRollNo(int rollNo) {
      this.rollNo = rollNo;
   }
}
cs


위 예에서 처럼 Student 클래스는 속성과 getter/setter 만 포함되고 별다른 로직을 갖지 않은 순수한 데이터 객체이다.

이것을 흔히들 Model Object / Damain Class / DTO(Data Transfer Object) / VO(Value Object) 등으로 혼용하여 부른다.



2. DAO Interface


StudentDao.java


import java.util.List;
 
public interface StudentDao {
   public List<Student> getAllStudents();
   public Student getStudent(int rollNo);
   public void updateStudent(Student student);
   public void deleteStudent(Student student);
}
cs


CRUD 관련한 인터페이스를 작성하였다..



3. Class implementing interface


StudentDaoImpl.java


import java.util.ArrayList;
import java.util.List;
 
public class StudentDaoImpl implements StudentDao {
    
   List<Student> students;
 
   public StudentDaoImpl(){
      students = new ArrayList<Student>();
      Student student1 = new Student("Robert",0);
      Student student2 = new Student("John",1);
      students.add(student1);
      students.add(student2);        
   }
 
   @Override
   public void deleteStudent(Student student) {
      students.remove(student.getRollNo());
   }
 
   @Override
   public List<Student> getAllStudents() {
      return students;
   }
 
   @Override
   public Student getStudent(int rollNo) {
      return students.get(rollNo);
   }
 
   @Override
   public void updateStudent(Student student) {
      students.get(student.getRollNo()).setName(student.getName());
   }
}
cs


DAO 인터페이스를 구현하여 비즈니스 계층과의 연결고리를 만들었다.

이제 이 객체만을 생성하여 CRUD 를 사용하면 되겠다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

Integer vs int

Programming/Java 2018. 12. 6. 21:31

Integer 와 int 이 둘의 차이를 흘려넘겼다가는 예상치 못한 곳에서 시간 낭비를 할 수도 있다.



기능


1. Integer : int 의 랩퍼 클래스로 산술 연산이 불가능하고, null 로 초기화가 가능하다. int를 처리 할 때 유용한 상수 및 메소드를 제공한다.

2. int : 원시 자료형으로 산술 연산이 가능하고, 키워드로 쓰이며 null 로 초기화 할 수 없다.



상호 변환 


1. Boxing : Integer integer = new Integer(i);

2. Unboxing : int i = integer.intValue();



문자열 변환


1. String -> Integer : Integer.valueOf(String)

2. String -> int : Integer.parseInt(String)



사이즈


1. Integer : 20 byte

2. int : 4 byte




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,