diff --git a/build.gradle b/build.gradle index d5b0a57..0407db4 100644 --- a/build.gradle +++ b/build.gradle @@ -50,6 +50,10 @@ dependencies { implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security' // RestTemplate 대신 WebClient 사용 implementation group: 'org.springframework.boot', name: 'spring-boot-starter-webflux' + // validation + implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation' + // vuejs 파일 index 지정 + implementation group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf' // JSP 사용시 // implementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper' // implementation group: 'javax.servlet', name: 'jstl', version: '1.2' @@ -96,18 +100,6 @@ dependencies { // custom libs implementation fileTree(dir:'libs', include:'*.jar') - // mysql 사용시 - // https://mvnrepository.com/artifact/mysql/mysql-connector-java - implementation 'mysql:mysql-connector-java' - //implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.22' - //implementation group: 'mysql', name: 'mysql-connector-java', version: '5.1.47' - - // https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp - implementation group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4' - - // validation - implementation 'org.springframework.boot:spring-boot-starter-validation' - } bootJar { diff --git a/settings.gradle b/settings.gradle index 2706854..c747209 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1 @@ -rootProject.name = 'hubeasy-admin' - -// include ':cm-web-common' -// project(':cm-web-common').projectDir = new File(settingsDir, '../cm-web-common') +rootProject.name = 'hubez-admin' diff --git a/src/main/java/kr/co/uplus/ez/Scheduler.java b/src/main/java/kr/co/uplus/ez/Scheduler.java index 0b2b29f..99c70bd 100644 --- a/src/main/java/kr/co/uplus/ez/Scheduler.java +++ b/src/main/java/kr/co/uplus/ez/Scheduler.java @@ -1,15 +1,14 @@ package kr.co.uplus.ez; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import lombok.extern.slf4j.Slf4j; + +@Slf4j @Component public class Scheduler { - private static final Logger log = LoggerFactory.getLogger(Scheduler.class); - /** * 스케줄러 트리거는 해당영역에 선언 / 서비스영역은 별도 */ diff --git a/src/main/java/kr/co/uplus/ez/WebApplication.java b/src/main/java/kr/co/uplus/ez/WebApplication.java index 2984040..8a5dfd5 100644 --- a/src/main/java/kr/co/uplus/ez/WebApplication.java +++ b/src/main/java/kr/co/uplus/ez/WebApplication.java @@ -3,19 +3,18 @@ package kr.co.uplus.ez; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.core.env.AbstractEnvironment; -@SpringBootApplication(exclude = { SecurityAutoConfiguration.class }) -public class WebApplication extends SpringBootServletInitializer { +import kr.co.uplus.ez.common.utils.USecuritySupUtils; +import lombok.extern.slf4j.Slf4j; - private static final Logger log = LoggerFactory.getLogger(WebApplication.class); +@Slf4j +@SpringBootApplication +public class WebApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { @@ -32,6 +31,9 @@ public class WebApplication extends SpringBootServletInitializer { @PostConstruct public void onStartup() { + // 유플러스 마스킹 유틸 적용 + USecuritySupUtils.initMaskingRule(); + Thread checkThread = new Thread(new CheckProcess()); checkThread.setDaemon(true); checkThread.start(); @@ -44,10 +46,13 @@ public class WebApplication extends SpringBootServletInitializer { } } +/** + * 프로세스 hang 확인을 위한 1분마다 메모리 로깅 기능 + * 데몬 스레드 방식으로 스프링 관리 스레드 아님 + */ +@Slf4j class CheckProcess implements Runnable { - private static final Logger log = LoggerFactory.getLogger(CheckProcess.class); - private static final String PROC_NAME = "mhez-admin"; @Override public void run() { diff --git a/src/main/java/kr/co/uplus/ez/common/jwt/JwtAuthFilter.java b/src/main/java/kr/co/uplus/ez/common/jwt/JwtAuthFilter.java index 36dae6a..fde6026 100644 --- a/src/main/java/kr/co/uplus/ez/common/jwt/JwtAuthFilter.java +++ b/src/main/java/kr/co/uplus/ez/common/jwt/JwtAuthFilter.java @@ -1,8 +1,5 @@ package kr.co.uplus.ez.common.jwt; -import static kr.co.uplus.ez.config.SecurityConfig.LOGIN_API_URL; -import static kr.co.uplus.ez.config.SecurityConfig.PUBLIC_API_URL; - import java.io.IOException; import java.util.Map; @@ -22,34 +19,25 @@ import io.jsonwebtoken.impl.TextCodec; import kr.co.uplus.ez.common.data.Const; import kr.co.uplus.ez.common.utils.WebUtils; -public abstract class JwtAuthFilter extends OncePerRequestFilter { +public abstract class JwtAuthFilter extends OncePerRequestFilter { protected final JwtProperties jwtProps; - public JwtAuthFilter(JwtProperties jwtProps) { this.jwtProps = jwtProps; } public abstract String getToken(HttpServletRequest request); + public abstract void onValidateSuccess(HttpServletRequest request, HttpServletResponse response, Claims claims); - public abstract void onValidateException(HttpServletRequest request, HttpServletResponse response, JwtException exception); + + public abstract void onValidateException(HttpServletRequest request, HttpServletResponse response, + JwtException exception); @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { - if (WebUtils.isResourceRequest(request) || WebUtils.isMatchedUriPattern(request, "/login", - "/api/v1/bo/login/**", - "/v2/api-docs", - "/swagger-resources", - "/swagger-resources/**", - "/configuration/ui", - "/configuration/security", - "/swagger-ui.html", - "/webjars/**", - "/v3/api-docs/**", - "/swagger-ui/**", - "/")) { + if (WebUtils.isResourceRequest(request) || WebUtils.isMatchedUriPattern(request, "/api/v1/bo/login/**")) { chain.doFilter(request, response); return; } @@ -57,7 +45,7 @@ public abstract class JwtAuthFilter extends OncePerRequestFilter { // 쿠키에서 토큰 추출 (client - server token) String token = getToken(request); - if(token == null) { + if (token == null) { chain.doFilter(request, response); // go to the next filter in the filter chain return; } @@ -67,26 +55,24 @@ public abstract class JwtAuthFilter extends OncePerRequestFilter { try { // 4. 토큰 검증 - claims = Jwts.parser() - .setSigningKey(TextCodec.BASE64.decode(jwtProps.getKeyString())) - .parseClaimsJws(token) + claims = Jwts.parser().setSigningKey(TextCodec.BASE64.decode(jwtProps.getKeyString())).parseClaimsJws(token) .getBody(); - String subject = claims.getSubject(); - if(subject != null) { + String subject = claims.getSubject(); + if (subject != null) { onValidateSuccess(request, response, claims); // 5. 스프링 용 UsernamePasswordAuthenticationToken 객체 생성 @SuppressWarnings("unchecked") - Map principalMap = (Map) claims.get("principal"); + Map principalMap = (Map) claims.get("principal"); JwtUser user = JwtUser.createAuthUser(principalMap); - UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); + UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, null, + user.getAuthorities()); // 6. 사용자 인증 처리 (Now, user is authenticated) SecurityContextHolder.getContext().setAuthentication(auth); } - } - catch(JwtException e) { + } catch (JwtException e) { onValidateException(request, response, e); throw e; } diff --git a/src/main/java/kr/co/uplus/ez/common/utils/USecuritySupUtils.java b/src/main/java/kr/co/uplus/ez/common/utils/USecuritySupUtils.java new file mode 100644 index 0000000..6216b61 --- /dev/null +++ b/src/main/java/kr/co/uplus/ez/common/utils/USecuritySupUtils.java @@ -0,0 +1,251 @@ +package kr.co.uplus.ez.common.utils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.FileUtils; +import org.springframework.core.io.ClassPathResource; +import org.springframework.util.StringUtils; + +import lguplus.security.data.USecurityModule; +import lguplus.security.json.simple.parser.ParseException; +import lguplus.security.vulner.SetPolicyFile; + +public class USecuritySupUtils { + + private static final String RULE_NM = "UplusMR"; + private static final String RULE_FILE_NAME = "UplusMaskingRule"; + private static final String RULE_FILE_SUFFIX = "json"; + + /** + * 마스킹룰 JSON 파일 위치를 재지정 하기 위한 기능 + * USecuritySupUtils.initMaskingRule() + */ + public static void initMaskingRule() { + try { + ClassPathResource resource = new ClassPathResource(RULE_FILE_NAME + "." + RULE_FILE_SUFFIX); + InputStream inputStream = resource.getInputStream(); + File tmpFile = File.createTempFile(RULE_FILE_NAME, RULE_FILE_SUFFIX); + FileUtils.copyInputStreamToFile(inputStream, tmpFile); + SetPolicyFile.setRuleFile(RULE_NM, tmpFile.getPath()); + } catch (IOException | ParseException e) { + e.printStackTrace(); + } + } + + /** + * 카드정보 + * + * 앞3자리, 뒤4자리 남긴 후 마스킹 + * 단, 7자리 이하는 앞 3자리 남기고 마스킹 + * 3자리 이하는 모두 마스킹 + * ex) 123*-****-****-1234 + * USecuritySupUtils.maskingCardnum("1234-1234-1234-1234") + * + * @param value + * @return + */ + public static String maskingCardnum(String value) { + String v = ""; + if (StringUtils.hasText(value)) { + try { + v = USecurityModule.maskingApply(RULE_NM, "cardnum", value); + } catch (IOException | ParseException e) { + e.printStackTrace(); + } + } + return v; + } + + /** + * 전화번호 + * + * 국번 3자리 혹은 4자리 마스킹 + * 단, 8자리 이하는 뒤 4자리 남기고 마스킹 + * 4자리 이하는 모두 마스킹 + * ex) 02-****-1234 / 010-****-1234 + * USecuritySupUtils.maskingPhone("02-1234-1234") + * USecuritySupUtils.maskingPhone("010-1234-1234") + * + * @param value + * @return + */ + public static String maskingPhone(String value) { + String v = ""; + if (StringUtils.hasText(value)) { + try { + v = USecurityModule.maskingApply(RULE_NM, "phone", value); + } catch (IOException | ParseException e) { + e.printStackTrace(); + } + } + return v; + } + + /** + * 시리얼번호 + * + * 뒤 4자리 외 마스킹 + * 단, 4자리 이하는 모두 마스킹 + * ex) ***4567 + * USecuritySupUtils.maskingSerial("12345678") + * + * @param value + * @return + */ + public static String maskingSerial(String value) { + String v = ""; + if (StringUtils.hasText(value)) { + try { + v = USecurityModule.maskingApply(RULE_NM, "serial", value); + } catch (IOException | ParseException e) { + e.printStackTrace(); + } + } + return v; + } + + /** + * 계좌번호 + * + * 앞 3자리, 뒤 4자리 남긴 후 마스킹 + * 단, 7자리 이하는 앞 3자리 남기고 마스킹 + * 3자리 이하는 모두 마스킹 + * ex) 123-***-**3456 + * USecuritySupUtils.maskingAccountnum("123-123-123456") + * + * @param value + * @return + */ + public static String maskingAccountnum(String value) { + String v = ""; + if (StringUtils.hasText(value)) { + try { + v = USecurityModule.maskingApply(RULE_NM, "accountnum", value); + } catch (IOException | ParseException e) { + e.printStackTrace(); + } + } + return v; + } + + /** + * IP + * + * ipv4: Dot 기준으로 3번째 블록 마스킹 + * ex) 123.123.***.123 + * USecuritySupUtils.maskingIp("123.123.123.123") + * ipv6: Colon 기준으로 마지막 블록 마스킹 + * ex) 2001:0DB8:0:0:0:0:1428:**** + * USecuritySupUtils.maskingIp("2001:0DB8:0:0:0:0:1428:1234") + * + * @param value + * @return + */ + public static String maskingIp(String value) { + String v = ""; + if (StringUtils.hasText(value)) { + try { + v = USecurityModule.maskingApply(RULE_NM, "ip", value); + } catch (IOException | ParseException e) { + e.printStackTrace(); + } + } + return v; + } + + /** + * 이름 + * + * 성 뒤 이름의 첫자리 마스킹 + * ex) 홍*동, 허*설헌 + * USecuritySupUtils.maskingName("홍길동") + * + * @param value + * @return + */ + public static String maskingName(String value) { + String v = ""; + if (StringUtils.hasText(value)) { + try { + v = USecurityModule.maskingApply(RULE_NM, "name", value); + } catch (IOException | ParseException e) { + e.printStackTrace(); + } + } + return v; + } + + /** + * 주민번호 + * + * 뒤 6자리 마스킹 + * ex) 800101-1****** + * USecuritySupUtils.maskingJumin("800101-1234567") + * + * @param value + * @return + */ + public static String maskingJumin(String value) { + String v = ""; + if (StringUtils.hasText(value)) { + try { + v = USecurityModule.maskingApply(RULE_NM, "jumin", value); + } catch (IOException | ParseException e) { + e.printStackTrace(); + } + } + return v; + } + + /** + * 이메일주소 + * + * 계정 앞 3자리 외 마스킹 + * 단, 3자리 이하는 계정 모두 마스킹 + * ex) abc*****@hanmail.net + * USecuritySupUtils.maskingEmail("abcdefg@hanmail.net") + * + * @param value + * @return + */ + public static String maskingEmail(String value) { + String v = ""; + if (StringUtils.hasText(value)) { + try { + v = USecurityModule.maskingApply(RULE_NM, "email", value); + } catch (IOException | ParseException e) { + e.printStackTrace(); + } + } + return v; + } + + /** + * 주소 + * + * 도로명 뒤 마스킹(단 병기되는 동은 표시가능) 읍,면,동,리 이후 마스킹 또는 상세주소 제외 + * 단, 마스킹 대상이 없을 경우 (주소입력오류) + * 1) 1차로 숫자만 마스킹 + * 2) 숫자도 없을 경우 뒤에서 3자리 마스킹 + * ex) 서울시 마포구 월드컵북로 *** + * ex) 서울 영등포구 여의도동 **-* + * USecuritySupUtils.maskingAddress("서울시 마포구 월드컵북로 200-1") + * + * @param value + * @return + */ + public static String maskingAddress(String value) { + String v = ""; + if (StringUtils.hasText(value)) { + try { + v = USecurityModule.maskingApply(RULE_NM, "address", value); + } catch (IOException | ParseException e) { + e.printStackTrace(); + } + } + return v; + } + +} diff --git a/src/main/java/kr/co/uplus/ez/config/SecurityConfig.java b/src/main/java/kr/co/uplus/ez/config/SecurityConfig.java index 60e957e..a7c0de9 100644 --- a/src/main/java/kr/co/uplus/ez/config/SecurityConfig.java +++ b/src/main/java/kr/co/uplus/ez/config/SecurityConfig.java @@ -20,7 +20,6 @@ import org.springframework.web.cors.CorsUtils; import kr.co.uplus.ez.api.login.LoginFailureHandler; import kr.co.uplus.ez.api.login.LoginSuccessHandler; -import kr.co.uplus.ez.common.data.ConfigProps; import kr.co.uplus.ez.common.jwt.JwtAuthCookieFilter; import kr.co.uplus.ez.common.jwt.JwtAuthHeaderFilter; import kr.co.uplus.ez.common.jwt.JwtExceptionFilter; @@ -31,7 +30,7 @@ import kr.co.uplus.ez.config.filter.VueStaticFilter; @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { - private static final String LOGIN_FORM_URL = "/login/**"; + private static final String LOGIN_FORM_URL = "/login"; public static final String LOGIN_API_URL = "/api/v1/bo/login"; public static final String LOGIN_FAIL_URL = "/login?error=true"; public static final String LOGIN_SUCC_URL = "/"; @@ -43,19 +42,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { private static final String[] PERMIT_URL_ARRAY = { "/login", "/api/v1/bo/login/**", - "/v2/api-docs", - "/swagger-resources", - "/swagger-resources/**", - "/configuration/ui", - "/configuration/security", - "/swagger-ui.html", - "/webjars/**", - "/v3/api-docs/**", - "/swagger-ui/**", + "/swagger-ui/**", + "/swagger-resources/**", + "/v3/api-docs", + "/v3/api-docs/**", "/" }; - private static final String[] AUTH_URL_ARRAY = { "/api/v1/bo/login/*", "/api/v1/bo/comm/**", @@ -75,16 +68,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; - @Autowired - private ConfigProps cprops; @Autowired private JwtProperties jwtProps; -// @Autowired -// private AuthService authService; - - - @Override public void configure(WebSecurity web) throws Exception { web.ignoring() @@ -100,7 +86,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { public void configure(HttpSecurity http) throws Exception { http .addFilterBefore(new VueStaticFilter(), UsernamePasswordAuthenticationFilter.class) // Vue에서 호출시 화면관련 URL은 / forward -// .addFilterBefore(new XssFilter(cprops), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(new JwtExceptionFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(jwtAuthFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(new JwtAuthHeaderFilter(jwtProps), UsernamePasswordAuthenticationFilter.class); diff --git a/src/main/java/kr/co/uplus/ez/config/SwaggerConfig.java b/src/main/java/kr/co/uplus/ez/config/SwaggerConfig.java index c2b4ed7..1c90a0c 100644 --- a/src/main/java/kr/co/uplus/ez/config/SwaggerConfig.java +++ b/src/main/java/kr/co/uplus/ez/config/SwaggerConfig.java @@ -2,8 +2,6 @@ package kr.co.uplus.ez.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; @@ -15,20 +13,12 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 -public class SwaggerConfig extends WebMvcConfigurationSupport { +public class SwaggerConfig { - private static final String API_TITLE = "HubEasy Admin"; - private static final String API_DESC = "허브이지 어드민에서 사용되는 API 문서입니다."; + private static final String API_TITLE = "mhez-admin"; + private static final String API_DESC = "U+메시지허브이지 어드민에서 사용되는 API 문서입니다."; private static final String API_VER = "1.0"; - @Override - protected void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/swagger-ui/**") - .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/"); - registry.addResourceHandler("/webjars/**") - .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/"); - } - @Bean public Docket api() { return new Docket(DocumentationType.OAS_30).useDefaultResponseMessages(false).select() diff --git a/src/main/java/kr/co/uplus/ez/config/WebMvcConfig.java b/src/main/java/kr/co/uplus/ez/config/WebMvcConfig.java new file mode 100644 index 0000000..116330c --- /dev/null +++ b/src/main/java/kr/co/uplus/ez/config/WebMvcConfig.java @@ -0,0 +1,22 @@ +package kr.co.uplus.ez.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; + +@Configuration +public class WebMvcConfig extends WebMvcConfigurationSupport { + + /** + * swagger 및 정적파일 경로 지정 + */ + @Override + protected void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/swagger-ui/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/"); + registry.addResourceHandler("/webjars/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/"); + registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); + } + +} diff --git a/src/main/java/kr/co/uplus/ez/config/filter/VueStaticFilter.java b/src/main/java/kr/co/uplus/ez/config/filter/VueStaticFilter.java index ecc2ec8..0e7130b 100644 --- a/src/main/java/kr/co/uplus/ez/config/filter/VueStaticFilter.java +++ b/src/main/java/kr/co/uplus/ez/config/filter/VueStaticFilter.java @@ -1,6 +1,7 @@ package kr.co.uplus.ez.config.filter; import java.io.IOException; +import java.util.Arrays; import javax.servlet.FilterChain; import javax.servlet.ServletException; @@ -10,33 +11,32 @@ import javax.servlet.http.HttpServletRequest; import org.springframework.web.filter.GenericFilterBean; -// http://www.servletsuite.com/servlets/xssflt.htm public class VueStaticFilter extends GenericFilterBean { + // Vuejs router url prefix 선언 + private static final String[] FRONTEND_URLS = { "/view", "/custMgt", "/sysMgt", "/attractMgt", "/servMgt", + "/calculate", "/channelMgt", "/sendNumMgt", "/mntrng", "/riskMgt", "/stats" }; + @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (shouldExclude(request)) { chain.doFilter(request, response); - // some logic so the request doesnt go to the servlet - - // maybe you could just forward - // the request directly to the file getting accessed. not sure if that would - // work } else { + // vuejs에 해당하는 페이지는 index를 바라보도록 전달 ((HttpServletRequest) request).getRequestDispatcher("/").forward(request, response); } - - // file should be passed to the servlet; you can do some logic here - // if you want } private boolean shouldExclude(ServletRequest req) { + boolean isEx = true; if (req instanceof HttpServletRequest) { HttpServletRequest hreq = (HttpServletRequest) req; - return !(hreq.getRequestURI().startsWith("/view")); + if (Arrays.stream(FRONTEND_URLS).anyMatch(s -> hreq.getRequestURI().startsWith(s))) { + return false; + } } - return true; + return isEx; } } \ No newline at end of file diff --git a/src/main/java/kr/co/uplus/ez/view/main/MainViewController.java b/src/main/java/kr/co/uplus/ez/view/main/MainViewController.java new file mode 100644 index 0000000..6c01bad --- /dev/null +++ b/src/main/java/kr/co/uplus/ez/view/main/MainViewController.java @@ -0,0 +1,150 @@ +package kr.co.uplus.ez.view.main; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; + +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import kr.co.uplus.ez.common.data.ApiResponseCode; +import kr.co.uplus.ez.common.data.ApiResponseMessage; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Controller +public class MainViewController { + + // Vue일 경우 index로 전달 + @GetMapping("/") + public String home() { + return "index"; + } + + /* + * 엑셀 업로드 poi 4.1 사용 테스트 x + */ + @PostMapping("/insertFileXcel") + @ResponseBody + public ApiResponseMessage insertFileXcel(MultipartHttpServletRequest multipartRequest) { + + MultipartFile file = multipartRequest.getFile("file"); + String colName = multipartRequest.getParameter("colName"); + ApiResponseMessage result = new ApiResponseMessage(ApiResponseCode.SUCCESS); + + try { + int rowindex = 0; + int columnindex = 0; + + InputStream in = file.getInputStream(); + @SuppressWarnings("resource") + XSSFWorkbook workbook = new XSSFWorkbook(in); + XSSFSheet sheet = workbook.getSheetAt(0); + + int rows = sheet.getPhysicalNumberOfRows(); + + if (rows > 10000 || rows < 1) { + // 엑셀 로우 건수가 10000건이 넘으면 false 반환 + result.setData(false); + } else { + HashMap xcelData = new HashMap(); + for (rowindex = 0; rowindex < rows; rowindex++) { + XSSFRow row = sheet.getRow(rowindex); + if (row != null) { + int cells = row.getPhysicalNumberOfCells(); + for (columnindex = 0; columnindex <= cells - 1; columnindex++) { + // 셀값을 읽는다 + XSSFCell cell = row.getCell(columnindex); + String value = ""; + + if (cell == null) { + continue; + } else { + // 타입별로 내용 읽기 + switch (cell.getCellType()) { + case FORMULA: + value = cell.getCellFormula(); + break; + case NUMERIC: + value = cell.getNumericCellValue() + ""; + break; + case STRING: + value = cell.getStringCellValue() + ""; + break; + case BLANK: + value = cell.getBooleanCellValue() + ""; + break; + } + } + if ("false".equals(value)) { + // logger.info(rowindex+"번 행 Error :" +value); + + break; + } else { + // logger.info(rowindex+"번 행 : "+columnindex+"번 열 값은: "+value); + // xcelData.put(value, value) + } + } + } + XSSFCell cell = row.getCell(columnindex); + } + result.setData(true); + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + log.info("data : {}", result); + return result; + } + + /* + * 엑셀 업로드 poi 3.13 사용 rcs에서 테스트 완료 + */ + + /* + * @PostMapping("/insertFileXcel") + * + * @ResponseBody public Result insertFileXcel(MultipartHttpServletRequest + * multipartRequest){ + * + * MultipartFile file = multipartRequest.getFile("file"); String colName = + * multipartRequest.getParameter("colName"); Result> result = + * new Result<>(); + * + * try { int rowindex=0; int columnindex=0; + * + * InputStream in = file.getInputStream(); + * + * @SuppressWarnings("resource") XSSFWorkbook workbook = new XSSFWorkbook(in); + * XSSFSheet sheet=workbook.getSheetAt(0); + * + * int rows=sheet.getPhysicalNumberOfRows(); // 엑셀 갯수 if(rows > 100 || rows < 1) + * { result.setSuccess(false); }else { HashMap xcelData = new + * HashMap(); for(rowindex=0;rowindex insertFileXcel(MultipartHttpServletRequest multipartRequest){ - - MultipartFile file = multipartRequest.getFile("file"); - String colName = multipartRequest.getParameter("colName"); - ApiResponseMessage result = new ApiResponseMessage(ApiResponseCode.SUCCESS); - - try { - int rowindex=0; - int columnindex=0; - - InputStream in = file.getInputStream(); - @SuppressWarnings("resource") - XSSFWorkbook workbook = new XSSFWorkbook(in); - XSSFSheet sheet=workbook.getSheetAt(0); - - int rows=sheet.getPhysicalNumberOfRows(); - - if(rows > 10000 || rows < 1) { - // 엑셀 로우 건수가 10000건이 넘으면 false 반환 - result.setData(false); - }else { - HashMap xcelData = new HashMap(); - for(rowindex=0;rowindex insertFileXcel(MultipartHttpServletRequest multipartRequest){ - - MultipartFile file = multipartRequest.getFile("file"); - String colName = multipartRequest.getParameter("colName"); - Result> result = new Result<>(); - - try { - int rowindex=0; - int columnindex=0; - - InputStream in = file.getInputStream(); - @SuppressWarnings("resource") - XSSFWorkbook workbook = new XSSFWorkbook(in); - XSSFSheet sheet=workbook.getSheetAt(0); - - int rows=sheet.getPhysicalNumberOfRows(); - // 엑셀 갯수 - if(rows > 100 || rows < 1) { - result.setSuccess(false); - }else { - HashMap xcelData = new HashMap(); - for(rowindex=0;rowindex