초기소스

This commit is contained in:
jazz
2025-10-29 17:08:05 +09:00
parent e531aa9540
commit 439a379a02
7551 changed files with 1234427 additions and 3 deletions

View File

@@ -0,0 +1,98 @@
package com.wb.domainserver.util;
import com.wb.domainserver.realm.RealmContextHolder;
import com.wb.domainserver.realm.util.UrlExtractor;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Map;
public abstract class CookieUtils {
public static String getCookieValue(String cookieName, HttpServletRequest request){
String cookieValue = "";
if(request.getCookies() != null){
for(Cookie cookie : request.getCookies()){
if(cookieName.equals(cookie.getName())){
cookieValue = cookie.getValue();
break;
}
}
}
return cookieValue;
}
public static void deleteCookie(String name, String path, HttpServletRequest request, HttpServletResponse response) {
String host = request.getHeader("X-Forwarded-Host");
if (host == null) {
host = request.getServerName(); // 기본값으로 현재 요청의 호스트명 사용
}
String originHost = UrlExtractor.getOriginalHost(host);
Cookie cookie = new Cookie(name, null);
cookie.setMaxAge(0);
cookie.setPath(path);
cookie.setDomain(originHost);
cookie.setHttpOnly(true);
response.addCookie(cookie);
}
public static void createCookie(String name, String value, String path, int maxAge, boolean httpOnly, HttpServletRequest request, HttpServletResponse response) {
String host = request.getHeader("X-Forwarded-Host");
if (host == null) {
host = request.getServerName(); // 기본값으로 현재 요청의 호스트명 사용
}
String originHost = UrlExtractor.getOriginalHost(host);
Cookie cookie = new Cookie(name, value);
cookie.setMaxAge(maxAge);
cookie.setPath(path);
cookie.setDomain(originHost);
cookie.setHttpOnly(httpOnly);
response.addCookie(cookie);
}
public static void createCookie(String name, String value, String path, boolean httpOnly, HttpServletRequest request, HttpServletResponse response) {
String host = request.getHeader("X-Forwarded-Host");
if (host == null) {
host = request.getServerName(); // 기본값으로 현재 요청의 호스트명 사용
}
String originHost = UrlExtractor.getOriginalHost(host);
Cookie cookie = new Cookie(name, value);
cookie.setPath(path);
cookie.setDomain(originHost);
cookie.setHttpOnly(httpOnly);
response.addCookie(cookie);
}
/**
* 로그인 쿠키 경로
* */
public static Map<String, String> loginCookiePath(){
String realm = RealmContextHolder.getRealm().toLowerCase();
String ACTPath = "sopmal".equals(realm) ? "/" : "/" + realm;
String RFTPath = "/" + realm + "/tokens/refresh";
return Map.of("ACTPath", ACTPath, "RFTPath", RFTPath);
}
}

View File

@@ -0,0 +1,131 @@
package com.wb.domainserver.util;
import lombok.extern.slf4j.Slf4j;
import java.io.Closeable;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.*;
/**
* 각종 resource close를 지원하는 util
*
* @author 박철민
* @since 2024-01-03
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2024-01-03 박철민 최초 생성
*
* </pre>
*/
@Slf4j
public class ResourceCloseHelper {
/**
* Resource close 처리.
* @param resources
*/
public static void close(Closeable ... resources) {
for (Closeable resource : resources) {
if (resource != null) {
try {
resource.close();
} catch (IOException ignore) {
log.debug("Occurred IOException to close resource is ingored!!");
}
}
}
}
/**
* JDBC 관련 resource 객체 close 처리
* @param objects
*/
public static void closeDBObjects(Wrapper ... objects) {
for (Object object : objects) {
if (object != null) {
if (object instanceof ResultSet) {
try {
((ResultSet)object).close();
} catch (SQLException ignore) {//KISA 보안약점 조치 (2018-10-29, 윤창원)
log.debug("Occurred SQLException to close resource is ingored!!");
}
} else if (object instanceof Statement) {
try {
((Statement)object).close();
} catch (SQLException ignore) {//KISA 보안약점 조치 (2018-10-29, 윤창원)
log.debug("Occurred SQLException to close resource is ingored!!");
}
} else if (object instanceof Connection) {
try {
((Connection)object).close();
} catch (SQLException ignore) {
log.debug("Occurred SQLException to close resource is ingored!!");
}
} else {
throw new IllegalArgumentException("Wrapper type is not found : " + object.toString());
}
}
}
}
/**
* Socket 관련 resource 객체 close 처리
* @param objects
*/
public static void closeSocketObjects(Socket socket, ServerSocket server) {
if (socket != null) {
try {
socket.shutdownOutput();
} catch (IOException ignore) {
log.debug("Occurred IOException to close resource is ingored!!");
}
try {
socket.close();
} catch (IOException ignore) {
log.debug("Occurred IOException to close resource is ingored!!");
}
}
if (server != null) {
try {
server.close();
} catch (IOException ignore) {
log.debug("Occurred IOException to close resource is ingored!!");
}
}
}
/**
* Socket 관련 resource 객체 close 처리
*
* @param sockets
*/
public static void closeSockets(Socket ... sockets) {
for (Socket socket : sockets) {
if (socket != null) {
try {
socket.shutdownOutput();
} catch (IOException ignore) {
log.debug("Occurred IOException to close resource is ingored!!");
}
try {
socket.close();
} catch (IOException ignore) {
log.debug("Occurred IOException to close resource is ingored!!");
}
}
}
}
}

View File

@@ -0,0 +1,66 @@
package com.wb.domainserver.util.communicate;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wb.domainserver.common.mvc.tags.ui.pagination.PaginationInfo;
import com.wb.domainserver.exception.WnbtRestException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
/**
* BO에서 전달받은 JSON String 변환을 지원하는 Object
*
* @author 박철민
* @since 2023-11-28
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-11-28 박철민 최초 생성
*
* </pre>
*/
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BoResultMapConverter {
@SuppressWarnings("unchecked")
public static Map<String, Object> convert(ObjectMapper objectMapper, String resultStr) {
try {
Map<String, Object> resultMap = objectMapper.readValue(resultStr, new TypeReference<Map<String, Object>>() {});
if(resultMap.containsKey("paginationInfo")) {
PaginationInfo paginationInfo = new PaginationInfo();
Map<String, Object> paginationMap = (Map<String, Object>)resultMap.get("paginationInfo");
if(paginationMap != null) {
if(paginationMap.get("currentPageNo") != null) {
paginationInfo.setCurrentPageNo(Integer.parseInt(paginationMap.get("currentPageNo").toString()));
}
if(paginationMap.get("recordCountPerPage") != null) {
paginationInfo.setRecordCountPerPage(Integer.parseInt(paginationMap.get("recordCountPerPage").toString()));
}
if(paginationMap.get("pageSize") != null) {
paginationInfo.setPageSize(Integer.parseInt(paginationMap.get("pageSize").toString()));
}
if(paginationMap.get("totalRecordCount") != null) {
paginationInfo.setTotalRecordCount(Integer.parseInt(paginationMap.get("totalRecordCount").toString()));
}
resultMap.put("paginationInfo", paginationInfo);
}
}
return resultMap;
} catch (WnbtRestException wre){
throw new WnbtRestException(wre.getMessage());
} catch (Exception e) {
log.error("BO에서 전달받은 결과 JsonString 변환 중 오류가 발생하였습니다. resultJsonString={}", resultStr, e);
throw new IllegalStateException("BO에서 전달받은 결과 JsonString 변환 중 오류가 발생하였습니다");
}
}
}

View File

@@ -0,0 +1,26 @@
package com.wb.domainserver.util.communicate;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
@Data
@Configuration
@ConfigurationProperties(prefix = "kakao")
public class KakaoProperties {
private static final Logger logger = LoggerFactory.getLogger(KakaoProperties.class);
private Map<String, String> keys;
public String getKeyForDomain(String domain) {
if (keys == null) {
logger.error("Domains map is null!");
}
return keys != null ? keys.get(domain) : null;
}
}

View File

@@ -0,0 +1,32 @@
package com.wb.domainserver.util.communicate;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wb.domainserver.exception.WnbtRestException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import java.util.Map;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public class MultiValueMapConverter {
public static MultiValueMap<String, Object> convert(ObjectMapper objectMapper, Object dto) {
try {
MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
Map<String, Object> map = objectMapper.convertValue(dto, new TypeReference<Map<String, Object>>() {});
params.setAll(map);
return params;
} catch (WnbtRestException wre) {
log.error("Url Parameter 변환중 오류가 발생했습니다. requestDto={}", dto, wre);
throw new WnbtRestException("Url Parameter 변환중 오류가 발생했습니다.");
} catch (Exception e) {
log.error("Url Parameter 변환중 오류가 발생했습니다. requestDto={}", dto, e);
throw new IllegalStateException("Url Parameter 변환중 오류가 발생했습니다.");
}
}
}

View File

@@ -0,0 +1,19 @@
package com.wb.domainserver.util.communicate;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum RESRC {
GCONEBO(RESRC_URL.gconeboServerUrl, "messaging-client"),
GCONEBO2(RESRC_URL.gconeboServerUrl, "messaging-gconebo"),
GCONEBO3(RESRC_URL.gconeboServerUrl, "messaging-sopmalfo-bd"),
GCONEBO4(RESRC_URL.gconeboServerUrl, "messaging-sopmalfo-dl"),
GCONEBO5(RESRC_URL.gconeboServerUrl, "messaging-sopmalfo-jm"),
REVIEWBO(RESRC_URL.reviewboServerUrl, "messaging-reviewbo"),
;
private final String registeredClientUrl;
private final String registeredClientId;
}

View File

@@ -0,0 +1,20 @@
package com.wb.domainserver.util.communicate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class RESRC_URL {
public static String gconeboServerUrl;
public static String reviewboServerUrl;
// @Value("${url.resource.server.gconebo}")
public void setGconeboServerUrl(String gconeboServerUrl) {
RESRC_URL.gconeboServerUrl = gconeboServerUrl;
}
// @Value("${url.resource.server.reviewbo}")
public void setReviewboServerUrl(String reviewboServerUrl) {
RESRC_URL.reviewboServerUrl = reviewboServerUrl;
}
}

View File

@@ -0,0 +1,11 @@
package com.wb.domainserver.util.communicate;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class ReplyFromResrc {
private boolean isEmpty;
private String reply;
}

View File

@@ -0,0 +1,128 @@
package com.wb.domainserver.util.communicate;
import com.wb.domainserver.security.authentication.MemberJwtContextHolder;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
@Slf4j
@Component
public class SendToResrc {
private static final Logger logger = LoggerFactory.getLogger(SendToResrc.class);
private final WebClient webClient;
private final MessageSource messageSource;
private final HttpServletRequest request;
public SendToResrc(WebClient webClient, MessageSource messageSource, HttpServletRequest request){
this.webClient = webClient;
this.messageSource = messageSource;
this.request = request;
}
public Mono<ReplyFromResrc> ofGetWithParam(RESRC resrc, String apiUri, Map<String, Object> param) {
String requestApiUrl = apiUri + (!param.isEmpty() ? "?".concat(urlEncodeUTF8(param)) : "");
return ofGet(resrc, requestApiUrl);
}
public Mono<ReplyFromResrc> ofGet(RESRC resrc, String apiUri) {
log.info("ReplyFromResrc ofGet ::: accessUrl = {}", MemberJwtContextHolder.getMemberInfo().getAccessUrl());
var authentication = SecurityContextHolder.getContext().getAuthentication();
var requestApiUrl = resrc.getRegisteredClientUrl() + apiUri;
WebClient.RequestHeadersSpec<?> request = this.webClient
.get()
.uri(requestApiUrl)
.header("X-Original-Host", MemberJwtContextHolder.getMemberInfo().getAccessUrl());
if (authentication instanceof Jwt accessToken) {
request = request.headers(h -> h.setBearerAuth(accessToken.getTokenValue()));
}
return request
.retrieve()
.toEntity(String.class)
.map(responseEntity -> {
boolean checkEmpty = responseEntity.getStatusCode().equals(HttpStatus.NO_CONTENT);
String content = checkEmpty ? "no Content" : responseEntity.getBody();
return ReplyFromResrc.builder().isEmpty(checkEmpty).reply(content).build();
})
.onErrorResume(this::handleError);
}
public Mono<ReplyFromResrc> ofPost(RESRC resrc, String apiUri, MultiValueMap<String, ?> param) {
return executePost(resrc, apiUri, param);
}
public Mono<ReplyFromResrc> ofPost(RESRC resrc, String apiUri, Object obj) {
return executePost(resrc, apiUri, obj);
}
private Mono<ReplyFromResrc> executePost(RESRC resrc, String apiUri, Object body) {
String tenantId = (String) request.getSession().getAttribute("X-Tenant-Id");
var authentication = SecurityContextHolder.getContext().getAuthentication();
var requestApiUrl = resrc.getRegisteredClientUrl() + apiUri;
WebClient.RequestBodySpec requestSpec = this.webClient
.post()
.uri(requestApiUrl)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML);
if (authentication instanceof Jwt jwt) {
requestSpec = requestSpec
.headers(h -> h.setBearerAuth(jwt.getTokenValue()))
.header("X-Tenant-Id", tenantId);
}
return requestSpec
.bodyValue(body)
.retrieve()
.toEntity(String.class)
.map(responseEntity -> {
boolean checkEmpty = responseEntity.getStatusCode().equals(HttpStatus.NO_CONTENT);
String content = checkEmpty ? "no Content" : responseEntity.getBody();
return ReplyFromResrc.builder().isEmpty(checkEmpty).reply(content).build();
})
.onErrorResume(this::handleError);
}
private Mono<ReplyFromResrc> handleError(Throwable e) {
log.error("Error occurred during API call", e);
return Mono.just(ReplyFromResrc.builder().isEmpty(true).reply("Error occurred: " + e.getMessage()).build());
}
static String urlEncodeUTF8(String s) {
return URLEncoder.encode(s, StandardCharsets.UTF_8);
}
static String urlEncodeUTF8(Map<?,?> map) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<?,?> entry : map.entrySet()) {
if (sb.length() > 0) {
sb.append("&");
}
sb.append(String.format("%s=%s",
urlEncodeUTF8(entry.getKey().toString()),
urlEncodeUTF8(entry.getValue().toString())
));
}
return sb.toString();
}
}

View File

@@ -0,0 +1,169 @@
package com.wb.domainserver.util.communicate;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wb.domainserver.common.msg.GconeMessageSource;
import com.wb.domainserver.exception.WnbtRestException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 정합성 점검결과 메시지 처리를 지원하는 Object
*
* @author 박철민
* @since 2023-11-28
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-11-28 박철민 최초 생성
*
* </pre>
*/
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ValidateResultConverter {
public static String convert(BindingResult bindingResult,
GconeMessageSource gconeMessageSource) {
StringBuffer resultMsgBf = new StringBuffer();
Map<String, Object> errorMap = new HashMap<>();
List<String> errorFields = new ArrayList<>();
errorMap.put("errorFiledNm", bindingResult.getFieldErrors().get(0).getField());
for(FieldError fieldError : bindingResult.getFieldErrors()) {
errorFields.add(fieldError.getField());
}
errorMap.put("errorFields", errorFields);
Object minValue = null;
Object maxValue = null;
for (ObjectError error : bindingResult.getAllErrors()) {
switch(error.getCode()) {
case "NotBlank" :
case "NotNull" :
case "NotEmpty" :
resultMsgBf.append(gconeMessageSource.getMessage("errors.required", new Object[] {error.getDefaultMessage()})).append("\n");
break;
case "Min" :
if(error.getArguments().length >= 2) {
minValue = error.getArguments()[1];
}
resultMsgBf.append(gconeMessageSource.getMessage("errors.min", new Object[] {error.getDefaultMessage(), minValue})).append("\n");
break;
case "Max" :
if(error.getArguments().length >= 2) {
maxValue = error.getArguments()[1];
}
resultMsgBf.append(gconeMessageSource.getMessage("errors.max", new Object[] {error.getDefaultMessage(), maxValue})).append("\n");
break;
case "Length" :
if(error.getArguments().length >= 2
&& error.getArguments().length < 3) {
maxValue = error.getArguments()[1];
} else if(error.getArguments().length >= 3) {
maxValue = error.getArguments()[1];
minValue = error.getArguments()[2];
}
resultMsgBf.append(gconeMessageSource.getMessage("errors.length", new Object[] {error.getDefaultMessage(), minValue, maxValue})).append("\n");
break;
case "Korean" :
resultMsgBf.append(gconeMessageSource.getMessage("errors.korean", new Object[] {error.getDefaultMessage()})).append("\n");
break;
case "English" :
resultMsgBf.append(gconeMessageSource.getMessage("errors.english", new Object[] {error.getDefaultMessage()})).append("\n");
break;
case "NumberOnly" :
resultMsgBf.append(gconeMessageSource.getMessage("errors.integer", new Object[] {error.getDefaultMessage()})).append("\n");
break;
case "NumberWithHyphen" :
resultMsgBf.append(gconeMessageSource.getMessage("errors.numberWithHyphen", new Object[] {error.getDefaultMessage()})).append("\n");
break;
case "Range" :
if(error.getArguments().length >= 2
&& error.getArguments().length < 3) {
maxValue = error.getArguments()[1];
} else if(error.getArguments().length >= 3) {
maxValue = error.getArguments()[1];
minValue = error.getArguments()[2];
}
resultMsgBf.append(gconeMessageSource.getMessage("errors.range", new Object[] {error.getDefaultMessage(), minValue, maxValue})).append("\n");
break;
case "Email" :
resultMsgBf.append(gconeMessageSource.getMessage("errors.email", new Object[] {error.getDefaultMessage()})).append("\n");
break;
case "Size":
if(error.getArguments().length >= 2
&& error.getArguments().length < 3) {
maxValue = error.getArguments()[1];
} else if(error.getArguments().length >= 3) {
maxValue = error.getArguments()[1];
minValue = error.getArguments()[2];
}
resultMsgBf.append(gconeMessageSource.getMessage("errors.size", new Object[] {error.getDefaultMessage(), minValue, maxValue})).append("\n");
break;
case "Password" :
resultMsgBf.append(gconeMessageSource.getMessage("errors.mngrPassword", new Object[] {error.getDefaultMessage()})).append("\n");
break;
case "Id" :
resultMsgBf.append(gconeMessageSource.getMessage("errors.id", new Object[] {error.getDefaultMessage()})).append("\n");
break;
case "BoardId" :
resultMsgBf.append(gconeMessageSource.getMessage("errors.boardId", new Object[] {error.getDefaultMessage()})).append("\n");
break;
}
}
errorMap.put("errorMsg", resultMsgBf.toString());
return makeErrorString(errorMap);
}
public static String convertCustomValidate(List<Map<String, String>> errorList) {
Map<String, Object> errorMap = new HashMap<>();
List<String> errorFields = new ArrayList<>();
StringBuffer resultMsgBf = new StringBuffer();
errorMap.put("errorFiledNm", errorList.get(0).get("errorFiledNm"));
for(Map<String, String> error : errorList) {
errorFields.add(error.get("errorFiledNm"));
resultMsgBf.append(error.get("errorMsg")).append("\n");
}
errorMap.put("errorMsg", resultMsgBf.toString());
errorMap.put("errorFields", errorFields);
return makeErrorString(errorMap);
}
public static Map<String, String> setErrorMap(String fieldNm, String errorMsg) {
Map<String, String> errorMap = new HashMap<>();
errorMap.put("errorFiledNm", fieldNm);
errorMap.put("errorMsg", errorMsg);
return errorMap;
}
private static String makeErrorString(Map<String, Object> errorMap) {
String resultMsg = null;
ObjectMapper objectMapper = new ObjectMapper();
try {
resultMsg = objectMapper.writeValueAsString(errorMap);
} catch (WnbtRestException wre){
throw new WnbtRestException(wre.getMessage());
} catch(Exception e) {
log.error("정합성 점검 결과 메시지 생성중 오류가 발생하였습니다.", e);
}
return resultMsg;
}
}

View File

@@ -0,0 +1,28 @@
package com.wb.domainserver.util.cookie;
import jakarta.servlet.http.Cookie;
public class CookieUtil {
public static boolean hasAgentCookie(Cookie[] cookies) {
if (cookies == null) return false;
for (Cookie cookie : cookies) {
if ("gc_agent_id".equals(cookie.getName())) {
return true;
}
}
return false;
}
public static String getAgentCookieValue(Cookie[] cookies) {
if (cookies == null) return null;
for (Cookie cookie : cookies) {
if ("gc_agent_id".equals(cookie.getName())) {
return cookie.getValue();
}
}
return null;
}
}

View File

@@ -0,0 +1,59 @@
package com.wb.domainserver.util.dataaccess;
/**
* 입력 문자열에 대하여 Camel 표기법으로 변환을 지원하는 Utility
*
* @author 박철민
* @since 2023-11-24
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-11-24 박철민 최초 생성
*
* </pre>
*/
public final class CamelUtil {
private CamelUtil() {
}
/**
* underscore ('_') 가 포함되어 있는 문자열을 Camel Case ( 낙타등
* 표기법 - 단어의 변경시에 대문자로 시작하는 형태. 시작은 소문자) 로 변환해주는
* utility 메서드 ('_' 가 나타나지 않고 첫문자가 대문자인 경우도 변환 처리
* 함.)
* @param underScore - '_' 가 포함된 변수명
* @return Camel 표기법 변수명
*/
public static String convert2CamelCase(String underScore) {
// '_' 가 나타나지 않으면 이미 camel case 로 가정함.
// 단 첫째문자가 대문자이면 camel case 변환 (전체를 소문자로) 처리가
// 필요하다고 가정함. --> 아래 로직을 수행하면 바뀜
if (underScore.indexOf('_') < 0 && Character.isLowerCase(underScore.charAt(0))) {
return underScore;
}
StringBuilder result = new StringBuilder();
boolean nextUpper = false;
int len = underScore.length();
for (int i = 0; i < len; i++) {
char currentChar = underScore.charAt(i);
if (currentChar == '_') {
nextUpper = true;
} else {
if (nextUpper) {
result.append(Character.toUpperCase(currentChar));
nextUpper = false;
} else {
result.append(Character.toLowerCase(currentChar));
}
}
}
return result.toString();
}
}

View File

@@ -0,0 +1,25 @@
package com.wb.domainserver.util.dataaccess;
import org.apache.commons.collections4.map.ListOrderedMap;
public class DataMap extends ListOrderedMap<Object, Object> {
private static final long serialVersionUID = 6723434363565852261L;
/**
* key 에 대하여 Camel Case 변환하여 super.put
* (ListOrderedMap) 을 호출한다.
* @param key
* - '_' 가 포함된 변수명
* @param value
* - 명시된 key 에 대한 값 (변경 없음)
* @return previous value associated with specified
* key, or null if there was no mapping for
* key
*/
@Override
public Object put(Object key, Object value) {
return super.put(CamelUtil.convert2CamelCase((String) key), value);
}
}

View File

@@ -0,0 +1,128 @@
package com.wb.domainserver.util.dataaccess;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
/**
* Mybatis 지원하는 Utility
*
* @author 박철민
* @since 2023-11-24
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-11-24 박철민 최초 생성
*
* </pre>
*/
@Slf4j
public class MybaitsUtil {
/**
* Empty 여부를 확인한다.
* @param o Object
* @return boolean
* @exception IllegalArgumentException
*/
public static boolean isEmpty(Object o) throws IllegalArgumentException {
try {
if(o == null) return true;
if(o instanceof String) {
if(((String)o).length() == 0){
return true;
}
} else if(o instanceof Collection) {
if(((Collection<?>)o).isEmpty()){
return true;
}
} else if(o.getClass().isArray()) {
if(Array.getLength(o) == 0){
return true;
}
} else if(o instanceof Map) {
if(((Map<?, ?>)o).isEmpty()){
return true;
}
}else {
return false;
}
return false;
} catch(IllegalArgumentException e) {
log.error("[IllegalArgumentException] Try/Catch...usingParameters Runing : "+ e.getMessage());
} catch(Exception e) {
log.error("["+e.getClass()+"] Try/Catch...Exception : " + e.getMessage());
}
return false;
}
/**
* Not Empty 여부를 확인한다.
* @param o Object
* @return boolean
* @exception IllegalArgumentException
*/
public static boolean isNotEmpty(Object o) {
return !isEmpty(o);
}
/**
* Equal 여부를 확인한다.
* @param obj Object, obj Object
* @return boolean
*/
public static boolean isEquals(Object obj, Object obj2){
if(isEmpty(obj)) return false;
if(obj instanceof String && obj2 instanceof String) {
if( (String.valueOf(obj)).equals( String.valueOf(obj2) )){
return true;
}
}else if(obj instanceof String && obj2 instanceof Character) {
if( (String.valueOf(obj) ).equals( String.valueOf(obj2) )){
return true;
}
}else if(obj instanceof String && obj2 instanceof Integer) {
if( (String.valueOf(obj)).equals( String.valueOf((Integer)obj2) )){
return true;
}
}else if(obj instanceof Integer && obj2 instanceof String) {
if( (String.valueOf(obj2)).equals( String.valueOf((Integer)obj) )){
return true;
}
} else if(obj instanceof Integer && obj instanceof Integer) {
if((Integer)obj == (Integer)obj2){
return true;
}
}
return false;
}
/**
* String의 Equal 여부를 확인한다.
* @param obj Object, obj Object
* @return boolean
*/
public static boolean isEqualsStr(Object obj, String s){
if(isEmpty(obj)) return false;
if(s.equals(String.valueOf(obj))){
return true;
}
return false;
}
}

View File

@@ -0,0 +1,785 @@
package com.wb.domainserver.util.date;
import java.security.SecureRandom;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import com.wb.domainserver.util.string.StringUtil;
/**
* Date 처리를 지원하는 Utility
*
* @author 박철민
* @since 2023-11-24
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-11-24 박철민 최초 생성
*
* </pre>
*/
public class DateUtil {
/**
* <p>yyyyMMdd 혹은 yyyy-MM-dd 형식의 날짜 문자열을 입력 받아 년, 월, 일을
* 증감한다. 년, 월, 일은 가감할 수를 의미하며, 음수를 입력할 경우 감한다.</p>
*
* <pre>
* DateUtil.addYearMonthDay("19810828", 0, 0, 19) = "19810916"
* DateUtil.addYearMonthDay("20060228", 0, 0, -10) = "20060218"
* DateUtil.addYearMonthDay("20060228", 0, 0, 10) = "20060310"
* DateUtil.addYearMonthDay("20060228", 0, 0, 32) = "20060401"
* DateUtil.addYearMonthDay("20050331", 0, -1, 0) = "20050228"
* DateUtil.addYearMonthDay("20050301", 0, 2, 30) = "20050531"
* DateUtil.addYearMonthDay("20050301", 1, 2, 30) = "20060531"
* DateUtil.addYearMonthDay("20040301", 2, 0, 0) = "20060301"
* DateUtil.addYearMonthDay("20040229", 2, 0, 0) = "20060228"
* DateUtil.addYearMonthDay("20040229", 2, 0, 1) = "20060301"
* </pre>
*
* @param dateStr 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식)
* @param year 가감할 년. 0이 입력될 경우 가감이 없다
* @param month 가감할 월. 0이 입력될 경우 가감이 없다
* @param day 가감할 일. 0이 입력될 경우 가감이 없다
* @return yyyyMMdd 형식의 날짜 문자열
* @throws IllegalArgumentException 날짜 포맷이 정해진 바와 다를 경우.
* 입력 값이 <code>null</code>인 경우.
*/
public static String addYearMonthDay(String sDate, int year, int month, int day) {
String dateStr = validChkDate(sDate);
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
try {
cal.setTime(sdf.parse(dateStr));
} catch (ParseException e) {
throw new IllegalArgumentException("Invalid date format: " + dateStr);
}
if (year != 0) {
cal.add(Calendar.YEAR, year);
}
if (month != 0) {
cal.add(Calendar.MONTH, month);
}
if (day != 0) {
cal.add(Calendar.DATE, day);
}
return sdf.format(cal.getTime());
}
/**
* <p>yyyyMMdd 혹은 yyyy-MM-dd 형식의 날짜 문자열을 입력 받아 년을
* 증감한다. <code>year</code>는 가감할 수를 의미하며, 음수를 입력할 경우 감한다.</p>
*
* <pre>
* DateUtil.addYear("20000201", 62) = "20620201"
* DateUtil.addYear("20620201", -62) = "20000201"
* DateUtil.addYear("20040229", 2) = "20060228"
* DateUtil.addYear("20060228", -2) = "20040228"
* DateUtil.addYear("19000101", 200) = "21000101"
* </pre>
*
* @param dateStr 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식)
* @param year 가감할 년. 0이 입력될 경우 가감이 없다
* @return yyyyMMdd 형식의 날짜 문자열
* @throws IllegalArgumentException 날짜 포맷이 정해진 바와 다를 경우.
* 입력 값이 <code>null</code>인 경우.
*/
public static String addYear(String dateStr, int year) {
return addYearMonthDay(dateStr, year, 0, 0);
}
/**
* <p>yyyyMMdd 혹은 yyyy-MM-dd 형식의 날짜 문자열을 입력 받아 월을
* 증감한다. <code>month</code>는 가감할 수를 의미하며, 음수를 입력할 경우 감한다.</p>
*
* <pre>
* DateUtil.addMonth("20010201", 12) = "20020201"
* DateUtil.addMonth("19800229", 12) = "19810228"
* DateUtil.addMonth("20040229", 12) = "20050228"
* DateUtil.addMonth("20050228", -12) = "20040228"
* DateUtil.addMonth("20060131", 1) = "20060228"
* DateUtil.addMonth("20060228", -1) = "20060128"
* </pre>
*
* @param dateStr 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식)
* @param month 가감할 월. 0이 입력될 경우 가감이 없다
* @return yyyyMMdd 형식의 날짜 문자열
* @throws IllegalArgumentException 날짜 포맷이 정해진 바와 다를 경우.
* 입력 값이 <code>null</code>인 경우.
*/
public static String addMonth(String dateStr, int month) {
return addYearMonthDay(dateStr, 0, month, 0);
}
/**
* <p>yyyyMMdd 혹은 yyyy-MM-dd 형식의 날짜 문자열을 입력 받아 일(day)를
* 증감한다. <code>day</code>는 가감할 수를 의미하며, 음수를 입력할 경우 감한다.
* <br/><br/>
* 위에 정의된 addDays 메서드는 사용자가 ParseException을 반드시 처리해야 하는 불편함이
* 있기 때문에 추가된 메서드이다.</p>
*
* <pre>
* DateUtil.addDay("19991201", 62) = "20000201"
* DateUtil.addDay("20000201", -62) = "19991201"
* DateUtil.addDay("20050831", 3) = "20050903"
* DateUtil.addDay("20050831", 3) = "20050903"
* // 2006년 6월 31일은 실제로 존재하지 않는 날짜이다 -> 20060701로 간주된다
* DateUtil.addDay("20060631", 1) = "20060702"
* </pre>
*
* @param dateStr 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식)
* @param day 가감할 일. 0이 입력될 경우 가감이 없다
* @return yyyyMMdd 형식의 날짜 문자열
* @throws IllegalArgumentException 날짜 포맷이 정해진 바와 다를 경우.
* 입력 값이 <code>null</code>인 경우.
*/
public static String addDay(String dateStr, int day) {
return addYearMonthDay(dateStr, 0, 0, day);
}
/**
* <p>yyyyMMdd 혹은 yyyy-MM-dd 형식의 날짜 문자열 <code>dateStr1</code>과 <code>
* dateStr2</code> 사이의 일 수를 구한다.<br>
* <code>dateStr2</code>가 <code>dateStr1</code> 보다 과거 날짜일 경우에는
* 음수를 반환한다. 동일한 경우에는 0을 반환한다.</p>
*
* <pre>
* DateUtil.getDaysDiff("20060228","20060310") = 10
* DateUtil.getDaysDiff("20060101","20070101") = 365
* DateUtil.getDaysDiff("19990228","19990131") = -28
* DateUtil.getDaysDiff("20060801","20060802") = 1
* DateUtil.getDaysDiff("20060801","20060801") = 0
* </pre>
*
* @param dateStr1 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식)
* @param dateStr2 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식)
* @return 일 수 차이.
* @throws IllegalArgumentException 날짜 포맷이 정해진 바와 다를 경우.
* 입력 값이 <code>null</code>인 경우.
*/
public static int getDaysDiff(String sDate1, String sDate2) {
String dateStr1 = validChkDate(sDate1);
String dateStr2 = validChkDate(sDate2);
if (!checkDate(sDate1) || !checkDate(sDate2)) {
throw new IllegalArgumentException("Invalid date format: args[0]=" + sDate1 + " args[1]=" + sDate2);
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
Date date1 = null;
Date date2 = null;
try {
date1 = sdf.parse(dateStr1);
date2 = sdf.parse(dateStr2);
} catch (ParseException e) {
throw new IllegalArgumentException("Invalid date format: args[0]=" + dateStr1 + " args[1]=" + dateStr2);
}
if (date1 != null && date2 != null) {
int days1 = (int) ((date1.getTime() / 3600000) / 24);
int days2 = (int) ((date2.getTime() / 3600000) / 24);
return days2 - days1;
} else {
return 0;
}
}
/**
* <p>yyyyMMdd 혹은 yyyy-MM-dd 형식의 날짜 문자열을 입력 받아 유효한 날짜인지 검사.</p>
*
* <pre>
* DateUtil.checkDate("1999-02-35") = false
* DateUtil.checkDate("2000-13-31") = false
* DateUtil.checkDate("2006-11-31") = false
* DateUtil.checkDate("2006-2-28") = false
* DateUtil.checkDate("2006-2-8") = false
* DateUtil.checkDate("20060228") = true
* DateUtil.checkDate("2006-02-28") = true
* </pre>
*
* @param dateStr 날짜 문자열(yyyyMMdd, yyyy-MM-dd의 형식)
* @return 유효한 날짜인지 여부
*/
public static boolean checkDate(String sDate) {
String dateStr = validChkDate(sDate);
String year = dateStr.substring(0, 4);
String month = dateStr.substring(4, 6);
String day = dateStr.substring(6);
return checkDate(year, month, day);
}
/**
* <p>입력한 년, 월, 일이 유효한지 검사.</p>
*
* @param year 연도
* @param month 월
* @param day 일
* @return 유효한 날짜인지 여부
*/
public static boolean checkDate(String year, String month, String day) {
boolean isValidDate = false;
try {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd", Locale.getDefault());
Date result = formatter.parse(year + "." + month + "." + day);
String resultStr = formatter.format(result);
if (resultStr.equalsIgnoreCase(year + "." + month + "." + day)) {
isValidDate = true; // 올바른 날짜 형식일 경우 true 설정
} else {
isValidDate = false; // 잘못된 날짜 형식일 경우 false 설정
}
} catch (ParseException e) {
isValidDate = false;
}
return isValidDate;
}
/**
* 날짜형태의 String의 날짜 포맷 및 TimeZone을 변경해 주는 메서드
*
* @param strSource 바꿀 날짜 String
* @param fromDateFormat 기존의 날짜 형태
* @param toDateFormat 원하는 날짜 형태
* @param strTimeZone 변경할 TimeZone(""이면 변경 안함)
* @return 소스 String의 날짜 포맷을 변경한 String
*/
public static String convertDate(String strSource, String fromDateFormat, String toDateFormat, String strTimeZone) {
SimpleDateFormat simpledateformat = null;
Date date = null;
String fromFormat = "";
String toFormat = "";
if (StringUtil.isNullToString(strSource).trim().equals("")) {
return "";
}
if (StringUtil.isNullToString(fromDateFormat).trim().equals(""))
fromFormat = "yyyyMMddHHmmss"; // default값
if (StringUtil.isNullToString(toDateFormat).trim().equals(""))
toFormat = "yyyy-MM-dd HH:mm:ss"; // default값
try {
simpledateformat = new SimpleDateFormat(fromFormat, Locale.getDefault());
date = simpledateformat.parse(strSource);
if (!StringUtil.isNullToString(strTimeZone).trim().equals("")) {
simpledateformat.setTimeZone(TimeZone.getTimeZone(strTimeZone));
}
simpledateformat = new SimpleDateFormat(toFormat, Locale.getDefault());
} catch (ParseException exception) {
throw new RuntimeException(exception);
}
return simpledateformat.format(date);
}
/**
* yyyyMMdd 형식의 날짜문자열을 원하는 캐릭터(ch)로 쪼개 돌려준다<br/>
* <pre>
* ex) 20030405, ch(.) -> 2003.04.05
* ex) 200304, ch(.) -> 2003.04
* ex) 20040101,ch(/) --> 2004/01/01 로 리턴
* </pre>
*
* @param date yyyyMMdd 형식의 날짜문자열
* @param ch 구분자
* @return 변환된 문자열
*/
public static String formatDate(String sDate, String ch) {
String dateStr = validChkDate(sDate);
String str = dateStr.trim();
String yyyy = "";
String mm = "";
String dd = "";
if (str.length() == 8) {
yyyy = str.substring(0, 4);
if (yyyy.equals("0000")) {
return "";
}
mm = str.substring(4, 6);
if (mm.equals("00")) {
return yyyy;
}
dd = str.substring(6, 8);
if (dd.equals("00")) {
return yyyy + ch + mm;
}
return yyyy + ch + mm + ch + dd;
} else if (str.length() == 6) {
yyyy = str.substring(0, 4);
if (yyyy.equals("0000")) {
return "";
}
mm = str.substring(4, 6);
if (mm.equals("00")) {
return yyyy;
}
return yyyy + ch + mm;
} else if (str.length() == 4) {
yyyy = str.substring(0, 4);
if (yyyy.equals("0000")) {
return "";
} else {
return yyyy;
}
} else {
return "";
}
}
/**
* HH24MISS 형식의 시간문자열을 원하는 캐릭터(ch)로 쪼개 돌려준다 <br>
* <pre>
* ex) 151241, ch(/) -> 15/12/31
* </pre>
*
* @param str HH24MISS 형식의 시간문자열
* @param ch 구분자
* @return 변환된 문자열
*/
public static String formatTime(String sTime, String ch) {
String timeStr = validChkTime(sTime);
return timeStr.substring(0, 2) + ch + timeStr.substring(2, 4) + ch + timeStr.substring(4, 6);
}
/**
* 연도를 입력 받아 해당 연도 2월의 말일(일수)를 문자열로 반환한다.
*
* @param year
* @return 해당 연도 2월의 말일(일수)
*/
public String leapYear(int year) {
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
return "29";
}
return "28";
}
/**
* <p>입력받은 연도가 윤년인지 아닌지 검사한다.</p>
*
* <pre>
* DateUtil.isLeapYear(2004) = false
* DateUtil.isLeapYear(2005) = true
* DateUtil.isLeapYear(2006) = true
* </pre>
*
* @param year 연도
* @return 윤년 여부
*/
public static boolean isLeapYear(int year) {
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
return false;
}
return true;
}
/**
* 현재(한국기준) 날짜정보를 얻는다. <BR>
* 표기법은 yyyy-mm-dd <BR>
* @return String yyyymmdd형태의 현재 한국시간. <BR>
*/
public static String getToday() {
return getCurrentDate("");
}
/**
* 현재(한국기준) 날짜정보를 얻는다. <BR>
* 표기법은 yyyy-mm-dd <BR>
* @return String yyyymmdd형태의 현재 한국시간. <BR>
*/
public static String getCurrentDate(String dateType) {
Calendar aCalendar = Calendar.getInstance();
int year = aCalendar.get(Calendar.YEAR);
int month = aCalendar.get(Calendar.MONTH) + 1;
int date = aCalendar.get(Calendar.DATE);
String strDate = Integer.toString(year)
+ ((month < 10) ? "0" + Integer.toString(month) : Integer.toString(month))
+ ((date < 10) ? "0" + Integer.toString(date) : Integer.toString(date));
if (!"".equals(dateType)) {
strDate = convertDate(strDate, "yyyyMMdd", dateType);
}
return strDate;
}
/**
* 날짜형태의 String의 날짜 포맷만을 변경해 주는 메서드
* @param sDate 날짜
* @param sTime 시간
* @param sFormatStr 포멧 스트링 문자열
* @return 지정한 날짜/시간을 지정한 포맷으로 출력
* @See Letter Date or Time Component Presentation Examples
G Era designator Text AD
y Year Year 1996; 96
M Month in year Month July; Jul; 07
w Week in year Number 27
W Week in month Number 2
D Day in year Number 189
d Day in month Number 10
F Day of week in month Number 2
E Day in week Text Tuesday; Tue
a Am/pm marker Text PM
H Hour in day (0-23) Number 0
k Hour in day (1-24) Number 24
K Hour in am/pm (0-11) Number 0
h Hour in am/pm (1-12) Number 12
m Minute in hour Number 30
s Second in minute Number 55
S Millisecond Number 978
z Time zone General time zone Pacific Standard Time; PST; GMT-08:00
Z Time zone RFC 822 time zone -0800
Date and Time Pattern Result
"yyyy.MM.dd G 'at' HH:mm:ss z" 2001.07.04 AD at 12:08:56 PDT
"EEE, MMM d, ''yy" Wed, Jul 4, '01
"h:mm a" 12:08 PM
"hh 'o''clock' a, zzzz" 12 o'clock PM, Pacific Daylight Time
"K:mm a, z" 0:08 PM, PDT
"yyyyy.MMMMM.dd GGG hh:mm aaa" 02001.July.04 AD 12:08 PM
"EEE, d MMM yyyy HH:mm:ss Z" Wed, 4 Jul 2001 12:08:56 -0700
"yyMMddHHmmssZ" 010704120856-0700
*/
public static String convertDate(String sDate, String sTime, String sFormatStr) {
String dateStr = validChkDate(sDate);
String timeStr = validChkTime(sTime);
Calendar cal = null;
cal = Calendar.getInstance();
cal.set(Calendar.YEAR, Integer.parseInt(dateStr.substring(0, 4)));
cal.set(Calendar.MONTH, Integer.parseInt(dateStr.substring(4, 6)) - 1);
cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateStr.substring(6, 8)));
cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(timeStr.substring(0, 2)));
cal.set(Calendar.MINUTE, Integer.parseInt(timeStr.substring(2, 4)));
SimpleDateFormat sdf = new SimpleDateFormat(sFormatStr, Locale.ENGLISH);
return sdf.format(cal.getTime());
}
/**
* 입력받은 일자 사이의 임의의 일자를 반환
* @param sDate1 시작일자
* @param sDate2 종료일자
* @return 임의일자
*/
public static String getRandomDate(String sDate1, String sDate2) {
String dateStr1 = validChkDate(sDate1);
String dateStr2 = validChkDate(sDate2);
String randomDate = null;
int sYear, sMonth, sDay;
int eYear, eMonth, eDay;
sYear = Integer.parseInt(dateStr1.substring(0, 4));
sMonth = Integer.parseInt(dateStr1.substring(4, 6));
sDay = Integer.parseInt(dateStr1.substring(6, 8));
eYear = Integer.parseInt(dateStr2.substring(0, 4));
eMonth = Integer.parseInt(dateStr2.substring(4, 6));
eDay = Integer.parseInt(dateStr2.substring(6, 8));
GregorianCalendar beginDate = new GregorianCalendar(sYear, sMonth - 1, sDay, 0, 0);
GregorianCalendar endDate = new GregorianCalendar(eYear, eMonth - 1, eDay, 23, 59);
if (endDate.getTimeInMillis() < beginDate.getTimeInMillis()) {
throw new IllegalArgumentException("Invalid input date : " + sDate1 + "~" + sDate2);
}
SecureRandom r = new SecureRandom();
r.setSeed(new Date().getTime());
long rand = ((r.nextLong() >>> 1) % (endDate.getTimeInMillis() - beginDate.getTimeInMillis() + 1)) + beginDate.getTimeInMillis();
GregorianCalendar cal = new GregorianCalendar();
//SimpleDateFormat calformat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat calformat = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH);
cal.setTimeInMillis(rand);
randomDate = calformat.format(cal.getTime());
// 랜덤문자열를 리턴
return randomDate;
}
/**
* 입력받은 요일의 영문명을 국문명의 요일로 반환
* @param sWeek 영문 요일명
* @return 국문 요일명
*/
public static String convertWeek(String sWeek) {
String retStr = null;
if (sWeek.equals("SUN")) {
retStr = "일요일";
} else if (sWeek.equals("MON")) {
retStr = "월요일";
} else if (sWeek.equals("TUE")) {
retStr = "화요일";
} else if (sWeek.equals("WED")) {
retStr = "수요일";
} else if (sWeek.equals("THR")) {
retStr = "목요일";
} else if (sWeek.equals("FRI")) {
retStr = "금요일";
} else if (sWeek.equals("SAT")) {
retStr = "토요일";
}
return retStr;
}
/**
* 입력일자의 유효 여부를 확인
* @param sDate 일자
* @return 유효 여부
*/
public static boolean validDate(String sDate) {
String dateStr = validChkDate(sDate);
Calendar cal;
boolean ret = false;
cal = Calendar.getInstance();
cal.set(Calendar.YEAR, Integer.parseInt(dateStr.substring(0, 4)));
cal.set(Calendar.MONTH, Integer.parseInt(dateStr.substring(4, 6)) - 1);
cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateStr.substring(6, 8)));
String year = String.valueOf(cal.get(Calendar.YEAR));
String month = String.valueOf(cal.get(Calendar.MONTH) + 1);
String day = String.valueOf(cal.get(Calendar.DAY_OF_MONTH));
String pad4Str = "0000";
String pad2Str = "00";
String retYear = (pad4Str + year).substring(year.length());
String retMonth = (pad2Str + month).substring(month.length());
String retDay = (pad2Str + day).substring(day.length());
String retYMD = retYear + retMonth + retDay;
if (sDate.equals(retYMD)) {
ret = true;
}
return ret;
}
/**
* 입력일자, 요일의 유효 여부를 확인
* @param sDate 일자
* @param sWeek 요일 (DAY_OF_WEEK)
* @return 유효 여부
*/
public static boolean validDate(String sDate, int sWeek) {
String dateStr = validChkDate(sDate);
Calendar cal;
boolean ret = false;
cal = Calendar.getInstance();
cal.set(Calendar.YEAR, Integer.parseInt(dateStr.substring(0, 4)));
cal.set(Calendar.MONTH, Integer.parseInt(dateStr.substring(4, 6)) - 1);
cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateStr.substring(6, 8)));
int Week = cal.get(Calendar.DAY_OF_WEEK);
if (validDate(sDate)) {
if (sWeek == Week) {
ret = true;
}
}
return ret;
}
/**
* 입력시간의 유효 여부를 확인
* @param sTime 입력시간
* @return 유효 여부
*/
public static boolean validTime(String sTime) {
String timeStr = validChkTime(sTime);
Calendar cal;
boolean ret = false;
cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(timeStr.substring(0, 2)));
cal.set(Calendar.MINUTE, Integer.parseInt(timeStr.substring(2, 4)));
String HH = String.valueOf(cal.get(Calendar.HOUR_OF_DAY));
String MM = String.valueOf(cal.get(Calendar.MINUTE));
String pad2Str = "00";
String retHH = (pad2Str + HH).substring(HH.length());
String retMM = (pad2Str + MM).substring(MM.length());
String retTime = retHH + retMM;
if (sTime.equals(retTime)) {
ret = true;
}
return ret;
}
/**
* 입력된 일자에 연, 월, 일을 가감한 날짜의 요일을 반환
* @param sDate 날짜
* @param year 연
* @param month 월
* @param day 일
* @return 계산된 일자의 요일(DAY_OF_WEEK)
*/
public static String addYMDtoWeek(String sDate, int year, int month, int day) {
String dateStr = validChkDate(sDate);
dateStr = addYearMonthDay(dateStr, year, month, day);
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH);
try {
cal.setTime(sdf.parse(dateStr));
} catch (ParseException e) {
throw new IllegalArgumentException("Invalid date format: " + dateStr);
}
SimpleDateFormat rsdf = new SimpleDateFormat("E", Locale.ENGLISH);
return rsdf.format(cal.getTime());
}
/**
* 입력된 일자에 연, 월, 일, 시간, 분을 가감한 날짜, 시간을 포멧스트링 형식으로 반환
* @param sDate 날짜
* @param sTime 시간
* @param year 연
* @param month 월
* @param day 일
* @param hour 시간
* @param minute 분
* @param formatStr 포멧스트링
* @return
*/
public static String addYMDtoDayTime(String sDate, String sTime, int year, int month, int day, int hour, int minute, String formatStr) {
String dateStr = validChkDate(sDate);
String timeStr = validChkTime(sTime);
dateStr = addYearMonthDay(dateStr, year, month, day);
dateStr = convertDate(dateStr, timeStr, "yyyyMMddHHmm");
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm", Locale.ENGLISH);
try {
cal.setTime(sdf.parse(dateStr));
} catch (ParseException e) {
throw new IllegalArgumentException("Invalid date format: " + dateStr);
}
if (hour != 0) {
cal.add(Calendar.HOUR, hour);
}
if (minute != 0) {
cal.add(Calendar.MINUTE, minute);
}
SimpleDateFormat rsdf = new SimpleDateFormat(formatStr, Locale.ENGLISH);
return rsdf.format(cal.getTime());
}
/**
* 입력된 일자를 int 형으로 반환
* @param sDate 일자
* @return int(일자)
*/
public static int datetoInt(String sDate) {
return Integer.parseInt(convertDate(sDate, "0000", "yyyyMMdd"));
}
/**
* 입력된 시간을 int 형으로 반환
* @param sTime 시간
* @return int(시간)
*/
public static int timetoInt(String sTime) {
return Integer.parseInt(convertDate("00000101", sTime, "HHmm"));
}
/**
* 입력된 일자 문자열을 확인하고 8자리로 리턴
* @param sDate
* @return
*/
public static String validChkDate(String dateStr) {
if (dateStr == null || !(dateStr.trim().length() == 8 || dateStr.trim().length() == 10)) {
throw new IllegalArgumentException("Invalid date format: " + dateStr);
}
if (dateStr.length() == 10) {
return StringUtil.removeMinusChar(dateStr);
}
return dateStr;
}
/**
* 입력된 일자 문자열을 확인하고 8자리로 리턴
* @param sDate
* @return
*/
public static String validChkTime(String timeStr) {
if (timeStr == null || !(timeStr.trim().length() == 4)) {
throw new IllegalArgumentException("Invalid time format: " + timeStr);
}
if (timeStr.length() == 5) {
timeStr = StringUtil.remove(timeStr, ':');
}
return timeStr;
}
}

View File

@@ -0,0 +1,202 @@
package com.wb.domainserver.util.excel;
import com.wb.domainserver.util.ResourceCloseHelper;
import com.wb.domainserver.util.string.StringUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
*
* 엑셀 생성 및 다운로드를 처리해주는
* @author 박철민
* @since 2023-12-20
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-12-20 박철민 최초 생성
*
* </pre>
*/
@Slf4j
public class ExcelDownloadUtil {
/**
* 엑셀파일 생성 및 다운로드 처리
* @param excelFileName 다운로드될 엑셀파일명
* @param headerMap 제목영역에 출력될 데이터 map
* @param dataList 데이터영역에 출력될 데이터 map list
* @param response 다운로드 처리를 위한 응답객체
* @param useType cell 데이터 타입 적용여부
* @throws IOException
*/
public static void createExcel(String excelFileName,
LinkedHashMap<String, String> headerMap,
List<Map<String, Object>> dataList,
HttpServletResponse response,
boolean useType) throws IOException {
Workbook wb = new SXSSFWorkbook();
try {
Sheet sheet = wb.createSheet();
createHeaderRow(wb, sheet, headerMap);
createDataRow(wb, sheet, headerMap, dataList, useType);
response.setContentType("ms-vnd/excel");
response.setHeader("Content-Disposition", "attachment;filename="+excelFileName+".xlsx");
wb.write(response.getOutputStream());
} catch (IOException e) {
log.error("Workbook write 수행 중 IOException 발생!");
throw e;
} finally {
ResourceCloseHelper.close(wb);
}
}
public static void createExcel(String excelFileName,
LinkedHashMap<String, String> headerMap,
List<Map<String, Object>> dataList,
HttpServletResponse response) throws IOException {
createExcel(excelFileName, headerMap, dataList, response, false);
}
/**
* 엑셀 제목영역 생성
* @param wb 엑셀workbook객체
* @param sheet 엑셀sheet객체
* @param headerMap 제목영역에 출력될 데이터 map
*/
private static void createHeaderRow(Workbook wb,
Sheet sheet,
LinkedHashMap<String, String> headerMap) {
Row row = sheet.createRow(0);
CellStyle excelheaderStyle = wb.createCellStyle();
Font excelheaderFont = wb.createFont();
getExcelHeaderCellStyle(excelheaderStyle, excelheaderFont);
headerMap.forEach((key, value)->{
createCell(wb, row, value, excelheaderStyle, false);
});
}
/**
* 엑셀 데이터영역 생성
* @param wb 엑셀workbook객체
* @param sheet 엑셀sheet객체
* @param headerMap 제목영역에 출력될 데이터 map
* @param dataList 데이터영역에 출력될 데이터 map list
* @param useType cell 데이터 타입 적용여부
*/
private static void createDataRow(Workbook wb,
Sheet sheet,
LinkedHashMap<String, String> headerMap,
List<Map<String, Object>> dataList,
boolean useType) {
if(dataList != null
&& !dataList.isEmpty()) {
CellStyle excelheaderStyle = wb.createCellStyle();
Font excelheaderFont = wb.createFont();
getExcelDataCellStyle(excelheaderStyle, excelheaderFont);
for(int idx=0; idx<dataList.size(); idx++) {
Row row = sheet.createRow(idx+1);
for( String key : headerMap.keySet() ){
createCell(wb, row, dataList.get(idx).get(key), excelheaderStyle, useType);
}
}
}
}
/**
* 엑셀 셀생성
* @param wb 엑셀workbook객체
* @param row 엑셀sheet객체
* @param cellValue cell에 설정될 값
* @param cellStyle cell에 적용될 style
* @param useType cell 데이터 타입 적용여부
*/
private static void createCell(Workbook wb,
Row row,
Object cellValue,
CellStyle cellStyle,
boolean useType) {
int column=0;
if(row.getLastCellNum() > 0) {
column = row.getLastCellNum();
}
Cell cell = row.createCell(column);
if (useType && cellValue instanceof Number) {
cell.setCellValue(((Number) cellValue).doubleValue());
} else {
cell.setCellValue(StringUtil.isNullToString(cellValue));
}
cell.setCellStyle(cellStyle);
}
/**
* 엑셀 제목영역 cell style 설정
* @param wb 엑셀workbook객체
* @return CellStyle 엑셀 제목영역 cell style
*/
private static void getExcelHeaderCellStyle(CellStyle excelheaderStyle, Font excelheaderFont) {
//정렬설정
excelheaderStyle.setAlignment(HorizontalAlignment.CENTER);
excelheaderStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//제목영역 배경색 설정
excelheaderStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
excelheaderStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
//테두리 선 (우,좌,위,아래)
excelheaderStyle.setBorderRight(BorderStyle.THIN);
excelheaderStyle.setBorderLeft(BorderStyle.THIN);
excelheaderStyle.setBorderTop(BorderStyle.THIN);
excelheaderStyle.setBorderBottom(BorderStyle.THIN);
//폰트 설정
excelheaderFont.setFontName("나눔고딕"); //글씨체
excelheaderFont.setFontHeight((short)(10*20)); //사이즈
excelheaderFont.setBold(true);
excelheaderStyle.setFont(excelheaderFont);
}
/**
* 엑셀 데이터영역 cell style 설정
* @param wb 엑셀workbook객체
* @return CellStyle 엑셀 데이터영역 cell style
*/
private static void getExcelDataCellStyle(CellStyle excelheaderStyle, Font excelheaderFont) {
//정렬설정
excelheaderStyle.setAlignment(HorizontalAlignment.LEFT);
excelheaderStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//테두리 선 (우,좌,위,아래)
excelheaderStyle.setBorderRight(BorderStyle.THIN);
excelheaderStyle.setBorderLeft(BorderStyle.THIN);
excelheaderStyle.setBorderTop(BorderStyle.THIN);
excelheaderStyle.setBorderBottom(BorderStyle.THIN);
//폰트 설정
excelheaderFont.setFontName("나눔고딕"); //글씨체
excelheaderFont.setFontHeight((short)(10*20)); //사이즈
excelheaderFont.setBold(false);
excelheaderStyle.setFont(excelheaderFont);
}
}

View File

@@ -0,0 +1,347 @@
package com.wb.domainserver.util.file;
import com.wb.domainserver.exception.WnbtRestException;
import com.wb.domainserver.util.string.StringUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.tika.Tika;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
/**
* multipart로 업로드된 파일을 처리하는 UTIL
*
* @author 박철민
* @since 2024-01-03
* @version 1.0
* @see
*
* CkEditor로 업로드 하는 경우 사용
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2024-01-03 박철민 최초 생성
* 2024-02-21 김혜지 수정
*
*/
@Slf4j
@Component("fileMngUtil")
public class FileMngUtil {
/**
* 첨부파일에 대한 목록 정보 취득 및 저장처리를 진행한다.
* @param files 업로드된 multipartfile 목록
* @param KeyStr rename되는 파일명 앞에 설정될 prefix
* @param storePath 업로드된 파일이 저장될 경로
* @param whiteListFileUploadExtensions 업로드가 허용된 파일확장자 목록
* @return List<Map<String, Object>> 처리결과 목록 정보
*/
public List<Map<String, Object>> parseFileInf(List<MultipartFile> files,
String prefix,
String storePath,
String whiteListFileUploadExtensions) {
List<Map<String, Object>> resultList= new ArrayList<>();
Map<String, Object> fileMap = null;
File saveFolder = null;
String storePathString = null;
String orginFileName = null;
String fileExt = null;
String newName = null;
String filePath = null;
Long size = null;
Integer fileKey = 0;
try {
log.debug("whiteListFileUploadExtensions is {}", whiteListFileUploadExtensions);
storePathString = storePath;
if (storePath == null || "".equals(storePath)) {
throw new WnbtRestException("파일 업로드 경로가 존재하지 않습니다.");
}
log.debug("storePathString is {}", storePathString);
//파일이 저장될 디렉토리 생성
saveFolder = new File(filePathBlackList(storePathString));
if (!saveFolder.exists() || saveFolder.isFile()) {
if (saveFolder.mkdirs()) {
log.debug("[file.mkdirs] saveFolder : Creation Success ");
} else {
log.error("[file.mkdirs] saveFolder : Creation Fail ");
}
}
//MultipartFile 정보 parsing 및 확장자 허용여부 점검 후 파일 시스템에 저장
for (MultipartFile file : files) {
orginFileName = file.getOriginalFilename();
log.debug("orginFileName is {}", orginFileName);
if (StringUtil.isEmpty(orginFileName)) {
continue;
}
//파일명, mimetype 검사
if (!isSanitizeFileName(file)) {
throw new WnbtRestException("허용되지 않은 파일명입니다.");
}
//확장자검사
String orgFileNm = FilenameUtils.getExtension(orginFileName);
if(orgFileNm != null) {
fileExt = orgFileNm.toUpperCase();
}
if(!StringUtil.isEmpty(whiteListFileUploadExtensions) && !StringUtil.isEmpty(fileExt)) {
if(!whiteListFileUploadExtensions.contains("."+fileExt.toLowerCase())) {
throw new WnbtRestException("허용되지 않은 파일유형입니다.");
}
}else {
throw new WnbtRestException("지원하지 않는 파일확장자입니다.");
}
//파일 중복을 방지하기 위해 rename 처리 : prefix(shopCd) + ddhhmmssSSS + 영문대소숫자 (20자)
newName = RandomGenerator.genString(20, prefix+getTimeStamp());
size = file.getSize();
filePath = storePathString + File.separator + newName;
//MultipartFile 정보 parsing 결과 설정
fileMap = new HashMap<>();
fileMap.put("fileExt", fileExt);
fileMap.put("fileStreCours", storePathString); //저장경로
// byte를 KB로 변환하기 위한 로직 추가
if(StringUtil.isEmpty(size.toString())) {
fileMap.put("size", "");
} else {
fileMap.put("size", String.valueOf(Math.round(size/1024.0)));
}
fileMap.put("orginFileName", orginFileName);
fileMap.put("streFileNm", newName);
fileMap.put("filePath", filePath);
fileMap.put("multipartFile", file);
resultList.add(fileMap);
fileKey++;
}
//업로드된 파일 파일시스템에 저장
//확장자 점검 중 오류가 발생할 경우 불필요한 파일이 파일시스템에 남지않게 하기위해 점검 후 저장수행
transferFile(resultList);
log.debug("file upload result is {}", resultList);
} catch(WnbtRestException wre) {
throw new WnbtRestException(wre.getMessage());
} catch(Exception e) {
throw new WnbtRestException(e.getMessage());
}
return resultList;
}
/**
* 서버 파일에 대하여 다운로드를 처리한다.
* @param response
* @param streFileNm
* @param orignFileNm
* @throws Exception
*/
public void downFile(HttpServletResponse response, String streFileNm, String orignFileNm) throws Exception {
downFile(response, streFileNm, orignFileNm, "application/x-msdownload");
}
/**
* 서버 파일에 대하여 다운로드를 처리한다.
* @param response
* @param streFileNm
* @param orignFileNm
* @param mimetype
* @throws Exception
*/
public void downFile(HttpServletResponse response, String streFileNm, String orignFileNm, String mimetype) throws Exception {
String downFileName = filePathBlackList(streFileNm);
String orgFileName = orignFileNm;
File file = new File(downFileName);
if (!file.exists()) {
throw new FileNotFoundException(downFileName);
}
if (!file.isFile()) {
throw new FileNotFoundException(downFileName);
}
int fSize = (int) file.length();
if (fSize > 0) {
// BufferedInputStream in = null;
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file)) ) {
// in = new BufferedInputStream(new FileInputStream(file));
response.setContentType(mimetype);
response.setHeader("Content-Disposition:", "attachment; filename=" + orgFileName);
response.setContentLength(fSize);
FileCopyUtils.copy(in, response.getOutputStream());
} finally {
// ResourceCloseHelper.close(in);
}
// response.getOutputStream().flush();
// response.getOutputStream().close();
}
}
/**
* 서버 파일에 대하여 view를 처리한다.
* @param response
* @param serverSubPath
* @param physicalName
* @param orginalName
* @param mimeTypeParam
* @throws Exception
*/
public void viewFile(HttpServletResponse response,
String serverSubPath,
String physicalName,
String orginalName,
String mimeTypeParam) throws Exception {
String mimeType = mimeTypeParam;
String downFileName = serverSubPath + File.separator + physicalName;
log.debug("downFileName ========== {}", downFileName);
File file = new File(filePathBlackList(downFileName));
if (!file.exists()) {
throw new FileNotFoundException(downFileName);
}
if (!file.isFile()) {
throw new FileNotFoundException(downFileName);
}
byte[] b = new byte[8192];
if (mimeType == null) {
mimeType = "application/octet-stream;";
}
response.setContentType(removeCRLF(mimeType));
response.setHeader("Content-Disposition", "filename="+orginalName+";");
// BufferedInputStream fin = null;
// BufferedOutputStream outs = null;
try (
BufferedInputStream fin = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream outs = new BufferedOutputStream(response.getOutputStream());
) {
// fin = new BufferedInputStream(new FileInputStream(file));
// outs = new BufferedOutputStream(response.getOutputStream());
int read = 0;
while ((read = fin.read(b)) != -1) {
outs.write(b, 0, read);
}
} finally {
// ResourceCloseHelper.close(outs, fin);
}
}
/**
* 업로드된 파일 파일시스템에 저장한다.
* @param parseReulstList MultipartFile정보를 parsing한 결과 목록
* @throws Exception
*/
private static void transferFile(List<Map<String, Object>> parseReulstList) throws Exception {
MultipartFile file;
for(Map<String, Object> tempMap : parseReulstList) {
file = (MultipartFile) tempMap.get("multipartFile");
if(file != null && !StringUtil.isEmpty(StringUtil.nullConvert(tempMap.get("filePath")))) {
Path fileDirectory = Paths.get((String) tempMap.get("filePath")).toAbsolutePath().normalize();
file.transferTo(new File(filePathBlackList(StringUtil.nullConvert(fileDirectory+"."+tempMap.get("fileExt")))));
//파일시스템 저장한 multipartFile은 parsing결과에서 삭제
tempMap.remove("multipartFile");
}
}
}
/**
* rename시 필요한 시간기반의 패턴정보 생성
* @return String 시간기반의 패턴정보
*/
private static String getTimeStamp() {
String rtnStr = null;
// 문자열로 변환하기 위한 패턴 설정(연도-월-일 시:분:초:초(자정이후 초))
String pattern = "ddhhmmssSSS"; //"yyyyMMddhhmmssSSS";
SimpleDateFormat sdfCurrent = new SimpleDateFormat(pattern, Locale.KOREA);
Timestamp ts = new Timestamp(System.currentTimeMillis());
rtnStr = sdfCurrent.format(ts.getTime());
return rtnStr;
}
/**
* 업로드된 파일을 저장할 경로에 허용되지 않은 문자열 치환
* @param value 저장될 파일 경로 문자열
* @return String 치환된 경로 문자열
*/
public static String filePathBlackList(String value) {
String returnValue = value;
if (returnValue == null || returnValue.trim().equals("")) {
return "";
}
returnValue = returnValue.replaceAll("\\.\\.", "");
return returnValue;
}
public static String removeCRLF(String parameter) {
return parameter.replaceAll("\r", "").replaceAll("\n", "");
}
/**
* 파일명, mimeType 검사
* @param fileName 저장될 원본파일명
* @return boolean 검사결과
*/
public static boolean isSanitizeFileName(MultipartFile file) {
boolean isPermission = false;
String orginFileName = file.getOriginalFilename();
log.debug("isSanitizeFileName orginFileName ::: {}",orginFileName);
// 파일명 확인
// 허용불가문자열 \ / : * ? " < > % |
String regex = "[:\\\\/%*?:|\"<>]";
if(Pattern.compile(regex).matcher(orginFileName).find()) {
log.debug("isFileNameVaild orginFileName_error ::: {}",orginFileName);
isPermission = false;
}else {
isPermission = true;
}
// 허용된 MIME 타입 검사 (ck_editor는 이미지만 업로드 됨)
try {
if(isPermission) {
String mimeType = new Tika().detect(file.getInputStream());
if (mimeType.startsWith("image")) {
isPermission = true;
}else {
isPermission = false;
}
}
} catch (IOException e) {
throw new WnbtRestException("업로드 파일 검증 중 파일 입출력 오류 발생");
}
return isPermission;
}
}

View File

@@ -0,0 +1,57 @@
package com.wb.domainserver.util.file;
import com.wb.domainserver.exception.WnbtRestException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.SecureRandom;
public class RandomGenerator {
private static final Logger logger = LoggerFactory.getLogger(RandomGenerator.class);
private static SecureRandom random = new SecureRandom();
private static String englishLower = "abcdefghijklmnopqrstuvwxyz";
private static String englishUpper = englishLower.toUpperCase();
private static String number = "0123456789";
private static String seed = englishLower + englishUpper + number;
private RandomGenerator() {
try {
throw new IllegalStateException("Utility class");
}catch(WnbtRestException wre) {
throw new WnbtRestException(wre.getMessage());
} catch(Exception e) {
logger.error("RandomGenerator 클래스는 생성자를 사용하여 초기화할 수 없습니다.");
}
}
public static String genString(int length, String prefix) {
try {
if(length < 1) throw new IllegalArgumentException("Length must be a positive number.");
} catch(WnbtRestException wre) {
throw new WnbtRestException(wre.getMessage());
} catch(Exception e) {
logger.error("파라미터 오류 ::: 길이는 최소한 0 보다 커야 합니다.");
}
StringBuilder sb = new StringBuilder(length);
int prefixLength = prefix.length();
for (int i = 0; i < length - prefixLength; i++) {
sb.append( seed.charAt(random.nextInt(seed.length())));
}
return prefix + sb.toString();
}
public static String genNumber(int length) {
try {
if(length < 1) throw new IllegalArgumentException("Length must be a positive number.");
} catch(WnbtRestException wre) {
throw new WnbtRestException(wre.getMessage());
} catch(Exception e) {
logger.error("파라미터 오류 ::: 길이는 최소한 0 보다 커야 합니다.");
}
StringBuilder sb = new StringBuilder(length);
for(int i = 0;i<length; i++) {
sb.append(number.charAt(random.nextInt(number.length())));
}
return sb.toString();
}
}

View File

@@ -0,0 +1,223 @@
package com.wb.domainserver.util.file.controller;
import com.wb.domainserver.domain.gcone.common.service.BOCommonService;
import com.wb.domainserver.domain.gcone.common.vo.BOCommonVO;
import com.wb.domainserver.exception.WnbtRestException;
import com.wb.domainserver.exception.code.ErrorCode;
import com.wb.domainserver.response.WnbtWebClientResponseHandler;
import com.wb.domainserver.security.authorization.annotation.AuthPolicy;
import com.wb.domainserver.security.authorization.annotation.Policy;
import com.wb.domainserver.util.communicate.SendToResrc;
import com.wb.domainserver.util.file.FileMngUtil;
import com.wb.domainserver.util.file.service.FileStorageService;
import com.wb.domainserver.util.file.vo.FileStorageProperties;
import com.wb.domainserver.util.string.StringUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.util.WebUtils;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@Slf4j
@Controller
@RequestMapping("/mngr/file")
public class FileController {
@Autowired
WnbtWebClientResponseHandler restResponseHandler;
@Autowired
private SendToResrc sendToResrc;
@Autowired
private FileStorageService filestore;
@Autowired
private FileStorageProperties fileStorageProperties;
@Autowired
private FileMngUtil fileMngUtil;
@Autowired
private BOCommonService boCommonService;
@Value("${sopmalfo.common.fileupload.cdnurl}")
private String cdnUrl;
@Value("${sopmalfo.common.fileupload.uploaddirs.web}")
private String uploadFilePath;
@Value("${sopmalfo.common.fileupload.extensions.images}")
private String whiteListFileUploadExtensions;
//파일업로드는
//filestore.fileUpload(request) 바로 실행함
// 파일 다운로드
@ResponseBody
@Policy(AuthPolicy.RESTRICTED)
@RequestMapping("/fileDownload")
public ResponseEntity<Resource> downloadFiles(HttpServletRequest request) {
String sopCd = request.getParameter("sopCd");
String menuGb = request.getParameter("menuGb");
String fileKey = request.getParameter("fileKey");
BOCommonVO vo = new BOCommonVO();
vo.setShopCd(sopCd);
vo.setMenuGb(menuGb);
vo.setFileSeq(fileKey);
// 각 구분자별 이미지관련정보 삭제 및 경로조회
Map<String, Object> message = new HashMap<>();
message.put("fileInfo", boCommonService.selectImgPath(vo));
Map<String, Object> fileInfoMap = (Map<String, Object>) message.get("fileInfo");
if(fileInfoMap != null) {
log.debug("fileFullPath :::: {}",fileInfoMap.get("fileFullPath"));
}
//파일절대경로 조회
Resource resource = filestore.loadFileAsResource(fileInfoMap);
String contentType = "application/octet-stream";
String fileName = "";
if(fileInfoMap != null) {
fileName = (String)fileInfoMap.get("orginlFilNm");//orgFileId; //원본파일명
}
log.debug("orgFileId {} ",fileName);
String headerValue = "";
if(fileName != null) {
headerValue = "attachment; filename=\"" + new String( fileName.getBytes(StandardCharsets.UTF_8),StandardCharsets.ISO_8859_1) + "\"";
}
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION, headerValue)
.body(resource);
}
// 파일 삭제
@ResponseBody
@Policy(AuthPolicy.RESTRICTED)
// @PostMapping(path = "/deleteUploadedFile/{sopCd}/{menuGb}/{fileKey}/ajax")
// public ResponseEntity<String> deleteUploadedFiles(@PathVariable String sopCd, @PathVariable String menuGb
// , @PathVariable String fileKey, HttpServletRequest request) {
@RequestMapping("/deleteUploadedFile")
public ResponseEntity<String> deleteUploadedFiles(HttpServletRequest request) {
String sopCd = request.getParameter("sopCd");
String menuGb = request.getParameter("menuGb");
String fileKey = request.getParameter("fileKey");
log.debug(" [파일 삭제] FileVo sopCd : {}",sopCd + " :menuGb: " + menuGb + " :fileKey: " + fileKey);
//게시글첨부파일고유번호, 쇼핑몰코드 - DB조회로 경로 알아옴.
BOCommonVO vo = new BOCommonVO();
vo.setShopCd(sopCd);
vo.setMenuGb(menuGb);
vo.setFileSeq(fileKey);
// 각 구분자별 이미지관련정보 삭제 및 경로조회
Map<String, Object> message = new HashMap<>();
message = boCommonService.deleteFileProcess(vo);
String result = (String)message.get("result");
log.debug("파일삭제 return::::::::{}",result);
return ResponseEntity.ok().body(result);
}
/**
* CK에디터로 업로드된 이미지 파일 처리
* @param request
* @return
*/
@Policy(AuthPolicy.PUBLIC)
@RequestMapping(value = "/ckeditorFileUpload", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<?> fileUpload(HttpServletRequest request) {
Map<String, List<Map<String, Object>>> ulpladFileMap = new HashMap<>();
Map<String, Object> resultMap = new HashMap<>();
MultipartHttpServletRequest mptRequest = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
String shopCd = request.getParameter("shopCd");
String subFolder = "";
if (mptRequest != null) {
//저장경로 생성 : /data/gcone/webFile/shop_cd/editor/YYYYMM
subFolder = shopCd+"/editor"+fileStorageProperties.getDateDir("yyyyMM", false);
MultiValueMap<String, MultipartFile> files = mptRequest.getMultiFileMap();
Iterator<String> fInputs = files.keySet().iterator();
while (fInputs.hasNext()) {
String key = fInputs.next();
try {
ulpladFileMap.put(key, fileMngUtil.parseFileInf(files.get(key), shopCd, uploadFilePath+"/"+subFolder , whiteListFileUploadExtensions));
} catch (WnbtRestException wre){
throw new WnbtRestException(wre.getMessage());
} catch (Exception e) {
throw new WnbtRestException(ErrorCode.BAD_REQUEST_ERROR,"파일 업로드에 실패했습니다."+e.getMessage());
}
}
}
if(ulpladFileMap.get("upload") != null && !ulpladFileMap.get("upload").isEmpty()) {
resultMap.put("uploaded", true);
//resultMap.put("url", "/file/ckeditor/image/fileView?item01="+subFolder+"/"+ulpladFileMap.get("upload").get(0).get("streFileNm")+"."+ulpladFileMap.get("upload").get(0).get("fileExt"));
//resultMap.put("url", "/file/ckeditorFileView?item01="+subFolder+"/"+ulpladFileMap.get("upload").get(0).get("streFileNm")+"."+ulpladFileMap.get("upload").get(0).get("fileExt"));
resultMap.put("url", cdnUrl+"/"+subFolder+"/"+ulpladFileMap.get("upload").get(0).get("streFileNm")+"."+ulpladFileMap.get("upload").get(0).get("fileExt"));
} else {
resultMap.put("uploaded", false);
resultMap.put("url", "");
}
log.debug("ckeditor - fileUpload ==========={}",resultMap.get("url"));
return ResponseEntity.status(HttpStatus.OK).body(resultMap);
}
/**
* CK에디터로 업로드된 이미지 view 처리
* @param request
* @param response
*/
@Policy(AuthPolicy.PUBLIC)
@RequestMapping("/ckeditorFileView")
public void fileUpload(HttpServletRequest request, HttpServletResponse response, String uploadFilePath1) {
String item01 = request.getParameter("item01");
if(uploadFilePath1 == null) uploadFilePath1 = uploadFilePath;
try {
if(!StringUtil.isEmpty(item01)) {
//response, 서버경로중 고정경로, 변형경로+시스템파일명, orginalName, mimeTypeParam
fileMngUtil.viewFile(response, uploadFilePath1, item01, "", null);
}
} catch (WnbtRestException wre){
throw new WnbtRestException(wre.getMessage());
} catch(Exception e) {
throw new WnbtRestException("에디터 업로드 이미지 조회 중 오류가 발생하였습니다.");
}
}
}

View File

@@ -0,0 +1,263 @@
package com.wb.domainserver.util.file.service;//package com.wb.domainserver.util.file.service;
//
//import java.io.BufferedInputStream;
//import java.io.BufferedOutputStream;
//import java.io.File;
//import java.io.FileInputStream;
//import java.io.FileOutputStream;
//import java.io.UnsupportedEncodingException;
//import java.lang.reflect.Field;
//import java.text.SimpleDateFormat;
//import java.util.ArrayList;
//import java.util.Date;
//import java.util.List;
//import java.util.Locale;
//import java.util.Map;
//import java.util.zip.ZipEntry;
//import java.util.zip.ZipOutputStream;
//
//import javax.servlet.ServletOutputStream;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//
//import org.apache.poi.ss.usermodel.Cell;
//import org.apache.poi.ss.usermodel.CellStyle;
//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.celebpay.exception.CelebpayException;
//import org.celebpay.model.common.file.ExcelFile;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.util.StringUtils;
//import org.springframework.web.servlet.view.document.AbstractXlsxView;
//
//public class ExcelDownloadViewSvc extends AbstractXlsxView {
// private static final Logger logger = LoggerFactory.getLogger(ExcelDownloadViewSvc.class);
// private static final String local_path = "D:/temp/";
// private static final String server_path = "/temp/";
//
// @Override
// protected void buildExcelDocument(Map modelMap, Workbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception {
// List listSet = (List)modelMap.get("listSet");
// List listExcel = (List) modelMap.get("list");
// List<String> header = (List) modelMap.get("header");
// List fileName = (List) modelMap.get("fileName");
//
// String excelName = "";
//
// if(listSet == null) {
// String sCurTime = null;
// sCurTime = new SimpleDateFormat("yyyyMMdd", Locale.KOREA).format(new Date());
// excelName = sCurTime + "_" + (StringUtils.isEmpty(fileName) ? "엑셀파일" : fileName) + ".xlsx";
//
// Sheet worksheet = null;
// Row row = null;
// Cell cell = null;
//
// CellStyle style = workbook.createCellStyle(); // 셀 스타일을 위한 변수
// style.setVerticalAlignment(CellStyle.VERTICAL_TOP); // 글 위치를 상단으로 설정
// style.setAlignment(CellStyle.ALIGN_CENTER); // 글 위치를 중앙으로 설정
// style.setWrapText(true);
//
// //새로운 Sheet를 생성
// worksheet = workbook.createSheet("sheet1");
//
// //타이틀 ROW 생성
// row = worksheet.createRow(0);
// for(int i=0; i<header.size(); i++) {
// cell = row.createCell(i);
// cell.setCellValue(header.get(i));
// cell.setCellStyle(style);
// }
//
// for(int i=0; i<listExcel.size(); i++) {
// row = worksheet.createRow(i+1);
// ExcelFile colSet = (ExcelFile)listExcel.get(i);
// for(int j=0; j<header.size(); j++) {
// cell = row.createCell(j);
//
// Field field = colSet.getClass().getDeclaredField("col"+j);
// field.setAccessible(true);
// String v = (String)field.get(colSet);
//
// cell.setCellValue(v);
// cell.setCellStyle(style);
// // worksheet.autoSizeColumn(j);
// worksheet.setColumnWidth(j, StringUtils.isEmpty(header.get(j)) ? 1200 : header.get(j).length() * 1200);
// }
// }
//
// try {
// response.setHeader("Content-Disposition", "attachement; filename=\""+java.net.URLEncoder.encode(excelName, "UTF-8")+"\";charset=\"UTF-8\"");
// }catch(UnsupportedEncodingException e) {
// throw new CelebpayException("엑셀 다운로드 도중 인코딩 오류 발생"+e);
// }
//
// }else {
// List<File> fileSet = new ArrayList<>();
//
// String path = "";
// if(request.getRequestURL().indexOf("http://localhost:8090") > -1) {
// path = local_path + new SimpleDateFormat("yyyyMMddHHmmss", Locale.KOREA).format(new Date()) + "/";
// }else {
// path = server_path + new SimpleDateFormat("yyyyMMddHHmmss", Locale.KOREA).format(new Date()) + "/";
// }
//
// File Folder = new File(path);
//
// if(!Folder.exists()) {
// Folder.setExecutable(false, true);
// Folder.setReadable(true);
// Folder.setWritable(false, true);
// try {
// Folder.mkdirs();
// }catch(Exception e) {
// throw new CelebpayException("엑셀 파일 압축을 위한 임시 폴더 생성 중 오류"+e);
// }
// }
//
// for(int idx=0; idx<listSet.size(); idx++) {
// listExcel = (List)listSet.get(idx);
//
// String sCurTime = null;
// sCurTime = new SimpleDateFormat("yyyyMMdd", Locale.KOREA).format(new Date());
// excelName = sCurTime + "_엑셀다운로드"+idx+".xlsx";
// Workbook book = new XSSFWorkbook();
// Sheet worksheet = null;
// Row row = null;
// Cell cell = null;
//
// CellStyle style = book.createCellStyle(); // 셀 스타일을 위한 변수
// style.setVerticalAlignment(CellStyle.VERTICAL_TOP); // 글 위치를 상단으로 설정
// style.setAlignment(CellStyle.ALIGN_CENTER); // 글 위치를 중앙으로 설정
// style.setWrapText(true);
//
// //새로운 Sheet를 생성
// worksheet = book.createSheet("sheet1");
//
// //타이틀 ROW 생성
// row = worksheet.createRow(0);
// for(int i=0; i<header.size(); i++) {
// cell = row.createCell(i);
// cell.setCellValue(header.get(i));
// cell.setCellStyle(style);
// }
//
// for(int i=0; i<listExcel.size(); i++) {
// row = worksheet.createRow(i+1);
// ExcelFile colSet = (ExcelFile)listExcel.get(i);
// for(int j=0; j<header.size(); j++) {
// cell = row.createCell(j);
//
// Field field = colSet.getClass().getDeclaredField("col"+j);
// field.setAccessible(true);
// String v = (String)field.get(colSet);
//
// cell.setCellValue(v);
// cell.setCellStyle(style);
// // worksheet.autoSizeColumn(j);
// worksheet.setColumnWidth(j, StringUtils.isEmpty(header.get(j)) ? 1200 : header.get(j).length() * 1200);
// }
// }
//
// File file = new File(path + excelName);
// FileOutputStream fos = null;
// fos = new FileOutputStream(file);
// book.write(fos);
// fileSet.add(file);
//
// if(book != null)book.close();
// }
// compressZip(fileSet, path, response);
// }
// }
//
// private void compressZip(List<File> fileSet, String path, HttpServletResponse response) {
// ZipOutputStream zout = null;
// String zipName = "엑셀파일.zip";
// String tempPath = "";
//
// if(fileSet.size()>0) {
// try {
// tempPath = path;
//
// zout = new ZipOutputStream(new FileOutputStream(tempPath + zipName));
// byte[] buffer = new byte[1024];
// FileInputStream in = null;
//
// try {
// for(int k=0; k<fileSet.size(); k++) {
// in= new FileInputStream(fileSet.get(k));
// zout.putNextEntry(new ZipEntry(fileSet.get(k).getName()));
// int len;
// while((len=in.read(buffer))>0) {
// zout.write(buffer, 0, len);
// }
//
// zout.closeEntry();
// }
// }catch(Exception e) {
// throw new CelebpayException("엑셀 파일 압축 도중 오류 발생"+e);
// }finally {
// in.close();
// }
//
// zout.close();
//
// response.setContentType("application/zip");
// response.addHeader("Content-Disposition", "attachement; filename=\""+java.net.URLEncoder.encode(zipName, "UTF-8")+"\";charset=\"UTF-8\"");
//
// FileInputStream fis = new FileInputStream(tempPath+zipName);
// BufferedInputStream bis = new BufferedInputStream(fis);
// ServletOutputStream so = response.getOutputStream();
// BufferedOutputStream bos = new BufferedOutputStream(so);
//
// try {
// int n = 0;
// while((n=bis.read(buffer))>0) {
// bos.write(buffer, 0, n);
// bos.flush();
// }
// }catch(Exception e) {
// throw new CelebpayException("엑셀 파일 압축 도중 오류 발생"+e);
// }finally {
// if(bos != null) bos.close();
// if(bis != null) bis.close();
// if(so != null) so.close();
// if(fis != null) fis.close();
// }
//
// }catch(Exception e) {
// throw new CelebpayException("엑셀 파일 압축 도중 오류 발생"+e);
// }finally {
// if(zout != null) {
// zout = null;
// }
//
// deleteTempFolder(path);
// }
// }
// }
//
// private void deleteTempFolder(String path) {
// File folder = new File(path);
//
// try {
// while(folder.exists()) {
// File[] folder_list = folder.listFiles();
// for(File f: folder_list) {
// f.delete();
// }
// if(folder_list.length == 0 && folder.isDirectory()) {
// folder.delete();
// }
// }
// }catch(Exception e) {
// throw new CelebpayException("임시 디렉토리 삭제 중 오류 발생"+e);
// }
// }
//
//
//}

View File

@@ -0,0 +1,718 @@
package com.wb.domainserver.util.file.service;
import com.wb.domainserver.exception.FileStorageException;
import com.wb.domainserver.exception.WnbtRestException;
import com.wb.domainserver.util.file.RandomGenerator;
import com.wb.domainserver.util.file.vo.FileStorageProperties;
import com.wb.domainserver.util.file.vo.FileVo;
import com.wb.domainserver.util.file.vo.UploadFile;
import com.wb.domainserver.util.string.StringUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.tika.Tika;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import org.springframework.web.util.WebUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Slf4j
@Service
public class FileStorageService {
private final Path docFileStorageLocation;
private final Path imgFileStorageLocation;
private final Path pharFileStorageLocation;
private final Path rtrnFileStorageLocation;
@Autowired
private FileStorageProperties fileStorageProperties;
@Value("${sopmalfo.common.fileupload.extensions.images}")
private String whiteListFileUploadExtensions;
@Autowired
public FileStorageService(FileStorageProperties fileStorageProperties) {
this.docFileStorageLocation = Paths.get(fileStorageProperties.getDocUploadDir()).toAbsolutePath().normalize();
this.imgFileStorageLocation = Paths.get(fileStorageProperties.getImgUploadDir()).toAbsolutePath().normalize();
this.pharFileStorageLocation = Paths.get(fileStorageProperties.getPharUploadDir()).toAbsolutePath().normalize();
this.rtrnFileStorageLocation = Paths.get(fileStorageProperties.getRtrnUploadDir()).toAbsolutePath().normalize();
}
public Path getDocFileStorageLocation() {
return this.docFileStorageLocation;
}
public Path getImgFileStorageLocation() {
return this.imgFileStorageLocation;
}
public Path getPharFileStorageLocation() { return this.pharFileStorageLocation; }
public Path getRtrnFileStorageLocation() { return this.rtrnFileStorageLocation; }
/**
* 파일 업로드 서비스
* @param request
* @return
*/
public List<HashMap<String, Object>> fileUpload(HttpServletRequest request) {
log.debug("====FileStorageService fileUpload");
List<HashMap<String, Object>> ulpladFileMap = new ArrayList<HashMap<String, Object>>();
MultipartHttpServletRequest mptRequest = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
//구분자 받아와야 함. 이 구분자로 파일저장 경로가 지정됨.
String shopCd = (String)request.getAttribute("shopCd");
String pathGubun = (String)request.getAttribute("pathGubun");
String subPathId = (String)request.getAttribute("subPathId");
String validExp = (String)request.getAttribute("validExp");
subPathId = (subPathId == null || subPathId.equals(""))? "" : "/"+subPathId;
if (mptRequest != null && mptRequest.getFiles("files").size()>0) {
List<MultipartFile> fileList = mptRequest.getFiles("files");
log.debug("====fileList:{}",fileList);
MultipartFile[] filesparam = fileList.toArray(new MultipartFile[0]);
UploadFile params = new UploadFile();
params.setShopCd(shopCd);
params.setPathGubun(pathGubun);
params.setSubPathId(subPathId);
params.setValidExp(validExp);
//파일저장 메소드 호출
ulpladFileMap = getFilesUpload(params,filesparam);
}
return ulpladFileMap;
}
/**
* 파일 저장처리 (퍼미션확인, 경로생성, 저장)
* @param params
* @param files
* @return
*/
public List<HashMap<String, Object>> getFilesUpload(UploadFile params,MultipartFile[] files) {
List<HashMap<String, Object>> fileStoreResult = new ArrayList<HashMap<String, Object>>();
try {
log.debug("files ::파일객체 퍼미션 확인: "+files);
List<MultipartFile> allowedFiles = new ArrayList<>();
log.debug("files ::파일객체 퍼미션 확인: "+params);
//파일확장자 검증 - 파일명, 마임타입, 확장자 검증 : 게시판일반첨부파일 - 나머지 첨부파일(이미지)
String validExp = params.getValidExp();
if(params.getPathGubun().equals("BDFL")) {
allowedFiles = Arrays.asList(files)
.stream()
.filter(t->isPermissionFileMimeType(t,validExp))
.collect(Collectors.toList());
}else {
if(StringUtil.isEmpty(validExp)){
allowedFiles = Arrays.asList(files)
.stream()
.filter(t->isPermissionImgMimeType(t))
.collect(Collectors.toList());
}else{
allowedFiles = Arrays.asList(files)
.stream()
.filter(t->isPermissionFileMimeType(t,validExp))
.collect(Collectors.toList());
}
}
log.debug("files ::파일경로 생성: "+allowedFiles);
if(!allowedFiles.isEmpty()) {
log.debug("allowedFiles if : "+allowedFiles);
String uploadFilePath = getUploadFilePath(params,"yyyyMM",false); //코드에 따라 저장경로를 생성함.
log.debug("getFilesUpload - UPLOADFILEPATH ::파일저장: "+uploadFilePath);
fileStoreResult = Arrays.asList(files)
.stream()
.map(file -> fileProcess(uploadFilePath, params, file))
.collect(Collectors.toList());
log.debug("getFilesUpload - FILESTORERESULT ::파일저장완료: "+fileStoreResult);
/* 파일데이터저장은 BO 단에서 처리 */
}else {
log.debug("allowedFiles else : ");
throw new WnbtRestException ("허용되지 않은 파일입니다.");
}
}catch (WnbtRestException wre){
throw new WnbtRestException(wre.getMessage());
} catch (Exception e) {
throw new WnbtRestException("파일 업로드시 오류 발생 ["+e.getMessage()+"]");
}
return fileStoreResult;
}
/**
* 파일에 대하여 서버저장을 하고 정보를 처리한다. (파일저장, download_url, content_type, file_size 정보셋팅)
* @param filePath 파일저장경로
* @param file MultipartFile
*/
public HashMap<String, Object> fileProcess(String filePath, UploadFile params, MultipartFile file){
HashMap<String, Object> param = new HashMap<>();
param.put("domainPath", filePath);
param.put("shopCd", params.getShopCd());
log.debug("fileProcess - String.DOMAINPATH ::: "+filePath);
//파일저장
HashMap<String, Object> fileMap = storeFile(file, param);
//파일 다운로드 url 생성 - 실제 큰 의미없는.....
String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/bo/file")
.path("/download/")
.path((String)fileMap.get("fileId"))
.toUriString();
fileMap.put("fileDownloadUri", fileDownloadUri);
fileMap.put("fileContentType", file.getContentType());
fileMap.put("fileSize", file.getSize());
return fileMap;
}
/**
* 파일 서버 저장
* @param file MultipartFile
* @param param 기타정보들
*/
public HashMap<String, Object> storeFile(MultipartFile file, HashMap<String, Object> param) {
String domainPath = (String)param.get("domainPath");
String prefix = (String)param.get("shopCd");
int thumbnailWidth = 500;
int thumbnailHeight = 500;
if(param.get("thumbnailWidth") != null && param.get("thumbnailHeight") != null) {
thumbnailWidth = (Integer)param.get("thumbnailWidth");
thumbnailHeight = (Integer)param.get("thumbnailHeight");
}
String originalFileName = StringUtils.cleanPath(file.getOriginalFilename()); //원본명
String ext = FilenameUtils.getExtension(file.getOriginalFilename()); //확장자
log.debug("storeFile - FILE_NAME ::: " + originalFileName);
log.debug("storeFile - FILE_EXT ::: " + ext);
try {
if(originalFileName.contains("..")) {
throw new WnbtRestException("허용되지 않은 파일입니다. "+ originalFileName);
}
String storeGubun = "";
String fileId = "";
Path targetLocation = null;
if(!"".equals(domainPath) && domainPath !=null) {
if(domainPath.indexOf("/goods/") > 0) {
storeGubun = "GDIG";
}
}else {
throw new WnbtRestException("파일 업로드 경로가 존재하지 않습니다.");
}
//물리적 파일명 생성 : prefix(shopCd) + ddhhmmssSSS + 영문대소숫자 (20자)
fileId = RandomGenerator.genString(20, prefix+getTimeStamp())+'.'+ext;
log.debug("storeFile - 물리파일명 ::: " + fileId);
Path fileDirectory = Paths.get(domainPath).toAbsolutePath().normalize(); //저장경로를 파일시스템의 루트부터 시작하는 절대경로롤 바꿈.
log.debug("storeFile - fileDirectory ::: " + fileDirectory);
Files.createDirectories(fileDirectory); //디렉토리 생성
targetLocation = fileDirectory.resolve(fileId); //경로결합 - 절대경로/물리적파일명
log.debug("PATH.TARGET_LOCATION ::: " + targetLocation);
FileVo thumbnail = new FileVo();
FileVo listimg = new FileVo();
if(storeGubun.equals("GDIG")) { //상품일 경우
//1. 사이즈 줄임 500*500
storeResize(file, fileId, targetLocation, thumbnailWidth, thumbnailHeight);
//2. 리스트이미지 만들기 300*300
listimg = storeThumbnail(file, fileId, "_list", domainPath, 300, 300);
//3. 썸네일 만들기 100*100
thumbnail = storeThumbnail(file, fileId, "_thumb", domainPath, 100, 100);
}else {
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
}
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("fileName", originalFileName);
map.put("fileExt", ext);
map.put("fileId", fileId);
map.put("listImg", listimg);
map.put("thumbNail", thumbnail);
//파일경로를 쇼핑몰코드부터 DB에 저장하기로 함.
String docRoot = docFileStorageLocation.toString(); //일반첨부파일들
String webRoot = imgFileStorageLocation.toString(); //웹서버첨부파일 (이미지등)
domainPath = fileDirectory.toString().replace(docRoot, "").replace(webRoot, "");
map.put("filePath", domainPath);
log.debug("[쇼핑몰코드형이후 domainPath] :::{}",domainPath);
return map;
}catch(IOException ex) {
throw new WnbtRestException(originalFileName+" 파일 저장 중 오류가 발생하였습니다. ", ex);
}
}
/**
* 이미지 크기 변경
*/
public void storeResize(MultipartFile file, String fileId, Path targetLocation, int imgWidth, int imgHeight) {
try(ByteArrayOutputStream os = new ByteArrayOutputStream();) {
log.debug("TARGET_LOCATION ::: " + targetLocation);
try {
BufferedImage image = null;
if(file.getInputStream() != null) {
image = ImageIO.read(file.getInputStream());
}
int destWidth = 0, destHeight = 0;
int posX = 0, posY = 0;
destWidth = imgWidth;
destHeight = imgHeight;
Image thumbnail = null;
if(image != null) {
thumbnail = image.getScaledInstance(destWidth, destHeight, Image.SCALE_SMOOTH);
}
BufferedImage convertImage = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);
convertImage.getGraphics().drawImage(thumbnail, posX, posY, null);
String ext = FilenameUtils.getExtension(file.getOriginalFilename());
ImageIO.write(convertImage, ext, os);
}catch (WnbtRestException wre){
throw new WnbtRestException(wre.getMessage());
} catch(Exception e) {
throw new WnbtRestException("이미지 크기 변경 중 오류가 발생하였습니다.");
// e.getMessage();
// e.printStackTrace();
}
try(InputStream is = new ByteArrayInputStream(os.toByteArray());){
Files.copy(is, targetLocation, StandardCopyOption.REPLACE_EXISTING);
}catch(IOException e) {
throw new WnbtRestException("파일 리사이즈 저장 중 오류가 발생하였습니다.");
}
}catch(IOException ex) {
throw new WnbtRestException("파일 리사이즈 저장 중 오류가 발생하였습니다.");
}
}
/**
* 썸네일이미지 저장
*/
public FileVo storeThumbnail(MultipartFile file, String fileId, String addFileId, String domainPath, int thumbnailWidth, int thumbnailHeight) {
FileVo thumbnail_file = new FileVo();
String ext = FilenameUtils.getExtension(file.getOriginalFilename());
String thumbAddId = "_thumb";
if(addFileId != null && !addFileId.equals("")) thumbAddId = addFileId;
String thumbNailId = fileId.substring(0, fileId.indexOf("."))+thumbAddId+"."+ext;
try(ByteArrayOutputStream os = new ByteArrayOutputStream();) {
Path targetLocation = null;
if("".equals(domainPath)) {
throw new FileStorageException("파일 업로드 경로가 존재하지 않습니다.");
}else {
Path fileDirectory = Paths.get(domainPath).toAbsolutePath().normalize();
Files.createDirectories(fileDirectory);
targetLocation = fileDirectory.resolve(thumbNailId);
}
log.debug("TARGET_LOCATION ::: " + targetLocation);
try {
BufferedImage image = null;
if(file.getInputStream() != null) {
image = ImageIO.read(file.getInputStream());
}
int destWidth = 0, destHeight = 0;
int posX = 0, posY = 0;
double ratio = 0.0;
destWidth = thumbnailWidth;
destHeight = thumbnailHeight;
Image thumbnail = null;
if(image != null) {
thumbnail = image.getScaledInstance(destWidth, destHeight, Image.SCALE_SMOOTH);
}
BufferedImage convertImage = new BufferedImage(thumbnailWidth, thumbnailHeight, BufferedImage.TYPE_INT_RGB);
convertImage.getGraphics().drawImage(thumbnail, posX, posY, null);
ImageIO.write(convertImage, ext, os);
}catch (WnbtRestException wre){
throw new WnbtRestException(wre.getMessage());
} catch(Exception e) {
throw new WnbtRestException("썸네일 파일 저장 중 오류가 발생하였습니다.");
}
try(InputStream is = new ByteArrayInputStream(os.toByteArray());){
Files.copy(is, targetLocation, StandardCopyOption.REPLACE_EXISTING);
thumbnail_file.setFilePath(domainPath);
thumbnail_file.setFileName(thumbNailId);
thumbnail_file.setDocName(thumbNailId);
thumbnail_file.setFileExt(ext);
thumbnail_file.setFileType("21");
thumbnail_file.setFileSize(Integer.toString(os.size()));
}catch(IOException e) {
throw new WnbtRestException("썸네일 파일 저장 중 오류가 발생하였습니다.");
}
}catch(IOException ex) {
throw new WnbtRestException("썸네일 파일 저장 중 오류가 발생하였습니다.");
}
log.debug("thumbnail_file ::: filePath ::: "+thumbnail_file.getFilePath());
log.debug("thumbnail_file ::: fileName ::: "+thumbnail_file.getFileName());
return thumbnail_file;
}
/**
* combineFilePath 에 지정된 경로에 저장이 됨
* @param lnkMasterId 저장위치 구분자
* @param subPath1 구분자에 따른 하위폴더명
* @return 저장경로
*/
public String getUploadFilePath(UploadFile param) {
return combineFilePath(param);
}
/**
* combineFilePath에 지정된 경로에 아래에 날짜폴더 만들어서 저장이 됨
* @param lnkMasterId 저장위치 구분자
* @param subPath1 구분자에 따른 내 하위폴더명
* @param dateDirPattern 날짜폴더생성 패턴 (yyyy / yyyyMM / yyyyMMdd)
* @param dateDirSeperate 날짜폴더생성시 년/월/일 형태의 구분 여부
* @return 저장경로
*/
public String getUploadFilePath(UploadFile param, String dateDirPattern, boolean dateDirSeperate) {
String path = combineFilePath(param);
if(!"".equals(dateDirPattern) && dateDirPattern != null) {
path = path + fileStorageProperties.getDateDir(dateDirPattern, dateDirSeperate);
}
return path;
}
/**
* 구분자에 따라 저장 경로를 설정한다.
* @param lnkMasterId 구분자
* @param subPath1 구분자에 따른 내 하위폴더명
* @return
*/
private String combineFilePath(UploadFile param) {
String docRoot = docFileStorageLocation.toString(); //일반첨부파일들
String webRoot = imgFileStorageLocation.toString(); //웹서버첨부파일 (이미지등)
String pharRoot = pharFileStorageLocation.toString(); //약국첨부파일들 (사업자등록증, 약사면허증, 계약서)
String rtrnRoot = rtrnFileStorageLocation.toString(); //반품이미지
String path = "";
/* 경로규칙
* 게시판 일반(BDFL): /docRoot/data/shop_cd/board/board_id/YYYYMM
* 게시판 이미지(BDIG): /webRoot/data/shop_cd/board/board_id/YYYYMM
* 상품 이미지(GDIG): /webRoot/data/shop_cd/goods/YYYYMM/ 기본파일명, 기본파일명_list(리스트파일), 기본파일명_view(썸네일파일) - 3가지 사이즈로 저장해야 함
* 회원 이미지(MBRI): /pharRoot/data/shop_cd/mbr/YYYYMM
* 모바일앱 이미지(APFL): /webRoot/shop_cd/app/YYYYMM
* 기타 이미지(ETCM): /webRoot/data/shop_cd/etc/YYYYMM
* 반품 이미지(RTRN): /rtrnRoot/data/shop_cd/mbr/YYYYMM
* 에디터 이미지: /webRoot/data/shop_cd/editor/YYYYMM (FileMngUtil.java 사용)
* */
String shopCd = param.getShopCd();
String lnkMasterId = param.getPathGubun();
String subPath = param.getSubPathId(); //게시판bbsid
if(!"".equals(lnkMasterId)&&lnkMasterId != null) {
if(lnkMasterId.startsWith("BDFL")) {
path = docRoot+"/"+shopCd+"/board"+subPath;
}else if(lnkMasterId.startsWith("BDIG")) {
path = webRoot+"/"+shopCd+"/board"+subPath;
}else if(lnkMasterId.startsWith("GDIG")) {
path = webRoot+"/"+shopCd+"/goods"+subPath;
}else if(lnkMasterId.startsWith("MBRI")) {
path = pharRoot+"/"+shopCd+"/mbr"+subPath;
}else if(lnkMasterId.startsWith("APFL")) {
path = webRoot+"/"+shopCd+"/app"+subPath;
}else if(lnkMasterId.startsWith("ETCM")) {
path = webRoot+"/"+shopCd+"/etc"+subPath;
}else if(lnkMasterId.startsWith("RTRN")){
path = rtrnRoot+"/"+shopCd+"/rtrn"+subPath;
}
} else {
path = path + subPath;
}
return path;
}
/* 절대경로 반환 */
public Resource loadFileAsResource(Map<String, Object> dataMap) {
try {
String path = null;
if(dataMap != null && dataMap.get("fileFullPath") != null) {
path = dataMap.get("fileFullPath").toString();
}
if(path != null && !path.equals("") && !path.equals("/")) {
/* *************************************
path는 DB경로. webroot , docroot 붙여줘야 함.
************************************* */
String fileDv = null;
if(dataMap.get("filDvCd") != null) {
fileDv = dataMap.get("filDvCd").toString();
}
if(fileDv != null) {
if(fileDv.equals("01")) {
path = imgFileStorageLocation + path;
}else if(fileDv.equals("02")) {
path = docFileStorageLocation + path;
}
}
Path filePath = Paths.get(path).toAbsolutePath().normalize();
log.debug("[파일DB경로 path] ::: "+path);
log.debug("[파일절대경로 filePath] ::: "+filePath);
Resource resource = new UrlResource(filePath.toUri());
if(resource.exists()) {
return resource;
}else {
throw new WnbtRestException("파일이 존재하지 않습니다.");
}
}else {
throw new WnbtRestException("파일이 존재하지 않습니다.");
}
}catch(MalformedURLException ex) {
throw new WnbtRestException("파일이 존재하지 않습니다.");
}
}
/**
* 파일명, 유효확장자, mimeType 검사
* @param file 저장될 파일
* @param validExp 유효한 확장자
* @return boolean 검사결과
*/
public boolean isPermissionFileMimeType(MultipartFile file, String validExp){
log.debug("isPermissionFileMimeType ::: 게시판 ");
boolean isPermission = false;
String orginFileName = file.getOriginalFilename();
// 1. 유효한 파일명 검사
if(orginFileName != null && isFileNameVaild(orginFileName)) {
isPermission = true;
log.debug("파일명 적합 ::: ");
//2. 허용확장자 검사 (DB 값 참조)
String fileExt = FilenameUtils.getExtension(orginFileName);
if(fileExt != null) {
fileExt = fileExt.toUpperCase();
}
log.debug("isPermissionFileMimeType fileExt ::: {}",fileExt);
log.debug("isPermissionFileMimeType validExp ::: {}",validExp);
if(!StringUtil.isEmpty(validExp) && !StringUtil.isEmpty(fileExt)) {
if(!(validExp).contains("."+fileExt.toLowerCase())) {
isPermission = false;
}
}else {
isPermission = false;
}
}
// 3. 허용된 MIME 타입 검사
if(isPermission) {
try {
InputStream inputStream;
inputStream = file.getInputStream();
String mimeType = new Tika().detect(inputStream);
log.debug("MIME-TYPE ::: "+mimeType);
if(isAllowedMIMEType(mimeType)) {
isPermission = true;
}
}catch(IOException e) {
throw new WnbtRestException("업로드 파일 검증 중 파일 입출력 오류 발생");
}
}
return isPermission;
}
/**
* 파일명, 유효확장자, mimeType(이미지) 검사
* @param file 저장될 파일
* @return boolean 검사결과
*/
private boolean isPermissionImgMimeType(MultipartFile file) {
log.debug("isPermissionImgMimeType ::: 이미지 ");
boolean isPermission = false;
String orginFileName = file.getOriginalFilename();
// 1. 유효한 파일명 검사
if(orginFileName != null && isFileNameVaild(orginFileName)) {
isPermission = true;
log.debug("파일명 적합 ::: ");
//2. 허용확장자 검사 (.yml 파일 참조)
String fileExt = FilenameUtils.getExtension(orginFileName);
if(fileExt != null) {
fileExt = fileExt.toUpperCase();
}
log.debug("isPermissionImgMimeType fileExt ::: {}",fileExt);
log.debug("isPermissionImgMimeType 허용확장자 ::: {}",whiteListFileUploadExtensions);
if(!StringUtil.isEmpty(whiteListFileUploadExtensions) && !StringUtil.isEmpty(fileExt)) {
if(!(whiteListFileUploadExtensions).contains("."+fileExt.toLowerCase())) {
isPermission = false;
}
}else {
isPermission = false;
}
}
log.debug("isPermission ::: 1 "+isPermission);
// 3. 허용된 MIME 타입 검사
if(isPermission) {
try {
String mimeType = new Tika().detect(file.getInputStream());
if (mimeType.startsWith("image")) {
isPermission = true;
}else {
isPermission = false;
}
} catch (IOException e) {
throw new WnbtRestException("업로드 파일 검증 중 파일 입출력 오류 발생");
}
}
log.debug("isPermission ::: 2 "+isPermission);
return isPermission;
}
private boolean isAllowedMIMEType(String mimeType) {
if (mimeType == null || mimeType.equals("")) return false;
String[] allowedMIMETypesEquals = {
"application/zip", // .zip
"application/pdf", // .pdf
"application/msword", // .doc, .dot
"application/x-hwp", "applicaion/haansofthwp", // .hwp
"application/x-tika-msoffice", // .docx
"application/x-tika-ooxml" // .xlsx, .pptx
};
for (int i=0; i<allowedMIMETypesEquals.length; i++) {
if (mimeType.equals(allowedMIMETypesEquals[i])) {
return true;
}
}
String[] allowedMIMETypesStartsWith = {
"image", // .png, .jpg, .jpeg, .gif, .bmp
"text", // .txt, .html 등
"application/vnd.ms-word", // .docx 등 워드 관련
"application/vnd.ms-excel", // .xls 등 엑셀 관련
"application/vnd.ms-powerpoint", // .ppt 등 파워포인트 관련
"application/vnd.openxmlformats-officedocument", // .docx, .dotx, .xlsx, .xltx, .pptx, .potx, .ppsx
"applicaion/vnd.hancom" // .hwp 관련
};
for (int i=0; i<allowedMIMETypesStartsWith.length; i++) {
if (mimeType.startsWith(allowedMIMETypesStartsWith[i])) {
return true;
}
}
return false;
}
private boolean isFileNameVaild(String orginFileName) {
// 허용불가문자열 \ / : * ? " < > % | .sh
String regex = "[:\\\\/%*?:|\"<>]|\\.sh";
log.debug("isFileNameVaild orginFileName ::: {}",orginFileName);
if(Pattern.compile(regex).matcher(orginFileName).find()) {
log.debug("isFileNameVaild orginFileName1111 ::: {}",orginFileName);
return false;
}
return true;
/* URL 디코딩
String decodedFileName = "";
decodedFileName = URLDecoder.decode(orginFileName, StandardCharsets.UTF_8);
log.debug("isFileNameVaild decodedFileName 1 ::: {}",decodedFileName);
decodedFileName = decodedFileName.substring(0,decodedFileName.lastIndexOf("."));
log.debug("isFileNameVaild decodedFileName 2 ::: {}",decodedFileName);
return !Pattern.compile(regex).matcher(decodedFileName).find();
*/
}
private String getTimeStamp() {
String rtnStr = null;
// 문자열로 변환하기 위한 패턴 설정(연도-월-일 시:분:초:초(자정이후 초))
String pattern = "ddhhmmssSSS"; //"yyyyMMddhhmmssSSS";
SimpleDateFormat sdfCurrent = new SimpleDateFormat(pattern, Locale.KOREA);
Timestamp ts = new Timestamp(System.currentTimeMillis());
rtnStr = sdfCurrent.format(ts.getTime());
return rtnStr;
}
}

View File

@@ -0,0 +1,85 @@
package com.wb.domainserver.util.file.service;
import com.wb.domainserver.util.file.vo.EmailProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Properties;
@Service
@EnableAsync
public class MailSenderSvc {
private static final Logger logger = LoggerFactory.getLogger(MailSenderSvc.class);
@Autowired
EmailProperties emailProperties;
// 보낼사람의 이메일,제목 , 내용
@Async
public void sendMail(String toEmail, String fromEmail, String subject, String text, File file) throws MessagingException{
String smtpHostServer = emailProperties.getHost();
String senderEmail = fromEmail;
if("".equals(fromEmail) || fromEmail == null) {
senderEmail = emailProperties.getUsername();
}
Properties props = System.getProperties();
// props.put("mail.smtp.host", smtpHostServer);
props.put("mail.smtp.host", "127.0.0.1");
Session session = Session.getInstance(props, null);
try {
MimeMessage msg = new MimeMessage(session);
//set message headers
msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
msg.addHeader("format", "flowed");
msg.addHeader("Content-Transfer-Encoding", "8bit");
msg.setFrom(new InternetAddress(senderEmail, "셀럽페이"));
msg.setReplyTo(InternetAddress.parse(senderEmail, false));
msg.setSubject(subject, "UTF-8");
MimeBodyPart mbp1 = new MimeBodyPart();
mbp1.setContent(text, "text/html;charset=euc-kr");
Multipart mp = new MimeMultipart();
mp.addBodyPart(mbp1);
if(file != null) {
MimeBodyPart mbp2 = new MimeBodyPart();
FileDataSource fds = new FileDataSource(file.getAbsolutePath());
mbp2.setDataHandler(new DataHandler(fds));
mbp2.setFileName(fds.getName());
mp.addBodyPart(mbp2);
}
msg.setContent(mp);
msg.setSentDate(new Date());
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
System.out.println("Message is ready");
Transport.send(msg);
System.out.println("EMail Sent Successfully!!");
}catch(UnsupportedEncodingException e) {
logger.error(e.getMessage());
}
}
}

View File

@@ -0,0 +1,14 @@
package com.wb.domainserver.util.file.vo;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
@Data
public class EmailProperties {
@Value("${mail.host}")
private String host;
@Value("${mail.username}")
private String username;
}

View File

@@ -0,0 +1,48 @@
package com.wb.domainserver.util.file.vo;
import lombok.Data;
@Data
public class ExcelFile {
private String col0;
private String col1;
private String col2;
private String col3;
private String col4;
private String col5;
private String col6;
private String col7;
private String col8;
private String col9;
private String col10;
private String col11;
private String col12;
private String col13;
private String col14;
private String col15;
private String col16;
private String col17;
private String col18;
private String col19;
private String col20;
private String col21;
private String col22;
private String col23;
private String col24;
private String col25;
private String col26;
private String col27;
private String col28;
private String col29;
private String col30;
private String col31;
private String col32;
private String col33;
private String col34;
private String col35;
private String col36;
private String col37;
private String col38;
private String col39;
private String col40;
}

View File

@@ -0,0 +1,43 @@
package com.wb.domainserver.util.file.vo;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
@Data
public class FileStorageProperties {
@Value("${sopmalfo.common.fileupload.uploaddirs.doc}")
private String docUploadDir;
@Value("${sopmalfo.common.fileupload.uploaddirs.web}")
private String imgUploadDir;
@Value("${sopmalfo.common.fileupload.uploaddirs.phar}")
private String pharUploadDir;
@Value("${sopmalfo.common.fileupload.uploaddirs.rtrn}")
private String rtrnUploadDir;
public String getDateDir(String pattern, boolean seperator) {
String dirPath = "";
DateFormat format = new SimpleDateFormat(pattern);
Date nowDate = new Date();
String toDate = format.format(nowDate);
if(seperator) {
if("yyyy".equals(pattern)) {
dirPath = "/" + toDate;
}else if("yyyyMM".equals(pattern)) {
dirPath = "/" + toDate.substring(0, 4) + "/" + toDate.substring(4, 6);
}else if("yyyyMMdd".equals(pattern)) {
dirPath = "/" + toDate.substring(0, 4) + "/" + toDate.substring(4, 6) + "/" + toDate.substring(6);
}
}else {
dirPath = "/" + toDate;
}
return dirPath;
}
}

View File

@@ -0,0 +1,35 @@
package com.wb.domainserver.util.file.vo;
import lombok.Data;
import org.springframework.stereotype.Component;
@Data
@Component
public class FileVo {
//파일유형
private String fileType;
//파일일련번호
private String fileSeq;
//문서명
private String docName;
//파일경로
private String filePath;
//파일명
private String fileName;
//파일확장자
private String fileExt;
//파일크기
private String fileSize;
//파일상태
private String status;
//구분도메인
private String domain;
//subPath
private String subPath;
//shopCd
private String shopCd;
//menuGb
private String menuGb;
}

View File

@@ -0,0 +1,33 @@
package com.wb.domainserver.util.file.vo;
import lombok.Data;
@Data
public class UploadFile {
private String foreignColumn;
private String attachNo;
private String fileId;
private int fileSeq;
private String fileType;
private String docName;
private String filePath;
private String fileName;
private String fileExt;
private long fileSize;
private int sort;
private String status;
private String fileDownloadUri;
private String extFileNm;
private String fileTabName;
private String regDate;
private String regId;
private String modDate;
private String modId;
private String pathNumber;
private String shopCd;
private String pathGubun="";
private String subPathId="";
private String validExp="";
}

View File

@@ -0,0 +1,160 @@
package com.wb.domainserver.util.format;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
/**
* 날짜 및 시간에 대한 변환을 지원하는 Utility
*
* @author 박철민
* @since 2023-11-24
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-11-24 박철민 최초 생성
*
* </pre>
*/
public class DateFormatUtil {
/**
* 기본 Locale에 해당하는 형식으로 날짜를 변환한다.
*
* @param date 날짜
* @return 날짜 문자열
*/
public static String formatDate(Date date) {
return DateFormat.getDateInstance().format(date);
}
/**
* Locale에 해당하는 형식으로 날짜를 변환한다.
*
* @param locale 로케일
* @param date 날짜
* @return 날짜 문자열
*/
public static String formatDate(Locale locale, Date date) {
return DateFormat.getDateInstance(DateFormat.DEFAULT, locale).format(date);
}
/**
* 주어진 스타일에 따라, 기본 Locale에 해당하는 형식으로 날짜를 변환한다.
*
* @param style 날짜 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT})
* @param date 날짜
* @return 날짜 문자열
*/
public static String formatDate(int style, Date date) {
return DateFormat.getDateInstance(style).format(date);
}
/**
* 주어진 스타일에 따라, Locale에 해당하는 형식으로 날짜를 변환한다.
*
* @param style 날짜 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT})
* @param locale 로케일
* @param date 날짜
* @return 날짜 문자열
*/
public static String formatDate(int style, Locale locale, Date date) {
return DateFormat.getDateInstance(style, locale).format(date);
}
/**
* 기본 Locale에 해당하는 형식으로 날짜 및 시간을 변환한다.
*
* @param date 날짜 및 시간
* @return 날짜 및 시간 문자열
*/
public static String formatDateTime(Date date) {
return DateFormat.getDateTimeInstance().format(date);
}
/**
* Locale에 해당하는 형식으로 날짜 및 시간을 변환한다.
*
* @param locale 로케일
* @param date 날짜 및 시간
* @return 날짜 및 시간 문자열
*/
public static String formatDateTime(Locale locale, Date date) {
return DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, locale).format(date);
}
/**
* 주어진 스타일에 따라, 기본 Locale에 해당하는 형식으로 날짜 및 시간을 변환한다.
*
* @param dateStyle 날짜 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT})
* @param timeStyle 시간 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT})
* @param date 날짜 및 시간
* @return 날짜 및 시간 문자열
*/
public static String formatDateTime(int dateStyle, int timeStyle, Date date) {
return DateFormat.getDateTimeInstance(dateStyle, timeStyle).format(date);
}
/**
* 주어진 스타일에 따라, Locale에 해당하는 형식으로 날짜 및 시간을 변환한다.
*
* @param dateStyle 날짜 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT})
* @param timeStyle 시간 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT})
* @param locale 로케일
* @param date 날짜 및 시간
* @return 날짜 및 시간 문자열
*/
public static String formatDateTime(int dateStyle, int timeStyle, Locale locale, Date date) {
return DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale).format(date);
}
/**
* 기본 Locale에 해당하는 형식으로 시간을 변환한다.
*
* @param date 시간
* @return 시간 문자열
*/
public static String formatTime(Date date) {
return DateFormat.getTimeInstance().format(date);
}
/**
* Locale에 해당하는 형식으로 시간을 변환한다.
*
* @param locale 로케일
* @param date 시간
* @return 시간 문자열
*/
public static String formatTime(Locale locale, Date date) {
return DateFormat.getTimeInstance(DateFormat.DEFAULT, locale).format(date);
}
/**
* 주어진 스타일에 따라, 기본 Locale에 해당하는 형식으로 시간을 변환한다.
*
* @param style 시간 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT})
* @param date 시간
* @return 시간 문자열
*/
public static String formatTime(int style, Date date) {
return DateFormat.getTimeInstance(style).format(date);
}
/**
* 주어진 스타일에 따라, Locale에 해당하는 형식으로 시간을 변환한다.
*
* @param style 시간 스타일 (사용 가능한 값 : {@link DateFormat#FULL}, {@link DateFormat#LONG}, {@link DateFormat#MEDIUM}, {@link DateFormat#SHORT}, {@link DateFormat#DEFAULT})
* @param locale 로케일
* @param date 시간
* @return 시간 문자열
*/
public static String formatTime(int style, Locale locale, Date date) {
return DateFormat.getTimeInstance(style, locale).format(date);
}
}

View File

@@ -0,0 +1,270 @@
package com.wb.domainserver.util.format;
import java.text.NumberFormat;
import java.util.Locale;
/**
* 숫자, 통화, 퍼센트에 대한 형식 변환을 지원하는 Utility
*
* @author 박철민
* @since 2023-11-24
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-11-24 박철민 최초 생성
*
* </pre>
*/
public class NumberFormatUtil {
private static final int MAX_FRACTION_DIGIT = 3;
private static final boolean GROUPING_USED = true;
/**
* 기본 Locale에 해당하는 형식으로 숫자를 변환한다.
*
* @param number 숫자
* @return 숫자 문자열
*/
public static String formatNumber(Number number) {
return formatNumber(number, GROUPING_USED, MAX_FRACTION_DIGIT);
}
/**
* Locale에 해당하는 형식으로 숫자를 변환한다.
*
* @param locale 로케일
* @param number 숫자
* @return 숫자 문자열
*/
public static String formatNumber(Locale locale, Number number) {
return formatNumber(locale, number, GROUPING_USED, MAX_FRACTION_DIGIT);
}
/**
* 기본 Locale에 해당하는 형식으로 숫자를 변환한다.
*
* @param number 숫자
* @param groupingUsed 그룹 분리기호 포함 여부
* @return 숫자 문자열
*/
public static String formatNumber(Number number, boolean groupingUsed) {
return formatNumber(number, groupingUsed, MAX_FRACTION_DIGIT);
}
/**
* Locale에 해당하는 형식으로 숫자를 변환한다.
*
* @param locale 로케일
* @param number 숫자
* @param groupingUsed 그룹 분리기호 포함 여부
* @return 숫자 문자열
*/
public static String formatNumber(Locale locale, Number number, boolean groupingUsed) {
return formatNumber(locale, number, groupingUsed, MAX_FRACTION_DIGIT);
}
/**
* 기본 Locale에 해당하는 형식으로 숫자를 변환한다.
*
* @param number 숫자
* @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수
* @return 숫자 문자열
*/
public static String formatNumber(Number number, int maxFactionDigits) {
return formatNumber(number, GROUPING_USED, maxFactionDigits);
}
/**
* Locale에 해당하는 형식으로 숫자를 변환한다.
*
* @param locale 로케일
* @param number 숫자
* @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수
* @return 숫자 문자열
*/
public static String formatNumber(Locale locale, Number number, int maxFactionDigits) {
return formatNumber(locale, number, GROUPING_USED, maxFactionDigits);
}
/**
* 기본 Locale에 해당하는 형식으로 숫자를 변환한다.
*
* @param number 숫자
* @param groupingUsed 그룹 분리기호 포함 여부
* @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수
* @return 숫자 문자열
*/
public static String formatNumber(Number number, boolean groupingUsed, int maxFactionDigits) {
NumberFormat numberberFormat = NumberFormat.getNumberInstance();
numberberFormat.setGroupingUsed(groupingUsed);
numberberFormat.setMaximumFractionDigits(maxFactionDigits);
return numberberFormat.format(number);
}
/**
* Locale에 해당하는 형식으로 숫자를 변환한다.
*
* @param locale 로케일
* @param number 숫자
* @param groupingUsed 그룹 분리기호 포함 여부
* @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수
* @return 숫자 문자열
*/
public static String formatNumber(Locale locale, Number number, boolean groupingUsed, int maxFactionDigits) {
NumberFormat numberberFormat = NumberFormat.getNumberInstance(locale);
numberberFormat.setGroupingUsed(groupingUsed);
numberberFormat.setMaximumFractionDigits(maxFactionDigits);
return numberberFormat.format(number);
}
/**
* 기본 Locale에 해당하는 형식으로 통화를 변환한다.
*
* @param number 숫자
* @return 통화 문자열
*/
public static String formatCurrency(Number number) {
return formatCurrency(number, GROUPING_USED);
}
/**
* Locale에 해당하는 형식으로 통화를 변환한다.
*
* @param locale 로케일
* @param number 숫자
* @return 통화 문자열
*/
public static String formatCurrency(Locale locale, Number number) {
return formatCurrency(locale, number, GROUPING_USED);
}
/**
* 기본 Locale에 해당하는 형식으로 통화를 변환한다.
*
* @param number 숫자
* @param groupingUsed 그룹 분리기호 포함 여부
* @return 통화 문자열
*/
public static String formatCurrency(Number number, boolean groupingUsed) {
NumberFormat numberberFormat = NumberFormat.getCurrencyInstance();
numberberFormat.setGroupingUsed(groupingUsed);
return numberberFormat.format(number);
}
/**
* Locale에 해당하는 형식으로 통화를 변환한다.
*
* @param locale 로케일
* @param number 숫자
* @param groupingUsed 그룹 분리기호 포함 여부
* @return 통화 문자열
*/
public static String formatCurrency(Locale locale, Number number, boolean groupingUsed) {
NumberFormat numberberFormat = NumberFormat.getCurrencyInstance(locale);
numberberFormat.setGroupingUsed(groupingUsed);
return numberberFormat.format(number);
}
/**
* 기본 Locale에 해당하는 형식으로 퍼센트를 변환한다.
*
* @param number 숫자
* @return 퍼센트 문자열
*/
public static String formatPercent(Number number) {
return formatPercent(number, GROUPING_USED, MAX_FRACTION_DIGIT);
}
/**
* Locale에 해당하는 형식으로 퍼센트를 변환한다.
*
* @param locale 로케일
* @param number 숫자
* @return 퍼센트 문자열
*/
public static String formatPercent(Locale locale, Number number) {
return formatPercent(locale, number, GROUPING_USED, MAX_FRACTION_DIGIT);
}
/**
* 기본 Locale에 해당하는 형식으로 퍼센트를 변환한다.
*
* @param number 숫자
* @param groupingUsed 그룹 분리기호 포함 여부
* @return 퍼센트 문자열
*/
public static String formatPercent(Number number, boolean groupingUsed) {
return formatPercent(number, groupingUsed, MAX_FRACTION_DIGIT);
}
/**
* Locale에 해당하는 형식으로 퍼센트를 변환한다.
*
* @param locale 로케일
* @param number 숫자
* @param groupingUsed 그룹 분리기호 포함 여부
* @return 퍼센트 문자열
*/
public static String formatPercent(Locale locale, Number number, boolean groupingUsed) {
return formatPercent(locale, number, groupingUsed, MAX_FRACTION_DIGIT);
}
/**
* 기본 Locale에 해당하는 형식으로 퍼센트를 변환한다.
*
* @param number 숫자
* @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수
* @return 퍼센트 문자열
*/
public static String formatPercent(Number number, int maxFactionDigits) {
return formatPercent(number, GROUPING_USED, maxFactionDigits);
}
/**
* Locale에 해당하는 형식으로 퍼센트를 변환한다.
*
* @param locale 로케일
* @param number 숫자
* @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수
* @return 퍼센트 문자열
*/
public static String formatPercent(Locale locale, Number number, int maxFactionDigits) {
return formatPercent(locale, number, GROUPING_USED, maxFactionDigits);
}
/**
* 기본 Locale에 해당하는 형식으로 퍼센트를 변환한다.
*
* @param number 숫자
* @param groupingUsed 그룹 분리기호 포함 여부
* @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수
* @return 퍼센트 문자열
*/
public static String formatPercent(Number number, boolean groupingUsed, int maxFactionDigits) {
NumberFormat numberberFormat = NumberFormat.getPercentInstance();
numberberFormat.setGroupingUsed(groupingUsed);
numberberFormat.setMaximumFractionDigits(maxFactionDigits);
return numberberFormat.format(number);
}
/**
* Locale에 해당하는 형식으로 퍼센트를 변환한다.
*
* @param locale 로케일
* @param number 숫자
* @param groupingUsed 그룹 분리기호 포함 여부
* @param maxFactionDigits 변환된 문자열에서 출력할 소수점 이하 최대 자리수
* @return 퍼센트 문자열
*/
public static String formatPercent(Locale locale, Number number, boolean groupingUsed, int maxFactionDigits) {
NumberFormat numberberFormat = NumberFormat.getPercentInstance(locale);
numberberFormat.setGroupingUsed(groupingUsed);
numberberFormat.setMaximumFractionDigits(maxFactionDigits);
return numberberFormat.format(number);
}
}

View File

@@ -0,0 +1,216 @@
package com.wb.domainserver.util.number;
import java.security.SecureRandom;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* 숫자 처리를 지원하는 Utility
*
* @author 박철민
* @since 2023-11-24
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-11-24 박철민 최초 생성
*
* </pre>
*/
public class NumberUtil {
private static SecureRandom rnd = new SecureRandom();
/**
* 특정숫자 집합에서 랜덤 숫자를 구하는 기능 시작숫자와 종료숫자 사이에서 구한 랜덤 숫자를 반환한다
*
* @param startNum - 시작숫자
* @param endNum - 종료숫자
* @return 랜덤숫자
* @see
*/
public static int getRandomNum(int startNum, int endNum) {
int randomNum = 0;
do {
// 종료숫자내에서 랜덤 숫자를 발생시킨다.
randomNum = rnd.nextInt(endNum + 1);
} while (randomNum < startNum); // 랜덤 숫자가 시작숫자보다 작을경우 다시 랜덤숫자를 발생시킨다.
return randomNum;
}
/**
* 특정 숫자 집합에서 특정 숫자가 있는지 체크하는 기능 12345678에서 7이 있는지 없는지 체크하는 기능을 제공함
*
* @param sourceInt - 특정숫자집합
* @param searchInt - 검색숫자
* @return 존재여부
* @see
*/
public static Boolean getNumSearchCheck(int sourceInt, int searchInt) {
String sourceStr = String.valueOf(sourceInt);
String searchStr = String.valueOf(searchInt);
// 특정숫자가 존재하는지 하여 위치값을 리턴한다. 없을 시 -1
if (sourceStr.indexOf(searchStr) == -1) {
return false;
} else {
return true;
}
}
/**
* 숫자타입을 문자열로 변환하는 기능 숫자 20081212를 문자열 '20081212'로 변환하는 기능
*
* @param srcNumber - 숫자
* @return 문자열
* @see
*/
public static String getNumToStrCnvr(int srcNumber) {
String rtnStr = null;
rtnStr = String.valueOf(srcNumber);
return rtnStr;
}
/**
* 숫자타입을 데이트 타입으로 변환하는 기능
* 숫자 20081212를 데이트타입 '2008-12-12'로 변환하는 기능
* @param srcNumber - 숫자
* @return String
* @see
*/
public static String getNumToDateCnvr(int srcNumber) {
String pattern = null;
String cnvrStr = null;
String srcStr = String.valueOf(srcNumber);
// Date 형태인 8자리 및 14자리만 정상처리
if (srcStr.length() != 8 && srcStr.length() != 14) {
throw new IllegalArgumentException("Invalid Number: " + srcStr + " Length=" + srcStr.trim().length());
}
if (srcStr.length() == 8) {
pattern = "yyyyMMdd";
} else if (srcStr.length() == 14) {
pattern = "yyyyMMddhhmmss";
}
SimpleDateFormat dateFormatter = new SimpleDateFormat(pattern, Locale.KOREA);
Date cnvrDate = null;
try {
cnvrDate = dateFormatter.parse(srcStr);
} catch (ParseException e) {
throw new RuntimeException(e);
}
cnvrStr = String.format("%1$tY-%1$tm-%1$td", cnvrDate);
return cnvrStr;
}
/**
* 체크할 숫자 중에서 숫자인지 아닌지 체크하는 기능
* 숫자이면 True, 아니면 False를 반환한다
* @param checkStr - 체크문자열
* @return 숫자여부
* @see
*/
public static Boolean getNumberValidCheck(String checkStr) {
int i;
//String sourceStr = String.valueOf(sourceInt);
int checkStrLt = checkStr.length();
for (i = 0; i < checkStrLt; i++) {
// 아스키코드값( '0'-> 48, '9' -> 57)
if (checkStr.charAt(i) > 47 && checkStr.charAt(i) < 58) {
continue;
} else {
return false;
}
}
return true;
}
/**
* 특정숫자를 다른 숫자로 치환하는 기능 숫자 12345678에서 123를 999로 변환하는 기능을 제공(99945678)
*
* @param srcNumber - 숫자집합
* @param cnvrSrcNumber - 원래숫자
* @param cnvrTrgtNumber - 치환숫자
* @return 치환숫자
* @see
*/
public static int getNumberCnvr(int srcNumber, int cnvrSrcNumber, int cnvrTrgtNumber) {
// 입력받은 숫자를 문자열로 변환
String source = String.valueOf(srcNumber);
String subject = String.valueOf(cnvrSrcNumber);
String object = String.valueOf(cnvrTrgtNumber);
StringBuffer rtnStr = new StringBuffer();
String preStr = "";
String nextStr = source;
// 원본숫자에서 변환대상숫자의 위치를 찾는다.
while (source.indexOf(subject) >= 0) {
preStr = source.substring(0, source.indexOf(subject)); // 변환대상숫자 위치까지 숫자를 잘라낸다
nextStr = source.substring(source.indexOf(subject) + subject.length(), source.length());
source = nextStr;
rtnStr.append(preStr).append(object); // 변환대상위치 숫자에 변환할 숫자를 붙여준다.
}
rtnStr.append(nextStr); // 변환대상 숫자 이후 숫자를 붙여준다.
return Integer.parseInt(rtnStr.toString());
}
/**
* 특정숫자가 실수인지, 정수인지, 음수인지 체크하는 기능 123이 실수인지, 정수인지, 음수인지 체크하는 기능을 제공함
*
* @param srcNumber - 숫자집합
* @return -1(음수), 0(정수), 1(실수)
* @see
*/
public static int checkRlnoInteger(double srcNumber) {
// byte 1바이트 ▶소수점이 없는 숫자로, 범위 -2^7 ~ 2^7 -1
// short 2바이트 ▶소수점이 없는 숫자로, 범위 -2^15 ~ 2^15 -1
// int 4바이트 ▶소수점이 없는 숫자로, 범위 -2^31 ~ 2^31 - 1
// long 8바이트 ▶소수점이 없는 숫자로, 범위 -2^63 ~ 2^63-1
// float 4바이트 ▶소수점이 있는 숫자로, 끝에 F 또는 f 가 붙는 숫자 (예:3.14f)
// double 8바이트 ▶소수점이 있는 숫자로, 끝에 아무것도 붙지 않는 숫자 (예:3.14)
// ▶소수점이 있는 숫자로, 끝에 D 또는 d 가 붙는 숫자(예:3.14d)
String cnvrString = null;
if (srcNumber < 0) {
return -1;
} else {
cnvrString = String.valueOf(srcNumber);
if (cnvrString.indexOf(".") == -1) {
return 0;
} else {
return 1;
}
}
}
}

View File

@@ -0,0 +1,944 @@
package com.wb.domainserver.util.string;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.SecureRandom;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Locale;
/**
* 문자열 관련 처리를 지원하는 Utility
*
* @author 박철민
* @since 2023-11-24
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-11-24 박철민 최초 생성
*
* </pre>
*/
public class StringUtil {
public static final String EMPTY = "";
private static SecureRandom rnd = new SecureRandom();
/**
* 문자열이 지정한 길이를 초과했을때 지정한길이에다가 해당 문자열을 붙여주는 메서드.
* @param source 원본 문자열 배열
* @param output 더할문자열
* @param slength 지정길이
* @return 지정길이로 잘라서 더할분자열 합친 문자열
*/
public static String cutString(String source, String output, int slength) {
String returnVal = null;
if (source != null) {
if (source.length() > slength) {
returnVal = source.substring(0, slength) + output;
} else {
returnVal = source;
}
}
return returnVal;
}
/**
* 문자열이 지정한 길이를 초과했을때 해당 문자열을 삭제하는 메서드
* @param source 원본 문자열 배열
* @param slength 지정길이
* @return 지정길이로 잘라서 더할분자열 합친 문자열
*/
public static String cutString(String source, int slength) {
String result = null;
if (source != null) {
if (source.length() > slength) {
result = source.substring(0, slength);
} else {
result = source;
}
}
return result;
}
/**
* <p>
* String이 비었거나("") 혹은 null 인지 검증한다.
* </p>
*
* <pre>
* StringUtil.isEmpty(null) = true
* StringUtil.isEmpty("") = true
* StringUtil.isEmpty(" ") = false
* StringUtil.isEmpty("bob") = false
* StringUtil.isEmpty(" bob ") = false
* </pre>
*
* @param str - 체크 대상 스트링오브젝트이며 null을 허용함
* @return <code>true</code> - 입력받은 String 이 빈 문자열 또는 null인 경우
*/
public static boolean isEmpty(String str) {
return str == null || str.length() == 0;
}
/**
* <p>기준 문자열에 포함된 모든 대상 문자(char)를 제거한다.</p>
*
* <pre>
* StringUtil.remove(null, *) = null
* StringUtil.remove("", *) = ""
* StringUtil.remove("queued", 'u') = "qeed"
* StringUtil.remove("queued", 'z') = "queued"
* </pre>
*
* @param str 입력받는 기준 문자열
* @param remove 입력받는 문자열에서 제거할 대상 문자열
* @return 제거대상 문자열이 제거된 입력문자열. 입력문자열이 null인 경우 출력문자열은 null
*/
public static String remove(String str, char remove) {
if (isEmpty(str) || str.indexOf(remove) == -1) {
return str;
}
char[] chars = str.toCharArray();
int pos = 0;
for (int i = 0; i < chars.length; i++) {
if (chars[i] != remove) {
chars[pos++] = chars[i];
}
}
return new String(chars, 0, pos);
}
/**
* <p>문자열 내부의 콤마 character(,)를 모두 제거한다.</p>
*
* <pre>
* StringUtil.removeCommaChar(null) = null
* StringUtil.removeCommaChar("") = ""
* StringUtil.removeCommaChar("asdfg,qweqe") = "asdfgqweqe"
* </pre>
*
* @param str 입력받는 기준 문자열
* @return " , "가 제거된 입력문자열
* 입력문자열이 null인 경우 출력문자열은 null
*/
public static String removeCommaChar(String str) {
return remove(str, ',');
}
/**
* <p>문자열 내부의 마이너스 character(-)를 모두 제거한다.</p>
*
* <pre>
* StringUtil.removeMinusChar(null) = null
* StringUtil.removeMinusChar("") = ""
* StringUtil.removeMinusChar("a-sdfg-qweqe") = "asdfgqweqe"
* </pre>
*
* @param str 입력받는 기준 문자열
* @return " - "가 제거된 입력문자열
* 입력문자열이 null인 경우 출력문자열은 null
*/
public static String removeMinusChar(String str) {
return remove(str, '-');
}
/**
* 원본 문자열의 포함된 특정 문자열을 새로운 문자열로 변환하는 메서드
* @param source 원본 문자열
* @param subject 원본 문자열에 포함된 특정 문자열
* @param object 변환할 문자열
* @return sb.toString() 새로운 문자열로 변환된 문자열
*/
public static String replace(String source, String subject, String object) {
StringBuffer rtnStr = new StringBuffer();
String preStr = "";
String nextStr = source;
String srcStr = source;
while (srcStr.indexOf(subject) >= 0) {
preStr = srcStr.substring(0, srcStr.indexOf(subject));
nextStr = srcStr.substring(srcStr.indexOf(subject) + subject.length(), srcStr.length());
srcStr = nextStr;
rtnStr.append(preStr).append(object);
}
rtnStr.append(nextStr);
return rtnStr.toString();
}
/**
* 원본 문자열의 포함된 특정 문자열 첫번째 한개만 새로운 문자열로 변환하는 메서드
* @param source 원본 문자열
* @param subject 원본 문자열에 포함된 특정 문자열
* @param object 변환할 문자열
* @return sb.toString() 새로운 문자열로 변환된 문자열 / source 특정문자열이 없는 경우 원본 문자열
*/
public static String replaceOnce(String source, String subject, String object) {
StringBuffer rtnStr = new StringBuffer();
String preStr = "";
String nextStr = source;
if (source.indexOf(subject) >= 0) {
preStr = source.substring(0, source.indexOf(subject));
nextStr = source.substring(source.indexOf(subject) + subject.length(), source.length());
rtnStr.append(preStr).append(object).append(nextStr);
return rtnStr.toString();
} else {
return source;
}
}
/**
* <code>subject</code>에 포함된 각각의 문자를 object로 변환한다.
*
* @param source 원본 문자열
* @param subject 원본 문자열에 포함된 특정 문자열
* @param object 변환할 문자열
* @return sb.toString() 새로운 문자열로 변환된 문자열
*/
public static String replaceChar(String source, String subject, String object) {
StringBuffer rtnStr = new StringBuffer();
String preStr = "";
String nextStr = source;
String srcStr = source;
char chA;
for (int i = 0; i < subject.length(); i++) {
chA = subject.charAt(i);
if (srcStr.indexOf(chA) >= 0) {
preStr = srcStr.substring(0, srcStr.indexOf(chA));
nextStr = srcStr.substring(srcStr.indexOf(chA) + 1, srcStr.length());
srcStr = rtnStr.append(preStr).append(object).append(nextStr).toString();
}
}
return srcStr;
}
/**
* <p><code>str</code> 중 <code>searchStr</code>의 시작(index) 위치를 반환.</p>
*
* <p>입력값 중 <code>null</code>이 있을 경우 <code>-1</code>을 반환.</p>
*
* <pre>
* StringUtil.indexOf(null, *) = -1
* StringUtil.indexOf(*, null) = -1
* StringUtil.indexOf("", "") = 0
* StringUtil.indexOf("aabaabaa", "a") = 0
* StringUtil.indexOf("aabaabaa", "b") = 2
* StringUtil.indexOf("aabaabaa", "ab") = 1
* StringUtil.indexOf("aabaabaa", "") = 0
* </pre>
*
* @param str 검색 문자열
* @param searchStr 검색 대상문자열
* @return 검색 문자열 중 검색 대상문자열이 있는 시작 위치 검색대상 문자열이 없거나 null인 경우 -1
*/
public static int indexOf(String str, String searchStr) {
if (str == null || searchStr == null) {
return -1;
}
return str.indexOf(searchStr);
}
/**
* <p>오라클의 decode 함수와 동일한 기능을 가진 메서드이다.
* <code>sourStr</code>과 <code>compareStr</code>의 값이 같으면
* <code>returStr</code>을 반환하며, 다르면 <code>defaultStr</code>을 반환한다.
* </p>
*
* <pre>
* StringUtil.decode(null, null, "foo", "bar")= "foo"
* StringUtil.decode("", null, "foo", "bar") = "bar"
* StringUtil.decode(null, "", "foo", "bar") = "bar"
* StringUtil.decode("하이", "하이", null, "bar") = null
* StringUtil.decode("하이", "하이 ", "foo", null) = null
* StringUtil.decode("하이", "하이", "foo", "bar") = "foo"
* StringUtil.decode("하이", "하이 ", "foo", "bar") = "bar"
* </pre>
*
* @param sourceStr 비교할 문자열
* @param compareStr 비교 대상 문자열
* @param returnStr sourceStr와 compareStr의 값이 같을 때 반환할 문자열
* @param defaultStr sourceStr와 compareStr의 값이 다를 때 반환할 문자열
* @return sourceStr과 compareStr의 값이 동일(equal)할 때 returnStr을 반환하며,
* <br/>다르면 defaultStr을 반환한다.
*/
public static String decode(String sourceStr, String compareStr, String returnStr, String defaultStr) {
// if (sourceStr == null && compareStr == null) {
// return returnStr;
// }
//
// if (sourceStr == null && compareStr != null) {
// return defaultStr;
// }
//
// if (sourceStr.trim().equals(compareStr)) {
// return returnStr;
// }
if (sourceStr == null) { //2022.01. Possible null pointer dereference
if (compareStr == null) {
return returnStr;
} else {
return defaultStr;
}
} else {
if (sourceStr.trim().equals(compareStr)) {
return returnStr;
}
}
return defaultStr;
}
/**
* <p>오라클의 decode 함수와 동일한 기능을 가진 메서드이다.
* <code>sourStr</code>과 <code>compareStr</code>의 값이 같으면
* <code>returStr</code>을 반환하며, 다르면 <code>sourceStr</code>을 반환한다.
* </p>
*
* <pre>
* StringUtil.decode(null, null, "foo") = "foo"
* StringUtil.decode("", null, "foo") = ""
* StringUtil.decode(null, "", "foo") = null
* StringUtil.decode("하이", "하이", "foo") = "foo"
* StringUtil.decode("하이", "하이 ", "foo") = "하이"
* StringUtil.decode("하이", "바이", "foo") = "하이"
* </pre>
*
* @param sourceStr 비교할 문자열
* @param compareStr 비교 대상 문자열
* @param returnStr sourceStr와 compareStr의 값이 같을 때 반환할 문자열
* @return sourceStr과 compareStr의 값이 동일(equal)할 때 returnStr을 반환하며,
* <br/>다르면 sourceStr을 반환한다.
*/
public static String decode(String sourceStr, String compareStr, String returnStr) {
return decode(sourceStr, compareStr, returnStr, sourceStr);
}
/**
* 객체가 null인지 확인하고 null인 경우 "" 로 바꾸는 메서드
* @param object 원본 객체
* @return resultVal 문자열
*/
public static String isNullToString(Object object) {
String string = "";
if (object != null) {
string = object.toString().trim();
}
return string;
}
/**
*<pre>
* 인자로 받은 String이 null일 경우 &quot;&quot;로 리턴한다.
* &#064;param src null값일 가능성이 있는 String 값.
* &#064;return 만약 String이 null 값일 경우 &quot;&quot;로 바꾼 String 값.
*</pre>
*/
public static String nullConvert(Object src) {
//if (src != null && src.getClass().getName().equals("java.math.BigDecimal")) {
if (src != null && src instanceof BigDecimal) {
return ((BigDecimal)src).toString();
}
if (src == null || src.equals("null")) {
return "";
} else {
return ((String)src).trim();
}
}
/**
*<pre>
* 인자로 받은 String이 null일 경우 &quot;&quot;로 리턴한다.
* &#064;param src null값일 가능성이 있는 String 값.
* &#064;return 만약 String이 null 값일 경우 &quot;&quot;로 바꾼 String 값.
*</pre>
*/
public static String nullConvertInt(Object src) {
//if (src != null && src.getClass().getName().equals("java.math.BigDecimal")) {
if (src != null && src instanceof BigDecimal) {
return ((BigDecimal)src).toString();
}
if (src == null || src.equals("null")) {
return "0";
} else {
return ((String)src).trim();
}
}
/**
*<pre>
* 인자로 받은 String이 null일 경우 &quot;&quot;로 리턴한다.
* &#064;param src null값일 가능성이 있는 String 값.
* &#064;return 만약 String이 null 값일 경우 &quot;&quot;로 바꾼 String 값.
*</pre>
*/
public static String nullConvert(String src) {
if (src == null || src.equals("null") || "".equals(src) || " ".equals(src)) {
return "";
} else {
return src.trim();
}
}
/**
*<pre>
* 인자로 받은 String이 null일 경우 &quot;0&quot;로 리턴한다.
* &#064;param src null값일 가능성이 있는 String 값.
* &#064;return 만약 String이 null 값일 경우 &quot;0&quot;로 바꾼 String 값.
*</pre>
*/
public static int zeroConvert(Object src) {
if (src == null || src.equals("null")) {
return 0;
} else {
return Integer.parseInt(((String)src).trim());
}
}
/**
*<pre>
* 인자로 받은 String이 null일 경우 &quot;&quot;로 리턴한다.
* &#064;param src null값일 가능성이 있는 String 값.
* &#064;return 만약 String이 null 값일 경우 &quot;&quot;로 바꾼 String 값.
*</pre>
*/
public static int zeroConvert(String src) {
if (src == null || src.equals("null") || "".equals(src) || " ".equals(src)) {
return 0;
} else {
return Integer.parseInt(src.trim());
}
}
/**
* <p>문자열에서 {@link Character#isWhitespace(char)}에 정의된
* 모든 공백문자를 제거한다.</p>
*
* <pre>
* StringUtil.removeWhitespace(null) = null
* StringUtil.removeWhitespace("") = ""
* StringUtil.removeWhitespace("abc") = "abc"
* StringUtil.removeWhitespace(" ab c ") = "abc"
* </pre>
*
* @param str 공백문자가 제거도어야 할 문자열
* @return the 공백문자가 제거된 문자열, null이 입력되면 <code>null</code>이 리턴
*/
public static String removeWhitespace(String str) {
if (isEmpty(str)) {
return str;
}
int sz = str.length();
char[] chs = new char[sz];
int count = 0;
for (int i = 0; i < sz; i++) {
if (!Character.isWhitespace(str.charAt(i))) {
chs[count++] = str.charAt(i);
}
}
if (count == sz) {
return str;
}
return new String(chs, 0, count);
}
/**
* Html 코드가 들어간 문서를 표시할때 태그에 손상없이 보이기 위한 메서드
*
* @param strString
* @return HTML 태그를 치환한 문자열
*/
public static String checkHtmlView(String strString) {
String strNew = "";
StringBuffer strTxt = new StringBuffer("");
char chrBuff;
int len = strString.length();
for (int i = 0; i < len; i++) {
chrBuff = strString.charAt(i);
switch (chrBuff) {
case '<':
strTxt.append("&lt;");
break;
case '>':
strTxt.append("&gt;");
break;
case '"':
strTxt.append("&quot;");
break;
case 10:
strTxt.append("<br>");
break;
case ' ':
strTxt.append("&nbsp;");
break;
//case '&' :
//strTxt.append("&amp;");
//break;
default:
strTxt.append(chrBuff);
}
}
strNew = strTxt.toString();
return strNew;
}
/**
* 문자열을 지정한 분리자에 의해 배열로 리턴하는 메서드.
* @param source 원본 문자열
* @param separator 분리자
* @return result 분리자로 나뉘어진 문자열 배열
*/
public static String[] split(String source, String separator) throws NullPointerException {
String[] returnVal = null;
int cnt = 1;
int index = source.indexOf(separator);
int index0 = 0;
while (index >= 0) {
cnt++;
index = source.indexOf(separator, index + 1);
}
returnVal = new String[cnt];
cnt = 0;
index = source.indexOf(separator);
while (index >= 0) {
returnVal[cnt] = source.substring(index0, index);
index0 = index + 1;
index = source.indexOf(separator, index + 1);
cnt++;
}
returnVal[cnt] = source.substring(index0);
return returnVal;
}
/**
* <p>{@link String#toLowerCase()}를 이용하여 소문자로 변환한다.</p>
*
* <pre>
* StringUtil.lowerCase(null) = null
* StringUtil.lowerCase("") = ""
* StringUtil.lowerCase("aBc") = "abc"
* </pre>
*
* @param str 소문자로 변환되어야 할 문자열
* @return 소문자로 변환된 문자열, null이 입력되면 <code>null</code> 리턴
*/
public static String lowerCase(String str) {
if (str == null) {
return null;
}
return str.toLowerCase();
}
/**
* <p>{@link String#toUpperCase()}를 이용하여 대문자로 변환한다.</p>
*
* <pre>
* StringUtil.upperCase(null) = null
* StringUtil.upperCase("") = ""
* StringUtil.upperCase("aBc") = "ABC"
* </pre>
*
* @param str 대문자로 변환되어야 할 문자열
* @return 대문자로 변환된 문자열, null이 입력되면 <code>null</code> 리턴
*/
public static String upperCase(String str) {
if (str == null) {
return null;
}
return str.toUpperCase();
}
/**
* <p>입력된 String의 앞쪽에서 두번째 인자로 전달된 문자(stripChars)를 모두 제거한다.</p>
*
* <pre>
* StringUtil.stripStart(null, *) = null
* StringUtil.stripStart("", *) = ""
* StringUtil.stripStart("abc", "") = "abc"
* StringUtil.stripStart("abc", null) = "abc"
* StringUtil.stripStart(" abc", null) = "abc"
* StringUtil.stripStart("abc ", null) = "abc "
* StringUtil.stripStart(" abc ", null) = "abc "
* StringUtil.stripStart("yxabc ", "xyz") = "abc "
* </pre>
*
* @param str 지정된 문자가 제거되어야 할 문자열
* @param stripChars 제거대상 문자열
* @return 지정된 문자가 제거된 문자열, null이 입력되면 <code>null</code> 리턴
*/
public static String stripStart(String str, String stripChars) {
int strLen;
if (str == null || (strLen = str.length()) == 0) {
return str;
}
int start = 0;
if (stripChars == null) {
while ((start != strLen) && Character.isWhitespace(str.charAt(start))) {
start++;
}
} else if (stripChars.length() == 0) {
return str;
} else {
while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != -1)) {
start++;
}
}
return str.substring(start);
}
/**
* <p>입력된 String의 뒤쪽에서 두번째 인자로 전달된 문자(stripChars)를 모두 제거한다.</p>
*
* <pre>
* StringUtil.stripEnd(null, *) = null
* StringUtil.stripEnd("", *) = ""
* StringUtil.stripEnd("abc", "") = "abc"
* StringUtil.stripEnd("abc", null) = "abc"
* StringUtil.stripEnd(" abc", null) = " abc"
* StringUtil.stripEnd("abc ", null) = "abc"
* StringUtil.stripEnd(" abc ", null) = " abc"
* StringUtil.stripEnd(" abcyx", "xyz") = " abc"
* </pre>
*
* @param str 지정된 문자가 제거되어야 할 문자열
* @param stripChars 제거대상 문자열
* @return 지정된 문자가 제거된 문자열, null이 입력되면 <code>null</code> 리턴
*/
public static String stripEnd(String str, String stripChars) {
int end;
if (str == null || (end = str.length()) == 0) {
return str;
}
if (stripChars == null) {
while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
end--;
}
} else if (stripChars.length() == 0) {
return str;
} else {
while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != -1)) {
end--;
}
}
return str.substring(0, end);
}
/**
* <p>입력된 String의 앞, 뒤에서 두번째 인자로 전달된 문자(stripChars)를 모두 제거한다.</p>
*
* <pre>
* StringUtil.strip(null, *) = null
* StringUtil.strip("", *) = ""
* StringUtil.strip("abc", null) = "abc"
* StringUtil.strip(" abc", null) = "abc"
* StringUtil.strip("abc ", null) = "abc"
* StringUtil.strip(" abc ", null) = "abc"
* StringUtil.strip(" abcyx", "xyz") = " abc"
* </pre>
*
* @param str 지정된 문자가 제거되어야 할 문자열
* @param stripChars 제거대상 문자열
* @return 지정된 문자가 제거된 문자열, null이 입력되면 <code>null</code> 리턴
*/
public static String strip(String str, String stripChars) {
if (isEmpty(str)) {
return str;
}
String srcStr = str;
srcStr = stripStart(srcStr, stripChars);
return stripEnd(srcStr, stripChars);
}
/**
* 문자열을 지정한 분리자에 의해 지정된 길이의 배열로 리턴하는 메서드.
* @param source 원본 문자열
* @param separator 분리자
* @param arraylength 배열 길이
* @return 분리자로 나뉘어진 문자열 배열
*/
public static String[] split(String source, String separator, int arraylength) throws NullPointerException {
String[] returnVal = new String[arraylength];
int cnt = 0;
int index0 = 0;
int index = source.indexOf(separator);
while (index >= 0 && cnt < (arraylength - 1)) {
returnVal[cnt] = source.substring(index0, index);
index0 = index + 1;
index = source.indexOf(separator, index + 1);
cnt++;
}
returnVal[cnt] = source.substring(index0);
if (cnt < (arraylength - 1)) {
for (int i = cnt + 1; i < arraylength; i++) {
returnVal[i] = "";
}
}
return returnVal;
}
/**
* 문자열 A에서 Z사이의 랜덤 문자열을 구하는 기능을 제공 시작문자열과 종료문자열 사이의 랜덤 문자열을 구하는 기능
*
* @param startChr - 첫 문자
* @param endChr - 마지막문자
* @return 랜덤문자
* @exception MyException
* @see
*/
public static String getRandomStr(char startChr, char endChr) {
int randomInt;
String randomStr = null;
// 시작문자 및 종료문자를 아스키숫자로 변환한다.
int startInt = Integer.valueOf(startChr);
int endInt = Integer.valueOf(endChr);
// 시작문자열이 종료문자열보가 클경우
if (startInt > endInt) {
throw new IllegalArgumentException("Start String: " + startChr + " End String: " + endChr);
}
do {
// 시작문자 및 종료문자 중에서 랜덤 숫자를 발생시킨다.
randomInt = rnd.nextInt(endInt + 1);
} while (randomInt < startInt); // 입력받은 문자 'A'(65)보다 작으면 다시 랜덤 숫자 발생.
// 랜덤 숫자를 문자로 변환 후 스트링으로 다시 변환
randomStr = (char)randomInt + "";
// 랜덤문자열를 리턴
return randomStr;
}
/**
* 문자열을 다양한 문자셋(EUC-KR[KSC5601],UTF-8..)을 사용하여 인코딩하는 기능 역으로 디코딩하여 원래의 문자열을
* 복원하는 기능을 제공함 String temp = new String(문자열.getBytes("바꾸기전 인코딩"),"바꿀 인코딩");
* String temp = new String(문자열.getBytes("8859_1"),"KSC5601"); => UTF-8 에서
* EUC-KR
*
* @param srcString - 문자열
* @param srcCharsetNm - 원래 CharsetNm
* @param charsetNm - CharsetNm
* @return 인(디)코딩 문자열
* @exception MyException
* @see
*/
public static String getEncdDcd(String srcString, String srcCharsetNm, String cnvrCharsetNm) {
String rtnStr = null;
if (srcString == null) {
return null;
}
try {
rtnStr = new String(srcString.getBytes(srcCharsetNm), cnvrCharsetNm);
} catch (UnsupportedEncodingException e) {
rtnStr = null;
}
return rtnStr;
}
/**
* 특수문자를 웹 브라우저에서 정상적으로 보이기 위해 특수문자를 처리('<' -> & lT)하는 기능이다
* @param srcString - '<'
* @return 변환문자열('<' -> "&lt"
* @exception MyException
* @see
*/
public static String getSpclStrCnvr(String srcString) {
String rtnStr = null;
StringBuffer strTxt = new StringBuffer("");
char chrBuff;
int len = srcString.length();
for (int i = 0; i < len; i++) {
chrBuff = srcString.charAt(i);
switch (chrBuff) {
case '<':
strTxt.append("&lt;");
break;
case '>':
strTxt.append("&gt;");
break;
case '&':
strTxt.append("&amp;");
break;
default:
strTxt.append(chrBuff);
}
}
rtnStr = strTxt.toString();
return rtnStr;
}
/**
* 응용어플리케이션에서 고유값을 사용하기 위해 시스템에서17자리의TIMESTAMP값을 구하는 기능
*
* @param
* @return Timestamp 값
* @exception MyException
* @see
*/
public static String getTimeStamp() {
String rtnStr = null;
// 문자열로 변환하기 위한 패턴 설정(연도-월-일 시:분:초:초(자정이후 초))
String pattern = "yyyyMMddhhmmssSSS";
SimpleDateFormat sdfCurrent = new SimpleDateFormat(pattern, Locale.KOREA);
Timestamp ts = new Timestamp(System.currentTimeMillis());
rtnStr = sdfCurrent.format(ts.getTime());
return rtnStr;
}
/**
* html의 특수문자를 표현하기 위해
*
* @param srcString
* @return String
* @exception Exception
* @see
*/
public static String getHtmlStrCnvr(String srcString) {
String tmpString = srcString;
tmpString = tmpString.replaceAll("&lt;", "<");
tmpString = tmpString.replaceAll("&gt;", ">");
tmpString = tmpString.replaceAll("&amp;", "&");
tmpString = tmpString.replaceAll("&nbsp;", " ");
tmpString = tmpString.replaceAll("&apos;", "\'");
tmpString = tmpString.replaceAll("&quot;", "\"");
return tmpString;
}
/**
* <p>날짜 형식의 문자열 내부에 마이너스 character(-)를 추가한다.</p>
*
* <pre>
* StringUtil.addMinusChar("20100901") = "2010-09-01"
* </pre>
*
* @param date 입력받는 문자열
* @return " - "가 추가된 입력문자열
*/
public static String addMinusChar(String date) {
if (date.length() == 8) {
return date.substring(0, 4).concat("-").concat(date.substring(4, 6)).concat("-")
.concat(date.substring(6, 8));
} else {
return "";
}
}
/**
* <p>시간 형식의 문자열 내부에 character(:)를 추가한다.</p>
*
* <pre>
* StringUtil.addColonChar("0000") = "00:00"
* </pre>
*
* @param time 입력받는 문자열
* @return ":"가 추가된 입력문자열
*/
public static String addColonChar(String time) {
if (time.length() == 4) {
return time.substring(0, 2).concat(":").concat(time.substring(2, 4));
} else {
return "";
}
}
/**
* 휴대폰번호를 전환한다.
*
* @param rawPhone EX) "+82 10-1234-5678"
* @return DB에 넣을 번호
*/
public static String formatKoreanPhoneNumber(String rawPhone) {
if (rawPhone == null || rawPhone.isEmpty()) {
return "";
}
// Step 1: 공백 -> 하이픈, 숫자/하이픈만 남김
String cleaned = rawPhone.replaceAll("\\s+", "-").replaceAll("[^0-9\\-]", "");
// Step 2: 국가번호 +82 → 0으로 변경
if (cleaned.startsWith("82")) {
cleaned = "0" + cleaned.substring(2);
}
// Step 3: 하이픈 제거 후 숫자만 추출
String digits = cleaned.replaceAll("-", "");
// Step 4: 패턴 매칭 및 하이픈 삽입
String formatted;
if (digits.matches("^01[016789]\\d{7,8}$")) {
// 휴대폰
formatted = digits.replaceFirst("(\\d{3})(\\d{3,4})(\\d{4})", "$1-$2-$3");
} else if (digits.matches("^02\\d{7,8}$")) {
// 서울
formatted = digits.replaceFirst("(02)(\\d{3,4})(\\d{4})", "$1-$2-$3");
} else if (digits.matches("^0\\d{2}\\d{7,8}$")) {
// 지방 지역번호
formatted = digits.replaceFirst("(0\\d{2})(\\d{3,4})(\\d{4})", "$1-$2-$3");
} else {
return digits; // 매칭 안 되면 숫자만 반환
}
// Step 5: 최종적으로 하이픈 제거
return formatted.replaceAll("-", "");
}
}

View File

@@ -0,0 +1,94 @@
package com.wb.domainserver.util.util;
import com.wb.domainserver.util.string.StringUtil;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class Util {
/**
* 값 비교후 checked 처리
*
* @param arg1 비교값 1
* @param arg2 비교값 2
* @return the string
*/
public static String setChecked(String arg1, String arg2) {
return (arg1.equals(arg2)) ? " checked" : "";
}
/**
* 값 비교후 checked 처리
*
* @param arg1 the arg1
* @param arg2 the arg2
* @return the string
*/
public static String setChecked(boolean arg1,boolean arg2) {
return (arg1 == arg2) ? " checked" : "";
}
/**
* 값 비교후 checked 처리
*
* @param arg1 the arg1
* @param arg2 the arg2
* @return the string
*/
public static String setChecked(int arg1,int arg2) {
return (arg1 == arg2) ? " checked" : "";
}
/**
* 값 비교후 selected 처리
*
* @param arg1 비교값 1
* @param arg2 비교값 2
* @return the string
*/
public static String setSelected(String arg1, String arg2) {
return (arg1.equals(arg2)) ? " selected" : "";
}
/**
* 값 비교
*
* @param arg1 the arg1
* @param arg2 the arg2
* @return the string
*/
public static String setCheckedArray(String[] arg1, String arg2) {
return Arrays.asList(arg1).contains(arg2) ? " checked" : "";
}
public static String getDeviceType(HttpServletRequest request) {
Object deviceTypeAttr = request.getAttribute("deviceType");
return deviceTypeAttr != null ? deviceTypeAttr.toString() : "unknown";
}
public static Map<String, String> getRequestInfo(HttpServletRequest request) {
Map<String, String> requestInfo = new HashMap<>();
requestInfo.put("referer", request.getHeader("referer")); // 접속 경로
requestInfo.put("userAgent", request.getHeader("User-Agent")); // 시스템 정보
requestInfo.put("host", request.getHeader("host")); // 접속 ip
// 접속 ip
String clientIp = request.getHeader("X-Forwarded-For");
if (!StringUtil.isEmpty(clientIp) && clientIp.contains(",")) {
clientIp = clientIp.split(",")[0];
}
if (StringUtil.isEmpty(clientIp)) {
clientIp = request.getRemoteAddr();
}
requestInfo.put("XForwardedFor", clientIp); // 클라이언트 ip 주소
return requestInfo;
}
}