Spring Batch:將資料從Web服務處理到MongoDB
概觀
在這篇文章中,我們將介紹如何建立一個使用Web服務資料並將其插入MongoDB資料庫的Spring Batch應用程式。
要求
閱讀本文的開發人員必須熟悉Spring Batch( 示例 )和MongoDB。
環境
-
Mongo資料庫部署在 MLab中 。 請按照本 快速入門中的步驟操作 。
-
IDE STS或IntelliJ或Eclipse。
-
Java 8 JDK。
注意 :批處理也可以在本地執行。
指令碼
全域性場景步驟是:
-
從Web服務讀取資料,在這種情況下:https://sunrise-sunset.org/api
獲取城市列表的座標,然後呼叫API以讀取日出和日落日期時間。
2.處理資料並提取業務資料
收集資料的業務處理
3.在MongoDB中插入已處理的資料
將處理過的資料儲存為mongo文件
編碼
-
輸入:本地檔案中JSON格式的城市資料列表,如下所示:
[
{
“名字”:“Danemark”,
“城市”:[
{
“名字”:“Copenhague”,
“lat”:55.676098,
“lng”:12.568337,
“timeZone”:“CET”
},
{
“名字”:“奧胡斯”,
“lat”:56.162939,
“lng”:10.203921,
“timeZone”:“CET”
},
{
“名字”:“歐登塞”,
“lat”:55.39594,
“lng”:10.38831,
“timeZone”:“CET”
},
{
“名字”:“奧爾堡”,
“lat”:57.046707,
“lng”:9.935932,
“timeZone”:“CET”
}
]
}
]
我們的場景從本地json檔案獲取輸入資料。 對映bean如下:
國豆:
匯入 java。io。可序列化 ;
匯入 java。util。清單 ;
進口 com。fastxml。傑克遜。註釋。JsonIgnoreProperties ;
@JsonIgnoreProperties(ignoreUnknown = true)
public class BCountry 實現 Serializable {
private static final long serialVersionUID = 1L ;
私有 字串 名稱 ;
私人 名單< BCity > 城市 ;
public BCountry(){
super();
}
public BCountry(String name,List < BCity > cities){
super();
這個。name = name ;
這個。城市 = 城市 ;
}
public BCountry(String name){
super();
這個。name = name ;
}
public String getName(){
返回 名稱 ;
}
public void setName(String name){
這個。name = name ;
}
public List < BCity > getCities(){
返回 城市 ;
}
public void setCities(List < BCity > cities){
這個。城市 = 城市 ;
}
@覆蓋
public int hashCode(){
final int prime = 31 ;
int result = 1 ;
結果 = 黃金 * 結果 +((城市 == 空)? 0:城市。的hashCode());
結果 = 黃金 * 結果 +((名稱 == 空)? 0:名稱。的hashCode());
返回 結果 ;
}
@覆蓋
public boolean equals(Object obj){
if(this == obj)
返回 true ;
if(obj == null)
返回 虛假 ;
如果(的getClass()!= OBJ。的getClass())
返回 虛假 ;
BCountry other =(BCountry)obj ;
if(cities == null){
如果(其他。城市 != 空)
返回 虛假 ;
} 否則 如果(!城市。平等(等。城市))
返回 虛假 ;
if(name == null){
如果(其他。名字 != 空)
返回 虛假 ;
} 否則 如果(!名字。平等(其它。名))
返回 虛假 ;
返回 true ;
}
@覆蓋
public String toString(){
返回 “BCountry [name =” + name + “,cities =” + cities + “]” ;
}
}
和城市豆:
匯入 java。io。可序列化 ;
進口 com。fastxml。傑克遜。註釋。JsonIgnoreProperties ;
@JsonIgnoreProperties(ignoreUnknown = true)
公共 類 BCity 實現 Serializable {
private static final long serialVersionUID = 1L ;
private String name,timeZone ;
私人 雙 拉特,lng ;
public BCity(){
super();
}
public BCity(String name,String timeZone,double lat,double lng){
super();
這個。name = name ;
這個。timeZone = timeZone ;
這個。lat = lat ;
這個。lng = lng ;
}
public String getName(){
返回 名稱 ;
}
public void setName(String name){
這個。name = name ;
}
public String getTimeZone(){
返回時 區 ;
}
public void setTimeZone(String timeZone){
這個。timeZone = timeZone ;
}
public double getLat(){
返回 緯度 ;
}
public void setLat(double lat){
這個。lat = lat ;
}
public double getLng(){
返回 lng ;
}
public void setLng(double lng){
這個。lng = lng ;
}
@覆蓋
public String toString(){
返回 “BCity [name =” + name + “,timeZone =” + timeZone + “,lat =” + lat + “,lng =” + lng + “]” ;
}
@覆蓋
public int hashCode(){
final int prime = 31 ;
int result = 1 ;
長 溫度 ;
temp = Double。doubleToLongBits(lat);
result = prime * result +(int)(temp ^(temp >>> 32));
temp = Double。doubleToLongBits(lng);
result = prime * result +(int)(temp ^(temp >>> 32));
結果 = 黃金 * 結果 +((名稱 == 空)? 0:名稱。的hashCode());
結果 = 素 * 結果 +((的timeZone == 空)? 0:的timeZone。的hashCode());
返回 結果 ;
}
@覆蓋
public boolean equals(Object obj){
if(this == obj)
返回 true ;
if(obj == null)
返回 虛假 ;
如果(的getClass()!= OBJ。的getClass())
返回 虛假 ;
BCity other =(BCity)obj ;
如果(雙。doubleToLongBits的(LAT)!= 雙。doubleToLongBits的(其他的。LAT))
返回 虛假 ;
如果(雙。doubleToLongBits的(LNG)!= 雙。doubleToLongBits的(其他的。LNG))
返回 虛假 ;
if(name == null){
如果(其他。名字 != 空)
返回 虛假 ;
} 否則 如果(!名字。平等(其它。名))
返回 虛假 ;
if(timeZone == null){
如果(其他。的timeZone != 空)
返回 虛假 ;
} 否則 如果(!的timeZone。平等(其它。的timeZone))
返回 虛假 ;
返回 true ;
}
}
批次閱讀器實現@LineMapper。 您可以使讀者適應我們的資料來源( 示例 ):
匯入 java。util。清單 ;
進口 組織。彈簧框架。批次。專案。檔案。LineMapper ;
進口 com。ahajri。批次。豆子。BCountry ;
進口 com。fastxml。傑克遜。資料繫結。ObjectMapper ;
進口 com。fastxml。傑克遜。資料繫結。型別。CollectionType ;
公共 類 BCountryJsonLineMapper 實現了 LineMapper < List < BCountry >> {
private final ObjectMapper mapper = new ObjectMapper();
@覆蓋
public List < BCountry > mapLine(String line,int lineNumber)throws Exception {
CollectionType collectionType = mapper。getTypeFactory()。constructCollectionType(列表。類,BCountry。類);
返回 對映器。readValue(line,collectionType);
}
}
處理資料批處理時,檢查同一天某個城市的業務處理資料是否已儲存在資料庫中。 在MongoDB的搜尋資料的方式就是在這個詳細的 崗位 。
ItemProcessor將@BCountry物件轉換為MongoDB Document物件。 該過程詳述如下:
public class BCountryPrayTimeEventItemProcessor 實現 ItemProcessor < List < BCountry >,List < Document >> {
private static final String EVENTS_COLLECTION_NAME = “event” ;
private static final Logger LOG = LoggerFactory。getLogger(BCountryPrayTimeEventItemProcessor。類);
@Autowired
private PrayTimeService prayTimeService ;
@Autowired
private CloudMongoService cloudMongoService ;
@覆蓋
public List < Document > 程式(List < BCountry > items)丟擲 Exception {
final List < Document > docs = new ArrayList <>();
物品。stream()。forEach(item - > {
final String countryName = item。getName();
專案。getCities()。stream()。forEach(c - > {
final Document prayTimeCityEventDoc = new Document();
//迴圈城市併為今天提取祈禱時間
final String cityName = c。getName();
final String cityTimeZone = c。getTimeZone();
final double lat = c。getLat();
final double lng = c。getLng();
final LocalDateTime nowOfCity = LocalDateTime。現在(了zoneid。的(cityTimeZone));
final QueryParam [] queryParams = new QueryParam [ 5 ];
queryParams [ 0 ] = 新 QueryParam(“CITY_NAME” ,OperatorEnum。EQ。名稱(),的cityName);
queryParams [ 1 ] = 新 QueryParam(“EVENT_TYPE” ,OperatorEnum。EQ。名稱(),事件型別。PRAY_TIME。名稱());
queryParams [ 2 ] = 新 QueryParam(“月”,OperatorEnum。EQ。名稱(),nowOfCity。getMonthValue());
queryParams [ 3 ] = 新 QueryParam(“DAY_OF_MONTH” ,OperatorEnum。EQ。名稱(),nowOfCity。getDayOfMonth());
queryParams [ 4 ] = 新 QueryParam(“COUNTRY_NAME” ,OperatorEnum。EQ。名稱(),國家名稱);
List < Document > foundEvents = null ;
嘗試 {
foundEvents = cloudMongoService。搜尋(EVENTS_COLLECTION_NAME,queryParams);
} catch(BusinessException e1){
記錄。錯誤(“====>未找到城市祈禱時間” + 的cityName + “對” + nowOfCity。getDayOfMonth()+ “/”
+ nowOfCity。getMonthValue());
}
嘗試 {
如果(CollectionUtils。的isEmpty(foundEvents)){
//祈禱時間尚未建立
prayTimeCityEventDoc。put(“country_name”,countryName);
prayTimeCityEventDoc。put(“city_name”,cityName);
prayTimeCityEventDoc。把(“EVENT_TYPE” ,事件型別。PRAY_TIME。名稱());
prayTimeCityEventDoc。把(“復發”,RecurringEnum。YEARLY。名稱());
prayTimeCityEventDoc。把(“月”,nowOfCity。getMonthValue());
prayTimeCityEventDoc。把(“DAY_OF_MONTH” ,nowOfCity。getDayOfMonth());
prayTimeCityEventDoc。put(“lat”,lat);
prayTimeCityEventDoc。put(“lng”,lng);
prayTimeCityEventDoc。把(“CREATION_DATE” ,HCDateUtils。convertToDateViaSqlTimestamp(nowOfCity));
final Map < String,Object > prayInfos = prayTimeService。getPrayTimeByLatLngDate(lat,lng,
日期。從(nowOfCity。atZone(了zoneid。的(cityTimeZone))。toInstant()),cityTimeZone);
prayTimeCityEventDoc。把(“pray_infos” ,檔案。解析(新 GSON()的toJSON(prayInfos)));
docs。add(prayTimeCityEventDoc);
} else {
記錄。資訊(字串。格式(“====>祈禱的時間已經存在的城市:%S,月:%d,日:%d” ,
cityName,nowOfCity。getMonthValue(),nowOfCity。getDayOfMonth()));
}
} catch(BusinessException e){
記錄。錯誤(“計算祈禱時間時出問題:”,e);
丟擲 新的 RuntimeException(e);
}
});
});
返回 文件 ;
}
}
批次配置類:
@組態
@EnableBatchProcessing
@EnableScheduling
公共 類 BatchConfiguration {
private static final String SCANDINAVIAN_COUNTRIES_JSON_FILE = “scandinavian-countries.json” ;
private static final String EVENT_COLLECTION_NAME = “event_collection” ;
private static final Logger LOG = LoggerFactory。getLogger(BatchConfiguration。類);
@Autowired
private JobBuilderFactory jobBuilderFactory ;
@Autowired
private StepBuilderFactory stepBuilderFactory ;
@Autowired
私有的 MLabMongoService mlabMongoService ;
@豆
public ResourcelessTransactionManager transactionManager(){
返回 新的 ResourcelessTransactionManager();
}
@豆
public MapJobRepositoryFactoryBean mapJobRepositoryFactory(ResourcelessTransactionManager txManager)
丟擲 異常 {
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean(txManager);
工廠。afterPropertiesSet();
返回 工廠 ;
}
@豆
public JobRepository jobRepository(MapJobRepositoryFactoryBean factory)丟擲 異常 {
return(JobRepository)工廠。getObject();
}
private SimpleJobLauncher jobLauncher ;
@豆
public SimpleJobLauncher jobLauncher(JobRepository jobRepository){
jobLauncher。setJobRepository(jobRepository);
return jobLauncher ;
}
@PostConstruct
private void initJobLauncher(){
jobLauncher = new SimpleJobLauncher();
}
@豆
FlatFileItemReader < List < BCountry >> reader(){
FlatFileItemReader < List < BCountry >> reader = new FlatFileItemReader <>();
讀者。setName(“scandinaviandCountriesReader”);
讀者。setResource(new ClassPathResource(SCANDINAVIAN_COUNTRIES_JSON_FILE));
讀者。setLineMapper(new BCountryJsonLineMapper());
回報 讀者 ;
}
@豆
public ItemWriter < List < Document >> writer(){
返回 新的 ItemWriter < List < Document >>(){
@覆蓋
public void write(List <? extends List < Document >> items)丟擲 Exception {
嘗試 {
如果(!CollectionUtils。的isEmpty(專案)&& 專案。大小()> 0){
List < Document > flatDocs = items。stream()。flatMap(List :: stream)。收集(收藏家。toList());
mlabMongoService。insertMany(EVENT_COLLECTION_NAME,flatDocs);
} else {
記錄。警告(“沒有事件可以救......”);
}
} catch(BusinessException e){
丟擲 新的 RuntimeException(e);
}
}
};
}
@豆
public BCountryTimeEventItemProcessor processor(){
返回 新的 BCountryTimeEventItemProcessor();
}
@豆
public Job scandvTimeJob(){
返回 jobBuilderFactory。get(“scandvTimeJob”)。incrementmenter(new RunIdIncrementer())。流程(step1())。結束()
。build();
}
@豆
public Step step1(){
返回 stepBuilderFactory。得到(“step1”)。< List < BCountry >,List < Document >> chunk(10)。讀者(讀者())
。處理器(處理器())。作家(作家())。build();
}
// end :: jobstep []
//每天午夜15分鐘
@Scheduled(cron = “0 15 0 * * *”)
public void startScandvEventTimeJob()throws Exception {
記錄。info(“====>工作開始時間:” + 新 日期());
JobParameters param = new JobParametersBuilder()。addString(“作業ID” ,字串。的valueOf(系統。的currentTimeMillis()))
。toJobParameters();
JobExecution 執行 = jobLauncher。run(scandvPrayTimeJob(),param);
記錄。資訊(“====>工作完成了狀態:” + 執行。的getStatus());
}
}
部署de Batch到Heroku:
git add。
git commit -m “Deploy Batch”
git push heroku master
注意:要禁用預設批次啟動,請將此新增到application.yml
s p r i n g:
b a t c h:
j o b:
Ë Ñ 一個b 升é d:˚F 一升小號ë
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31557424/viewspace-2285031/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 服務發現-從原理到實現
- 資料共享-spring batch(9)上下文處理SpringBAT
- 《Python機器學習手冊:從資料預處理到深度學習》Python機器學習深度學習
- 從資料治理到資料應用需要多久
- 如何將MongoDB加入到Windows服務中MongoDBWindows
- JSON WEB TOKEN 從原理到實戰JSONWeb
- 從動態代理到Spring AOP(上)Spring
- 從動態代理到Spring AOP(中)Spring
- 從模仿到獨立 從管理到服務 ERP向智慧化發展(轉)
- Dynamics 365 Web API 批處理(batch requests)WebAPIBAT
- Spring Boot 之 Spring Batch 批處理實踐Spring BootBAT
- Nginx服務系列——靜態資源web服務NginxWeb
- Spring Batch + JPA 處理 Excel 檔案教程SpringBATExcel
- 《Spring Batch 權威指南》之“批處理和 Spring”SpringBAT
- 基於spring的web應用,如何處理服務層的錯誤?SpringWeb
- 使用Kafka分割槽擴充套件Spring Batch大資料排程批處理 – ArnoldKafka套件SpringBAT大資料
- MongoDB 為系統新增MongoDB服務MongoDB
- 【資料庫資料恢復】無法啟動MongoDB服務的資料恢復案例資料庫資料恢復MongoDB
- 服務端指南 資料儲存篇 | 聊聊 MongoDB 使用場景服務端MongoDB
- 大資料 - MapReduce:從原理到實戰的全面指南大資料
- 陪你解讀Spring Batch(一)Spring Batch介紹SpringBAT
- 資料庫資料恢復——Windows無法啟動MongoDB服務的資料恢復案例資料庫資料恢復WindowsMongoDB
- 【資料庫資料恢復】MongoDB資料庫服務啟動失敗的資料恢復案例資料庫資料恢復MongoDB
- Node.js 服務連線 MongoDB 處理最佳實踐Node.jsMongoDB
- 陪你解讀Spring Batch(二)帶你入手Spring BatchSpringBAT
- Spring Batch 基本的批處理指導原則SpringBAT
- Spring Boot整合Spring BatchSpring BootBAT
- 資料融合平臺,資料服務一站式處理
- MongoDB 在 Spring的資料應用MongoDBSpring
- Spring Batch專題SpringBAT
- Spring Batch 簡介SpringBAT
- 你是否應該將簡訊服務整合到客戶服務中去?–資料資訊圖
- mongodb服務在哪裡啟動?MongoDB
- Java後端開發中的任務排程:使用Spring Batch實現批處理Java後端SpringBAT
- Springboot資料庫事務處理——Spring宣告式事務Spring Boot資料庫
- 配置 Spring Batch 批處理失敗重試機制SpringBAT
- 一文輕鬆搞定批處理框架 Spring Batch框架SpringBAT
- 美國國防部從“中國”購買資料傳輸服務