基于Java方式如何实现数据同步
本篇內容介紹了“基于Java方式如何實現數據同步”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
業務背景
在新系統中設置定時任務需要實時把客戶系統中的數據及時同步過來,保持數據的一致性。
實現邏輯
1.根據客戶提供的接口,本系統中采用Http的Post請求方式獲取接口數據。
2.由于客戶提供的接口必帶頁碼和頁面容量,因此會涉及到多次請求接口才能拿到全量數據,因此相同的操作可以采用遞歸的方式進行。
3.每次請求一次接口根據頁面容量(pageSize)可獲取多條數據,此時可以采用批量添加數據庫的操作,使用批量SQL添加語句。
4.由于數據同步需要保持兩個系統數據的一致性,因此需要使用定時任務并規定同步頻率,例如:一天一次或者一天兩次。
5.定時任務的使用會產生數據重復的問題,因此根據某個唯一字段建立唯一索引來避免數據重復添加的問題。
6.唯一索引的建立可以避免同一記錄重復添加的問題,但是避免不了同一條記錄除唯一索引字段之外其它字段對應數據發生變化問題,因此使用replace into添加SQL語句可以解決此問題。
提示: a. 如果發現表中已經有此行數據(根據主鍵或者唯一索引判斷)則先刪除此行數據,然后插入新的數據。 b. 不然的話,直接插入新的數據。
使用技術
1.設置定時任務。
2.采用Http的Post方式獲取接口數據。
3.涉及多頁數據采用遞歸方式循環調用。
4.批量操作數據庫(replace into)。
5.建立唯一索引避免重復插入數據。
代碼詳情
1.StudentMapper.java
/**
* 批量添加數據同步接口學生數據
* @param studentList
* @return
*/
int addBatchStudent(@Param(value = “studentList”) List studentList);
2.SyncStudentServiceImpl.java代碼如下:
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import ***.common.utils.HttpUtils;
import ***.common.utils.StringUtils;
import ***.entity.sync.Student;
import ***.mapper.sync.StudentMapper;
import ***.service.sync.SyncStudentService;
import ***.vo.StudentVO;
import lombok.extern.slf4j.Slf4j;
/**
-
數據同步的學生實現類
-
@author hc
-
@create 2021/03/25 11:20
-
@version 1.0
-
@since 1.0
*/
@Service
@Slf4j
public class SyncStudentServiceImpl implements SyncStudentService {
@Autowired
private StudentMapper studentMapper;
@Autowired
private HttpUtils httpUtils;@Override
public void bulkAddStudent(StudentVO studentVO) {
log.info(“調取學生接口傳的參數對象studentVO:”+studentVO);
log.info(“開始調取學生接口獲取第” + studentVO.getPageIndex() + “頁數據”);
//如何頁面容量小于100,則按100計算
if(studentVO.getPageSize() < 100) {
studentVO.setPageSize(100);
}
//根據當前頁碼和頁面容量調取獲取學生數據接口
JSONObject jsonObject = this.sendStudentHttpPost(studentVO);
//判斷返回JSONObject是否為null
if (StringUtils.isNotNull(jsonObject) && jsonObject.containsKey(“errcode”) && jsonObject.getInteger(“errcode”) == 0) {
if(jsonObject.containsKey(“data”)){
JSONArray jsonArray = jsonObject.getJSONArray(“data”);
//通過判斷獲取的jsonObject對象中key值為data是否為null和其 jsonArray的長度來判斷是否進行遞歸
//提示:此判斷方法好于通過計算總頁碼的方式來遞歸拿數據(對獲取的total依賴過大,因此放棄此方式)
if(jsonObject.getString(“data”) != null && jsonArray.size() > 0) {
log.info(“當前數據加載到幾頁》》》》:{}”, studentVO.getPageIndex());
//調取批量添加數據
this.addStudentCycleData(jsonObject, studentVO);
//頁碼加1,繼續調取下一頁數據
studentVO.setPageIndex(studentVO.getPageIndex() + 1);
//采用遞歸方式直至循環結束
this.bulkAddStudent(studentVO);
}else {
log.info(“學生數據同步結束》》》”);
}
}
}
}/**
- 批量添加學生數據
- @param jsonObject
- @param areaVO
- @return
*/
public void addStudentCycleData(JSONObject jsonObject, StudentVO studentVO){
List studentList = null;
//判斷jsonArray時候為空
if (jsonObject != null && StringUtils.isNotBlank(jsonObject.getString(“data”))) {
//把JsonArray轉成對應實體類集合
studentList = JSONObject.parseArray(jsonObject.getString(“data”), Student.class);
}
try {
log.info(“學生接口第” + studentVO.getPageIndex() + “頁數據開始入庫…”);
//調取方法批量進行添加學生數據
studentMapper.addBatchStudent(studentList);
log.info(“學生接口第” + studentVO.getPageIndex() + “頁數據入庫成功…”);
} catch (Exception e) {
log.error(“學生批量添加數據庫異常:{}”, e.getMessage());
}
}
/**
- 根據studentVO(當前頁碼和頁面容量)發送獲取學生數據的請求
- @param studentVO
- @return
*/
public JSONObject sendStudentHttpPost(StudentVO studentVO){
JSONObject jsonObject = null;
String studentUrl = “http://*****/async-api/jc/student”;
try {
if (StringUtils.isNotEmpty(studentUrl)) {
Map<String, Object> param = new HashMap<>();
param.put(“pageIndex”, studentVO.getPageIndex());
param.put(“pageSize”, studentVO.getPageSize());
log.info(“開始發起http請求…”);
jsonObject = httpUtils.sendHttpPost(param, studentUrl);
}
} catch (Exception e) {
log.error(“調取客戶學生同步接口出現異常:{},頁面容量為:{},頁碼:{}”, e.getMessage(),
studentVO.getPageSize(), studentVO.getPageIndex());
}
return jsonObject;
}
}
3.StudentVO.java代碼如下:
import lombok.Data;
/**
- 數據同步接口獲取學生數據傳的參數VO類
- @author hc
- @create 2021/3/11 10:35
- @version 1.0
- @since 1.0
*/
@Data
public class StudentVO{
//當前頁碼(初始值為0)
private Integer pageIndex = 0;
//頁碼容量
private Integer pageSize;
}
4.HttpUtils.java代碼如下:
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
/**
-
Http請求工具類
-
@author hc
-
@create 2021/3/4
-
@version 1.0
*/
@Component
@Slf4j
public class HttpUtils {
@Autowired
private RestTemplate restTemplate;/**
- 發送http的post請求方法
- @param param
- @return
*/
public JSONObject sendHttpPost(Integer type, Map<String, Object> param, String url){
log.info(“調取同步接口Url:{}”, url);
JSONObject jsonObject = null;
//發起http的post準備工作
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(“Content-Type”, “application/json”);
HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(param, httpHeaders);
ResponseEntity response = null;
try {
log.info(“param參數為:{}”,param.toString());
response = restTemplate.postForEntity(url, httpEntity, String.class);
} catch (HttpClientErrorException e) {
log.error(“發起http請求報錯信息:{}”,e.getResponseBodyAsString());
}
String bodyData = response.getBody();
if (StringUtils.isNotEmpty(bodyData)) {
jsonObject = JSONObject.parseObject(bodyData);
}
return jsonObject;
}
}
5.StudentMapper.xml的SQL語句如下:
“基于Java方式如何實現數據同步”的內容就介紹到這里了,感謝大家的閱讀。
總結
以上是生活随笔為你收集整理的基于Java方式如何实现数据同步的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么给PPT加密、选用隐大师U盘
- 下一篇: 记录年前Java岗整个历程(附字节,阿里