기존에 Java 에서 작업한 코드를 Kotlin 으로 변환하면서 기록한다
공통 엑셀 다운로드 기능 코드인데 Java 코드를 Kotlin 으로 변환하는 부분이 약간 햇갈려서 삽질을 조금 했다
1. 엑셀 업로드 Sample 객체 변환
Java 버전
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@ApiModel("Sample 엑셀 업로드 객체")
public class SampleExcel {
@NotEmpty//(message = "이름은 필수 입력값 입니다")
@ApiModelProperty(value = "이름", position = 1)
private String name;
@ApiModelProperty(value = "이메일", position = 2)
private String email;
@NotEmpty//(message = "전화번호는 필수 입력값입니다")
@ApiModelProperty(value = "전화번호", position = 3)
private String phone;
@NotEmpty//(message = "소속부서는 필수 입력값입니다")
@ApiModelProperty(value = "소속부서", position = 4)
@Size(min = 1, max = 10)
private String dept;
@NotNull//(message = "업무코드는 필수 입력값입니다")
@ApiModelProperty(value = "업무코드", position = 5)
private Integer workCode;
@NotNull//(message = "부서코드는 필수 입력값입니다")
@ApiModelProperty(value = "부서코드", position = 6)
private Integer deptCode;
@Size(min = 1, max = 500)
@ApiModelProperty(value = "내용", position = 7)
private String content;
@Size(max = 15)
@Pattern(regexp="(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])", message="IP 주소 형식이 올바르지 않습니다")
@ApiModelProperty(value = "IP", position = 8)
private String ip;
@ApiModelProperty(value = "소수", position = 9)
private Double percent;
@ApiModelProperty(value = "날짜", position = 10)
private String createDate;
@ApiModelProperty(value = "일시", position = 11)
private String updateDatetime;
@ApiModelProperty(value = "빈데이터", position = 12)
private String emptyData;
/**
* 엑셀 업로드 처리를 위한 객체
* @param row
* @return
*/
public static SampleExcel from(Row row) {
return ExcelUtils.setObjectMapping(new SampleExcel(), row);
}
}
⬇︎⬇︎⬇︎⬇︎
Kotlin
참고로 springfox 버전의 Swagger 를 사용했었는데 MSA 지원이나 최근까지 활발히 업데이트가 되고 있는 springdoc 로 변경했다
springfox 의 @ApiModel
,@ApiModelProperty
어노테이션 들은 springdoc 에서는 @Schema
로 사용된다
Kotlin 에서는 ()
안에 기본생성자로 생성한 객체 속성값에 어노테이션 기능을 적용하기 위해 @field
를 추가해주어야 정상적으로 적용이 된다
그리고 Kotlin 에서 static
은 companion object
로 선언해서 사용하는 방식으로 사용해야 한다
@Schema(title = "Sample 엑셀 업로드 객체", hidden = true)
class SampleExcel(
@field:Schema(title = "이름")
@field:NotEmpty
var name: String? = null,
@field:Schema(title = "이메일")
@field:NotEmpty
var email: String? = null,
@field:Schema(title = "전화번호")
@field:NotEmpty
var phone: String? = null,
@field:NotEmpty
@field:Schema(title = "소속부서")
var dept: String? = null,
@field:NotNull
@field:Schema(title = "업무코드")
var workCode: Int? = null,
@field:NotNull
@field:Schema(title = "부서코드")
var deptCode: Int? = null,
@field:Size(min = 1, max = 500)
@field:Schema(title = "내용")
var content: String? = null,
@field:Size(max = 15)
@field:Pattern(regexp="(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])", message = "IP 주소 형식이 올바르지 않습니다")
@field:Schema(title = "IP")
var ip: String? = null,
@field:Schema(title = "소수")
var percent: BigDecimal? = null,
@field:Schema(title = "날짜")
var createDate: String? = null,
@field:Schema(title = "일시")
var updateDatetime: String? = null,
@field:Schema(title = "빈데이터")
var empty: String? = null,
) {
override fun toString(): String {
return "SampleExcel(name=$name, email=$email, phone=$phone, dept=$dept, workCode=$workCode, deptCode=$deptCode, content=$content, ip=$ip, percent=$percent, createDate=$createDate, updateDatetime=$updateDatetime, empty=$empty)"
}
companion object {
/**
* 엑셀 업로드 처리를 위한 객체
* @param row Row
* @return SampleExcel?
*/
fun from(row: Row): SampleExcel = ExcelUtils.setObjectMapping(SampleExcel(), row)
}
}
2. 메서드 레퍼런스(Methond Reference) 를 사용하는 Function 인자값 변환
Java 버전
Java 버전에서는 Function<Row, T> rowfunc
인자값 전달을 위해 SampleExcel::from
메서드 레퍼런스를 전달하면 되었다
List<SampleExcel> sampleExcelList = ExcelReader.getObjectList(file, SampleExcel::from);
public static <T> List<T> getObjectList(final MultipartFile multipartFile, final Function<Row, T> rowFunc) {
⬇︎⬇︎⬇︎⬇︎
Kotlin 버전
Kotlin 버전에서는 Function<Row, T> rowfunc
인자값 전달을 위해 동일한 코드가 동작하지 않았고
아래와 같이 Lambda 함수로 변환하여 전달하여야 동일하게 동작되었다
val sampleExcelList: List<SampleExcel> = ExcelReader.getObjectList(file) { row -> SampleExcel.from(row) }
fun <T> getObjectList(multipartFile: MultipartFile, rowFunc: Function<Row, T>): List<T> {
3. IntStream, mapToObj 를 Kotlin 코드로 변환
Java 버전
List<T> objectList = IntStream
.range(startRow, rowCount)
.filter(rowIndex -> isPass(sheet.getRow(rowIndex)))
.mapToObj(rowIndex -> rowFunc.apply(sheet.getRow(rowIndex)))
.collect(Collectors.toList());
/**
* 해당 ROW에 있는 데이터가 모두 비어있으면 빈 ROW로 판단하고 해당 ROW는 PASS 시킨다
* @param row
* @return
*/
private static boolean isPass(Row row) {
int i =0;
boolean isPass = false;
while (i < row.getPhysicalNumberOfCells()) {
if(StringUtils.isNotEmpty(ExcelUtils.getValue(row.getCell(i++))))
isPass = true;
}
return isPass;
}
⬇︎⬇︎⬇︎⬇︎
Kotlin 버전
Kotlin 에서는 IntStream.range
를 사용할 필요 없이 아래와 같이 Range expression 을 구현할 수 있다mapToObj
는 Kotlin 에서 map
으로 구현하면 된다
또한 Java 에서 .collect(Collectors.toList())
장황하게 길던 코드를 Kotlin 에서는 .toList()
로 간결하게 표현할 수 있다
val objectList =
(startRow until rowCount)
.filter { isPass(sheet.getRow(it)) }
.map { rowFunc.apply(sheet.getRow(it)) }
.toList()
위의 로직의 filter
에서 사용되어지는 isPass
메서드도 불필요한 i
변수를 제거하고 Range expression 을 사용하여 아래와 같이 변환하였다
/**
* 해당 ROW에 있는 데이터가 모두 비어있으면 빈 ROW로 판단하고 해당 ROW는 PASS 시킨다
* @param row
* @return
*/
private fun isPass(row: Row): Boolean {
var isPass = false
(0 until row.physicalNumberOfCells).forEachIndexed { i, it ->
if (StringUtils.isNotEmpty(ExcelUtils.getValue(row.getCell(i)))) isPass = true
}
return isPass
}
'Kotlin' 카테고리의 다른 글
[Kotlin] Intellij에서 Kotlin SDK를 실수로 삭제 했을때 (0) | 2022.02.23 |
---|---|
[Kotlin] Kotlin Entity Field 생성 SQL (0) | 2021.10.06 |
[Kotlin] 리플렉션(Reflection) 으로 제네릭(Generic) 객체 생성하기 (0) | 2021.08.02 |
[Kotlin] Spring 리소스(Resource) to File 파일변환 (0) | 2021.08.01 |
[Kotlin] Spring 리소스(Resource) 파일 읽어오기, 다운로드 (0) | 2021.08.01 |
댓글