https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser?rq=1  에서 본 내용을 간단하게 정리해봄.




결과


'프로그래밍 > Javascript' 카테고리의 다른 글

How to detect browser.  (0) 13:00:00
IOS 버전 관련 처리  (0) 2018.07.20
[Jquery] .each에서 break, continue 구현하기.  (0) 2018.07.02
How to create dynamic a form!  (0) 2018.06.07
javascript replaceAll 사용하기  (0) 2018.03.08
Timer 구현하기  (0) 2017.01.25

1. IOS Useagent


Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1


2. 하고싶은 것

 - 11.4 버전 이상일 경우를 체크하고 싶다.


 - 소스

function osVersion(){
var mt = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);

if (mt === undefined || mt === null || nt === '') {
return false;
}

var version = [
parseInt(mt[1], 10),
parseInt(mt[2], 10),
parseInt(mt[3] || 0, 10)
];

return parseFloat(version.join('.'))
}

 - 사용법

if (osVersion() > 11.4) {
alert("에러");
}


* IOS 인지 아닌지에 대한 처리는 없습니다. 관련 소스는 추가해서 사용하세요 ^_^

'프로그래밍 > Javascript' 카테고리의 다른 글

How to detect browser.  (0) 13:00:00
IOS 버전 관련 처리  (0) 2018.07.20
[Jquery] .each에서 break, continue 구현하기.  (0) 2018.07.02
How to create dynamic a form!  (0) 2018.06.07
javascript replaceAll 사용하기  (0) 2018.03.08
Timer 구현하기  (0) 2017.01.25

(작성일 기준으로 1.2.8 버전이 최신버전)


자바(with Spring)를 개발하다보면 Class를 추가/변경 하는 작업을 많이 한다. 그럴때마다 서버를 리스타트하는 일은 엄청나게 번거로운 일이다. 그래서 자동으로 reload 시켜주는 걸 찾아봤다.


1. 설치하기

 - pom.xml

<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.8.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>


 - jar 다운로드(이 경우에는 다운로드한 경로를 따로 복사해 놓으세요.)

http://mvnrepository.com/artifact/org.springframework/springloaded/1.2.8.RELEASE


4. Spring Boot

 1) maven 명령어로 실행

spring-boot:run 을 실행시킨다.


 2) vm option 추가

-javaagent:<pathTo>/springloaded-{VERSION}.jar -noverify


  (1) Intelli J 일 경우

 - File -> Setting -> Build, Execution, Deployment -> Compiler

Build project automatically 체크!!




  (2) Eclipse 일 경우

    - 추후 작성


5. Spring Framework + Tomcat

 - 추후 작성


6. Daemon 실행

java -javaagent:<pathTo>/springloaded-{VERSION}.jar -noverify SomeJavaClass


7. 테스트 결과

 1) 전역변수 추가 -> 안됨.

  - 테스트 코드(변경 전)

@RequestMapping(value = "/")
public ResponseEntity<String> test() {
return new ResponseEntity<String>("INDEX", HttpStatus.OK);
}

  - 테스트코드(변경 후)

private String ma = "test222";

@RequestMapping(value = "/")
public ResponseEntity<String> test() {
LOG.info("test : {} ", ma);
return new ResponseEntity<String>("INDEX", HttpStatus.OK);
}


  - 결과


 2) @Controller 추가 -> 안됨.

@Controller
public class Test {
@RequestMapping(value = "/test")
public ResponseEntity<String> test2() {
return new ResponseEntity<String>("INDEX 2", HttpStatus.OK);
}
}

 

 3) @RequestMapping 추가 -> 안됨.

@RequestMapping(value = "/test")
public ResponseEntity<String> test2() {
return new ResponseEntity<String>("INDEX 2", HttpStatus.OK);
}

   - 404가 뜬다.


 4) Class 추가 - 됨!!

  - 테스트 코드

public enum TestCd {
BOOK, NOTE;
}

  - 잘 추가/수정 된다.


 5) 지역변수 -> 됨!

@RequestMapping(value = "/")
public ResponseEntity<String> test() {

String testValue = "test test test";
LOG.info("test : {} ", testValue);

return new ResponseEntity<String>("INDEX", HttpStatus.OK);
}

 - 잘 추가/수정 된다.



관련문서

 - https://github.com/spring-projects/spring-loaded

 - https://andromedarabbit.net/spring-loaded%EC%99%80-gradle%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4-%ED%95%AB%EC%8A%A4%EC%99%91-%EC%A7%80%EC%9B%90%ED%95%98%EA%B8%B0/

 - http://www.holaxprogramming.com/2015/05/29/spring-boot-and-loaded/





1. X Stream

 - IntStream 은 int를 지정한 범위 내에서 반복문을 동작함

 - LongStream dms Long을 지정한 범위 내에서 반복문을 동작함


2. range, rangeclosed

 - range는 endExclusive 값 전까지만 반복

 - rangeClosed는 endExclusive 를 포함하여 반복


3. IntStream

 - 소스

public class IntRangeTest {

public static void main(String[] args) {
int startNum = 1;
int endNum = 9;

intRangeTest(startNum, endNum);
System.out.println("\n");
intRangeClosedTest(startNum, endNum);

System.out.println("\n");
}

private static void intRangeTest(int startNum, int endNum) {
System.out.print("IntRange Test 1 : ");
IntStream.range(startNum, endNum).forEach(System.out::print);

System.out.println();

System.out.print("IntRange Test 2 : ");
for (int i = startNum; i < endNum; i++) {
System.out.print(i);
}
}

private static void intRangeClosedTest(int startNum, int endNum) {
System.out.print("IntRangeClosed Test 1 : ");
IntStream.rangeClosed(startNum, endNum).forEach(System.out::print);

System.out.println();

System.out.print("IntRangeClosed Test 2 : ");
for (int i = startNum; i <= endNum; i++) {
System.out.print(i);
}
}
}


 - 결과



4. LongStream

 - 소스

public class LongRangeTest {

public static void main(String[] args) {
long startNum = 1L;
long endNum = 9L;

longRangeTest(startNum, endNum);
System.out.println("\n");
longRangeClosedTest(startNum, endNum);

System.out.println("\n");
}

private static void longRangeTest(long startNum, long endNum) {
System.out.print("LongRange Test 1 : ");
LongStream.range(startNum, endNum).forEach(System.out::print);

System.out.println();

System.out.print("LongRange Test 2 : ");
for (long i = startNum; i < endNum; i++) {
System.out.print(i);
}
}

private static void longRangeClosedTest(long startNum, long endNum) {
System.out.print("LongRangeClosed Test 1 : ");
LongStream.rangeClosed(startNum, endNum).forEach(System.out::print);

System.out.println();

System.out.print("LongRangeClosed Test 2 : ");
for (long i = startNum; i <= endNum; i++) {
System.out.print(i);
}
}
}

 

 - 결과

<!-- 리사이즈 변경 불가 -->
<textarea style="resize: none;"></textarea>
<!-- vertical horizontal 둘다 가능 -->
<textarea style="resize: both;"></textarea>
<!-- vertical 둘다 가능 -->
<textarea style="resize: vertical;"></textarea>
<!-- horizontal 둘다 가능 -->
<textarea style="resize: horizontal;"></textarea>


업무 중에 엑셀 다운로드 기능에 "암호 걸기"가 필요해짐.


1. pom.xml에 필요한 dependencyt 추가

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.16</version>
</dependency>


2. 샘플

 - 아래와 같이 설정해주면 잘 나온다.

EncryptionInfo encryptionInfo = new EncryptionInfo(EncryptionMode.agile);
Encryptor encryptor = encryptionInfo.getEncryptor();
encryptor.confirmPassword(password);


 - 결과


3. 전체소스

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.crypt.EncryptionMode;
import org.apache.poi.poifs.crypt.Encryptor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
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.junit.Test;

import java.io.*;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;

@Slf4j
public class ExcelTest {

@Test
public void 엑셀파일에_암호걸기() {
final String password = "1234";
final String savePath = "c:\\temp\\excel2.xlsx";

List<String> tmpData = Arrays.asList("Java", "JavaScript", "Python", "GoLang");

try (Workbook wb2 = new XSSFWorkbook();
ByteArrayOutputStream fileOut = new ByteArrayOutputStream();
FileOutputStream fos = new FileOutputStream(savePath);) {

Sheet sheet1 = wb2.createSheet("Sheet1");

//Write Excel File
for (int i = 0; i < tmpData.size(); i++) {
String data = tmpData.get(i);

Row row = sheet1.createRow(i);
Cell cell = row.createCell(0);

cell.setCellValue(data);

}

wb2.write(fileOut);

InputStream filein = new ByteArrayInputStream(fileOut.toByteArray());
OPCPackage opc = OPCPackage.open(filein);

POIFSFileSystem fileSystem = new POIFSFileSystem();

EncryptionInfo encryptionInfo = new EncryptionInfo(EncryptionMode.agile);
Encryptor encryptor = encryptionInfo.getEncryptor();
encryptor.confirmPassword(password);

opc.save(encryptor.getDataStream(fileSystem));
fileSystem.writeFilesystem(fos);

log.info("Create Excel File!!");

} catch (IOException e) {
log.error(e.getMessage(), e);

} catch (InvalidFormatException e) {
log.error(e.getMessage(), e);

} catch (GeneralSecurityException e) {
log.error(e.getMessage(), e);
}

}

}


1. 현상

 - 아래와 같은 소스를 사용할 경우

@PropertySource(value = {"classpath:common.properties"})

 - 아래와 같이 호출할 경우,한글이 깨진다.

@Autowired
private Environment env;


private void test(){
env.getRequiredProperty("test");
}


2. 해결법

@PropertySource(value = {"classpath:common.properties"}, encoding = "UTF-8")


간단한 해결 법이지만 기억하기 위해 기록해 놓는다.

개인 프로젝트에서 nginx를 웹서버로 사용하고 있다. 그 뒤에는 2대의 WAS를 사용하고 있고, nginx upstream 기능을 사용하여 로드 밸런싱을 했다. 그러다 보니 배포시에 아래 upstream 내 server를 주석처리하고 nginx 를 reload 하고 다 배포하고 또 주석 처리하고 nginx reload하고.... 다 처리하고 다시 reload하고... 휴.... 반복 해야 한다. 


upstream.conf

upstream project_was {
least_conn;
server 127.0.0.1:8081 weight=1;
server 127.0.0.1:8080 weight=1;
}


생각보다 이 작업이 시간도 많이 걸리고 사람이 작업을 하다 보니, 실수가 종종 나오곤 했다. 좋은 방법이 없나 고민을 하기 시작했다!



매일 반복적으로 처리하는 업무의 경우, 최대한 자동화를 진행해야 보다 쾌적한 하루를 보낼 수 있다.


위 글처럼 언제나... 귀찮은 일을 반복하는 걸 싫어하기 때문에 방법 찾아보았다.


1.....?

 - Nginx Plus를 구매!

 - https://www.nginx.com/products/pricing/

 - 비싸다.......


다시!!


1. Nginx Upstream 파일을 만들자!

 - 위 upstream.conf 파일도 어찌 보면 단순 텍스트 파일이다.

 

 1) 배포할 서버를 제외하고 Argument로 활성화 시킬 서버를 넣고 위 파일을 새롭게 생성한다.

  - Argument

USE_HOST_INFO_STR=$1

  - 파일 생성

HOSTS=(${USE_HOST_INFO_STR//,/' '})

SERVER_TEXT_TMPL='server HOST weight=1;'
UPSTM_NM_TEXT_TMPL='upstream UPSTM_NM '

UPSTM_NM="tmp_upstream"
BASIC_NGINX_CONF_PATH="/etc/nginx/"
UPSTREAM_CONF_FILE_NM=$UPSTM_NM".conf"

RTN_CONF_STR="${UPSTM_NM_TEXT_TMPL/UPSTM_NM/$UPSTM_NM} { \n"
RTN_CONF_STR+=" least_conn; \n "
for host in ${HOSTS[@]}
do
RTN_CONF_STR+="${SERVER_TEXT_TMPL/HOST/$host} \n"
done
RTN_CONF_STR+="} \n"

echo -e $RTN_CONF_STR > $BASIC_NGINX_CONF_PATH$UPSTREAM_CONF_FILE_NM


2. nginx -t 명령어로 conf파일 valid 체크를 한다.

if nginx -t ; then
echo "=======OK========"
systemctl reload nginx.service
else
echo "=======ERROR========"
exit -1;
fi


3. 전체파일

#!/bin/sh

USE_HOST_INFO_STR=$1

function create_conf_file
{
HOSTS=(${USE_HOST_INFO_STR//,/' '})

SERVER_TEXT_TMPL='server HOST weight=1;'
UPSTM_NM_TEXT_TMPL='upstream UPSTM_NM '

UPSTM_NM="tmp_upstream"
BASIC_NGINX_CONF_PATH="/etc/nginx/"
UPSTREAM_CONF_FILE_NM=$UPSTM_NM".conf"

RTN_CONF_STR="${UPSTM_NM_TEXT_TMPL/UPSTM_NM/$UPSTM_NM} { \n"
RTN_CONF_STR+=" least_conn; \n "
for host in ${HOSTS[@]}
do
RTN_CONF_STR+="${SERVER_TEXT_TMPL/HOST/$host} \n"
done
RTN_CONF_STR+="} \n"

echo -e $RTN_CONF_STR > $BASIC_NGINX_CONF_PATH$UPSTREAM_CONF_FILE_NM
}

function valid_check
{
if nginx -t ; then
echo "=======OK========"
systemctl reload nginx.service
else
echo "=======ERROR========"
exit -1;
fi
}

create_conf_file
valid_check


위 작업을 하면서 쉘 스크립트 작성은 오래 걸리지 않았다. 그러나 프로젝트를 진행하면서 배포를 자동화 해 놓으니 너무 너무 편했다. 


결론!!!!!!!!!!!


 - 반복적인 작업을 자동화하는 습관이 필요하다.

 - 조금만 머리를 쓰면 몸이 편하다!

 - 한번 배포할 때 30초에서 1분 정도 소비되던 반복 작업을 빼니, 좀 더 프로젝트에 집중 할 수 있었다.




* 참고로 위에 스크립트를 업무에 가져다 쓰실 경우 sleep을 충분히 주시기 바랍니다. ^_^ 




1. Jquery Each 

 - API 문서 바로가기

 - 쉽게 말해 반복문이다.


2. Break, Continue란?

 - break 는 반복문을 중지하는 기능

 - continue 는 해당하는 반복구간을 건너뛰는 기능


3. Jquery each에서는??

 1) 요약

  - break는 return false;

  - continue는  return true;

  2) 샘플

   - 소스

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>

<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$("ul li").each(function(index) {

var tmpTxt = $(this).text();

if (tmpTxt == "1") {
console.log("Continue value "+ tmpTxt);
return true;

} else if (tmpTxt == "5") {
console.log("Break value "+ tmpTxt);
return false;
}

console.log("value "+ tmpTxt);

});


</script>
</body>
</html>

  - 결과( <li>6</li>에 해당하는 value값은 출력되지 않는다.)



'프로그래밍 > Javascript' 카테고리의 다른 글

How to detect browser.  (0) 13:00:00
IOS 버전 관련 처리  (0) 2018.07.20
[Jquery] .each에서 break, continue 구현하기.  (0) 2018.07.02
How to create dynamic a form!  (0) 2018.06.07
javascript replaceAll 사용하기  (0) 2018.03.08
Timer 구현하기  (0) 2017.01.25

1. 현상

 - Spring boot 1.5.14 로 프로젝트를 세팅하는 중 에러 발생.

 - Lombok Annotation 적용해놓은 class에서 컴파일 에러

 - Github 이슈함 검색... 버그...


@Data
@NoArgsConstructor
@AllArgsConstructor
public class Sample {
private String test1;
private String test2;

}


2. 해결법

 - @NoArgsConstructor 를 @Data 보다 위에 선언해야한다.


@NoArgsConstructor
@AllArgsConstructor
@Data
public class Sample {

private String test1;
private String test2;

}


* 관련 문서

https://github.com/rzwitserloot/lombok/issues/1703

+ Recent posts