Spring Boot 에서 스케줄 만들기
다음 예제는 업비트 open api 와 Spring Boot의 스케쥴러 기능을 통하여 매 시간 마다 업비트의 다양한 정보를 Mysql 에 적재하는 방법을 서술한다.
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import com.example.demo.vo.UserInfo;
@EnableScheduling
@SpringBootApplication
public class StartApplication {
public static void main(String[] args) {
SpringApplication.run(StartApplication.class, args);
}
}
먼저 spring boot 가 시작되는 지점에 "@EnableScheduling" 을 작성해준다. 그 이후 위 의 작성한 자바 파일과 같은 패키지에 스케줄 class를 아래와 같이 작성해준다.
package com.example.demo;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.common.Common;
/**
* 배치 목록입니다.
* @author kimhosung
*
*/
@Component
public class BatchScheduler {
Logger logger = LoggerFactory.getLogger(this.getClass());
// 업비트에 있는 종목정보를 가져옵니다.
@Scheduled(fixedRate = 10000)
public void scheduleFixedRateTask() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date now = new Date();
String strDate = sdf.format(now);
System.out.println("작업 날짜 시간 fixedRate::" + strDate);
Common.openapi("http://localhost:8081/batch/list");
}
}
Common.openapi 메소드는 아래와 같이 작성하였다.
package com.common;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
/**
* 공통 메소드
* @author kimhosung
*
*/
public class Common {
//단순 url call
public static void openapi(String url) {
try {
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(url);
request.setHeader("Content-Type", "application/json");
HttpResponse response = client.execute(request);
} catch (IOException e) {
e.printStackTrace();
}
}
}
그럼 결국 "http://localhost:8081/batch/list" url 을 통해 아래와 같이 REST 방식으로 컨트롤러를 호출할것이다. 컨트롤러의 소스는 아래와 같다.
package com.upbit.openapi;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.mapper.LoginMapper;
import com.example.demo.mapper.MarketListMapper;
import com.example.demo.vo.MartListVO;
import com.example.demo.vo.UserInfo;
@RestController
@CrossOrigin(origins = "http://localhost:8080") // 컨트롤러에서 설정
@Service
public class BatchProgram {
@Autowired
MarketListMapper mrMapper;
/*
* 마켓의 종목의 명칭을 가져옵니다.
*/
@RequestMapping(value="/batch/list", method=RequestMethod.GET)
public void testpp() {
try {
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet("https://api.upbit.com/v1/market/all");
request.setHeader("Content-Type", "application/json");
HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
String json = EntityUtils.toString(entity, "UTF-8");
JSONParser parser = new JSONParser();
JSONArray jsonarray = (JSONArray) parser.parse(json);
//테이블 초기
mrMapper.initMarketList();
for (int i = 0; i < jsonarray.size(); i++) {
JSONObject obj = (JSONObject) jsonarray.get(i);
MartListVO vo = new MartListVO();
vo.setMr_cd(obj.get("market").toString());
vo.setEng_nm(obj.get("english_name").toString());
vo.setKor_nm(obj.get("korean_name").toString());
try {
mrMapper.insertMarketList(vo);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (org.apache.http.ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (org.json.simple.parser.ParseException e) {
e.printStackTrace();
}
}
}
여기서 중요하게 봐야될 부분은 json 형식의 파싱 방법이다.
JSONParser parser = new JSONParser();
JSONArray jsonarray = (JSONArray) parser.parse(json);
위와 같이 JSONParser를 만들고 JSON이 [] 로 시작한다면 배열이기 때문에 사용하였다.
jsonarray에 String으로 된 json 을 담아 파싱한다.
그 다음 아래와 같은 서비스를 호출하고 이 서비스는 @Mapper로 선언 되어있기 때문에 mapper 파일을 만들어 준다.
package com.example.demo.mapper;
import org.apache.ibatis.annotations.Mapper;
import com.example.demo.vo.MartListVO;
@Mapper
public interface MarketListMapper {
int insertMarketList(MartListVO vo);
int initMarketList();
}
mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.MarketListMapper">
<insert id="insertMarketList" parameterType="MartListVO" >
INSERT INTO `shoppingMall`.`TB_MR_LIST`
(`MR_CD`,
`KOR_NM`,
`ENG_NM`,
`SYS_DT`)
VALUES
(#{mr_cd},
#{kor_nm},
#{eng_nm},
sysdate())
</insert>
<delete id="initMarketList">
TRUNCATE TB_MR_LIST;
</delete>
</mapper>