반응형

개발하면서 카카오톡에서 바로 브라우저 실행하여 인앱브라우저에서 실행하는 경우가 많은데

//탭닫기
self.close()

안 통하므로 카카오톡 스키마를 통해 브라우저를 닫을 수가 있어요.


var os = window.navigator.userAgent || window.navigator.vgjendor || window.opera;
	
if(os.toLocaleLowerCase().indexOf("android") > -1){
		
	location.href = “kakaotalk://inappbrowser/close”;
    
}else if(os.toLocaleLowerCase().indexOf("iphone") > -1 
			|| os.toLocaleLowerCase().indexOf("ipad") > -1){
		
	location.href = "kakaoweb://closeBrowser";
}else{
		
	self.close();
}

위와 같이 안드로이드 아이폰 나눠서 실행하면 인앱브라우저를 닫을 수 있어요.

반응형

'개발 > Web' 카테고리의 다른 글

Thymeleaf each value sum  (2) 2020.12.15
Thymeleaf Layout구성  (2) 2020.12.06
Thymeleaf spring security 사용하기  (5) 2020.12.02
Thymeleaf 문법  (2) 2020.12.01
반응형

이번에 개발을 하면서

- 1시간 안에 본인증 문자 발송이 5회 이상 안되도록

- 본인증이 완료가 되면 5회 카운터 초기화

이 2가지 조건을 만족하게 열심히 검색하고 쿼리를 만들어봤어요. 찾아보니 "5일 연속 지각" 이런 게시글이 많이 보여서 참고를 했어요.

01011112222 발송완료 2024/02/06 18:01:01
01011112222 인증완료 2024/02/06 18:00:01
01011112222 발송완료 2024/02/06 17:59:01
01011112222 발송완료 2024/02/06 17:58:01
01011112222 발송완료 2024/02/06 17:57:01
01011112222 발송완료 2024/02/06 17:56:01

샘플 데이터가 있어요

발송완료 2024/02/06 18:01:01
인증완료 2024/02/06 18:00:01
발송완료 2024/02/06 17:59:01
발송완료 2024/02/06 17:58:01
발송완료 2024/02/06 17:57:01
발송완료 2024/02/06 17:56:01

5번째에 인증을 완료했으므로 발송 횟수를 초기화

발송완료 2024/02/06 18:01:01 N
인증완료 2024/02/06 18:00:01 Y
발송완료 2024/02/06 17:59:01 N
발송완료 2024/02/06 17:58:01 N
발송완료 2024/02/06 17:57:01 N
발송완료 2024/02/06 17:56:01 N

6번째에는 발송이되야 하고

발송완료 2024/02/06 18:01:01 N
발송완료 2024/02/06 18:00:01 N
발송완료 2024/02/06 17:59:01 N
발송완료 2024/02/06 17:58:01 N
발송완료 2024/02/06 17:57:01 N
발송완료 2024/02/06 17:56:01 N

6번째에 발송이 안되어야 해요.

그럼 어떻게 이걸 체크를 했는지 쿼리를 작성해 볼게요.

 

SELECT
	CASE WHEN LISTAGG(YN) WITHIN GROUP (ORDER BY 등록시간) LIKE '%YYYYY%' THEN 'Y' ELSE 'N' END
FROM (
		SELECT 핸드폰번호,결과,등록시간
      		DECODE(결과,'발송완료','Y','N') AS YN
        FROM TABLE
        WHERE 등록시간 > SYSDATE - 1 / 24 --지금부터 1시간이내
        AND 핸드폰번호 = '01011112222'
        ORDER BY 등록시간 DESC
)

해당방법으로 Y가 연속으로 몇 개 있냐 이걸로 5번 발송요청 4번 발송요청 이렇게 조절을 할 수 있어요.

 

해당쿼리로

- 1시간 안에 본인증 문자 발송이 5회 이상 안되도록

- 본인증이 완료가 되면 5회 카운터 초기화

두 가지 조건을 만족하여 개발을 했습니다. 처음에 요건을 들었을 때 JAVA에서 풀어야 하나 고민을 했지만 역시 검색으로 힌트를 얻어 쿼리로 해결을 했어요.

반응형

'개발 > DB' 카테고리의 다른 글

Mysql 컬럼 예약어 사용  (0) 2021.01.18
MariaDB Sequence(10.3)이상  (0) 2020.11.12
반응형

모바일 브라우저에서스크롤에따라 주소창,하단 탭바등이 동적으로 나왔다가 사라졌다하며 scrollTop이 이상하게 동작할경우 주소창을 고정할수는방법이있어 공유할려구해요.

//해당 컨텐츠 마지막으로 가야하지만 스크롤에따라 주소창,탭에따라 동작이 안될경우
$(".contents").scrollTop($(".contents").prop("scrollTop"));

//창을 고정하면 스크롤에따라 화면이 변화가 없으므로 scrollTop이 원하는곳으로 이동이될거에요
setTimeout(scrollTo,0 ,0, $(document).outerHeight());
$(".contents").scrollTop($(".contents").prop("scrollTop"));

 

반응형

'개발 > Javascript' 카테고리의 다른 글

Javascript canvas 캡처이미지 그리기  (0) 2021.08.24
IE opener가 undefined  (0) 2021.03.25
Jquery Datepicker 동적생성  (0) 2021.03.03
Jquery each break,continue  (0) 2021.02.17
Jquery sort 사용하기  (0) 2021.02.15
반응형

이번에 프로젝트를 하면서 화면 캡처 기능을 만들어야 하는데 script로 간단하게 해주는 라이브러리가 있어 사용하게 되었어요.

 

js파일은 해당 링크에있어요

 

https://html2canvas.hertzen.com/

 

html2canvas - Screenshots with JavaScript

Try out html2canvas Test out html2canvas by rendering the viewport from the current page. Capture

html2canvas.hertzen.com

 

//사용법은 간단해요
//document.querySelector("#capture") 부분에 화면에서 캡처할 element를 넣어주면되요
html2canvas(document.querySelector("#capture")).then(canvas => {
   
	var dataURL = canvas.toDataURL("image/png");
	//저는 dataURL ajax로 서버로 보내어 서버에서 파일로 저장을 했어요
   
});

혹시 예전 버전을 사용해서 캡처 태그들이 깨지면 최신 버전을 적용해서 다시 해보세요.

제가 하던 프로젝트에서 아이폰에서 "SecurityError: The operation is insecure" 에러가 발생하여 원인을 살펴보니

body {
  background-color: #000;
}

#element {
  background-color: rgba(var(--color), 0.8);
}

이번 프로젝트에서는 variable? 방식으로 css가 되었는데 아이폰에서 저 부분을 컬러 값을 직접 입력했더니 에러 없이 정상작동을 하네요.

반응형

'개발 > Javascript' 카테고리의 다른 글

모바일 주소창때문에 scrollTop이 동작이 안될경우  (0) 2022.04.02
IE opener가 undefined  (0) 2021.03.25
Jquery Datepicker 동적생성  (0) 2021.03.03
Jquery each break,continue  (0) 2021.02.17
Jquery sort 사용하기  (0) 2021.02.15
반응형

Chrome에 opener가 문제가 없는데 IE에서 발생하여 확인한 결과

페이지 -> 팝업호출 -> 다시페이지 호출은 정상적으로 동작을 하는데

페이지 -> 팝업호출 -> 외부페이지 -> 팝업페이지 -> 다시페이지 호출일 경우 IE에서 opener가 undefined발생

window.onload = function(){

		var url = location.href;
		var inputYn= juso.inputYn;

		if(inputYn != "Y"){
			
			document.form.returnUrl.value = url;
			document.form.resultType.value = resultType; // resultType항목 추가(2016.10.06)
			document.form.action="https://www.juso.go.kr/addrlink/addrLinkUrl.do"; // 인터넷망

			document.form.submit();
		}else{
			/** API 서비스 제공항목 확대 (2017.02) **/
			opener.jusoCallBack(JSON.stringify(juso));
			window.close();
		}

}

다른 브라우저에서는 문제가 없는데 IE에서 opener undefined발생

window.onload = function(){

	var url = location.href;
				
	var resultType = "4"; // 도로명주소 검색결과 화면 출력유형, 1 : 도로명, 2 : 도로명+지번, 3 : 도로명+상세건물명, 4 : 도로명+지번+상세건물명
	var inputYn= juso.inputYn;

	if(inputYn != "Y"){

		document.form.confmKey.value = confmKey;
		document.form.returnUrl.value = url;
		document.form.resultType.value = resultType; // resultType항목 추가(2016.10.06)
		document.form.action="https://www.juso.go.kr/addrlink/addrLinkUrl.do"; // 인터넷망
		document.form.submit();
	}else{
		// 수정버전
		if(opener == null || opener == undefined) opener = window.open("", "jusoPopup");

		/** API 서비스 제공항목 확대 (2017.02) **/
		opener.jusoCallBack(JSON.stringify(juso));
		window.open("about:blank", "_self").close();
					
	}

}

www.juso.go.kr/addrlink/devCenterEventBoardDetail.do?regSn=716&noticeType=T&currentPage=4&keyword=&searchType=

 

Tech & Tips 상세보기 | 도로명주소 개발자센터

 

www.juso.go.kr

 

반응형
반응형

오늘은 프로젝트에서 적용한 일괄등록에서 사용한 @Async를 포스팅해볼게요.

월래는 Batch를 이용하여 새벽시간에 동작을 하도록 적용을 하였는데 @Async를 이용하여 빠르게 선처리 작업을 하고 이후 Async메서드를 호출하여 비동기 방식으로 작동하도록 구현을 하였습니다.

@Configuration
@EnableScheduling
@EnableAsync
public class AsyncThreadConfiguration {

	@Bean(name = "asyncExecutor")
	public Executor asyncThreadTaskExecutor() {
		ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
		threadPoolTaskExecutor.setCorePoolSize(2); //최초생성수
		threadPoolTaskExecutor.setMaxPoolSize(4); //max생성수
		threadPoolTaskExecutor.setThreadNamePrefix("fabs-batch-pool");

		return threadPoolTaskExecutor;
	}

	public class HandlingExecutor implements AsyncTaskExecutor {
		private final AsyncTaskExecutor executor;

		public HandlingExecutor(AsyncTaskExecutor executor) {
			this.executor = executor;
		}

		@Override
		public void execute(Runnable task) {
			executor.execute(createWrappedRunnable(task));
		}

		@Override
		public void execute(Runnable task, long startTimeout) {
			executor.execute(createWrappedRunnable(task), startTimeout);
		}

		@Override
		public Future<?> submit(Runnable task) {
			return executor.submit(createWrappedRunnable(task));
		}

		@Override
		public <T> Future<T> submit(final Callable<T> task) {
			return executor.submit(createCallable(task));
		}

		private <T> Callable<T> createCallable(final Callable<T> task) {
			return () -> {
				try {
					return task.call();
				} catch (Exception ex) {
					handle(ex);
					throw ex;
				}
			};
		}

		private Runnable createWrappedRunnable(final Runnable task) {
			return () -> {
				try {
					task.run();
				} catch (Exception ex) {
					handle(ex);
				}
			};
		}

		private void handle(Exception ex) {
			log.info("Failed to execute task. : {}", ex.getMessage());
			log.error("Failed to execute task. ", ex);
		}

		public void destroy() {
			if (executor instanceof ThreadPoolTaskExecutor) {
				((ThreadPoolTaskExecutor) executor).shutdown();
			}
		}
	}

먼저 ThreadPool설정입니다. 

setCorePoolSize 최초 생성 시 사용되는 Thread 수입니다.

setMaxPoolSize 생성할 수 있는 Thread Max값입니다. 

setThreadNamePrefix ThreadPool이 여러 곳에서 사용이 되면 알아볼 수 있도록 Name을 지정합니다.

@Bean(name = "asyncExecutor") <- "asyncExecutor"이름으로 비동기 호출을 사용할 수 있습니다.

//Controller Class
@RequestMapping(value = "/excelUpload", method = RequestMethod.POST)
public ResponseEntity<HttpResponse<?>> excelUpload(MultipartHttpServletRequest req, HttpServletResponse res,
    @AuthenticationPrincipal UserAuthentication userAuthentication) throws Exception {
    
    //비동기 Method호출
    Service.add(reqFundManagement);
    
    //비동기 Method 실행이 다 완료 안되더라도 이후 코드 실행
    
}

//Service Class

@Async("asyncExecutor")
public void add(ReqFundManagement reqFundManagement) {
    // 필요한 소스구현
}

기존 방식은

1) Excel업로드

2) 대상자 추출(LIST)

3) 대상자 등록

4) 대상자 API를 이용해 데이터 가져오기

대상자가 많을수록 3->4번이 대기 시간들이 길어져서 Batch로 만들려고 고민 중에 비동기 호출 방식 확인

비동기

1) Excel업로드

2) 대상자 추출(LIST)

3) 대상자 등록

4) 대상자 API를 이용해 데이터 가져오기

호출 순서는 같은데 3->4번 실행 후 4번 응답 대기 없이 바로 3->4가 반복을 하여 3번 대상자 먼저 등록이 되고 4번은  비동기로 작동이 돼서 여러 건을 동시에 가져와서 호출 시간이 절약이 되었어요.

 

반응형

'개발 > Java' 카테고리의 다른 글

Java Excel Upload  (0) 2021.02.25
이클립스 Formatter off  (0) 2021.02.16
Java 단방향,양방향 암호화  (1) 2021.01.25
Spring RestTemplate Converter오류  (0) 2021.01.14
List 중복 제거 및 List 정렬(Collections.sort)  (1) 2021.01.04
반응형

Jquery Datepicker를 동적으로 생성을 하면 동작을 안 하는데 동적 생성법을 포스팅해볼게요.

$(document).ready(function(){
	
    function 동적생성(){
    
    	//페이지에 적용된 class를 삭제
    	$(".ui-datepicker-trigger").remove();
        //필요한 Datepicker에 다시 적용
	$("input[name='researchStartDtm'],input[name='researchEndDtm']").removeClass('hasDatepicker').datepicker();
    
    }
    
});

위 코드처럼 기존 class를 삭제를 하고 다시 적용을 시켜주면 정상 작동을 할 수 있습니다.

반응형

'개발 > Javascript' 카테고리의 다른 글

Javascript canvas 캡처이미지 그리기  (0) 2021.08.24
IE opener가 undefined  (0) 2021.03.25
Jquery each break,continue  (0) 2021.02.17
Jquery sort 사용하기  (0) 2021.02.15
Javascript delete Json  (0) 2021.01.22
반응형

Java에서 excel 파일을 읽을 때 대부분 apache-poi lib를 사용을 할 거예요 저도 poi를 사용하여 구현을 했어요.

compile group: 'org.apache.poi', name: 'poi', version: '4.1.2'
compile group: 'org.apache.poi', name: 'poi-ooxml', version: '4.1.2'

4.1.2 버전을 사용을 했어요.

보통 2003,통합문서 2가지 버전들이 있는데 org.apache.poi.ss.usermodel.WorkbookFactory를 이용하면 포맷 구분 없이 읽을 수 있어요.

 

예를 들어 위 해당하는 문서를 읽을경우를 해볼게요.

//엑셀파일을 넣구 Wookbook를 생성합니다
Workbook workbook = WorkbookFactory.create(file1.getInputStream());

int rowindex = 0;
int cellindex = 0;
//시트 수 (첫번째에만 존재하므로 0을 준다)
//만약 각 시트를 읽기위해서는 FOR문을 한번더 돌려준다
Sheet sheet = workbook.getSheetAt(0);
//행의 수
int rows = sheet.getPhysicalNumberOfRows();
//3번째 row부터 읽기위해 rowindex는 2부터
for (rowindex = 2; rowindex < rows; rowindex++) {
	//행을읽는다
	Row row = sheet.getRow(rowindex);
	
    //row값이 있으면
	if (row != null) {
			//B3부터 데이터 추출
        	//엑셀에 데이터 형식에 따라 get방식이 달르게 가져와야해요 전 전부 일반으로 설정을하고 가져오고 있어요        
        	for (cellindex = 1; cellindex < row.getPhysicalNumberOfCells(); cellindex++) {

			System.out.println(getStringValue(row.getCell(cellindex)));

		}
        
	}
            
}


public static String getStringValue(Cell cell) {
	String rtnValue = "";
	try {
		rtnValue = cell.getStringCellValue();
	} catch (IllegalStateException e) {
		rtnValue = Integer.toString((int) cell.getNumericCellValue());
	} catch (NullPointerException e) {
		rtnValue = "";
	}

	return rtnValue;
}

cell이 늘어남에 따라 row.getCell(1) 2,3,4.... 이렇게 계속할 수 없어 for문을 사용했어요.

 

그럼 B3~F3까지 데이터를 와서 sysout으로 출력을 하고 있어요. 엑셀에 데이터 방식에 따라 cell처리 방식들이 다른데 저는 전부 텍스트 형식으로 지정하고 업로드를 했어요

 

반응형
반응형

종종 Jquery each를 사용 중에 break, continue가 필요한 경우가 있는데 그때 사용방법 포스팅해볼게요.

//checkbox체크된 값중에 특정값이 있으면 break를 하고싶을경우
$("input[name='lumpId']:checked").each(function(i,o){

	if ( //조건 ) {

		return false; //break;
        
	}

	formData.push(o.value);

});
//checkbox체크된 값중에 특정값이 있으면 continue를 하고싶을경우
$("input[name='lumpId']:checked").each(function(i,o){

	if ( //조건 ) {

		return true; //continue
        
	}

	formData.push(o.value);

});

each 중에 return false는 break이고 return true는 continue입니다.

반응형

'개발 > Javascript' 카테고리의 다른 글

IE opener가 undefined  (0) 2021.03.25
Jquery Datepicker 동적생성  (0) 2021.03.03
Jquery sort 사용하기  (0) 2021.02.15
Javascript delete Json  (0) 2021.01.22
Jquery 이벤트 여러번발생  (0) 2020.11.05
반응형

이클립스로 개발 중에 save action에 지정된 formatter방식으로 저장이 되는데 간혹 소스가 길어져서 가독성이 안 좋게 저장이 되면 그 라인은 formatter가 적용 안되게 off 할 수가 있습니다.

	public static enum ProgressStatus_new {

		RECEPTION(238, "접수완료", "241"), VERIFICATION(239, "현장검증완료", "VERIFICATION"), PRIMARY(240, "읍면동 최종확인",
		    "PRIMARY"), COMPLETE(241, "시군 최종확인", "COMPLETE"), END(242, "지급완료", "END"), REJECT_RECEPTION(243, "접수완료 반려",
		        "REJECT_RECEPTION"), REJECT_VERIFICATION(244, "현장검증 완료 반려", "REJECT_VERIFICATION"), REJECT_PRIMARY(245,
		            "읍면동 최종확인 반려", "REJECT_PRIMARY"), REJECT_COMPLETE(246, "시군 최종확인 반려", "REJECT_COMPLETE"), DENY_RECEPTION(
		                247, "접수완료 부정수급", "DEMY_RECEPTION"), DENY_VERIFICATION(248, "현장검증 완료 부정수급",
		                    "DENY_VERIFICATION"), DENY_PRIMARY(249, "읍면동 최종확인 부정수급", "DENY_PRIMARY"), DENY_COMPLETE(250,
		                        "시군최종확인 부정수급", "DENY_COMPLETE"), UNDEFINED(-1 - 199, "정의되지않음", "UNDEFINED");

		@Getter
		private Integer id;

		@Getter
		private String nm;

		@Getter
		private String alias;

		private ProgressStatus_new(Integer id, String nm, String alias) {
			this.id = id;
			this.nm = nm;
			this.alias = alias;
		}

		public static ProgressStatus_new get(Integer id) {
			for (ProgressStatus_new o : ProgressStatus_new.values()) {
				if (o.id.intValue() == id.intValue()) {
					return o;
				}
			}

			return UNDEFINED;
		}

		public static ProgressStatus_new get(String alias) {
			for (ProgressStatus_new o : ProgressStatus_new.values()) {
				if (o.alias.equals(alias)) {
					return o;
				}
			}

			return UNDEFINED;
		}

	}

적용된 formatter가 적용된 부분인데 선언 부분이 가독성이 너무 떨어져서

//@formatter:off
	public static enum ProgressStatus_new {

		RECEPTION(238, "접수완료", "241"),
		VERIFICATION(239, "현장검증완료", "VERIFICATION"),
		PRIMARY(240, "읍면동 최종확인","PRIMARY"),
		COMPLETE(241, "시군 최종확인", "COMPLETE"),
		END(242, "지급완료", "END"),
		REJECT_RECEPTION(243, "접수완료 반려","REJECT_RECEPTION"),
		REJECT_VERIFICATION(244, "현장검증 완료 반려", "REJECT_VERIFICATION"),
		REJECT_PRIMARY(245,"읍면동 최종확인 반려", "REJECT_PRIMARY"),
		REJECT_COMPLETE(246, "시군 최종확인 반려", "REJECT_COMPLETE"),
		DENY_RECEPTION(247, "접수완료 부정수급", "DEMY_RECEPTION"),
		DENY_VERIFICATION(248, "현장검증 완료 부정수급","DENY_VERIFICATION"),
		DENY_PRIMARY(249, "읍면동 최종확인 부정수급", "DENY_PRIMARY"),
		DENY_COMPLETE(250,"시군최종확인 부정수급", "DENY_COMPLETE"), UNDEFINED(-1 - 199, "정의되지않음", "UNDEFINED");

		@Getter
		private Integer id;

		@Getter
		private String nm;

		@Getter
		private String alias;

		private ProgressStatus_new(Integer id, String nm, String alias) {
			this.id = id;
			this.nm = nm;
			this.alias = alias;
		}

		public static ProgressStatus_new get(Integer id) {
			for (ProgressStatus_new o : ProgressStatus_new.values()) {
				if (o.id.intValue() == id.intValue()) {
					return o;
				}
			}

			return UNDEFINED;
		}

		public static ProgressStatus_new get(String alias) {
			for (ProgressStatus_new o : ProgressStatus_new.values()) {
				if (o.alias.equals(alias)) {
					return o;
				}
			}

			return UNDEFINED;
		}

	}
	//@formatter:on

보기 좋게 적용을 했어요. 기본적으로 off가 되어있는데

Window -> Preferences -> Java -> Code Style -> Formatter

사용 중인 formatter에서 edit를 누르시면

enable off가 되어있을겅에요. 이걸 활성화시키고 off/on 태그를 소스에 입력을 하시면 돼요. 만약 여러 명이 같이 하는 프로젝트일 경우 모든 사용자가 동일하게 기능 활성화를 해야 해요.

반응형

'개발 > Java' 카테고리의 다른 글

Spring @Async(비동기 Method) 사용하기  (0) 2021.03.18
Java Excel Upload  (0) 2021.02.25
Java 단방향,양방향 암호화  (1) 2021.01.25
Spring RestTemplate Converter오류  (0) 2021.01.14
List 중복 제거 및 List 정렬(Collections.sort)  (1) 2021.01.04

+ Recent posts