2016년 12월 28일 수요일

[mysql] multiple PRIMARY KEY 추가 하기( 기존 pk auto_increment 일때)

1.ALTER TABLE `테이블` MODIFY COLUMN `autoincrement pk컬럼명` INT NOT NULL;
2.ALTER TABLE `테이블` DROP PRIMARY KEY;
3.ALTER TABLE `테이블` ADD PRIMARY KEY (pk할컬럼1, pk할컬럼2, pk할컬럼3 , ...);
4.ALTER TABLE `테이블` MODIFY `autoincrement pk컬럼명` INT NOT NULL AUTO_INCREMENT;

기존에 자동증가 값으로 설정된 pk (mysql의 경우 오토인크리먼트 칼럼은 자동으로 pk 지정되는거로 알고 있음) 가 존재 할경우 ADD PRIMARY KEY 를통해서 멀티플 PK 지정이 불가능 하다.
따라서

1. autoincrement pk컬럼명 을 일반 INT NOT NULL 컬럼으로 MODIFY 를 먼저하고
2. 해당 테이블에 PK 를 드랍시킨후
3. 멀티플 PK를 새로 지정한후
4. 원레 오토 인크리먼트로 지정됐던 컬럼을 다시 오토 인크리먼트로 설정.

결과 증가값은 그대로 유지 하면서 멀티플 PK 가 추가되었다.


%%%주의%%%


기존 데이터가 존재 할경우
멀티플 칼럼에 대한 중복된 데이터를 삭제해야만 3번 쿼리가 실행될수 있다.



2016년 12월 25일 일요일

[java] sftp 파일전송 소스

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

public class FileUploadSFTPClient {

    private Session session = null;

    private Channel channel = null;

    private ChannelSftp channelSftp = null;

    /**
     * 서버와 연결에 필요한 값들을 가져와 초기화 시킴
     * 작성자 : 어셈블링블링
     *
     * @param host
     *            서버 주소
     * @param userName
     *            접속에 사용될 아이디
     * @param password
     *            비밀번호
     * @param port
     *            포트번호
     */
    public void init(String host, String userName, String password, int port) {
   
        JSch jsch = new JSch();
        try {
            session = jsch.getSession(userName, host, port);
            session.setPassword(password);

            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();

            channel = session.openChannel("sftp");
            channel.connect();
        } catch (JSchException e) {
            System.out.println(e);
        }

        channelSftp = (ChannelSftp) channel;
    }
   
   
    /**
     * 하나의 파일을 업로드 한다.
     *
     * @param dir
     *            저장시킬 주소(서버)
     * @param file
     *            저장할 파일
     */
    public void upload(String dir, File file) {
        FileInputStream in = null;
        try {
            in = new FileInputStream(file);
            channelSftp.cd(dir);
            channelSftp.put(in, file.getName());
        } catch (SftpException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     
    }
   
    /**
     * 하나의 파일을 다운로드 한다.
     * 작성자 : 어셈블링블링
     * @param dir
     *            저장할 경로(서버)
     * @param downloadFileName
     *            다운로드할 파일
     * @param path
     *            저장될 공간
     */
    public void download(String dir, String downloadFileName, String path) {
        InputStream in = null;
        FileOutputStream out = null;
        try {
            channelSftp.cd(dir);
            in = channelSftp.get(downloadFileName);
        } catch (SftpException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            out = new FileOutputStream(new File(path));
            int i;

            while ((i = in.read()) != -1) {
                out.write(i);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                out.close();
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

    /**
     * 서버와의 연결을 끊는다.
     * 작성자 : 어셈블링블링
     */
    public void disconnection() {
        channelSftp.quit();

    }
   
}

어디서 퍼온거 같은데 기억이 안남.


암튼 퍼가실때 글좀 남져주세용!!~~~~~

[java] ftp 파일 전송 소스

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;

/**
 * 작성자 : 어셈블링블링
 * 설명 : ftp를 이용한 파일전송.
 */
public class FileUploadFtpClient {
FTPClient ftpClient = null;

        //생성자를 통해 ftp 설정을 한다.
public FileUploadFtpClient(String url, int port, String id, String pw){
this.ftpClient = new FTPClient();

try {
ftpClient.connect(url, port);
       ftpClient.login(id, pw);
       ftpClient.enterLocalPassiveMode();
       ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
}catch (IOException ex) {
            //System.out.println("Error: " + ex.getMessage());
            ex.printStackTrace();
        }
}


        //경로, 파일명, 파일을 받아 해당 경로에 파일을 파일명으로 저장한다.

public boolean put(String path, String file_name, File file){

boolean bReault = false;
InputStream inputStream = null;
try {
                        //경로를 / 구분
String path_arr[] = path.split("/");
for(int i = 0 ; i < path_arr.length ; i++){
String directory = path_arr[i];
if(directory != null && directory.length() > 0){
                                        //경로를 찾아 들어 간다.
                                        //경로가 없는 경우 경로 생성
if(!ftpClient.changeWorkingDirectory(directory)){
ftpClient.makeDirectory(directory);
ftpClient.changeWorkingDirectory(directory);
}else{
ftpClient.changeWorkingDirectory(directory);
}
}
}

            inputStream = new FileInputStream(file);
            //저장하고 경과 리턴받음.
            bReault = ftpClient.storeFile(file_name, inputStream);
            //System.out.println("bReault" + " : " + bReault);
}catch (IOException ex) {
bReault = false;
            //System.out.println("Error: " + ex.getMessage());
            ex.printStackTrace();
        }finally{
        if(inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
        disconnect();
        }
return bReault;
}

        //ftp 연결을 해제한다.
public void disconnect(){
try {
             if (ftpClient.isConnected()) {
                 ftpClient.logout();
                 ftpClient.disconnect();
             }
         } catch (IOException ex) {
             ex.printStackTrace();
         }
}

}



댓글좀.....달아주세용~~

[java]웹 이미지 로드

웹이미지를 로컬에 저장하는 방법은 크게 네가지가 있을수 있다.

1. javaIO, NIO 로 읽어서 저장하기
2. ftp(file transfer protocol) 로 다운받기
3. 캡쳐 이미지 생성후 javaIO,NIO 로 읽어서 저장하기
4. 해킹

사실상 불특정 url 일경우 파일권한 또는 폴더 권한때문에 1번은  안될 확률이 많고
2번또한 ftp 계정을 알아야 가능 하다. 계정을 알아도 해당 계정에 대한 퍼미션이 문제가 될수 도 있다.

4 번은 잘모르겟어서

3 번으로 도전

loadWebImage() 함수를 호출 해서 이미지를 버퍼에 담고 saveByteBufferImage() 전달하여
저장한다.

         /**
* 웹에서 이미지 받아서 바이트 버퍼에 담은후 saveByteBufferImage 함수를호출 이          * 미지 저장후 경로 리턴 받기
* 작성자 : 어셈블링블링
* @param imageUrl
* @param fileName
* @param sftpClient
* @return
*/
protected String loadWebImage(String imageUrl, String fileName,String type,                                         FileUploadSFTPClient sftpClient) {

String serverImagePath = null;
   
            //자바 http 파싱 라이브러리 jsoup 를 이용 이미지를 바이트에 배열에 담는다.
           
   try {
       byte[] bytes = Jsoup.connect(imageUrl)
        .ignoreContentType(true)
        .userAgent("Mozilla/5.0 (Windows NT 6.1; Win64;                                                     x64; rv:25.0) Gecko/20100101 Firefox/25.0")
        .referrer("http://www.google.com")
        .timeout(12000)
        .followRedirects(true)
        .execute().bodyAsBytes();
               
                //바이트 버퍼로 옮기기
       ByteBuffer buffer = ByteBuffer.wrap(bytes);
     
     
     
        //이미지 파일저장 하고 경로 리턴 받기
       serverImagePath = saveByteBufferImage(buffer, TEMP_LOCAL_IMAGE_PATH,                 fileName , type, sftpClient);

   } catch (IOException e) {
       e.printStackTrace();
   }
   return serverImagePath;
}


이제 바이트 버퍼에 담겨있는 데이터를 자신이 원하는 경로에 저장하면된다.

saveByteBufferImage() 함수는 보안상 공개 하지 않겟다. 퍼갈때 댓들 들좀 달아주삼.

[java]이미지 섬네일 생성하기 소스


나도 어디서 퍼왔는지 기억이 잘 나지 않는다. 포맷부분만 약간 수정 했다.
비율이 유지 되면서

thumbWidth 값과 thumbHeight 값은 알아서 셋팅 하면되고

 int thumbWidth;
 int thumbHeight;



final int RATIO = 0;
final int SAME = -1;




        /**
* src 파일을 읽어 dest 파일에 전달 받은 format 형식으로 썸네일을 생성한다.
         * 비율 유지
* 작성자 : 어셈블링블링
* @param src
* @param dest
* @param width
* @param height
* @throws IOException
*/
public void makeThumb(File src, File dest, String format) throws IOException {
        Image srcImg = null;
        String suffix =                                                                                                 src.getName().substring(src.getName().lastIndexOf('.')+1).toLowerCase();

        if (suffix.equals("bmp") || suffix.equals("png") || suffix.equals("gif")) {
            srcImg = ImageIO.read(src);
        } else {
            // BMP가 아닌 경우 ImageIcon을 활용해서 Image 생성
            // 이렇게 하는 이유는 getScaledInstance를 통해 구한 이미지를
            // PixelGrabber.grabPixels로 리사이즈 할때
            // 빠르게 처리하기 위함이다.
            srcImg = new ImageIcon(src.toURL()).getImage();
        }
       
        int srcWidth = srcImg.getWidth(null);
        int srcHeight = srcImg.getHeight(null);
       
        int destWidth = -1, destHeight = -1;
       
        if (thumbWidth == SAME) {
            destWidth = srcWidth;
        } else if (thumbWidth > 0) {
            destWidth = thumbWidth;
        }
       
        if (thumbHeight == SAME) {
            destHeight = srcHeight;
        } else if (thumbHeight > 0) {
            destHeight = thumbHeight;
        }
       
        if (thumbWidth == RATIO && thumbHeight == RATIO) {
            destWidth = srcWidth;
            destHeight = srcHeight;
        } else if (thumbWidth == RATIO) {
            double ratio = ((double)destHeight) / ((double)srcHeight);
            destWidth = (int)((double)srcWidth * ratio);
        } else if (thumbWidth == RATIO) {
            double ratio = ((double)destWidth) / ((double)srcWidth);
            destHeight = (int)((double)srcHeight * ratio);
        }
       
        Image imgTarget = srcImg.getScaledInstance(destWidth, destHeight,                           Image.SCALE_SMOOTH);
        int pixels[] = new int[destWidth * destHeight];
        PixelGrabber pg = new PixelGrabber(imgTarget, 0, 0, destWidth, destHeight, pixels,         0, destWidth);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
            throw new IOException(e.getMessage());
        }
        BufferedImage destImg = new BufferedImage(destWidth, destHeight,                           BufferedImage.TYPE_INT_RGB);
        destImg.setRGB(0, 0, destWidth, destHeight, pixels, 0, destWidth);
       
     
        ImageIO.write(destImg, format, dest);
       
    }


퍼갈때 댓글 하나씩 남겨주삼.

2016년 12월 18일 일요일

[java] sql 실행하기

DBConnectionPool connPool = null;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
CallableStatement cstmt = null;
.
.
.
.

역시 커넥션 풀은 커넥션 객체가 싱글톤으로 셋팅 되었다고 가정한다.


try{      

        //sql 구문 . 주의 할점 . 문자열을 더할때 앞 1칸은 공백으로 한다. 그러지 않으면
        //문자열이 붙어서 sql 을 인식하지못함.

String sql = "";
sql +=" SELECT";
sql +=" A.MB_SEQ";
sql +=" ,A.MB_NICKNAME";
sql +=" ,A.MB_LEVEL";
sql +=" ,A.MB_LAST_LOGIN_IP";
sql +=" FROM MB_MEMBER A";
sql +=" WHERE 1=1";
sql +=" AND A.MB_ISADMIN = 1";
sql +=" AND MB_SEQ NOT IN (240,293,294,3129)";
sql +=" AND MB_SEQ NOT IN (";
sql +=" SELECT ";
sql +=" DISTINCT(CMT_WRITER_SEQ)";
sql +=" FROM CMT_COMMENT";
sql +=" WHERE";
sql +=" AC_ARTICLE_SEQ= ?)";
sql +=" AND MB_SEQ != (SELECT AC_WRITER_SEQ FROM AC_ARTICLE WHERE"             sql +=" AC_ARTICLE_SEQ = ?)";
sql +=" ORDER BY RAND()";
sql +=" LIMIT 1";

        //커넥션 얻기
conn = connPool.getConnection();
        //스테이트 먼트에 sql 담기
        //쿼리 캐싱이 필요한경우는 prepareStatement 로 쓰고 그러지 않으면 걍 Statement
        //로 사용

pstmt = conn.prepareStatement(sql);

        // ? 순서대로 파라미터 셋팅.
pstmt.setLong(1, ac_article_seq);
pstmt.setLong(2, ac_article_seq);

        //쿼리 실행
rs = pstmt.executeQuery();

        //컬럼명으로 읽어드리기
while(rs.next()){
member.put("MB_SEQ", rs.getString("MB_SEQ"));
member.put("MB_NICKNAME", rs.getString("MB_NICKNAME"));
member.put("MB_LEVEL", rs.getString("MB_LEVEL"));
member.put("MB_LAST_LOGIN_IP", rs.getString("MB_LAST_LOGIN_IP"));
}
}catch(Exception e){

}finally{
if(rs != null){ try{ rs.close(); }catch(SQLException e){} }
        if(pstmt != null){ try{ pstmt.close(); }catch(SQLException e){} }
        //커넥션 반환.
        connPool.returnConnection(conn);
}

[java] 프로시저 호출하기

코드 예)


DBConnectionPool connPool = null;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
CallableStatement cstmt = null;

.
.
.
.


클래스 상단 전역 변수로 선언되어있는 데이터베이스 관련 객채들.
코드상엔 없지만 connPool  커넥션풀에 데이터베이스 커넥션 싱글톤 처리가 되었다고 가정한다.

try{  
        //쿼리  
String sql = "{ CALL PROC_COMMENT_INSERT( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) }";

        //커넥션을 얻는다.
conn = connPool.getConnection();
        //스테이트먼트 객체를 얻는다
cstmt = conn.prepareCall(sql);
        //전달 파타미터 셋팅
cstmt.setLong(1, ac_article_seq);
cstmt.setLong(2,(long)0);
cstmt.setLong(3, mb_seq);
cstmt.setString(4,mn_nickname);
cstmt.setInt(5,Integer.parseInt((String)member.get("MB_LEVEL")));
cstmt.setString(6,"U");
cstmt.setString(7,comment);
cstmt.setString(8,(String)member.get("MB_LAST_LOGIN_IP"));
//전달 파라미터 셋팅끝

        //프로시저 리턴 파라미터
cstmt.registerOutParameter(9, java.sql.Types.BIGINT);
cstmt.registerOutParameter(10, java.sql.Types.SMALLINT);
cstmt.registerOutParameter(11, java.sql.Types.TINYINT);
cstmt.registerOutParameter(12, java.sql.Types.BIGINT);
        //리턴 파라미터 끝

        //실행
cstmt.execute();

}catch(Exception e){
setTextAppend("등록실패");
setTextAppend(e.toString());
}finally{
if(rs != null){ try{ rs.close(); }catch(SQLException e){} }
if(cstmt != null){ try{ cstmt.close(); }catch(SQLException e){} }
connPool.returnConnection(conn);
}

[java] properties 파일 읽기,수정하기

읽기

경로는 app 이 위치한 경로가 어디로될지 모르기때문에 절대 경로로 넣으면 안된다.
따라서 System 의 getProperty 메소드를 이용해서 현재 app이 위치한 경로를 읽어오고
하위경로를 잡아준다.

예)
String propPath = System.getProperty("user.dir") + File.separator + "properties"+File.separator+"database.properties";

app위치한경로/properties/database.properties

Properties props = new Properties();

props.load(new FileReader(propPath));

String url = props.getProperty("dburl");

.
.
.

위와 같이 읽어오면 된다 IOException 예외처리는 필수.

수정.

경로 얻기는 동일.

String propPath = System.getProperty("user.dir") + File.separator + "properties"+File.separator+"database.properties";

Properties props = new Properties();
props.setProperty("dburl", "변경할 값");
props.store(new FileOutputStream(propPath), "");






[java]데이터베이스 커넥션 싱글톤 구현

자바 기반 웹 어플리케이션의 경우 보통은 spring datasource + jndi 를 설정 하여 사용하는 경우가 대부분이다.

datasource 는 풀링 기법(connection 자원을 동적으로 재사용.) 및 분산처리  등 의 중요한 기능을 제공 하고 jndi 에서 각각의 데이터 베이스 별로 논리적 이름을 사용하여 설정 접근DBMS를 제어한다.

결국 datasource 는 서버에서 설정관리 되는 부분이고 개발자는 필요한 데이터 베이스 연결정보를 논리적 이름을 갖는 jndi 서비스 등록만 하게되면 사용 가능 하기때문에. 굳이..
싱글톤 패턴 (미리 정의된 객체를 매번 생성하지 않고 쓰고 반납하는 구조.)을 구현할 필요가 없다.

하지만. 소규모의 어플리케이션 에서는 직접 구현해야 할필요가 있을수도 있기때문에
알고는 있어야함.


//소스

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.Hashtable;


public class DBConnectionPool {
String dburl;
String id;
String pwd;
String driverClass;

ArrayList<Connection> list = new ArrayList<Connection>();
Hashtable<Thread,Connection> rentTable = new Hashtable<Thread,Connection>();

public DBConnectionPool() {}

        //생정자로 데이터 베이스 연결정보를 셋팅한다.
public DBConnectionPool(
String dburl, String id, String pwd, String driverClass) {
this.dburl = dburl;
this.id = id;
this.pwd = pwd;
this.driverClass = driverClass;
}

        //부분 설정도 가능하게 setter method 생성
public DBConnectionPool setUrl(String url) {
this.dburl = url;
return this;
}

public DBConnectionPool setDriver(String driver) {
this.driverClass = driver;
return this;
}

public DBConnectionPool setUsername(String username) {
this.id = username;
return this;
}

public DBConnectionPool setPassword(String password) {
this.pwd = password;
return this;
}

         //--부분 설정도 가능하게 setter method 생성
     

        //현재의 프로세스에서 커넥션이 없을경우 생성후 보관 있을경우 재사용
public Connection getConnection() throws Exception {
Thread currThread = Thread.currentThread();

                //현제의 프로세스 에서 사용중인 connection 을 구한다.
Connection con = rentTable.get(currThread);

                //사용중인 connection 이 있을경우 재사용
if (con != null) {
return con;

        //없을경우
} else {
                        //커넥션 리스트에 사용가능한 커넥션이 있을 경우
                        if (list.size() > 0) {
con = list.remove(0);
//모든 커넥션이 사용중인 경우 커넥션을 생성한다.
} else {
Class.forName(driverClass);
con = DriverManager.getConnection(dburl, id, pwd);
}

                        //사용중으로 등록
rentTable.put(currThread, con);
return con;
}
}

        //커넥션 반환시 사용중 내역 삭제 및 다쓴 커넥션을 커넥션 리스트에 반환.
public void returnConnection(Connection con) {
Thread currThread = Thread.currentThread();
rentTable.remove(currThread);
list.add(con);
}
}


어플리케이션 시작시 생성자를 통해 셋팅하고 어플리케이션 컨텍스트에 저장해놓고 쓰기로 하자.

2016년 12월 3일 토요일

[javascript] onkeyup 이벤를 이용 select 태그 선택하기.

input 에서 텍스트를 입력 받아 select 박스의 옵션을 선택 해야할 경우

select 태그를 하나 준비한다.

<select name="searchList">
    <option value="1">가</option>
    <option value="2">나</option>
    <option value="3">다</option>
    <option value="4">가나다</option>
    <option value="5">가나</option>
    <option value="6">aa</option>
</select>

input 태그를  하나 준비한다.

<input type="text" id="searchId_input" placeholder="아이디 검색" onkeyup="javascript:func(this.value);return false;">

위 input 태그는 입력될때마다 func 를 호출 하고 현재 입력되어진 값을 전달할 것이다.



호출될 func 함수
function func(val){
   
     //현재 입력되어진 input 태그의 값이 존재 할 경우에만 select 태그를 검사한다.
     if(val.trim().length > 0 && val != ""){
       
        //각각의 옵션태그를  검사
$("select[name=searchList] > option").each(function(idx){
                //입력된 val 문자열로 시작할 경우 셀렉트 박스에 해당 옵션 태그를 selecred
                //로 바꿔 준다.
if($(this).text().indexOf(val) == 0){

                    $(this).prop("selected", true);
            return false;
                //검색된 option 태그가 없을경우 0번째 꺼를 다시 선택 하도록 한다.
}else{

                   $("select[name=cmt_writer_seq]").find("option:eq(0)").prop("selected", true);
}
});
     //입력되어진 값이 없는 경우 첫번째 옵션태그의 상태를 selected 로 변경한다.
     }else{
$("select[name=cmt_writer_seq]").find("option:eq(0)").prop("selected", true);
     }
}


일반 적으로 위와 같이 select 박스를 검색 하는 경우는 많이 없을테지만 (보통은 li 로 리스트 뿌리고 거기서 검색한거 선택하겟지 우편번호 찾기 처럼.) , 그냥 한번 해봤다.

위코드는 한가지 문제점이 있다.

예를 들면    option 태그 리스트 에  

<option>홍길동전</option>
<option>홍길동</option>


이렇게 되어있을 경우  "홍길동"  을 입력 했을때 무조건 홍길동전 만 셀렉트가 될것이다.
포함하는것을 리스트로 뿌려줘서 선택 하게 하는 추가 로직이 있으면 좋겟지만

어차피 option 태그를 가나다 순으로 뿌리면 셀렉트 박스를 클릭 하여 바로 옆에꺼를 클릭하면 되기 때문에 처리하지 않았다. 알아서 편집해서 사용할것.



2016년 12월 1일 목요일

[javascript]불특정(랜덤) 시간마다 특정 함수 실행하기

음 이거는 공개 안할려다가 한다.


var _interval = setInterval(func,120000);

setInterval  함수를 이용하면 특정 시간마다 함수를 실행할수 있는데

함수등록시 시간값이 고정으로 들어가기 때문에  일정한 시간 간격을 두고 실행되기

때문에 내가 원하는 결과를 얻을수 없었다.

그럼 어떻게 해야하는가?

1.먼저 랜덤 시간을 리턴 하는 함수를 하나 만든다.

난 2분안짝으로 초로 리턴 하게끔 했다.

//0~120초 사이 리턴 랜덤 초
function getRandSec(){
return Math.floor(Math.random() * 120) + 1;
}

2. 그리고 2분마다 실행하는 인터벌 함수를 정의한다.

var _interval = setInterval(targetFunction,120000);

3.실행할 함수 내에서 setTimeout 으로 실행하되 시간 값을 랜덤으로 준다.


function targetFunction(){
var sec = getRandSec();
console.log(sec);
if(_autoStartStatus){
setTimeout(function(){

                //여기가 실제로 실행되는 비지니스 로직.

}, sec*1000);
}
}

정리.

인터벌 함수를 통해 targetFunction 함수를 2분마다 실행하고 실행된 targetFunction 함수 내에서 setTimeout 함수로 일정시간뒤에 비지니스 로직을 수행하는데 시간값을
getRandSec() 를 통해서 1~120 초 사이를 얻는다. 

경고.

랜덤으로 얻는 시간 값의 범위 최대값이 인터벌 파라미터로 넣는 시간값보다 작거나 같아야 한다.



[oracle]백업및 복구

[oracle]백업및 복구 오라클 덤프 백업및 복구 윈도우 서버 기반 간단 정리 --디렉터리 조회 sqlplus 또는 dbtool 입력시작 SELECT * FROM DBA_DIRECTORIES ; --D:...